diff --git a/newbrt/recover.c b/newbrt/recover.c index 5a58ea28e08..f1150ae1385 100644 --- a/newbrt/recover.c +++ b/newbrt/recover.c @@ -29,7 +29,7 @@ static void backward_scan_state_init(struct backward_scan_state *bs) { // Map filenum to brt // TODO why can't we use the cachetable to find by filenum? -struct filenum_map { +struct file_map { struct cf_pair { FILENUM filenum; CACHEFILE cf; @@ -38,40 +38,44 @@ struct filenum_map { int n_cf_pairs, max_cf_pairs; }; -static void filenum_map_init(struct filenum_map *fmap) { +static void file_map_init(struct file_map *fmap) { fmap->cf_pairs = NULL; fmap->n_cf_pairs = fmap->max_cf_pairs = 0; } -static void filenum_map_close_dictionaries(struct filenum_map *fmap) { +static void file_map_close_dictionaries(struct file_map *fmap) { int r; - int i; - for (i=0; in_cf_pairs; i++) { + for (int i=0; in_cf_pairs; i++) { if (fmap->cf_pairs[i].brt) { r = toku_close_brt(fmap->cf_pairs[i].brt, 0, 0); //r = toku_cachefile_close(&cf_pairs[i].cf); assert(r == 0); } } - fmap->n_cf_pairs = 0; + fmap->n_cf_pairs = fmap->max_cf_pairs = 0; if (fmap->cf_pairs) { toku_free(fmap->cf_pairs); fmap->cf_pairs = NULL; } } -static int filenum_map_add (struct filenum_map *fmap, FILENUM fnum, CACHEFILE cf, BRT brt) { - if (fmap->max_cf_pairs==0) { - fmap->n_cf_pairs=1; - fmap->max_cf_pairs=2; +static int file_map_add (struct file_map *fmap, FILENUM fnum, CACHEFILE cf, BRT brt) { + if (fmap->cf_pairs == NULL) { + fmap->max_cf_pairs = 1; MALLOC_N(fmap->max_cf_pairs, fmap->cf_pairs); - if (fmap->cf_pairs==0) return errno; + if (fmap->cf_pairs == NULL) { + fmap->max_cf_pairs = 0; + return errno; + } + fmap->n_cf_pairs=1; } else { if (fmap->n_cf_pairs >= fmap->max_cf_pairs) { - fmap->cf_pairs = toku_realloc(fmap->cf_pairs, 2*fmap->max_cf_pairs*sizeof(struct cf_pair)); - assert(fmap->cf_pairs); - fmap->max_cf_pairs*=2; + struct cf_pair *new_cf_pairs = toku_realloc(fmap->cf_pairs, 2*fmap->max_cf_pairs*sizeof(struct cf_pair)); + if (new_cf_pairs == NULL) + return errno; + fmap->cf_pairs = new_cf_pairs; + fmap->max_cf_pairs *= 2; } fmap->n_cf_pairs++; } @@ -81,9 +85,8 @@ static int filenum_map_add (struct filenum_map *fmap, FILENUM fnum, CACHEFILE cf return 0; } -static int find_cachefile (struct filenum_map *fmap, FILENUM fnum, struct cf_pair **cf_pair) { - int i; - for (i=0; in_cf_pairs; i++) { +static int find_cachefile (struct file_map *fmap, FILENUM fnum, struct cf_pair **cf_pair) { + for (int i=0; in_cf_pairs; i++) { if (fnum.fileid==fmap->cf_pairs[i].filenum.fileid) { *cf_pair = fmap->cf_pairs+i; return 0; @@ -98,7 +101,7 @@ struct recover_env { brt_compare_func bt_compare; brt_compare_func dup_compare; struct backward_scan_state bs; - struct filenum_map fmap; + struct file_map fmap; }; typedef struct recover_env *RECOVER_ENV; @@ -113,7 +116,7 @@ int recover_env_init (RECOVER_ENV env, brt_compare_func bt_compare, brt_compare_ toku_logger_set_cachetable(env->logger, env->ct); env->bt_compare = bt_compare; env->dup_compare = dup_compare; - filenum_map_init(&env->fmap); + file_map_init(&env->fmap); if (toku_recover_trace) printf("%s:%d\n", __FUNCTION__, __LINE__); @@ -123,7 +126,7 @@ int recover_env_init (RECOVER_ENV env, brt_compare_func bt_compare, brt_compare_ void recover_env_cleanup (RECOVER_ENV env) { int r; - filenum_map_close_dictionaries(&env->fmap); + file_map_close_dictionaries(&env->fmap); r = toku_logger_close(&env->logger); assert(r == 0); @@ -183,10 +186,9 @@ static int toku_recover_backward_xabort (struct logtype_xabort *UU(l), RECOVER_E } static void create_dir_from_file (const char *fname) { - int i; char *tmp=toku_strdup(fname); char ch; - for (i=0; (ch=fname[i]); i++) { + for (int i=0; (ch=fname[i]); i++) { // // TODO: this may fail in windows, double check the absolute path names // and '/' as the directory delimiter or something @@ -210,27 +212,25 @@ static void create_dir_from_file (const char *fname) { // Open the file if it is not already open. If it is already open, then do nothing. static void internal_toku_recover_fopen_or_fcreate (RECOVER_ENV env, int flags, int mode, char *fixedfname, FILENUM filenum, u_int32_t treeflags) { - { - struct cf_pair *pair = NULL; - int r = find_cachefile(&env->fmap, filenum, &pair); - if (0==r) { - toku_free(fixedfname); - return; - } + int r; + + // already open + struct cf_pair *pair = NULL; + r = find_cachefile(&env->fmap, filenum, &pair); + if (r == 0) { + toku_free(fixedfname); + return; } - CACHEFILE cf; - int fd = open(fixedfname, O_RDWR|O_BINARY|flags, mode); - if (fd<0) { - char org_wd[1000]; - char *wd=getcwd(org_wd, sizeof(org_wd)); - fprintf(stderr, "%s:%d Could not open file %s, cwd=%s, errno=%d (%s)\n", - __FILE__, __LINE__, fixedfname, wd, errno, strerror(errno)); + if (flags & O_TRUNC) { + // maybe unlink + r = unlink(fixedfname); + if (r != 0) + printf("%s:%d unlink %d\n", __FUNCTION__, __LINE__, errno); } - assert(fd>=0); BRT brt=0; - int r = toku_brt_create(&brt); + r = toku_brt_create(&brt); assert(r == 0); // create tree with treeflags, otherwise use the treeflags from the tree @@ -243,17 +243,15 @@ static void internal_toku_recover_fopen_or_fcreate (RECOVER_ENV env, int flags, if (env->dup_compare) toku_brt_set_dup_compare(brt, env->dup_compare); - brt->fname = fixedfname; - brt->h=0; - brt->db = 0; - r = toku_cachetable_openfd(&cf, env->ct, fd, fixedfname); + // TODO mode + mode = mode; + + r = toku_brt_open(brt, fixedfname, fixedfname, (flags & O_CREAT) != 0, FALSE, env->ct, NULL, NULL); assert(r == 0); - brt->cf=cf; - r = toku_read_brt_header_and_store_in_cachefile(brt->cf, &brt->h); - if (r==TOKUDB_DICTIONARY_NO_HEADER) { - r = toku_brt_alloc_init_header(brt); - } - filenum_map_add(&env->fmap, filenum, cf, brt); + + toku_free(fixedfname); + + file_map_add(&env->fmap, filenum, NULL, brt); } static void toku_recover_fopen (LSN UU(lsn), TXNID UU(xid), BYTESTRING fname, FILENUM filenum, RECOVER_ENV env) { @@ -261,7 +259,17 @@ static void toku_recover_fopen (LSN UU(lsn), TXNID UU(xid), BYTESTRING fname, FI internal_toku_recover_fopen_or_fcreate(env, 0, 0, fixedfname, filenum, 0); } -static int toku_recover_backward_fopen (struct logtype_fopen *UU(l), RECOVER_ENV UU(env)) { +static int toku_recover_backward_fopen (struct logtype_fopen *l, RECOVER_ENV env) { + if (env->bs.bs == BS_SAW_CKPT_END) { + // close the tree + struct cf_pair *pair = NULL; + int r = find_cachefile(&env->fmap, l->filenum, &pair); + if (r == 0) { + r = toku_close_brt(pair->brt, 0, 0); + assert(r == 0); + pair->brt=0; + } + } return 0; } @@ -348,13 +356,19 @@ static int toku_recover_backward_enq_delete_any (struct logtype_enq_delete_any * static void toku_recover_fclose (LSN UU(lsn), BYTESTRING UU(fname), FILENUM filenum, RECOVER_ENV UU(env)) { struct cf_pair *pair = NULL; int r = find_cachefile(&env->fmap, filenum, &pair); - assert(r == 0); - r = toku_close_brt(pair->brt, 0, 0); - assert(r == 0); - pair->brt=0; + if (r == 0) { + r = toku_close_brt(pair->brt, 0, 0); + assert(r == 0); + pair->brt=0; + } } -static int toku_recover_backward_fclose (struct logtype_fclose *UU(l), RECOVER_ENV UU(env)) { +static int toku_recover_backward_fclose (struct logtype_fclose *l, RECOVER_ENV env) { + if (env->bs.bs == BS_SAW_CKPT) { + // tree open + char *fixedfname = fixup_fname(&l->fname); + internal_toku_recover_fopen_or_fcreate(env, 0, 0, fixedfname, l->filenum, 0); + } return 0; } @@ -374,8 +388,8 @@ static int toku_recover_backward_begin_checkpoint (struct logtype_begin_checkpoi if (bs->n_live_txns==0) { fprintf(stderr, "Turning around at begin_checkpoint %" PRIu64 "\n", l->lsn.lsn); return 1; - } - else return 0; + } else + return 0; case BS_SAW_CKPT: return 0; // ignore it } @@ -427,11 +441,11 @@ static int toku_recover_backward_xstillopen (struct logtype_xstillopen *l, RECOV case BS_INIT: return 0; // ignore live txns from incomplete checkpoint case BS_SAW_CKPT_END: - if (bs->n_live_txns==0) { + if (bs->n_live_txns == 0) bs->min_live_txn = l->txnid; - } else { - if (bs->min_live_txn > l->txnid) bs->min_live_txn = l->txnid; - } + // TODO need a new txnid comparison + else if (bs->min_live_txn > l->txnid) + bs->min_live_txn = l->txnid; bs->n_live_txns++; return 0; case BS_SAW_CKPT: @@ -470,7 +484,7 @@ static int toku_recover_backward_xbegin (struct logtype_xbegin *l, RECOVER_ENV e fprintf(stderr, "Turning around at xbegin %" PRIu64 "\n", l->lsn.lsn); return 1; } else { - fprintf(stderr, "scanning back at xbegin %" PRIu64 " (looking for %" PRIu64 ")\n", l->lsn.lsn, bs->min_live_txn); + fprintf(stderr, "Scanning back at xbegin %" PRIu64 " (looking for %" PRIu64 ")\n", l->lsn.lsn, bs->min_live_txn); return 0; } } @@ -580,6 +594,7 @@ int tokudb_needs_recovery(const char *log_dir) { static int compare_txn(const void *a, const void *b) { TOKUTXN atxn = (TOKUTXN) * (void **) a; TOKUTXN btxn = (TOKUTXN) * (void **) b; + // TODO this is wrong. we want if (older(atxn, btxn)) return -1 if (atxn->txnid64 > btxn->txnid64) return -1; if (atxn->txnid64 < btxn->txnid64) @@ -676,7 +691,7 @@ static int do_recovery(RECOVER_ENV env, const char *data_dir, const char *log_di varray_destroy(&live_txns); // close the open dictionaries - filenum_map_close_dictionaries(&env->fmap); + file_map_close_dictionaries(&env->fmap); // write a recovery log entry BYTESTRING recover_comment = { strlen("recover"), "recover" }; diff --git a/src/tests/recover-checkpoint-fcreate-fdelete-fcreate.c b/src/tests/recover-checkpoint-fcreate-fdelete-fcreate.c new file mode 100644 index 00000000000..525f155e778 --- /dev/null +++ b/src/tests/recover-checkpoint-fcreate-fdelete-fcreate.c @@ -0,0 +1,130 @@ +// fcreate, fdelete, fcreate after a checkpoint + +#include +#include +#include "test.h" + +const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN; + +char *namea="a.db"; +char *nameb="b.db"; + +static void run_test (void) { + int r; + system("rm -rf " ENVDIR); + toku_os_mkdir(ENVDIR, S_IRWXU+S_IRWXG+S_IRWXO); + DB_ENV *env; + DB *db; + r = db_env_create(&env, 0); CKERR(r); + r = env->open(env, ENVDIR, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + + // checkpoint + r = env->txn_checkpoint(env, 0, 0, 0); CKERR(r); + + // create + r = db_create(&db, env, 0); CKERR(r); + r = db->open(db, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r); + r = db->close(db, 0); CKERR(r); + + // delete + r = db_create(&db, env, 0); CKERR(r); + r = db->remove(db, namea, NULL, 0); CKERR(r); + + // create + r = db_create(&db, env, 0); CKERR(r); + r = db->set_flags(db, DB_DUPSORT); CKERR(r); + r = db->open(db, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r); + r = db->close(db, 0); CKERR(r); + + abort(); +} + +static void run_recover (void) { + DB_ENV *env; + int r; + + r = db_env_create(&env, 0); CKERR(r); + r = env->open(env, ENVDIR, envflags + DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + + u_int32_t dbflags; + DB *db; + r = db_create(&db, env, 0); CKERR(r); + r = db->open(db, NULL, namea, NULL, DB_UNKNOWN, DB_AUTO_COMMIT, 0666); CKERR(r); + r = db->get_flags(db, &dbflags); CKERR(r); + assert(dbflags == DB_DUPSORT); + r = db->close(db, 0); CKERR(r); + + r = env->close(env, 0); CKERR(r); + exit(0); +} + +static void run_recover_only (void) { + DB_ENV *env; + int r; + + r = db_env_create(&env, 0); CKERR(r); + r = env->open(env, ENVDIR, envflags + DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + r = env->close(env, 0); CKERR(r); + exit(0); +} + +static void run_no_recover (void) { + DB_ENV *env; + int r; + + r = db_env_create(&env, 0); CKERR(r); + r = env->open(env, ENVDIR, envflags & ~DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + r = env->close(env, 0); CKERR(r); + exit(0); +} + +const char *cmd; + +BOOL do_test=FALSE, do_recover=FALSE, do_recover_only=FALSE, do_no_recover = FALSE; + +static void test_parse_args (int argc, char *argv[]) { + int resultcode; + cmd = argv[0]; + argc--; argv++; + while (argc>0) { + if (strcmp(argv[0], "-v") == 0) { + verbose++; + } else if (strcmp(argv[0],"-q")==0) { + verbose--; + if (verbose<0) verbose=0; + } else if (strcmp(argv[0], "--test")==0) { + do_test=TRUE; + } else if (strcmp(argv[0], "--recover") == 0) { + do_recover=TRUE; + } else if (strcmp(argv[0], "--recover-only") == 0) { + do_recover_only=TRUE; + } else if (strcmp(argv[0], "--no-recover") == 0) { + do_no_recover=TRUE; + } else if (strcmp(argv[0], "-h")==0) { + resultcode=0; + do_usage: + fprintf(stderr, "Usage:\n%s [-v|-q]* [-h] {--test | --recover } \n", cmd); + exit(resultcode); + } else { + fprintf(stderr, "Unknown arg: %s\n", argv[0]); + resultcode=1; + goto do_usage; + } + argc--; + argv++; + } +} + +int test_main (int argc, char *argv[]) { + test_parse_args(argc, argv); + if (do_test) { + run_test(); + } else if (do_recover) { + run_recover(); + } else if (do_recover_only) { + run_recover_only(); + } else if (do_no_recover) { + run_no_recover(); + } + return 0; +} diff --git a/src/tests/recover-checkpoint-fopen-1.c b/src/tests/recover-checkpoint-fopen-1.c index 5d6cc2b1fc6..2bd762a89a2 100644 --- a/src/tests/recover-checkpoint-fopen-1.c +++ b/src/tests/recover-checkpoint-fopen-1.c @@ -1,12 +1,12 @@ +// this test verifies that db creation after a checkpoint works for nodup and dupsort dictionaries + #include -#include #include "test.h" const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN |DB_RECOVER; char *namea="a.db"; char *nameb="b.db"; - static void run_test (BOOL do_commit, BOOL do_abort) { int r; system("rm -rf " ENVDIR); @@ -29,8 +29,8 @@ static void run_test (BOOL do_commit, BOOL do_abort) { { DBT a={.data="a", .size=2}; DBT b={.data="b", .size=2}; - r = dba->put(dba, txn, &a, &b, 0); CKERR(r); - r = dbb->put(dbb, txn, &b, &a, 0); CKERR(r); + r = dba->put(dba, txn, &a, &b, DB_YESOVERWRITE); CKERR(r); + r = dbb->put(dbb, txn, &b, &a, DB_YESOVERWRITE); CKERR(r); } //printf("opened\n"); if (do_commit) { @@ -46,8 +46,6 @@ static void run_test (BOOL do_commit, BOOL do_abort) { abort(); } -#if 0 - static void run_recover (BOOL did_commit) { DB_ENV *env; DB *dba, *dbb; @@ -56,8 +54,19 @@ static void run_recover (BOOL did_commit) { r = env->open(env, ENVDIR, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); r = db_create(&dba, env, 0); CKERR(r); r = dba->open(dba, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r); + + u_int32_t dbflags; + dbflags = 0; + r = dba->get_flags(dba, &dbflags); CKERR(r); + assert(dbflags == 0); + r = db_create(&dbb, env, 0); CKERR(r); - r = dba->open(dbb, NULL, nameb, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r); + r = dbb->open(dbb, NULL, nameb, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r); + + dbflags = 0; + r = dbb->get_flags(dbb, &dbflags); CKERR(r); + assert(dbflags == 0); + DBT aa={.size=0}, ab={.size=0}; DBT ba={.size=0}, bb={.size=0}; DB_TXN *txn; @@ -99,8 +108,6 @@ static void run_recover (BOOL did_commit) { r = env->close(env, 0); CKERR(r); } -#endif - static void run_recover_only (void) { DB_ENV *env; int r; @@ -184,6 +191,10 @@ int test_main (int argc, char *argv[]) { run_test(TRUE, FALSE); } else if (do_abort) { run_test(FALSE, TRUE); + } else if (do_recover_committed) { + run_recover(TRUE); + } else if (do_recover_aborted) { + run_recover(FALSE); } else if (do_recover_only) { run_recover_only(); } else if (do_no_recover) { diff --git a/src/tests/recover-checkpoint-fopen-dupsort-1.c b/src/tests/recover-checkpoint-fopen-dupsort-1.c index 09974ac400f..bface0aaf8a 100644 --- a/src/tests/recover-checkpoint-fopen-dupsort-1.c +++ b/src/tests/recover-checkpoint-fopen-dupsort-1.c @@ -1,3 +1,5 @@ +// this test verifies that db creation after a checkpoint works for nodup and dupsort dictionaries + #include #include "test.h" @@ -46,8 +48,6 @@ static void run_test (BOOL do_commit, BOOL do_abort) { abort(); } -#if 0 - static void run_recover (BOOL did_commit) { DB_ENV *env; DB *dba, *dbb; @@ -56,8 +56,19 @@ static void run_recover (BOOL did_commit) { r = env->open(env, ENVDIR, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); r = db_create(&dba, env, 0); CKERR(r); r = dba->open(dba, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r); + + u_int32_t dbflags; + dbflags = 0; + r = dba->get_flags(dba, &dbflags); CKERR(r); + assert(dbflags == 0); + r = db_create(&dbb, env, 0); CKERR(r); r = dba->open(dbb, NULL, nameb, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r); + + dbflags = 0; + r = dbb->get_flags(dbb, &dbflags); CKERR(r); + assert(dbflags == DB_DUPSORT); + DBT aa={.size=0}, ab={.size=0}; DBT ba={.size=0}, bb={.size=0}; DB_TXN *txn; @@ -99,8 +110,6 @@ static void run_recover (BOOL did_commit) { r = env->close(env, 0); CKERR(r); } -#endif - static void run_recover_only (void) { DB_ENV *env; int r; @@ -184,6 +193,10 @@ int test_main (int argc, char *argv[]) { run_test(TRUE, FALSE); } else if (do_abort) { run_test(FALSE, TRUE); + } else if (do_recover_committed) { + run_recover(TRUE); + } else if (do_recover_aborted) { + run_recover(FALSE); } else if (do_recover_only) { run_recover_only(); } else if (do_no_recover) { diff --git a/src/tests/recover-fassociate-dupsort.c b/src/tests/recover-fassociate-dupsort.c index 811ed46d185..13c1ef40f66 100644 --- a/src/tests/recover-fassociate-dupsort.c +++ b/src/tests/recover-fassociate-dupsort.c @@ -1,3 +1,5 @@ +// this test makes sure that fassociate can open nodup and dupsort dictionaries + #include #include #include "test.h" @@ -7,8 +9,7 @@ const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG char *namea="a.db"; char *nameb="b.db"; -static void -run_test (void) { +static void run_test (void) { int r; system("rm -rf " ENVDIR); toku_os_mkdir(ENVDIR, S_IRWXU+S_IRWXG+S_IRWXO); @@ -40,19 +41,32 @@ run_test (void) { abort(); } -static void -run_recover (void) { +static void run_recover (void) { DB_ENV *env; int r; r = db_env_create(&env, 0); CKERR(r); r = env->open(env, ENVDIR, envflags + DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + + u_int32_t dbflags; + DB *dba; + r = db_create(&dba, env, 0); CKERR(r); + r = dba->open(dba, NULL, namea, NULL, DB_UNKNOWN, DB_AUTO_COMMIT, 0666); CKERR(r); + r = dba->get_flags(dba, &dbflags); CKERR(r); + assert(dbflags == DB_DUPSORT); + r = dba->close(dba, 0); CKERR(r); + DB *dbb; + r = db_create(&dbb, env, 0); CKERR(r); + r = dbb->open(dbb, NULL, nameb, NULL, DB_UNKNOWN, DB_AUTO_COMMIT, 0666); CKERR(r); + r = dbb->get_flags(dbb, &dbflags); CKERR(r); + assert(dbflags == DB_DUPSORT); + r = dbb->close(dbb, 0); CKERR(r); + r = env->close(env, 0); CKERR(r); exit(0); } -static void -run_no_recover (void) { +static void run_no_recover (void) { DB_ENV *env; int r; @@ -64,7 +78,7 @@ run_no_recover (void) { const char *cmd; -BOOL do_commit=FALSE, do_abort=FALSE, do_explicit_abort=FALSE, do_recover_committed=FALSE, do_recover_aborted=FALSE, do_recover_only=FALSE, do_no_recover = FALSE; +BOOL do_test=FALSE, do_recover=FALSE, do_recover_only=FALSE, do_no_recover = FALSE; static void test_parse_args (int argc, char *argv[]) { int resultcode; @@ -76,16 +90,10 @@ static void test_parse_args (int argc, char *argv[]) { } else if (strcmp(argv[0],"-q")==0) { verbose--; if (verbose<0) verbose=0; - } else if (strcmp(argv[0], "--commit")==0) { - do_commit=TRUE; - } else if (strcmp(argv[0], "--abort")==0) { - do_abort=TRUE; - } else if (strcmp(argv[0], "--explicit-abort")==0) { - do_explicit_abort=TRUE; - } else if (strcmp(argv[0], "--recover-committed")==0) { - do_recover_committed=TRUE; - } else if (strcmp(argv[0], "--recover-aborted")==0) { - do_recover_aborted=TRUE; + } else if (strcmp(argv[0], "--test")==0) { + do_test=TRUE; + } else if (strcmp(argv[0], "--recover") == 0) { + do_recover=TRUE; } else if (strcmp(argv[0], "--recover-only") == 0) { do_recover_only=TRUE; } else if (strcmp(argv[0], "--no-recover") == 0) { @@ -93,7 +101,7 @@ static void test_parse_args (int argc, char *argv[]) { } else if (strcmp(argv[0], "-h")==0) { resultcode=0; do_usage: - fprintf(stderr, "Usage:\n%s [-v|-q]* [-h] {--commit | --abort | --explicit-abort | --recover-committed | --recover-aborted } \n", cmd); + fprintf(stderr, "Usage:\n%s [-v|-q]* [-h] {--test | --recover } \n", cmd); exit(resultcode); } else { fprintf(stderr, "Unknown arg: %s\n", argv[0]); @@ -103,28 +111,14 @@ static void test_parse_args (int argc, char *argv[]) { argc--; argv++; } - { - int n_specified=0; - if (do_commit) n_specified++; - if (do_abort) n_specified++; - if (do_explicit_abort) n_specified++; - if (do_recover_committed) n_specified++; - if (do_recover_aborted) n_specified++; - if (do_recover_only) n_specified++; - if (do_no_recover) n_specified++; - if (n_specified>1) { - printf("Specify only one of --commit or --abort or --recover-committed or --recover-aborted\n"); - resultcode=1; - goto do_usage; - } - } } -int -test_main (int argc, char *argv[]) { +int test_main (int argc, char *argv[]) { test_parse_args(argc, argv); - if (do_commit) { + if (do_test) { run_test(); + } else if (do_recover) { + run_recover(); } else if (do_recover_only) { run_recover(); } else if (do_no_recover) { diff --git a/src/tests/recover-fassociate-nodup.c b/src/tests/recover-fassociate-nodup.c index 1f486e3418a..74724c18379 100644 --- a/src/tests/recover-fassociate-nodup.c +++ b/src/tests/recover-fassociate-nodup.c @@ -1,3 +1,5 @@ +// this test makes sure that fassociate can open nodup and dupsort dictionaries + #include #include #include "test.h" @@ -7,8 +9,7 @@ const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG char *namea="a.db"; char *nameb="b.db"; -static void -run_test (void) { +static void run_test (void) { int r; system("rm -rf " ENVDIR); toku_os_mkdir(ENVDIR, S_IRWXU+S_IRWXG+S_IRWXO); @@ -38,19 +39,32 @@ run_test (void) { abort(); } -static void -run_recover (void) { +static void run_recover (void) { DB_ENV *env; int r; r = db_env_create(&env, 0); CKERR(r); r = env->open(env, ENVDIR, envflags + DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + + u_int32_t dbflags; + DB *dba; + r = db_create(&dba, env, 0); CKERR(r); + r = dba->open(dba, NULL, namea, NULL, DB_UNKNOWN, DB_AUTO_COMMIT, 0666); CKERR(r); + r = dba->get_flags(dba, &dbflags); CKERR(r); + assert(dbflags == 0); + r = dba->close(dba, 0); CKERR(r); + DB *dbb; + r = db_create(&dbb, env, 0); CKERR(r); + r = dbb->open(dbb, NULL, nameb, NULL, DB_UNKNOWN, DB_AUTO_COMMIT, 0666); CKERR(r); + r = dbb->get_flags(dbb, &dbflags); CKERR(r); + assert(dbflags == 0); + r = dbb->close(dbb, 0); CKERR(r); + r = env->close(env, 0); CKERR(r); exit(0); } -static void -run_no_recover (void) { +static void run_no_recover (void) { DB_ENV *env; int r; @@ -62,7 +76,7 @@ run_no_recover (void) { const char *cmd; -BOOL do_commit=FALSE, do_abort=FALSE, do_explicit_abort=FALSE, do_recover_committed=FALSE, do_recover_aborted=FALSE, do_recover_only=FALSE, do_no_recover = FALSE; +BOOL do_test=FALSE, do_recover=FALSE, do_recover_only=FALSE, do_no_recover = FALSE; static void test_parse_args (int argc, char *argv[]) { int resultcode; @@ -74,16 +88,10 @@ static void test_parse_args (int argc, char *argv[]) { } else if (strcmp(argv[0],"-q")==0) { verbose--; if (verbose<0) verbose=0; - } else if (strcmp(argv[0], "--commit")==0) { - do_commit=TRUE; - } else if (strcmp(argv[0], "--abort")==0) { - do_abort=TRUE; - } else if (strcmp(argv[0], "--explicit-abort")==0) { - do_explicit_abort=TRUE; - } else if (strcmp(argv[0], "--recover-committed")==0) { - do_recover_committed=TRUE; - } else if (strcmp(argv[0], "--recover-aborted")==0) { - do_recover_aborted=TRUE; + } else if (strcmp(argv[0], "--test")==0) { + do_test=TRUE; + } else if (strcmp(argv[0], "--recover") == 0) { + do_recover=TRUE; } else if (strcmp(argv[0], "--recover-only") == 0) { do_recover_only=TRUE; } else if (strcmp(argv[0], "--no-recover") == 0) { @@ -91,7 +99,7 @@ static void test_parse_args (int argc, char *argv[]) { } else if (strcmp(argv[0], "-h")==0) { resultcode=0; do_usage: - fprintf(stderr, "Usage:\n%s [-v|-q]* [-h] {--commit | --abort | --explicit-abort | --recover-committed | --recover-aborted } \n", cmd); + fprintf(stderr, "Usage:\n%s [-v|-q]* [-h] {--test | --recover } \n", cmd); exit(resultcode); } else { fprintf(stderr, "Unknown arg: %s\n", argv[0]); @@ -101,28 +109,14 @@ static void test_parse_args (int argc, char *argv[]) { argc--; argv++; } - { - int n_specified=0; - if (do_commit) n_specified++; - if (do_abort) n_specified++; - if (do_explicit_abort) n_specified++; - if (do_recover_committed) n_specified++; - if (do_recover_aborted) n_specified++; - if (do_recover_only) n_specified++; - if (do_no_recover) n_specified++; - if (n_specified>1) { - printf("Specify only one of --commit or --abort or --recover-committed or --recover-aborted\n"); - resultcode=1; - goto do_usage; - } - } } -int -test_main (int argc, char *argv[]) { +int test_main (int argc, char *argv[]) { test_parse_args(argc, argv); - if (do_commit) { + if (do_test) { run_test(); + } else if (do_recover) { + run_recover(); } else if (do_recover_only) { run_recover(); } else if (do_no_recover) { diff --git a/src/tests/recover-fcreate-fdelete.c b/src/tests/recover-fcreate-fdelete.c new file mode 100644 index 00000000000..1a3e689c9cf --- /dev/null +++ b/src/tests/recover-fcreate-fdelete.c @@ -0,0 +1,121 @@ +// verify thtat we can create the correct tree type after the db is removed + +#include +#include +#include "test.h" + +const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN; + +char *namea="a.db"; +char *nameb="b.db"; + +static void run_test (void) { + int r; + system("rm -rf " ENVDIR); + toku_os_mkdir(ENVDIR, S_IRWXU+S_IRWXG+S_IRWXO); + DB_ENV *env; + DB *db; + r = db_env_create(&env, 0); CKERR(r); + r = env->open(env, ENVDIR, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + + DB_TXN *txn; + r = env->txn_begin(env, NULL, &txn, 0); CKERR(r); + + r = db_create(&db, env, 0); CKERR(r); + r = db->open(db, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r); + r = db->close(db, 0); CKERR(r); + + r = db_create(&db, env, 0); CKERR(r); + r = db->remove(db, namea, NULL, 0); CKERR(r); + + r = env->txn_checkpoint(env, 0, 0, 0); CKERR(r); + + r = db_create(&db, env, 0); CKERR(r); + r = db->set_flags(db, DB_DUPSORT); CKERR(r); + r = db->open(db, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r); + r = db->close(db, 0); CKERR(r); + + r = txn->commit(txn, 0); CKERR(r); + + abort(); +} + +static void run_recover (void) { + DB_ENV *env; + int r; + + r = db_env_create(&env, 0); CKERR(r); + r = env->open(env, ENVDIR, envflags + DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + + u_int32_t dbflags; + DB *db; + r = db_create(&db, env, 0); CKERR(r); + r = db->open(db, NULL, namea, NULL, DB_UNKNOWN, DB_AUTO_COMMIT, 0666); CKERR(r); + r = db->get_flags(db, &dbflags); CKERR(r); + assert(dbflags == DB_DUPSORT); + r = db->close(db, 0); CKERR(r); + + r = env->close(env, 0); CKERR(r); + exit(0); +} + +static void run_no_recover (void) { + DB_ENV *env; + int r; + + r = db_env_create(&env, 0); CKERR(r); + r = env->open(env, ENVDIR, envflags & ~DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + r = env->close(env, 0); CKERR(r); + exit(0); +} + +const char *cmd; + +BOOL do_test=FALSE, do_recover=FALSE, do_recover_only=FALSE, do_no_recover = FALSE; + +static void test_parse_args (int argc, char *argv[]) { + int resultcode; + cmd = argv[0]; + argc--; argv++; + while (argc>0) { + if (strcmp(argv[0], "-v") == 0) { + verbose++; + } else if (strcmp(argv[0],"-q")==0) { + verbose--; + if (verbose<0) verbose=0; + } else if (strcmp(argv[0], "--test")==0) { + do_test=TRUE; + } else if (strcmp(argv[0], "--recover") == 0) { + do_recover=TRUE; + } else if (strcmp(argv[0], "--recover-only") == 0) { + do_recover_only=TRUE; + } else if (strcmp(argv[0], "--no-recover") == 0) { + do_no_recover=TRUE; + } else if (strcmp(argv[0], "-h")==0) { + resultcode=0; + do_usage: + fprintf(stderr, "Usage:\n%s [-v|-q]* [-h] {--test | --recover } \n", cmd); + exit(resultcode); + } else { + fprintf(stderr, "Unknown arg: %s\n", argv[0]); + resultcode=1; + goto do_usage; + } + argc--; + argv++; + } +} + +int test_main (int argc, char *argv[]) { + test_parse_args(argc, argv); + if (do_test) { + run_test(); + } else if (do_recover) { + run_recover(); + } else if (do_recover_only) { + run_recover(); + } else if (do_no_recover) { + run_no_recover(); + } + return 0; +} diff --git a/src/tests/recover-fopen-fdelete-checkpoint-fcreate.c b/src/tests/recover-fopen-fdelete-checkpoint-fcreate.c new file mode 100644 index 00000000000..a6a1c6fa3ed --- /dev/null +++ b/src/tests/recover-fopen-fdelete-checkpoint-fcreate.c @@ -0,0 +1,151 @@ +// verify that we can fcreate after fdelete with different treeflags + +#include +#include +#include "test.h" + +const int envflags = DB_INIT_MPOOL|DB_CREATE|DB_THREAD |DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_TXN; + +char *namea="a.db"; +char *nameb="b.db"; + +static void put_something(DB_ENV *env, DB *db, char *k, char *v) { + int r; + DBT key={.data=k, .size=strlen(k)}; + DBT val={.data=v, .size=strlen(v)}; + DB_TXN *txn; + r = env->txn_begin(env, 0, &txn, 0); CKERR(r); + r = db->put(db, txn, &key, &val, DB_YESOVERWRITE); CKERR(r); + r = txn->commit(txn, 0); CKERR(r); +} + +static void run_test (void) { + int r; + system("rm -rf " ENVDIR); + toku_os_mkdir(ENVDIR, S_IRWXU+S_IRWXG+S_IRWXO); + + DB_ENV *env; + DB *db; + DB_TXN *txn; + + r = db_env_create(&env, 0); CKERR(r); + r = env->open(env, ENVDIR, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + + // fcreate + r = db_create(&db, env, 0); CKERR(r); + r = db->open(db, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r); + r = db->close(db, 0); CKERR(r); + + // dummy transaction + r = env->txn_begin(env, NULL, &txn, 0); CKERR(r); + + // fopen + r = db_create(&db, env, 0); CKERR(r); + r = db->open(db, NULL, namea, NULL, DB_UNKNOWN, DB_AUTO_COMMIT, 0666); CKERR(r); + + // insert something + put_something(env, db, "a", "b"); + + r = db->close(db, 0); CKERR(r); + + // fdelete + r = db_create(&db, env, 0); CKERR(r); + r = db->remove(db, namea, NULL, 0); CKERR(r); + + // checkpoint + r = env->txn_checkpoint(env, 0, 0, 0); CKERR(r); + + r = txn->commit(txn, 0); CKERR(r); + + // fcreate with different treeflags + r = db_create(&db, env, 0); CKERR(r); + r = db->set_flags(db, DB_DUPSORT); CKERR(r); + r = db->open(db, NULL, namea, NULL, DB_BTREE, DB_AUTO_COMMIT|DB_CREATE, 0666); CKERR(r); + + // insert something + put_something(env, db, "c", "d"); + + r = db->close(db, 0); CKERR(r); + + abort(); +} + +static void run_recover (void) { + DB_ENV *env; + int r; + + r = db_env_create(&env, 0); CKERR(r); + r = env->open(env, ENVDIR, envflags + DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + + u_int32_t dbflags; + DB *db; + r = db_create(&db, env, 0); CKERR(r); + r = db->open(db, NULL, namea, NULL, DB_UNKNOWN, DB_AUTO_COMMIT, 0666); CKERR(r); + r = db->get_flags(db, &dbflags); CKERR(r); + assert(dbflags == DB_DUPSORT); + r = db->close(db, 0); CKERR(r); + + r = env->close(env, 0); CKERR(r); + exit(0); +} + +static void run_no_recover (void) { + DB_ENV *env; + int r; + + r = db_env_create(&env, 0); CKERR(r); + r = env->open(env, ENVDIR, envflags & ~DB_RECOVER, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + r = env->close(env, 0); CKERR(r); + exit(0); +} + +const char *cmd; + +BOOL do_test=FALSE, do_recover=FALSE, do_recover_only=FALSE, do_no_recover = FALSE; + +static void test_parse_args (int argc, char *argv[]) { + int resultcode; + cmd = argv[0]; + argc--; argv++; + while (argc>0) { + if (strcmp(argv[0], "-v") == 0) { + verbose++; + } else if (strcmp(argv[0],"-q")==0) { + verbose--; + if (verbose<0) verbose=0; + } else if (strcmp(argv[0], "--test")==0) { + do_test=TRUE; + } else if (strcmp(argv[0], "--recover") == 0) { + do_recover=TRUE; + } else if (strcmp(argv[0], "--recover-only") == 0) { + do_recover_only=TRUE; + } else if (strcmp(argv[0], "--no-recover") == 0) { + do_no_recover=TRUE; + } else if (strcmp(argv[0], "-h")==0) { + resultcode=0; + do_usage: + fprintf(stderr, "Usage:\n%s [-v|-q]* [-h] {--test | --recover } \n", cmd); + exit(resultcode); + } else { + fprintf(stderr, "Unknown arg: %s\n", argv[0]); + resultcode=1; + goto do_usage; + } + argc--; + argv++; + } +} + +int test_main (int argc, char *argv[]) { + test_parse_args(argc, argv); + if (do_test) { + run_test(); + } else if (do_recover) { + run_recover(); + } else if (do_recover_only) { + run_recover(); + } else if (do_no_recover) { + run_no_recover(); + } + return 0; +} diff --git a/src/tests/x1-nested2.c b/src/tests/x1-nested2.c index c2cbb2afd99..8aa19ff8e5f 100644 --- a/src/tests/x1-nested2.c +++ b/src/tests/x1-nested2.c @@ -45,11 +45,10 @@ do_x1_shutdown (BOOL do_commit, BOOL do_abort) { r = dbb->put(dbb, txn, &b, &a, 0); CKERR(r); } //printf("opened\n"); + r = txn->commit(txn, 0); CKERR(r); if (do_commit) { - r = txn->commit(txn, 0); CKERR(r); r = txn->commit(txn0, 0); CKERR(r); } else if (do_abort) { - r = txn->abort(txn); CKERR(r); r = txn->abort(txn0); CKERR(r); // force an fsync of the log