Commit 4db5b506 authored by Bradley C. Kuszmaul's avatar Bradley C. Kuszmaul

Did

{{{
svn merge -r4556:4568 https://svn.tokutek.com/tokudb/tokudb.906
}}}
to incorporate the hash improvements.

Addresses #906.


git-svn-id: file:///svn/tokudb@4596 c7de825b-a66e-492c-adef-691d508d4ae1
parent 53161133
......@@ -67,6 +67,7 @@ struct brtnode {
u_int32_t rand4fingerprint;
u_int32_t local_fingerprint; /* For leaves this is everything in the buffer. For nonleaves, this is everything in the buffers, but does not include child subtree fingerprints. */
int dirty;
u_int32_t fullhash;
union node {
struct nonleaf {
// Don't actually store the subree fingerprint in the in-memory data structure.
......@@ -103,6 +104,7 @@ enum {
struct brt_header {
int dirty;
u_int32_t fullhash;
int layout_version;
unsigned int nodesize;
DISKOFF freelist;
......@@ -140,7 +142,7 @@ struct brt {
/* serialization code */
void toku_serialize_brtnode_to(int fd, DISKOFF off, BRTNODE node);
int toku_deserialize_brtnode_from (int fd, DISKOFF off, BRTNODE *brtnode);
int toku_deserialize_brtnode_from (int fd, DISKOFF off, u_int32_t /*fullhash*/, BRTNODE *brtnode);
unsigned int toku_serialize_brtnode_size(BRTNODE node); /* How much space will it take? */
int toku_keycompare (bytevec key1, ITEMLEN key1len, bytevec key2, ITEMLEN key2len);
......@@ -149,7 +151,7 @@ void toku_verify_counts(BRTNODE);
int toku_serialize_brt_header_size (struct brt_header *h);
int toku_serialize_brt_header_to (int fd, struct brt_header *h);
int toku_serialize_brt_header_to_wbuf (struct wbuf *, struct brt_header *h);
int toku_deserialize_brtheader_from (int fd, DISKOFF off, struct brt_header **brth);
int toku_deserialize_brtheader_from (int fd, DISKOFF off, u_int32_t fullhash, struct brt_header **brth);
int toku_serialize_fifo_at (int fd, off_t freeoff, FIFO fifo); // Write a fifo into a disk, without worrying about fitting it into a block. This write is done at the end of the file.
int toku_deserialize_fifo_at (int fd, off_t at, FIFO *fifo);
......@@ -200,7 +202,7 @@ struct brt_cursor {
// logs the memory allocation, but not the creation of the new node
int toku_create_new_brtnode (BRT t, BRTNODE *result, int height, TOKULOGGER logger);
int toku_unpin_brtnode (BRT brt, BRTNODE node) ;
int toku_unpin_brtnode (BRT brt, BRTNODE node);
unsigned int toku_brtnode_which_child (BRTNODE node , DBT *k, DBT *d, BRT t);
/* Stuff for testing */
......
......@@ -215,7 +215,7 @@ void toku_serialize_brtnode_to (int fd, DISKOFF off, BRTNODE node) {
toku_free(buf);
}
int toku_deserialize_brtnode_from (int fd, DISKOFF off, BRTNODE *brtnode) {
int toku_deserialize_brtnode_from (int fd, DISKOFF off, u_int32_t fullhash, BRTNODE *brtnode) {
TAGMALLOC(BRTNODE, result);
struct rbuf rc;
int i;
......@@ -294,6 +294,7 @@ int toku_deserialize_brtnode_from (int fd, DISKOFF off, BRTNODE *brtnode) {
result->local_fingerprint = rbuf_int(&rc);
// printf("%s:%d read %08x\n", __FILE__, __LINE__, result->local_fingerprint);
result->dirty = 0;
result->fullhash = fullhash;
//printf("height==%d\n", result->height);
if (result->height>0) {
result->u.n.totalchildkeylens=0;
......@@ -552,10 +553,11 @@ int toku_serialize_brt_header_to (int fd, struct brt_header *h) {
return r;
}
static int deserialize_brtheader_6_or_earlier (int fd, DISKOFF off, struct brt_header **brth) {
static int deserialize_brtheader_6_or_earlier (int fd, DISKOFF off, struct brt_header **brth, u_int32_t fullhash) {
// Deserialize a brt header from version 6 or earlier.
struct brt_header *MALLOC(h);
if (h==0) return errno;
h->fullhash = fullhash;
int ret=-1;
if (0) { died0: toku_free(h); return ret; }
int size;
......@@ -632,11 +634,12 @@ static int deserialize_brtheader_6_or_earlier (int fd, DISKOFF off, struct brt_h
return 0;
}
int deserialize_brtheader_7_or_later(u_int32_t size, int fd, DISKOFF off, struct brt_header **brth) {
int deserialize_brtheader_7_or_later(u_int32_t size, int fd, DISKOFF off, struct brt_header **brth, u_int32_t fullhash) {
// We already know the first 8 bytes are "tokudata", and we read in the size.
struct brt_header *MALLOC(h);
if (h==0) return errno;
int ret=-1;
h->fullhash = fullhash;
if (0) { died0: toku_free(h); return ret; }
struct rbuf rc;
rc.buf = toku_malloc(size-12); // we can skip the first 12 bytes.
......@@ -685,7 +688,7 @@ int deserialize_brtheader_7_or_later(u_int32_t size, int fd, DISKOFF off, struct
return 0;
}
int toku_deserialize_brtheader_from (int fd, DISKOFF off, struct brt_header **brth) {
int toku_deserialize_brtheader_from (int fd, DISKOFF off, u_int32_t fullhash, struct brt_header **brth) {
//printf("%s:%d calling MALLOC\n", __FILE__, __LINE__);
assert(off==0);
//printf("%s:%d malloced %p\n", __FILE__, __LINE__, h);
......@@ -697,9 +700,9 @@ int toku_deserialize_brtheader_from (int fd, DISKOFF off, struct brt_header **br
if (r!=12) return EINVAL;
if (memcmp(magic,"tokudata",8)==0) {
// It's version 7 or later
return deserialize_brtheader_7_or_later(ntohl(*(int*)(&magic[8])), fd, off, brth);
return deserialize_brtheader_7_or_later(ntohl(*(int*)(&magic[8])), fd, off, brth, fullhash);
} else {
return deserialize_brtheader_6_or_earlier(fd, off, brth);
return deserialize_brtheader_6_or_earlier(fd, off, brth, fullhash);
}
}
......
......@@ -58,7 +58,7 @@ int toku_testsetup_root(BRT brt, DISKOFF diskoff) {
int toku_testsetup_get_sersize(BRT brt, DISKOFF diskoff) // Return the size on disk
{
void *node_v;
int r = toku_cachetable_get_and_pin(brt->cf, diskoff, &node_v, NULL,
int r = toku_cachetable_get_and_pin(brt->cf, diskoff, toku_cachetable_hash(brt->cf, diskoff), &node_v, NULL,
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt);
assert(r==0);
int size = toku_serialize_brtnode_size(node_v);
......@@ -70,7 +70,7 @@ int toku_testsetup_get_sersize(BRT brt, DISKOFF diskoff) // Return the size on d
int toku_testsetup_insert_to_leaf (BRT brt, DISKOFF diskoff, char *key, int keylen, char *val, int vallen, u_int32_t *subtree_fingerprint) {
void *node_v;
int r;
r = toku_cachetable_get_and_pin(brt->cf, diskoff, &node_v, NULL,
r = toku_cachetable_get_and_pin(brt->cf, diskoff, toku_cachetable_hash(brt->cf, diskoff), &node_v, NULL,
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt);
if (r!=0) return r;
BRTNODE node=node_v;
......@@ -122,7 +122,7 @@ int toku_testsetup_insert_to_leaf (BRT brt, DISKOFF diskoff, char *key, int keyl
int toku_testsetup_insert_to_nonleaf (BRT brt, DISKOFF diskoff, enum brt_cmd_type cmdtype, char *key, int keylen, char *val, int vallen, u_int32_t *subtree_fingerprint) {
void *node_v;
int r;
r = toku_cachetable_get_and_pin(brt->cf, diskoff, &node_v, NULL,
r = toku_cachetable_get_and_pin(brt->cf, diskoff, toku_cachetable_hash(brt->cf, diskoff), &node_v, NULL,
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt);
if (r!=0) return r;
BRTNODE node=node_v;
......
......@@ -64,11 +64,13 @@ int toku_verify_brtnode (BRT brt, DISKOFF off, bytevec lorange, ITEMLEN lolen, b
BRTNODE node;
void *node_v;
int r;
if ((r = toku_cachetable_get_and_pin(brt->cf, off, &node_v, NULL,
u_int32_t fullhash = toku_cachetable_hash(brt->cf, off);
if ((r = toku_cachetable_get_and_pin(brt->cf, off, fullhash, &node_v, NULL,
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, (void*)(long)brt->h->nodesize)))
return r;
//printf("%s:%d pin %p\n", __FILE__, __LINE__, node_v);
node=node_v;
assert(node->fullhash==fullhash);
verify_local_fingerprint(node);
if (node->height>0) {
int i;
......@@ -138,7 +140,7 @@ int toku_verify_brtnode (BRT brt, DISKOFF off, bytevec lorange, ITEMLEN lolen, b
LEAFENTRY prev=0;
toku_omt_iterate(node->u.l.buffer, check_increasing, &prev);
}
if ((r = toku_cachetable_unpin(brt->cf, off, 0, 0))) return r;
if ((r = toku_cachetable_unpin(brt->cf, off, fullhash, 0, 0))) return r;
return result;
}
......
......@@ -184,9 +184,9 @@ void toku_brtnode_flush_callback (CACHEFILE cachefile, DISKOFF nodename, void *b
//printf("%s:%d n_items_malloced=%lld\n", __FILE__, __LINE__, n_items_malloced);
}
int toku_brtnode_fetch_callback (CACHEFILE cachefile, DISKOFF nodename, void **brtnode_pv, long *sizep, void*UU(extraargs), LSN *written_lsn) {
int toku_brtnode_fetch_callback (CACHEFILE cachefile, DISKOFF nodename, u_int32_t fullhash, void **brtnode_pv, long *sizep, void*UU(extraargs), LSN *written_lsn) {
BRTNODE *result=(BRTNODE*)brtnode_pv;
int r = toku_deserialize_brtnode_from(toku_cachefile_fd(cachefile), nodename, result);
int r = toku_deserialize_brtnode_from(toku_cachefile_fd(cachefile), nodename, fullhash, result);
if (r == 0) {
*sizep = brtnode_memory_size(*result);
*written_lsn = (*result)->disk_lsn;
......@@ -223,11 +223,11 @@ void toku_brtheader_flush_callback (CACHEFILE cachefile, DISKOFF nodename, void
}
}
int toku_brtheader_fetch_callback (CACHEFILE cachefile, DISKOFF nodename, void **headerp_v, long *sizep __attribute__((unused)), void*extraargs __attribute__((__unused__)), LSN *written_lsn) {
int toku_brtheader_fetch_callback (CACHEFILE cachefile, DISKOFF nodename, u_int32_t fullhash, void **headerp_v, long *sizep __attribute__((unused)), void*extraargs __attribute__((__unused__)), LSN *written_lsn) {
int r;
struct brt_header **h = (struct brt_header **)headerp_v;
assert(nodename==0);
if ((r = toku_deserialize_brtheader_from(toku_cachefile_fd(cachefile), nodename, h))) return r;
if ((r = toku_deserialize_brtheader_from(toku_cachefile_fd(cachefile), nodename, fullhash, h))) return r;
if ((r = toku_deserialize_fifo_at(toku_cachefile_fd(cachefile), (*h)->unused_memory, &(*h)->fifo))) return r;
//printf("%s:%d fifo=%p\nn", __FILE__, __LINE__, (*h)->fifo);
written_lsn->lsn = 0; // !!! WRONG. This should be stored or kept redundantly or something.
......@@ -238,17 +238,21 @@ int toku_brtheader_fetch_callback (CACHEFILE cachefile, DISKOFF nodename, void *
int toku_read_and_pin_brt_header (CACHEFILE cf, struct brt_header **header) {
void *header_p;
//fprintf(stderr, "%s:%d read_and_pin_brt_header(...)\n", __FILE__, __LINE__);
int r = toku_cachetable_get_and_pin(cf, 0, &header_p, NULL,
u_int32_t fullhash = toku_cachefile_fullhash_of_header(cf);
//assert(fullhash==toku_cachetable_hash(cf, 0));
int r = toku_cachetable_get_and_pin(cf, 0, fullhash, &header_p, NULL,
toku_brtheader_flush_callback, toku_brtheader_fetch_callback, 0);
if (r!=0) return r;
*header = header_p;
struct brt_header *bheader = header_p;
assert(bheader->fullhash==fullhash);
*header = bheader;
return 0;
}
int toku_unpin_brt_header (BRT brt) {
int dirty = brt->h->dirty;
brt->h->dirty=0; // Unpinning it may make it go way.
int r = toku_cachetable_unpin(brt->cf, 0, dirty, 0);
int r = toku_cachetable_unpin(brt->cf, 0, brt->h->fullhash, dirty, 0);
brt->h=0;
return r;
}
......@@ -259,7 +263,7 @@ int toku_unpin_brtnode (BRT brt, BRTNODE node) {
// //if (node->log_lsn.lsn>33320) printf("%s:%d node%lld lsn=%lld\n", __FILE__, __LINE__, node->thisnodename, node->log_lsn.lsn);
// }
VERIFY_NODE(node);
return toku_cachetable_unpin(brt->cf, node->thisnodename, node->dirty, brtnode_memory_size(node));
return toku_cachetable_unpin(brt->cf, node->thisnodename, node->fullhash, node->dirty, brtnode_memory_size(node));
}
typedef struct kvpair {
......@@ -372,7 +376,10 @@ int toku_create_new_brtnode (BRT t, BRTNODE *result, int height, TOKULOGGER logg
assert(n->nodesize>0);
// n->brt = t;
//printf("%s:%d putting %p (%lld)\n", __FILE__, __LINE__, n, n->thisnodename);
r=toku_cachetable_put(t->cf, n->thisnodename, n, brtnode_memory_size(n),
u_int32_t fullhash = toku_cachetable_hash(t->cf, n->thisnodename);
n->fullhash = fullhash;
r=toku_cachetable_put(t->cf, n->thisnodename, fullhash,
n, brtnode_memory_size(n),
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, t);
assert(r==0);
return 0;
......@@ -990,7 +997,8 @@ static int push_some_brt_cmds_down (BRT t, BRTNODE node, int childnum,
assert(node->height>0);
DISKOFF targetchild = BNC_DISKOFF(node, childnum);
assert(targetchild>=0 && targetchild<t->h->unused_memory); // This assertion could fail in a concurrent setting since another process might have bumped unused memory.
r = toku_cachetable_get_and_pin(t->cf, targetchild, &childnode_v, NULL,
u_int32_t childfullhash = toku_cachetable_hash(t->cf, targetchild);
r = toku_cachetable_get_and_pin(t->cf, targetchild, childfullhash, &childnode_v, NULL,
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, t);
if (r!=0) return r;
//printf("%s:%d pin %p\n", __FILE__, __LINE__, childnode_v);
......@@ -1620,10 +1628,12 @@ static int brt_nonleaf_put_cmd_child_node (BRT t, BRTNODE node, BRT_CMD cmd,
*did_split = 0;
DISKOFF childdiskoff=BNC_DISKOFF(node, childnum);
u_int32_t fullhash = toku_cachetable_hash(t->cf, childdiskoff);
if (maybe)
r = toku_cachetable_maybe_get_and_pin(t->cf, BNC_DISKOFF(node, childnum), &child_v);
r = toku_cachetable_maybe_get_and_pin(t->cf, childdiskoff, fullhash, &child_v);
else
r = toku_cachetable_get_and_pin(t->cf, BNC_DISKOFF(node, childnum), &child_v, NULL,
r = toku_cachetable_get_and_pin(t->cf, childdiskoff, fullhash, &child_v, NULL,
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, t);
if (r != 0)
return r;
......@@ -1895,7 +1905,10 @@ static int setup_initial_brt_root_node (BRT t, DISKOFF offset, TOKULOGGER logger
printf("%s:%d put root at %lld\n", __FILE__, __LINE__, offset);
}
//printf("%s:%d putting %p (%lld)\n", __FILE__, __LINE__, node, node->thisnodename);
r=toku_cachetable_put(t->cf, offset, node, brtnode_memory_size(node),
u_int32_t fullhash = toku_cachetable_hash(t->cf, offset);
node->fullhash = fullhash;
r=toku_cachetable_put(t->cf, offset, fullhash,
node, brtnode_memory_size(node),
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, t);
if (r!=0) {
toku_free(node);
......@@ -2033,7 +2046,7 @@ int toku_brt_open(BRT t, const char *fname, const char *fname_in_env, const char
//printf("%s:%d %d alloced\n", __FILE__, __LINE__, get_n_items_malloced()); toku_print_malloced_items();
if (0) {
died_after_read_and_pin:
toku_cachetable_unpin(t->cf, 0, 0, 0); // unpin the header
toku_cachetable_unpin(t->cf, 0, toku_cachefile_fullhash_of_header(t->cf), 0, 0); // unpin the header
goto died1;
}
if (is_create) {
......@@ -2085,7 +2098,9 @@ int toku_brt_open(BRT t, const char *fname, const char *fname_in_env, const char
}
if ((r=setup_initial_brt_root_node(t, t->nodesize, toku_txn_logger(txn)))!=0) { goto died6; }
//printf("%s:%d putting %p (%d)\n", __FILE__, __LINE__, t->h, 0);
if ((r=toku_cachetable_put(t->cf, 0, t->h, 0, toku_brtheader_flush_callback, toku_brtheader_fetch_callback, 0))) { goto died6; }
u_int32_t fullhash = toku_cachefile_fullhash_of_header(t->cf);//toku_cachetable_hash(t->cf, 0);
t->h->fullhash = fullhash;
if ((r=toku_cachetable_put(t->cf, 0, fullhash, t->h, 0, toku_brtheader_flush_callback, toku_brtheader_fetch_callback, 0))) { goto died6; }
}
else if (r!=0) {
goto died_after_read_and_pin;
......@@ -2332,7 +2347,9 @@ static int brt_init_new_root(BRT brt, BRTNODE nodea, BRTNODE nodeb, DBT splitk,
r = toku_unpin_brtnode(brt, nodeb);
if (r!=0) return r;
//printf("%s:%d put %lld\n", __FILE__, __LINE__, newroot_diskoff);
toku_cachetable_put(brt->cf, newroot_diskoff, newroot, brtnode_memory_size(newroot),
u_int32_t fullhash = toku_cachetable_hash(brt->cf, newroot_diskoff);
newroot->fullhash = fullhash;
toku_cachetable_put(brt->cf, newroot_diskoff, fullhash, newroot, brtnode_memory_size(newroot),
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt);
*newrootp = newroot;
return 0;
......@@ -2352,7 +2369,7 @@ int toku_cachefile_root_put_cmd (CACHEFILE cf, BRT_CMD cmd, TOKULOGGER logger) {
if (r!=0) return r;
}
h->dirty = 0;
r = toku_cachetable_unpin(cf, 0, 1, 0);
r = toku_cachetable_unpin(cf, 0, h->fullhash, 1, 0);
return 0;
}
......@@ -2394,12 +2411,14 @@ int toku_brt_root_put_cmd(BRT brt, BRT_CMD cmd, TOKULOGGER logger) {
}
brt->h->root_put_counter = global_root_put_counter++;
rootp = toku_calculate_root_offset_pointer(brt);
if ((r=toku_cachetable_get_and_pin(brt->cf, *rootp, &node_v, NULL,
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt))) {
u_int32_t fullhash = toku_cachetable_hash(brt->cf, *rootp);
if ((r=toku_cachetable_get_and_pin(brt->cf, *rootp, fullhash, &node_v, NULL,
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt))) {
goto died0;
}
//printf("%s:%d pin %p\n", __FILE__, __LINE__, node_v);
node=node_v;
assert(node->fullhash==fullhash);
// push the fifo stuff
{
DBT okey,odata;
......@@ -2487,11 +2506,14 @@ int toku_dump_brtnode (BRT brt, DISKOFF off, int depth, bytevec lorange, ITEMLEN
int result=0;
BRTNODE node;
void *node_v;
int r = toku_cachetable_get_and_pin(brt->cf, off, &node_v, NULL,
u_int32_t fullhash = toku_cachetable_hash(brt->cf, off);
int r = toku_cachetable_get_and_pin(brt->cf, off, fullhash,
&node_v, NULL,
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt);
assert(r==0);
printf("%s:%d pin %p\n", __FILE__, __LINE__, node_v);
node=node_v;
assert(node->fullhash==fullhash);
result=toku_verify_brtnode(brt, off, lorange, lolen, hirange, hilen, 0);
printf("%*sNode=%p\n", depth, "", node);
if (node->height>0) {
......@@ -2530,7 +2552,7 @@ int toku_dump_brtnode (BRT brt, DISKOFF off, int depth, bytevec lorange, ITEMLEN
// printf(" (%d)%u ", len, *(int*)le_any_key(data)));
printf("\n");
}
r = toku_cachetable_unpin(brt->cf, off, 0, 0);
r = toku_cachetable_unpin(brt->cf, off, fullhash, 0, 0);
assert(r==0);
return result;
}
......@@ -2618,7 +2640,8 @@ static int brt_search_child(BRT brt, BRTNODE node, int childnum, brt_search_t *s
}
void *node_v;
rr = toku_cachetable_get_and_pin(brt->cf, BNC_DISKOFF(node,childnum), &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt);
DISKOFF childdiskoff = BNC_DISKOFF(node,childnum);
rr = toku_cachetable_get_and_pin(brt->cf, childdiskoff, toku_cachetable_hash(brt->cf, childdiskoff), &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt);
assert(rr == 0);
for (;;) {
......@@ -2633,7 +2656,7 @@ static int brt_search_child(BRT brt, BRTNODE node, int childnum, brt_search_t *s
} else {
if (r == EAGAIN)
continue;
rr = toku_cachetable_unpin(brt->cf, childnode->thisnodename, childnode->dirty, brtnode_memory_size(childnode));
rr = toku_cachetable_unpin(brt->cf, childnode->thisnodename, childnode->fullhash, childnode->dirty, brtnode_memory_size(childnode));
assert(rr == 0);
break;
}
......@@ -2813,7 +2836,8 @@ int toku_brt_search(BRT brt, brt_search_t *search, DBT *newkey, DBT *newval, TOK
CACHEKEY *rootp = toku_calculate_root_offset_pointer(brt);
void *node_v;
rr = toku_cachetable_get_and_pin(brt->cf, *rootp, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt);
rr = toku_cachetable_get_and_pin(brt->cf, *rootp, toku_cachetable_hash(brt->cf, *rootp),
&node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt);
assert(rr == 0);
BRTNODE node = node_v;
......@@ -3359,9 +3383,12 @@ static void toku_brt_keyrange_internal (BRT brt, CACHEKEY nodename, DBT *key, u_
BRTNODE node;
{
void *node_v;
int rr = toku_cachetable_get_and_pin(brt->cf, nodename, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt);
u_int32_t fullhash = toku_cachetable_hash(brt->cf, nodename);
int rr = toku_cachetable_get_and_pin(brt->cf, nodename, fullhash,
&node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt);
assert(rr == 0);
node = node_v;
assert(node->fullhash==fullhash);
}
if (node->height>0) {
int n_keys = node->u.n.n_children-1;
......@@ -3460,7 +3487,7 @@ int toku_brt_height_of_root(BRT brt, int *height) {
}
CACHEKEY *rootp = toku_calculate_root_offset_pointer(brt);
void *node_v;
if ((r=toku_cachetable_get_and_pin(brt->cf, *rootp, &node_v, NULL,
if ((r=toku_cachetable_get_and_pin(brt->cf, *rootp, toku_cachetable_hash(brt->cf, *rootp), &node_v, NULL,
toku_brtnode_flush_callback, toku_brtnode_fetch_callback, brt))) {
goto died0;
}
......
......@@ -26,7 +26,7 @@ void print_item (bytevec val, ITEMLEN len) {
void dump_header (int f, struct brt_header **header) {
struct brt_header *h;
int r;
r = toku_deserialize_brtheader_from (f, 0, &h); assert(r==0);
r = toku_deserialize_brtheader_from (f, 0, 0/*pass 0 for hash. It doesn't matter.*/, &h); assert(r==0);
printf("brtheader:\n");
if (h->layout_version==BRT_LAYOUT_VERSION_6) printf(" layout_version<=6\n");
else printf(" layout_version=%d\n", h->layout_version);
......@@ -78,7 +78,7 @@ void dump_header (int f, struct brt_header **header) {
void dump_node (int f, DISKOFF off) {
BRTNODE n;
int r = toku_deserialize_brtnode_from (f, off, &n);
int r = toku_deserialize_brtnode_from (f, off, 0 /*pass zero for hash, it doesn't matter*/, &n);
assert(r==0);
assert(n!=0);
printf("brtnode\n");
......
......@@ -39,6 +39,7 @@ struct ctpair {
int verify_flag; /* Used in verify_cachetable() */
LSN modified_lsn; // What was the LSN when modified (undefined if not dirty)
LSN written_lsn; // What was the LSN when written (we need to get this information when we fetch)
u_int32_t fullhash;
};
// The cachetable is as close to an ENV as we get.
......@@ -61,6 +62,7 @@ struct fileid {
struct cachefile {
CACHEFILE next;
u_int32_t header_fullhash;
u_int64_t refcount; /* CACHEFILEs are shared. Use a refcount to decide when to really close it.
* The reference count is one for every open DB.
* Plus one for every commit/rollback record. (It would be harder to keep a count for every open transaction,
......@@ -144,6 +146,7 @@ int toku_cachetable_openfd (CACHEFILE *cf, CACHETABLE t, int fd, const char *fna
{
CACHEFILE MALLOC(newcf);
newcf->filenum.fileid = next_filenum_to_use.fileid++;
newcf->header_fullhash = toku_cachetable_hash(newcf, 0);
newcf->next = t->cachefiles;
newcf->refcount = 1;
newcf->fd = fd;
......@@ -265,26 +268,18 @@ static inline u_int32_t final (u_int32_t a, u_int32_t b, u_int32_t c) {
return c;
}
u_int32_t toku_cachetable_hash (CACHEFILE cachefile, CACHEKEY key)
// Effect: Return a 32-bit hash key. The hash key shall be suitable for using with bitmasking for a table of size power-of-two.
{
return final(cachefile->filenum.fileid, (u_int32_t)(key>>32), (u_int32_t)key);
}
#if 0
static unsigned int hashit (CACHETABLE t, CACHEKEY key, CACHEFILE cachefile) {
if (0) {
unsigned int h1;
if (0) {
h1 = hash_key((unsigned char*)&key, sizeof(key));
h1 = hash_key_extend(h1, (unsigned char*)&cachefile->filenum, sizeof(cachefile->filenum));
h1 = hash_key_extend(h1, (unsigned char*)&cachefile, sizeof(cachefile));
} else {
unsigned long long k = (unsigned long long) key;
u_int32_t f = cachefile->filenum.fileid;
h1 = k >> 32;
h1 = (h1 * 16777619) ^ (k & 0xffffffff);
h1 = (h1 * 16777619) ^ f;
}
return h1%t->table_size;
} else {
assert(0==(t->table_size & (t->table_size -1))); // make sure table is power of two
return (final(cachefile->filenum.fileid, (u_int32_t)(key>>32), (u_int32_t)key))&(t->table_size-1);
}
assert(0==(t->table_size & (t->table_size -1))); // make sure table is power of two
return (toku_cachetable_hash(key,cachefile))&(t->table_size-1);
}
#endif
static void cachetable_rehash (CACHETABLE t, u_int32_t newtable_size) {
// printf("rehash %p %d %d %d\n", t, primeindexdelta, t->n_in_table, t->table_size);
......@@ -300,7 +295,7 @@ static void cachetable_rehash (CACHETABLE t, u_int32_t newtable_size) {
for (i=0; i<oldtable_size; i++) {
PAIR p;
while ((p=t->table[i])!=0) {
unsigned int h = hashit(t, p->key, p->cachefile);
unsigned int h = p->fullhash&(newtable_size-1);
t->table[i] = p->hash_chain;
p->hash_chain = newtable[h];
newtable[h] = p;
......@@ -376,7 +371,7 @@ static void flush_and_remove (CACHETABLE t, PAIR remove_me, int write_me) {
t->n_in_table--;
// Remove it from the hash chain.
{
unsigned int h = hashit(t, remove_me->key, remove_me->cachefile);
unsigned int h = remove_me->fullhash&(t->table_size-1);
t->table[h] = remove_from_hash_chain (remove_me, t->table[h]);
}
t->size_current -= remove_me->size;
......@@ -433,12 +428,13 @@ again:
return r;
}
static int cachetable_insert_at(CACHEFILE cachefile, int h, CACHEKEY key, void *value, long size,
static int cachetable_insert_at(CACHEFILE cachefile, u_int32_t fullhash, CACHEKEY key, void *value, long size,
cachetable_flush_func_t flush_callback,
cachetable_fetch_func_t fetch_callback,
void *extraargs, int dirty,
LSN written_lsn) {
TAGMALLOC(PAIR, p);
p->fullhash = fullhash;
p->pinned = 1;
p->dirty = dirty;
p->size = size;
......@@ -452,8 +448,10 @@ static int cachetable_insert_at(CACHEFILE cachefile, int h, CACHEKEY key, void *
p->extraargs = extraargs;
p->modified_lsn.lsn = 0;
p->written_lsn = written_lsn;
p->fullhash = fullhash;
CACHETABLE ct = cachefile->cachetable;
lru_add_to_list(ct, p);
u_int32_t h = fullhash & (ct->table_size-1);
p->hash_chain = ct->table[h];
ct->table[h] = p;
ct->n_in_table++;
......@@ -478,13 +476,13 @@ void note_hash_count (int count) {
hash_histogram[count]++;
}
int toku_cachetable_put(CACHEFILE cachefile, CACHEKEY key, void*value, long size,
cachetable_flush_func_t flush_callback, cachetable_fetch_func_t fetch_callback, void *extraargs) {
int toku_cachetable_put(CACHEFILE cachefile, CACHEKEY key, u_int32_t fullhash, void*value, long size,
cachetable_flush_func_t flush_callback, cachetable_fetch_func_t fetch_callback, void *extraargs) {
WHEN_TRACE_CT(printf("%s:%d CT cachetable_put(%lld)=%p\n", __FILE__, __LINE__, key, value));
int count=0;
{
PAIR p;
for (p=cachefile->cachetable->table[hashit(cachefile->cachetable, key, cachefile)]; p; p=p->hash_chain) {
for (p=cachefile->cachetable->table[fullhash&(cachefile->cachetable->table_size-1)]; p; p=p->hash_chain) {
count++;
if (p->key==key && p->cachefile==cachefile) {
note_hash_count(count);
......@@ -501,18 +499,18 @@ int toku_cachetable_put(CACHEFILE cachefile, CACHEKEY key, void*value, long size
int r;
note_hash_count(count);
if ((r=maybe_flush_some(cachefile->cachetable, size))) return r;
// flushing could change the result from hashit()
r = cachetable_insert_at(cachefile, hashit(cachefile->cachetable, key, cachefile), key, value, size, flush_callback, fetch_callback, extraargs, 1, ZERO_LSN);
// flushing could change the table size, but wont' change the fullhash
r = cachetable_insert_at(cachefile, fullhash, key, value, size, flush_callback, fetch_callback, extraargs, 1, ZERO_LSN);
return r;
}
int toku_cachetable_get_and_pin(CACHEFILE cachefile, CACHEKEY key, void**value, long *sizep,
int toku_cachetable_get_and_pin(CACHEFILE cachefile, CACHEKEY key, u_int32_t fullhash, void**value, long *sizep,
cachetable_flush_func_t flush_callback, cachetable_fetch_func_t fetch_callback, void *extraargs) {
CACHETABLE t = cachefile->cachetable;
int tsize __attribute__((__unused__)) = t->table_size;
PAIR p;
int count=0;
for (p=t->table[hashit(t,key,cachefile)]; p; p=p->hash_chain) {
for (p=t->table[fullhash&(t->table_size-1)]; p; p=p->hash_chain) {
count++;
if (p->key==key && p->cachefile==cachefile) {
note_hash_count(count);
......@@ -526,16 +524,16 @@ int toku_cachetable_get_and_pin(CACHEFILE cachefile, CACHEKEY key, void**value,
}
note_hash_count(count);
int r;
// Note. hashit(t,key) may have changed as a result of flushing.
// Note. hashit(t,key) may have changed as a result of flushing. But fullhash won't have changed.
{
void *toku_value;
long size = 1; // compat
LSN written_lsn;
WHEN_TRACE_CT(printf("%s:%d CT: fetch_callback(%lld...)\n", __FILE__, __LINE__, key));
if ((r=fetch_callback(cachefile, key, &toku_value, &size, extraargs, &written_lsn))) {
if ((r=fetch_callback(cachefile, key, fullhash, &toku_value, &size, extraargs, &written_lsn))) {
return r;
}
cachetable_insert_at(cachefile, hashit(t,key,cachefile), key, toku_value, size, flush_callback, fetch_callback, extraargs, 0, written_lsn);
cachetable_insert_at(cachefile, fullhash, key, toku_value, size, flush_callback, fetch_callback, extraargs, 0, written_lsn);
*value = toku_value;
if (sizep)
*sizep = size;
......@@ -546,11 +544,11 @@ int toku_cachetable_get_and_pin(CACHEFILE cachefile, CACHEKEY key, void**value,
return 0;
}
int toku_cachetable_maybe_get_and_pin (CACHEFILE cachefile, CACHEKEY key, void**value) {
int toku_cachetable_maybe_get_and_pin (CACHEFILE cachefile, CACHEKEY key, u_int32_t fullhash, void**value) {
CACHETABLE t = cachefile->cachetable;
PAIR p;
int count = 0;
for (p=t->table[hashit(t,key,cachefile)]; p; p=p->hash_chain) {
for (p=t->table[fullhash&(t->table_size-1)]; p; p=p->hash_chain) {
count++;
if (p->key==key && p->cachefile==cachefile) {
note_hash_count(count);
......@@ -566,13 +564,14 @@ int toku_cachetable_maybe_get_and_pin (CACHEFILE cachefile, CACHEKEY key, void**
}
int toku_cachetable_unpin(CACHEFILE cachefile, CACHEKEY key, int dirty, long size) {
int toku_cachetable_unpin(CACHEFILE cachefile, CACHEKEY key, u_int32_t fullhash, int dirty, long size) {
CACHETABLE t = cachefile->cachetable;
PAIR p;
WHEN_TRACE_CT(printf("%s:%d unpin(%lld)", __FILE__, __LINE__, key));
//printf("%s:%d is dirty now=%d\n", __FILE__, __LINE__, dirty);
int count = 0;
for (p=t->table[hashit(t,key,cachefile)]; p; p=p->hash_chain) {
//assert(fullhash == toku_cachetable_hash(cachefile, key));
for (p=t->table[fullhash&(t->table_size-1)]; p; p=p->hash_chain) {
count++;
if (p->key==key && p->cachefile==cachefile) {
note_hash_count(count);
......@@ -602,7 +601,8 @@ int toku_cachetable_rename (CACHEFILE cachefile, CACHEKEY oldkey, CACHEKEY newke
CACHETABLE t = cachefile->cachetable;
PAIR *ptr_to_p,p;
int count = 0;
for (ptr_to_p = &t->table[hashit(t, oldkey,cachefile)], p = *ptr_to_p;
u_int32_t fullhash = toku_cachetable_hash(cachefile, oldkey);
for (ptr_to_p = &t->table[fullhash&(t->table_size-1)], p = *ptr_to_p;
p;
ptr_to_p = &p->hash_chain, p = *ptr_to_p) {
count++;
......@@ -610,7 +610,9 @@ int toku_cachetable_rename (CACHEFILE cachefile, CACHEKEY oldkey, CACHEKEY newke
note_hash_count(count);
*ptr_to_p = p->hash_chain;
p->key = newkey;
int nh = hashit(t, newkey, cachefile);
u_int32_t new_fullhash = toku_cachetable_hash(cachefile, newkey);
u_int32_t nh = new_fullhash&(t->table_size-1);
p->fullhash = new_fullhash;
p->hash_chain = t->table[nh];
t->table[nh] = p;
return 0;
......@@ -651,7 +653,9 @@ void toku_cachetable_verify (CACHETABLE t) {
for (p=t->head; p; p=p->next) {
assert(p->verify_flag==0);
PAIR p2;
for (p2=t->table[hashit(t,p->key, p->cachefile)]; p2; p2=p2->hash_chain) {
u_int32_t fullhash = p->fullhash;
//assert(fullhash==toku_cachetable_hash(p->cachefile, p->key));
for (p2=t->table[fullhash&(t->table_size-1)]; p2; p2=p2->hash_chain) {
if (p2==p) {
/* found it */
goto next;
......@@ -740,7 +744,8 @@ int toku_cachetable_remove (CACHEFILE cachefile, CACHEKEY key, int write_me) {
CACHETABLE t = cachefile->cachetable;
PAIR p;
int count = 0;
for (p=t->table[hashit(t,key, cachefile)]; p; p=p->hash_chain) {
u_int32_t fullhash = toku_cachetable_hash(cachefile, key);
for (p=t->table[fullhash&(t->table_size-1)]; p; p=p->hash_chain) {
count++;
if (p->key==key && p->cachefile==cachefile) {
flush_and_remove(t, p, write_me);
......@@ -834,7 +839,8 @@ int toku_cachetable_get_key_state (CACHETABLE ct, CACHEKEY key, CACHEFILE cf, vo
int *dirty_ptr, long long *pin_ptr, long *size_ptr) {
PAIR p;
int count = 0;
for (p = ct->table[hashit(ct, key, cf)]; p; p = p->hash_chain) {
u_int32_t fullhash = toku_cachetable_hash(cf, key);
for (p = ct->table[fullhash&(ct->table_size-1)]; p; p = p->hash_chain) {
count++;
if (p->key == key) {
note_hash_count(count);
......@@ -904,3 +910,7 @@ TOKULOGGER toku_cachefile_logger (CACHEFILE cf) {
FILENUM toku_cachefile_filenum (CACHEFILE cf) {
return cf->filenum;
}
u_int32_t toku_cachefile_fullhash_of_header (CACHEFILE cachefile) {
return cachefile->header_fullhash;
}
......@@ -32,25 +32,27 @@ typedef void (cachetable_flush_func_t)(CACHEFILE, CACHEKEY key, void*value, long
typedef cachetable_flush_func_t *CACHETABLE_FLUSH_FUNC_T;
/* If we are asked to fetch something, get it by calling this back. */
typedef int (cachetable_fetch_func_t)(CACHEFILE, CACHEKEY key, void **value, long *sizep, void *extraargs, LSN *written_lsn);
typedef int (cachetable_fetch_func_t)(CACHEFILE, CACHEKEY key, u_int32_t fullhash, void **value, long *sizep, void *extraargs, LSN *written_lsn);
typedef cachetable_fetch_func_t *CACHETABLE_FETCH_FUNC_T;
/* Error if already present. On success, pin the value. */
int toku_cachetable_put(CACHEFILE cf, CACHEKEY key, void* value, long size,
int toku_cachetable_put(CACHEFILE cf, CACHEKEY key, u_int32_t fullhash,
void* value, long size,
cachetable_flush_func_t flush_callback, cachetable_fetch_func_t fetch_callback, void *extraargs);
int toku_cachetable_get_and_pin(CACHEFILE, CACHEKEY, void**/*value*/, long *sizep,
int toku_cachetable_get_and_pin(CACHEFILE, CACHEKEY, u_int32_t /*fullhash*/,
void**/*value*/, long *sizep,
cachetable_flush_func_t flush_callback, cachetable_fetch_func_t fetch_callback, void *extraargs);
/* If the the item is already in memory, then return 0 and store it in the void**.
* If the item is not in memory, then return nonzero. */
int toku_cachetable_maybe_get_and_pin (CACHEFILE, CACHEKEY, void**);
int toku_cachetable_maybe_get_and_pin (CACHEFILE, CACHEKEY, u_int32_t /*fullhash*/, void**);
/* cachetable object state wrt external memory */
#define CACHETABLE_CLEAN 0
#define CACHETABLE_DIRTY 1
int toku_cachetable_unpin(CACHEFILE, CACHEKEY, int dirty, long size); /* Note whether it is dirty when we unpin it. */
int toku_cachetable_unpin(CACHEFILE, CACHEKEY, u_int32_t fullhash, int dirty, long size); /* Note whether it is dirty when we unpin it. */
int toku_cachetable_remove (CACHEFILE, CACHEKEY, int /*write_me*/); /* Removing something already present is OK. */
int toku_cachetable_assert_all_unpinned (CACHETABLE);
int toku_cachefile_count_pinned (CACHEFILE, int /*printthem*/ );
......@@ -90,4 +92,9 @@ int toku_cachefile_of_filenum (CACHETABLE t, FILENUM filenum, CACHEFILE *cf);
int toku_cachetable_checkpoint (CACHETABLE ct);
u_int32_t toku_cachetable_hash (CACHEFILE cachefile, CACHEKEY key);
// Effect: Return a 32-bit hash key. The hash key shall be suitable for using with bitmasking for a table of size power-of-two.
u_int32_t toku_cachefile_fullhash_of_header (CACHEFILE cachefile);
#endif
......@@ -147,7 +147,9 @@ static void toku_recover_fheader (LSN UU(lsn), TXNID UU(txnid),FILENUM filenum,L
} else {
assert(0);
}
toku_cachetable_put(pair->cf, 0, h, 0, toku_brtheader_flush_callback, toku_brtheader_fetch_callback, 0);
u_int32_t fullhash = toku_cachetable_hash(pair->cf, 0);
h->fullhash = fullhash;
toku_cachetable_put(pair->cf, 0, fullhash, h, 0, toku_brtheader_flush_callback, toku_brtheader_fetch_callback, 0);
if (pair->brt) {
toku_free(pair->brt->h);
} else {
......@@ -203,12 +205,14 @@ void toku_recover_newbrtnode (LSN lsn, FILENUM filenum,DISKOFF diskoff,u_int32_t
MALLOC_N(2,n->u.n.childkeys);
}
// Now put it in the cachetable
toku_cachetable_put(pair->cf, diskoff, n, toku_serialize_brtnode_size(n), toku_brtnode_flush_callback, toku_brtnode_fetch_callback, 0);
u_int32_t fullhash = toku_cachetable_hash(pair->cf, diskoff);
n->fullhash = fullhash;
toku_cachetable_put(pair->cf, diskoff, fullhash, n, toku_serialize_brtnode_size(n), toku_brtnode_flush_callback, toku_brtnode_fetch_callback, 0);
VERIFY_COUNTS(n);
n->log_lsn = lsn;
r = toku_cachetable_unpin(pair->cf, diskoff, 1, toku_serialize_brtnode_size(n));
r = toku_cachetable_unpin(pair->cf, diskoff, fullhash, 1, toku_serialize_brtnode_size(n));
assert(r==0);
}
......@@ -218,9 +222,12 @@ static void recover_setup_node (FILENUM filenum, DISKOFF diskoff, CACHEFILE *cf,
assert(r==0);
assert(pair->brt);
void *node_v;
r = toku_cachetable_get_and_pin(pair->cf, diskoff, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
u_int32_t fullhash = toku_cachetable_hash(pair->cf, diskoff);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, fullhash,
&node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
assert(r==0);
BRTNODE node = node_v;
assert(fullhash==node->fullhash);
*resultnode = node;
*cf = pair->cf;
}
......@@ -230,7 +237,9 @@ static void toku_recover_deqrootentry (LSN lsn __attribute__((__unused__)), FILE
int r = find_cachefile(filenum, &pair);
assert(r==0);
void *h_v;
r = toku_cachetable_get_and_pin(pair->cf, 0, &h_v, NULL, toku_brtheader_flush_callback, toku_brtheader_fetch_callback, 0);
u_int32_t fullhash = toku_cachetable_hash(pair->cf, 0);
r = toku_cachetable_get_and_pin(pair->cf, 0, fullhash,
&h_v, NULL, toku_brtheader_flush_callback, toku_brtheader_fetch_callback, 0);
assert(r==0);
struct brt_header *h=h_v;
bytevec storedkey,storeddata;
......@@ -241,7 +250,7 @@ static void toku_recover_deqrootentry (LSN lsn __attribute__((__unused__)), FILE
assert(r==0);
r = toku_fifo_deq(h->fifo);
assert(r==0);
r = toku_cachetable_unpin(pair->cf, 0, 1, 0);
r = toku_cachetable_unpin(pair->cf, 0, fullhash, 1, 0);
assert(r==0);
}
......@@ -250,12 +259,13 @@ void toku_recover_enqrootentry (LSN lsn __attribute__((__unused__)), FILENUM fil
int r = find_cachefile(filenum, &pair);
assert(r==0);
void *h_v;
r = toku_cachetable_get_and_pin(pair->cf, 0, &h_v, NULL, toku_brtheader_flush_callback, toku_brtheader_fetch_callback, 0);
u_int32_t fullhash = toku_cachetable_hash(pair->cf, 0);
r = toku_cachetable_get_and_pin(pair->cf, 0, fullhash, &h_v, NULL, toku_brtheader_flush_callback, toku_brtheader_fetch_callback, 0);
assert(r==0);
struct brt_header *h=h_v;
r = toku_fifo_enq(h->fifo, key.data, key.len, val.data, val.len, typ, xid);
assert(r==0);
r = toku_cachetable_unpin(pair->cf, 0, 1, 0);
r = toku_cachetable_unpin(pair->cf, 0, fullhash, 1, 0);
assert(r==0);
toku_free(key.data);
toku_free(val.data);
......@@ -281,7 +291,7 @@ void toku_recover_brtdeq (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_int32_t c
node->u.n.n_bytes_in_buffers -= sizediff;
BNC_NBYTESINBUF(node, childnum) -= sizediff;
r = toku_fifo_deq(BNC_BUFFER(node, childnum)); // don't deq till were' done looking at the data.
r = toku_cachetable_unpin(cf, diskoff, 1, toku_serialize_brtnode_size(node));
r = toku_cachetable_unpin(cf, diskoff, node->fullhash, 1, toku_serialize_brtnode_size(node));
assert(r==0);
}
......@@ -297,7 +307,7 @@ void toku_recover_brtenq (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_int32_t c
node->local_fingerprint += node->rand4fingerprint * toku_calccrc32_cmd(typ, xid, key.data, key.len, data.data, data.len);
node->log_lsn = lsn;
u_int32_t sizediff = key.len + data.len + KEY_VALUE_OVERHEAD + BRT_CMD_OVERHEAD;
r = toku_cachetable_unpin(cf, diskoff, 1, toku_serialize_brtnode_size(node));
r = toku_cachetable_unpin(cf, diskoff, node->fullhash, 1, toku_serialize_brtnode_size(node));
assert(r==0);
node->u.n.n_bytes_in_buffers += sizediff;
BNC_NBYTESINBUF(node, childnum) += sizediff;
......@@ -330,7 +340,7 @@ void toku_recover_addchild (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_int32_t
BNC_NBYTESINBUF(node, childnum) = 0;
node->u.n.n_children++;
node->log_lsn = lsn;
r = toku_cachetable_unpin(cf, diskoff, 1, toku_serialize_brtnode_size(node));
r = toku_cachetable_unpin(cf, diskoff, node->fullhash, 1, toku_serialize_brtnode_size(node));
assert(r==0);
}
......@@ -340,10 +350,12 @@ void toku_recover_delchild (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_int32_t
assert(r==0);
void *node_v;
assert(pair->brt);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
u_int32_t fullhash = toku_cachetable_hash(pair->cf, diskoff);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, fullhash, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
assert(r==0);
BRTNODE node = node_v;
assert(node->height>0);
assert(node->fullhash==fullhash);
assert(childnum < (unsigned)node->u.n.n_children);
assert(node->u.n.childinfos[childnum].subtree_fingerprint == childfingerprint);
......@@ -364,7 +376,7 @@ void toku_recover_delchild (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_int32_t
node->u.n.n_children--;
node->log_lsn = lsn;
r = toku_cachetable_unpin(pair->cf, diskoff, 1, toku_serialize_brtnode_size(node));
r = toku_cachetable_unpin(pair->cf, diskoff, node->fullhash, 1, toku_serialize_brtnode_size(node));
assert(r==0);
toku_free(pivotkey.data);
}
......@@ -375,14 +387,16 @@ void toku_recover_setchild (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_int32_t
assert(r==0);
void *node_v;
assert(pair->brt);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
u_int32_t fullhash = toku_cachetable_hash(pair->cf, diskoff);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, fullhash, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
assert(r==0);
BRTNODE node = node_v;
assert(node->fullhash == fullhash);
assert(node->height>0);
assert(childnum < (unsigned)node->u.n.n_children);
BNC_DISKOFF(node, childnum) = newchild;
node->log_lsn = lsn;
r = toku_cachetable_unpin(pair->cf, diskoff, 1, toku_serialize_brtnode_size(node));
r = toku_cachetable_unpin(pair->cf, diskoff, node->fullhash, 1, toku_serialize_brtnode_size(node));
assert(r==0);
}
void toku_recover_setpivot (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_int32_t childnum, BYTESTRING pivotkey) {
......@@ -391,9 +405,11 @@ void toku_recover_setpivot (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_int32_t
assert(r==0);
void *node_v;
assert(pair->brt);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
u_int32_t fullhash = toku_cachetable_hash(pair->cf, diskoff);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, fullhash, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
assert(r==0);
BRTNODE node = node_v;
assert(node->fullhash==fullhash);
assert(node->height>0);
struct kv_pair *new_pivot = kv_pair_malloc(pivotkey.data, pivotkey.len, 0, 0);
......@@ -402,7 +418,7 @@ void toku_recover_setpivot (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_int32_t
node->u.n.totalchildkeylens += toku_brt_pivot_key_len(pair->brt, node->u.n.childkeys[childnum]);
node->log_lsn = lsn;
r = toku_cachetable_unpin(pair->cf, diskoff, 1, toku_serialize_brtnode_size(node));
r = toku_cachetable_unpin(pair->cf, diskoff, node->fullhash, 1, toku_serialize_brtnode_size(node));
assert(r==0);
toku_free(pivotkey.data);
......@@ -414,14 +430,16 @@ void toku_recover_changechildfingerprint (LSN lsn, FILENUM filenum, DISKOFF disk
assert(r==0);
void *node_v;
assert(pair->brt);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
u_int32_t fullhash = toku_cachetable_hash(pair->cf, diskoff);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, fullhash, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
assert(r==0);
BRTNODE node = node_v;
assert(node->fullhash == fullhash);
assert(node->height>0);
assert((signed)childnum <= node->u.n.n_children); // we allow the childnum to be one too large.
BNC_SUBTREE_FINGERPRINT(node, childnum) = newfingerprint;
node->log_lsn = lsn;
r = toku_cachetable_unpin(pair->cf, diskoff, 1, toku_serialize_brtnode_size(node));
r = toku_cachetable_unpin(pair->cf, diskoff, node->fullhash, 1, toku_serialize_brtnode_size(node));
assert(r==0);
}
......@@ -488,15 +506,18 @@ void toku_recover_leafsplit (LSN lsn, FILENUM filenum, DISKOFF old_diskoff, DISK
int r = find_cachefile(filenum, &pair);
void *nodeA_v;
assert(pair->brt);
r = toku_cachetable_get_and_pin(pair->cf, old_diskoff, &nodeA_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
u_int32_t oldn_fullhash = toku_cachetable_hash(pair->cf, old_diskoff);
r = toku_cachetable_get_and_pin(pair->cf, old_diskoff, oldn_fullhash, &nodeA_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
assert(r==0);
BRTNODE oldn = nodeA_v;
assert(oldn->fullhash==oldn_fullhash);
assert(oldn->height==0);
TAGMALLOC(BRTNODE, newn);
assert(newn);
//printf("%s:%d leafsplit %p (%lld) %p (%lld)\n", __FILE__, __LINE__, oldn, old_diskoff, newn, new_diskoff);
newn->fullhash = toku_cachetable_hash(pair->cf, new_diskoff);
newn->nodesize = new_node_size;
newn->thisnodename = new_diskoff;
newn->log_lsn = newn->disk_lsn = lsn;
......@@ -557,12 +578,13 @@ void toku_recover_leafsplit (LSN lsn, FILENUM filenum, DISKOFF old_diskoff, DISK
toku_verify_all_in_mempool(oldn); toku_verify_counts(oldn);
toku_verify_all_in_mempool(newn); toku_verify_counts(newn);
toku_cachetable_put(pair->cf, new_diskoff, newn, toku_serialize_brtnode_size(newn), toku_brtnode_flush_callback, toku_brtnode_fetch_callback, 0);
toku_cachetable_put(pair->cf, new_diskoff, newn->fullhash,
newn, toku_serialize_brtnode_size(newn), toku_brtnode_flush_callback, toku_brtnode_fetch_callback, 0);
newn->log_lsn = lsn;
r = toku_cachetable_unpin(pair->cf, new_diskoff, 1, toku_serialize_brtnode_size(newn));
r = toku_cachetable_unpin(pair->cf, new_diskoff, newn->fullhash, 1, toku_serialize_brtnode_size(newn));
assert(r==0);
oldn->log_lsn = lsn;
r = toku_cachetable_unpin(pair->cf, old_diskoff, 1, toku_serialize_brtnode_size(oldn));
r = toku_cachetable_unpin(pair->cf, old_diskoff, oldn->fullhash, 1, toku_serialize_brtnode_size(oldn));
assert(r==0);
}
......@@ -572,9 +594,11 @@ void toku_recover_insertleafentry (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_
assert(r==0);
void *node_v;
assert(pair->brt);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
u_int32_t fullhash = toku_cachetable_hash(pair->cf, diskoff);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, fullhash, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
assert(r==0);
BRTNODE node = node_v;
assert(node->fullhash==fullhash);
assert(node->height==0);
VERIFY_COUNTS(node);
node->log_lsn = lsn;
......@@ -588,7 +612,7 @@ void toku_recover_insertleafentry (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_
node->u.l.n_bytes_in_buffer += OMT_ITEM_OVERHEAD + leafentry_disksize(newleafentry);
node->local_fingerprint += node->rand4fingerprint * toku_le_crc(newleafentry);
}
r = toku_cachetable_unpin(pair->cf, diskoff, 1, toku_serialize_brtnode_size(node));
r = toku_cachetable_unpin(pair->cf, diskoff, node->fullhash, 1, toku_serialize_brtnode_size(node));
assert(r==0);
toku_free_LEAFENTRY(newleafentry);
}
......@@ -599,9 +623,11 @@ void toku_recover_deleteleafentry (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_
assert(r==0);
void *node_v;
assert(pair->brt);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
u_int32_t fullhash = toku_cachetable_hash(pair->cf, diskoff);
r = toku_cachetable_get_and_pin(pair->cf, diskoff, fullhash, &node_v, NULL, toku_brtnode_flush_callback, toku_brtnode_fetch_callback, pair->brt);
assert(r==0);
BRTNODE node = node_v;
assert(node->fullhash==fullhash);
assert(node->height==0);
VERIFY_COUNTS(node);
node->log_lsn = lsn;
......@@ -618,7 +644,7 @@ void toku_recover_deleteleafentry (LSN lsn, FILENUM filenum, DISKOFF diskoff, u_
r = toku_omt_delete_at(node->u.l.buffer, idx);
assert(r==0);
}
r = toku_cachetable_unpin(pair->cf, diskoff, 1, toku_serialize_brtnode_size(node));
r = toku_cachetable_unpin(pair->cf, diskoff, node->fullhash, 1, toku_serialize_brtnode_size(node));
assert(r==0);
}
......
......@@ -55,7 +55,7 @@ static void test_serialize(void) {
toku_serialize_brtnode_to(fd, sn.nodesize*(DISKOFF)20, &sn); assert(r==0);
r = toku_deserialize_brtnode_from(fd, nodesize*(DISKOFF)20, &dn);
r = toku_deserialize_brtnode_from(fd, nodesize*(DISKOFF)20, 0/*pass zero for hash*/, &dn);
assert(r==0);
assert(dn->thisnodename==nodesize*20);
......
......@@ -64,7 +64,7 @@ static struct item *make_item (CACHEKEY key) {
}
static CACHEKEY did_fetch=-1;
static int fetch (CACHEFILE f, CACHEKEY key, void**value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
static int fetch (CACHEFILE f, CACHEKEY key, u_int32_t fullhash __attribute__((__unused__)), void**value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
if (verbose) printf("Fetch %lld\n", key);
assert (expect_f==f);
assert((long)extraargs==23);
......@@ -89,52 +89,59 @@ static void test0 (void) {
expect_f = f;
expect_n_flushes=0;
r=toku_cachetable_put(f, 1, make_item(1), test_object_size, flush, fetch, t3); /* 1P */ /* this is the lru list. 1 is pinned. */
u_int32_t h1 = toku_cachetable_hash(f, 1);
u_int32_t h2 = toku_cachetable_hash(f, 2);
u_int32_t h3 = toku_cachetable_hash(f, 3);
u_int32_t h4 = toku_cachetable_hash(f, 4);
u_int32_t h5 = toku_cachetable_hash(f, 5);
u_int32_t h6 = toku_cachetable_hash(f, 6);
u_int32_t h7 = toku_cachetable_hash(f, 7);
r=toku_cachetable_put(f, 1, h1, make_item(1), test_object_size, flush, fetch, t3); /* 1P */ /* this is the lru list. 1 is pinned. */
assert(r==0);
assert(expect_n_flushes==0);
expect_n_flushes=0;
r=toku_cachetable_put(f, 2, make_item(2), test_object_size, flush, fetch, t3);
r=toku_cachetable_put(f, 2, h2, make_item(2), test_object_size, flush, fetch, t3);
assert(r==0);
r=toku_cachetable_unpin(f, 2, CACHETABLE_DIRTY, 1); /* 2U 1P */
r=toku_cachetable_unpin(f, 2, h2, CACHETABLE_DIRTY, 1); /* 2U 1P */
assert(expect_n_flushes==0);
expect_n_flushes=0;
r=toku_cachetable_put(f, 3, make_item(3), test_object_size, flush, fetch, t3);
r=toku_cachetable_put(f, 3, h3, make_item(3), test_object_size, flush, fetch, t3);
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;
r=toku_cachetable_put(f, 4, make_item(4), test_object_size, flush, fetch, t3);
r=toku_cachetable_put(f, 4, h4, make_item(4), test_object_size, flush, fetch, t3);
assert(r==0);
assert(expect_n_flushes==0); /* 4P 3P 2U 1P */
expect_n_flushes=0;
r=toku_cachetable_put(f, 5, make_item(5), test_object_size, flush, fetch, t3);
r=toku_cachetable_put(f, 5, h5, make_item(5), test_object_size, flush, fetch, t3);
assert(r==0);
r=toku_cachetable_unpin(f, 5, CACHETABLE_DIRTY, test_object_size);
r=toku_cachetable_unpin(f, 5, h5, CACHETABLE_DIRTY, test_object_size);
assert(r==0);
r=toku_cachetable_unpin(f, 3, CACHETABLE_DIRTY, test_object_size);
r=toku_cachetable_unpin(f, 3, h3, CACHETABLE_DIRTY, test_object_size);
assert(r==0);
assert(expect_n_flushes==0); /* 5U 4P 3U 2U 1P */
expect1(2); /* 2 is the oldest unpinned item. */
r=toku_cachetable_put(f, 6, make_item(6), test_object_size, flush, fetch, t3); /* 6P 5U 4P 3U 1P */
r=toku_cachetable_put(f, 6, h6, make_item(6), test_object_size, flush, fetch, t3); /* 6P 5U 4P 3U 1P */
assert(r==0);
assert(expect_n_flushes==0);
expect1(3);
r=toku_cachetable_put(f, 7, make_item(7), test_object_size, flush, fetch, t3);
r=toku_cachetable_put(f, 7, h7, make_item(7), test_object_size, flush, fetch, t3);
assert(r==0);
assert(expect_n_flushes==0);
r=toku_cachetable_unpin(f, 7, CACHETABLE_DIRTY, test_object_size); /* 7U 6P 5U 4P 1P */
r=toku_cachetable_unpin(f, 7, h7, CACHETABLE_DIRTY, test_object_size); /* 7U 6P 5U 4P 1P */
assert(r==0);
{
void *item_v=0;
expect_n_flushes=0;
r=toku_cachetable_get_and_pin(f, 5, &item_v, NULL, flush, fetch, t3); /* 5P 7U 6P 4P 1P */
r=toku_cachetable_get_and_pin(f, 5, toku_cachetable_hash(f, 5), &item_v, NULL, flush, fetch, t3); /* 5P 7U 6P 4P 1P */
assert(r==0);
assert(((struct item *)item_v)->key==5);
assert(strcmp(((struct item *)item_v)->something,"something")==0);
......@@ -143,11 +150,11 @@ static void test0 (void) {
{
void *item_v=0;
r=toku_cachetable_unpin(f, 4, CACHETABLE_DIRTY, test_object_size);
r=toku_cachetable_unpin(f, 4, h4, CACHETABLE_DIRTY, test_object_size);
assert(r==0);
expect1(4);
did_fetch=-1;
r=toku_cachetable_get_and_pin(f, 2, &item_v, NULL, flush, fetch, t3); /* 2p 5P 7U 6P 1P */
r=toku_cachetable_get_and_pin(f, 2, toku_cachetable_hash(f, 2), &item_v, NULL, flush, fetch, t3); /* 2p 5P 7U 6P 1P */
assert(r==0);
assert(did_fetch==2); /* Expect that 2 is fetched in. */
assert(((struct item *)item_v)->key==2);
......@@ -155,13 +162,13 @@ static void test0 (void) {
assert(expect_n_flushes==0);
}
r=toku_cachetable_unpin(f, 2, CACHETABLE_DIRTY, test_object_size);
r=toku_cachetable_unpin(f, 2, h2, CACHETABLE_DIRTY, test_object_size);
assert(r==0);
r=toku_cachetable_unpin(f ,5, CACHETABLE_DIRTY, test_object_size);
r=toku_cachetable_unpin(f, 5, h5, CACHETABLE_DIRTY, test_object_size);
assert(r==0);
r=toku_cachetable_unpin(f, 6, CACHETABLE_DIRTY, test_object_size);
r=toku_cachetable_unpin(f, 6, h6, CACHETABLE_DIRTY, test_object_size);
assert(r==0);
r=toku_cachetable_unpin(f, 1, CACHETABLE_DIRTY, test_object_size);
r=toku_cachetable_unpin(f, 1, h1, CACHETABLE_DIRTY, test_object_size);
assert(r==0);
r=toku_cachetable_assert_all_unpinned(t);
assert(r==0);
......@@ -189,6 +196,7 @@ static void flush_n (CACHEFILE f __attribute__((__unused__)), CACHEKEY key __att
assert(*v==0);
}
static int fetch_n (CACHEFILE f __attribute__((__unused__)), CACHEKEY key __attribute__((__unused__)),
u_int32_t fullhash __attribute__((__unused__)),
void**value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
assert((long)extraargs==42);
*value=0;
......@@ -213,21 +221,22 @@ static void test_nested_pin (void) {
expect_f = f;
i0=0; i1=0;
r = toku_cachetable_put(f, 1, &i0, 1, flush_n, fetch_n, f2);
u_int32_t f1hash = toku_cachetable_hash(f, 1);
r = toku_cachetable_put(f, 1, f1hash, &i0, 1, flush_n, fetch_n, f2);
assert(r==0);
r = toku_cachetable_get_and_pin(f, 1, &vv, NULL, flush_n, fetch_n, f2);
r = toku_cachetable_get_and_pin(f, 1, f1hash, &vv, NULL, flush_n, fetch_n, f2);
assert(r==0);
assert(vv==&i0);
assert(i0==0);
r = toku_cachetable_unpin(f, 1, 0, test_object_size);
r = toku_cachetable_unpin(f, 1, f1hash, 0, test_object_size);
assert(r==0);
r = toku_cachetable_maybe_get_and_pin(f, 1, &vv2);
r = toku_cachetable_maybe_get_and_pin(f, 1, f1hash, &vv2);
assert(r==0);
assert(vv2==vv);
r = toku_cachetable_unpin(f, 1, 0, test_object_size);
r = toku_cachetable_put(f, 2, &i1, test_object_size, flush_n, fetch_n, f2);
r = toku_cachetable_unpin(f, 1, f1hash, 0, test_object_size);
r = toku_cachetable_put(f, 2, toku_cachetable_hash(f, 2), &i1, test_object_size, flush_n, fetch_n, f2);
assert(r==0); // The other one is pinned, but now the cachetable fails gracefully: It allows the pin to happen
r = toku_cachetable_unpin(f, 1, 0, test_object_size);
r = toku_cachetable_unpin(f, 1, f1hash, 0, test_object_size);
assert(r==0);
r = toku_cachefile_close(&f, 0); assert(r==0);
......@@ -245,13 +254,15 @@ static void null_flush (CACHEFILE cf __attribute__((__unused__)),
LSN modified_lsn __attribute__((__unused__)),
BOOL rename_p __attribute__((__unused__))) {
}
static int add123_fetch (CACHEFILE cf __attribute__((__unused__)), CACHEKEY key, void **value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
static int add123_fetch (CACHEFILE cf, CACHEKEY key, u_int32_t fullhash, void **value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
assert(fullhash==toku_cachetable_hash(cf,key));
assert((long)extraargs==123);
*value = (void*)((unsigned long)key+123L);
written_lsn->lsn = 0;
return 0;
}
static int add222_fetch (CACHEFILE cf __attribute__((__unused__)), CACHEKEY key, void **value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
static int add222_fetch (CACHEFILE cf, CACHEKEY key, u_int32_t fullhash, void **value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
assert(fullhash==toku_cachetable_hash(cf,key));
assert((long)extraargs==222);
*value = (void*)((unsigned long)key+222L);
written_lsn->lsn = 0;
......@@ -279,14 +290,14 @@ static void test_multi_filehandles (void) {
assert(f1==f2);
assert(f1!=f3);
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);
r = toku_cachetable_put(f1, 1, toku_cachetable_hash(f1, 1), (void*)124, test_object_size, null_flush, add123_fetch, (void*)123); assert(r==0);
r = toku_cachetable_get_and_pin(f2, 1, toku_cachetable_hash(f2, 1), &v, NULL, null_flush, add123_fetch, (void*)123); assert(r==0);
assert((unsigned long)v==124);
r = toku_cachetable_get_and_pin(f2, 2, &v, NULL, null_flush, add123_fetch, (void*)123); assert(r==0);
r = toku_cachetable_get_and_pin(f2, 2, toku_cachetable_hash(f2, 2), &v, NULL, null_flush, add123_fetch, (void*)123); assert(r==0);
assert((unsigned long)v==125);
r = toku_cachetable_get_and_pin(f3, 2, &v, NULL, null_flush, add222_fetch, (void*)222); assert(r==0);
r = toku_cachetable_get_and_pin(f3, 2, toku_cachetable_hash(f3, 2), &v, NULL, null_flush, add222_fetch, (void*)222); assert(r==0);
assert((unsigned long)v==224);
r = toku_cachetable_maybe_get_and_pin(f1, 2, &v); assert(r==0);
r = toku_cachetable_maybe_get_and_pin(f1, 2, toku_cachetable_hash(f1, 2), &v); assert(r==0);
assert((unsigned long)v==125);
r = toku_cachefile_close(&f1, 0); assert(r==0);
......@@ -299,9 +310,10 @@ static void test_dirty_flush(CACHEFILE f, CACHEKEY key, void *value, long size,
if (verbose) printf("test_dirty_flush %p %lld %p %ld %d %d\n", f, key, value, size, do_write, keep);
}
static int test_dirty_fetch(CACHEFILE f, CACHEKEY key, void **value_ptr, long *size_ptr, void *arg, LSN *written_lsn) {
static int test_dirty_fetch(CACHEFILE f, CACHEKEY key, u_int32_t fullhash, void **value_ptr, long *size_ptr, void *arg, LSN *written_lsn) {
*value_ptr = arg;
written_lsn->lsn = 0;
assert(fullhash==toku_cachetable_hash(f,key));
if (verbose) printf("test_dirty_fetch %p %lld %p %ld %p\n", f, key, *value_ptr, *size_ptr, arg);
return 0;
}
......@@ -324,7 +336,8 @@ static void test_dirty() {
assert(r == 0);
key = 1; value = (void*)1;
r = toku_cachetable_put(f, key, value, test_object_size, test_dirty_flush, 0, 0);
u_int32_t hkey = toku_cachetable_hash(f, key);
r = toku_cachetable_put(f, key, hkey, value, test_object_size, test_dirty_flush, 0, 0);
assert(r == 0);
// cachetable_print_state(t);
......@@ -333,15 +346,15 @@ static void test_dirty() {
assert(dirty == 1);
assert(pinned == 1);
r = toku_cachetable_unpin(f, key, CACHETABLE_CLEAN, 0);
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_CLEAN, 0);
assert(r == 0);
r = toku_cachetable_get_key_state(t, key, f, &value, &dirty, &pinned, &entry_size);
assert(r == 0);
assert(dirty == 1);
assert(pinned == 0);
r = toku_cachetable_get_and_pin(f, key, &value, NULL, test_dirty_flush,
test_dirty_fetch, 0);
r = toku_cachetable_get_and_pin(f, key, hkey, &value, NULL, test_dirty_flush,
test_dirty_fetch, 0);
assert(r == 0);
// cachetable_print_state(t);
......@@ -350,7 +363,7 @@ static void test_dirty() {
assert(dirty == 1);
assert(pinned == 1);
r = toku_cachetable_unpin(f, key, CACHETABLE_CLEAN, test_object_size);
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_CLEAN, test_object_size);
assert(r == 0);
// cachetable_print_state(t);
......@@ -360,8 +373,10 @@ static void test_dirty() {
assert(pinned == 0);
key = 2;
r = toku_cachetable_get_and_pin(f, key, &value, NULL, test_dirty_flush,
test_dirty_fetch, 0);
hkey = toku_cachetable_hash(f, key);
r = toku_cachetable_get_and_pin(f, key, hkey,
&value, NULL, test_dirty_flush,
test_dirty_fetch, 0);
assert(r == 0);
// cachetable_print_state(t);
......@@ -370,7 +385,7 @@ static void test_dirty() {
assert(dirty == 0);
assert(pinned == 1);
r = toku_cachetable_unpin(f, key, CACHETABLE_CLEAN, test_object_size);
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_CLEAN, test_object_size);
assert(r == 0);
// cachetable_print_state(t);
......@@ -379,7 +394,8 @@ static void test_dirty() {
assert(dirty == 0);
assert(pinned == 0);
r = toku_cachetable_get_and_pin(f, key, &value, NULL, test_dirty_flush,
r = toku_cachetable_get_and_pin(f, key, hkey,
&value, NULL, test_dirty_flush,
test_dirty_fetch, 0);
assert(r == 0);
......@@ -389,7 +405,7 @@ static void test_dirty() {
assert(dirty == 0);
assert(pinned == 1);
r = toku_cachetable_unpin(f, key, CACHETABLE_DIRTY, test_object_size);
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_DIRTY, test_object_size);
assert(r == 0);
// cachetable_print_state(t);
......@@ -434,7 +450,9 @@ static void test_size_resize() {
CACHEKEY key = 42;
void *value = (void *) -42;
r = toku_cachetable_put(f, key, value, size, test_size_flush_callback, 0, 0);
u_int32_t hkey = toku_cachetable_hash(f, key);
r = toku_cachetable_put(f, key, hkey, value, size, test_size_flush_callback, 0, 0);
assert(r == 0);
void *entry_value; int dirty; long long pinned; long entry_size;
......@@ -446,17 +464,17 @@ static void test_size_resize() {
assert(entry_size == size);
long long new_size = 2*size;
r = toku_cachetable_unpin(f, key, CACHETABLE_CLEAN, new_size);
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_CLEAN, new_size);
assert(r == 0);
void *current_value;
long current_size;
r = toku_cachetable_get_and_pin(f, key, &current_value, &current_size, test_size_flush_callback, 0, 0);
r = toku_cachetable_get_and_pin(f, key, hkey, &current_value, &current_size, test_size_flush_callback, 0, 0);
assert(r == 0);
assert(current_value == value);
assert(current_size == new_size);
r = toku_cachetable_unpin(f, key, CACHETABLE_CLEAN, new_size);
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_CLEAN, new_size);
assert(r == 0);
r = toku_cachefile_close(&f, 0);
......@@ -491,7 +509,8 @@ static void test_size_flush() {
CACHEKEY key = i;
void *value = (void *)(long)-i;
// printf("test_size put %lld %p %lld\n", key, value, size);
r = toku_cachetable_put(f, key, value, size, test_size_flush_callback, 0, 0);
u_int32_t hkey = toku_cachetable_hash(f, key);
r = toku_cachetable_put(f, key, hkey, value, size, test_size_flush_callback, 0, 0);
assert(r == 0);
int n_entries;
......@@ -513,7 +532,7 @@ static void test_size_flush() {
expect_flush_key += 1;
}
r = toku_cachetable_unpin(f, key, CACHETABLE_CLEAN, size);
r = toku_cachetable_unpin(f, key, hkey, CACHETABLE_CLEAN, size);
assert(r == 0);
}
......@@ -552,12 +571,13 @@ static void r_flush (CACHEFILE f __attribute__((__unused__)),
abort();
}
static int r_fetch (CACHEFILE f __attribute__((__unused__)),
CACHEKEY key __attribute__((__unused__)),
void**value __attribute__((__unused__)),
long *sizep __attribute__((__unused__)),
void*extraargs __attribute__((__unused__)),
LSN *modified_lsn __attribute__((__unused__))) {
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 0;
}
......@@ -580,14 +600,16 @@ static void test_rename (void) {
CACHEKEY nkey = random();
long nval = random();
//printf("n_keys=%d Insert %08llx\n", n_keys, nkey);
r = toku_cachetable_put(f, nkey, (void*)nval, 1,
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);
assert(n_keys<KEYLIMIT);
keys[n_keys] = nkey;
vals[n_keys] = (void*)nval;
n_keys++;
r = toku_cachetable_unpin(f, nkey, CACHETABLE_DIRTY, 1);
r = toku_cachetable_unpin(f, nkey, hnkey, CACHETABLE_DIRTY, 1);
assert(r==0);
} else if (ra==2 && n_keys>0) {
// Rename something
......@@ -598,11 +620,11 @@ static void test_rename (void) {
long current_size;
keys[objnum]=nkey;
//printf("Rename %llx to %llx\n", okey, nkey);
r = toku_cachetable_get_and_pin(f, okey, &current_value, &current_size, r_flush, r_fetch, 0);
r = toku_cachetable_get_and_pin(f, okey, toku_cachetable_hash(f, okey), &current_value, &current_size, r_flush, r_fetch, 0);
assert(r==0);
r = toku_cachetable_rename(f, okey, nkey);
assert(r==0);
r = toku_cachetable_unpin(f, nkey, CACHETABLE_DIRTY, 1);
r = toku_cachetable_unpin(f, nkey, toku_cachetable_hash(f, nkey), CACHETABLE_DIRTY, 1);
}
}
......
......@@ -80,7 +80,8 @@ static void flush_forchain (CACHEFILE f __attribute__((__unused__)),
//print_ints();
}
static int fetch_forchain (CACHEFILE f __attribute__((__unused__)), CACHEKEY key, void**value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
static int fetch_forchain (CACHEFILE f, CACHEKEY key, u_int32_t fullhash, void**value, long *sizep __attribute__((__unused__)), void*extraargs, LSN *written_lsn) {
assert(toku_cachetable_hash(f, key)==fullhash);
assert((long)extraargs==(long)key);
*value = (void*)(long)key;
written_lsn->lsn = 0;
......@@ -91,11 +92,13 @@ static void verify_cachetable_against_present (void) {
int i;
for (i=0; i<n_present; i++) {
void *v;
int r;
assert(toku_cachetable_maybe_get_and_pin(present_items[i].cf,
present_items[i].key,
&v)==0);
r = toku_cachetable_unpin(present_items[i].cf, present_items[i].key, CACHETABLE_CLEAN, test_object_size);
u_int32_t fullhash = toku_cachetable_hash(present_items[i].cf, present_items[i].key);
int r=toku_cachetable_maybe_get_and_pin(present_items[i].cf,
present_items[i].key,
toku_cachetable_hash(present_items[i].cf, present_items[i].key),
&v);
assert(r==0);
r = toku_cachetable_unpin(present_items[i].cf, present_items[i].key, fullhash, CACHETABLE_CLEAN, test_object_size);
}
}
......@@ -117,9 +120,10 @@ static void test_chaining (void) {
for (i=0; i<N_PRESENT_LIMIT; i++) {
int fnum = i%N_FILES;
//printf("%s:%d Add %d\n", __FILE__, __LINE__, i);
r = toku_cachetable_put(f[fnum], i, (void*)i, test_object_size, flush_forchain, fetch_forchain, (void*)i); assert(r==0);
u_int32_t fhash = toku_cachetable_hash(f[fnum], i);
r = toku_cachetable_put(f[fnum], i, fhash, (void*)i, test_object_size, flush_forchain, fetch_forchain, (void*)i); assert(r==0);
item_becomes_present(f[fnum], i);
r = toku_cachetable_unpin(f[fnum], i, CACHETABLE_CLEAN, test_object_size); assert(r==0);
r = toku_cachetable_unpin(f[fnum], i, fhash, CACHETABLE_CLEAN, test_object_size); assert(r==0);
//print_ints();
}
for (trial=0; trial<TRIALS; trial++) {
......@@ -128,8 +132,10 @@ static void test_chaining (void) {
int whichone = random()%n_present;
void *value;
//printf("Touching %d (%lld, %p)\n", whichone, present_items[whichone].key, present_items[whichone].cf);
u_int32_t fhash = toku_cachetable_hash(present_items[whichone].cf, present_items[whichone].key);
r = toku_cachetable_get_and_pin(present_items[whichone].cf,
present_items[whichone].key,
fhash,
&value,
NULL,
flush_forchain,
......@@ -139,6 +145,7 @@ static void test_chaining (void) {
assert(r==0);
r = toku_cachetable_unpin(present_items[whichone].cf,
present_items[whichone].key,
fhash,
CACHETABLE_CLEAN, test_object_size);
assert(r==0);
}
......@@ -147,11 +154,12 @@ static void test_chaining (void) {
int fnum = i%N_FILES;
// i is always incrementing, so we need not worry about inserting a duplicate
//printf("%s:%d Add {%d,%p}\n", __FILE__, __LINE__, i, f[fnum]);
r = toku_cachetable_put(f[fnum], i, (void*)i, test_object_size, flush_forchain, fetch_forchain, (void*)i); assert(r==0);
u_int32_t fhash = toku_cachetable_hash(f[fnum], i);
r = toku_cachetable_put(f[fnum], i, fhash, (void*)i, test_object_size, flush_forchain, fetch_forchain, (void*)i); assert(r==0);
item_becomes_present(f[fnum], i);
//print_ints();
//cachetable_print_state(ct);
r = toku_cachetable_unpin(f[fnum], i, CACHETABLE_CLEAN, test_object_size); assert(r==0);
r = toku_cachetable_unpin(f[fnum], i, fhash, CACHETABLE_CLEAN, test_object_size); assert(r==0);
verify_cachetable_against_present();
if (random()%10==0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment