Commit 15b37bc4 authored by Rich Prohaska's avatar Rich Prohaska Committed by Yoni Fogel

merge -r 18992:head ptq to main refs[t:2351]

git-svn-id: file:///svn/toku/tokudb@19099 c7de825b-a66e-492c-adef-691d508d4ae1
parent ade9c07e
......@@ -502,6 +502,7 @@ static int print_usage (const char *argv0) {
fprintf(stderr, " --numdbs N Insert same items into N dbs (1 to %d)\n", MAX_DBS);
fprintf(stderr, " --insertmultiple Use DB_ENV->put_multiple api. Requires transactions.\n");
fprintf(stderr, " --redzone N redzone in percent\n");
fprintf(stderr, " --srandom N srandom(N)\n");
fprintf(stderr, " n_iterations how many iterations (default %lld)\n", default_n_items/DEFAULT_ITEMS_TO_INSERT_PER_ITERATION);
return 1;
......
......@@ -44,8 +44,9 @@ static int print_usage (const char *argv0) {
fprintf(stderr, " --mysql compare keys that are mysql big int not null types\n");
fprintf(stderr, " --env DIR put db files in DIR instead of default\n");
fprintf(stderr, " --log_dir LOGDIR put the logs in LOGDIR\n");
fprintf(stderr, " --range <low> <high> set the low and high key boundaries in which random range queries are made\n");
fprintf(stderr, " --experiments <n> run n experiments (default:%d)\n", n_experiments);
fprintf(stderr, " --range LOW HIGH set the LOW and HIGH key boundaries in which random range queries are made\n");
fprintf(stderr, " --experiments N run N experiments (default:%d)\n", n_experiments);
fprintf(stderr, " --srandom N srandom(N)\n");
fprintf(stderr, " --recover run recovery\n");
fprintf(stderr, " --verbose print verbose information\n");
return 1;
......@@ -128,6 +129,9 @@ static void parse_args (int argc, const char *const argv[]) {
} else if (strcmp(*argv, "--experiments") == 0 && argc > 1) {
argc--; argv++;
n_experiments = strtol(*argv, NULL, 10);
} else if (strcmp(*argv, "--srandom") == 0 && argc > 1) {
argc--; argv++;
srandom(atoi(*argv));
} else if (strcmp(*argv, "--recover") == 0) {
env_open_flags_yesx |= DB_RECOVER;
env_open_flags_nox |= DB_RECOVER;
......@@ -309,8 +313,7 @@ static void scanscan_lwc (void) {
static void scanscan_flatten (void) {
int r;
int counter=0;
for (counter=0; counter<n_experiments; counter++) {
for (int counter=0; counter<n_experiments; counter++) {
double prevtime = gettime();
r = db->flatten(db, tid);
assert(r==0);
......@@ -325,20 +328,21 @@ static void scanscan_range (void) {
int r;
double texperiments[n_experiments];
int counter;
for (counter=0; counter<n_experiments; counter++) {
makekey:
;
// generate a random key in the key range
u_int64_t k = (start_range + (random() % (end_range - start_range))) * (1<<6);
char kv[8];
int i;
for (i=0; i<8; i++)
kv[i] = k >> (56-8*i);
DBT key; memset(&key, 0, sizeof key); key.data = &kv, key.size = sizeof kv;
DBT val; memset(&val, 0, sizeof val);
u_int64_t k = 0;
char kv[8];
DBT key, val;
for (int counter = 0; counter < n_experiments; counter++) {
if (1) { //if ((counter&1) == 0) {
makekey:
// generate a random key in the key range
k = (start_range + (random() % (end_range - start_range))) * (1<<6);
for (int i = 0; i < 8; i++)
kv[i] = k >> (56-8*i);
}
memset(&key, 0, sizeof key); key.data = &kv, key.size = sizeof kv;
memset(&val, 0, sizeof val);
double tstart = gettime();
......@@ -349,7 +353,7 @@ static void scanscan_range (void) {
r = dbc->c_get(dbc, &key, &val, DB_SET_RANGE+lock_flag);
if (r != 0) {
assert(r == DB_NOTFOUND);
printf("%s:%d\n", __FUNCTION__, __LINE__);
printf("%s:%d %"PRIu64"\n", __FUNCTION__, __LINE__, k);
goto makekey;
}
......@@ -369,12 +373,12 @@ static void scanscan_range (void) {
assert(r==0);
texperiments[counter] = gettime() - tstart;
printf("%f\n", texperiments[counter]); fflush(stdout);
printf("%"PRIu64" %f\n", k, texperiments[counter]); fflush(stdout);
}
// print the times
double tsum = 0.0, tmin = 0.0, tmax = 0.0;
for (counter=0; counter<n_experiments; counter++) {
for (int counter = 0; counter < n_experiments; counter++) {
if (counter==0 || texperiments[counter] < tmin)
tmin = texperiments[counter];
if (counter==0 || texperiments[counter] > tmax)
......
This diff is collapsed.
......@@ -104,7 +104,10 @@ dump_node (int f, BLOCKNUM blocknum, struct brt_header *h) {
printf(" children:\n");
for (i=0; i<n->u.n.n_children; i++) {
printf(" child %d: %" PRId64 "\n", i, BNC_BLOCKNUM(n, i).b);
printf(" buffer contains %u bytes (%d items)\n", BNC_NBYTESINBUF(n, i), toku_fifo_n_entries(BNC_BUFFER(n,i)));
unsigned int n_bytes = BNC_NBYTESINBUF(n, i);
int n_entries = toku_fifo_n_entries(BNC_BUFFER(n, i));
if (n_bytes > 0 || n_entries > 0)
printf(" buffer contains %u bytes (%d items)\n", n_bytes, n_entries);
if (dump_data) {
FIFO_ITERATE(BNC_BUFFER(n,i), key, keylen, data, datalen, typ, xids,
{
......
......@@ -24,6 +24,10 @@ static inline void rbuf_init(struct rbuf *r, unsigned char *buf, unsigned int si
r->ndone = 0;
}
static inline unsigned int rbuf_get_roffset(struct rbuf *r) {
return r->ndone;
}
static inline unsigned int rbuf_char (struct rbuf *r) {
assert(r->ndone<r->size);
return r->buf[r->ndone++];
......
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <zlib.h>
#include "toku_portability.h"
......@@ -53,14 +54,19 @@ alignup32(int a, int b) {
// Choose n_sub_blocks and sub_block_size such that the product is >= total_size and the sub_block_size is at
// least >= the target_sub_block_size.
void
int
choose_sub_block_size(int total_size, int n_sub_blocks_limit, int *sub_block_size_ret, int *n_sub_blocks_ret) {
if (total_size < 0 || n_sub_blocks_limit < 1)
return EINVAL;
const int alignment = 32;
int n_sub_blocks, sub_block_size;
n_sub_blocks = total_size / target_sub_block_size;
if (n_sub_blocks <= 1) {
n_sub_blocks = 1;
n_sub_blocks = n_sub_blocks;
if (total_size > 0 && n_sub_blocks_limit > 0)
n_sub_blocks = 1;
sub_block_size = total_size;
} else {
if (n_sub_blocks > n_sub_blocks_limit) // limit the number of sub-blocks
......@@ -72,6 +78,8 @@ choose_sub_block_size(int total_size, int n_sub_blocks_limit, int *sub_block_siz
*sub_block_size_ret = sub_block_size;
*n_sub_blocks_ret = n_sub_blocks;
return 0;
}
void
......@@ -86,6 +94,20 @@ set_all_sub_block_sizes(int total_size, int sub_block_size, int n_sub_blocks, st
sub_block[i].uncompressed_size = size_left;
}
// find the index of the first sub block that contains offset
// Returns the sub block index, else returns -1
int
get_sub_block_index(int n_sub_blocks, struct sub_block sub_block[], size_t offset) {
size_t start_offset = 0;
for (int i = 0; i < n_sub_blocks; i++) {
size_t size = sub_block[i].uncompressed_size;
if (offset < start_offset + size)
return i;
start_offset += size;
}
return -1;
}
#include "workset.h"
void
......@@ -198,13 +220,14 @@ int
decompress_sub_block(void *compress_ptr, u_int32_t compress_size, void *uncompress_ptr, u_int32_t uncompress_size, u_int32_t expected_xsum) {
// verify checksum
u_int32_t xsum = x1764_memory(compress_ptr, compress_size);
assert(xsum == expected_xsum);
if (xsum != expected_xsum)
return EINVAL;
// decompress
uLongf destlen = uncompress_size;
int r = uncompress(uncompress_ptr, &destlen, compress_ptr, compress_size);
assert(destlen == uncompress_size);
assert(r==Z_OK);
if (r != Z_OK || destlen != uncompress_size)
return EINVAL;
return 0;
}
......@@ -222,10 +245,12 @@ decompress_worker(void *arg) {
return arg;
}
void
int
decompress_all_sub_blocks(int n_sub_blocks, struct sub_block sub_block[], unsigned char *compressed_data, unsigned char *uncompressed_data, int num_cores) {
int r;
if (n_sub_blocks == 1) {
decompress_sub_block(compressed_data, sub_block[0].compressed_size, uncompressed_data, sub_block[0].uncompressed_size, sub_block[0].xsum);
r = decompress_sub_block(compressed_data, sub_block[0].compressed_size, uncompressed_data, sub_block[0].uncompressed_size, sub_block[0].xsum);
} else {
// compute the number of additional threads needed for decompressing this node
int T = num_cores; // T = min(#cores, #blocks) - 1
......@@ -259,5 +284,14 @@ decompress_all_sub_blocks(int n_sub_blocks, struct sub_block sub_block[], unsign
// cleanup
threadset_join(tids, T);
workset_destroy(&ws);
r = 0;
for (int i = 0; i < n_sub_blocks; i++) {
r = decompress_work[i].error;
if (r != 0)
break;
}
}
return r;
}
......@@ -38,12 +38,17 @@ get_sum_uncompressed_size(int n_sub_blocks, struct sub_block sub_block[]);
// Choose n_sub_blocks and sub_block_size such that the product is >= total_size and the sub_block_size is at
// least >= the target_sub_block_size.
void
int
choose_sub_block_size(int total_size, int n_sub_blocks_limit, int *sub_block_size_ret, int *n_sub_blocks_ret);
void
set_all_sub_block_sizes(int total_size, int sub_block_size, int n_sub_blocks, struct sub_block sub_block[]);
// find the index of the first sub block that contains the offset
// Returns the index if found, else returns -1
int
get_sub_block_index(int n_sub_blocks, struct sub_block sub_block[], size_t offset);
#include "workset.h"
struct compress_work {
......@@ -88,7 +93,9 @@ decompress_sub_block(void *compress_ptr, u_int32_t compress_size, void *uncompre
void *
decompress_worker(void *arg);
void
// decompress all sub blocks from the compressed_data buffer to the uncompressed_data buffer
// Returns 0 if success, otherwise an error
int
decompress_all_sub_blocks(int n_sub_blocks, struct sub_block sub_block[], unsigned char *compressed_data, unsigned char *uncompressed_data, int num_cores);
......
#ifndef _TOKU_SUB_BLOCK_MAP_H
#define TOKU_SUB_BLOCK_MAP_H
// Map objects to a sequence of sub block
struct sub_block_map {
u_int32_t idx;
u_int32_t offset;
u_int32_t size;
};
enum {
stored_sub_block_map_size = sizeof (struct sub_block_map), // size of a sub-block map on disk
};
static inline void
sub_block_map_init(struct sub_block_map *sbmap, u_int32_t idx, u_int32_t offset, u_int32_t size) {
sbmap->idx = idx;
sbmap->offset = offset;
sbmap->size = size;
}
static inline void
sub_block_map_serialize(struct sub_block_map *sbmap, struct wbuf *wbuf) {
wbuf_nocrc_int(wbuf, sbmap->idx);
wbuf_nocrc_int(wbuf, sbmap->offset);
wbuf_nocrc_int(wbuf, sbmap->size);
}
static inline void
sub_block_map_deserialize(struct sub_block_map *sbmap, struct rbuf *rbuf) {
sbmap->idx = rbuf_int(rbuf);
sbmap->offset = rbuf_int(rbuf);
sbmap->size = rbuf_int(rbuf);
}
#endif
// test that corrupt checksums are detected
#include <toku_portability.h>
#include "test.h"
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "sub_block.h"
int verbose;
static uint8_t
get_uint8_at_offset(void *vp, size_t offset) {
uint8_t *ip = (uint8_t *) vp;
return ip[offset];
}
static void
set_uint8_at_offset(void *vp, size_t offset, uint8_t newv) {
uint8_t *ip = (uint8_t *) vp;
ip[offset] = newv;
}
static void
test_sub_block_checksum(void *buf, int total_size, int my_max_sub_blocks, int n_cores) {
if (verbose)
printf("%s:%d %d %d\n", __FUNCTION__, __LINE__, total_size, my_max_sub_blocks);
int r;
int sub_block_size, n_sub_blocks;
r = choose_sub_block_size(total_size, my_max_sub_blocks, &sub_block_size, &n_sub_blocks);
assert(r == 0);
if (verbose)
printf("%s:%d %d %d\n", __FUNCTION__, __LINE__, sub_block_size, n_sub_blocks);
struct sub_block sub_blocks[n_sub_blocks];
set_all_sub_block_sizes(total_size, sub_block_size, n_sub_blocks, sub_blocks);
size_t cbuf_size_bound = get_sum_compressed_size_bound(n_sub_blocks, sub_blocks);
void *cbuf = toku_malloc(cbuf_size_bound);
assert(cbuf);
size_t cbuf_size = compress_all_sub_blocks(n_sub_blocks, sub_blocks, buf, cbuf, n_cores);
assert(cbuf_size <= cbuf_size_bound);
void *ubuf = toku_malloc(total_size);
assert(ubuf);
for (int xidx = 0; xidx < n_sub_blocks; xidx++) {
// corrupt a checksum
sub_blocks[xidx].xsum += 1;
r = decompress_all_sub_blocks(n_sub_blocks, sub_blocks, cbuf, ubuf, n_cores);
assert(r != 0);
// reset the checksums
sub_blocks[xidx].xsum -= 1;
r = decompress_all_sub_blocks(n_sub_blocks, sub_blocks, cbuf, ubuf, n_cores);
assert(r == 0);
assert(memcmp(buf, ubuf, total_size) == 0);
// corrupt the data
size_t offset = random() % cbuf_size;
unsigned char c = get_uint8_at_offset(cbuf, offset);
set_uint8_at_offset(cbuf, offset, c+1);
r = decompress_all_sub_blocks(n_sub_blocks, sub_blocks, cbuf, ubuf, n_cores);
assert(r != 0);
// reset the data
set_uint8_at_offset(cbuf, offset, c);
r = decompress_all_sub_blocks(n_sub_blocks, sub_blocks, cbuf, ubuf, n_cores);
assert(r == 0);
assert(memcmp(buf, ubuf, total_size) == 0);
}
toku_free(ubuf);
toku_free(cbuf);
}
static void
set_random(void *buf, int total_size) {
char *bp = (char *) buf;
for (int i = 0; i < total_size; i++)
bp[i] = random();
}
static void
run_test(int total_size, int n_cores) {
void *buf = toku_malloc(total_size);
assert(buf);
for (int my_max_sub_blocks = 1; my_max_sub_blocks <= max_sub_blocks; my_max_sub_blocks++) {
memset(buf, 0, total_size);
test_sub_block_checksum(buf, total_size, my_max_sub_blocks, n_cores);
set_random(buf, total_size);
test_sub_block_checksum(buf, total_size, my_max_sub_blocks, n_cores);
}
toku_free(buf);
}
int
test_main (int argc, const char *argv[]) {
int n_cores = 1;
int e = 1;
for (int i = 1; i < argc; i++) {
const char *arg = argv[i];
if (strcmp(arg, "-v") == 0 || strcmp(arg, "--verbose") == 0) {
verbose++;
continue;
}
if (strcmp(arg, "-n") == 0) {
if (i+1 < argc) {
n_cores = atoi(argv[++i]);
continue;
}
}
if (strcmp(arg, "-e") == 0) {
if (i+1 < argc) {
e = atoi(argv[++i]);
continue;
}
}
}
for (int total_size = 256*1024; total_size <= 4*1024*1024; total_size *= 2) {
for (int size = total_size - e; size <= total_size + e; size++) {
run_test(size, n_cores);
}
}
return 0;
}
// test sub block compression and decompression
#include <toku_portability.h>
#include "test.h"
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "sub_block.h"
int verbose;
static void
test_sub_block_compression(void *buf, int total_size, int my_max_sub_blocks, int n_cores) {
if (verbose)
printf("%s:%d %d %d\n", __FUNCTION__, __LINE__, total_size, my_max_sub_blocks);
int r;
int sub_block_size, n_sub_blocks;
r = choose_sub_block_size(total_size, my_max_sub_blocks, &sub_block_size, &n_sub_blocks);
assert(r == 0);
if (verbose)
printf("%s:%d %d %d\n", __FUNCTION__, __LINE__, sub_block_size, n_sub_blocks);
struct sub_block sub_blocks[n_sub_blocks];
set_all_sub_block_sizes(total_size, sub_block_size, n_sub_blocks, sub_blocks);
size_t cbuf_size_bound = get_sum_compressed_size_bound(n_sub_blocks, sub_blocks);
void *cbuf = toku_malloc(cbuf_size_bound);
assert(cbuf);
size_t cbuf_size = compress_all_sub_blocks(n_sub_blocks, sub_blocks, buf, cbuf, n_cores);
assert(cbuf_size <= cbuf_size_bound);
void *ubuf = toku_malloc(total_size);
assert(ubuf);
r = decompress_all_sub_blocks(n_sub_blocks, sub_blocks, cbuf, ubuf, n_cores);
assert(r == 0);
assert(memcmp(buf, ubuf, total_size) == 0);
toku_free(ubuf);
toku_free(cbuf);
}
static void
set_random(void *buf, int total_size) {
char *bp = (char *) buf;
for (int i = 0; i < total_size; i++)
bp[i] = random();
}
static void
run_test(int total_size, int n_cores) {
void *buf = toku_malloc(total_size);
assert(buf);
for (int my_max_sub_blocks = 1; my_max_sub_blocks <= max_sub_blocks; my_max_sub_blocks++) {
memset(buf, 0, total_size);
test_sub_block_compression(buf, total_size, my_max_sub_blocks, n_cores);
set_random(buf, total_size);
test_sub_block_compression(buf, total_size, my_max_sub_blocks, n_cores);
}
toku_free(buf);
}
int
test_main (int argc, const char *argv[]) {
int n_cores = 1;
int e = 1;
for (int i = 1; i < argc; i++) {
const char *arg = argv[i];
if (strcmp(arg, "-v") == 0 || strcmp(arg, "--verbose") == 0) {
verbose++;
continue;
}
if (strcmp(arg, "-n") == 0) {
if (i+1 < argc) {
n_cores = atoi(argv[++i]);
continue;
}
}
if (strcmp(arg, "-e") == 0) {
if (i+1 < argc) {
e = atoi(argv[++i]);
continue;
}
}
}
for (int total_size = 256*1024; total_size <= 4*1024*1024; total_size *= 2) {
for (int size = total_size - e; size <= total_size + e; size++) {
run_test(size, n_cores);
}
}
return 0;
}
// test the sub block index function
#include <toku_portability.h>
#include "test.h"
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "sub_block.h"
int verbose;
static void
test_sub_block_index(void) {
if (verbose)
printf("%s:%d\n", __FUNCTION__, __LINE__);
const int n_sub_blocks = max_sub_blocks;
struct sub_block sub_block[n_sub_blocks];
size_t max_offset = 0;
for (int i = 0 ; i < n_sub_blocks; i++) {
size_t size = i+1;
sub_block_init(&sub_block[i]);
sub_block[i].uncompressed_size = size;
max_offset += size;
}
int offset_to_sub_block[max_offset];
for (int i = 0; i < (int) max_offset; i++)
offset_to_sub_block[i] = -1;
size_t start_offset = 0;
for (int i = 0; i < n_sub_blocks; i++) {
size_t size = sub_block[i].uncompressed_size;
for (int j = 0; j < (int) (start_offset + size); j++) {
if (offset_to_sub_block[j] == -1)
offset_to_sub_block[j] = i;
}
start_offset += size;
}
int r;
for (size_t offset = 0; offset < max_offset; offset++) {
r = get_sub_block_index(n_sub_blocks, sub_block, offset);
if (verbose)
printf("%s:%d %u %d\n", __FUNCTION__, __LINE__, (unsigned int) offset, r);
assert(0 <= r && r < n_sub_blocks);
assert(r == offset_to_sub_block[offset]);
}
r = get_sub_block_index(n_sub_blocks, sub_block, max_offset);
assert(r == -1);
}
int
test_main (int argc, const char *argv[]) {
int i;
for (i=1; i<argc; i++) {
const char *arg = argv[i];
if (strcmp(arg, "-v") == 0)
verbose++;
}
test_sub_block_index();
return 0;
}
// test the choose sub block size function
#include <toku_portability.h>
#include "test.h"
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include "sub_block.h"
int verbose;
static void
test_sub_block_size(int total_size) {
if (verbose)
printf("%s:%d %d\n", __FUNCTION__, __LINE__, total_size);
int r;
int sub_block_size, n_sub_blocks;
r = choose_sub_block_size(total_size, 0, &sub_block_size, &n_sub_blocks);
assert(r == EINVAL);
for (int i = 1; i < max_sub_blocks; i++) {
r = choose_sub_block_size(total_size, i, &sub_block_size, &n_sub_blocks);
assert(r == 0);
assert(0 <= n_sub_blocks && n_sub_blocks <= i);
assert(total_size <= n_sub_blocks * sub_block_size);
}
}
int
test_main (int argc, const char *argv[]) {
int i;
for (i=1; i<argc; i++) {
const char *arg = argv[i];
if (strcmp(arg, "-v") == 0)
verbose++;
}
test_sub_block_size(0);
for (int total_size = 1; total_size <= 4*1024*1024; total_size *= 2) {
test_sub_block_size(total_size);
}
return 0;
}
......@@ -35,6 +35,10 @@ static inline void wbuf_init (struct wbuf *w, void *buf, DISKOFF size) {
x1764_init(&w->checksum);
}
static inline size_t wbuf_get_woffset(struct wbuf *w) {
return w->ndone;
}
/* Write a character. */
static inline void wbuf_nocrc_char (struct wbuf *w, unsigned char ch) {
assert(w->ndone<w->size);
......
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