Commit ea0736aa authored by John Esmet's avatar John Esmet Committed by Yoni Fogel

fixes #5723 refs #5801 merge 5723 to main and merge some last-minute 5801 fixes:

- widely adopt the use of ybt abstractions instead of raw dbt management. TODO: the loader and the descriptor are still manually managed.
- remove templates from the perf framework in favor of explicit key size checks that more accurately describe "How Keys/Vals Work", and prevent type related bugs.
- also: removed some dead code, refs #5101



git-svn-id: file:///svn/toku/tokudb@51665 c7de825b-a66e-492c-adef-691d508d4ae1
parent b32f4f52
...@@ -67,43 +67,13 @@ hot_set_highest_key(struct hot_flusher_extra *flusher) ...@@ -67,43 +67,13 @@ hot_set_highest_key(struct hot_flusher_extra *flusher)
// The max current key will be NULL if we are traversing in the // The max current key will be NULL if we are traversing in the
// rightmost subtree of a given parent. As such, we don't want to // rightmost subtree of a given parent. As such, we don't want to
// allocate memory for this case. // allocate memory for this case.
if (flusher->max_current_key.data == NULL) { toku_destroy_dbt(&flusher->highest_pivot_key);
if (flusher->highest_pivot_key.data) { if (flusher->max_current_key.data != NULL) {
toku_free(flusher->highest_pivot_key.data);
}
flusher->highest_pivot_key.data = NULL;
} else {
// Otherwise, let's copy all the contents from one key to the other. // Otherwise, let's copy all the contents from one key to the other.
void *source = flusher->max_current_key.data; toku_clone_dbt(&flusher->highest_pivot_key, flusher->max_current_key);
void *destination = flusher->highest_pivot_key.data;
uint32_t size = flusher->max_current_key.size;
destination = toku_xrealloc(destination, size);
memcpy(destination, source, size);
// Finish copying all fields from the max current key.
// Add free here.
toku_fill_dbt(&(flusher->highest_pivot_key), destination, size);
} }
} }
// Copies the pivot key in the parent to the given DBT key, using the
// pivot corresponding to the given child.
static void
hot_set_key(DBT *key, FTNODE parent, int childnum)
{
// assert that childnum is less than number of children - 1.
DBT *pivot = &parent->childkeys[childnum];
void *data = key->data;
uint32_t size = pivot->size;
data = toku_xrealloc(data, size);
memcpy(data, pivot->data, size);
toku_fill_dbt(key, data, size);
}
static int static int
hot_just_pick_child(FT h, hot_just_pick_child(FT h,
FTNODE parent, FTNODE parent,
...@@ -137,7 +107,8 @@ hot_update_flusher_keys(FTNODE parent, ...@@ -137,7 +107,8 @@ hot_update_flusher_keys(FTNODE parent,
// Update maximum current key if the child is NOT the rightmost // Update maximum current key if the child is NOT the rightmost
// child node. // child node.
if (childnum < (parent->n_children - 1)) { if (childnum < (parent->n_children - 1)) {
hot_set_key(&flusher->max_current_key, parent, childnum); toku_destroy_dbt(&flusher->max_current_key);
toku_clone_dbt(&flusher->max_current_key, parent->childkeys[childnum]);
} }
} }
...@@ -227,13 +198,8 @@ hot_flusher_init(struct flusher_advice *advice, ...@@ -227,13 +198,8 @@ hot_flusher_init(struct flusher_advice *advice,
static void static void
hot_flusher_destroy(struct hot_flusher_extra *flusher) hot_flusher_destroy(struct hot_flusher_extra *flusher)
{ {
if (flusher->highest_pivot_key.data) { toku_destroy_dbt(&flusher->highest_pivot_key);
toku_free(flusher->highest_pivot_key.data); toku_destroy_dbt(&flusher->max_current_key);
}
if (flusher->max_current_key.data) {
toku_free(flusher->max_current_key.data);
}
} }
// Entry point for Hot Optimize Table (HOT). Note, this function is // Entry point for Hot Optimize Table (HOT). Note, this function is
...@@ -254,9 +220,7 @@ toku_ft_hot_optimize(FT_HANDLE brt, ...@@ -254,9 +220,7 @@ toku_ft_hot_optimize(FT_HANDLE brt,
// start of HOT operation // start of HOT operation
(void) toku_sync_fetch_and_add(&STATUS_VALUE(FT_HOT_NUM_STARTED), 1); (void) toku_sync_fetch_and_add(&STATUS_VALUE(FT_HOT_NUM_STARTED), 1);
{
toku_ft_note_hot_begin(brt); toku_ft_note_hot_begin(brt);
}
// Higher level logic prevents a dictionary from being deleted or // Higher level logic prevents a dictionary from being deleted or
// truncated during a hot optimize operation. Doing so would violate // truncated during a hot optimize operation. Doing so would violate
...@@ -297,10 +261,7 @@ toku_ft_hot_optimize(FT_HANDLE brt, ...@@ -297,10 +261,7 @@ toku_ft_hot_optimize(FT_HANDLE brt,
// Initialize the maximum current key. We need to do this for // Initialize the maximum current key. We need to do this for
// every traversal. // every traversal.
if (flusher.max_current_key.data) { toku_destroy_dbt(&flusher.max_current_key);
toku_free(flusher.max_current_key.data);
}
flusher.max_current_key.data = NULL;
flusher.sub_tree_size = 1.0; flusher.sub_tree_size = 1.0;
flusher.percentage_done = 0.0; flusher.percentage_done = 0.0;
......
...@@ -78,7 +78,7 @@ struct ftnode_fetch_extra { ...@@ -78,7 +78,7 @@ struct ftnode_fetch_extra {
// used in the case where type == ftnode_fetch_subset // used in the case where type == ftnode_fetch_subset
// parameters needed to find out which child needs to be decompressed (so it can be read) // parameters needed to find out which child needs to be decompressed (so it can be read)
ft_search_t* search; ft_search_t* search;
DBT *range_lock_left_key, *range_lock_right_key; DBT range_lock_left_key, range_lock_right_key;
bool left_is_neg_infty, right_is_pos_infty; bool left_is_neg_infty, right_is_pos_infty;
// states if we should try to aggressively fetch basement nodes // states if we should try to aggressively fetch basement nodes
// that are not specifically needed for current query, // that are not specifically needed for current query,
...@@ -721,8 +721,8 @@ static inline void fill_bfe_for_full_read(struct ftnode_fetch_extra *bfe, FT h) ...@@ -721,8 +721,8 @@ static inline void fill_bfe_for_full_read(struct ftnode_fetch_extra *bfe, FT h)
bfe->type = ftnode_fetch_all; bfe->type = ftnode_fetch_all;
bfe->h = h; bfe->h = h;
bfe->search = NULL; bfe->search = NULL;
bfe->range_lock_left_key = NULL; toku_init_dbt(&bfe->range_lock_left_key);
bfe->range_lock_right_key = NULL; toku_init_dbt(&bfe->range_lock_right_key);
bfe->left_is_neg_infty = false; bfe->left_is_neg_infty = false;
bfe->right_is_pos_infty = false; bfe->right_is_pos_infty = false;
bfe->child_to_read = -1; bfe->child_to_read = -1;
...@@ -754,8 +754,14 @@ static inline void fill_bfe_for_subset_read( ...@@ -754,8 +754,14 @@ static inline void fill_bfe_for_subset_read(
bfe->type = ftnode_fetch_subset; bfe->type = ftnode_fetch_subset;
bfe->h = h; bfe->h = h;
bfe->search = search; bfe->search = search;
bfe->range_lock_left_key = (left->data ? left : NULL); toku_init_dbt(&bfe->range_lock_left_key);
bfe->range_lock_right_key = (right->data ? right : NULL); toku_init_dbt(&bfe->range_lock_right_key);
if (left) {
toku_copyref_dbt(&bfe->range_lock_left_key, *left);
}
if (right) {
toku_copyref_dbt(&bfe->range_lock_right_key, *right);
}
bfe->left_is_neg_infty = left_is_neg_infty; bfe->left_is_neg_infty = left_is_neg_infty;
bfe->right_is_pos_infty = right_is_pos_infty; bfe->right_is_pos_infty = right_is_pos_infty;
bfe->child_to_read = -1; bfe->child_to_read = -1;
...@@ -776,8 +782,8 @@ static inline void fill_bfe_for_min_read(struct ftnode_fetch_extra *bfe, FT h) { ...@@ -776,8 +782,8 @@ static inline void fill_bfe_for_min_read(struct ftnode_fetch_extra *bfe, FT h) {
bfe->type = ftnode_fetch_none; bfe->type = ftnode_fetch_none;
bfe->h = h; bfe->h = h;
bfe->search = NULL; bfe->search = NULL;
bfe->range_lock_left_key = NULL; toku_init_dbt(&bfe->range_lock_left_key);
bfe->range_lock_right_key = NULL; toku_init_dbt(&bfe->range_lock_right_key);
bfe->left_is_neg_infty = false; bfe->left_is_neg_infty = false;
bfe->right_is_pos_infty = false; bfe->right_is_pos_infty = false;
bfe->child_to_read = -1; bfe->child_to_read = -1;
...@@ -789,18 +795,8 @@ static inline void fill_bfe_for_min_read(struct ftnode_fetch_extra *bfe, FT h) { ...@@ -789,18 +795,8 @@ static inline void fill_bfe_for_min_read(struct ftnode_fetch_extra *bfe, FT h) {
static inline void destroy_bfe_for_prefetch(struct ftnode_fetch_extra *bfe) { static inline void destroy_bfe_for_prefetch(struct ftnode_fetch_extra *bfe) {
paranoid_invariant(bfe->type == ftnode_fetch_prefetch); paranoid_invariant(bfe->type == ftnode_fetch_prefetch);
if (bfe->range_lock_left_key != NULL) { toku_destroy_dbt(&bfe->range_lock_left_key);
toku_free(bfe->range_lock_left_key->data); toku_destroy_dbt(&bfe->range_lock_right_key);
toku_destroy_dbt(bfe->range_lock_left_key);
toku_free(bfe->range_lock_left_key);
bfe->range_lock_left_key = NULL;
}
if (bfe->range_lock_right_key != NULL) {
toku_free(bfe->range_lock_right_key->data);
toku_destroy_dbt(bfe->range_lock_right_key);
toku_free(bfe->range_lock_right_key);
bfe->range_lock_right_key = NULL;
}
} }
// this is in a strange place because it needs the cursor struct to be defined // this is in a strange place because it needs the cursor struct to be defined
...@@ -811,21 +807,15 @@ static inline void fill_bfe_for_prefetch(struct ftnode_fetch_extra *bfe, ...@@ -811,21 +807,15 @@ static inline void fill_bfe_for_prefetch(struct ftnode_fetch_extra *bfe,
bfe->type = ftnode_fetch_prefetch; bfe->type = ftnode_fetch_prefetch;
bfe->h = h; bfe->h = h;
bfe->search = NULL; bfe->search = NULL;
{ toku_init_dbt(&bfe->range_lock_left_key);
toku_init_dbt(&bfe->range_lock_right_key);
const DBT *left = &c->range_lock_left_key; const DBT *left = &c->range_lock_left_key;
const DBT *right = &c->range_lock_right_key;
if (left->data) { if (left->data) {
XMALLOC(bfe->range_lock_left_key); toku_clone_dbt(&bfe->range_lock_left_key, *left);
toku_fill_dbt(bfe->range_lock_left_key, toku_xmemdup(left->data, left->size), left->size);
} else {
bfe->range_lock_left_key = NULL;
} }
const DBT *right = &c->range_lock_right_key;
if (right->data) { if (right->data) {
XMALLOC(bfe->range_lock_right_key); toku_clone_dbt(&bfe->range_lock_right_key, *right);
toku_fill_dbt(bfe->range_lock_right_key, toku_xmemdup(right->data, right->size), right->size);
} else {
bfe->range_lock_right_key = NULL;
}
} }
bfe->left_is_neg_infty = c->left_is_neg_infty; bfe->left_is_neg_infty = c->left_is_neg_infty;
bfe->right_is_pos_infty = c->right_is_pos_infty; bfe->right_is_pos_infty = c->right_is_pos_infty;
......
This diff is collapsed.
...@@ -50,7 +50,6 @@ typedef struct ft_search { ...@@ -50,7 +50,6 @@ typedef struct ft_search {
// There also remains a potential thrashing problem. When we get a TOKUDB_TRY_AGAIN, we unpin everything. There's // There also remains a potential thrashing problem. When we get a TOKUDB_TRY_AGAIN, we unpin everything. There's
// no guarantee that we will get everything pinned again. We ought to keep nodes pinned when we retry, except that on the // no guarantee that we will get everything pinned again. We ought to keep nodes pinned when we retry, except that on the
// way out with a DB_NOTFOUND we ought to unpin those nodes. See #3528. // way out with a DB_NOTFOUND we ought to unpin those nodes. See #3528.
bool have_pivot_bound;
DBT pivot_bound; DBT pivot_bound;
} ft_search_t; } ft_search_t;
...@@ -60,13 +59,12 @@ static inline ft_search_t *ft_search_init(ft_search_t *so, ft_search_compare_fun ...@@ -60,13 +59,12 @@ static inline ft_search_t *ft_search_init(ft_search_t *so, ft_search_compare_fun
so->direction = direction; so->direction = direction;
so->k = k; so->k = k;
so->context = context; so->context = context;
so->have_pivot_bound = false; toku_init_dbt(&so->pivot_bound);
return so; return so;
} }
static inline void ft_search_finish(ft_search_t *so) { static inline void ft_search_finish(ft_search_t *so) {
if (so->have_pivot_bound) toku_free(so->pivot_bound.data); toku_destroy_dbt(&so->pivot_bound);
} }
#endif #endif
...@@ -7,10 +7,11 @@ ...@@ -7,10 +7,11 @@
#include <toku_portability.h> #include <toku_portability.h>
#include <toku_assert.h> #include <toku_assert.h>
#include <toku_pthread.h> #include <toku_pthread.h>
#include <string.h>
#include <errno.h> #include <errno.h>
#include "memory.h" #include <string.h>
#include "ftloader-internal.h" #include "ftloader-internal.h"
#include "ybt.h"
static void error_callback_lock(ft_loader_error_callback loader_error) { static void error_callback_lock(ft_loader_error_callback loader_error) {
toku_mutex_lock(&loader_error->mutex); toku_mutex_lock(&loader_error->mutex);
...@@ -22,13 +23,15 @@ static void error_callback_unlock(ft_loader_error_callback loader_error) { ...@@ -22,13 +23,15 @@ static void error_callback_unlock(ft_loader_error_callback loader_error) {
void ft_loader_init_error_callback(ft_loader_error_callback loader_error) { void ft_loader_init_error_callback(ft_loader_error_callback loader_error) {
memset(loader_error, 0, sizeof *loader_error); memset(loader_error, 0, sizeof *loader_error);
toku_init_dbt(&loader_error->key);
toku_init_dbt(&loader_error->val);
toku_mutex_init(&loader_error->mutex, NULL); toku_mutex_init(&loader_error->mutex, NULL);
} }
void ft_loader_destroy_error_callback(ft_loader_error_callback loader_error) { void ft_loader_destroy_error_callback(ft_loader_error_callback loader_error) {
toku_mutex_destroy(&loader_error->mutex); toku_mutex_destroy(&loader_error->mutex);
toku_free(loader_error->key.data); toku_destroy_dbt(&loader_error->key);
toku_free(loader_error->val.data); toku_destroy_dbt(&loader_error->val);
memset(loader_error, 0, sizeof *loader_error); memset(loader_error, 0, sizeof *loader_error);
} }
...@@ -44,14 +47,6 @@ void ft_loader_set_error_function(ft_loader_error_callback loader_error, ft_load ...@@ -44,14 +47,6 @@ void ft_loader_set_error_function(ft_loader_error_callback loader_error, ft_load
loader_error->extra = error_extra; loader_error->extra = error_extra;
} }
static void copy_dbt(DBT *dest, DBT *src) {
if (src) {
dest->data = toku_malloc(src->size);
memcpy(dest->data, src->data, src->size);
dest->size = src->size;
}
}
int ft_loader_set_error(ft_loader_error_callback loader_error, int error, DB *db, int which_db, DBT *key, DBT *val) { int ft_loader_set_error(ft_loader_error_callback loader_error, int error, DB *db, int which_db, DBT *key, DBT *val) {
int r; int r;
error_callback_lock(loader_error); error_callback_lock(loader_error);
...@@ -62,8 +57,12 @@ int ft_loader_set_error(ft_loader_error_callback loader_error, int error, DB *db ...@@ -62,8 +57,12 @@ int ft_loader_set_error(ft_loader_error_callback loader_error, int error, DB *db
loader_error->error = error; // set the error loader_error->error = error; // set the error
loader_error->db = db; loader_error->db = db;
loader_error->which_db = which_db; loader_error->which_db = which_db;
copy_dbt(&loader_error->key, key); // copy the data if (key != nullptr) {
copy_dbt(&loader_error->val, val); toku_clone_dbt(&loader_error->key, *key);
}
if (val != nullptr) {
toku_clone_dbt(&loader_error->val, *val);
}
} }
error_callback_unlock(loader_error); error_callback_unlock(loader_error);
return r; return r;
......
...@@ -216,11 +216,6 @@ toku_free(void *p) { ...@@ -216,11 +216,6 @@ toku_free(void *p) {
} }
} }
void
toku_free_n(void* p, size_t size __attribute__((unused))) {
toku_free(p);
}
void * void *
toku_xmalloc(size_t size) { toku_xmalloc(size_t size) {
void *p = t_xmalloc ? t_xmalloc(size) : os_malloc(size); void *p = t_xmalloc ? t_xmalloc(size) : os_malloc(size);
......
...@@ -106,8 +106,8 @@ struct __toku_loader_internal { ...@@ -106,8 +106,8 @@ struct __toku_loader_internal {
static void free_loader_resources(DB_LOADER *loader) static void free_loader_resources(DB_LOADER *loader)
{ {
if ( loader->i ) { if ( loader->i ) {
if (loader->i->err_key.data) toku_free(loader->i->err_key.data); toku_destroy_dbt(&loader->i->err_key);
if (loader->i->err_val.data) toku_free(loader->i->err_val.data); toku_destroy_dbt(&loader->i->err_val);
if (loader->i->inames_in_env) { if (loader->i->inames_in_env) {
for (int i=0; i<loader->i->N; i++) { for (int i=0; i<loader->i->N; i++) {
...@@ -194,8 +194,8 @@ toku_loader_create_loader(DB_ENV *env, ...@@ -194,8 +194,8 @@ toku_loader_create_loader(DB_ENV *env,
goto create_exit; goto create_exit;
} }
memset(&loader->i->err_key, 0, sizeof(loader->i->err_key)); toku_init_dbt(&loader->i->err_key);
memset(&loader->i->err_val, 0, sizeof(loader->i->err_val)); toku_init_dbt(&loader->i->err_val);
loader->i->err_i = 0; loader->i->err_i = 0;
loader->i->err_errno = 0; loader->i->err_errno = 0;
...@@ -335,13 +335,8 @@ int toku_loader_put(DB_LOADER *loader, DBT *key, DBT *val) ...@@ -335,13 +335,8 @@ int toku_loader_put(DB_LOADER *loader, DBT *key, DBT *val)
if ( r != 0 ) { if ( r != 0 ) {
// spec says errors all happen on close // spec says errors all happen on close
// - have to save key, val, errno (r) and i for duplicate callback // - have to save key, val, errno (r) and i for duplicate callback
loader->i->err_key.size = key->size; toku_clone_dbt(&loader->i->err_key, *key);
loader->i->err_key.data = toku_malloc(key->size); toku_clone_dbt(&loader->i->err_val, *val);
memcpy(loader->i->err_key.data, key->data, key->size);
loader->i->err_val.size = val->size;
loader->i->err_val.data = toku_malloc(val->size);
memcpy(loader->i->err_val.data, val->data, val->size);
loader->i->err_i = i; loader->i->err_i = i;
loader->i->err_errno = r; loader->i->err_errno = r;
......
...@@ -90,7 +90,7 @@ static int hi_inserts(DB_TXN* UU(txn), ARG arg, void* UU(operation_extra), void ...@@ -90,7 +90,7 @@ static int hi_inserts(DB_TXN* UU(txn), ARG arg, void* UU(operation_extra), void
// by the table size manually. fill_key_buf_random will // by the table size manually. fill_key_buf_random will
// do this iff arg->bounded_element_range is true. // do this iff arg->bounded_element_range is true.
invariant(arg->bounded_element_range); invariant(arg->bounded_element_range);
fill_key_buf_random<int>(arg->random_data, keybuf, arg); fill_key_buf_random(arg->random_data, keybuf, arg);
fill_val_buf_random(arg->random_data, valbuf, arg->cli); fill_val_buf_random(arg->random_data, valbuf, arg->cli);
r = env->put_multiple( r = env->put_multiple(
env, env,
......
...@@ -640,13 +640,23 @@ static int generate_row_for_put( ...@@ -640,13 +640,23 @@ static int generate_row_for_put(
return 0; return 0;
} }
template <typename integer_t> // How Keys Work:
static integer_t breverse(integer_t v) //
// Keys are either
// - 4 byte little endian non-negative integers
// - 8 byte little endian non-negative integers
// - 8 byte little endian non-negative integers, padded with zeroes.
//
// The comparison function treats the key as a 4 byte
// int if the key size is exactly 4, and it treats
// the key as an 8 byte int if the key size is 8 or more.
static uint64_t breverse(uint64_t v)
// Effect: return the bits in i, reversed // Effect: return the bits in i, reversed
// Notes: implementation taken from http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious // Notes: implementation taken from http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious
// Rationale: just a hack to spread out the keys during loading, doesn't need to be fast but does need to be correct. // Rationale: just a hack to spread out the keys during loading, doesn't need to be fast but does need to be correct.
{ {
integer_t r = v; // r will be reversed bits of v; first get LSB of v uint64_t r = v; // r will be reversed bits of v; first get LSB of v
int s = sizeof(v) * CHAR_BIT - 1; // extra shift needed at end int s = sizeof(v) * CHAR_BIT - 1; // extra shift needed at end
for (v >>= 1; v; v >>= 1) { for (v >>= 1; v; v >>= 1) {
...@@ -658,52 +668,58 @@ static integer_t breverse(integer_t v) ...@@ -658,52 +668,58 @@ static integer_t breverse(integer_t v)
return r; return r;
} }
template <typename integer_t>
static void static void
fill_key_buf(integer_t key, uint8_t *data, struct cli_args *args) { fill_key_buf(int64_t key, uint8_t *data, struct cli_args *args) {
// Effect: Fill data with a little-endian integer with the given integer_t type // Effect: Fill data with a specific little-endian integer, 4 or 8 bytes long
// If the data buf is bigger than the integer's size, pad with zeroes. // depending on args->key_size, possibly padded with zeroes.
// Requires: *data is at least sizeof(integer_t) // Requires: *data is at least sizeof(uint64_t)
// Note: If you want to store 4 bytes, pass a 4 byte type. 8 bytes? 8 byte type. invariant(key >= 0);
// to store an 8-byte integer valued 5:
// int k = 5; fill_key_buf(k, ...) // WRONG
// int64_t k = 5; fill_key_buf(k, ...) // RIGHT
invariant(sizeof(integer_t) >= min_key_size);
invariant(sizeof(integer_t) <= args->key_size);
integer_t *k = reinterpret_cast<integer_t *>(data);
if (args->disperse_keys) { if (args->disperse_keys) {
*k = static_cast<integer_t>(breverse(key)); key = breverse(key);
} else {
*k = key;
} }
if (args->key_size > sizeof(integer_t)) { if (args->key_size == sizeof(int)) {
memset(data + sizeof(integer_t), 0, args->key_size - sizeof(integer_t)); const int key32 = key;
memcpy(data, &key32, sizeof(key32));
} else {
invariant(args->key_size >= sizeof(key));
memcpy(data, &key, sizeof(key));
memset(data + sizeof(key), 0, args->key_size - sizeof(key));
} }
} }
template <typename integer_t>
static void static void
fill_key_buf_random(struct random_data *random_data, uint8_t *data, ARG arg) { fill_key_buf_random(struct random_data *random_data, uint8_t *data, ARG arg) {
// Effect: Fill data with a random little-endian integer with the given integer_t type, // Effect: Fill data with a random, little-endian, 4 or 8 byte integer, possibly
// possibly bounded by the size of the table, possibly padded with zeroes. // bounded by the size of the table, and padded with zeroes until key_size.
// Requires, Notes: see fill_key_buf() // Requires, Notes: see fill_key_buf()
invariant(sizeof(integer_t) <= arg->cli->key_size); int64_t key = myrandom_r(random_data);
integer_t key = static_cast<integer_t>(myrandom_r(random_data));
if (arg->bounded_element_range && arg->cli->num_elements > 0) { if (arg->bounded_element_range && arg->cli->num_elements > 0) {
key = key % arg->cli->num_elements; key = key % arg->cli->num_elements;
} }
fill_key_buf(key, data, arg->cli); fill_key_buf(key, data, arg->cli);
} }
template <typename integer_t> // How Vals Work:
//
// Values are either
// - 4 byte little endian integers
// - 4 byte little endian integers, padded with zeroes
// - X bytes random values, Y bytes zeroes, where X and Y
// are derived from the desired compressibility;
//
// Correctness tests use integer values, perf tests use random bytes.
// Both support padding out values > 4 bytes with zeroes.
static void static void
fill_val_buf(integer_t val, uint8_t *data, uint32_t val_size) { fill_val_buf(int64_t val, uint8_t *data, uint32_t val_size) {
// Effect, Requires, Notes: see fill_key_buf(). // Effect, Requires, Notes: see fill_key_buf().
invariant(sizeof(integer_t) <= val_size); if (val_size == sizeof(int)) {
integer_t *v = reinterpret_cast<integer_t *>(data); const int val32 = val;
*v = val; memcpy(data, &val32, sizeof(val32));
if (val_size > sizeof(integer_t)) { } else {
memset(data + sizeof(integer_t), 0, val_size - sizeof(integer_t)); invariant(val_size >= sizeof(val));
memcpy(data, &val, sizeof(val));
memset(data + sizeof(val), 0, val_size - sizeof(val));
} }
} }
...@@ -748,7 +764,7 @@ static int random_put_in_db(DB *db, DB_TXN *txn, ARG arg, bool ignore_errors, vo ...@@ -748,7 +764,7 @@ static int random_put_in_db(DB *db, DB_TXN *txn, ARG arg, bool ignore_errors, vo
uint64_t puts_to_increment = 0; uint64_t puts_to_increment = 0;
for (uint32_t i = 0; i < arg->cli->txn_size; ++i) { for (uint32_t i = 0; i < arg->cli->txn_size; ++i) {
fill_key_buf_random<uint64_t>(arg->random_data, keybuf, arg); fill_key_buf_random(arg->random_data, keybuf, arg);
fill_val_buf_random(arg->random_data, valbuf, arg->cli); fill_val_buf_random(arg->random_data, valbuf, arg->cli);
r = db->put(db, txn, &key, &val, put_flags); r = db->put(db, txn, &key, &val, put_flags);
if (!ignore_errors && r != 0) { if (!ignore_errors && r != 0) {
...@@ -868,7 +884,7 @@ static int UU() keyrange_op(DB_TXN *txn, ARG arg, void* UU(operation_extra), voi ...@@ -868,7 +884,7 @@ static int UU() keyrange_op(DB_TXN *txn, ARG arg, void* UU(operation_extra), voi
DBT key; DBT key;
dbt_init(&key, keybuf, sizeof keybuf); dbt_init(&key, keybuf, sizeof keybuf);
fill_key_buf_random<int>(arg->random_data, keybuf, arg); fill_key_buf_random(arg->random_data, keybuf, arg);
uint64_t less,equal,greater; uint64_t less,equal,greater;
int is_exact; int is_exact;
...@@ -959,7 +975,7 @@ static int UU() ptquery_and_maybe_check_op(DB* db, DB_TXN *txn, ARG arg, bool ch ...@@ -959,7 +975,7 @@ static int UU() ptquery_and_maybe_check_op(DB* db, DB_TXN *txn, ARG arg, bool ch
DBT key, val; DBT key, val;
dbt_init(&key, keybuf, sizeof keybuf); dbt_init(&key, keybuf, sizeof keybuf);
dbt_init(&val, nullptr, 0); dbt_init(&val, nullptr, 0);
fill_key_buf_random<int>(arg->random_data, keybuf, arg); fill_key_buf_random(arg->random_data, keybuf, arg);
r = db->getf_set( r = db->getf_set(
db, db,
...@@ -1100,7 +1116,7 @@ static int UU() update_op2(DB_TXN* txn, ARG arg, void* UU(operation_extra), void ...@@ -1100,7 +1116,7 @@ static int UU() update_op2(DB_TXN* txn, ARG arg, void* UU(operation_extra), void
dbt_init(&val, &extra, sizeof extra); dbt_init(&val, &extra, sizeof extra);
for (uint32_t i = 0; i < arg->cli->txn_size; i++) { for (uint32_t i = 0; i < arg->cli->txn_size; i++) {
fill_key_buf_random<int>(arg->random_data, keybuf, arg); fill_key_buf_random(arg->random_data, keybuf, arg);
extra.u.d.diff = 1; extra.u.d.diff = 1;
curr_val_sum += extra.u.d.diff; curr_val_sum += extra.u.d.diff;
r = db->update( r = db->update(
...@@ -1222,7 +1238,7 @@ UU() update_op_db(DB *db, DB_TXN *txn, ARG arg, void* operation_extra, void *UU( ...@@ -1222,7 +1238,7 @@ UU() update_op_db(DB *db, DB_TXN *txn, ARG arg, void* operation_extra, void *UU(
fill_key_buf(update_key, keybuf, arg->cli); fill_key_buf(update_key, keybuf, arg->cli);
} else { } else {
// just do a usual, random point update without locking first // just do a usual, random point update without locking first
fill_key_buf_random<int>(arg->random_data, keybuf, arg); fill_key_buf_random(arg->random_data, keybuf, arg);
} }
...@@ -1295,7 +1311,7 @@ static int UU() update_with_history_op(DB_TXN *txn, ARG arg, void* operation_ext ...@@ -1295,7 +1311,7 @@ static int UU() update_with_history_op(DB_TXN *txn, ARG arg, void* operation_ext
dbt_init(&val, &extra, sizeof extra); dbt_init(&val, &extra, sizeof extra);
for (uint32_t i = 0; i < arg->cli->txn_size; i++) { for (uint32_t i = 0; i < arg->cli->txn_size; i++) {
fill_key_buf_random<int>(arg->random_data, keybuf, arg); fill_key_buf_random(arg->random_data, keybuf, arg);
int *rkp = (int *) keybuf; int *rkp = (int *) keybuf;
rand_key = *rkp; rand_key = *rkp;
invariant(rand_key < arg->cli->num_elements); invariant(rand_key < arg->cli->num_elements);
...@@ -1729,16 +1745,13 @@ static void fill_single_table(DB_ENV *env, DB *db, struct cli_args *args, bool f ...@@ -1729,16 +1745,13 @@ static void fill_single_table(DB_ENV *env, DB *db, struct cli_args *args, bool f
} }
for (int i = 0; i < args->num_elements; i++) { for (int i = 0; i < args->num_elements; i++) {
fill_key_buf(i, keybuf, args);
// Correctness tests map every key to zeroes. Perf tests fill
// values with random bytes, based on compressibility.
if (fill_with_zeroes) { if (fill_with_zeroes) {
// Legacy test, 4 byte signed keys and 4 byte zero values. fill_val_buf(0, valbuf, args->val_size);
const int k = i;
const int zero = 0;
fill_key_buf(k, keybuf, args);
fill_val_buf(zero, valbuf, args->val_size);
} else { } else {
// Modern test, >= 8 byte unsigned keys, >= 8 byte random values.
const uint64_t k = i;
fill_key_buf(k, keybuf, args);
fill_val_buf_random(&random_data, valbuf, args); fill_val_buf_random(&random_data, valbuf, args);
} }
...@@ -2413,8 +2426,10 @@ static inline void parse_stress_test_args (int argc, char *const argv[], struct ...@@ -2413,8 +2426,10 @@ static inline void parse_stress_test_args (int argc, char *const argv[], struct
static void static void
stress_table(DB_ENV *, DB **, struct cli_args *); stress_table(DB_ENV *, DB **, struct cli_args *);
template<typename integer_t> static int
static int int_cmp(integer_t x, integer_t y) { stress_dbt_cmp_legacy(const DBT *a, const DBT *b) {
int x = *(int *) a->data;
int y = *(int *) b->data;
if (x < y) { if (x < y) {
return -1; return -1;
} else if (x > y) { } else if (x > y) {
...@@ -2424,13 +2439,6 @@ static int int_cmp(integer_t x, integer_t y) { ...@@ -2424,13 +2439,6 @@ static int int_cmp(integer_t x, integer_t y) {
} }
} }
static int
stress_dbt_cmp_legacy(const DBT *a, const DBT *b) {
int x = *(int *) a->data;
int y = *(int *) b->data;
return int_cmp(x, y);
}
static int static int
stress_dbt_cmp(const DBT *a, const DBT *b) { stress_dbt_cmp(const DBT *a, const DBT *b) {
// Keys are only compared by their first 8 bytes, // Keys are only compared by their first 8 bytes,
...@@ -2438,7 +2446,13 @@ stress_dbt_cmp(const DBT *a, const DBT *b) { ...@@ -2438,7 +2446,13 @@ stress_dbt_cmp(const DBT *a, const DBT *b) {
// The rest of the key is just padding. // The rest of the key is just padding.
uint64_t x = *(uint64_t *) a->data; uint64_t x = *(uint64_t *) a->data;
uint64_t y = *(uint64_t *) b->data; uint64_t y = *(uint64_t *) b->data;
return int_cmp(x, y); if (x < y) {
return -1;
} else if (x > y) {
return +1;
} else {
return 0;
}
} }
static int static int
...@@ -2510,6 +2524,12 @@ UU() stress_recover(struct cli_args *args) { ...@@ -2510,6 +2524,12 @@ UU() stress_recover(struct cli_args *args) {
static void static void
test_main(struct cli_args *args, bool fill_with_zeroes) test_main(struct cli_args *args, bool fill_with_zeroes)
{ {
if ((args->key_size < 8 && args->key_size != 4) ||
(args->val_size < 8 && args->val_size != 4)) {
fprintf(stderr, "The only valid key/val sizes are 4, 8, and > 8.\n");
return;
}
{ char *loc = setlocale(LC_NUMERIC, "en_US.UTF-8"); assert(loc); } { char *loc = setlocale(LC_NUMERIC, "en_US.UTF-8"); assert(loc); }
DB_ENV* env = nullptr; DB_ENV* env = nullptr;
DB* dbs[args->num_DBs]; DB* dbs[args->num_DBs];
......
...@@ -184,13 +184,6 @@ single_process_unlock(int *lockfd) { ...@@ -184,13 +184,6 @@ single_process_unlock(int *lockfd) {
return 0; return 0;
} }
static inline DBT*
init_dbt_realloc(DBT *dbt) {
memset(dbt, 0, sizeof(*dbt));
dbt->flags = DB_DBT_REALLOC;
return dbt;
}
int int
toku_ydb_init(void) { toku_ydb_init(void) {
int r = 0; int r = 0;
...@@ -2337,7 +2330,7 @@ env_dbremove(DB_ENV * env, DB_TXN *txn, const char *fname, const char *dbname, u ...@@ -2337,7 +2330,7 @@ env_dbremove(DB_ENV * env, DB_TXN *txn, const char *fname, const char *dbname, u
DBT dname_dbt; DBT dname_dbt;
DBT iname_dbt; DBT iname_dbt;
toku_fill_dbt(&dname_dbt, dname, strlen(dname)+1); toku_fill_dbt(&dname_dbt, dname, strlen(dname)+1);
init_dbt_realloc(&iname_dbt); // sets iname_dbt.data = NULL toku_init_dbt_flags(&iname_dbt, DB_DBT_REALLOC);
// get iname // get iname
r = toku_db_get(env->i->directory, txn, &dname_dbt, &iname_dbt, DB_SERIALIZABLE); // allocates memory for iname r = toku_db_get(env->i->directory, txn, &dname_dbt, &iname_dbt, DB_SERIALIZABLE); // allocates memory for iname
...@@ -2448,7 +2441,7 @@ env_dbrename(DB_ENV *env, DB_TXN *txn, const char *fname, const char *dbname, co ...@@ -2448,7 +2441,7 @@ env_dbrename(DB_ENV *env, DB_TXN *txn, const char *fname, const char *dbname, co
DBT iname_dbt; DBT iname_dbt;
toku_fill_dbt(&old_dname_dbt, dname, strlen(dname)+1); toku_fill_dbt(&old_dname_dbt, dname, strlen(dname)+1);
toku_fill_dbt(&new_dname_dbt, newname, strlen(newname)+1); toku_fill_dbt(&new_dname_dbt, newname, strlen(newname)+1);
init_dbt_realloc(&iname_dbt); // sets iname_dbt.data = NULL toku_init_dbt_flags(&iname_dbt, DB_DBT_REALLOC);
// get iname // get iname
r = toku_db_get(env->i->directory, txn, &old_dname_dbt, &iname_dbt, DB_SERIALIZABLE); // allocates memory for iname r = toku_db_get(env->i->directory, txn, &old_dname_dbt, &iname_dbt, DB_SERIALIZABLE); // allocates memory for iname
...@@ -2594,7 +2587,7 @@ toku_test_db_redirect_dictionary(DB * db, const char * dname_of_new_file, DB_TXN ...@@ -2594,7 +2587,7 @@ toku_test_db_redirect_dictionary(DB * db, const char * dname_of_new_file, DB_TXN
TOKUTXN tokutxn = db_txn_struct_i(dbtxn)->tokutxn; TOKUTXN tokutxn = db_txn_struct_i(dbtxn)->tokutxn;
toku_fill_dbt(&dname_dbt, dname_of_new_file, strlen(dname_of_new_file)+1); toku_fill_dbt(&dname_dbt, dname_of_new_file, strlen(dname_of_new_file)+1);
init_dbt_realloc(&iname_dbt); // sets iname_dbt.data = NULL toku_init_dbt_flags(&iname_dbt, DB_DBT_REALLOC);
r = toku_db_get(db->dbenv->i->directory, dbtxn, &dname_dbt, &iname_dbt, DB_SERIALIZABLE); // allocates memory for iname r = toku_db_get(db->dbenv->i->directory, dbtxn, &dname_dbt, &iname_dbt, DB_SERIALIZABLE); // allocates memory for iname
assert_zero(r); assert_zero(r);
new_iname_in_env = (char *) iname_dbt.data; new_iname_in_env = (char *) iname_dbt.data;
......
...@@ -54,13 +54,6 @@ ydb_db_layer_get_status(YDB_DB_LAYER_STATUS statp) { ...@@ -54,13 +54,6 @@ ydb_db_layer_get_status(YDB_DB_LAYER_STATUS statp) {
*statp = ydb_db_layer_status; *statp = ydb_db_layer_status;
} }
static inline DBT*
init_dbt_realloc(DBT *dbt) {
memset(dbt, 0, sizeof(*dbt));
dbt->flags = DB_DBT_REALLOC;
return dbt;
}
static void static void
create_iname_hint(const char *dname, char *hint) { create_iname_hint(const char *dname, char *hint) {
//Requires: size of hint array must be > strlen(dname) //Requires: size of hint array must be > strlen(dname)
...@@ -260,7 +253,7 @@ toku_db_open(DB * db, DB_TXN * txn, const char *fname, const char *dbname, DBTYP ...@@ -260,7 +253,7 @@ toku_db_open(DB * db, DB_TXN * txn, const char *fname, const char *dbname, DBTYP
DBT dname_dbt; // holds dname DBT dname_dbt; // holds dname
DBT iname_dbt; // holds iname_in_env DBT iname_dbt; // holds iname_in_env
toku_fill_dbt(&dname_dbt, dname, strlen(dname)+1); toku_fill_dbt(&dname_dbt, dname, strlen(dname)+1);
init_dbt_realloc(&iname_dbt); // sets iname_dbt.data = NULL toku_init_dbt_flags(&iname_dbt, DB_DBT_REALLOC);
r = toku_db_get(db->dbenv->i->directory, txn, &dname_dbt, &iname_dbt, DB_SERIALIZABLE); // allocates memory for iname r = toku_db_get(db->dbenv->i->directory, txn, &dname_dbt, &iname_dbt, DB_SERIALIZABLE); // allocates memory for iname
char *iname = (char *) iname_dbt.data; char *iname = (char *) iname_dbt.data;
if (r == DB_NOTFOUND && !is_db_create) { if (r == DB_NOTFOUND && !is_db_create) {
......
...@@ -28,8 +28,6 @@ void *toku_xmalloc(size_t size); ...@@ -28,8 +28,6 @@ void *toku_xmalloc(size_t size);
void *toku_xrealloc(void*, size_t size) __attribute__((__visibility__("default"))); void *toku_xrealloc(void*, size_t size) __attribute__((__visibility__("default")));
void toku_free(void*) __attribute__((__visibility__("default"))); void toku_free(void*) __attribute__((__visibility__("default")));
/* toku_free_n() should be used if the caller knows the size of the malloc'd object. */
void toku_free_n(void*, size_t size);
void *toku_realloc(void *, size_t size) __attribute__((__visibility__("default"))); void *toku_realloc(void *, size_t size) __attribute__((__visibility__("default")));
size_t toku_malloc_usable_size(void *p) __attribute__((__visibility__("default"))); size_t toku_malloc_usable_size(void *p) __attribute__((__visibility__("default")));
......
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