2007-11-14 17:58:38 +00:00
|
|
|
/* -*- mode: C; c-basic-offset: 4 -*- */
|
2013-04-16 23:59:44 -04:00
|
|
|
#ident "$Id$"
|
2008-01-24 15:10:32 +00:00
|
|
|
#ident "Copyright (c) 2007, 2008 Tokutek Inc. All rights reserved."
|
2007-11-14 17:58:38 +00:00
|
|
|
|
2013-04-16 23:57:20 -04:00
|
|
|
#include "includes.h"
|
2007-12-22 23:12:40 +00:00
|
|
|
#include "test.h"
|
2007-09-21 17:55:49 +00:00
|
|
|
|
2013-04-16 23:57:35 -04:00
|
|
|
// 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
|
|
|
|
|
|
|
|
toku_pthread_mutex_t test_mutex;
|
|
|
|
|
2013-04-16 23:58:00 -04:00
|
|
|
static inline void test_mutex_init(void) {
|
2013-04-16 23:57:35 -04:00
|
|
|
int r = toku_pthread_mutex_init(&test_mutex, 0); assert(r == 0);
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:58:00 -04:00
|
|
|
static inline void test_mutex_destroy(void) {
|
2013-04-16 23:57:35 -04:00
|
|
|
int r = toku_pthread_mutex_destroy(&test_mutex); assert(r == 0);
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:58:00 -04:00
|
|
|
static inline void test_mutex_lock(void) {
|
2013-04-16 23:57:35 -04:00
|
|
|
int r = toku_pthread_mutex_lock(&test_mutex); assert(r == 0);
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:58:00 -04:00
|
|
|
static inline void test_mutex_unlock(void) {
|
2013-04-16 23:57:35 -04:00
|
|
|
int r = toku_pthread_mutex_unlock(&test_mutex); assert(r == 0);
|
|
|
|
}
|
|
|
|
|
2013-04-17 00:00:02 -04:00
|
|
|
static void *my_malloc_always_fails(size_t n UU()) {
|
|
|
|
errno = ENOMEM;
|
|
|
|
return NULL;
|
2008-08-22 17:50:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// verify that cachetable creation and close works
|
|
|
|
|
2013-04-16 23:57:20 -04:00
|
|
|
static void
|
|
|
|
test_cachetable_create(void) {
|
2013-04-17 00:00:02 -04:00
|
|
|
CACHETABLE ct = NULL;
|
2008-08-22 17:50:05 +00:00
|
|
|
int r;
|
|
|
|
r = toku_create_cachetable(&ct, 0, ZERO_LSN, NULL_LOGGER);
|
|
|
|
assert(r == 0);
|
|
|
|
r = toku_cachetable_close(&ct);
|
|
|
|
assert(r == 0 && ct == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// verify that cachetable create with no memory returns ENOMEM
|
2013-04-16 23:57:20 -04:00
|
|
|
static void
|
|
|
|
test_cachetable_create_no_memory (void) {
|
2013-04-17 00:00:02 -04:00
|
|
|
toku_set_func_malloc(my_malloc_always_fails);
|
|
|
|
CACHETABLE ct = NULL;
|
2008-08-22 17:50:05 +00:00
|
|
|
int r;
|
|
|
|
r = toku_create_cachetable(&ct, 0, ZERO_LSN, NULL_LOGGER);
|
|
|
|
assert(r == ENOMEM);
|
2013-04-17 00:00:02 -04:00
|
|
|
toku_set_func_malloc(NULL);
|
2008-08-22 17:50:05 +00:00
|
|
|
}
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static const int test_object_size = 1;
|
2007-10-19 14:07:41 +00:00
|
|
|
|
2007-07-13 19:37:47 +00:00
|
|
|
struct item {
|
|
|
|
CACHEKEY key;
|
|
|
|
char *something;
|
|
|
|
};
|
|
|
|
|
2008-08-22 17:50:05 +00:00
|
|
|
static volatile int expect_n_flushes=0;
|
|
|
|
static volatile CACHEKEY flushes[100];
|
2007-07-13 19:37:47 +00:00
|
|
|
|
2013-04-16 23:57:35 -04:00
|
|
|
static void expect_init(void) {
|
|
|
|
test_mutex_lock();
|
|
|
|
expect_n_flushes = 0;
|
|
|
|
test_mutex_unlock();
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:18 -04:00
|
|
|
static void expect1(int64_t blocknum_n) {
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_lock();
|
2007-07-13 19:37:47 +00:00
|
|
|
expect_n_flushes=1;
|
2013-04-16 23:57:18 -04:00
|
|
|
flushes[0].b=blocknum_n;
|
|
|
|
//if (verbose) printf("%s:%d %lld\n", __FUNCTION__, 0, key.b);
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_unlock();
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
2013-04-16 23:57:18 -04:00
|
|
|
static void expectN(int64_t blocknum_n) {
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_lock();
|
2013-04-16 23:57:18 -04:00
|
|
|
//if (verbose) printf("%s:%d %lld\n", __FUNCTION__, expect_n_flushes, key);
|
|
|
|
flushes[expect_n_flushes++].b=blocknum_n;
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_unlock();
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static CACHEFILE expect_f;
|
2007-07-13 19:37:47 +00:00
|
|
|
|
2013-04-16 23:57:18 -04:00
|
|
|
static void flush (CACHEFILE f,
|
2013-04-16 23:59:02 -04:00
|
|
|
int UU(fd),
|
2013-04-16 23:57:18 -04:00
|
|
|
CACHEKEY key,
|
|
|
|
void*value,
|
2013-04-17 00:00:13 -04:00
|
|
|
void** UU(dd),
|
2013-04-16 23:57:18 -04:00
|
|
|
void *extra __attribute__((__unused__)),
|
2013-04-16 23:59:54 -04:00
|
|
|
PAIR_ATTR size __attribute__((__unused__)),
|
|
|
|
PAIR_ATTR* new_size __attribute__((__unused__)),
|
2013-04-16 23:57:18 -04:00
|
|
|
BOOL write_me __attribute__((__unused__)),
|
|
|
|
BOOL keep_me __attribute__((__unused__)),
|
2013-04-17 00:00:13 -04:00
|
|
|
BOOL for_checkpoint __attribute__((__unused__)),
|
|
|
|
BOOL UU(is_clone)
|
|
|
|
) {
|
2007-07-13 19:37:47 +00:00
|
|
|
struct item *it = value;
|
|
|
|
int i;
|
|
|
|
|
2008-08-22 17:50:05 +00:00
|
|
|
if (keep_me) return;
|
|
|
|
|
2013-04-16 23:57:18 -04:00
|
|
|
if (verbose) printf("Flushing %" PRId64 " (it=>key=%" PRId64 ")\n", key.b, it->key.b);
|
2007-07-13 19:37:47 +00:00
|
|
|
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_lock();
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(expect_f==f);
|
|
|
|
assert(strcmp(it->something,"something")==0);
|
2013-04-16 23:57:18 -04:00
|
|
|
assert(it->key.b==key.b);
|
2007-07-13 19:37:47 +00:00
|
|
|
|
|
|
|
/* Verify that we expected the flush. */
|
|
|
|
for (i=0; i<expect_n_flushes; i++) {
|
2013-04-16 23:57:18 -04:00
|
|
|
if (key.b==flushes[i].b) {
|
2007-07-13 19:37:47 +00:00
|
|
|
flushes[i] = flushes[expect_n_flushes-1];
|
|
|
|
expect_n_flushes--;
|
|
|
|
goto found_flush;
|
|
|
|
}
|
|
|
|
}
|
2013-04-16 23:57:18 -04:00
|
|
|
fprintf(stderr, "%" PRId64 " was flushed, but I didn't expect it\n", key.b);
|
2007-07-13 19:37:47 +00:00
|
|
|
abort();
|
|
|
|
found_flush:
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_unlock();
|
2007-07-20 18:00:14 +00:00
|
|
|
toku_free(value);
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:18 -04:00
|
|
|
static struct item *make_item (u_int64_t key) {
|
2007-07-13 19:37:47 +00:00
|
|
|
struct item *MALLOC(it);
|
2013-04-16 23:57:18 -04:00
|
|
|
it->key.b=key;
|
2007-07-13 19:37:47 +00:00
|
|
|
it->something="something";
|
|
|
|
return it;
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:18 -04:00
|
|
|
static CACHEKEY did_fetch={-1};
|
2013-04-17 00:00:13 -04:00
|
|
|
static int fetch (CACHEFILE f, int UU(fd), CACHEKEY key, u_int32_t fullhash __attribute__((__unused__)), void**value, void** UU(dd), PAIR_ATTR *sizep __attribute__((__unused__)), int *dirtyp, void*extraargs) {
|
2013-04-16 23:57:18 -04:00
|
|
|
if (verbose) printf("Fetch %" PRId64 "\n", key.b);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert (expect_f==f);
|
|
|
|
assert((long)extraargs==23);
|
2013-04-16 23:57:18 -04:00
|
|
|
*value = make_item(key.b);
|
2013-04-16 23:59:54 -04:00
|
|
|
*sizep = make_pair_attr(test_object_size);
|
2013-04-16 23:59:25 -04:00
|
|
|
*dirtyp = 0;
|
2007-07-13 19:37:47 +00:00
|
|
|
did_fetch=key;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:41 -04:00
|
|
|
static void maybe_flush(CACHETABLE t) {
|
|
|
|
toku_cachetable_maybe_flush_some(t);
|
|
|
|
}
|
|
|
|
|
2008-08-22 17:50:05 +00:00
|
|
|
// verify that a sequence of cachetable operations causes a particular sequence of
|
|
|
|
// callbacks
|
2007-07-13 19:37:47 +00:00
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static void test0 (void) {
|
2007-07-13 19:37:47 +00:00
|
|
|
void* t3=(void*)23;
|
|
|
|
CACHETABLE t;
|
|
|
|
CACHEFILE f;
|
|
|
|
int r;
|
2008-05-04 16:56:15 +00:00
|
|
|
char fname[] = __FILE__ "test.dat";
|
2013-04-16 23:57:35 -04:00
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_create_cachetable(&t, 5, ZERO_LSN, NULL_LOGGER);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:57:47 -04:00
|
|
|
unlink(fname);
|
2013-04-16 23:59:03 -04:00
|
|
|
r = toku_cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2008-08-26 14:07:27 +00:00
|
|
|
|
|
|
|
TOKULOGGER logger = toku_cachefile_logger(f);
|
|
|
|
assert(logger == NULL_LOGGER);
|
|
|
|
|
2007-07-13 19:37:47 +00:00
|
|
|
expect_f = f;
|
|
|
|
|
|
|
|
expect_n_flushes=0;
|
2013-04-16 23:57:18 -04:00
|
|
|
u_int32_t h1 = toku_cachetable_hash(f, make_blocknum(1));
|
|
|
|
u_int32_t h2 = toku_cachetable_hash(f, make_blocknum(2));
|
|
|
|
u_int32_t h3 = toku_cachetable_hash(f, make_blocknum(3));
|
|
|
|
u_int32_t h4 = toku_cachetable_hash(f, make_blocknum(4));
|
|
|
|
u_int32_t h5 = toku_cachetable_hash(f, make_blocknum(5));
|
|
|
|
u_int32_t h6 = toku_cachetable_hash(f, make_blocknum(6));
|
|
|
|
u_int32_t h7 = toku_cachetable_hash(f, make_blocknum(7));
|
2013-04-17 00:00:09 -04:00
|
|
|
CACHETABLE_WRITE_CALLBACK wc = def_write_callback(t3);
|
|
|
|
wc.flush_callback = flush;
|
|
|
|
r=toku_cachetable_put(f, make_blocknum(1), h1, make_item(1), make_pair_attr(test_object_size), wc); /* 1P */ /* this is the lru list. 1 is pinned. */
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(expect_n_flushes==0);
|
|
|
|
|
2013-04-16 23:57:35 -04:00
|
|
|
expect_init();
|
2013-04-17 00:00:09 -04:00
|
|
|
r=toku_cachetable_put(f, make_blocknum(2), h2, make_item(2), make_pair_attr(test_object_size), wc);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:59:54 -04:00
|
|
|
r=toku_cachetable_unpin(f, make_blocknum(2), h2, CACHETABLE_DIRTY, make_pair_attr(1)); /* 2U 1P */
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(expect_n_flushes==0);
|
|
|
|
|
2013-04-16 23:57:35 -04:00
|
|
|
expect_init();
|
2013-04-17 00:00:09 -04:00
|
|
|
r=toku_cachetable_put(f, make_blocknum(3), h3, make_item(3), make_pair_attr(test_object_size), wc);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(expect_n_flushes==0); /* 3P 2U 1P */ /* 3 is most recently used (pinned), 2 is next (unpinned), 1 is least recent (pinned) */
|
|
|
|
|
2013-04-16 23:57:35 -04:00
|
|
|
expect_init();
|
2013-04-17 00:00:09 -04:00
|
|
|
r=toku_cachetable_put(f, make_blocknum(4), h4, make_item(4), make_pair_attr(test_object_size), wc);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(expect_n_flushes==0); /* 4P 3P 2U 1P */
|
|
|
|
|
2013-04-16 23:57:35 -04:00
|
|
|
expect_init();
|
2013-04-17 00:00:09 -04:00
|
|
|
r=toku_cachetable_put(f, make_blocknum(5), h5, make_item(5), make_pair_attr(test_object_size), wc);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:59:54 -04:00
|
|
|
r=toku_cachetable_unpin(f, make_blocknum(5), h5, CACHETABLE_DIRTY, make_pair_attr(test_object_size));
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:59:54 -04:00
|
|
|
r=toku_cachetable_unpin(f, make_blocknum(3), h3, CACHETABLE_DIRTY, make_pair_attr(test_object_size));
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(expect_n_flushes==0); /* 5U 4P 3U 2U 1P */
|
|
|
|
|
|
|
|
expect1(2); /* 2 is the oldest unpinned item. */
|
2013-04-17 00:00:09 -04:00
|
|
|
r=toku_cachetable_put(f, make_blocknum(6), h6, make_item(6), make_pair_attr(test_object_size), wc); /* 6P 5U 4P 3U 1P */
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_lock();
|
|
|
|
while (expect_n_flushes != 0) {
|
2013-04-16 23:57:41 -04:00
|
|
|
test_mutex_unlock(); toku_pthread_yield(); maybe_flush(t); test_mutex_lock();
|
2013-04-16 23:57:35 -04:00
|
|
|
}
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(expect_n_flushes==0);
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_unlock();
|
2007-07-13 19:37:47 +00:00
|
|
|
|
|
|
|
expect1(3);
|
2013-04-17 00:00:09 -04:00
|
|
|
r=toku_cachetable_put(f, make_blocknum(7), h7, make_item(7), make_pair_attr(test_object_size), wc);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_lock();
|
|
|
|
while (expect_n_flushes != 0) {
|
2013-04-16 23:57:41 -04:00
|
|
|
test_mutex_unlock(); toku_pthread_yield(); maybe_flush(t); test_mutex_lock();
|
2013-04-16 23:57:35 -04:00
|
|
|
}
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(expect_n_flushes==0);
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_unlock();
|
2013-04-16 23:59:54 -04:00
|
|
|
r=toku_cachetable_unpin(f, make_blocknum(7), h7, CACHETABLE_DIRTY, make_pair_attr(test_object_size)); /* 7U 6P 5U 4P 1P */
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
|
|
|
|
{
|
|
|
|
void *item_v=0;
|
2013-04-16 23:57:35 -04:00
|
|
|
expect_init();
|
2013-04-17 00:00:13 -04:00
|
|
|
r=toku_cachetable_get_and_pin(f, make_blocknum(5), toku_cachetable_hash(f, make_blocknum(5)), &item_v, NULL, wc, fetch, def_pf_req_callback, def_pf_callback, TRUE, t3); /* 5P 7U 6P 4P 1P */
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:57:18 -04:00
|
|
|
assert(((struct item *)item_v)->key.b==5);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(strcmp(((struct item *)item_v)->something,"something")==0);
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_lock();
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(expect_n_flushes==0);
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_unlock();
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
void *item_v=0;
|
2013-04-16 23:59:54 -04:00
|
|
|
r=toku_cachetable_unpin(f, make_blocknum(4), h4, CACHETABLE_DIRTY, make_pair_attr(test_object_size));
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
expect1(4);
|
2013-04-16 23:57:18 -04:00
|
|
|
did_fetch=make_blocknum(-1);
|
2013-04-17 00:00:09 -04:00
|
|
|
CACHETABLE_WRITE_CALLBACK wc2 = def_write_callback(t3);
|
|
|
|
wc2.flush_callback = flush;
|
2013-04-17 00:00:13 -04:00
|
|
|
r=toku_cachetable_get_and_pin(f, make_blocknum(2), toku_cachetable_hash(f, make_blocknum(2)), &item_v, NULL, wc2, fetch, def_pf_req_callback, def_pf_callback, TRUE, t3); /* 2p 5P 7U 6P 1P */
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:57:18 -04:00
|
|
|
assert(did_fetch.b==2); /* Expect that 2 is fetched in. */
|
|
|
|
assert(((struct item *)item_v)->key.b==2);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(strcmp(((struct item *)item_v)->something,"something")==0);
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_lock();
|
|
|
|
while (expect_n_flushes != 0) {
|
2013-04-16 23:57:41 -04:00
|
|
|
test_mutex_unlock(); toku_pthread_yield(); maybe_flush(t); test_mutex_lock();
|
2013-04-16 23:57:35 -04:00
|
|
|
}
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(expect_n_flushes==0);
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_unlock();
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:59:54 -04:00
|
|
|
r=toku_cachetable_unpin(f, make_blocknum(2), h2, CACHETABLE_DIRTY, make_pair_attr(test_object_size));
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:59:54 -04:00
|
|
|
r=toku_cachetable_unpin(f, make_blocknum(5), h5, CACHETABLE_DIRTY, make_pair_attr(test_object_size));
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:59:54 -04:00
|
|
|
r=toku_cachetable_unpin(f, make_blocknum(6), h6, CACHETABLE_DIRTY, make_pair_attr(test_object_size));
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:59:54 -04:00
|
|
|
r=toku_cachetable_unpin(f, make_blocknum(1), h1, CACHETABLE_DIRTY, make_pair_attr(test_object_size));
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_assert_all_unpinned(t);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
|
2007-12-22 23:12:40 +00:00
|
|
|
if (verbose) printf("Closing\n");
|
2007-07-13 19:37:47 +00:00
|
|
|
expect1(2);
|
|
|
|
expectN(5);
|
|
|
|
expectN(7);
|
|
|
|
expectN(6);
|
|
|
|
expectN(1);
|
2013-04-16 23:58:06 -04:00
|
|
|
r=toku_cachefile_close(&f, 0, FALSE, ZERO_LSN);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_close(&t);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(expect_n_flushes==0);
|
2008-08-22 17:50:05 +00:00
|
|
|
expect_f = 0;
|
2013-04-16 23:59:22 -04:00
|
|
|
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:59:02 -04:00
|
|
|
static void flush_n (CACHEFILE f __attribute__((__unused__)), int UU(fd), CACHEKEY key __attribute__((__unused__)),
|
2013-04-16 23:57:18 -04:00
|
|
|
void *value,
|
2013-04-17 00:00:13 -04:00
|
|
|
void** UU(dd),
|
2013-04-16 23:57:18 -04:00
|
|
|
void *extra __attribute__((__unused__)),
|
2013-04-16 23:59:54 -04:00
|
|
|
PAIR_ATTR size __attribute__((__unused__)),
|
|
|
|
PAIR_ATTR* new_size __attribute__((__unused__)),
|
2007-11-14 17:58:38 +00:00
|
|
|
BOOL write_me __attribute__((__unused__)), BOOL keep_me __attribute__((__unused__)),
|
2013-04-17 00:00:13 -04:00
|
|
|
BOOL for_checkpoint __attribute__ ((__unused__)),
|
|
|
|
BOOL UU(is_clone)
|
|
|
|
) {
|
2007-07-13 19:37:47 +00:00
|
|
|
int *v = value;
|
|
|
|
assert(*v==0);
|
|
|
|
}
|
2013-04-16 23:59:02 -04:00
|
|
|
static int fetch_n (CACHEFILE f __attribute__((__unused__)), int UU(fd), CACHEKEY key __attribute__((__unused__)),
|
2008-06-17 17:05:19 +00:00
|
|
|
u_int32_t fullhash __attribute__((__unused__)),
|
2013-04-17 00:00:13 -04:00
|
|
|
void**value,
|
|
|
|
void** UU(dd),
|
|
|
|
PAIR_ATTR *sizep __attribute__((__unused__)),
|
2013-04-16 23:59:25 -04:00
|
|
|
int * dirtyp, void*extraargs) {
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((long)extraargs==42);
|
|
|
|
*value=0;
|
2013-04-16 23:59:25 -04:00
|
|
|
*dirtyp = 0;
|
2013-04-16 23:59:54 -04:00
|
|
|
*sizep = make_pair_attr(0);
|
2007-07-13 19:37:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static void test_nested_pin (void) {
|
2007-07-13 19:37:47 +00:00
|
|
|
void *f2=(void*)42;
|
|
|
|
CACHETABLE t;
|
|
|
|
CACHEFILE f;
|
|
|
|
int i0, i1;
|
|
|
|
int r;
|
2008-04-07 20:32:10 +00:00
|
|
|
void *vv,*vv2;
|
2008-05-04 16:56:15 +00:00
|
|
|
char fname[] = __FILE__ "test_ct.dat";
|
2013-04-17 00:00:01 -04:00
|
|
|
if (verbose) printf("creating cachetable\n");
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_create_cachetable(&t, 1, ZERO_LSN, NULL_LOGGER);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:57:47 -04:00
|
|
|
unlink(fname);
|
2013-04-16 23:59:03 -04:00
|
|
|
r = toku_cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
expect_f = f;
|
|
|
|
|
|
|
|
i0=0; i1=0;
|
2013-04-16 23:57:18 -04:00
|
|
|
u_int32_t f1hash = toku_cachetable_hash(f, make_blocknum(1));
|
2013-04-17 00:00:09 -04:00
|
|
|
CACHETABLE_WRITE_CALLBACK wc = def_write_callback(f2);
|
|
|
|
wc.flush_callback = flush_n;
|
|
|
|
r = toku_cachetable_put(f, make_blocknum(1), f1hash, &i0, make_pair_attr(1), wc);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f, make_blocknum(1), f1hash, CACHETABLE_CLEAN, make_pair_attr(test_object_size));
|
2013-04-17 00:00:13 -04:00
|
|
|
r = toku_cachetable_get_and_pin(f, make_blocknum(1), f1hash, &vv, NULL, wc, fetch_n, def_pf_req_callback, def_pf_callback, TRUE, f2);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(vv==&i0);
|
|
|
|
assert(i0==0);
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f, make_blocknum(1), f1hash, CACHETABLE_CLEAN, make_pair_attr(test_object_size));
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:57:18 -04:00
|
|
|
r = toku_cachetable_maybe_get_and_pin(f, make_blocknum(1), f1hash, &vv2);
|
2008-04-07 20:32:10 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(vv2==vv);
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f, make_blocknum(1), f1hash, CACHETABLE_CLEAN, make_pair_attr(test_object_size));
|
2008-08-22 17:50:05 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:57:18 -04:00
|
|
|
u_int32_t f2hash = toku_cachetable_hash(f, make_blocknum(2));
|
2013-04-17 00:00:09 -04:00
|
|
|
r = toku_cachetable_put(f, make_blocknum(2), f2hash, &i1, make_pair_attr(test_object_size), wc);
|
2008-04-07 20:32:10 +00:00
|
|
|
assert(r==0); // The other one is pinned, but now the cachetable fails gracefully: It allows the pin to happen
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f, make_blocknum(2), f2hash, CACHETABLE_CLEAN, make_pair_attr(test_object_size));
|
2008-08-22 17:50:05 +00:00
|
|
|
assert(r==0);
|
2013-04-16 23:57:28 -04:00
|
|
|
// toku_os_usleep(1*1000000);
|
2013-04-16 23:58:06 -04:00
|
|
|
r = toku_cachefile_close(&f, 0, FALSE, ZERO_LSN); assert(r==0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_close(&t); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static void null_flush (CACHEFILE cf __attribute__((__unused__)),
|
2013-04-16 23:59:02 -04:00
|
|
|
int UU(fd),
|
2008-08-22 17:50:05 +00:00
|
|
|
CACHEKEY k __attribute__((__unused__)),
|
|
|
|
void *v __attribute__((__unused__)),
|
2013-04-17 00:00:13 -04:00
|
|
|
void** UU(dd),
|
2013-04-16 23:57:18 -04:00
|
|
|
void *extra __attribute__((__unused__)),
|
2013-04-16 23:59:54 -04:00
|
|
|
PAIR_ATTR size __attribute__((__unused__)),
|
|
|
|
PAIR_ATTR* new_size __attribute__((__unused__)),
|
2008-08-22 17:50:05 +00:00
|
|
|
BOOL write_me __attribute__((__unused__)),
|
|
|
|
BOOL keep_me __attribute__((__unused__)),
|
2013-04-17 00:00:13 -04:00
|
|
|
BOOL for_checkpoint __attribute__((__unused__)),
|
|
|
|
BOOL UU(is_clone)
|
|
|
|
) {
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
2008-08-22 17:50:05 +00:00
|
|
|
|
2013-04-17 00:00:13 -04:00
|
|
|
static int add123_fetch (CACHEFILE cf, int UU(fd), CACHEKEY key, u_int32_t fullhash, void **value,
|
|
|
|
void** UU(dd),
|
|
|
|
PAIR_ATTR *sizep __attribute__((__unused__)), int * dirtyp, void*extraargs) {
|
2008-06-17 17:05:19 +00:00
|
|
|
assert(fullhash==toku_cachetable_hash(cf,key));
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((long)extraargs==123);
|
2013-04-16 23:57:18 -04:00
|
|
|
*value = (void*)((unsigned long)key.b+123L);
|
2013-04-16 23:59:25 -04:00
|
|
|
*dirtyp = 0;
|
2013-04-16 23:59:54 -04:00
|
|
|
*sizep = make_pair_attr(0);
|
2007-07-13 19:37:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2008-08-22 17:50:05 +00:00
|
|
|
|
2013-04-17 00:00:13 -04:00
|
|
|
static int add222_fetch (CACHEFILE cf, int UU(fd), CACHEKEY key, u_int32_t fullhash, void **value,
|
|
|
|
void** UU(dd),
|
|
|
|
PAIR_ATTR *sizep __attribute__((__unused__)), int * dirtyp, void*extraargs) {
|
2008-06-17 17:05:19 +00:00
|
|
|
assert(fullhash==toku_cachetable_hash(cf,key));
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((long)extraargs==222);
|
2013-04-16 23:57:18 -04:00
|
|
|
*value = (void*)((unsigned long)key.b+222L);
|
2013-04-16 23:59:25 -04:00
|
|
|
*dirtyp = 0;
|
2013-04-16 23:59:54 -04:00
|
|
|
*sizep = make_pair_attr(0);
|
2007-07-13 19:37:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:58:59 -04:00
|
|
|
#if !TOKU_WINDOWS
|
2013-04-16 23:57:27 -04:00
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static void test_multi_filehandles (void) {
|
2007-07-13 19:37:47 +00:00
|
|
|
CACHETABLE t;
|
|
|
|
CACHEFILE f1,f2,f3;
|
2008-05-04 16:56:15 +00:00
|
|
|
char fname1[]= __FILE__ "test_ct.dat";
|
|
|
|
char fname2[]= __FILE__ "test2_ct.dat";
|
|
|
|
char fname3[]= __FILE__ "test3_ct.dat";
|
2007-07-13 19:37:47 +00:00
|
|
|
int r;
|
|
|
|
void *v;
|
2013-04-16 23:57:47 -04:00
|
|
|
unlink(fname1);
|
|
|
|
unlink(fname2);
|
2007-07-13 19:37:47 +00:00
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_create_cachetable(&t, 4, ZERO_LSN, NULL_LOGGER); assert(r==0);
|
2013-04-16 23:59:03 -04:00
|
|
|
r = toku_cachetable_openf(&f1, t, fname1, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
r = link(fname1, fname2); assert(r==0);
|
2013-04-16 23:59:03 -04:00
|
|
|
r = toku_cachetable_openf(&f2, t, fname2, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r==0);
|
|
|
|
r = toku_cachetable_openf(&f3, t, fname3, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
|
|
|
|
assert(f1==f2);
|
|
|
|
assert(f1!=f3);
|
|
|
|
|
2013-04-17 00:00:09 -04:00
|
|
|
CACHETABLE_WRITE_CALLBACK wc = def_write_callback((void*)123);
|
|
|
|
wc.flush_callback = null_flush;
|
|
|
|
r = toku_cachetable_put(f1, make_blocknum(1), toku_cachetable_hash(f1, make_blocknum(1)), (void*)124, make_pair_attr(test_object_size), wc); assert(r==0);
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f1, make_blocknum(1), toku_cachetable_hash(f1, make_blocknum(1)), CACHETABLE_DIRTY, make_pair_attr(0)); assert(r==0);
|
2013-04-17 00:00:13 -04:00
|
|
|
r = toku_cachetable_get_and_pin(f2, make_blocknum(1), toku_cachetable_hash(f2, make_blocknum(1)), &v, NULL, wc, add123_fetch, def_pf_req_callback, def_pf_callback, TRUE, (void*)123); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((unsigned long)v==124);
|
2013-04-17 00:00:13 -04:00
|
|
|
r = toku_cachetable_get_and_pin(f2, make_blocknum(2), toku_cachetable_hash(f2, make_blocknum(2)), &v, NULL, wc, add123_fetch, def_pf_req_callback, def_pf_callback, TRUE, (void*)123); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((unsigned long)v==125);
|
2013-04-17 00:00:09 -04:00
|
|
|
wc.write_extraargs = (void*)222;
|
2013-04-17 00:00:13 -04:00
|
|
|
r = toku_cachetable_get_and_pin(f3, make_blocknum(2), toku_cachetable_hash(f3, make_blocknum(2)), &v, NULL, wc, add222_fetch, def_pf_req_callback, def_pf_callback, TRUE, (void*)222); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((unsigned long)v==224);
|
2008-08-22 17:50:05 +00:00
|
|
|
|
2013-04-17 00:00:27 -04:00
|
|
|
// we support only one close for a file handle
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f1, make_blocknum(1), toku_cachetable_hash(f1, make_blocknum(1)), CACHETABLE_CLEAN, make_pair_attr(0)); assert(r==0);
|
|
|
|
r = toku_cachetable_unpin(f2, make_blocknum(2), toku_cachetable_hash(f2, make_blocknum(2)), CACHETABLE_CLEAN, make_pair_attr(0)); assert(r==0);
|
2013-04-16 23:58:06 -04:00
|
|
|
r = toku_cachefile_close(&f2, 0, FALSE, ZERO_LSN); assert(r==0);
|
2008-08-22 17:50:05 +00:00
|
|
|
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f3, make_blocknum(2), toku_cachetable_hash(f3, make_blocknum(2)), CACHETABLE_CLEAN, make_pair_attr(0)); assert(r==0);
|
2013-04-16 23:58:06 -04:00
|
|
|
r = toku_cachefile_close(&f3, 0, FALSE, ZERO_LSN); assert(r==0);
|
2008-08-22 17:50:05 +00:00
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_close(&t); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:27 -04:00
|
|
|
#endif
|
|
|
|
|
2013-04-16 23:57:18 -04:00
|
|
|
static void test_dirty_flush(CACHEFILE f,
|
2013-04-16 23:59:02 -04:00
|
|
|
int UU(fd),
|
2013-04-16 23:57:18 -04:00
|
|
|
CACHEKEY key,
|
|
|
|
void *value,
|
2013-04-17 00:00:13 -04:00
|
|
|
void** UU(dd),
|
2013-04-16 23:57:18 -04:00
|
|
|
void *extra __attribute__((__unused__)),
|
2013-04-16 23:59:54 -04:00
|
|
|
PAIR_ATTR size,
|
|
|
|
PAIR_ATTR* new_size __attribute__((__unused__)),
|
2013-04-16 23:57:18 -04:00
|
|
|
BOOL do_write,
|
|
|
|
BOOL keep,
|
2013-04-17 00:00:13 -04:00
|
|
|
BOOL for_checkpoint __attribute__((__unused__)),
|
|
|
|
BOOL UU(is_clone)
|
|
|
|
) {
|
2013-04-16 23:59:54 -04:00
|
|
|
if (verbose) printf("test_dirty_flush %p %" PRId64 " %p %ld %u %u\n", f, key.b, value, size.size, (unsigned)do_write, (unsigned)keep);
|
2007-09-17 16:23:05 +00:00
|
|
|
}
|
|
|
|
|
2013-04-17 00:00:13 -04:00
|
|
|
static int test_dirty_fetch(CACHEFILE f, int UU(fd), CACHEKEY key, u_int32_t fullhash, void **value_ptr,
|
|
|
|
void** UU(dd),
|
|
|
|
PAIR_ATTR *size_ptr, int * dirtyp, void *arg) {
|
2007-09-17 16:23:05 +00:00
|
|
|
*value_ptr = arg;
|
2013-04-16 23:59:25 -04:00
|
|
|
*dirtyp = 0;
|
2013-04-16 23:59:54 -04:00
|
|
|
*size_ptr = make_pair_attr(0);
|
2008-06-17 17:05:19 +00:00
|
|
|
assert(fullhash==toku_cachetable_hash(f,key));
|
2013-04-16 23:59:54 -04:00
|
|
|
if (verbose) printf("test_dirty_fetch %p %" PRId64 " %p %ld %p\n", f, key.b, *value_ptr, size_ptr->size, arg);
|
2007-09-17 16:23:05 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:58:00 -04:00
|
|
|
static void test_dirty(void) {
|
2007-12-22 23:12:40 +00:00
|
|
|
if (verbose) printf("test_dirty\n");
|
2007-09-21 17:55:49 +00:00
|
|
|
|
2007-09-17 16:23:05 +00:00
|
|
|
CACHETABLE t;
|
|
|
|
CACHEFILE f;
|
|
|
|
CACHEKEY key; void *value;
|
2007-09-21 17:55:49 +00:00
|
|
|
int dirty; long long pinned; long entry_size;
|
2007-09-17 16:23:05 +00:00
|
|
|
int r;
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_create_cachetable(&t, 4, ZERO_LSN, NULL_LOGGER);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
2008-05-04 16:56:15 +00:00
|
|
|
char *fname = __FILE__ "test.dat";
|
2013-04-16 23:57:47 -04:00
|
|
|
unlink(fname);
|
2013-04-16 23:59:03 -04:00
|
|
|
r = toku_cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
2013-04-16 23:57:18 -04:00
|
|
|
key = make_blocknum(1); value = (void*)1;
|
2008-06-17 17:05:19 +00:00
|
|
|
u_int32_t hkey = toku_cachetable_hash(f, key);
|
2013-04-17 00:00:09 -04:00
|
|
|
CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
|
|
|
|
wc.flush_callback = test_dirty_flush;
|
|
|
|
r = toku_cachetable_put(f, key, hkey, value, make_pair_attr(test_object_size), wc);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2008-06-05 22:09:59 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, f, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 1);
|
|
|
|
assert(pinned == 1);
|
|
|
|
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_CLEAN, make_pair_attr(0));
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
2008-06-05 22:09:59 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, f, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 1);
|
|
|
|
assert(pinned == 0);
|
|
|
|
|
2013-04-17 00:00:09 -04:00
|
|
|
r = toku_cachetable_get_and_pin(f, key, hkey, &value, NULL, wc,
|
2013-04-17 00:00:13 -04:00
|
|
|
test_dirty_fetch, def_pf_req_callback, def_pf_callback, TRUE, 0);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2008-06-05 22:09:59 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, f, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 1);
|
|
|
|
assert(pinned == 1);
|
|
|
|
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_CLEAN, make_pair_attr(test_object_size));
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2008-06-05 22:09:59 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, f, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 1);
|
|
|
|
assert(pinned == 0);
|
|
|
|
|
2013-04-16 23:57:18 -04:00
|
|
|
key = make_blocknum(2);
|
2008-06-17 17:05:19 +00:00
|
|
|
hkey = toku_cachetable_hash(f, key);
|
|
|
|
r = toku_cachetable_get_and_pin(f, key, hkey,
|
2013-04-17 00:00:09 -04:00
|
|
|
&value, NULL, wc,
|
2013-04-17 00:00:13 -04:00
|
|
|
test_dirty_fetch, def_pf_req_callback, def_pf_callback, TRUE, 0);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2008-06-05 22:09:59 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, f, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 0);
|
|
|
|
assert(pinned == 1);
|
|
|
|
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_CLEAN, make_pair_attr(test_object_size));
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2008-06-05 22:09:59 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, f, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 0);
|
|
|
|
assert(pinned == 0);
|
|
|
|
|
2008-06-17 17:05:19 +00:00
|
|
|
r = toku_cachetable_get_and_pin(f, key, hkey,
|
2013-04-17 00:00:09 -04:00
|
|
|
&value, NULL, wc,
|
2013-04-17 00:00:13 -04:00
|
|
|
test_dirty_fetch, def_pf_req_callback, def_pf_callback, TRUE, 0);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2008-06-05 22:09:59 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, f, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 0);
|
|
|
|
assert(pinned == 1);
|
|
|
|
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_DIRTY, make_pair_attr(test_object_size));
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2008-06-05 22:09:59 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, f, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 1);
|
|
|
|
assert(pinned == 0);
|
2007-09-21 17:55:49 +00:00
|
|
|
|
2013-04-16 23:58:06 -04:00
|
|
|
r = toku_cachefile_close(&f, 0, FALSE, ZERO_LSN);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_close(&t);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
}
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static int test_size_debug;
|
|
|
|
static CACHEKEY test_size_flush_key;
|
2007-09-21 17:55:49 +00:00
|
|
|
|
2013-04-16 23:57:18 -04:00
|
|
|
static void test_size_flush_callback(CACHEFILE f,
|
2013-04-16 23:59:02 -04:00
|
|
|
int UU(fd),
|
2013-04-16 23:57:18 -04:00
|
|
|
CACHEKEY key,
|
|
|
|
void *value,
|
2013-04-17 00:00:13 -04:00
|
|
|
void** UU(dd),
|
2013-04-16 23:57:18 -04:00
|
|
|
void *extra __attribute__((__unused__)),
|
2013-04-16 23:59:54 -04:00
|
|
|
PAIR_ATTR size,
|
|
|
|
PAIR_ATTR* new_size __attribute__((__unused__)),
|
2013-04-16 23:57:18 -04:00
|
|
|
BOOL do_write,
|
|
|
|
BOOL keep,
|
2013-04-17 00:00:13 -04:00
|
|
|
BOOL for_checkpoint __attribute__((__unused__)),
|
|
|
|
BOOL UU(is_clone)
|
|
|
|
) {
|
2013-04-16 23:59:54 -04:00
|
|
|
if (test_size_debug && verbose) printf("test_size_flush %p %" PRId64 " %p %ld %u %u\n", f, key.b, value, size.size, (unsigned)do_write, (unsigned)keep);
|
2008-08-22 17:50:05 +00:00
|
|
|
if (keep) {
|
2013-04-16 23:57:41 -04:00
|
|
|
if (do_write) {
|
|
|
|
test_mutex_lock();
|
|
|
|
test_size_flush_key = key;
|
|
|
|
test_mutex_unlock();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
assert(!do_write);
|
2008-08-22 17:50:05 +00:00
|
|
|
}
|
2007-09-21 17:55:49 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:58:00 -04:00
|
|
|
static void test_size_resize(void) {
|
2007-12-22 23:12:40 +00:00
|
|
|
if (verbose) printf("test_size_resize\n");
|
2007-09-21 17:55:49 +00:00
|
|
|
|
|
|
|
CACHETABLE t;
|
|
|
|
CACHEFILE f;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
int n = 3;
|
|
|
|
long size = 1;
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_create_cachetable(&t, n*size, ZERO_LSN, NULL_LOGGER);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
2008-05-04 16:56:15 +00:00
|
|
|
char *fname = __FILE__ "test.dat";
|
2013-04-16 23:57:47 -04:00
|
|
|
unlink(fname);
|
2013-04-16 23:59:03 -04:00
|
|
|
r = toku_cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
2013-04-16 23:57:18 -04:00
|
|
|
CACHEKEY key = make_blocknum(42);
|
2007-09-21 17:55:49 +00:00
|
|
|
void *value = (void *) -42;
|
|
|
|
|
2008-06-17 17:05:19 +00:00
|
|
|
u_int32_t hkey = toku_cachetable_hash(f, key);
|
|
|
|
|
2013-04-17 00:00:09 -04:00
|
|
|
CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
|
|
|
|
wc.flush_callback = test_size_flush_callback;
|
|
|
|
r = toku_cachetable_put(f, key, hkey, value, make_pair_attr(size), wc);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
2007-09-17 16:23:05 +00:00
|
|
|
|
2007-09-21 17:55:49 +00:00
|
|
|
void *entry_value; int dirty; long long pinned; long entry_size;
|
2008-06-05 22:09:59 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, f, &entry_value, &dirty, &pinned, &entry_size);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 1);
|
|
|
|
assert(pinned == 1);
|
|
|
|
assert(entry_value == value);
|
|
|
|
assert(entry_size == size);
|
|
|
|
|
|
|
|
long long new_size = 2*size;
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_CLEAN, make_pair_attr(new_size));
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
void *current_value;
|
|
|
|
long current_size;
|
2013-04-17 00:00:13 -04:00
|
|
|
r = toku_cachetable_get_and_pin(f, key, hkey, ¤t_value, ¤t_size, wc, 0, def_pf_req_callback, def_pf_callback, TRUE, 0);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(current_value == value);
|
|
|
|
assert(current_size == new_size);
|
|
|
|
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_CLEAN, make_pair_attr(new_size));
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
2013-04-16 23:58:06 -04:00
|
|
|
r = toku_cachefile_close(&f, 0, FALSE, ZERO_LSN);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_close(&t);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:19 -04:00
|
|
|
static int min2(int a, int b) { return a < b ? a : b; }
|
|
|
|
|
2013-04-16 23:59:40 -04:00
|
|
|
__attribute__((unused))
|
2013-04-16 23:58:00 -04:00
|
|
|
static void test_size_flush(void) {
|
2007-12-22 23:12:40 +00:00
|
|
|
if (verbose) printf("test_size_flush\n");
|
2007-09-21 17:55:49 +00:00
|
|
|
|
|
|
|
CACHETABLE t;
|
|
|
|
CACHEFILE f;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
const int n = 8;
|
|
|
|
long long size = 1*1024*1024;
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_create_cachetable(&t, n*size, ZERO_LSN, NULL_LOGGER);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
2008-05-04 16:56:15 +00:00
|
|
|
char *fname = __FILE__ "test.dat";
|
2013-04-16 23:57:47 -04:00
|
|
|
unlink(fname);
|
2013-04-16 23:59:03 -04:00
|
|
|
r = toku_cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, S_IRWXU|S_IRWXG|S_IRWXO);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
/* put 2*n keys into the table, ensure flushes occur in key order */
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_lock();
|
2013-04-16 23:57:18 -04:00
|
|
|
test_size_flush_key = make_blocknum(-1);
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_unlock();
|
2007-09-21 17:55:49 +00:00
|
|
|
|
|
|
|
int i;
|
2013-04-16 23:57:18 -04:00
|
|
|
CACHEKEY expect_flush_key = make_blocknum(0);
|
2007-09-21 17:55:49 +00:00
|
|
|
for (i=0; i<2*n; i++) {
|
2013-04-16 23:57:18 -04:00
|
|
|
CACHEKEY key = make_blocknum(i);
|
2007-09-21 18:34:34 +00:00
|
|
|
void *value = (void *)(long)-i;
|
2007-09-21 17:55:49 +00:00
|
|
|
// printf("test_size put %lld %p %lld\n", key, value, size);
|
2008-06-17 17:05:19 +00:00
|
|
|
u_int32_t hkey = toku_cachetable_hash(f, key);
|
2013-04-17 00:00:09 -04:00
|
|
|
CACHETABLE_WRITE_CALLBACK wc = def_write_callback(NULL);
|
|
|
|
wc.flush_callback = test_size_flush_callback;
|
|
|
|
r = toku_cachetable_put(f, key, hkey, value, make_pair_attr(size), wc);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
2013-04-17 00:00:25 -04:00
|
|
|
int n_entries, hash_size; long size_current, size_limit; int64_t size_max;
|
2013-04-16 23:59:47 -04:00
|
|
|
toku_cachetable_get_state(t, &n_entries, &hash_size, &size_current, &size_limit, &size_max);
|
2008-08-22 17:50:05 +00:00
|
|
|
while (n_entries != min2(i+1, n)) {
|
2013-04-16 23:57:41 -04:00
|
|
|
toku_pthread_yield(); maybe_flush(t);
|
2013-04-16 23:59:47 -04:00
|
|
|
toku_cachetable_get_state(t, &n_entries, 0, 0, 0, 0);
|
2008-08-22 17:50:05 +00:00
|
|
|
}
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(n_entries == min2(i+1, n));
|
|
|
|
|
|
|
|
void *entry_value; int dirty; long long pinned; long entry_size;
|
2008-06-05 22:09:59 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, f, &entry_value, &dirty, &pinned, &entry_size);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 1);
|
|
|
|
assert(pinned == 1);
|
|
|
|
assert(entry_value == value);
|
|
|
|
assert(entry_size == size);
|
|
|
|
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_lock();
|
2013-04-16 23:57:18 -04:00
|
|
|
if (test_size_flush_key.b != -1) {
|
|
|
|
assert(test_size_flush_key.b == expect_flush_key.b);
|
|
|
|
assert(expect_flush_key.b == i-n);
|
|
|
|
expect_flush_key.b += 1;
|
2007-09-21 17:55:49 +00:00
|
|
|
}
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_unlock();
|
2007-09-21 17:55:49 +00:00
|
|
|
|
2013-04-16 23:59:54 -04:00
|
|
|
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_CLEAN, make_pair_attr(size));
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:58:06 -04:00
|
|
|
r = toku_cachefile_close(&f, 0, FALSE, ZERO_LSN);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_close(&t);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:32 -04:00
|
|
|
int
|
|
|
|
test_main (int argc, const char *argv[]) {
|
2008-08-22 17:50:05 +00:00
|
|
|
// defaults
|
|
|
|
int do_malloc_fail = 0;
|
2007-11-14 17:58:38 +00:00
|
|
|
|
2008-08-22 17:50:05 +00:00
|
|
|
// parse args
|
2007-11-14 17:58:38 +00:00
|
|
|
int i;
|
2008-08-22 17:50:05 +00:00
|
|
|
for (i=1; i<argc; i++) {
|
|
|
|
const char *arg = argv[i];
|
|
|
|
if (strcmp(arg, "-v") == 0) {
|
|
|
|
verbose++;
|
|
|
|
continue;
|
|
|
|
}
|
2013-04-17 00:00:02 -04:00
|
|
|
if (strcmp(arg, "-q") == 0) {
|
|
|
|
if (verbose > 0) verbose--;
|
|
|
|
continue;
|
|
|
|
}
|
2008-08-22 17:50:05 +00:00
|
|
|
if (strcmp(arg, "-malloc-fail") == 0) {
|
|
|
|
do_malloc_fail = 1;
|
|
|
|
continue;
|
|
|
|
}
|
2007-11-14 17:58:38 +00:00
|
|
|
}
|
|
|
|
|
2013-04-16 23:57:35 -04:00
|
|
|
test_mutex_init();
|
|
|
|
|
2008-08-22 17:50:05 +00:00
|
|
|
// run tests
|
2013-04-16 23:58:59 -04:00
|
|
|
#if !TOKU_WINDOWS
|
2008-08-22 17:50:05 +00:00
|
|
|
test_multi_filehandles();
|
2013-04-16 23:57:27 -04:00
|
|
|
#endif
|
2008-08-22 17:50:05 +00:00
|
|
|
test_cachetable_create();
|
|
|
|
if (do_malloc_fail)
|
|
|
|
test_cachetable_create_no_memory(); // fails with valgrind
|
|
|
|
for (i=0; i<1; i++) {
|
|
|
|
test0();
|
|
|
|
test_nested_pin();
|
2013-04-16 23:58:59 -04:00
|
|
|
#if !TOKU_WINDOWS
|
2008-08-22 17:50:05 +00:00
|
|
|
test_multi_filehandles ();
|
2013-04-16 23:57:27 -04:00
|
|
|
#endif
|
2008-08-22 17:50:05 +00:00
|
|
|
test_dirty();
|
|
|
|
test_size_resize();
|
2013-04-16 23:59:40 -04:00
|
|
|
//test_size_flush();
|
2008-08-22 17:50:05 +00:00
|
|
|
}
|
2013-04-16 23:57:35 -04:00
|
|
|
|
|
|
|
test_mutex_destroy();
|
2013-04-16 23:59:22 -04:00
|
|
|
|
2007-12-22 23:12:40 +00:00
|
|
|
if (verbose) printf("ok\n");
|
2007-07-13 19:37:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|