Commit 2781d1a3 authored by Rich Prohaska's avatar Rich Prohaska

_put sets dirty=1, get_and_pin sets dirty=0 for fetched items

git-svn-id: file:///svn/tokudb@314 c7de825b-a66e-492c-adef-691d508d4ae1
parent 1328a05a
...@@ -275,10 +275,117 @@ void test_multi_filehandles (void) { ...@@ -275,10 +275,117 @@ void test_multi_filehandles (void) {
r = cachetable_close(&t); assert(r==0); r = cachetable_close(&t); assert(r==0);
} }
void test_dirty_flush(CACHEFILE f, CACHEKEY key, void *value, int write, int keep) {
printf("test_dirty_flush %p %lld %p %d %d\n", f, key, value, write, keep);
}
int test_dirty_fetch(CACHEFILE f, CACHEKEY key, void **value_ptr, void *arg) {
*value_ptr = arg;
printf("test_dirty_fetch %p %lld %p %p\n", f, key, *value_ptr, arg);
return 0;
}
void test_dirty() {
CACHETABLE t;
CACHEFILE f;
CACHEKEY key; void *value;
int dirty; long long pinned;
int r;
r = create_cachetable(&t, 4);
assert(r == 0);
char *fname = "test.dat";
unlink(fname);
r = cachetable_openf(&f, t, fname, O_RDWR|O_CREAT, 0777);
assert(r == 0);
key = 1; value = (void*)1;
r = cachetable_put(f, key, value, test_dirty_flush, 0, 0);
assert(r == 0);
// cachetable_print_state(t);
r = cachetable_get_state(t, key, &value, &dirty, &pinned);
assert(r == 0);
assert(dirty == 1);
assert(pinned == 1);
r = cachetable_unpin(f, key, 0);
assert(r == 0);
r = cachetable_get_state(t, key, &value, &dirty, &pinned);
assert(r == 0);
assert(dirty == 1);
assert(pinned == 0);
r = cachetable_get_and_pin(f, key, &value, test_dirty_flush,
test_dirty_fetch, 0);
assert(r == 0);
// cachetable_print_state(t);
r = cachetable_get_state(t, key, &value, &dirty, &pinned);
assert(r == 0);
assert(dirty == 1);
assert(pinned == 1);
r = cachetable_unpin(f, key, 0);
assert(r == 0);
// cachetable_print_state(t);
r = cachetable_get_state(t, key, &value, &dirty, &pinned);
assert(r == 0);
assert(dirty == 1);
assert(pinned == 0);
key = 2;
r = cachetable_get_and_pin(f, key, &value, test_dirty_flush,
test_dirty_fetch, 0);
assert(r == 0);
// cachetable_print_state(t);
r = cachetable_get_state(t, key, &value, &dirty, &pinned);
assert(r == 0);
assert(dirty == 0);
assert(pinned == 1);
r = cachetable_unpin(f, key, 0);
assert(r == 0);
// cachetable_print_state(t);
r = cachetable_get_state(t, key, &value, &dirty, &pinned);
assert(r == 0);
assert(dirty == 0);
assert(pinned == 0);
r = cachetable_get_and_pin(f, key, &value, test_dirty_flush,
test_dirty_fetch, 0);
assert(r == 0);
// cachetable_print_state(t);
r = cachetable_get_state(t, key, &value, &dirty, &pinned);
assert(r == 0);
assert(dirty == 0);
assert(pinned == 1);
r = cachetable_unpin(f, key, 1);
assert(r == 0);
// cachetable_print_state(t);
r = cachetable_get_state(t, key, &value, &dirty, &pinned);
assert(r == 0);
assert(dirty == 1);
assert(pinned == 0);
r = cachefile_close(&f);
assert(r == 0);
r = cachetable_close(&t);
assert(r == 0);
}
int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) { int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
test0(); test0();
test_nested_pin(); test_nested_pin();
test_multi_filehandles (); test_multi_filehandles ();
test_dirty();
malloc_cleanup(); malloc_cleanup();
printf("ok\n"); printf("ok\n");
return 0; return 0;
......
#include "cachetable.h" #include "cachetable.h"
#include "memory.h" #include "memory.h"
#include "yerror.h" #include "yerror.h"
...@@ -26,8 +27,8 @@ struct ctpair { ...@@ -26,8 +27,8 @@ struct ctpair {
PAIR next,prev; // In LRU list. PAIR next,prev; // In LRU list.
PAIR hash_chain; PAIR hash_chain;
CACHEFILE cachefile; CACHEFILE cachefile;
void (*flush_callback)(CACHEFILE,CACHEKEY,void*, int write_me, int keep_me); cachetable_flush_func_t flush_callback;
int (*fetch_callback)(CACHEFILE,CACHEKEY,void**,void*extrargs); cachetable_fetch_func_t fetch_callback;
void*extraargs; void*extraargs;
}; };
...@@ -59,12 +60,13 @@ void cachetable_print_state (CACHETABLE ct) { ...@@ -59,12 +60,13 @@ void cachetable_print_state (CACHETABLE ct) {
PAIR p; PAIR p;
printf("t[%d]=", i); printf("t[%d]=", i);
for (p=ct->table[i]; p; p=p->hash_chain) { for (p=ct->table[i]; p; p=p->hash_chain) {
printf(" {%lld, %p}", p->key, p->cachefile); printf(" {%lld, %p, dirty=%d, pin=%lld}", p->key, p->cachefile, p->dirty, p->pinned);
} }
printf("\n"); printf("\n");
} }
} }
int create_cachetable (CACHETABLE *result, int n_entries) { int create_cachetable (CACHETABLE *result, int n_entries) {
TAGMALLOC(CACHETABLE, t); TAGMALLOC(CACHETABLE, t);
int i; int i;
...@@ -269,11 +271,30 @@ static int maybe_flush_some (CACHETABLE t) { ...@@ -269,11 +271,30 @@ static int maybe_flush_some (CACHETABLE t) {
return 0; return 0;
} }
static int cachetable_insert_at(CACHEFILE cachefile, int h, CACHEKEY key, void *value,
cachetable_flush_func_t flush_callback,
cachetable_fetch_func_t fetch_callback,
void *extraargs, int dirty) {
TAGMALLOC(PAIR, p);
p->pinned = 1;
p->dirty = dirty;
//printf("%s:%d p=%p dirty=%d\n", __FILE__, __LINE__, p, p->dirty);
p->key = key;
p->value = value;
p->next = p->prev = 0;
p->cachefile = cachefile;
p->flush_callback = flush_callback;
p->fetch_callback = fetch_callback;
p->extraargs = extraargs;
lru_add_to_list(cachefile->cachetable, p);
p->hash_chain = cachefile->cachetable->table[h];
cachefile->cachetable->table[h] = p;
cachefile->cachetable->n_in_table++;
return 0;
}
int cachetable_put (CACHEFILE cachefile, CACHEKEY key, void*value, int cachetable_put (CACHEFILE cachefile, CACHEKEY key, void*value,
void (*flush_callback)(CACHEFILE,CACHEKEY,void*, int /*write_me*/, int /*keep_me*/), cachetable_flush_func_t flush_callback, cachetable_fetch_func_t fetch_callback, void *extraargs) {
int (*fetch_callback)(CACHEFILE,CACHEKEY,void**,void*/*extraargs*/),
void*extraargs
) {
int h = hashit(cachefile->cachetable, key); int h = hashit(cachefile->cachetable, key);
WHEN_TRACE_CT(printf("%s:%d CT cachetable_put(%lld)=%p\n", __FILE__, __LINE__, key, value)); WHEN_TRACE_CT(printf("%s:%d CT cachetable_put(%lld)=%p\n", __FILE__, __LINE__, key, value));
{ {
...@@ -288,33 +309,13 @@ int cachetable_put (CACHEFILE cachefile, CACHEKEY key, void*value, ...@@ -288,33 +309,13 @@ int cachetable_put (CACHEFILE cachefile, CACHEKEY key, void*value,
} }
} }
} }
if (maybe_flush_some(cachefile->cachetable)) return -2; if (maybe_flush_some(cachefile->cachetable))
return -2;
{ return cachetable_insert_at(cachefile, h, key, value, flush_callback, fetch_callback, extraargs, 1);
TAGMALLOC(PAIR, p);
p->pinned=1;
p->dirty =1;
//printf("%s:%d p=%p dirty=%d\n", __FILE__, __LINE__, p, p->dirty);
p->key = key;
p->value = value;
p->next = p->prev = 0;
p->cachefile = cachefile;
p->flush_callback = flush_callback;
p->fetch_callback = fetch_callback;
p->extraargs = extraargs;
lru_add_to_list(cachefile->cachetable, p);
p->hash_chain = cachefile->cachetable->table[h];
cachefile->cachetable->table[h] = p;
cachefile->cachetable->n_in_table++;
return 0;
}
} }
int cachetable_get_and_pin (CACHEFILE cachefile, CACHEKEY key, void**value, int cachetable_get_and_pin (CACHEFILE cachefile, CACHEKEY key, void**value,
void(*flush_callback)(CACHEFILE,CACHEKEY,void*,int write_me, int keep_me), cachetable_flush_func_t flush_callback, cachetable_fetch_func_t fetch_callback, void *extraargs) {
int(*fetch_callback)(CACHEFILE, CACHEKEY key, void**value,void*extraargs), /* If we are asked to fetch something, get it by calling this back. */
void*extraargs
) {
CACHETABLE t = cachefile->cachetable; CACHETABLE t = cachefile->cachetable;
int h = hashit(t,key); int h = hashit(t,key);
PAIR p; PAIR p;
...@@ -333,7 +334,7 @@ int cachetable_get_and_pin (CACHEFILE cachefile, CACHEKEY key, void**value, ...@@ -333,7 +334,7 @@ int cachetable_get_and_pin (CACHEFILE cachefile, CACHEKEY key, void**value,
int r; int r;
WHEN_TRACE_CT(printf("%s:%d CT: fetch_callback(%lld...)\n", __FILE__, __LINE__, key)); WHEN_TRACE_CT(printf("%s:%d CT: fetch_callback(%lld...)\n", __FILE__, __LINE__, key));
if ((r=fetch_callback(cachefile, key, &toku_value,extraargs))) return r; if ((r=fetch_callback(cachefile, key, &toku_value,extraargs))) return r;
cachetable_put(cachefile, key, toku_value, flush_callback, fetch_callback,extraargs); cachetable_insert_at(cachefile, h, key, toku_value, flush_callback, fetch_callback, extraargs, 0);
*value = toku_value; *value = toku_value;
} }
WHEN_TRACE_CT(printf("%s:%d did fetch: cachtable_get_and_pin(%lld)--> %p\n", __FILE__, __LINE__, key, *value)); WHEN_TRACE_CT(printf("%s:%d did fetch: cachtable_get_and_pin(%lld)--> %p\n", __FILE__, __LINE__, key, *value));
...@@ -494,3 +495,19 @@ int cachefile_pread (CACHEFILE cf, void *buf, size_t count, off_t offset) { ...@@ -494,3 +495,19 @@ int cachefile_pread (CACHEFILE cf, void *buf, size_t count, off_t offset) {
int cachefile_fd (CACHEFILE cf) { int cachefile_fd (CACHEFILE cf) {
return cf->fd; return cf->fd;
} }
/* debug function */
int cachetable_get_state(CACHETABLE ct, CACHEKEY key, void **value_ptr,
int *dirty_ptr, long long *pin_ptr) {
int h = hashit(ct, key);
PAIR p;
for (p = ct->table[h]; p; p = p->hash_chain) {
if (p->key == key) {
*value_ptr = p->value;
*dirty_ptr = p->dirty;
*pin_ptr = p->pinned;
return 0;
}
}
return 1;
}
...@@ -24,18 +24,17 @@ int create_cachetable (CACHETABLE */*result*/, int /*n_entries*/); ...@@ -24,18 +24,17 @@ int create_cachetable (CACHETABLE */*result*/, int /*n_entries*/);
int cachetable_openf (CACHEFILE *,CACHETABLE, const char */*fname*/, int flags, mode_t mode); int cachetable_openf (CACHEFILE *,CACHETABLE, const char */*fname*/, int flags, mode_t mode);
typedef void (*cachetable_flush_func_t)(CACHEFILE, CACHEKEY key, void*value, int write_me, int keep_me);
/* If we are asked to fetch something, get it by calling this back. */
typedef int (*cachetable_fetch_func_t)(CACHEFILE, CACHEKEY key, void**value,void*extraargs);
/* Error if already present. On success, pin the value. */ /* Error if already present. On success, pin the value. */
int cachetable_put (CACHEFILE, CACHEKEY, void*/*value*/, int cachetable_put (CACHEFILE, CACHEKEY, void*/*value*/,
void(*flush_callback)(CACHEFILE, CACHEKEY key, void*value, int write_me, int keep_me), cachetable_flush_func_t flush_callback, cachetable_fetch_func_t fetch_callback, void *extraargs);
int(*fetch_callback)(CACHEFILE, CACHEKEY key, void**value,void*extraargs), /* If we are asked to fetch something, get it by calling this back. */
void*extraargs
);
int cachetable_get_and_pin (CACHEFILE, CACHEKEY, void**/*value*/, int cachetable_get_and_pin (CACHEFILE, CACHEKEY, void**/*value*/,
void(*flush_callback)(CACHEFILE,CACHEKEY,void*,int write_me, int keep_me), cachetable_flush_func_t flush_callback, cachetable_fetch_func_t fetch_callback, void *extraargs);
int(*fetch_callback)(CACHEFILE, CACHEKEY key, void**value,void*extraargs), /* If we are asked to fetch something, get it by calling this back. */
void*extraargs
);
/* If the the item is already in memory, then return 0 and store it in the void**. /* 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. */ * If the item is not in memory, then return nonzero. */
...@@ -59,5 +58,6 @@ int cachefile_fd (CACHEFILE); ...@@ -59,5 +58,6 @@ int cachefile_fd (CACHEFILE);
// Useful for debugging // Useful for debugging
void cachetable_print_state (CACHETABLE ct); void cachetable_print_state (CACHETABLE ct);
int cachetable_get_state(CACHETABLE ct, CACHEKEY key, void **value_ptr,
int *dirty_ptr, long long *pin_ptr);
#endif #endif
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