| 1 | /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
| 2 | // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: |
| 3 | #ident "$Id$" |
| 4 | /*====== |
| 5 | This file is part of PerconaFT. |
| 6 | |
| 7 | |
| 8 | Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. |
| 9 | |
| 10 | PerconaFT is free software: you can redistribute it and/or modify |
| 11 | it under the terms of the GNU General Public License, version 2, |
| 12 | as published by the Free Software Foundation. |
| 13 | |
| 14 | PerconaFT is distributed in the hope that it will be useful, |
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 17 | GNU General Public License for more details. |
| 18 | |
| 19 | You should have received a copy of the GNU General Public License |
| 20 | along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. |
| 21 | |
| 22 | ---------------------------------------- |
| 23 | |
| 24 | PerconaFT is free software: you can redistribute it and/or modify |
| 25 | it under the terms of the GNU Affero General Public License, version 3, |
| 26 | as published by the Free Software Foundation. |
| 27 | |
| 28 | PerconaFT is distributed in the hope that it will be useful, |
| 29 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 30 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 31 | GNU Affero General Public License for more details. |
| 32 | |
| 33 | You should have received a copy of the GNU Affero General Public License |
| 34 | along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. |
| 35 | ======= */ |
| 36 | |
| 37 | #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." |
| 38 | |
| 39 | #pragma once |
| 40 | |
| 41 | #include "ft/serialize/block_table.h" |
| 42 | #include "ft/serialize/ft_layout_version.h" |
| 43 | #include "ft/txn/txn.h" |
| 44 | |
| 45 | typedef struct tokulogger *TOKULOGGER; |
| 46 | |
| 47 | enum { |
| 48 | TOKU_LOG_VERSION_1 = 1, |
| 49 | TOKU_LOG_VERSION_2 = 2, |
| 50 | //After 2 we linked the log version to the FT_LAYOUT VERSION. |
| 51 | //So it went from 2 to 13 (3-12 do not exist) |
| 52 | TOKU_LOG_VERSION_24 = 24, |
| 53 | TOKU_LOG_VERSION_25 = 25, // change rollinclude rollback log entry |
| 54 | TOKU_LOG_VERSION_26 = 26, // no change from 25 |
| 55 | TOKU_LOG_VERSION_27 = 27, // no change from 26 |
| 56 | TOKU_LOG_VERSION_28 = 28, // no change from 27 |
| 57 | TOKU_LOG_VERSION_29 = 29, // no change from 28 |
| 58 | TOKU_LOG_VERSION = FT_LAYOUT_VERSION, |
| 59 | TOKU_LOG_MIN_SUPPORTED_VERSION = FT_LAYOUT_MIN_SUPPORTED_VERSION, |
| 60 | }; |
| 61 | |
| 62 | int toku_logger_create (TOKULOGGER *resultp); |
| 63 | int toku_logger_open (const char *directory, TOKULOGGER logger); |
| 64 | int toku_logger_open_with_last_xid(const char *directory, TOKULOGGER logger, TXNID last_xid); |
| 65 | void toku_logger_shutdown(TOKULOGGER logger); |
| 66 | int toku_logger_close(TOKULOGGER *loggerp); |
| 67 | void toku_logger_initialize_rollback_cache(TOKULOGGER logger, struct ft *ft); |
| 68 | int toku_logger_open_rollback(TOKULOGGER logger, struct cachetable *ct, bool create); |
| 69 | void toku_logger_close_rollback(TOKULOGGER logger); |
| 70 | void toku_logger_close_rollback_check_empty(TOKULOGGER logger, bool clean_shutdown); |
| 71 | bool toku_logger_rollback_is_open (TOKULOGGER); // return true iff the rollback is open. |
| 72 | |
| 73 | void toku_logger_fsync (TOKULOGGER logger); |
| 74 | void toku_logger_fsync_if_lsn_not_fsynced(TOKULOGGER logger, LSN lsn); |
| 75 | int toku_logger_is_open(TOKULOGGER logger); |
| 76 | void toku_logger_set_cachetable (TOKULOGGER logger, struct cachetable *ct); |
| 77 | int toku_logger_set_lg_max(TOKULOGGER logger, uint32_t lg_max); |
| 78 | int toku_logger_get_lg_max(TOKULOGGER logger, uint32_t *lg_maxp); |
| 79 | int toku_logger_set_lg_bsize(TOKULOGGER logger, uint32_t bsize); |
| 80 | |
| 81 | void toku_logger_write_log_files (TOKULOGGER logger, bool write_log_files); |
| 82 | void toku_logger_trim_log_files(TOKULOGGER logger, bool trim_log_files); |
| 83 | bool toku_logger_txns_exist(TOKULOGGER logger); |
| 84 | |
| 85 | // Restart the logger. This function is used by recovery to really start |
| 86 | // logging. |
| 87 | // Effects: Flush the current log buffer, reset the logger's lastlsn, and |
| 88 | // open a new log file. |
| 89 | // Returns: 0 if success |
| 90 | int toku_logger_restart(TOKULOGGER logger, LSN lastlsn); |
| 91 | |
| 92 | // Maybe trim the log entries from the log that are older than the given LSN |
| 93 | // Effect: find all of the log files whose largest LSN is smaller than the |
| 94 | // given LSN and delete them. |
| 95 | void toku_logger_maybe_trim_log(TOKULOGGER logger, LSN oldest_open_lsn); |
| 96 | |
| 97 | // At the ft layer, a FILENUM uniquely identifies an open file. |
| 98 | struct FILENUM { |
| 99 | uint32_t fileid; |
| 100 | }; |
| 101 | static const FILENUM FILENUM_NONE = { .fileid = UINT32_MAX }; |
| 102 | |
| 103 | struct FILENUMS { |
| 104 | uint32_t num; |
| 105 | FILENUM *filenums; |
| 106 | }; |
| 107 | |
| 108 | void toku_logger_log_fcreate(TOKUTXN txn, const char *fname, FILENUM filenum, uint32_t mode, uint32_t flags, uint32_t nodesize, uint32_t basementnodesize, enum toku_compression_method compression_method); |
| 109 | void toku_logger_log_fdelete(TOKUTXN txn, FILENUM filenum); |
| 110 | void toku_logger_log_fopen(TOKUTXN txn, const char * fname, FILENUM filenum, uint32_t treeflags); |
| 111 | |
| 112 | // the log generation code requires a typedef if we want to pass by pointer |
| 113 | typedef TOKU_XA_XID *XIDP; |
| 114 | |
| 115 | int toku_fread_uint8_t (FILE *f, uint8_t *v, struct x1764 *mm, uint32_t *len); |
| 116 | int toku_fread_uint32_t_nocrclen (FILE *f, uint32_t *v); |
| 117 | int toku_fread_uint32_t (FILE *f, uint32_t *v, struct x1764 *checksum, uint32_t *len); |
| 118 | int toku_fread_uint64_t (FILE *f, uint64_t *v, struct x1764 *checksum, uint32_t *len); |
| 119 | int toku_fread_bool (FILE *f, bool *v, struct x1764 *checksum, uint32_t *len); |
| 120 | int toku_fread_LSN (FILE *f, LSN *lsn, struct x1764 *checksum, uint32_t *len); |
| 121 | int toku_fread_BLOCKNUM (FILE *f, BLOCKNUM *lsn, struct x1764 *checksum, uint32_t *len); |
| 122 | int toku_fread_FILENUM (FILE *f, FILENUM *filenum, struct x1764 *checksum, uint32_t *len); |
| 123 | int toku_fread_TXNID (FILE *f, TXNID *txnid, struct x1764 *checksum, uint32_t *len); |
| 124 | int toku_fread_TXNID_PAIR (FILE *f, TXNID_PAIR *txnid, struct x1764 *checksum, uint32_t *len); |
| 125 | int toku_fread_XIDP (FILE *f, XIDP *xidp, struct x1764 *checksum, uint32_t *len); |
| 126 | int toku_fread_BYTESTRING (FILE *f, BYTESTRING *bs, struct x1764 *checksum, uint32_t *len); |
| 127 | int toku_fread_FILENUMS (FILE *f, FILENUMS *fs, struct x1764 *checksum, uint32_t *len); |
| 128 | |
| 129 | int toku_logprint_LSN (FILE *outf, FILE *inf, const char *fieldname, struct x1764 *checksum, uint32_t *len, const char *format __attribute__((__unused__))); |
| 130 | int toku_logprint_TXNID (FILE *outf, FILE *inf, const char *fieldname, struct x1764 *checksum, uint32_t *len, const char *format __attribute__((__unused__))); |
| 131 | int toku_logprint_TXNID_PAIR (FILE *outf, FILE *inf, const char *fieldname, struct x1764 *checksum, uint32_t *len, const char *format __attribute__((__unused__))); |
| 132 | int toku_logprint_XIDP (FILE *outf, FILE *inf, const char *fieldname, struct x1764 *checksum, uint32_t *len, const char *format __attribute__((__unused__))); |
| 133 | int toku_logprint_uint8_t (FILE *outf, FILE *inf, const char *fieldname, struct x1764 *checksum, uint32_t *len, const char *format); |
| 134 | int toku_logprint_uint32_t (FILE *outf, FILE *inf, const char *fieldname, struct x1764 *checksum, uint32_t *len, const char *format); |
| 135 | int toku_logprint_BLOCKNUM (FILE *outf, FILE *inf, const char *fieldname, struct x1764 *checksum, uint32_t *len, const char *format); |
| 136 | int toku_logprint_uint64_t (FILE *outf, FILE *inf, const char *fieldname, struct x1764 *checksum, uint32_t *len, const char *format); |
| 137 | int toku_logprint_bool (FILE *outf, FILE *inf, const char *fieldname, struct x1764 *checksum, uint32_t *len, const char *format __attribute__((__unused__))); |
| 138 | void toku_print_BYTESTRING (FILE *outf, uint32_t len, char *data); |
| 139 | int toku_logprint_BYTESTRING (FILE *outf, FILE *inf, const char *fieldname, struct x1764 *checksum, uint32_t *len, const char *format __attribute__((__unused__))); |
| 140 | int toku_logprint_FILENUM (FILE *outf, FILE *inf, const char *fieldname, struct x1764 *checksum, uint32_t *len, const char *format); |
| 141 | int toku_logprint_FILENUMS (FILE *outf, FILE *inf, const char *fieldname, struct x1764 *checksum, uint32_t *len, const char *format); |
| 142 | int toku_read_and_print_logmagic (FILE *f, uint32_t *versionp); |
| 143 | int toku_read_logmagic (FILE *f, uint32_t *versionp); |
| 144 | |
| 145 | TXNID_PAIR toku_txn_get_txnid (TOKUTXN txn); |
| 146 | LSN toku_logger_last_lsn(TOKULOGGER logger); |
| 147 | TOKULOGGER toku_txn_logger (TOKUTXN txn); |
| 148 | |
| 149 | void toku_txnid2txn (TOKULOGGER logger, TXNID_PAIR txnid, TOKUTXN *result); |
| 150 | |
| 151 | int toku_logger_log_archive (TOKULOGGER logger, char ***logs_p, int flags); |
| 152 | |
| 153 | TOKUTXN toku_logger_txn_parent (TOKUTXN txn); |
| 154 | void toku_logger_note_checkpoint(TOKULOGGER logger, LSN lsn); |
| 155 | |
| 156 | void toku_logger_make_space_in_inbuf (TOKULOGGER logger, int n_bytes_needed); |
| 157 | |
| 158 | int toku_logger_write_inbuf (TOKULOGGER logger); |
| 159 | // Effect: Write the buffered data (from the inbuf) to a file. No fsync, however. |
| 160 | // As a side effect, the inbuf will be made empty. |
| 161 | // Return 0 on success, otherwise return an error number. |
| 162 | // Requires: The inbuf lock is currently held, and the outbuf lock is not held. |
| 163 | // Upon return, the inbuf lock will be held, and the outbuf lock is not held. |
| 164 | // However, no side effects should have been made to the logger. The lock was acquired simply to determine that the buffer will overflow if we try to put something into it. |
| 165 | // The inbuf lock will be released, so the operations before and after this function call will not be atomic. |
| 166 | // Rationale: When the buffer becomes nearly full, call this function so that more can be put in. |
| 167 | // Implementation note: Since the output lock is acquired first, we must release the input lock, and then grab both in the right order. |
| 168 | |
| 169 | void toku_logger_maybe_fsync (TOKULOGGER logger, LSN lsn, int do_fsync, bool holds_input_lock); |
| 170 | // Effect: If fsync is nonzero, then make sure that the log is flushed and synced at least up to lsn. |
| 171 | // Entry: Holds input lock iff 'holds_input_lock'. |
| 172 | // Exit: Holds no locks. |
| 173 | |
| 174 | // Discussion: How does the logger work: |
| 175 | // The logger has two buffers: an inbuf and an outbuf. |
| 176 | // There are two locks, called the inlock, and the outlock. To write, both locks must be held, and the outlock is acquired first. |
| 177 | // Roughly speaking, the inbuf is used to accumulate logged data, and the outbuf is used to write to disk. |
| 178 | // When something is to be logged we do the following: |
| 179 | // acquire the inlock. |
| 180 | // Make sure there is space in the inbuf for the logentry. (We know the size of the logentry in advance): |
| 181 | // if the inbuf doesn't have enough space then |
| 182 | // release the inlock |
| 183 | // acquire the outlock |
| 184 | // acquire the inlock |
| 185 | // it's possible that some other thread made space. |
| 186 | // if there still isn't space |
| 187 | // swap the inbuf and the outbuf |
| 188 | // release the inlock |
| 189 | // write the outbuf |
| 190 | // acquire the inlock |
| 191 | // release the outlock |
| 192 | // if the inbuf is still too small, then increase the size of the inbuf |
| 193 | // Increment the LSN and fill the inbuf. |
| 194 | // If fsync is required then |
| 195 | // release the inlock |
| 196 | // acquire the outlock |
| 197 | // acquire the inlock |
| 198 | // if the LSN has been flushed and fsynced (if so we are done. Some other thread did the flush.) |
| 199 | // release the locks |
| 200 | // if the LSN has been flushed but not fsynced up to the LSN: |
| 201 | // release the inlock |
| 202 | // fsync |
| 203 | // release the outlock |
| 204 | // otherwise: |
| 205 | // swap the outbuf and the inbuf |
| 206 | // release the inlock |
| 207 | // write the outbuf |
| 208 | // fsync |
| 209 | // release the outlock |
| 210 | |
| 211 | void toku_logger_get_status(TOKULOGGER logger, LOGGER_STATUS s); |
| 212 | |
| 213 | int toku_get_version_of_logs_on_disk(const char *log_dir, bool *found_any_logs, uint32_t *version_found); |
| 214 | |
| 215 | struct txn_manager *toku_logger_get_txn_manager(TOKULOGGER logger); |
| 216 | |
| 217 | // For serialize / deserialize |
| 218 | |
| 219 | #include "ft/serialize/wbuf.h" |
| 220 | |
| 221 | static inline void wbuf_nocrc_FILENUM(struct wbuf *wb, FILENUM fileid) { |
| 222 | wbuf_nocrc_uint(wb, fileid.fileid); |
| 223 | } |
| 224 | |
| 225 | static inline void wbuf_FILENUM(struct wbuf *wb, FILENUM fileid) { |
| 226 | wbuf_uint(wb, fileid.fileid); |
| 227 | } |
| 228 | |
| 229 | static inline void wbuf_nocrc_FILENUMS(struct wbuf *wb, FILENUMS v) { |
| 230 | wbuf_nocrc_uint(wb, v.num); |
| 231 | for (uint32_t i = 0; i < v.num; i++) { |
| 232 | wbuf_nocrc_FILENUM(wb, v.filenums[i]); |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | static inline void wbuf_FILENUMS(struct wbuf *wb, FILENUMS v) { |
| 237 | wbuf_uint(wb, v.num); |
| 238 | for (uint32_t i = 0; i < v.num; i++) { |
| 239 | wbuf_FILENUM(wb, v.filenums[i]); |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | static inline void wbuf_nocrc_XIDP (struct wbuf *w, TOKU_XA_XID *xid) { |
| 244 | wbuf_nocrc_uint32_t(w, xid->formatID); |
| 245 | wbuf_nocrc_uint8_t(w, xid->gtrid_length); |
| 246 | wbuf_nocrc_uint8_t(w, xid->bqual_length); |
| 247 | wbuf_nocrc_literal_bytes(w, xid->data, xid->gtrid_length+xid->bqual_length); |
| 248 | } |
| 249 | |
| 250 | #include "ft/serialize/rbuf.h" |
| 251 | |
| 252 | static inline void rbuf_FILENUM(struct rbuf *rb, FILENUM *filenum) { |
| 253 | filenum->fileid = rbuf_int(rb); |
| 254 | } |
| 255 | static inline void rbuf_ma_FILENUM(struct rbuf *rb, memarena *UU(ma), FILENUM *filenum) { |
| 256 | rbuf_FILENUM(rb, filenum); |
| 257 | } |
| 258 | |
| 259 | static inline void rbuf_FILENUMS(struct rbuf *rb, FILENUMS *filenums) { |
| 260 | filenums->num = rbuf_int(rb); |
| 261 | XMALLOC_N(filenums->num, filenums->filenums); |
| 262 | for (uint32_t i = 0; i < filenums->num; i++) { |
| 263 | rbuf_FILENUM(rb, &(filenums->filenums[i])); |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | static inline void rbuf_ma_FILENUMS(struct rbuf *rb, memarena *ma, FILENUMS *filenums) { |
| 268 | rbuf_ma_uint32_t(rb, ma, &(filenums->num)); |
| 269 | filenums->filenums = (FILENUM *) ma->malloc_from_arena(filenums->num * sizeof(FILENUM)); |
| 270 | assert(filenums->filenums != NULL); |
| 271 | for (uint32_t i = 0; i < filenums->num; i++) { |
| 272 | rbuf_ma_FILENUM(rb, ma, &(filenums->filenums[i])); |
| 273 | } |
| 274 | } |
| 275 | |