From 192de3d723b1cf08b6e2100da1f40aa023b701fe Mon Sep 17 00:00:00 2001 From: Barry Perlman Date: Tue, 16 Apr 2013 23:59:31 -0400 Subject: [PATCH] [t:2892] Add test of upgrading dictionary created by 4.1.1 loader. git-svn-id: file:///svn/toku/tokudb@25885 c7de825b-a66e-492c-adef-691d508d4ae1 --- src/tests/upgrade-test-6.c | 384 +++++++++++++++++++++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 src/tests/upgrade-test-6.c diff --git a/src/tests/upgrade-test-6.c b/src/tests/upgrade-test-6.c new file mode 100644 index 00000000000..bb5fc8d9349 --- /dev/null +++ b/src/tests/upgrade-test-6.c @@ -0,0 +1,384 @@ +/* -*- mode: C; c-basic-offset: 4 -*- */ +#ident "Copyright (c) 2010 Tokutek Inc. All rights reserved." +#ident "$Id$" + + +// Purpose of this test is to verify that a dictionary created by the 4.1.1 +// loader can be properly read with 5.0. +// This file was derived from the 4.1.1 version of loader-stress-test.c, +// which was used to create the dictionary. +// This test only reads (and upgrades) the dictionary, it does not load it. + +// Need to use malloc for the malloc instrumentation tests +#define TOKU_ALLOW_DEPRECATED + +#include "test.h" +#include "toku_pthread.h" +#include "toku_atomic.h" +#include +#include +#include "ydb-internal.h" + +DB_ENV *env; +enum {MAX_NAME=128}; +enum {MAX_DBS=256}; +int NUM_DBS=1; +int NUM_ROWS=250000; +int CHECK_RESULTS=0; +int USE_PUTS=0; +enum { old_default_cachesize=1024 }; // MB +int CACHESIZE=old_default_cachesize; +int ALLOW_DUPS=0; +enum {MAGIC=311}; +char *datadir = NULL; +BOOL check_est = TRUE; // do check the estimates by default +BOOL footprint_print = FALSE; // print memory footprint info + + +// Code for showing memory footprint information. +pthread_mutex_t my_lock = PTHREAD_MUTEX_INITIALIZER; +size_t hiwater; +size_t water; +size_t hiwater_start; +static long long mcount = 0, fcount=0; + + +size_t malloc_usable_size(void *p); + +static void my_free(void*p) { + if (p) { + water-=malloc_usable_size(p); + } + free(p); +} + +static void *my_malloc(size_t size) { + void *r = malloc(size); + if (r) { + water += malloc_usable_size(r); + if (water>hiwater) hiwater=water; + } + return r; +} + +static void *my_realloc(void *p, size_t size) { + size_t old_usable = p ? malloc_usable_size(p) : 0; + void *r = realloc(p, size); + if (r) { + water -= old_usable; + water += malloc_usable_size(r); + } + return r; +} + +// +// Functions to create unique key/value pairs, row generators, checkers, ... for each of NUM_DBS +// + +// a is the bit-wise permute table. For DB[i], permute bits as described in a[i] using 'twiddle32' +// inv is the inverse bit-wise permute of a[]. To get the original value from a twiddled value, twiddle32 (again) with inv[] +int a[MAX_DBS][32]; +int inv[MAX_DBS][32]; + +#if defined(__cilkplusplus) || defined (__cplusplus) +extern "C" { +#endif + +// rotate right and left functions +static inline unsigned int rotr32(const unsigned int x, const unsigned int num) { + const unsigned int n = num % 32; + return (x >> n) | ( x << (32 - n)); +} +static inline unsigned int rotl32(const unsigned int x, const unsigned int num) { + const unsigned int n = num % 32; + return (x << n) | ( x >> (32 - n)); +} + +static void generate_permute_tables(void) { + int i, j, tmp; + for(int db=0;db> i ) & 1) << inv[db][i]; + } + return b; +} + + +static unsigned int pkey_for_val(int key, int i) { + return rotr32(key, i) - MAGIC; +} + +#if defined(__cilkplusplus) || defined(__cplusplus) +} // extern "C" +#endif + +static void check_results(DB **dbs) +{ + for(int j=0;jtxn_begin(env, NULL, &txn, 0); + CKERR(r); + + DBC *cursor; + r = dbs[j]->cursor(dbs[j], txn, &cursor, 0); + CKERR(r); + for(int i=0;ic_get(cursor, &key, &val, DB_NEXT); + CKERR(r); + k = *(unsigned int*)key.data; + pkey_for_db_key = (j == 0) ? k : inv_twiddle32(k, j); + v = *(unsigned int*)val.data; + // test that we have the expected keys and values + assert((unsigned int)pkey_for_db_key == (unsigned int)pkey_for_val(v, j)); +// printf(" DB[%d] key = %10u, val = %10u, pkey_for_db_key = %10u, pkey_for_val=%10d\n", j, v, k, pkey_for_db_key, pkey_for_val(v, j)); + } + {printf("."); fflush(stdout);} + r = cursor->c_close(cursor); + CKERR(r); + r = txn->commit(txn, 0); + CKERR(r); + } + printf("\nCheck OK\n"); +} + +static void *expect_poll_void = &expect_poll_void; + +static struct progress_info { + double time; + double progress; +} *progress_infos=NULL; +static int progress_infos_count=0; + +static void test_loader(DB **dbs) +{ + int r; + DB_TXN *txn; + + + // this is the essential part of the upgrade test + check_results(dbs); + + for (int i=0; itxn_begin(env, NULL, &txn, 0); + CKERR(r); + DB_BTREE_STAT64 stats; + r = dbs[i]->stat64(dbs[i], txn, &stats); + CKERR(r); + if (verbose) + printf("n_keys=%" PRIu64 " n_data=%" PRIu64 " dsize=%" PRIu64 " fsize=%" PRIu64 "\n", + stats.bt_nkeys, stats.bt_ndata, stats.bt_dsize, stats.bt_fsize); + assert(stats.bt_nkeys == (u_int64_t)NUM_ROWS); + assert(stats.bt_ndata == (u_int64_t)NUM_ROWS); + assert(stats.bt_dsize == ((u_int64_t)NUM_ROWS) * 2 * sizeof(unsigned int)); + r = txn->commit(txn, 0); + CKERR(r); + } +} + + +char *free_me = NULL; +char *env_dir = ENVDIR; // the default env_dir. +char *tmp_subdir = "tmp.subdir"; + +#define OLDDATADIR "../../../../tokudb.data/" +char *db_v4_dir = OLDDATADIR "env_preload.4.1.1.loader250kd1.cleanshutdown"; + + +static void setup(void) { + int r; + int len = 256; + char syscmd[len]; + char * src_db_dir; + + src_db_dir = db_v4_dir; + + r = snprintf(syscmd, len, "rm -rf %s", env_dir); + assert(rset_tmp_dir(env, tmp_subdir); CKERR(r); + } + r = env->set_default_bt_compare(env, uint_dbt_cmp); CKERR(r); + if ( verbose ) printf("CACHESIZE = %d MB\n", CACHESIZE); + r = env->set_cachesize(env, CACHESIZE / 1024, (CACHESIZE % 1024)*1024*1024, 1); CKERR(r); + if (datadir) { + r = env->set_data_dir(env, datadir); CKERR(r); + } + int envflags = DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_CREATE | DB_PRIVATE; + r = env->open(env, env_dir, envflags, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); + env->set_errfile(env, stderr); + r = env->checkpointing_set_period(env, 60); CKERR(r); + + DBT desc; + dbt_init(&desc, "foo", sizeof("foo")); + char name[MAX_NAME*2]; + + DB **dbs = (DB**)toku_malloc(sizeof(DB*) * NUM_DBS); + assert(dbs != NULL); + int idx[MAX_DBS]; + for(int i=0;iset_descriptor(dbs[i], 1, &desc); CKERR(r); + dbs[i]->app_private = &idx[i]; + snprintf(name, sizeof(name), "db_%04x", i); + r = dbs[i]->open(dbs[i], NULL, name, NULL, DB_BTREE, DB_CREATE, 0666); CKERR(r); + } + + generate_permute_tables(); + + // -------------------------- // + test_loader(dbs); + // -------------------------- // + + for(int i=0;iclose(dbs[i], 0); CKERR(r); + dbs[i] = NULL; + } + if (verbose >= 2) + print_engine_status(env); + r = env->close(env, 0); CKERR(r); + toku_free(dbs); +} + + +// ------------ infrastructure ---------- +static void do_args(int argc, char * const argv[]); + +int test_main(int argc, char * const *argv) { + do_args(argc, argv); + + run_test(); + if (free_me) toku_free(free_me); + + if (progress_infos) { + if (verbose>=2) { + double ratio=progress_infos[progress_infos_count-1].time/progress_infos[progress_infos_count-1].progress; + printf("Progress ratios:\n"); + for (int i=0; i0) { + 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], "-h")==0) { + resultcode=0; + do_usage: + fprintf(stderr, "Usage: -h -d -r [-m ] [-M]\n%s\n", cmd); + fprintf(stderr, " where -d is the number of dictionaries to build (primary & secondary). (Default=%d)\n", NUM_DBS); + fprintf(stderr, " -m use m MB of memory for the cachetable (default is %d MB)\n", CACHESIZE); + fprintf(stderr, " -M use %d MB of memory for the cachetable\n", old_default_cachesize); + fprintf(stderr, " -f print memory footprint information at various points in the load\n"); + exit(resultcode); + } else if (strcmp(argv[0], "-d")==0) { + argc--; argv++; + NUM_DBS = atoi(argv[0]); + if ( NUM_DBS > MAX_DBS ) { + fprintf(stderr, "max value for -d field is %d\n", MAX_DBS); + resultcode=1; + goto do_usage; + } + } else 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], "-f")==0) { + footprint_print = TRUE; + } else if (strcmp(argv[0], "-r")==0) { + argc--; argv++; + NUM_ROWS = atoi(argv[0]); + } else if (strcmp(argv[0], "-m")==0) { + argc--; argv++; + CACHESIZE = atoi(argv[0]); + } else if (strcmp(argv[0], "-M")==0) { + CACHESIZE = old_default_cachesize; + } else { + fprintf(stderr, "Unknown arg: %s\n", argv[0]); + resultcode=1; + goto do_usage; + } + argc--; + argv++; + } +}