Browse Source
merge new cachetable tests. addresses #1075
merge new cachetable tests. addresses #1075
git-svn-id: file:///svn/tokudb@5797 c7de825b-a66e-492c-adef-691d508d4ae1pull/56/head
11 changed files with 894 additions and 145 deletions
-
2newbrt/cachetable.c
-
10newbrt/tests/Makefile
-
113newbrt/tests/cachetable-checkpoint-test.c
-
68newbrt/tests/cachetable-count-pinned-test.c
-
47newbrt/tests/cachetable-fd-test.c
-
96newbrt/tests/cachetable-flush-test.c
-
80newbrt/tests/cachetable-put-test.c
-
196newbrt/tests/cachetable-rename-test.c
-
254newbrt/tests/cachetable-test.c
-
103newbrt/tests/cachetable-test2.c
-
70newbrt/tests/cachetable-unpin-test.c
@ -0,0 +1,113 @@ |
|||
#include <stdio.h> |
|||
#include <unistd.h> |
|||
#include <assert.h> |
|||
|
|||
#include "test.h" |
|||
#include "cachetable.h" |
|||
|
|||
const int item_size = 1; |
|||
|
|||
int n_flush, n_write_me, n_keep_me, n_fetch; |
|||
|
|||
void flush(CACHEFILE cf, CACHEKEY key, void *value, long size, BOOL write_me, BOOL keep_me, LSN modified_lsn, BOOL rename_p) { |
|||
cf = cf; modified_lsn = modified_lsn; rename_p = rename_p; |
|||
assert(key == (CACHEKEY)(long)value); |
|||
assert(size == item_size); |
|||
n_flush++; |
|||
if (write_me) n_write_me++; |
|||
if (keep_me) n_keep_me++; |
|||
} |
|||
|
|||
int fetch() { |
|||
n_fetch++; |
|||
return 0; |
|||
} |
|||
|
|||
// put n items into the cachetable, maybe mark them dirty, do a checkpoint, and |
|||
// verify that all of the items have been written and are clean. |
|||
|
|||
void cachetable_checkpoint_test(int n, int dirty) { |
|||
const int test_limit = n; |
|||
int r; |
|||
CACHETABLE ct; |
|||
r = toku_create_cachetable(&ct, test_limit, ZERO_LSN, NULL_LOGGER); assert(r == 0); |
|||
char fname1[] = __FILE__ "test1.dat"; |
|||
unlink(fname1); |
|||
CACHEFILE f1; |
|||
r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, 0777); assert(r == 0); |
|||
|
|||
// insert items into the cachetable. all should be dirty |
|||
int i; |
|||
for (i=0; i<n; i++) { |
|||
u_int32_t hi = toku_cachetable_hash(f1, i); |
|||
r = toku_cachetable_put(f1, i, hi, (void *)(long)i, 1, flush, fetch, 0); |
|||
assert(r == 0); |
|||
|
|||
r = toku_cachetable_unpin(f1, i, hi, dirty, item_size); |
|||
assert(r == 0); |
|||
|
|||
void *v; |
|||
int its_dirty; |
|||
long long its_pin; |
|||
long its_size; |
|||
r = toku_cachetable_get_key_state(ct, i, f1, &v, &its_dirty, &its_pin, &its_size); |
|||
if (r != 0) |
|||
continue; |
|||
assert(its_dirty == CACHETABLE_DIRTY); |
|||
assert(its_pin == 0); |
|||
assert(its_size == item_size); |
|||
} |
|||
|
|||
// the checkpoint should cause n writes, but since n <= the cachetable size, |
|||
// all items should be kept in the cachetable |
|||
n_flush = n_write_me = n_keep_me = n_fetch = 0; |
|||
r = toku_cachetable_checkpoint(ct); |
|||
assert(r == 0); |
|||
assert(n_flush == n && n_write_me == n && n_keep_me == n); |
|||
|
|||
// after the checkpoint, all of the items should be clean |
|||
for (i=0; i<n; i++) { |
|||
u_int32_t hi = toku_cachetable_hash(f1, i); |
|||
void *v; |
|||
r = toku_cachetable_maybe_get_and_pin(f1, i, hi, &v); |
|||
if (r != 0) |
|||
continue; |
|||
r = toku_cachetable_unpin(f1, i, hi, CACHETABLE_CLEAN, item_size); |
|||
assert(r == 0); |
|||
|
|||
int its_dirty; |
|||
long long its_pin; |
|||
long its_size; |
|||
r = toku_cachetable_get_key_state(ct, i, f1, &v, &its_dirty, &its_pin, &its_size); |
|||
if (r != 0) |
|||
continue; |
|||
assert(its_dirty == CACHETABLE_CLEAN); |
|||
assert(its_pin == 0); |
|||
assert(its_size == item_size); |
|||
} |
|||
|
|||
// a subsequent checkpoint should cause n flushes, but no writes since all |
|||
// of the items are clean |
|||
n_flush = n_write_me = n_keep_me = n_fetch = 0; |
|||
r = toku_cachetable_checkpoint(ct); |
|||
assert(r == 0); |
|||
assert(n_flush == n && n_write_me == 0 && n_keep_me == n); |
|||
|
|||
r = toku_cachefile_close(&f1, NULL_LOGGER); assert(r == 0 && f1 == 0); |
|||
r = toku_cachetable_close(&ct); assert(r == 0 && ct == 0); |
|||
} |
|||
|
|||
int main(int argc, const char *argv[]) { |
|||
int i; |
|||
for (i=1; i<argc; i++) { |
|||
if (strcmp(argv[i], "-v") == 0) { |
|||
verbose++; |
|||
continue; |
|||
} |
|||
} |
|||
for (i=0; i<8; i++) { |
|||
cachetable_checkpoint_test(i, CACHETABLE_CLEAN); |
|||
cachetable_checkpoint_test(i, CACHETABLE_DIRTY); |
|||
} |
|||
return 0; |
|||
} |
|||
@ -0,0 +1,68 @@ |
|||
#include <stdio.h> |
|||
#include <unistd.h> |
|||
#include <assert.h> |
|||
|
|||
#include "test.h" |
|||
#include "cachetable.h" |
|||
|
|||
void flush() { |
|||
} |
|||
|
|||
int fetch() { |
|||
return 0; |
|||
} |
|||
|
|||
void cachetable_count_pinned_test(int n) { |
|||
const int test_limit = 2*n; |
|||
int r; |
|||
CACHETABLE ct; |
|||
r = toku_create_cachetable(&ct, test_limit, ZERO_LSN, NULL_LOGGER); assert(r == 0); |
|||
char fname1[] = __FILE__ "test1.dat"; |
|||
unlink(fname1); |
|||
CACHEFILE f1; |
|||
r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, 0777); assert(r == 0); |
|||
|
|||
int i; |
|||
for (i=1; i<=n; i++) { |
|||
u_int32_t hi; |
|||
hi = toku_cachetable_hash(f1, i); |
|||
r = toku_cachetable_put(f1, i, hi, (void *)(long)i, 1, flush, fetch, 0); |
|||
assert(r == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i); |
|||
|
|||
void *v; |
|||
r = toku_cachetable_maybe_get_and_pin(f1, i, hi, &v); |
|||
assert(r == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i); |
|||
|
|||
r = toku_cachetable_unpin(f1, i, hi, CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i); |
|||
} |
|||
for (i=n; i>0; i--) { |
|||
u_int32_t hi; |
|||
hi = toku_cachetable_hash(f1, i); |
|||
r = toku_cachetable_unpin(f1, i, hi, CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
if (i-1) assert(toku_cachetable_assert_all_unpinned(ct)); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i-1); |
|||
} |
|||
assert(toku_cachetable_assert_all_unpinned(ct) == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 1) == 0); |
|||
toku_cachetable_verify(ct); |
|||
|
|||
r = toku_cachefile_close(&f1, NULL_LOGGER); assert(r == 0 && f1 == 0); |
|||
r = toku_cachetable_close(&ct); assert(r == 0 && ct == 0); |
|||
} |
|||
|
|||
int main(int argc, const char *argv[]) { |
|||
int i; |
|||
for (i=1; i<argc; i++) { |
|||
if (strcmp(argv[i], "-v") == 0) { |
|||
verbose++; |
|||
continue; |
|||
} |
|||
} |
|||
cachetable_count_pinned_test(8); |
|||
return 0; |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
#include <stdio.h> |
|||
#include <unistd.h> |
|||
#include <assert.h> |
|||
|
|||
#include "test.h" |
|||
#include "cachetable.h" |
|||
|
|||
void cachetable_fd_test() { |
|||
const int test_limit = 1; |
|||
int r; |
|||
CACHETABLE ct; |
|||
r = toku_create_cachetable(&ct, test_limit, ZERO_LSN, NULL_LOGGER); assert(r == 0); |
|||
char fname1[] = __FILE__ "test1.dat"; |
|||
unlink(fname1); |
|||
CACHEFILE cf; |
|||
r = toku_cachetable_openf(&cf, ct, fname1, O_RDWR|O_CREAT, 0777); assert(r == 0); |
|||
|
|||
int fd1 = toku_cachefile_fd(cf); assert(fd1 >= 0); |
|||
|
|||
// test set to good fd succeeds |
|||
char fname2[] = __FILE__ "test2.data"; |
|||
unlink(fname2); |
|||
int fd2 = open(fname2, O_RDWR + O_CREAT); assert(fd2 >= 0 && fd1 != fd2); |
|||
r = toku_cachefile_set_fd(cf, fd2, fname2); assert(r == 0); |
|||
assert(toku_cachefile_fd(cf) == fd2); |
|||
|
|||
// test set to bogus fd fails |
|||
int fd3 = open("/dev/null", O_RDWR); assert(fd3 >= 0); |
|||
r = close(fd3); assert(r == 0); |
|||
r = toku_cachefile_set_fd(cf, fd3, "/dev/null"); assert(r != 0); |
|||
assert(toku_cachefile_fd(cf) == fd2); |
|||
|
|||
r = toku_cachefile_close(&cf, NULL_LOGGER); assert(r == 0 && cf == 0); |
|||
r = toku_cachetable_close(&ct); assert(r == 0 && ct == 0); |
|||
} |
|||
|
|||
int main(int argc, const char *argv[]) { |
|||
int i; |
|||
for (i=1; i<argc; i++) { |
|||
if (strcmp(argv[i], "-v") == 0) { |
|||
verbose++; |
|||
continue; |
|||
} |
|||
} |
|||
cachetable_fd_test(); |
|||
return 0; |
|||
} |
|||
@ -0,0 +1,96 @@ |
|||
#include <stdio.h> |
|||
#include <unistd.h> |
|||
#include <assert.h> |
|||
|
|||
#include "test.h" |
|||
#include "cachetable.h" |
|||
|
|||
void flush() { |
|||
} |
|||
|
|||
int fetch() { |
|||
return 0; |
|||
} |
|||
|
|||
void test_cachetable_flush(int n) { |
|||
const int test_limit = 2*n; |
|||
int r; |
|||
CACHETABLE ct; |
|||
r = toku_create_cachetable(&ct, test_limit, ZERO_LSN, NULL_LOGGER); assert(r == 0); |
|||
char fname1[] = __FILE__ "test1.dat"; |
|||
unlink(fname1); |
|||
CACHEFILE f1; |
|||
r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, 0777); assert(r == 0); |
|||
|
|||
char fname2[] = __FILE__ "test2.dat"; |
|||
unlink(fname2); |
|||
CACHEFILE f2; |
|||
r = toku_cachetable_openf(&f2, ct, fname2, O_RDWR|O_CREAT, 0777); assert(r == 0); |
|||
|
|||
// insert keys 0..n-1 |
|||
int i; |
|||
for (i=0; i<n; i++) { |
|||
u_int32_t hi; |
|||
hi = toku_cachetable_hash(f1, i); |
|||
r = toku_cachetable_put(f1, i, hi, (void *)(long)i, 1, flush, fetch, 0); |
|||
assert(r == 0); |
|||
r = toku_cachetable_unpin(f1, i, hi, CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
hi = toku_cachetable_hash(f2, i); |
|||
r = toku_cachetable_put(f2, i, hi, (void *)(long)i, 1, flush, fetch, 0); |
|||
assert(r == 0); |
|||
r = toku_cachetable_unpin(f2, i, hi, CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
} |
|||
toku_cachetable_verify(ct); |
|||
|
|||
// verify keys exists |
|||
for (i=0; i<n; i++) { |
|||
u_int32_t hi; |
|||
void *v; |
|||
hi = toku_cachetable_hash(f1, i); |
|||
r = toku_cachetable_maybe_get_and_pin(f1, i, hi, &v); |
|||
assert(r == 0 && v == (void *)(long)i); |
|||
r = toku_cachetable_unpin(f1, i, hi, CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
hi = toku_cachetable_hash(f2, i); |
|||
r = toku_cachetable_maybe_get_and_pin(f2, i, hi, &v); |
|||
assert(r == 0 && v == (void *)(long)i); |
|||
r = toku_cachetable_unpin(f2, i, hi, CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
} |
|||
|
|||
// flush |
|||
r = toku_cachefile_flush(f1); assert(r == 0); |
|||
toku_cachefile_verify(f1); |
|||
|
|||
// verify keys do not exist in f1 but do exist in f2 |
|||
for (i=0; i<n; i++) { |
|||
u_int32_t hi; |
|||
void *v; |
|||
hi = toku_cachetable_hash(f1, i); |
|||
r = toku_cachetable_maybe_get_and_pin(f1, i, hi, &v); |
|||
assert(r != 0); |
|||
hi = toku_cachetable_hash(f2, i); |
|||
r = toku_cachetable_maybe_get_and_pin(f2, i, hi, &v); |
|||
assert(r == 0); |
|||
r = toku_cachetable_unpin(f2, i, hi, CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
} |
|||
|
|||
r = toku_cachefile_close(&f1, NULL_LOGGER); assert(r == 0 && f1 == 0); |
|||
r = toku_cachefile_close(&f2, NULL_LOGGER); assert(r == 0 && f2 == 0); |
|||
r = toku_cachetable_close(&ct); assert(r == 0 && ct == 0); |
|||
} |
|||
|
|||
int main(int argc, const char *argv[]) { |
|||
int i; |
|||
for (i=1; i<argc; i++) { |
|||
if (strcmp(argv[i], "-v") == 0) { |
|||
verbose++; |
|||
continue; |
|||
} |
|||
} |
|||
test_cachetable_flush(8); |
|||
return 0; |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
#include <stdio.h> |
|||
#include <unistd.h> |
|||
#include <assert.h> |
|||
|
|||
#include "test.h" |
|||
#include "cachetable.h" |
|||
|
|||
void flush() { |
|||
} |
|||
|
|||
int fetch() { |
|||
return 0; |
|||
} |
|||
|
|||
void cachetable_put_test(int n) { |
|||
const int test_limit = 2*n; |
|||
int r; |
|||
CACHETABLE ct; |
|||
r = toku_create_cachetable(&ct, test_limit, ZERO_LSN, NULL_LOGGER); assert(r == 0); |
|||
char fname1[] = __FILE__ "test1.dat"; |
|||
unlink(fname1); |
|||
CACHEFILE f1; |
|||
r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, 0777); assert(r == 0); |
|||
|
|||
int i; |
|||
for (i=1; i<=n; i++) { |
|||
u_int32_t hi; |
|||
hi = toku_cachetable_hash(f1, i); |
|||
r = toku_cachetable_put(f1, i, hi, (void *)(long)i, 1, flush, fetch, 0); |
|||
assert(r == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i); |
|||
|
|||
r = toku_cachetable_put(f1, i, hi, (void *)(long)i, 1, flush, fetch, 0); |
|||
assert(r == -1); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i); |
|||
|
|||
// the second put returns an error put increments the pin count, so we have |
|||
// to unpin it here |
|||
r = toku_cachetable_unpin(f1, i, hi, CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i); |
|||
|
|||
void *v; |
|||
r = toku_cachetable_maybe_get_and_pin(f1, i, hi, &v); |
|||
assert(r == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i); |
|||
|
|||
r = toku_cachetable_unpin(f1, i, hi, CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i); |
|||
} |
|||
for (i=n; i>0; i--) { |
|||
u_int32_t hi; |
|||
hi = toku_cachetable_hash(f1, i); |
|||
r = toku_cachetable_unpin(f1, i, hi, CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i-1); |
|||
} |
|||
assert(toku_cachefile_count_pinned(f1, 1) == 0); |
|||
toku_cachetable_verify(ct); |
|||
|
|||
CACHEKEY k = n+1; |
|||
r = toku_cachetable_unpin(f1, k, toku_cachetable_hash(f1, k), CACHETABLE_CLEAN, 1); |
|||
assert(r != 0); |
|||
|
|||
r = toku_cachefile_close(&f1, NULL_LOGGER); assert(r == 0 && f1 == 0); |
|||
r = toku_cachetable_close(&ct); assert(r == 0 && ct == 0); |
|||
} |
|||
|
|||
int main(int argc, const char *argv[]) { |
|||
int i; |
|||
for (i=1; i<argc; i++) { |
|||
if (strcmp(argv[i], "-v") == 0) { |
|||
verbose++; |
|||
continue; |
|||
} |
|||
} |
|||
cachetable_put_test(8); |
|||
return 0; |
|||
} |
|||
@ -0,0 +1,196 @@ |
|||
/* -*- mode: C; c-basic-offset: 4 -*- */ |
|||
#ident "Copyright (c) 2007, 2008 Tokutek Inc. All rights reserved." |
|||
|
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <stdint.h> |
|||
#include <string.h> |
|||
#include <unistd.h> |
|||
#include <malloc.h> |
|||
#include <errno.h> |
|||
#include <pthread.h> |
|||
|
|||
#include "toku_assert.h" |
|||
#include "memory.h" |
|||
#include "cachetable.h" |
|||
#include "test.h" |
|||
|
|||
// this mutex is used by some of the tests to serialize access to some |
|||
// global data, especially between the test thread and the cachetable |
|||
// writeback threads |
|||
|
|||
pthread_mutex_t test_mutex; |
|||
|
|||
static inline void test_mutex_init() { |
|||
int r = pthread_mutex_init(&test_mutex, 0); assert(r == 0); |
|||
} |
|||
|
|||
static inline void test_mutex_destroy() { |
|||
int r = pthread_mutex_destroy(&test_mutex); assert(r == 0); |
|||
} |
|||
|
|||
static inline void test_mutex_lock() { |
|||
int r = pthread_mutex_lock(&test_mutex); assert(r == 0); |
|||
} |
|||
|
|||
static inline void test_mutex_unlock() { |
|||
int r = pthread_mutex_unlock(&test_mutex); assert(r == 0); |
|||
} |
|||
|
|||
enum { KEYLIMIT = 4, TRIALLIMIT=256000 }; |
|||
static CACHEKEY keys[KEYLIMIT]; |
|||
static void* vals[KEYLIMIT]; |
|||
static int n_keys=0; |
|||
|
|||
static void r_flush (CACHEFILE f __attribute__((__unused__)), |
|||
CACHEKEY k, void *value, |
|||
long size __attribute__((__unused__)), |
|||
BOOL write_me __attribute__((__unused__)), |
|||
BOOL keep_me, |
|||
LSN modified_lsn __attribute__((__unused__)), |
|||
BOOL rename_p __attribute__((__unused__))) { |
|||
int i; |
|||
//printf("Flush\n"); |
|||
if (keep_me) return; |
|||
|
|||
test_mutex_lock(); |
|||
for (i=0; i<n_keys; i++) { |
|||
if (keys[i]==k) { |
|||
assert(vals[i]==value); |
|||
if (!keep_me) { |
|||
if (verbose) printf("%s: %d/%d %llx\n", __FUNCTION__, i, n_keys, k); |
|||
keys[i]=keys[n_keys-1]; |
|||
vals[i]=vals[n_keys-1]; |
|||
n_keys--; |
|||
test_mutex_unlock(); |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
fprintf(stderr, "Whoops\n"); |
|||
abort(); |
|||
test_mutex_unlock(); |
|||
} |
|||
|
|||
static int r_fetch (CACHEFILE f __attribute__((__unused__)), |
|||
CACHEKEY key __attribute__((__unused__)), |
|||
u_int32_t fullhash __attribute__((__unused__)), |
|||
void**value __attribute__((__unused__)), |
|||
long *sizep __attribute__((__unused__)), |
|||
void*extraargs __attribute__((__unused__)), |
|||
LSN *modified_lsn __attribute__((__unused__))) { |
|||
// fprintf(stderr, "Whoops, this should never be called"); |
|||
return -42; |
|||
} |
|||
|
|||
static void test_rename (void) { |
|||
CACHETABLE t; |
|||
CACHEFILE f; |
|||
int i; |
|||
int r; |
|||
test_mutex_init(); |
|||
const char fname[] = __FILE__ "rename.dat"; |
|||
r=toku_create_cachetable(&t, KEYLIMIT, ZERO_LSN, NULL_LOGGER); assert(r==0); |
|||
unlink(fname); |
|||
r = toku_cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, 0777); |
|||
assert(r==0); |
|||
for (i=0; i<TRIALLIMIT; i++) { |
|||
int ra = random()%3; |
|||
if (ra<=1) { |
|||
// Insert something |
|||
CACHEKEY nkey = random(); |
|||
long nval = random(); |
|||
if (verbose) printf("n_keys=%d Insert %08llx\n", n_keys, nkey); |
|||
u_int32_t hnkey = toku_cachetable_hash(f, nkey); |
|||
r = toku_cachetable_put(f, nkey, hnkey, |
|||
(void*)nval, 1, |
|||
r_flush, r_fetch, 0); |
|||
assert(r==0); |
|||
test_mutex_lock(); |
|||
while (n_keys >= KEYLIMIT) { |
|||
test_mutex_unlock(); |
|||
pthread_yield(); |
|||
test_mutex_lock(); |
|||
} |
|||
assert(n_keys<KEYLIMIT); |
|||
keys[n_keys] = nkey; |
|||
vals[n_keys] = (void*)nval; |
|||
n_keys++; |
|||
test_mutex_unlock(); |
|||
r = toku_cachetable_unpin(f, nkey, hnkey, CACHETABLE_DIRTY, 1); |
|||
assert(r==0); |
|||
} else if (ra==2 && n_keys>0) { |
|||
// Rename something |
|||
int objnum = random()%n_keys; |
|||
CACHEKEY nkey = random(); |
|||
test_mutex_lock(); |
|||
CACHEKEY okey = keys[objnum]; |
|||
test_mutex_unlock(); |
|||
void *current_value; |
|||
long current_size; |
|||
if (verbose) printf("Rename %llx to %llx\n", okey, nkey); |
|||
r = toku_cachetable_get_and_pin(f, okey, toku_cachetable_hash(f, okey), ¤t_value, ¤t_size, r_flush, r_fetch, 0); |
|||
if (r == -42) continue; |
|||
assert(r==0); |
|||
r = toku_cachetable_rename(f, okey, nkey); |
|||
assert(r==0); |
|||
test_mutex_lock(); |
|||
// assert(objnum < n_keys && keys[objnum] == okey); |
|||
// get_and_pin may reorganize the keys[], so we need to find it again |
|||
int j; |
|||
for (j=0; j < n_keys; j++) |
|||
if (keys[j] == okey) |
|||
break; |
|||
assert(j < n_keys); |
|||
keys[j]=nkey; |
|||
test_mutex_unlock(); |
|||
r = toku_cachetable_unpin(f, nkey, toku_cachetable_hash(f, nkey), CACHETABLE_DIRTY, 1); |
|||
} |
|||
} |
|||
|
|||
// test rename fails if old key does not exist in the cachetable |
|||
CACHEKEY okey, nkey; |
|||
while (1) { |
|||
okey = random(); |
|||
void *v; |
|||
r = toku_cachetable_maybe_get_and_pin(f, okey, toku_cachetable_hash(f, okey), &v); |
|||
if (r != 0) |
|||
break; |
|||
r = toku_cachetable_unpin(f, okey, toku_cachetable_hash(f, okey), CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
} |
|||
nkey = random(); |
|||
r = toku_cachetable_rename(f, okey, nkey); |
|||
assert(r != 0); |
|||
|
|||
r = toku_cachefile_close(&f, 0); |
|||
assert(r == 0); |
|||
r = toku_cachetable_close(&t); |
|||
assert(r == 0); |
|||
test_mutex_destroy(); |
|||
assert(n_keys == 0); |
|||
} |
|||
|
|||
int main (int argc, const char *argv[]) { |
|||
// defaults |
|||
int do_malloc_fail = 0; |
|||
|
|||
// parse args |
|||
int i; |
|||
for (i=1; i<argc; i++) { |
|||
const char *arg = argv[i]; |
|||
if (strcmp(arg, "-v") == 0) { |
|||
verbose++; |
|||
continue; |
|||
} |
|||
if (strcmp(arg, "-malloc-fail") == 0) { |
|||
do_malloc_fail = 1; |
|||
continue; |
|||
} |
|||
} |
|||
|
|||
// run tests |
|||
for (i=0; i<1; i++) |
|||
test_rename(); |
|||
return 0; |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
#include <stdio.h> |
|||
#include <unistd.h> |
|||
#include <assert.h> |
|||
|
|||
#include "test.h" |
|||
#include "cachetable.h" |
|||
|
|||
void flush() { |
|||
} |
|||
|
|||
int fetch() { |
|||
return 0; |
|||
} |
|||
|
|||
void cachetable_unpin_test(int n) { |
|||
const int test_limit = 2*n; |
|||
int r; |
|||
CACHETABLE ct; |
|||
r = toku_create_cachetable(&ct, test_limit, ZERO_LSN, NULL_LOGGER); assert(r == 0); |
|||
char fname1[] = __FILE__ "test1.dat"; |
|||
unlink(fname1); |
|||
CACHEFILE f1; |
|||
r = toku_cachetable_openf(&f1, ct, fname1, O_RDWR|O_CREAT, 0777); assert(r == 0); |
|||
|
|||
int i; |
|||
for (i=1; i<=n; i++) { |
|||
u_int32_t hi; |
|||
hi = toku_cachetable_hash(f1, i); |
|||
r = toku_cachetable_put(f1, i, hi, (void *)(long)i, 1, flush, fetch, 0); |
|||
assert(r == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i); |
|||
|
|||
void *v; |
|||
r = toku_cachetable_maybe_get_and_pin(f1, i, hi, &v); |
|||
assert(r == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i); |
|||
|
|||
r = toku_cachetable_unpin(f1, i, hi, CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i); |
|||
} |
|||
for (i=n; i>0; i--) { |
|||
u_int32_t hi; |
|||
hi = toku_cachetable_hash(f1, i); |
|||
r = toku_cachetable_unpin(f1, i, hi, CACHETABLE_CLEAN, 1); |
|||
assert(r == 0); |
|||
assert(toku_cachefile_count_pinned(f1, 0) == i-1); |
|||
} |
|||
assert(toku_cachefile_count_pinned(f1, 1) == 0); |
|||
toku_cachetable_verify(ct); |
|||
|
|||
CACHEKEY k = n+1; |
|||
r = toku_cachetable_unpin(f1, k, toku_cachetable_hash(f1, k), CACHETABLE_CLEAN, 1); |
|||
assert(r != 0); |
|||
|
|||
r = toku_cachefile_close(&f1, NULL_LOGGER); assert(r == 0 && f1 == 0); |
|||
r = toku_cachetable_close(&ct); assert(r == 0 && ct == 0); |
|||
} |
|||
|
|||
int main(int argc, const char *argv[]) { |
|||
int i; |
|||
for (i=1; i<argc; i++) { |
|||
if (strcmp(argv[i], "-v") == 0) { |
|||
verbose++; |
|||
continue; |
|||
} |
|||
} |
|||
cachetable_unpin_test(8); |
|||
return 0; |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue