Commit 28a62801 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 c370ee4c
......@@ -30,7 +30,6 @@ set(FT_SOURCES
cachetable
checkpoint
compress
fifo
ft
ft-cachetable-wrappers
ft-flusher
......@@ -52,6 +51,7 @@ set(FT_SOURCES
logfilemgr
logger
log_upgrade
msg_buffer
quicklz
recover
rollback
......
......@@ -198,9 +198,6 @@ void block_allocator_print (BLOCK_ALLOCATOR ba);
uint64_t block_allocator_allocated_limit (BLOCK_ALLOCATOR ba);
// Effect: Return the unallocated block address of "infinite" size.
// 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);
// 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:
#include "ft_layout_version.h"
#include "block_allocator.h"
#include "cachetable.h"
#include "fifo.h"
#include "ft-ops.h"
#include "toku_list.h"
#include <util/omt.h>
......@@ -118,6 +117,7 @@ PATENT RIGHTS GRANT:
#include "ft/bndata.h"
#include "ft/rollback.h"
#include "ft/ft-search.h"
#include "ft/msg_buffer.h"
enum { KEY_VALUE_OVERHEAD = 8 }; /* Must store the two lengths. */
enum { FT_MSG_OVERHEAD = (2 + sizeof(MSN)) }; // the type plus freshness plus MSN
......@@ -207,10 +207,10 @@ struct 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;
ft_compare_func cmp;
FIFO fifo;
message_buffer *msg_buffer;
const DBT *key;
MSN msn;
};
......@@ -218,24 +218,24 @@ struct toku_fifo_entry_key_msn_heaviside_extra {
// comparison function for inserting messages into a
// ftnode_nonleaf_childinfo's message_tree
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;
ft_compare_func cmp;
FIFO fifo;
message_buffer *msg_buffer;
};
// same thing for qsort_r
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, int32_t, true> marked_off_omt_t;
// data of an available partition of a nonleaf ftnode
struct ftnode_nonleaf_childinfo {
FIFO buffer;
message_buffer msg_buffer;
off_omt_t broadcast_list;
marked_off_omt_t fresh_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
__attribute__((nonnull))
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
toku_ft_search_which_child(
DESCRIPTOR desc,
......
This diff is collapsed.
This diff is collapsed.
......@@ -187,7 +187,7 @@ ft_log_fassociate_during_checkpoint (CACHEFILE cf, void *header_v) {
}
// 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).
//
// Not reentrant for a single FT (see ft_checkpoint)
......
......@@ -2,7 +2,8 @@
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
/* 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
......
This diff is collapsed.
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
/*
COPYING CONDITIONS NOTICE:
......@@ -30,7 +30,7 @@ COPYING CONDITIONS NOTICE:
COPYRIGHT NOTICE:
TokuDB, Tokutek Fractal Tree Indexing Library.
Copyright (C) 2007-2013 Tokutek, Inc.
Copyright (C) 2014 Tokutek, Inc.
DISCLAIMER:
......@@ -86,69 +86,33 @@ PATENT RIGHTS GRANT:
under this License.
*/
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#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 "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);
}
#include "ft/msg_buffer.h"
#include "ft/ybt.h"
int toku_fifo_create(FIFO *ptr) {
struct fifo *XMALLOC(fifo);
if (fifo == 0) return ENOMEM;
fifo_init(fifo);
*ptr = fifo;
return 0;
void message_buffer::create() {
_num_entries = 0;
_memory = nullptr;
_memory_size = 0;
_memory_used = 0;
}
void toku_fifo_resize(FIFO fifo, size_t new_size) {
XREALLOC_N(new_size, fifo->memory);
fifo->memory_size = new_size;
void message_buffer::clone(message_buffer *src) {
_num_entries = src->_num_entries;
_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) {
FIFO fifo = *ptr;
if (fifo->memory) toku_free(fifo->memory);
fifo->memory=0;
toku_free(fifo);
*ptr = 0;
void message_buffer::destroy() {
if (_memory != nullptr) {
toku_free(_memory);
}
}
int toku_fifo_n_entries(FIFO fifo) {
return fifo->n_items_in_fifo;
void message_buffer::resize(size_t new_size) {
XREALLOC_N(new_size, _memory);
_memory_size = new_size;
}
static int next_power_of_two (int n) {
......@@ -160,94 +124,101 @@ static int next_power_of_two (int n) {
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) {
int need_space_here = sizeof(struct fifo_entry)
struct message_buffer::buffer_entry *message_buffer::get_buffer_entry(int32_t offset) const {
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
+ xids_get_size(xids)
- sizeof(XIDS_S); //Prevent double counting
int need_space_total = fifo->memory_used+need_space_here;
if (fifo->memory == NULL || need_space_total > fifo->memory_size) {
// resize the fifo to the next power of 2 greater than the needed space
int need_space_total = _memory_used + need_space_here;
if (_memory == nullptr || need_space_total > _memory_size) {
// resize the buffer to the next power of 2 greater than the needed space
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);
entry->type = (unsigned char) type;
entry->msn = msn;
struct buffer_entry *entry = get_buffer_entry(_memory_used);
entry->type = (unsigned char) ft_msg_get_type(msg);
entry->msn = msg->msn;
xids_cpy(&entry->xids_s, xids);
entry->is_fresh = is_fresh;
entry->keylen = keylen;
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;
memcpy(e_key + keylen, data, datalen);
if (dest) {
*dest = fifo->memory_used;
memcpy(e_key + keylen, ft_msg_get_val(msg), datalen);
if (offset) {
*offset = _memory_used;
}
fifo->n_items_in_fifo++;
fifo->memory_used += need_space_here;
return 0;
_num_entries++;
_memory_used += need_space_here;
}
int toku_fifo_iterate_internal_start(FIFO UU(fifo)) { return 0; }
int toku_fifo_iterate_internal_has_more(FIFO fifo, int off) { return off < fifo->memory_used; }
int toku_fifo_iterate_internal_next(FIFO fifo, int off) {
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);
void message_buffer::set_freshness(int32_t offset, bool is_fresh) {
struct buffer_entry *entry = get_buffer_entry(offset);
entry->is_fresh = is_fresh;
}
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) {
FIFO_ITERATE(fifo,
key, keylen, data, datalen, type, msn, xids, is_fresh,
f(key,keylen,data,datalen,type,msn,xids,is_fresh, arg));
FT_MSG_S message_buffer::get_message(int32_t offset, DBT *keydbt, DBT *valdbt) const {
struct buffer_entry *entry = get_buffer_entry(offset);
ITEMLEN keylen = entry->keylen;
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) {
return fifo->memory_used;
void message_buffer::get_message_key_msn(int32_t offset, DBT *key, MSN *msn) const {
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) {
return sizeof(*fifo)+fifo->memory_used;
int message_buffer::num_entries() const {
return _num_entries;
}
unsigned long toku_fifo_memory_footprint(FIFO fifo) {
size_t size_used = toku_memory_footprint(fifo->memory, fifo->memory_used);
long rval = sizeof(*fifo) + size_used;
return rval;
size_t message_buffer::buffer_size_in_use() const {
return _memory_used;
}
DBT *fill_dbt_for_fifo_entry(DBT *dbt, const struct fifo_entry *entry) {
return toku_fill_dbt(dbt, xids_get_end_of_array((XIDS) &entry->xids_s), entry->keylen);
size_t message_buffer::memory_size_in_use() const {
return sizeof(*this) + _memory_used;
}
struct fifo_entry *toku_fifo_get_entry(FIFO fifo, int off) {
return toku_fifo_iterate_internal_get_entry(fifo, off);
size_t message_buffer::memory_footprint() const {
return sizeof(*this) + toku_memory_footprint(_memory, _memory_used);
}
void toku_fifo_clone(FIFO orig_fifo, FIFO* cloned_fifo) {
struct fifo *XMALLOC(new_fifo);
assert(new_fifo);
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 message_buffer::equals(message_buffer *other) const {
return (_memory_used == other->_memory_used &&
memcmp(_memory, other->_memory, _memory_used) == 0);
}
bool toku_are_fifos_same(FIFO fifo1, FIFO fifo2) {
return (
fifo1->memory_used == fifo2->memory_used &&
memcmp(fifo1->memory, fifo2->memory, fifo1->memory_used) == 0
);
size_t message_buffer::msg_memsize_in_buffer(FT_MSG msg) {
return sizeof(struct buffer_entry)
+ msg->u.id.key->size + msg->u.id.val->size
+ xids_get_size(msg->xids)
- sizeof(XIDS_S);
}
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ifndef FIFO_H
#define FIFO_H
#ident "$Id$"
/*
COPYING CONDITIONS NOTICE:
......@@ -32,7 +30,7 @@ COPYING CONDITIONS NOTICE:
COPYRIGHT NOTICE:
TokuDB, Tokutek Fractal Tree Indexing Library.
Copyright (C) 2007-2013 Tokutek, Inc.
Copyright (C) 2014 Tokutek, Inc.
DISCLAIMER:
......@@ -88,77 +86,76 @@ PATENT RIGHTS GRANT:
under this License.
*/
#ident "Copyright (c) 2007-2013 Tokutek Inc. All rights reserved."
#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."
#pragma once
#include "ft/fttypes.h"
#include "ft/xids-internal.h"
#include "ft/xids.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
struct __attribute__((__packed__)) fifo_entry {
unsigned int keylen;
unsigned int vallen;
unsigned char type;
bool is_fresh;
MSN msn;
XIDS_S xids_s;
};
typedef struct fifo *FIFO;
class message_buffer {
public:
void create();
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);
unsigned long toku_fifo_memory_size_in_use(FIFO fifo); // return how much memory in the fifo holds useful data
bool get_freshness(int32_t offset) const;
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) ({ \
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; \
} })
int num_entries() const;
#define FIFO_CURRENT_ENTRY_MEMSIZE toku_fifo_internal_entry_memsize(e)
size_t buffer_size_in_use() const;
// Internal functions for the iterator.
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));
size_t memory_size_in_use() const;
DBT *fill_dbt_for_fifo_entry(DBT *dbt, const struct fifo_entry *entry);
struct fifo_entry *toku_fifo_get_entry(FIFO fifo, int off);
size_t memory_footprint() const;
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:
#include "test.h"
static void
test_fifo_create (void) {
int r;
FIFO f;
f = 0;
r = toku_fifo_create(&f);
assert(r == 0); assert(f != 0);
toku_fifo_free(&f);
assert(f == 0);
test_create (void) {
message_buffer msg_buffer;
msg_buffer.create();
msg_buffer.destroy();
}
static void
test_fifo_enq (int n) {
test_enqueue(int n) {
int r;
FIFO f;
message_buffer msg_buffer;
MSN startmsn = ZERO_MSN;
f = 0;
r = toku_fifo_create(&f);
assert(r == 0); assert(f != 0);
msg_buffer.create();
char *thekey = 0; int thekeylen;
char *theval = 0; int thevallen;
......@@ -146,38 +137,56 @@ test_fifo_enq (int n) {
if (startmsn.msn == ZERO_MSN.msn)
startmsn = msn;
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);
}
int i = 0;
FIFO_ITERATE(f, key, keylen, val, vallen, type, msn, xids, UU(is_fresh), {
if (verbose) printf("checkit %d %d %" PRIu64 "\n", i, type, msn.msn);
assert(msn.msn == startmsn.msn + i);
buildkey(i);
buildval(i);
assert((int) keylen == thekeylen); assert(memcmp(key, thekey, keylen) == 0);
assert((int) vallen == thevallen); assert(memcmp(val, theval, vallen) == 0);
assert(i % 256 == (int)type);
assert((TXNID)i==xids_get_innermost_xid(xids));
i += 1;
});
assert(i == n);
struct checkit_fn {
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);
assert(msn.msn == startmsn.msn + i);
buildkey(i);
buildval(i);
assert((int) ft_msg_get_keylen(msg) == thekeylen); assert(memcmp(ft_msg_get_key(msg), thekey, ft_msg_get_keylen(msg)) == 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((TXNID)i==xids_get_innermost_xid(ft_msg_get_xids(msg)));
i += 1;
return 0;
}
} checkit(thekey, thekeylen, theval, thevallen, startmsn, verbose);
msg_buffer.iterate(checkit);
assert(checkit.i == n);
if (thekey) toku_free(thekey);
if (theval) toku_free(theval);
toku_fifo_free(&f);
assert(f == 0);
msg_buffer.destroy();
}
int
test_main(int argc, const char *argv[]) {
default_parse_args(argc, argv);
initialize_dummymsn();
test_fifo_create();
test_fifo_enq(4);
test_fifo_enq(512);
test_create();
test_enqueue(4);
test_enqueue(512);
return 0;
}
......@@ -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,1).b==35);
FIFO src_fifo_1 = BNC(&sn, 0)->buffer;
FIFO src_fifo_2 = BNC(&sn, 1)->buffer;
FIFO dest_fifo_1 = BNC(dn, 0)->buffer;
FIFO dest_fifo_2 = BNC(dn, 1)->buffer;
message_buffer *src_msg_buffer1 = &BNC(&sn, 0)->msg_buffer;
message_buffer *src_msg_buffer2 = &BNC(&sn, 1)->msg_buffer;
message_buffer *dest_msg_buffer1 = &BNC(dn, 0)->msg_buffer;
message_buffer *dest_msg_buffer2 = &BNC(dn, 1)->msg_buffer;
assert(toku_are_fifos_same(src_fifo_1, dest_fifo_1));
assert(toku_are_fifos_same(src_fifo_2, dest_fifo_2));
assert(src_msg_buffer1->equals(dest_msg_buffer1));
assert(src_msg_buffer2->equals(dest_msg_buffer2));
toku_ftnode_free(&dn);
......
This diff is collapsed.
......@@ -276,38 +276,47 @@ static void dump_node(int fd, BLOCKNUM blocknum, FT h) {
printf(" buffer contains %u bytes (%d items)\n", n_bytes, n_entries);
}
if (do_dump_data) {
FIFO_ITERATE(bnc->buffer, key, keylen, data, datalen, typ, msn, xids, UU(is_fresh),
{
printf(" msn=%" PRIu64 " (0x%" PRIx64 ") ", msn.msn, msn.msn);
printf(" TYPE=");
switch ((enum ft_msg_type)typ) {
case FT_NONE: printf("NONE"); goto ok;
case FT_INSERT: printf("INSERT"); goto ok;
case FT_INSERT_NO_OVERWRITE: printf("INSERT_NO_OVERWRITE"); goto ok;
case FT_DELETE_ANY: printf("DELETE_ANY"); goto ok;
case FT_ABORT_ANY: printf("ABORT_ANY"); goto ok;
case FT_COMMIT_ANY: printf("COMMIT_ANY"); goto ok;
case FT_COMMIT_BROADCAST_ALL: printf("COMMIT_BROADCAST_ALL"); goto ok;
case FT_COMMIT_BROADCAST_TXN: printf("COMMIT_BROADCAST_TXN"); goto ok;
case FT_ABORT_BROADCAST_TXN: printf("ABORT_BROADCAST_TXN"); goto ok;
case FT_OPTIMIZE: printf("OPTIMIZE"); goto ok;
case FT_OPTIMIZE_FOR_UPGRADE: printf("OPTIMIZE_FOR_UPGRADE"); goto ok;
case FT_UPDATE: printf("UPDATE"); goto ok;
case FT_UPDATE_BROADCAST_ALL: printf("UPDATE_BROADCAST_ALL"); goto ok;
}
printf("HUH?");
ok:
printf(" xid=");
xids_fprintf(stdout, xids);
printf(" ");
print_item(key, keylen);
if (datalen>0) {
printf(" ");
print_item(data, datalen);
}
printf("\n");
}
);
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(" TYPE=");
switch (type) {
case FT_NONE: printf("NONE"); goto ok;
case FT_INSERT: printf("INSERT"); goto ok;
case FT_INSERT_NO_OVERWRITE: printf("INSERT_NO_OVERWRITE"); goto ok;
case FT_DELETE_ANY: printf("DELETE_ANY"); goto ok;
case FT_ABORT_ANY: printf("ABORT_ANY"); goto ok;
case FT_COMMIT_ANY: printf("COMMIT_ANY"); goto ok;
case FT_COMMIT_BROADCAST_ALL: printf("COMMIT_BROADCAST_ALL"); goto ok;
case FT_COMMIT_BROADCAST_TXN: printf("COMMIT_BROADCAST_TXN"); goto ok;
case FT_ABORT_BROADCAST_TXN: printf("ABORT_BROADCAST_TXN"); goto ok;
case FT_OPTIMIZE: printf("OPTIMIZE"); goto ok;
case FT_OPTIMIZE_FOR_UPGRADE: printf("OPTIMIZE_FOR_UPGRADE"); goto ok;
case FT_UPDATE: printf("UPDATE"); goto ok;
case FT_UPDATE_BROADCAST_ALL: printf("UPDATE_BROADCAST_ALL"); goto ok;
}
printf("HUH?");
ok:
printf(" xid=");
xids_fprintf(stdout, xids);
printf(" ");
print_item(key, keylen);
if (datalen>0) {
printf(" ");
print_item(data, datalen);
}
printf("\n");
return 0;
}
} dump_fn;
bnc->msg_buffer.iterate(dump_fn);
}
} else {
printf(" n_bytes_in_buffer= %" PRIu64 "", BLB_DATA(n, i)->get_disk_size());
......
......@@ -98,6 +98,8 @@ PATENT RIGHTS GRANT:
// ids[num_xids - 1] is the innermost transaction.
// 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
typedef struct __attribute__((__packed__)) xids_t {
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