2007-11-14 17:58:38 +00:00
|
|
|
/* -*- mode: C; c-basic-offset: 4 -*- */
|
2007-11-29 14:18:54 +00:00
|
|
|
#ident "Copyright (c) 2007 Tokutek Inc. All rights reserved."
|
2007-11-14 17:58:38 +00:00
|
|
|
|
2007-07-13 19:37:47 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#include <stdio.h>
|
2007-09-12 18:12:31 +00:00
|
|
|
#include <stdlib.h>
|
2007-09-21 17:55:49 +00:00
|
|
|
#include <stdint.h>
|
2007-09-12 18:12:31 +00:00
|
|
|
#include <string.h>
|
2007-07-13 19:37:47 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2007-09-21 17:55:49 +00:00
|
|
|
#include "memory.h"
|
|
|
|
#include "cachetable.h"
|
2007-12-22 23:12:40 +00:00
|
|
|
#include "test.h"
|
2007-09-21 17:55:49 +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;
|
|
|
|
};
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static int expect_n_flushes=0;
|
|
|
|
static CACHEKEY flushes[100];
|
2007-07-13 19:37:47 +00:00
|
|
|
|
|
|
|
static void expect1(CACHEKEY key) {
|
|
|
|
expect_n_flushes=1;
|
|
|
|
flushes[0]=key;
|
|
|
|
}
|
|
|
|
static void expectN(CACHEKEY key) {
|
|
|
|
flushes[expect_n_flushes++]=key;
|
|
|
|
}
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static CACHEFILE expect_f;
|
2007-07-13 19:37:47 +00:00
|
|
|
|
2007-11-14 17:58:38 +00:00
|
|
|
static void flush (CACHEFILE f, CACHEKEY key, void*value, long size __attribute__((__unused__)), BOOL write_me __attribute__((__unused__)), BOOL keep_me __attribute__((__unused__)), LSN modified_lsn __attribute__((__unused__)), BOOL rename_p __attribute__((__unused__))) {
|
2007-07-13 19:37:47 +00:00
|
|
|
struct item *it = value;
|
|
|
|
int i;
|
|
|
|
|
2007-12-22 23:12:40 +00:00
|
|
|
if (verbose) printf("Flushing %lld (it=>key=%lld)\n", key, it->key);
|
2007-07-13 19:37:47 +00:00
|
|
|
|
|
|
|
assert(expect_f==f);
|
|
|
|
assert(strcmp(it->something,"something")==0);
|
|
|
|
assert(it->key==key);
|
|
|
|
|
|
|
|
/* Verify that we expected the flush. */
|
|
|
|
for (i=0; i<expect_n_flushes; i++) {
|
|
|
|
if (key==flushes[i]) {
|
|
|
|
flushes[i] = flushes[expect_n_flushes-1];
|
|
|
|
expect_n_flushes--;
|
|
|
|
goto found_flush;
|
|
|
|
}
|
|
|
|
}
|
2007-12-22 23:12:40 +00:00
|
|
|
fprintf(stderr, "%lld was flushed, but I didn't expect it\n", key);
|
2007-07-13 19:37:47 +00:00
|
|
|
abort();
|
|
|
|
found_flush:
|
2007-07-20 18:00:14 +00:00
|
|
|
toku_free(value);
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static struct item *make_item (CACHEKEY key) {
|
2007-07-13 19:37:47 +00:00
|
|
|
struct item *MALLOC(it);
|
|
|
|
it->key=key;
|
|
|
|
it->something="something";
|
|
|
|
return it;
|
|
|
|
}
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static CACHEKEY did_fetch=-1;
|
|
|
|
static int fetch (CACHEFILE f, CACHEKEY key, void**value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
|
2007-12-22 23:12:40 +00:00
|
|
|
if (verbose) printf("Fetch %lld\n", key);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert (expect_f==f);
|
|
|
|
assert((long)extraargs==23);
|
|
|
|
*value = make_item(key);
|
|
|
|
did_fetch=key;
|
2007-11-14 17:58:38 +00:00
|
|
|
written_lsn->lsn = 0;
|
2007-07-13 19:37:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
char fname[] = "test.dat";
|
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);
|
|
|
|
unlink(fname);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, 0777);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
expect_f = f;
|
|
|
|
|
|
|
|
expect_n_flushes=0;
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_put(f, 1, make_item(1), test_object_size, flush, fetch, t3); /* 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);
|
|
|
|
|
|
|
|
expect_n_flushes=0;
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_put(f, 2, make_item(2), test_object_size, flush, fetch, t3);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_unpin(f, 2, CACHETABLE_DIRTY, 1); /* 2U 1P */
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(expect_n_flushes==0);
|
|
|
|
|
|
|
|
expect_n_flushes=0;
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_put(f, 3, make_item(3), test_object_size, flush, fetch, t3);
|
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) */
|
|
|
|
|
|
|
|
expect_n_flushes=0;
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_put(f, 4, make_item(4), test_object_size, flush, fetch, t3);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(expect_n_flushes==0); /* 4P 3P 2U 1P */
|
|
|
|
|
|
|
|
expect_n_flushes=0;
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_put(f, 5, make_item(5), test_object_size, flush, fetch, t3);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_unpin(f, 5, CACHETABLE_DIRTY, 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_unpin(f, 3, CACHETABLE_DIRTY, 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. */
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_put(f, 6, make_item(6), test_object_size, flush, fetch, t3); /* 6P 5U 4P 3U 1P */
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(expect_n_flushes==0);
|
|
|
|
|
|
|
|
|
|
|
|
expect1(3);
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_put(f, 7, make_item(7), test_object_size, flush, fetch, t3);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(expect_n_flushes==0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_unpin(f, 7, CACHETABLE_DIRTY, test_object_size); /* 7U 6P 5U 4P 1P */
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
|
|
|
|
{
|
|
|
|
void *item_v=0;
|
|
|
|
expect_n_flushes=0;
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_get_and_pin(f, 5, &item_v, NULL, flush, fetch, t3); /* 5P 7U 6P 4P 1P */
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(((struct item *)item_v)->key==5);
|
|
|
|
assert(strcmp(((struct item *)item_v)->something,"something")==0);
|
|
|
|
assert(expect_n_flushes==0);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
void *item_v=0;
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_unpin(f, 4, CACHETABLE_DIRTY, test_object_size);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
expect1(4);
|
|
|
|
did_fetch=-1;
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_get_and_pin(f, 2, &item_v, NULL, flush, fetch, t3); /* 2p 5P 7U 6P 1P */
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(did_fetch==2); /* Expect that 2 is fetched in. */
|
|
|
|
assert(((struct item *)item_v)->key==2);
|
|
|
|
assert(strcmp(((struct item *)item_v)->something,"something")==0);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(expect_n_flushes==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachetable_unpin(f, 2, CACHETABLE_DIRTY, 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_unpin(f ,5, CACHETABLE_DIRTY, 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_unpin(f, 6, CACHETABLE_DIRTY, 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_unpin(f, 1, CACHETABLE_DIRTY, 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);
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_cachefile_close(&f);
|
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);
|
|
|
|
expect_f = 0;
|
2007-11-29 15:34:49 +00:00
|
|
|
toku_memory_check_all_free();
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
|
|
|
|
2007-09-21 17:55:49 +00:00
|
|
|
static void flush_n (CACHEFILE f __attribute__((__unused__)), CACHEKEY key __attribute__((__unused__)), void *value,
|
2007-11-14 17:58:38 +00:00
|
|
|
long size __attribute__((__unused__)),
|
|
|
|
BOOL write_me __attribute__((__unused__)), BOOL keep_me __attribute__((__unused__)),
|
|
|
|
LSN modified_lsn __attribute__((__unused__)), BOOL rename_p __attribute ((__unused__))) {
|
2007-07-13 19:37:47 +00:00
|
|
|
int *v = value;
|
|
|
|
assert(*v==0);
|
|
|
|
}
|
2007-09-21 17:55:49 +00:00
|
|
|
static int fetch_n (CACHEFILE f __attribute__((__unused__)), CACHEKEY key __attribute__((__unused__)),
|
2007-11-14 17:58:38 +00:00
|
|
|
void**value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((long)extraargs==42);
|
|
|
|
*value=0;
|
2007-11-14 17:58:38 +00:00
|
|
|
written_lsn->lsn = 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;
|
|
|
|
void *vv;
|
2007-08-24 18:36:02 +00:00
|
|
|
char fname[] = "test_ct.dat";
|
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);
|
|
|
|
unlink(fname);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, 0777);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
expect_f = f;
|
|
|
|
|
|
|
|
i0=0; i1=0;
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_put(f, 1, &i0, 1, flush_n, fetch_n, f2);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_and_pin(f, 1, &vv, NULL, flush_n, fetch_n, f2);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(vv==&i0);
|
|
|
|
assert(i0==0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_unpin(f, 1, 0, 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_put(f, 2, &i1, test_object_size, flush_n, fetch_n, f2);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r!=0); // previously pinned, we shouldn't be able to put.
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_unpin(f, 1, 0, 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_put(f, 2, &i1, test_object_size, flush_n, fetch_n, f2);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert(r==0); // now it is unpinned, we can put it.
|
2007-08-01 02:37:21 +00:00
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachefile_close(&f); assert(r==0);
|
|
|
|
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__)),
|
2007-11-14 17:58:38 +00:00
|
|
|
CACHEKEY k __attribute__((__unused__)),
|
|
|
|
void *v __attribute__((__unused__)),
|
|
|
|
long size __attribute__((__unused__)),
|
|
|
|
BOOL write_me __attribute__((__unused__)),
|
|
|
|
BOOL keep_me __attribute__((__unused__)),
|
|
|
|
LSN modified_lsn __attribute__((__unused__)),
|
|
|
|
BOOL rename_p __attribute__((__unused__))) {
|
2007-07-13 19:37:47 +00:00
|
|
|
}
|
2007-11-29 18:14:40 +00:00
|
|
|
static int add123_fetch (CACHEFILE cf __attribute__((__unused__)), CACHEKEY key, void **value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((long)extraargs==123);
|
|
|
|
*value = (void*)((unsigned long)key+123L);
|
2007-11-14 17:58:38 +00:00
|
|
|
written_lsn->lsn = 0;
|
2007-07-13 19:37:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2007-11-29 18:14:40 +00:00
|
|
|
static int add222_fetch (CACHEFILE cf __attribute__((__unused__)), CACHEKEY key, void **value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((long)extraargs==222);
|
|
|
|
*value = (void*)((unsigned long)key+222L);
|
2007-11-14 17:58:38 +00:00
|
|
|
written_lsn->lsn = 0;
|
2007-07-13 19:37:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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;
|
2007-08-24 18:36:02 +00:00
|
|
|
char fname1[]="test_ct.dat";
|
|
|
|
char fname2[]="test2_ct.dat";
|
|
|
|
char fname3[]="test3_ct.dat";
|
2007-07-13 19:37:47 +00:00
|
|
|
int r;
|
|
|
|
void *v;
|
|
|
|
unlink(fname1);
|
|
|
|
unlink(fname2);
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_create_cachetable(&t, 4, ZERO_LSN, NULL_LOGGER); assert(r==0);
|
|
|
|
r = toku_cachetable_openf(&f1, t, fname1, O_RDWR|O_CREAT, 0777); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
r = link(fname1, fname2); assert(r==0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_openf(&f2, t, fname2, O_RDWR|O_CREAT, 0777); assert(r==0);
|
|
|
|
r = toku_cachetable_openf(&f3, t, fname3, O_RDWR|O_CREAT, 0777); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
|
|
|
|
assert(f1==f2);
|
|
|
|
assert(f1!=f3);
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_put(f1, 1, (void*)124, test_object_size, null_flush, add123_fetch, (void*)123); assert(r==0);
|
|
|
|
r = toku_cachetable_get_and_pin(f2, 1, &v, NULL, null_flush, add123_fetch, (void*)123); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((unsigned long)v==124);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_and_pin(f2, 2, &v, NULL, null_flush, add123_fetch, (void*)123); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((unsigned long)v==125);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_and_pin(f3, 2, &v, NULL, null_flush, add222_fetch, (void*)222); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((unsigned long)v==224);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_maybe_get_and_pin(f1, 2, &v); assert(r==0);
|
2007-07-13 19:37:47 +00:00
|
|
|
assert((unsigned long)v==125);
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachefile_close(&f1); assert(r==0);
|
|
|
|
r = toku_cachefile_close(&f2); assert(r==0);
|
|
|
|
r = toku_cachefile_close(&f3); assert(r==0);
|
|
|
|
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 test_dirty_flush(CACHEFILE f, CACHEKEY key, void *value, long size, BOOL do_write, BOOL keep, LSN modified_lsn __attribute__((__unused__)), BOOL rename_p __attribute__((__unused__))) {
|
2007-12-22 23:12:40 +00:00
|
|
|
if (verbose) printf("test_dirty_flush %p %lld %p %ld %d %d\n", f, key, value, size, do_write, keep);
|
2007-09-17 16:23:05 +00:00
|
|
|
}
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static int test_dirty_fetch(CACHEFILE f, CACHEKEY key, void **value_ptr, long *size_ptr, void *arg, LSN *written_lsn) {
|
2007-09-17 16:23:05 +00:00
|
|
|
*value_ptr = arg;
|
2007-11-14 17:58:38 +00:00
|
|
|
written_lsn->lsn = 0;
|
2007-12-22 23:12:40 +00:00
|
|
|
if (verbose) printf("test_dirty_fetch %p %lld %p %ld %p\n", f, key, *value_ptr, *size_ptr, arg);
|
2007-09-17 16:23:05 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static void test_dirty() {
|
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);
|
|
|
|
|
|
|
|
char *fname = "test.dat";
|
|
|
|
unlink(fname);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, 0777);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
key = 1; value = (void*)1;
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_put(f, key, value, test_object_size, test_dirty_flush, 0, 0);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 1);
|
|
|
|
assert(pinned == 1);
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_unpin(f, key, CACHETABLE_CLEAN, 0);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 1);
|
|
|
|
assert(pinned == 0);
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_and_pin(f, key, &value, NULL, test_dirty_flush,
|
2007-09-17 16:23:05 +00:00
|
|
|
test_dirty_fetch, 0);
|
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 1);
|
|
|
|
assert(pinned == 1);
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_unpin(f, key, CACHETABLE_CLEAN, test_object_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 1);
|
|
|
|
assert(pinned == 0);
|
|
|
|
|
|
|
|
key = 2;
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_and_pin(f, key, &value, NULL, test_dirty_flush,
|
2007-09-17 16:23:05 +00:00
|
|
|
test_dirty_fetch, 0);
|
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 0);
|
|
|
|
assert(pinned == 1);
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_unpin(f, key, CACHETABLE_CLEAN, test_object_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 0);
|
|
|
|
assert(pinned == 0);
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_and_pin(f, key, &value, NULL, test_dirty_flush,
|
2007-11-29 18:14:40 +00:00
|
|
|
test_dirty_fetch, 0);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, &value, &dirty, &pinned, &entry_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(dirty == 0);
|
|
|
|
assert(pinned == 1);
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_unpin(f, key, CACHETABLE_DIRTY, test_object_size);
|
2007-09-17 16:23:05 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
// cachetable_print_state(t);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, &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
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachefile_close(&f);
|
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
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static void test_size_flush_callback(CACHEFILE f, CACHEKEY key, void *value, long size, BOOL do_write, BOOL keep, LSN modified_lsn __attribute__((__unused__)), BOOL rename_p __attribute__((__unused__))) {
|
2007-12-22 23:12:40 +00:00
|
|
|
if (test_size_debug && verbose) printf("test_size_flush %p %lld %p %ld %d %d\n", f, key, value, size, do_write, keep);
|
2007-11-26 15:39:38 +00:00
|
|
|
assert(do_write != 0);
|
2007-09-21 17:55:49 +00:00
|
|
|
test_size_flush_key = key;
|
|
|
|
}
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static void test_size_resize() {
|
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);
|
|
|
|
|
|
|
|
char *fname = "test.dat";
|
|
|
|
unlink(fname);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, 0777);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
CACHEKEY key = 42;
|
|
|
|
void *value = (void *) -42;
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_put(f, key, value, size, test_size_flush_callback, 0, 0);
|
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;
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, &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;
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_unpin(f, key, CACHETABLE_CLEAN, new_size);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
void *current_value;
|
|
|
|
long current_size;
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_and_pin(f, key, ¤t_value, ¤t_size, test_size_flush_callback, 0, 0);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
assert(current_value == value);
|
|
|
|
assert(current_size == new_size);
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_unpin(f, key, CACHETABLE_CLEAN, new_size);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachefile_close(&f);
|
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 void test_size_flush() {
|
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);
|
|
|
|
|
|
|
|
char *fname = "test.dat";
|
|
|
|
unlink(fname);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, 0777);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
/* put 2*n keys into the table, ensure flushes occur in key order */
|
|
|
|
test_size_flush_key = -1;
|
|
|
|
|
|
|
|
int i;
|
|
|
|
CACHEKEY expect_flush_key = 0;
|
|
|
|
for (i=0; i<2*n; i++) {
|
|
|
|
CACHEKEY key = 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);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_put(f, key, value, size, test_size_flush_callback, 0, 0);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
int n_entries;
|
2007-11-19 23:47:44 +00:00
|
|
|
toku_cachetable_get_state(t, &n_entries, 0, 0, 0);
|
2007-09-21 17:55:49 +00:00
|
|
|
int min2(int a, int b) { return a < b ? a : b; }
|
|
|
|
assert(n_entries == min2(i+1, n));
|
|
|
|
|
|
|
|
void *entry_value; int dirty; long long pinned; long entry_size;
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_key_state(t, key, &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);
|
|
|
|
|
|
|
|
if (test_size_flush_key != -1) {
|
|
|
|
assert(test_size_flush_key == expect_flush_key);
|
|
|
|
assert(expect_flush_key == i-n);
|
|
|
|
expect_flush_key += 1;
|
|
|
|
}
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_unpin(f, key, CACHETABLE_CLEAN, size);
|
2007-09-21 17:55:49 +00:00
|
|
|
assert(r == 0);
|
|
|
|
}
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachefile_close(&f);
|
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);
|
|
|
|
}
|
|
|
|
|
2007-11-14 17:58:38 +00:00
|
|
|
enum { KEYLIMIT = 4, TRIALLIMIT=64 };
|
2007-11-29 18:14:40 +00:00
|
|
|
static CACHEKEY keys[KEYLIMIT];
|
|
|
|
static void* vals[KEYLIMIT];
|
|
|
|
static int n_keys=0;
|
2007-11-14 17:58:38 +00:00
|
|
|
|
|
|
|
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");
|
|
|
|
for (i=0; i<n_keys; i++) {
|
|
|
|
if (keys[i]==k) {
|
|
|
|
assert(vals[i]==value);
|
|
|
|
if (!keep_me) {
|
|
|
|
keys[i]=keys[n_keys-1];
|
|
|
|
vals[i]=vals[n_keys-1];
|
|
|
|
n_keys--;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fprintf(stderr, "Whoops\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static int r_fetch (CACHEFILE f __attribute__((__unused__)),
|
2007-11-14 17:58:38 +00:00
|
|
|
CACHEKEY key __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 0;
|
|
|
|
}
|
|
|
|
|
2007-11-29 18:14:40 +00:00
|
|
|
static void test_rename (void) {
|
2007-11-14 17:58:38 +00:00
|
|
|
CACHETABLE t;
|
|
|
|
CACHEFILE f;
|
|
|
|
int i;
|
|
|
|
int r;
|
|
|
|
const char fname[] = "ct-test-rename.dat";
|
2007-11-19 23:47:44 +00:00
|
|
|
r=toku_create_cachetable(&t, KEYLIMIT, ZERO_LSN, NULL_LOGGER); assert(r==0);
|
2007-11-14 17:58:38 +00:00
|
|
|
unlink(fname);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, 0777);
|
2007-11-14 17:58:38 +00:00
|
|
|
assert(r==0);
|
|
|
|
|
|
|
|
for (i=0; i<TRIALLIMIT; i++) {
|
|
|
|
int ra = random()%3;
|
|
|
|
if (ra<=1) {
|
|
|
|
// Insert something
|
|
|
|
CACHEKEY nkey = random();
|
|
|
|
long nval = random();
|
|
|
|
//printf("n_keys=%d Insert %08llx\n", n_keys, nkey);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_put(f, nkey, (void*)nval, 1,
|
|
|
|
r_flush, r_fetch, 0);
|
2007-11-14 17:58:38 +00:00
|
|
|
assert(r==0);
|
|
|
|
assert(n_keys<KEYLIMIT);
|
|
|
|
keys[n_keys] = nkey;
|
|
|
|
vals[n_keys] = (void*)nval;
|
|
|
|
n_keys++;
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_unpin(f, nkey, CACHETABLE_DIRTY, 1);
|
2007-11-14 17:58:38 +00:00
|
|
|
assert(r==0);
|
|
|
|
} else if (ra==2 && n_keys>0) {
|
|
|
|
// Rename something
|
|
|
|
int objnum = random()%n_keys;
|
|
|
|
CACHEKEY okey = keys[objnum];
|
|
|
|
CACHEKEY nkey = random();
|
|
|
|
void *current_value;
|
|
|
|
long current_size;
|
|
|
|
keys[objnum]=nkey;
|
|
|
|
//printf("Rename %llx to %llx\n", okey, nkey);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_get_and_pin(f, okey, ¤t_value, ¤t_size, r_flush, r_fetch, 0);
|
2007-11-14 17:58:38 +00:00
|
|
|
assert(r==0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_rename(f, okey, nkey);
|
2007-11-14 17:58:38 +00:00
|
|
|
assert(r==0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_unpin(f, nkey, CACHETABLE_DIRTY, 1);
|
2007-11-14 17:58:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachefile_close(&f);
|
2007-11-14 17:58:38 +00:00
|
|
|
assert(r == 0);
|
2007-11-19 23:47:44 +00:00
|
|
|
r = toku_cachetable_close(&t);
|
2007-11-14 17:58:38 +00:00
|
|
|
assert(r == 0);
|
|
|
|
|
|
|
|
assert(n_keys == 0);
|
|
|
|
}
|
|
|
|
|
2007-12-22 23:12:40 +00:00
|
|
|
int main (int argc, const char *argv[]) {
|
|
|
|
default_parse_args(argc, argv);
|
2007-11-14 17:58:38 +00:00
|
|
|
test_rename();
|
2007-07-13 19:37:47 +00:00
|
|
|
test0();
|
|
|
|
test_nested_pin();
|
|
|
|
test_multi_filehandles ();
|
2007-09-17 16:23:05 +00:00
|
|
|
test_dirty();
|
2007-09-21 17:55:49 +00:00
|
|
|
test_size_resize();
|
|
|
|
test_size_flush();
|
2007-11-29 15:34:49 +00:00
|
|
|
toku_malloc_cleanup();
|
2007-12-22 23:12:40 +00:00
|
|
|
if (verbose) printf("ok\n");
|
2007-07-13 19:37:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|