closes[t:2483] Fix recovery bug in loader.

checkpoint_lsn written to headers made by loader are now the fsynced 'load' log entry's lsn instead of MAX_UINT64

git-svn-id: file:///svn/toku/tokudb@19136 c7de825b-a66e-492c-adef-691d508d4ae1
This commit is contained in:
Yoni Fogel 2013-04-16 23:59:05 -04:00
parent 56f23bc1ea
commit 667e46d60c
9 changed files with 33 additions and 21 deletions

View file

@ -2658,7 +2658,7 @@ txn_note_doing_work(TOKUTXN txn) {
int int
toku_brt_load_recovery(TOKUTXN txn, char const * old_iname, char const * new_iname, int do_fsync, int do_log) { toku_brt_load_recovery(TOKUTXN txn, char const * old_iname, char const * new_iname, int do_fsync, int do_log, LSN *load_lsn) {
int r = 0; int r = 0;
assert(txn); assert(txn);
toku_txn_force_fsync_on_commit(txn); //If the txn commits, the commit MUST be in the log toku_txn_force_fsync_on_commit(txn); //If the txn commits, the commit MUST be in the log
@ -2673,18 +2673,18 @@ toku_brt_load_recovery(TOKUTXN txn, char const * old_iname, char const * new_ina
r = toku_logger_save_rollback_load(txn, old_iname_bs, new_iname_bs); r = toku_logger_save_rollback_load(txn, old_iname_bs, new_iname_bs);
if (r==0 && do_log && logger) { if (r==0 && do_log && logger) {
TXNID xid = toku_txn_get_txnid(txn); TXNID xid = toku_txn_get_txnid(txn);
r = toku_log_load(logger, (LSN*)NULL, do_fsync, xid, old_iname_bs, new_iname_bs); r = toku_log_load(logger, load_lsn, do_fsync, xid, old_iname_bs, new_iname_bs);
} }
return r; return r;
} }
int int
toku_brt_load(BRT brt, TOKUTXN txn, char const * new_iname, int do_fsync) { toku_brt_load(BRT brt, TOKUTXN txn, char const * new_iname, int do_fsync, LSN *load_lsn) {
int r = 0; int r = 0;
char const * old_iname = toku_cachefile_fname_in_env(brt->cf); char const * old_iname = toku_cachefile_fname_in_env(brt->cf);
int do_log = 1; int do_log = 1;
r = toku_brt_load_recovery(txn, old_iname, new_iname, do_fsync, do_log); r = toku_brt_load_recovery(txn, old_iname, new_iname, do_fsync, do_log, load_lsn);
return r; return r;
} }

View file

@ -66,8 +66,8 @@ int toku_brt_insert (BRT brt, DBT *k, DBT *v, TOKUTXN txn);
// Effect: Insert a key and data pair into a brt if the oplsn is newer than the brt lsn. This function is called during recovery. // Effect: Insert a key and data pair into a brt if the oplsn is newer than the brt lsn. This function is called during recovery.
// Returns 0 if successful // Returns 0 if successful
int toku_brt_maybe_insert (BRT brt, DBT *k, DBT *v, TOKUTXN txn, BOOL oplsn_valid, LSN oplsn, int do_logging, enum brt_msg_type type); int toku_brt_maybe_insert (BRT brt, DBT *k, DBT *v, TOKUTXN txn, BOOL oplsn_valid, LSN oplsn, int do_logging, enum brt_msg_type type);
int toku_brt_load_recovery(TOKUTXN txn, char const * old_iname, char const * new_iname, int do_fsync, int do_log); int toku_brt_load_recovery(TOKUTXN txn, char const * old_iname, char const * new_iname, int do_fsync, int do_log, LSN *load_lsn);
int toku_brt_load(BRT brt, TOKUTXN txn, char const * new_iname, int do_fsync); int toku_brt_load(BRT brt, TOKUTXN txn, char const * new_iname, int do_fsync, LSN *get_lsn);
int toku_brt_log_put_multiple (TOKUTXN txn, BRT src_brt, BRT *brts, int num_brts, const DBT *key, const DBT *val); int toku_brt_log_put_multiple (TOKUTXN txn, BRT src_brt, BRT *brts, int num_brts, const DBT *key, const DBT *val);
int toku_brt_log_del_multiple (TOKUTXN txn, BRT src_brt, BRT *brts, int num_brts, const DBT *key, const DBT *val); int toku_brt_log_del_multiple (TOKUTXN txn, BRT src_brt, BRT *brts, int num_brts, const DBT *key, const DBT *val);

View file

@ -55,6 +55,7 @@ struct brtloader_s {
void *poll_extra; void *poll_extra;
int user_said_stop; // 0 if the poll_function always returned zero. If it ever returns nonzero, then store that value here. int user_said_stop; // 0 if the poll_function always returned zero. If it ever returns nonzero, then store that value here.
LSN load_lsn; //LSN of the fsynced 'load' log entry. Write this LSN (as checkpoint_lsn) in brt headers made by this loader.
}; };
/* These data structures are used for manipulating a collection of rows in main memory. */ /* These data structures are used for manipulating a collection of rows in main memory. */

View file

@ -172,7 +172,8 @@ int toku_brt_loader_open (/* out */ BRTLOADER *blp,
const struct descriptor *descriptors[/*N*/], const struct descriptor *descriptors[/*N*/],
const char *new_fnames_in_env[/*N*/], const char *new_fnames_in_env[/*N*/],
brt_compare_func bt_compare_functions[/*N*/], brt_compare_func bt_compare_functions[/*N*/],
const char *temp_file_template) const char *temp_file_template,
LSN load_lsn)
/* Effect: called by DB_ENV->create_loader to create a brt loader. /* Effect: called by DB_ENV->create_loader to create a brt loader.
* Arguments: * Arguments:
* blp Return the brt loader here. * blp Return the brt loader here.
@ -218,6 +219,7 @@ int toku_brt_loader_open (/* out */ BRTLOADER *blp,
bl->n_rows = 0; bl->n_rows = 0;
bl->progress = 0; bl->progress = 0;
bl->load_lsn = load_lsn;
*blp = bl; *blp = bl;
return 0; return 0;
@ -1275,10 +1277,10 @@ static int write_translation_table (struct dbout *out, long long *off_of_transla
} }
static void write_header (struct dbout *out, long long translation_location_on_disk, long long translation_size_on_disk, BLOCKNUM root_blocknum_on_disk) { static void write_header (struct dbout *out, long long translation_location_on_disk, long long translation_size_on_disk, BLOCKNUM root_blocknum_on_disk, LSN load_lsn) {
struct brt_header h = {.layout_version = BRT_LAYOUT_VERSION, struct brt_header h = {.layout_version = BRT_LAYOUT_VERSION,
.checkpoint_count = 1, .checkpoint_count = 1,
.checkpoint_lsn = (LSN){0xFFFFFFFFFFFFFFFF}, // (max_uint_long means that this doesn't need any kind of recovery .checkpoint_lsn = load_lsn, // Nothing is logged after the load.
.nodesize = nodesize, .nodesize = nodesize,
.root = root_blocknum_on_disk, .root = root_blocknum_on_disk,
.flags = 0, .flags = 0,
@ -1658,7 +1660,7 @@ int write_file_to_dbfile (int outfile, FIDX infile, BRTLOADER bl, const struct d
long long off_of_translation; long long off_of_translation;
int r = write_translation_table(&out, &off_of_translation); int r = write_translation_table(&out, &off_of_translation);
assert(r==0); assert(r==0);
write_header(&out, off_of_translation, (out.n_translations+1)*16+4, root_block); write_header(&out, off_of_translation, (out.n_translations+1)*16+4, root_block, bl->load_lsn);
if (key.data) toku_free(key.data); if (key.data) toku_free(key.data);
if (val.data) toku_free(val.data); if (val.data) toku_free(val.data);
if (out.translation) toku_free(out.translation); if (out.translation) toku_free(out.translation);

View file

@ -14,7 +14,8 @@ int toku_brt_loader_open (BRTLOADER *bl,
const struct descriptor *descriptors[/*N*/], const struct descriptor *descriptors[/*N*/],
const char * new_fnames_in_env[/*N*/], const char * new_fnames_in_env[/*N*/],
brt_compare_func bt_compare_functions[/*N*/], brt_compare_func bt_compare_functions[/*N*/],
const char *temp_file_template); const char *temp_file_template,
LSN load_lsn);
int toku_brt_loader_put (BRTLOADER bl, DBT *key, DBT *val); int toku_brt_loader_put (BRTLOADER bl, DBT *key, DBT *val);
int toku_brt_loader_close (BRTLOADER bl, int toku_brt_loader_close (BRTLOADER bl,
void (*error_callback)(DB *, int which_db, int err, DBT *key, DBT *val, void *extra), void *error_callback_extra, void (*error_callback)(DB *, int which_db, int err, DBT *key, DBT *val, void *extra), void *error_callback_extra,

View file

@ -1000,7 +1000,7 @@ static int toku_recover_load(struct logtype_load *UU(l), RECOVER_ENV UU(renv)) {
char *old_iname = fixup_fname(&l->old_iname); char *old_iname = fixup_fname(&l->old_iname);
char *new_iname = fixup_fname(&l->new_iname); char *new_iname = fixup_fname(&l->new_iname);
r = toku_brt_load_recovery(txn, old_iname, new_iname, 0, 0); r = toku_brt_load_recovery(txn, old_iname, new_iname, 0, 0, (LSN*)NULL);
assert(r==0); assert(r==0);
toku_free(old_iname); toku_free(old_iname);

View file

@ -197,7 +197,8 @@ int toku_loader_create_loader(DB_ENV *env,
} }
loader->i->ekeys = NULL; loader->i->ekeys = NULL;
loader->i->evals = NULL; loader->i->evals = NULL;
r = locked_ydb_load_inames (env, txn, N, dbs, new_inames_in_env); LSN load_lsn;
r = locked_ydb_load_inames (env, txn, N, dbs, new_inames_in_env, &load_lsn);
if ( r!=0 ) { if ( r!=0 ) {
toku_free(descriptors); toku_free(descriptors);
free_loader(loader); free_loader(loader);
@ -212,7 +213,8 @@ int toku_loader_create_loader(DB_ENV *env,
descriptors, descriptors,
(const char **)new_inames_in_env, (const char **)new_inames_in_env,
compare_functions, compare_functions,
loader->i->temp_file_template); loader->i->temp_file_template,
load_lsn);
loader->i->inames_in_env = new_inames_in_env; loader->i->inames_in_env = new_inames_in_env;
toku_free(descriptors); toku_free(descriptors);
} }

View file

@ -5538,7 +5538,7 @@ env_get_iname(DB_ENV* env, DBT* dname_dbt, DBT* iname_dbt) {
// It is the caller's responsibility to free them. // It is the caller's responsibility to free them.
// Return 0 on success (could fail if write lock not available). // Return 0 on success (could fail if write lock not available).
int int
ydb_load_inames(DB_ENV * env, DB_TXN * txn, int N, DB * dbs[N], char * new_inames_in_env[N]) { ydb_load_inames(DB_ENV * env, DB_TXN * txn, int N, DB * dbs[N], char * new_inames_in_env[N], LSN *load_lsn) {
int rval; int rval;
int i; int i;
@ -5575,11 +5575,15 @@ ydb_load_inames(DB_ENV * env, DB_TXN * txn, int N, DB * dbs[N], char * new_iname
if (!rval && using_txns) { if (!rval && using_txns) {
TOKUTXN ttxn = db_txn_struct_i(txn)->tokutxn; TOKUTXN ttxn = db_txn_struct_i(txn)->tokutxn;
int do_fsync = 0; int do_fsync = 0;
LSN *get_lsn = NULL;
for (i = 0; i < N; i++) { for (i = 0; i < N; i++) {
BRT brt = dbs[i]->i->brt; BRT brt = dbs[i]->i->brt;
//Fsync is necessary for the last one only. //Fsync is necessary for the last one only.
if (i==N-1) do_fsync = 1; //We only need a single fsync of logs. if (i==N-1) {
rval = toku_brt_load(brt, ttxn, new_inames_in_env[i], do_fsync); do_fsync = 1; //We only need a single fsync of logs.
get_lsn = load_lsn; //Set pointer to capture the last lsn.
}
rval = toku_brt_load(brt, ttxn, new_inames_in_env[i], do_fsync, get_lsn);
if (rval) break; if (rval) break;
} }
} }
@ -5606,9 +5610,9 @@ ydb_load_inames(DB_ENV * env, DB_TXN * txn, int N, DB * dbs[N], char * new_iname
} }
int int
locked_ydb_load_inames(DB_ENV * env, DB_TXN * txn, int N, DB * dbs[N], char * new_inames_in_env[N]) { locked_ydb_load_inames(DB_ENV * env, DB_TXN * txn, int N, DB * dbs[N], char * new_inames_in_env[N], LSN *load_lsn) {
toku_ydb_lock(); toku_ydb_lock();
int r = ydb_load_inames(env, txn, N, dbs, new_inames_in_env); int r = ydb_load_inames(env, txn, N, dbs, new_inames_in_env, load_lsn);
toku_ydb_unlock(); toku_ydb_unlock();
return r; return r;
} }

View file

@ -23,14 +23,16 @@ int ydb_load_inames(DB_ENV * env,
DB_TXN * txn, DB_TXN * txn,
int N, int N,
DB * dbs[/*N*/], DB * dbs[/*N*/],
/*out*/ char * new_inames_in_env[N]); /*out*/ char * new_inames_in_env[N],
LSN *load_lsn);
// Wrapper to ydb_load_inames if you are not holding the ydb lock. // Wrapper to ydb_load_inames if you are not holding the ydb lock.
int locked_ydb_load_inames(DB_ENV * env, int locked_ydb_load_inames(DB_ENV * env,
DB_TXN * txn, DB_TXN * txn,
int N, int N,
DB * dbs[/*N*/], DB * dbs[/*N*/],
/*out*/ char * new_inames_in_env[N]); /*out*/ char * new_inames_in_env[N],
LSN *load_lsn);
#endif #endif