/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: #ident "$Id$" #ident "Copyright (c) 2008-2011 Tokutek Inc. All rights reserved." // Test keyrange #include "includes.h" #include "test.h" #include static TOKUTXN const null_txn = 0; static DB * const null_db = 0; static char fname[]= __SRCFILE__ ".ft_handle"; static CACHETABLE ct; static FT_HANDLE t; static void close_ft_and_ct (void) { int r; r = toku_close_ft_handle_nolsn(t, 0); assert(r==0); r = toku_cachetable_close(&ct); assert(r==0); } static void open_ft_and_ct (bool unlink_old) { int r; if (unlink_old) unlink(fname); r = toku_create_cachetable(&ct, 0, ZERO_LSN, NULL_LOGGER); assert(r==0); r = toku_open_ft_handle(fname, 1, &t, 1<<12, 1<<9, TOKU_DEFAULT_COMPRESSION_METHOD, ct, null_txn, toku_builtin_compare_fun); assert(r==0); } static void close_and_reopen (void) { close_ft_and_ct(); open_ft_and_ct(false); } static void reload (uint64_t limit) { // insert keys 1, 3, 5, ... for (uint64_t i=0; i1 partitio in many leaves.) CLOSE_AND_REOPEN_LEAVE_ON_DISK // close the brts, reopen them, but leave the state on disk. }; static void maybe_reopen (enum memory_state ms, uint64_t limit) { switch (ms) { case CLOSE_AND_RELOAD: close_and_reopen(); reload(limit); return; case CLOSE_AND_REOPEN_LEAVE_ON_DISK: close_and_reopen(); return; case LEAVE_IN_MEMORY: return; } assert(0); } static void test_keyrange (enum memory_state ms, uint64_t limit) { open_ft_and_ct(true); // insert keys 1, 3, 5, ... for (uint64_t i=0; i 1) printf("Pkey %llu/%llu %llu %llu %llu\n", (unsigned long long)2*i+1, (unsigned long long)2*limit, (unsigned long long)less, (unsigned long long)equal, (unsigned long long)greater); assert(0 < less + equal + greater); assert(less + equal + greater <= 2 * limit); assert(equal == 0 || equal == 1); // It's an estimate, and the values don't even change monotonically. // And all the leaves are in main memory so it's always present. if (ms!=CLOSE_AND_REOPEN_LEAVE_ON_DISK) { if (equal==1) equal_count++; #if 0 // The first few items are exact for less. if (i<70) { assert(less==i); } // The last few items are exact for greater. if (limit-i<70) { assert(greater<=limit-i-1); } #endif } else { // after reopen, none of the basements are in memory assert(equal == 0); #if 0 if (i<10) { assert(less==0); } if (limit-i<10) { assert(greater==0); } #endif } // Count the number of times that prev_less is 1 less than less. if (prev_less+1 == less) { count_less_adjacent++; } if (prev_greater-1 == greater) { count_greater_adjacent++; } // the best we can do: It's an estimate. At least in the current implementation for this test (which has small rows) // the estimate grows monotonically as the leaf grows. prev_less = less; prev_greater = greater; } if (ms!=CLOSE_AND_REOPEN_LEAVE_ON_DISK) { // If we were doing the in-memory case then most keys are adjacent. assert(count_less_adjacent >= 0.9 * limit); // we expect at least 90% to be right. assert(count_greater_adjacent >= 0.9 * limit); // we expect at least 90% to be right. assert(equal_count >= 0.9 * limit); } } maybe_reopen(ms, limit); // lookup keys 0, 2, 4, ... not in the tree for (uint64_t i=0; i<1+limit; i++) { char key[100]; snprintf(key, 100, "%08llu", (unsigned long long)2*i); DBT k; uint64_t less,equal,greater; int r = toku_ft_keyrange(t, toku_fill_dbt(&k, key, 1+strlen(key)), &less, &equal, &greater); assert(r == 0); if (verbose > 1) printf("Akey %llu/%llu %llu %llu %llu\n", (unsigned long long)2*i, (unsigned long long)2*limit, (unsigned long long)less, (unsigned long long)equal, (unsigned long long)greater); assert(0 < less + equal + greater); assert(less + equal + greater <= 2 * limit); assert(equal == 0); #if 0 // The first few items are exact (looking a key that's not there) if (ms!=CLOSE_AND_REOPEN_LEAVE_ON_DISK) { if (i<70) { assert(less==i); } // The last few items are exact (looking up a key that's not there) if (limit-i<70) { assert(greater<=limit-i); } } else { if (i<10) { assert(less==0); } if (limit-i<10) { assert(greater==0); } } #endif } close_ft_and_ct(); } int test_main (int argc , const char *argv[]) { uint64_t limit = 30000; for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-v") == 0) { verbose++; continue; } if (strcmp(argv[i], "-q") == 0) { if (verbose > 0) verbose--; continue; } if (strcmp(argv[i], "-n") == 0 && i+1 < argc) { limit = atoll(argv[++i]); continue; } } test_keyrange(LEAVE_IN_MEMORY, limit); test_keyrange(CLOSE_AND_REOPEN_LEAVE_ON_DISK, limit); test_keyrange(CLOSE_AND_RELOAD, limit); if (verbose) printf("test ok\n"); return 0; }