Commit 2cd8b437 authored by John Esmet's avatar John Esmet

FT-249 FT-256 Add a message buffer class to replace FIFO. Use a real

functor instead of a macro for iterate.
parent 4f1762f8
...@@ -30,7 +30,6 @@ set(FT_SOURCES ...@@ -30,7 +30,6 @@ set(FT_SOURCES
cachetable cachetable
checkpoint checkpoint
compress compress
fifo
ft ft
ft-cachetable-wrappers ft-cachetable-wrappers
ft-flusher ft-flusher
...@@ -52,6 +51,7 @@ set(FT_SOURCES ...@@ -52,6 +51,7 @@ set(FT_SOURCES
logfilemgr logfilemgr
logger logger
log_upgrade log_upgrade
msg_buffer
quicklz quicklz
recover recover
rollback rollback
......
...@@ -198,9 +198,6 @@ void block_allocator_print (BLOCK_ALLOCATOR ba); ...@@ -198,9 +198,6 @@ void block_allocator_print (BLOCK_ALLOCATOR ba);
uint64_t block_allocator_allocated_limit (BLOCK_ALLOCATOR ba); uint64_t block_allocator_allocated_limit (BLOCK_ALLOCATOR ba);
// Effect: Return the unallocated block address of "infinite" size. // Effect: Return the unallocated block address of "infinite" size.
// That is, return the smallest address that is above all the allocated blocks. // That is, return the smallest address that is above all the allocated blocks.
// Rationale: When writing the root FIFO we don't know how big the block is.
// So we start at the "infinite" block, write the fifo, and then
// allocate_block_at of the correct size and offset to account for the root FIFO.
int block_allocator_get_nth_block_in_layout_order (BLOCK_ALLOCATOR ba, uint64_t b, uint64_t *offset, uint64_t *size); int block_allocator_get_nth_block_in_layout_order (BLOCK_ALLOCATOR ba, uint64_t b, uint64_t *offset, uint64_t *size);
// Effect: Consider the blocks in sorted order. The reserved block at the beginning is number 0. The next one is number 1 and so forth. // Effect: Consider the blocks in sorted order. The reserved block at the beginning is number 0. The next one is number 1 and so forth.
......
...@@ -106,7 +106,6 @@ PATENT RIGHTS GRANT: ...@@ -106,7 +106,6 @@ PATENT RIGHTS GRANT:
#include "ft_layout_version.h" #include "ft_layout_version.h"
#include "block_allocator.h" #include "block_allocator.h"
#include "cachetable.h" #include "cachetable.h"
#include "fifo.h"
#include "ft-ops.h" #include "ft-ops.h"
#include "toku_list.h" #include "toku_list.h"
#include <util/omt.h> #include <util/omt.h>
...@@ -118,6 +117,7 @@ PATENT RIGHTS GRANT: ...@@ -118,6 +117,7 @@ PATENT RIGHTS GRANT:
#include "ft/bndata.h" #include "ft/bndata.h"
#include "ft/rollback.h" #include "ft/rollback.h"
#include "ft/ft-search.h" #include "ft/ft-search.h"
#include "ft/msg_buffer.h"
enum { KEY_VALUE_OVERHEAD = 8 }; /* Must store the two lengths. */ enum { KEY_VALUE_OVERHEAD = 8 }; /* Must store the two lengths. */
enum { FT_MSG_OVERHEAD = (2 + sizeof(MSN)) }; // the type plus freshness plus MSN enum { FT_MSG_OVERHEAD = (2 + sizeof(MSN)) }; // the type plus freshness plus MSN
...@@ -207,10 +207,10 @@ struct ftnode_fetch_extra { ...@@ -207,10 +207,10 @@ struct ftnode_fetch_extra {
}; };
typedef struct ftnode_fetch_extra *FTNODE_FETCH_EXTRA; typedef struct ftnode_fetch_extra *FTNODE_FETCH_EXTRA;
struct toku_fifo_entry_key_msn_heaviside_extra { struct toku_msg_buffer_key_msn_heaviside_extra {
DESCRIPTOR desc; DESCRIPTOR desc;
ft_compare_func cmp; ft_compare_func cmp;
FIFO fifo; message_buffer *msg_buffer;
const DBT *key; const DBT *key;
MSN msn; MSN msn;
}; };
...@@ -218,24 +218,24 @@ struct toku_fifo_entry_key_msn_heaviside_extra { ...@@ -218,24 +218,24 @@ struct toku_fifo_entry_key_msn_heaviside_extra {
// comparison function for inserting messages into a // comparison function for inserting messages into a
// ftnode_nonleaf_childinfo's message_tree // ftnode_nonleaf_childinfo's message_tree
int int
toku_fifo_entry_key_msn_heaviside(const int32_t &v, const struct toku_fifo_entry_key_msn_heaviside_extra &extra); toku_msg_buffer_key_msn_heaviside(const int32_t &v, const struct toku_msg_buffer_key_msn_heaviside_extra &extra);
struct toku_fifo_entry_key_msn_cmp_extra { struct toku_msg_buffer_key_msn_cmp_extra {
DESCRIPTOR desc; DESCRIPTOR desc;
ft_compare_func cmp; ft_compare_func cmp;
FIFO fifo; message_buffer *msg_buffer;
}; };
// same thing for qsort_r // same thing for qsort_r
int int
toku_fifo_entry_key_msn_cmp(const struct toku_fifo_entry_key_msn_cmp_extra &extrap, const int &a, const int &b); toku_msg_buffer_key_msn_cmp(const struct toku_msg_buffer_key_msn_cmp_extra &extrap, const int &a, const int &b);
typedef toku::omt<int32_t> off_omt_t; typedef toku::omt<int32_t> off_omt_t;
typedef toku::omt<int32_t, int32_t, true> marked_off_omt_t; typedef toku::omt<int32_t, int32_t, true> marked_off_omt_t;
// data of an available partition of a nonleaf ftnode // data of an available partition of a nonleaf ftnode
struct ftnode_nonleaf_childinfo { struct ftnode_nonleaf_childinfo {
FIFO buffer; message_buffer msg_buffer;
off_omt_t broadcast_list; off_omt_t broadcast_list;
marked_off_omt_t fresh_message_tree; marked_off_omt_t fresh_message_tree;
off_omt_t stale_message_tree; off_omt_t stale_message_tree;
...@@ -946,9 +946,6 @@ bool toku_ft_leaf_needs_ancestors_messages(FT ft, FTNODE node, ANCESTORS ancesto ...@@ -946,9 +946,6 @@ bool toku_ft_leaf_needs_ancestors_messages(FT ft, FTNODE node, ANCESTORS ancesto
__attribute__((nonnull)) __attribute__((nonnull))
void toku_ft_bn_update_max_msn(FTNODE node, MSN max_msn_applied, int child_to_read); void toku_ft_bn_update_max_msn(FTNODE node, MSN max_msn_applied, int child_to_read);
__attribute__((const,nonnull))
size_t toku_ft_msg_memsize_in_fifo(FT_MSG msg);
int int
toku_ft_search_which_child( toku_ft_search_which_child(
DESCRIPTOR desc, DESCRIPTOR desc,
......
This diff is collapsed.
This diff is collapsed.
...@@ -187,7 +187,7 @@ ft_log_fassociate_during_checkpoint (CACHEFILE cf, void *header_v) { ...@@ -187,7 +187,7 @@ ft_log_fassociate_during_checkpoint (CACHEFILE cf, void *header_v) {
} }
// Maps to cf->begin_checkpoint_userdata // Maps to cf->begin_checkpoint_userdata
// Create checkpoint-in-progress versions of header and translation (btt) (and fifo for now...). // Create checkpoint-in-progress versions of header and translation (btt)
// Has access to fd (it is protected). // Has access to fd (it is protected).
// //
// Not reentrant for a single FT (see ft_checkpoint) // Not reentrant for a single FT (see ft_checkpoint)
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
/* The purpose of this file is to provide access to the ft_msg, /* The purpose of this file is to provide access to the ft_msg,
* which is the ephemeral version of the fifo_msg. * which is the ephemeral version of the messages that lives in
* a message buffer.
*/ */
#ifndef FT_MSG_H #ifndef FT_MSG_H
......
This diff is collapsed.
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
/* /*
COPYING CONDITIONS NOTICE: COPYING CONDITIONS NOTICE:
...@@ -30,7 +30,7 @@ COPYING CONDITIONS NOTICE: ...@@ -30,7 +30,7 @@ COPYING CONDITIONS NOTICE:
COPYRIGHT NOTICE: COPYRIGHT NOTICE:
TokuDB, Tokutek Fractal Tree Indexing Library. TokuDB, Tokutek Fractal Tree Indexing Library.
Copyright (C) 2007-2013 Tokutek, Inc. Copyright (C) 2014 Tokutek, Inc.
DISCLAIMER: DISCLAIMER:
...@@ -86,69 +86,33 @@ PATENT RIGHTS GRANT: ...@@ -86,69 +86,33 @@ PATENT RIGHTS GRANT:
under this License. under this License.
*/ */
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved." #include "ft/msg_buffer.h"
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it." #include "ft/ybt.h"
#include "fifo.h"
#include "xids.h"
#include "ybt.h"
#include <memory.h>
#include <toku_assert.h>
struct fifo {
int n_items_in_fifo;
char *memory; // An array of bytes into which fifo_entries are embedded.
int memory_size; // How big is fifo_memory
int memory_used; // How many bytes are in use?
};
static void fifo_init(struct fifo *fifo) {
fifo->n_items_in_fifo = 0;
fifo->memory = 0;
fifo->memory_size = 0;
fifo->memory_used = 0;
}
__attribute__((const,nonnull))
static int fifo_entry_size(struct fifo_entry *entry) {
return sizeof (struct fifo_entry) + entry->keylen + entry->vallen
+ xids_get_size(&entry->xids_s)
- sizeof(XIDS_S); //Prevent double counting from fifo_entry+xids_get_size
}
__attribute__((const,nonnull))
size_t toku_ft_msg_memsize_in_fifo(FT_MSG msg) {
// This must stay in sync with fifo_entry_size because that's what we
// really trust. But sometimes we only have an in-memory FT_MSG, not
// a serialized fifo_entry so we have to fake it.
return sizeof (struct fifo_entry) + msg->u.id.key->size + msg->u.id.val->size
+ xids_get_size(msg->xids)
- sizeof(XIDS_S);
}
int toku_fifo_create(FIFO *ptr) { void message_buffer::create() {
struct fifo *XMALLOC(fifo); _num_entries = 0;
if (fifo == 0) return ENOMEM; _memory = nullptr;
fifo_init(fifo); _memory_size = 0;
*ptr = fifo; _memory_used = 0;
return 0;
} }
void toku_fifo_resize(FIFO fifo, size_t new_size) { void message_buffer::clone(message_buffer *src) {
XREALLOC_N(new_size, fifo->memory); _num_entries = src->_num_entries;
fifo->memory_size = new_size; _memory_used = src->_memory_used;
_memory_size = src->_memory_size;
XMALLOC_N(_memory_size, _memory);
memcpy(_memory, src->_memory, _memory_size);
} }
void toku_fifo_free(FIFO *ptr) { void message_buffer::destroy() {
FIFO fifo = *ptr; if (_memory != nullptr) {
if (fifo->memory) toku_free(fifo->memory); toku_free(_memory);
fifo->memory=0; }
toku_free(fifo);
*ptr = 0;
} }
int toku_fifo_n_entries(FIFO fifo) { void message_buffer::resize(size_t new_size) {
return fifo->n_items_in_fifo; XREALLOC_N(new_size, _memory);
_memory_size = new_size;
} }
static int next_power_of_two (int n) { static int next_power_of_two (int n) {
...@@ -160,94 +124,101 @@ static int next_power_of_two (int n) { ...@@ -160,94 +124,101 @@ static int next_power_of_two (int n) {
return r; return r;
} }
int toku_fifo_enq(FIFO fifo, const void *key, unsigned int keylen, const void *data, unsigned int datalen, enum ft_msg_type type, MSN msn, XIDS xids, bool is_fresh, int32_t *dest) { struct message_buffer::buffer_entry *message_buffer::get_buffer_entry(int32_t offset) const {
int need_space_here = sizeof(struct fifo_entry) return (struct buffer_entry *) (_memory + offset);
}
void message_buffer::enqueue(FT_MSG msg, bool is_fresh, int32_t *offset) {
ITEMLEN keylen = ft_msg_get_keylen(msg);
ITEMLEN datalen = ft_msg_get_vallen(msg);
XIDS xids = ft_msg_get_xids(msg);
int need_space_here = sizeof(struct buffer_entry)
+ keylen + datalen + keylen + datalen
+ xids_get_size(xids) + xids_get_size(xids)
- sizeof(XIDS_S); //Prevent double counting - sizeof(XIDS_S); //Prevent double counting
int need_space_total = fifo->memory_used+need_space_here; int need_space_total = _memory_used + need_space_here;
if (fifo->memory == NULL || need_space_total > fifo->memory_size) { if (_memory == nullptr || need_space_total > _memory_size) {
// resize the fifo to the next power of 2 greater than the needed space // resize the buffer to the next power of 2 greater than the needed space
int next_2 = next_power_of_two(need_space_total); int next_2 = next_power_of_two(need_space_total);
toku_fifo_resize(fifo, next_2); resize(next_2);
} }
struct fifo_entry *entry = (struct fifo_entry *)(fifo->memory + fifo->memory_used); struct buffer_entry *entry = get_buffer_entry(_memory_used);
entry->type = (unsigned char) type; entry->type = (unsigned char) ft_msg_get_type(msg);
entry->msn = msn; entry->msn = msg->msn;
xids_cpy(&entry->xids_s, xids); xids_cpy(&entry->xids_s, xids);
entry->is_fresh = is_fresh; entry->is_fresh = is_fresh;
entry->keylen = keylen;
unsigned char *e_key = xids_get_end_of_array(&entry->xids_s); unsigned char *e_key = xids_get_end_of_array(&entry->xids_s);
memcpy(e_key, key, keylen); entry->keylen = keylen;
memcpy(e_key, ft_msg_get_key(msg), keylen);
entry->vallen = datalen; entry->vallen = datalen;
memcpy(e_key + keylen, data, datalen); memcpy(e_key + keylen, ft_msg_get_val(msg), datalen);
if (dest) { if (offset) {
*dest = fifo->memory_used; *offset = _memory_used;
} }
fifo->n_items_in_fifo++; _num_entries++;
fifo->memory_used += need_space_here; _memory_used += need_space_here;
return 0;
} }
int toku_fifo_iterate_internal_start(FIFO UU(fifo)) { return 0; } void message_buffer::set_freshness(int32_t offset, bool is_fresh) {
int toku_fifo_iterate_internal_has_more(FIFO fifo, int off) { return off < fifo->memory_used; } struct buffer_entry *entry = get_buffer_entry(offset);
int toku_fifo_iterate_internal_next(FIFO fifo, int off) { entry->is_fresh = is_fresh;
struct fifo_entry *e = (struct fifo_entry *)(fifo->memory + off);
return off + fifo_entry_size(e);
}
struct fifo_entry * toku_fifo_iterate_internal_get_entry(FIFO fifo, int off) {
return (struct fifo_entry *)(fifo->memory + off);
} }
size_t toku_fifo_internal_entry_memsize(struct fifo_entry *e) {
return fifo_entry_size(e); bool message_buffer::get_freshness(int32_t offset) const {
struct buffer_entry *entry = get_buffer_entry(offset);
return entry->is_fresh;
} }
void toku_fifo_iterate (FIFO fifo, void(*f)(bytevec key,ITEMLEN keylen,bytevec data,ITEMLEN datalen, enum ft_msg_type type, MSN msn, XIDS xids, bool is_fresh, void*), void *arg) { FT_MSG_S message_buffer::get_message(int32_t offset, DBT *keydbt, DBT *valdbt) const {
FIFO_ITERATE(fifo, struct buffer_entry *entry = get_buffer_entry(offset);
key, keylen, data, datalen, type, msn, xids, is_fresh, ITEMLEN keylen = entry->keylen;
f(key,keylen,data,datalen,type,msn,xids,is_fresh, arg)); ITEMLEN vallen = entry->vallen;
enum ft_msg_type type = (enum ft_msg_type) entry->type;
MSN msn = entry->msn;
const XIDS xids = (XIDS) &entry->xids_s;
bytevec key = xids_get_end_of_array(xids);
bytevec val = (uint8_t *) key + entry->keylen;
FT_MSG_S msg = {
type, msn, xids,
.u = { .id = { toku_fill_dbt(keydbt, key, keylen), toku_fill_dbt(valdbt, val, vallen) } }
};
return msg;
} }
unsigned int toku_fifo_buffer_size_in_use (FIFO fifo) { void message_buffer::get_message_key_msn(int32_t offset, DBT *key, MSN *msn) const {
return fifo->memory_used; struct buffer_entry *entry = get_buffer_entry(offset);
if (key != nullptr) {
toku_fill_dbt(key, xids_get_end_of_array((XIDS) &entry->xids_s), entry->keylen);
}
if (msn != nullptr) {
*msn = entry->msn;
}
} }
unsigned long toku_fifo_memory_size_in_use(FIFO fifo) { int message_buffer::num_entries() const {
return sizeof(*fifo)+fifo->memory_used; return _num_entries;
} }
unsigned long toku_fifo_memory_footprint(FIFO fifo) { size_t message_buffer::buffer_size_in_use() const {
size_t size_used = toku_memory_footprint(fifo->memory, fifo->memory_used); return _memory_used;
long rval = sizeof(*fifo) + size_used;
return rval;
} }
DBT *fill_dbt_for_fifo_entry(DBT *dbt, const struct fifo_entry *entry) { size_t message_buffer::memory_size_in_use() const {
return toku_fill_dbt(dbt, xids_get_end_of_array((XIDS) &entry->xids_s), entry->keylen); return sizeof(*this) + _memory_used;
} }
struct fifo_entry *toku_fifo_get_entry(FIFO fifo, int off) { size_t message_buffer::memory_footprint() const {
return toku_fifo_iterate_internal_get_entry(fifo, off); return sizeof(*this) + toku_memory_footprint(_memory, _memory_used);
} }
void toku_fifo_clone(FIFO orig_fifo, FIFO* cloned_fifo) { bool message_buffer::equals(message_buffer *other) const {
struct fifo *XMALLOC(new_fifo); return (_memory_used == other->_memory_used &&
assert(new_fifo); memcmp(_memory, other->_memory, _memory_used) == 0);
new_fifo->n_items_in_fifo = orig_fifo->n_items_in_fifo;
new_fifo->memory_used = orig_fifo->memory_used;
new_fifo->memory_size = new_fifo->memory_used;
XMALLOC_N(new_fifo->memory_size, new_fifo->memory);
memcpy(
new_fifo->memory,
orig_fifo->memory,
new_fifo->memory_size
);
*cloned_fifo = new_fifo;
} }
bool toku_are_fifos_same(FIFO fifo1, FIFO fifo2) { size_t message_buffer::msg_memsize_in_buffer(FT_MSG msg) {
return ( return sizeof(struct buffer_entry)
fifo1->memory_used == fifo2->memory_used && + msg->u.id.key->size + msg->u.id.val->size
memcmp(fifo1->memory, fifo2->memory, fifo1->memory_used) == 0 + xids_get_size(msg->xids)
); - sizeof(XIDS_S);
} }
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ifndef FIFO_H
#define FIFO_H
#ident "$Id$"
/* /*
COPYING CONDITIONS NOTICE: COPYING CONDITIONS NOTICE:
...@@ -32,7 +30,7 @@ COPYING CONDITIONS NOTICE: ...@@ -32,7 +30,7 @@ COPYING CONDITIONS NOTICE:
COPYRIGHT NOTICE: COPYRIGHT NOTICE:
TokuDB, Tokutek Fractal Tree Indexing Library. TokuDB, Tokutek Fractal Tree Indexing Library.
Copyright (C) 2007-2013 Tokutek, Inc. Copyright (C) 2014 Tokutek, Inc.
DISCLAIMER: DISCLAIMER:
...@@ -88,77 +86,76 @@ PATENT RIGHTS GRANT: ...@@ -88,77 +86,76 @@ PATENT RIGHTS GRANT:
under this License. under this License.
*/ */
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved." #pragma once
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
#include "ft/fttypes.h" #include "ft/fttypes.h"
#include "ft/xids-internal.h" #include "ft/xids-internal.h"
#include "ft/xids.h" #include "ft/xids.h"
#include "ft/ft_msg.h" #include "ft/ft_msg.h"
#include "ft/ybt.h"
// If the fifo_entry is unpacked, the compiler aligns the xids array and we waste a lot of space class message_buffer {
struct __attribute__((__packed__)) fifo_entry { public:
unsigned int keylen; void create();
unsigned int vallen;
unsigned char type;
bool is_fresh;
MSN msn;
XIDS_S xids_s;
};
typedef struct fifo *FIFO;
int toku_fifo_create(FIFO *); void clone(message_buffer *dst);
void toku_fifo_resize(FIFO fifo, size_t new_size); void destroy();
void toku_fifo_free(FIFO *); void resize(size_t new_size);
int toku_fifo_n_entries(FIFO); void enqueue(FT_MSG msg, bool is_fresh, int32_t *offset);
int toku_fifo_enq (FIFO, const void *key, ITEMLEN keylen, const void *data, ITEMLEN datalen, enum ft_msg_type type, MSN msn, XIDS xids, bool is_fresh, int32_t *dest); void set_freshness(int32_t offset, bool is_fresh);
unsigned int toku_fifo_buffer_size_in_use (FIFO fifo); bool get_freshness(int32_t offset) const;
unsigned long toku_fifo_memory_size_in_use(FIFO fifo); // return how much memory in the fifo holds useful data
unsigned long toku_fifo_memory_footprint(FIFO fifo); // return how much memory the fifo occupies FT_MSG_S get_message(int32_t offset, DBT *keydbt, DBT *valdbt) const;
void toku_fifo_iterate(FIFO, void(*f)(bytevec key,ITEMLEN keylen,bytevec data,ITEMLEN datalen, enum ft_msg_type type, MSN msn, XIDS xids, bool is_fresh, void*), void*); void get_message_key_msn(int32_t offset, DBT *key, MSN *msn) const;
#define FIFO_ITERATE(fifo,keyvar,keylenvar,datavar,datalenvar,typevar,msnvar,xidsvar,is_freshvar,body) ({ \ int num_entries() const;
for (int fifo_iterate_off = toku_fifo_iterate_internal_start(fifo); \
toku_fifo_iterate_internal_has_more(fifo, fifo_iterate_off); \
fifo_iterate_off = toku_fifo_iterate_internal_next(fifo, fifo_iterate_off)) { \
struct fifo_entry *e = toku_fifo_iterate_internal_get_entry(fifo, fifo_iterate_off); \
ITEMLEN keylenvar = e->keylen; \
ITEMLEN datalenvar = e->vallen; \
enum ft_msg_type typevar = (enum ft_msg_type) e->type; \
MSN msnvar = e->msn; \
XIDS xidsvar = &e->xids_s; \
bytevec keyvar = xids_get_end_of_array(xidsvar); \
bytevec datavar = (const uint8_t*)keyvar + e->keylen; \
bool is_freshvar = e->is_fresh; \
body; \
} })
#define FIFO_CURRENT_ENTRY_MEMSIZE toku_fifo_internal_entry_memsize(e) size_t buffer_size_in_use() const;
// Internal functions for the iterator. size_t memory_size_in_use() const;
int toku_fifo_iterate_internal_start(FIFO fifo);
int toku_fifo_iterate_internal_has_more(FIFO fifo, int off);
int toku_fifo_iterate_internal_next(FIFO fifo, int off);
struct fifo_entry * toku_fifo_iterate_internal_get_entry(FIFO fifo, int off);
size_t toku_fifo_internal_entry_memsize(struct fifo_entry *e) __attribute__((const,nonnull));
size_t toku_ft_msg_memsize_in_fifo(FT_MSG msg) __attribute__((const,nonnull));
DBT *fill_dbt_for_fifo_entry(DBT *dbt, const struct fifo_entry *entry); size_t memory_footprint() const;
struct fifo_entry *toku_fifo_get_entry(FIFO fifo, int off);
void toku_fifo_clone(FIFO orig_fifo, FIFO* cloned_fifo); template <typename F>
int iterate(F &fn) const {
for (int32_t offset = 0; offset < _memory_used; ) {
DBT k, v;
FT_MSG_S msg = get_message(offset, &k, &v);
bool is_fresh = get_freshness(offset);
int r = fn(&msg, is_fresh);
if (r != 0) {
return r;
}
offset += msg_memsize_in_buffer(&msg);
}
return 0;
}
bool toku_are_fifos_same(FIFO fifo1, FIFO fifo2); bool equals(message_buffer *other) const;
static size_t msg_memsize_in_buffer(FT_MSG msg);
private:
// If this isn't packged, the compiler aligns the xids array and we waste a lot of space
struct __attribute__((__packed__)) buffer_entry {
unsigned int keylen;
unsigned int vallen;
unsigned char type;
bool is_fresh;
MSN msn;
XIDS_S xids_s;
};
struct buffer_entry *get_buffer_entry(int32_t offset) const;
#endif int _num_entries;
char *_memory; // An array of bytes into which buffer entries are embedded.
int _memory_size; // How big is _memory
int _memory_used; // How many bytes are in use?
};
...@@ -94,28 +94,19 @@ PATENT RIGHTS GRANT: ...@@ -94,28 +94,19 @@ PATENT RIGHTS GRANT:
#include "test.h" #include "test.h"
static void static void
test_fifo_create (void) { test_create (void) {
int r; message_buffer msg_buffer;
FIFO f; msg_buffer.create();
msg_buffer.destroy();
f = 0;
r = toku_fifo_create(&f);
assert(r == 0); assert(f != 0);
toku_fifo_free(&f);
assert(f == 0);
} }
static void static void
test_fifo_enq (int n) { test_enqueue(int n) {
int r; int r;
FIFO f; message_buffer msg_buffer;
MSN startmsn = ZERO_MSN; MSN startmsn = ZERO_MSN;
f = 0; msg_buffer.create();
r = toku_fifo_create(&f);
assert(r == 0); assert(f != 0);
char *thekey = 0; int thekeylen; char *thekey = 0; int thekeylen;
char *theval = 0; int thevallen; char *theval = 0; int thevallen;
...@@ -146,38 +137,56 @@ test_fifo_enq (int n) { ...@@ -146,38 +137,56 @@ test_fifo_enq (int n) {
if (startmsn.msn == ZERO_MSN.msn) if (startmsn.msn == ZERO_MSN.msn)
startmsn = msn; startmsn = msn;
enum ft_msg_type type = (enum ft_msg_type) i; enum ft_msg_type type = (enum ft_msg_type) i;
r = toku_fifo_enq(f, thekey, thekeylen, theval, thevallen, type, msn, xids, true, NULL); assert(r == 0); DBT k, v;
FT_MSG_S msg = {
type, msn, xids, .u = { .id = { toku_fill_dbt(&k, thekey, thekeylen), toku_fill_dbt(&v, theval, thevallen) } }
};
msg_buffer.enqueue(&msg, true, nullptr);
xids_destroy(&xids); xids_destroy(&xids);
} }
int i = 0; struct checkit_fn {
FIFO_ITERATE(f, key, keylen, val, vallen, type, msn, xids, UU(is_fresh), { char *thekey;
int thekeylen;
char *theval;
int thevallen;
MSN startmsn;
int verbose;
int i;
checkit_fn(char *tk, int tkl, char *tv, int tvl, MSN smsn, bool v)
: thekey(tk), thekeylen(tkl), theval(tv), thevallen(tvl), startmsn(smsn), verbose(v), i(0) {
}
int operator()(FT_MSG msg, bool UU(is_fresh)) {
MSN msn = msg->msn;
enum ft_msg_type type = ft_msg_get_type(msg);
if (verbose) printf("checkit %d %d %" PRIu64 "\n", i, type, msn.msn); if (verbose) printf("checkit %d %d %" PRIu64 "\n", i, type, msn.msn);
assert(msn.msn == startmsn.msn + i); assert(msn.msn == startmsn.msn + i);
buildkey(i); buildkey(i);
buildval(i); buildval(i);
assert((int) keylen == thekeylen); assert(memcmp(key, thekey, keylen) == 0); assert((int) ft_msg_get_keylen(msg) == thekeylen); assert(memcmp(ft_msg_get_key(msg), thekey, ft_msg_get_keylen(msg)) == 0);
assert((int) vallen == thevallen); assert(memcmp(val, theval, vallen) == 0); assert((int) ft_msg_get_vallen(msg) == thevallen); assert(memcmp(ft_msg_get_val(msg), theval, ft_msg_get_vallen(msg)) == 0);
assert(i % 256 == (int)type); assert(i % 256 == (int)type);
assert((TXNID)i==xids_get_innermost_xid(xids)); assert((TXNID)i==xids_get_innermost_xid(ft_msg_get_xids(msg)));
i += 1; i += 1;
}); return 0;
assert(i == n); }
} checkit(thekey, thekeylen, theval, thevallen, startmsn, verbose);
msg_buffer.iterate(checkit);
assert(checkit.i == n);
if (thekey) toku_free(thekey); if (thekey) toku_free(thekey);
if (theval) toku_free(theval); if (theval) toku_free(theval);
toku_fifo_free(&f); msg_buffer.destroy();
assert(f == 0);
} }
int int
test_main(int argc, const char *argv[]) { test_main(int argc, const char *argv[]) {
default_parse_args(argc, argv); default_parse_args(argc, argv);
initialize_dummymsn(); initialize_dummymsn();
test_fifo_create(); test_create();
test_fifo_enq(4); test_enqueue(4);
test_fifo_enq(512); test_enqueue(512);
return 0; return 0;
} }
...@@ -1160,13 +1160,13 @@ test_serialize_nonleaf(enum ftnode_verify_type bft, bool do_clone) { ...@@ -1160,13 +1160,13 @@ test_serialize_nonleaf(enum ftnode_verify_type bft, bool do_clone) {
assert(BP_BLOCKNUM(dn,0).b==30); assert(BP_BLOCKNUM(dn,0).b==30);
assert(BP_BLOCKNUM(dn,1).b==35); assert(BP_BLOCKNUM(dn,1).b==35);
FIFO src_fifo_1 = BNC(&sn, 0)->buffer; message_buffer *src_msg_buffer1 = &BNC(&sn, 0)->msg_buffer;
FIFO src_fifo_2 = BNC(&sn, 1)->buffer; message_buffer *src_msg_buffer2 = &BNC(&sn, 1)->msg_buffer;
FIFO dest_fifo_1 = BNC(dn, 0)->buffer; message_buffer *dest_msg_buffer1 = &BNC(dn, 0)->msg_buffer;
FIFO dest_fifo_2 = BNC(dn, 1)->buffer; message_buffer *dest_msg_buffer2 = &BNC(dn, 1)->msg_buffer;
assert(toku_are_fifos_same(src_fifo_1, dest_fifo_1)); assert(src_msg_buffer1->equals(dest_msg_buffer1));
assert(toku_are_fifos_same(src_fifo_2, dest_fifo_2)); assert(src_msg_buffer2->equals(dest_msg_buffer2));
toku_ftnode_free(&dn); toku_ftnode_free(&dn);
......
...@@ -384,14 +384,29 @@ flush_to_internal(FT_HANDLE t) { ...@@ -384,14 +384,29 @@ flush_to_internal(FT_HANDLE t) {
memset(parent_messages_present, 0, sizeof parent_messages_present); memset(parent_messages_present, 0, sizeof parent_messages_present);
memset(child_messages_present, 0, sizeof child_messages_present); memset(child_messages_present, 0, sizeof child_messages_present);
FIFO_ITERATE(child_bnc->buffer, key, keylen, val, vallen, type, msn, xids, is_fresh, struct checkit_fn {
{ int num_parent_messages;
FT_MSG *parent_messages;
int *parent_messages_present;
bool *parent_messages_is_fresh;
int num_child_messages;
FT_MSG *child_messages;
int *child_messages_present;
bool *child_messages_is_fresh;
checkit_fn(int np, FT_MSG *pm, int *npp, bool *pmf, int nc, FT_MSG *cm, int *ncp, bool *cmf) :
num_parent_messages(np), parent_messages(pm), parent_messages_present(npp), parent_messages_is_fresh(pmf),
num_child_messages(nc), child_messages(cm), child_messages_present(ncp), child_messages_is_fresh(cmf) {
}
int operator()(FT_MSG msg, bool is_fresh) {
DBT keydbt; DBT keydbt;
DBT valdbt; DBT valdbt;
toku_fill_dbt(&keydbt, key, keylen); toku_fill_dbt(&keydbt, ft_msg_get_key(msg), ft_msg_get_keylen(msg));
toku_fill_dbt(&valdbt, val, vallen); toku_fill_dbt(&valdbt, ft_msg_get_val(msg), ft_msg_get_vallen(msg));
int found = 0; int found = 0;
for (i = 0; i < num_parent_messages; ++i) { MSN msn = msg->msn;
enum ft_msg_type type = ft_msg_get_type(msg);
XIDS xids = ft_msg_get_xids(msg);
for (int i = 0; i < num_parent_messages; ++i) {
if (dummy_cmp(NULL, &keydbt, parent_messages[i]->u.id.key) == 0 && if (dummy_cmp(NULL, &keydbt, parent_messages[i]->u.id.key) == 0 &&
msn.msn == parent_messages[i]->msn.msn) { msn.msn == parent_messages[i]->msn.msn) {
assert(parent_messages_present[i] == 0); assert(parent_messages_present[i] == 0);
...@@ -404,7 +419,7 @@ flush_to_internal(FT_HANDLE t) { ...@@ -404,7 +419,7 @@ flush_to_internal(FT_HANDLE t) {
found++; found++;
} }
} }
for (i = 0; i < num_child_messages; ++i) { for (int i = 0; i < num_child_messages; ++i) {
if (dummy_cmp(NULL, &keydbt, child_messages[i]->u.id.key) == 0 && if (dummy_cmp(NULL, &keydbt, child_messages[i]->u.id.key) == 0 &&
msn.msn == child_messages[i]->msn.msn) { msn.msn == child_messages[i]->msn.msn) {
assert(child_messages_present[i] == 0); assert(child_messages_present[i] == 0);
...@@ -418,7 +433,11 @@ flush_to_internal(FT_HANDLE t) { ...@@ -418,7 +433,11 @@ flush_to_internal(FT_HANDLE t) {
} }
} }
assert(found == 1); assert(found == 1);
}); return 0;
}
} checkit(num_parent_messages, parent_messages, parent_messages_present, parent_messages_is_fresh,
num_child_messages, child_messages, child_messages_present, child_messages_is_fresh);
child_bnc->msg_buffer.iterate(checkit);
for (i = 0; i < num_parent_messages; ++i) { for (i = 0; i < num_parent_messages; ++i) {
assert(parent_messages_present[i] == 1); assert(parent_messages_present[i] == 1);
...@@ -525,14 +544,29 @@ flush_to_internal_multiple(FT_HANDLE t) { ...@@ -525,14 +544,29 @@ flush_to_internal_multiple(FT_HANDLE t) {
memset(child_messages_present, 0, sizeof child_messages_present); memset(child_messages_present, 0, sizeof child_messages_present);
for (int j = 0; j < 8; ++j) { for (int j = 0; j < 8; ++j) {
FIFO_ITERATE(child_bncs[j]->buffer, key, keylen, val, vallen, type, msn, xids, is_fresh, struct checkit_fn {
{ int num_parent_messages;
FT_MSG *parent_messages;
int *parent_messages_present;
bool *parent_messages_is_fresh;
int num_child_messages;
FT_MSG *child_messages;
int *child_messages_present;
bool *child_messages_is_fresh;
checkit_fn(int np, FT_MSG *pm, int *npp, bool *pmf, int nc, FT_MSG *cm, int *ncp, bool *cmf) :
num_parent_messages(np), parent_messages(pm), parent_messages_present(npp), parent_messages_is_fresh(pmf),
num_child_messages(nc), child_messages(cm), child_messages_present(ncp), child_messages_is_fresh(cmf) {
}
int operator()(FT_MSG msg, bool is_fresh) {
DBT keydbt; DBT keydbt;
DBT valdbt; DBT valdbt;
toku_fill_dbt(&keydbt, key, keylen); toku_fill_dbt(&keydbt, ft_msg_get_key(msg), ft_msg_get_keylen(msg));
toku_fill_dbt(&valdbt, val, vallen); toku_fill_dbt(&valdbt, ft_msg_get_val(msg), ft_msg_get_vallen(msg));
int found = 0; int found = 0;
for (i = 0; i < num_parent_messages; ++i) { MSN msn = msg->msn;
enum ft_msg_type type = ft_msg_get_type(msg);
XIDS xids = ft_msg_get_xids(msg);
for (int i = 0; i < num_parent_messages; ++i) {
if (dummy_cmp(NULL, &keydbt, parent_messages[i]->u.id.key) == 0 && if (dummy_cmp(NULL, &keydbt, parent_messages[i]->u.id.key) == 0 &&
msn.msn == parent_messages[i]->msn.msn) { msn.msn == parent_messages[i]->msn.msn) {
assert(parent_messages_present[i] == 0); assert(parent_messages_present[i] == 0);
...@@ -545,7 +579,7 @@ flush_to_internal_multiple(FT_HANDLE t) { ...@@ -545,7 +579,7 @@ flush_to_internal_multiple(FT_HANDLE t) {
found++; found++;
} }
} }
for (i = 0; i < num_child_messages; ++i) { for (int i = 0; i < num_child_messages; ++i) {
if (dummy_cmp(NULL, &keydbt, child_messages[i]->u.id.key) == 0 && if (dummy_cmp(NULL, &keydbt, child_messages[i]->u.id.key) == 0 &&
msn.msn == child_messages[i]->msn.msn) { msn.msn == child_messages[i]->msn.msn) {
assert(child_messages_present[i] == 0); assert(child_messages_present[i] == 0);
...@@ -559,7 +593,11 @@ flush_to_internal_multiple(FT_HANDLE t) { ...@@ -559,7 +593,11 @@ flush_to_internal_multiple(FT_HANDLE t) {
} }
} }
assert(found == 1); assert(found == 1);
}); return 0;
}
} checkit(num_parent_messages, parent_messages, parent_messages_present, parent_messages_is_fresh,
num_child_messages, child_messages, child_messages_present, child_messages_is_fresh);
child_bncs[j]->msg_buffer.iterate(checkit);
} }
for (i = 0; i < num_parent_messages; ++i) { for (i = 0; i < num_parent_messages; ++i) {
...@@ -721,11 +759,13 @@ flush_to_leaf(FT_HANDLE t, bool make_leaf_up_to_date, bool use_flush) { ...@@ -721,11 +759,13 @@ flush_to_leaf(FT_HANDLE t, bool make_leaf_up_to_date, bool use_flush) {
bool msgs_applied; bool msgs_applied;
toku_apply_ancestors_messages_to_node(t, child, &ancestors, &infinite_bounds, &msgs_applied, -1); toku_apply_ancestors_messages_to_node(t, child, &ancestors, &infinite_bounds, &msgs_applied, -1);
FIFO_ITERATE(parent_bnc->buffer, key, keylen, val, vallen, type, msn, xids, is_fresh, struct checkit_fn {
{ int operator()(FT_MSG UU(msg), bool is_fresh) {
key = key; keylen = keylen; val = val; vallen = vallen; type = type; msn = msn; xids = xids;
assert(!is_fresh); assert(!is_fresh);
}); return 0;
}
} checkit;
parent_bnc->msg_buffer.iterate(checkit);
invariant(parent_bnc->fresh_message_tree.size() + parent_bnc->stale_message_tree.size() invariant(parent_bnc->fresh_message_tree.size() + parent_bnc->stale_message_tree.size()
== (uint32_t) num_parent_messages); == (uint32_t) num_parent_messages);
...@@ -947,13 +987,20 @@ flush_to_leaf_with_keyrange(FT_HANDLE t, bool make_leaf_up_to_date) { ...@@ -947,13 +987,20 @@ flush_to_leaf_with_keyrange(FT_HANDLE t, bool make_leaf_up_to_date) {
bool msgs_applied; bool msgs_applied;
toku_apply_ancestors_messages_to_node(t, child, &ancestors, &bounds, &msgs_applied, -1); toku_apply_ancestors_messages_to_node(t, child, &ancestors, &bounds, &msgs_applied, -1);
FIFO_ITERATE(parent_bnc->buffer, key, keylen, val, vallen, type, msn, xids, is_fresh, struct checkit_fn {
{ DBT *childkeys;
val = val; vallen = vallen; type = type; msn = msn; xids = xids; int num_parent_messages;
FT_MSG *parent_messages;
bool *parent_messages_is_fresh;
checkit_fn(DBT *ck, int np, FT_MSG *pm, bool *pmf) :
childkeys(ck), num_parent_messages(np), parent_messages(pm), parent_messages_is_fresh(pmf) {
}
int operator()(FT_MSG msg, bool is_fresh) {
DBT keydbt; DBT keydbt;
toku_fill_dbt(&keydbt, key, keylen); toku_fill_dbt(&keydbt, ft_msg_get_key(msg), ft_msg_get_keylen(msg));
MSN msn = msg->msn;
if (dummy_cmp(NULL, &keydbt, &childkeys[7]) > 0) { if (dummy_cmp(NULL, &keydbt, &childkeys[7]) > 0) {
for (i = 0; i < num_parent_messages; ++i) { for (int i = 0; i < num_parent_messages; ++i) {
if (dummy_cmp(NULL, &keydbt, parent_messages[i]->u.id.key) == 0 && if (dummy_cmp(NULL, &keydbt, parent_messages[i]->u.id.key) == 0 &&
msn.msn == parent_messages[i]->msn.msn) { msn.msn == parent_messages[i]->msn.msn) {
assert(is_fresh == parent_messages_is_fresh[i]); assert(is_fresh == parent_messages_is_fresh[i]);
...@@ -963,7 +1010,10 @@ flush_to_leaf_with_keyrange(FT_HANDLE t, bool make_leaf_up_to_date) { ...@@ -963,7 +1010,10 @@ flush_to_leaf_with_keyrange(FT_HANDLE t, bool make_leaf_up_to_date) {
} else { } else {
assert(!is_fresh); assert(!is_fresh);
} }
}); return 0;
}
} checkit(childkeys, num_parent_messages, parent_messages, parent_messages_is_fresh);
parent_bnc->msg_buffer.iterate(checkit);
toku_ftnode_free(&parentnode); toku_ftnode_free(&parentnode);
...@@ -1134,11 +1184,13 @@ compare_apply_and_flush(FT_HANDLE t, bool make_leaf_up_to_date) { ...@@ -1134,11 +1184,13 @@ compare_apply_and_flush(FT_HANDLE t, bool make_leaf_up_to_date) {
bool msgs_applied; bool msgs_applied;
toku_apply_ancestors_messages_to_node(t, child2, &ancestors, &infinite_bounds, &msgs_applied, -1); toku_apply_ancestors_messages_to_node(t, child2, &ancestors, &infinite_bounds, &msgs_applied, -1);
FIFO_ITERATE(parent_bnc->buffer, key, keylen, val, vallen, type, msn, xids, is_fresh, struct checkit_fn {
{ int operator()(FT_MSG UU(msg), bool is_fresh) {
key = key; keylen = keylen; val = val; vallen = vallen; type = type; msn = msn; xids = xids;
assert(!is_fresh); assert(!is_fresh);
}); return 0;
}
} checkit;
parent_bnc->msg_buffer.iterate(checkit);
invariant(parent_bnc->fresh_message_tree.size() + parent_bnc->stale_message_tree.size() invariant(parent_bnc->fresh_message_tree.size() + parent_bnc->stale_message_tree.size()
== (uint32_t) num_parent_messages); == (uint32_t) num_parent_messages);
......
...@@ -276,11 +276,18 @@ static void dump_node(int fd, BLOCKNUM blocknum, FT h) { ...@@ -276,11 +276,18 @@ static void dump_node(int fd, BLOCKNUM blocknum, FT h) {
printf(" buffer contains %u bytes (%d items)\n", n_bytes, n_entries); printf(" buffer contains %u bytes (%d items)\n", n_bytes, n_entries);
} }
if (do_dump_data) { if (do_dump_data) {
FIFO_ITERATE(bnc->buffer, key, keylen, data, datalen, typ, msn, xids, UU(is_fresh), struct dump_data_fn {
{ int operator()(FT_MSG msg, bool UU(is_fresh)) {
enum ft_msg_type type = (enum ft_msg_type) msg->type;
MSN msn = msg->msn;
XIDS xids = msg->xids;
const void *key = ft_msg_get_key(msg);
const void *data = ft_msg_get_val(msg);
ITEMLEN keylen = ft_msg_get_keylen(msg);
ITEMLEN datalen = ft_msg_get_vallen(msg);
printf(" msn=%" PRIu64 " (0x%" PRIx64 ") ", msn.msn, msn.msn); printf(" msn=%" PRIu64 " (0x%" PRIx64 ") ", msn.msn, msn.msn);
printf(" TYPE="); printf(" TYPE=");
switch ((enum ft_msg_type)typ) { switch (type) {
case FT_NONE: printf("NONE"); goto ok; case FT_NONE: printf("NONE"); goto ok;
case FT_INSERT: printf("INSERT"); goto ok; case FT_INSERT: printf("INSERT"); goto ok;
case FT_INSERT_NO_OVERWRITE: printf("INSERT_NO_OVERWRITE"); goto ok; case FT_INSERT_NO_OVERWRITE: printf("INSERT_NO_OVERWRITE"); goto ok;
...@@ -296,7 +303,7 @@ static void dump_node(int fd, BLOCKNUM blocknum, FT h) { ...@@ -296,7 +303,7 @@ static void dump_node(int fd, BLOCKNUM blocknum, FT h) {
case FT_UPDATE_BROADCAST_ALL: printf("UPDATE_BROADCAST_ALL"); goto ok; case FT_UPDATE_BROADCAST_ALL: printf("UPDATE_BROADCAST_ALL"); goto ok;
} }
printf("HUH?"); printf("HUH?");
ok: ok:
printf(" xid="); printf(" xid=");
xids_fprintf(stdout, xids); xids_fprintf(stdout, xids);
printf(" "); printf(" ");
...@@ -306,8 +313,10 @@ static void dump_node(int fd, BLOCKNUM blocknum, FT h) { ...@@ -306,8 +313,10 @@ static void dump_node(int fd, BLOCKNUM blocknum, FT h) {
print_item(data, datalen); print_item(data, datalen);
} }
printf("\n"); printf("\n");
return 0;
} }
); } dump_fn;
bnc->msg_buffer.iterate(dump_fn);
} }
} else { } else {
printf(" n_bytes_in_buffer= %" PRIu64 "", BLB_DATA(n, i)->get_disk_size()); printf(" n_bytes_in_buffer= %" PRIu64 "", BLB_DATA(n, i)->get_disk_size());
......
...@@ -98,6 +98,8 @@ PATENT RIGHTS GRANT: ...@@ -98,6 +98,8 @@ PATENT RIGHTS GRANT:
// ids[num_xids - 1] is the innermost transaction. // ids[num_xids - 1] is the innermost transaction.
// Should only be accessed by accessor functions xids_xxx, not directly. // Should only be accessed by accessor functions xids_xxx, not directly.
#include <portability/toku_stdint.h>
// If the xids struct is unpacked, the compiler aligns the ids[] and we waste a lot of space // If the xids struct is unpacked, the compiler aligns the ids[] and we waste a lot of space
typedef struct __attribute__((__packed__)) xids_t { typedef struct __attribute__((__packed__)) xids_t {
uint8_t num_xids; // maximum value of MAX_TRANSACTION_RECORDS - 1 ... uint8_t num_xids; // maximum value of MAX_TRANSACTION_RECORDS - 1 ...
......
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