/* -*- mode: C; c-basic-offset: 4 -*- */ #ident "Copyright (c) 2007, 2008 Tokutek Inc. All rights reserved." #include "brt.h" #include "key.h" #include "pma.h" #include "brt-internal.h" #include "memory.h" #include "toku_assert.h" #include #include #include #include #include #include #include #include "test.h" static const char fname[]= __FILE__ ".brt"; static TOKUTXN const null_txn = 0; static DB * const null_db = 0; static int test_cursor_debug = 0; static int test_brt_cursor_keycompare(DB *db __attribute__((unused)), const DBT *a, const DBT *b) { return toku_keycompare(a->data, a->size, b->data, b->size); } static void assert_cursor_notfound(BRT brt, int position) { BRT_CURSOR cursor; int r; DBT kbt, vbt; r = toku_brt_cursor(brt, &cursor, 0); assert(r==0); toku_init_dbt(&kbt); kbt.flags = DB_DBT_MALLOC; toku_init_dbt(&vbt); vbt.flags = DB_DBT_MALLOC; r = toku_brt_cursor_get(cursor, &kbt, &vbt, position, null_txn); assert(r == DB_NOTFOUND); r = toku_brt_cursor_close(cursor); assert(r==0); } static void assert_cursor_value(BRT brt, int position, long long value) { BRT_CURSOR cursor; int r; DBT kbt, vbt; long long v; r = toku_brt_cursor(brt, &cursor, 0); assert(r==0); if (test_cursor_debug && verbose) printf("key: "); toku_init_dbt(&kbt); kbt.flags = DB_DBT_MALLOC; toku_init_dbt(&vbt); vbt.flags = DB_DBT_MALLOC; r = toku_brt_cursor_get(cursor, &kbt, &vbt, position, null_txn); assert(r == 0); if (test_cursor_debug && verbose) printf("%s ", (char*)kbt.data); assert(vbt.size == sizeof v); memcpy(&v, vbt.data, vbt.size); assert(v == value); toku_free(kbt.data); toku_free(vbt.data); if (test_cursor_debug && verbose) printf("\n"); r = toku_brt_cursor_close(cursor); assert(r==0); } static void assert_cursor_first_last(BRT brt, long long firstv, long long lastv) { BRT_CURSOR cursor; int r; DBT kbt, vbt; long long v; r = toku_brt_cursor(brt, &cursor, 0); assert(r==0); if (test_cursor_debug && verbose) printf("first key: "); toku_init_dbt(&kbt); kbt.flags = DB_DBT_MALLOC; toku_init_dbt(&vbt); vbt.flags = DB_DBT_MALLOC; r = toku_brt_cursor_get(cursor, &kbt, &vbt, DB_FIRST, null_txn); assert(r == 0); if (test_cursor_debug && verbose) printf("%s ", (char*)kbt.data); assert(vbt.size == sizeof v); memcpy(&v, vbt.data, vbt.size); assert(v == firstv); toku_free(kbt.data); toku_free(vbt.data); if (test_cursor_debug && verbose) printf("\n"); if (test_cursor_debug && verbose) printf("last key:"); toku_init_dbt(&kbt); kbt.flags = DB_DBT_MALLOC; toku_init_dbt(&vbt); vbt.flags = DB_DBT_MALLOC; r = toku_brt_cursor_get(cursor, &kbt, &vbt, DB_LAST, null_txn); assert(r == 0); if (test_cursor_debug)printf("%s ", (char*)kbt.data); assert(vbt.size == sizeof v); memcpy(&v, vbt.data, vbt.size); assert(v == lastv); toku_free(kbt.data); toku_free(vbt.data); if (test_cursor_debug) printf("\n"); r = toku_brt_cursor_close(cursor); assert(r==0); } static void test_brt_cursor_first(int n, DB *db) { CACHETABLE ct; BRT brt; int r; int i; if (verbose) printf("test_brt_cursor_first:%d %p\n", n, db); unlink(fname); r = toku_brt_create_cachetable(&ct, 0, ZERO_LSN, NULL_LOGGER); assert(r==0); r = toku_open_brt(fname, 0, 1, &brt, 1<<12, ct, null_txn, test_brt_cursor_keycompare, db); assert(r==0); /* insert a bunch of kv pairs */ for (i=0; i=0; i--) { char key[8]; long long v; DBT kbt, vbt; snprintf(key, sizeof key, "%4.4d", i); toku_fill_dbt(&kbt, key, strlen(key)+1); v = i; toku_fill_dbt(&vbt, &v, sizeof v); r = toku_brt_insert(brt, &kbt, &vbt, 0); assert(r==0); } if (n == 0) assert_cursor_notfound(brt, DB_FIRST); else assert_cursor_value(brt, DB_FIRST, 0); r = toku_close_brt(brt); assert(r==0); r = toku_cachetable_close(&ct); assert(r==0); } static void assert_cursor_walk(BRT brt, int n) { BRT_CURSOR cursor; int i; int r; r = toku_brt_cursor(brt, &cursor, 0); assert(r==0); if (test_cursor_debug && verbose) printf("key: "); for (i=0; ; i++) { DBT kbt, vbt; long long v; toku_init_dbt(&kbt); kbt.flags = DB_DBT_MALLOC; toku_init_dbt(&vbt); vbt.flags = DB_DBT_MALLOC; r = toku_brt_cursor_get(cursor, &kbt, &vbt, DB_NEXT, null_txn); if (r != 0) break; if (test_cursor_debug && verbose) printf("%s ", (char*)kbt.data); assert(vbt.size == sizeof v); memcpy(&v, vbt.data, vbt.size); assert(v == i); toku_free(kbt.data); toku_free(vbt.data); } if (test_cursor_debug && verbose) printf("\n"); assert(i == n); r = toku_brt_cursor_close(cursor); assert(r==0); } static void test_brt_cursor_walk(int n, DB *db) { CACHETABLE ct; BRT brt; int r; int i; if (verbose) printf("test_brt_cursor_walk:%d %p\n", n, db); unlink(fname); r = toku_brt_create_cachetable(&ct, 0, ZERO_LSN, NULL_LOGGER); assert(r==0); r = toku_open_brt(fname, 0, 1, &brt, 1<<12, ct, null_txn, test_brt_cursor_keycompare, db); assert(r==0); /* insert a bunch of kv pairs */ for (i=0; i= v */ for (i=0; i max_key) /* there is no smallest key if v > the max key */ assert(r == DB_NOTFOUND); else { assert(r == 0); assert(val.size == sizeof vv); memcpy(&vv, val.data, val.size); assert(vv == (((v+9)/10)*10)); toku_free(val.data); } } r = toku_brt_cursor_close(cursor); assert(r==0); r = toku_close_brt(brt); assert(r==0); r = toku_cachetable_close(&ct); assert(r==0); } static void test_brt_cursor_delete(int n, DB *db) { if (verbose) printf("test_brt_cursor_delete:%d %p\n", n, db); int error; CACHETABLE ct; BRT brt; BRT_CURSOR cursor; unlink(fname); error = toku_brt_create_cachetable(&ct, 0, ZERO_LSN, NULL_LOGGER); assert(error == 0); error = toku_open_brt(fname, 0, 1, &brt, 1<<12, ct, null_txn, test_brt_cursor_keycompare, db); assert(error == 0); error = toku_brt_cursor(brt, &cursor, 0); assert(error == 0); DBT key, val; int k, v; int i; /* insert keys 0, 1, 2, .. (n-1) */ for (i=0; i