Commit 203c925d authored by Bradley C. Kuszmaul's avatar Bradley C. Kuszmaul

{{{

svn delete tokudb.872
cd tokudb
svn merge -r4187:4233 https://svn.tokutek.com/tokudb/tokudb.872
}}}

Fixes #849, #872.
Addresses #820.


git-svn-id: file:///svn/tokudb@4234 c7de825b-a66e-492c-adef-691d508d4ae1
parent 3d2c57fa
......@@ -220,7 +220,6 @@ int toku_cmd_leafval_bessel (OMTVALUE leafentry, void *extra);
int toku_brt_root_put_cmd(BRT brt, BRT_CMD cmd, TOKULOGGER logger);
int toku_cachefile_root_put_cmd (CACHEFILE cf, BRT_CMD cmd, TOKULOGGER logger);
int toku_omt_compress_kvspace (OMT omt, struct mempool *memp);
void *mempool_malloc_from_omt(OMT omt, struct mempool *mp, size_t size);
void toku_verify_all_in_mempool(BRTNODE node);
......
......@@ -379,37 +379,35 @@ int toku_deserialize_brtnode_from (int fd, DISKOFF off, BRTNODE *brtnode) {
} else {
int n_in_buf = rbuf_int(&rc);
result->u.l.n_bytes_in_buffer = 0;
r=toku_omt_create(&result->u.l.buffer);
if (r!=0) {
if (0) { died_21: toku_omt_destroy(&result->u.l.buffer); }
goto died1;
}
//printf("%s:%d r PMA= %p\n", __FILE__, __LINE__, result->u.l.buffer);
{
int mpsize = result->nodesize + result->nodesize/4;
void *mp = toku_malloc(mpsize);
if (mp==0) return ENOMEM; // TODO cleanup
toku_mempool_init(&result->u.l.buffer_mempool, mp, mpsize);
}
toku_mempool_init(&result->u.l.buffer_mempool, rc.buf, datasize);
u_int32_t actual_sum = 0;
//printf("%s:%d node %lld, reading %d items\n", __FILE__, __LINE__, off, n_in_buf);
u_int32_t start_of_data = rc.ndone;
OMTVALUE *MALLOC_N(n_in_buf, array);
for (i=0; i<n_in_buf; i++) {
LEAFENTRY tmp_le;
//printf("%s:%d reading %dth item\n", __FILE__, __LINE__, i);
u_int32_t memsize, disksize;
rbuf_LEAFENTRY(&rc, &memsize, &disksize, &tmp_le);
LEAFENTRY le = mempool_malloc_from_omt(result->u.l.buffer, &result->u.l.buffer_mempool, memsize);
assert(le);
memcpy(le, tmp_le, memsize);
toku_free(tmp_le);
assert(disksize==leafentry_disksize(le));
result->u.l.n_bytes_in_buffer += disksize + OMT_ITEM_OVERHEAD;
toku_omt_insert_at(result->u.l.buffer, le, i);
actual_sum += result->rand4fingerprint*toku_le_crc(le);
//printf("%s:%d rand4=%08x fp=%08x \n", __FILE__, __LINE__, result->rand4fingerprint, actual_sum);
LEAFENTRY le = (LEAFENTRY)(&rc.buf[rc.ndone]);
u_int32_t disksize = leafentry_disksize(le);
rc.ndone += disksize;
assert(rc.ndone<=rc.size);
array[i]=(OMTVALUE)le;
actual_sum += toku_crc32(toku_null_crc, le, disksize);
}
u_int32_t end_of_data = rc.ndone;
result->u.l.n_bytes_in_buffer += end_of_data-start_of_data + n_in_buf*OMT_ITEM_OVERHEAD;
actual_sum *= result->rand4fingerprint;
r = toku_omt_create_from_sorted_array(&result->u.l.buffer, array, n_in_buf);
toku_free(array);
if (r!=0) {
if (0) { died_21: toku_omt_destroy(&result->u.l.buffer); }
goto died1;
}
result->u.l.buffer_mempool.frag_size = start_of_data;
result->u.l.buffer_mempool.free_offset = end_of_data;
if (r!=0) goto died_21;
if (actual_sum!=result->local_fingerprint) {
//fprintf(stderr, "%s:%d Corrupted checksum stored=%08x rand=%08x actual=%08x height=%d n_keys=%d\n", __FILE__, __LINE__, result->rand4fingerprint, result->local_fingerprint, actual_sum, result->height, n_in_buf);
......@@ -436,7 +434,10 @@ int toku_deserialize_brtnode_from (int fd, DISKOFF off, BRTNODE *brtnode) {
}
}
//printf("%s:%d Ok got %lld n_children=%d\n", __FILE__, __LINE__, result->thisnodename, result->n_children);
if (result->height>0) {
// For height==0 we used the buf inside the OMT
toku_free(rc.buf);
}
*brtnode = result;
//toku_verify_counts(result);
return 0;
......
......@@ -3334,9 +3334,12 @@ static int move_it (OMTVALUE lev, u_int32_t idx, void *v) {
return 0;
}
int toku_omt_compress_kvspace (OMT omt, struct mempool *memp) {
if (toku_mempool_get_frag_size(memp) == 0)
return -1;
// Compress things, and grow the mempool if needed.
static int omt_compress_kvspace (OMT omt, struct mempool *memp, size_t added_size) {
u_int32_t total_size_needed = memp->free_offset-memp->frag_size + added_size;
if (total_size_needed+total_size_needed/4 >= memp->size) {
memp->size = total_size_needed+total_size_needed/4;
}
void *newmem = toku_malloc(memp->size);
if (newmem == 0)
return -2;
......@@ -3353,7 +3356,7 @@ int toku_omt_compress_kvspace (OMT omt, struct mempool *memp) {
void *mempool_malloc_from_omt(OMT omt, struct mempool *mp, size_t size) {
void *v = toku_mempool_malloc(mp, size, 1);
if (v==0) {
if (0 == toku_omt_compress_kvspace(omt, mp)) {
if (0 == omt_compress_kvspace(omt, mp, size)) {
v = toku_mempool_malloc(mp, size, 1);
assert(v);
}
......
......@@ -13,256 +13,97 @@
#include <stdlib.h>
#include <string.h>
struct leafentry {
enum typ_tag tag; // Delete this later
char state;
char contents[0];
} __attribute__((packed));
struct contents_committed {
u_int32_t keylen;
u_int32_t vallen;
char data[0];
} __attribute__((packed));
struct contents_both {
TXNID xid;
u_int32_t keylen;
u_int32_t committed_vallen;
u_int32_t prov_vallen;
char data[0];
} __attribute__((packed));
struct contents_provdelorpair { // The PROVDEL or PROVPAIR cases
TXNID xid;
u_int32_t keylen;
u_int32_t vallen;
char data[0];
} __attribute__((packed));
enum le_state get_le_state(LEAFENTRY le) {
return le->state;
}
void* get_le_contents(LEAFENTRY le) {
return &le->contents[0];
}
enum typ_tag get_le_tag(LEAFENTRY le) {
return le->tag;
}
u_int32_t committed_keylen (void*cev) {
struct contents_committed *ce=cev;
return ce->keylen;
}
void* committed_key (void*cev) {
struct contents_committed *ce=cev;
return &ce->data[0];
}
u_int32_t committed_vallen (struct contents_committed *ce) {
return ce->vallen;
}
void* committed_val (struct contents_committed *ce) {
return &ce->data[ce->keylen];
}
TXNID both_xid (struct contents_both *ce) {
return ce->xid;
}
u_int32_t both_keylen (struct contents_both *ce) {
return ce->keylen;
}
u_int32_t both_committed_vallen (struct contents_both *ce) {
return ce->committed_vallen;
}
u_int32_t both_prov_vallen (struct contents_both *ce) {
return ce->prov_vallen;
}
void* both_key (struct contents_both *ce) {
return &ce->data[0];
}
void* both_committed_val (struct contents_both *ce) {
return &ce->data[ce->keylen];
}
void* both_prov_val (struct contents_both*ce) {
return &ce->data[ce->keylen+ce->committed_vallen];
}
TXNID provdelorpair_xid (struct contents_provdelorpair *ce) {
return ce->xid;
}
u_int32_t provdelorpair_keylen (struct contents_provdelorpair *ce) {
return ce->keylen;
}
u_int32_t provdelorpair_vallen (struct contents_provdelorpair *ce) {
return ce->vallen;
}
void* provdelorpair_key (struct contents_provdelorpair *ce) {
return &ce->data[0];
}
void* provdelorpair_val (struct contents_provdelorpair *ce) {
return &ce->data[ce->keylen];
}
static u_int32_t crc_uint32_t (u_int32_t crc, u_int32_t v) {
u_int32_t i = htonl(v);
return toku_crc32(crc, &i, 4);
}
static u_int32_t crc_uint64_t (u_int32_t crc, u_int64_t v) {
crc = crc_uint32_t (crc, (u_int32_t)(v>>32));
crc = crc_uint32_t (crc, (u_int32_t)(v&0xffffffff));
return crc;
}
static u_int32_t crc_dbt (u_int32_t crc, u_int32_t len, void *data) {
crc = crc_uint32_t(crc, len);
crc = toku_crc32(crc, data, len);
return crc;
}
static u_int32_t crc_le_committed(u_int32_t keylen, void *key, u_int32_t vallen, void *val, u_int32_t crc) {
crc = crc_dbt(crc, keylen, key);
crc = crc_dbt(crc, vallen, val);
return crc;
}
static u_int32_t crc_le_both(TXNID xid, u_int32_t keylen, void *key, u_int32_t cvallen, void *cval, u_int32_t pvallen, void *pval, u_int32_t crc) {
crc = crc_uint64_t(crc, xid);
crc = crc_dbt(crc, keylen, key);
crc = crc_dbt(crc, cvallen, cval);
crc = crc_dbt(crc, pvallen, pval);
return crc;
}
static u_int32_t crc_le_provdel(TXNID xid, u_int32_t keylen, void *key, u_int32_t vallen, void *val, u_int32_t crc) {
crc = crc_uint64_t(crc, xid);
crc = crc_dbt(crc, keylen, key);
crc = crc_dbt(crc, vallen, val);
return crc;
}
static u_int32_t crc_le_provpair(TXNID xid, u_int32_t keylen, void *key, u_int32_t vallen, void *val, u_int32_t crc) {
return crc_le_provdel(xid, keylen, key, vallen, val, crc);
}
u_int32_t toku_le_crc(LEAFENTRY v) {
u_int32_t crc = toku_null_crc;
crc = toku_crc32(crc, &v->state, 1);
LESWITCHCALL(v, crc, crc);
return toku_crc32(toku_null_crc, v, leafentry_memsize(v));
}
int le_committed (u_int32_t klen, void* kval, u_int32_t dlen, void* dval, u_int32_t *resultsize, u_int32_t *disksize, LEAFENTRY *result) {
struct contents_committed *ce;
LEAFENTRY le;
size_t size = sizeof(*le)+sizeof(*ce)+klen+dlen;
le=toku_malloc(size);
le->tag = TYP_LEAFENTRY;
le->state= LE_COMMITTED;
ce=(struct contents_committed*)&le->contents[0];
ce->keylen = klen;
ce->vallen = dlen;
memcpy(&ce->data[0], kval, (size_t)klen);
memcpy(&ce->data[klen], dval, (size_t)dlen);
size_t size = 9+klen+dlen;
unsigned char *lec=toku_malloc(size);
assert(lec);
lec[0] = LE_COMMITTED;
putint(lec+1, klen);
memcpy(lec+1+4, kval, klen);
putint(lec+1+4+klen, dlen);
memcpy(lec+1+4+klen+4, dval, dlen);
*resultsize=size;
*disksize = 1 + 4 + 4 + klen + dlen;
*result=le;
*result=(LEAFENTRY)lec;
return 0;
}
int le_both (TXNID xid, u_int32_t klen, void* kval, u_int32_t clen, void* cval, u_int32_t plen, void* pval,
u_int32_t *resultsize, u_int32_t *disksize, LEAFENTRY *result) {
struct contents_both *ce;
LEAFENTRY le;
size_t size = sizeof(*le)+sizeof(*ce)+klen+plen+clen;
le=toku_malloc(size);
le->tag = TYP_LEAFENTRY;
le->state= LE_BOTH;
ce=(struct contents_both*)&le->contents[0];
ce->xid = xid;
ce->keylen = klen;
ce->committed_vallen = clen;
ce->prov_vallen = plen;
memcpy(&ce->data[0], kval, (size_t)klen);
memcpy(&ce->data[klen], cval, (size_t)clen);
memcpy(&ce->data[klen+clen], pval, (size_t)plen);
size_t size = 1+8+4*3+klen+clen+plen;
unsigned char *lec=toku_malloc(size);
assert(lec);
lec[0] = LE_BOTH;
putint64(lec+1, xid);
putint (lec+1+8, klen);
memcpy (lec+1+8+4, kval, klen);
putint (lec+1+8+4+klen, clen);
memcpy (lec+1+8+4+klen+4, cval, clen);
putint (lec+1+8+4+klen+4+clen, plen);
memcpy (lec+1+8+4+klen+4+clen+4, pval, plen);
*resultsize=size;
*disksize = 1 + 8 + 4*3 + klen + clen + plen;
*result=le;
*result=(LEAFENTRY)lec;
return 0;
}
int le_provdel (TXNID xid, u_int32_t klen, void* kval, u_int32_t dlen, void* dval,
u_int32_t *memsize, u_int32_t *disksize, LEAFENTRY *result) {
struct contents_provdelorpair *ce;
LEAFENTRY le;
size_t size = sizeof(*le)+sizeof(*ce)+klen+dlen;
le=toku_malloc(size);
le->tag = TYP_LEAFENTRY;
le->state= LE_PROVDEL;
ce=(struct contents_provdelorpair*)&le->contents[0];
ce->xid = xid;
ce->keylen = klen;
ce->vallen = dlen;
memcpy(&ce->data[0], kval, (size_t)klen);
memcpy(&ce->data[klen], dval, (size_t)dlen);
size_t size = 1 + 8 + 2*4 + klen + dlen;
unsigned char *lec=toku_malloc(size);
assert(lec);
lec[0] = LE_PROVDEL;
putint64(lec+1, xid);
putint (lec+1+8, klen);
memcpy (lec+1+8+4, kval, klen);
putint (lec+1+8+4+klen, dlen);
memcpy (lec+1+8+4+klen+4, dval, dlen);
*memsize=size;
*disksize = 1 + 4 + 4 + 8 + klen + dlen;
*result=le;
*result=(LEAFENTRY)lec;
return 0;
}
int le_provpair (TXNID xid, u_int32_t klen, void* kval, u_int32_t dlen, void* dval, u_int32_t *resultsize, u_int32_t *disksize, LEAFENTRY *result) {
struct contents_provdelorpair *ce;
LEAFENTRY le;
size_t size = sizeof(*le)+sizeof(*ce)+klen+dlen;
le=toku_malloc(size);
le->tag = TYP_LEAFENTRY;
le->state= LE_PROVPAIR;
ce=(struct contents_provdelorpair*)&le->contents[0];
ce->xid = xid;
ce->keylen = klen;
ce->vallen = dlen;
memcpy(&ce->data[0], kval, (size_t)klen);
memcpy(&ce->data[klen], dval, (size_t)dlen);
*resultsize=size;
*disksize = 1 + 4 + 4 + 8 + klen + dlen;
*result=le;
int le_provpair (TXNID xid, u_int32_t klen, void* kval, u_int32_t plen, void* pval, u_int32_t *memsize, u_int32_t *disksize, LEAFENTRY *result) {
size_t size = 1 + 8 + 2*4 + klen + plen;
unsigned char *lec=toku_malloc(size);
assert(lec);
lec[0] = LE_PROVPAIR;
putint64(lec+1, xid);
putint (lec+1+8, klen);
memcpy (lec+1+8+4, kval, klen);
putint (lec+1+8+4+klen, plen);
memcpy (lec+1+8+4+klen+4, pval, plen);
*memsize=size;
*disksize = 1 + 4 + 4 + 8 + klen + plen;
*result=(LEAFENTRY)lec;
return 0;
}
static u_int32_t memsize_le_committed (u_int32_t keylen, void *key __attribute__((__unused__)),
u_int32_t vallen, void *val __attribute__((__unused__))) {
return sizeof(struct leafentry) + sizeof(struct contents_committed) + keylen + vallen;
return 1+ 2*4 + keylen + vallen;
}
static u_int32_t memsize_le_both (TXNID txnid __attribute__((__unused__)),
u_int32_t klen, void *kval __attribute__((__unused__)),
u_int32_t clen, void *cval __attribute__((__unused__)),
u_int32_t plen, void *pval __attribute__((__unused__))) {
return sizeof(struct leafentry) + sizeof(struct contents_both) + klen + clen + plen;
return 1 + 8 + 4*3 + klen + clen + plen;
}
static u_int32_t memsize_le_provdel (TXNID txnid __attribute__((__unused__)),
u_int32_t klen, void *kval __attribute__((__unused__)),
u_int32_t clen, void *cval __attribute__((__unused__))) {
return sizeof(struct leafentry) + sizeof(struct contents_provdelorpair) + klen + clen;
return 1 + 8 + 4*2 + klen + clen;
}
static u_int32_t memsize_le_provpair (TXNID txnid __attribute__((__unused__)),
u_int32_t klen, void *kval __attribute__((__unused__)),
u_int32_t plen, void *pval __attribute__((__unused__))) {
return sizeof(struct leafentry) + sizeof(struct contents_provdelorpair) + klen + plen;
return 1 + 8 + 4*2 + klen + plen;
}
u_int32_t leafentry_memsize (LEAFENTRY le) {
......@@ -293,15 +134,22 @@ static u_int32_t disksize_le_provpair (TXNID txnid __attribute__((__unused__)),
return 1 + 8 + 4 + 4 + klen + plen;
}
u_int32_t leafentry_disksize (LEAFENTRY le) {
u_int32_t leafentry_disksize_internal (LEAFENTRY le) {
LESWITCHCALL(le, disksize);
}
u_int32_t leafentry_disksize (LEAFENTRY le) {
u_int32_t m = leafentry_memsize(le);
u_int32_t d = leafentry_disksize_internal(le);
assert(m==d);
return d;
}
u_int32_t toku_logsizeof_LEAFENTRY (LEAFENTRY le) {
return leafentry_disksize(le);
}
int toku_fread_LEAFENTRY(FILE *f, LEAFENTRY *le, u_int32_t *crc, u_int32_t *len) {
assert(0);
u_int8_t state;
int r = toku_fread_u_int8_t (f, &state, crc, len); if (r!=0) return r;
TXNID xid;
......@@ -406,95 +254,30 @@ int toku_logprint_LEAFENTRY (FILE *outf, FILE *inf, const char *fieldname, u_int
return 0;
}
static int wbuf_le_committed (u_int32_t keylen, void *key, u_int32_t vallen, void *val, struct wbuf *w) {
wbuf_bytes(w, key, keylen);
wbuf_bytes(w, val, vallen);
return 0;
}
static int wbuf_le_both (TXNID xid, u_int32_t klen, void *kval, u_int32_t clen, void *cval, u_int32_t plen, void *pval, struct wbuf *w) {
wbuf_TXNID(w, xid);
wbuf_bytes(w, kval, klen);
wbuf_bytes(w, cval, clen);
wbuf_bytes(w, pval, plen);
return 0;
}
static int wbuf_le_provdel (TXNID xid, u_int32_t klen, void *kval, u_int32_t clen, void *cval, struct wbuf *w) {
wbuf_TXNID(w, xid);
wbuf_bytes(w, kval, klen);
wbuf_bytes(w, cval, clen);
return 0;
}
static int wbuf_le_provpair (TXNID xid, u_int32_t klen, void *kval, u_int32_t plen, void *pval, struct wbuf *w) {
wbuf_TXNID(w, xid);
wbuf_bytes(w, kval, klen);
wbuf_bytes(w, pval, plen);
return 0;
}
static int do_wbuf_le (struct wbuf *w, LEAFENTRY le) {
LESWITCHCALL(le, wbuf, w);
}
void wbuf_LEAFENTRY(struct wbuf *w, LEAFENTRY le) {
wbuf_char(w, (unsigned int)le->state);
do_wbuf_le(w,le);
}
void rbuf_LEAFENTRY(struct rbuf *r, u_int32_t *resultsize, u_int32_t *disksize, LEAFENTRY *le) {
enum le_state state = rbuf_char(r);
switch (state) {
case LE_COMMITTED: {
//printf("%s:%d reading committed\n", __FILE__, __LINE__);
bytevec key, val;
u_int32_t keylen, vallen;
rbuf_bytes(r, &key, &keylen);
rbuf_bytes(r, &val, &vallen);
le_committed(keylen, (void*)key, vallen, (void*)val, resultsize, disksize, le);
wbuf_literal_bytes(w, le, leafentry_disksize(le));
}
void rbuf_LEAFENTRY(struct rbuf *r, u_int32_t *resultsize, u_int32_t *disksize, LEAFENTRY *lep) {
LEAFENTRY le = (LEAFENTRY)(&r->buf[r->ndone]);
u_int32_t siz = leafentry_disksize(le);
bytevec bytes;
rbuf_literal_bytes(r, &bytes, siz);
*lep = toku_memdup(le, siz);
assert(*lep);
*resultsize = siz;
*disksize = siz;
return;
}
case LE_BOTH: {
//printf("%s:%d reading both\n", __FILE__, __LINE__);
bytevec kval, cval, pval;
u_int32_t klen, clen, plen;
TXNID xid = rbuf_ulonglong(r);
rbuf_bytes(r, &kval, &klen);
rbuf_bytes(r, &cval, &clen);
rbuf_bytes(r, &pval, &plen);
le_both(xid, klen, (void*)kval, clen, (void*)cval, plen, (void*)pval, resultsize, disksize, le);
return;
}
case LE_PROVDEL: {
//printf("%s:%d reading provdel\n", __FILE__, __LINE__);
bytevec kval, cval;
u_int32_t klen, clen;
TXNID xid = rbuf_ulonglong(r);
rbuf_bytes(r, &kval, &klen);
rbuf_bytes(r, &cval, &clen);
le_provdel(xid, klen, (void*)kval, clen, (void*)cval, resultsize, disksize, le);
return;
}
case LE_PROVPAIR: {
//printf("%s:%d reading both\n", __FILE__, __LINE__);
bytevec kval, pval;
u_int32_t klen, plen;
TXNID xid = rbuf_ulonglong(r);
rbuf_bytes(r, &kval, &klen);
rbuf_bytes(r, &pval, &plen);
le_provpair(xid, klen, (void*)kval, plen, (void*)pval, resultsize, disksize, le);
return;
}
}
assert(0);
}
// Use toku_free()
// LEAFENTRUse toku_free()
void toku_free_LEAFENTRY(LEAFENTRY le) {
toku_free(le);
}
int le_is_provdel(LEAFENTRY le) {
return le->state==LE_PROVDEL;
return get_le_state(le)==LE_PROVDEL;
}
void* latest_key_le_committed (u_int32_t UU(keylen), void *key, u_int32_t UU(vallen), void *UU(val)) {
......
......@@ -29,6 +29,7 @@
#include "brttypes.h"
#include "rbuf.h"
#include <arpa/inet.h>
u_int32_t toku_le_crc(LEAFENTRY v);
......@@ -45,61 +46,68 @@ enum le_state { LE_COMMITTED=1, // A committed pair.
LE_PROVDEL, // A committed pair that has been provisionally deleted
LE_PROVPAIR }; // No committed value, but a provisional pair.
struct contents_committed;
struct contents_both;
struct contents_provdelorpair;
u_int32_t leafentry_memsize (LEAFENTRY);
enum le_state get_le_state(LEAFENTRY);
void *get_le_contents(LEAFENTRY);
enum typ_tag get_le_tag(LEAFENTRY);
u_int32_t committed_keylen (void*cev);
void* committed_key (void*cev);
u_int32_t committed_vallen (struct contents_committed *ce);
void* committed_val (struct contents_committed *ce);
TXNID both_xid (struct contents_both *ce);
u_int32_t both_keylen (struct contents_both *ce);
u_int32_t both_committed_vallen (struct contents_both *ce);
u_int32_t both_prov_vallen (struct contents_both *ce);
void* both_key (struct contents_both *ce);
void* both_committed_val (struct contents_both *ce);
void* both_prov_val (struct contents_both*ce);
TXNID provdelorpair_xid (struct contents_provdelorpair *ce);
u_int32_t provdelorpair_keylen (struct contents_provdelorpair *ce);
u_int32_t provdelorpair_vallen (struct contents_provdelorpair *ce);
void* provdelorpair_key (struct contents_provdelorpair *ce);
void* provdelorpair_val (struct contents_provdelorpair *ce);
static inline enum le_state get_le_state(LEAFENTRY le) {
return *(unsigned char *)le;
}
static inline void putint (unsigned char *p, u_int32_t i) {
#if 1
*(u_int32_t*)p = htonl(i);
#else
p[0]=(i>>24)&0xff;
p[1]=(i>>16)&0xff;
p[2]=(i>> 8)&0xff;
p[3]=(i>> 0)&0xff;
#endif
}
static inline void putint64 (unsigned char *p, u_int64_t i) {
putint(p, (u_int32_t)(i>>32));
putint(p+4, (u_int32_t)(i&0xffffffff));
}
static inline u_int32_t getint (unsigned char *p) {
#if 1
return ntohl(*(u_int32_t*)p);
#else
return (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+(p[3]);
#endif
}
static inline u_int64_t getint64 (unsigned char *p) {
return (((u_int64_t)getint(p))<<32) + getint(p+4);
}
#define LESWITCHCALL(le,funname, ...) ({ \
assert(get_le_tag(le)==TYP_LEAFENTRY); \
switch(get_le_state(le)) { \
case LE_COMMITTED: return funname ## _le_committed( committed_keylen((struct contents_committed*)(get_le_contents(le))), \
committed_key((struct contents_committed*)(get_le_contents(le))), \
committed_vallen((struct contents_committed*)(get_le_contents(le))), \
committed_val((struct contents_committed*)(get_le_contents(le))), \
## __VA_ARGS__); \
case LE_BOTH: return funname ## _le_both( both_xid((struct contents_both*)(get_le_contents(le))), \
both_keylen((struct contents_both*)(get_le_contents(le))), \
both_key((struct contents_both*)(get_le_contents(le))), \
both_committed_vallen((struct contents_both*)(get_le_contents(le))), \
both_committed_val((struct contents_both*)(get_le_contents(le))), \
both_prov_vallen((struct contents_both*)(get_le_contents(le))), \
both_prov_val((struct contents_both*)(get_le_contents(le))), \
## __VA_ARGS__); \
case LE_PROVDEL: return funname ## _le_provdel ( provdelorpair_xid((struct contents_provdelorpair*)(get_le_contents(le))), \
provdelorpair_keylen((struct contents_provdelorpair*)(get_le_contents(le))), \
provdelorpair_key((struct contents_provdelorpair*)(get_le_contents(le))), \
provdelorpair_vallen((struct contents_provdelorpair*)(get_le_contents(le))), \
provdelorpair_val((struct contents_provdelorpair*)(get_le_contents(le))), \
## __VA_ARGS__); \
case LE_PROVPAIR: return funname ## _le_provpair(provdelorpair_xid((struct contents_provdelorpair*)(get_le_contents(le))), \
provdelorpair_keylen((struct contents_provdelorpair*)(get_le_contents(le))), \
provdelorpair_key((struct contents_provdelorpair*)(get_le_contents(le))), \
provdelorpair_vallen((struct contents_provdelorpair*)(get_le_contents(le))), \
provdelorpair_val((struct contents_provdelorpair*)(get_le_contents(le))), \
## __VA_ARGS__); \
case LE_COMMITTED: { \
unsigned char* __klenaddr = 1+(unsigned char*)le; u_int32_t __klen = getint(__klenaddr); \
unsigned char* __kvaladdr = 4 + __klenaddr; \
unsigned char* __clenaddr = __klen + __kvaladdr; u_int32_t __clen = getint(__clenaddr); \
unsigned char* __cvaladdr = 4 + __clenaddr; \
return funname ## _le_committed(__klen, __kvaladdr, __clen, __cvaladdr, ## __VA_ARGS__); } \
case LE_BOTH: { \
unsigned char* __xidaddr = 1+(unsigned char*)le; u_int64_t __xid = getint64(__xidaddr); \
unsigned char* __klenaddr = 8 + __xidaddr; u_int32_t __klen = getint(__klenaddr); \
unsigned char* __kvaladdr = 4 + __klenaddr; \
unsigned char* __clenaddr = __klen + __kvaladdr; u_int32_t __clen = getint(__clenaddr); \
unsigned char* __cvaladdr = 4 + __clenaddr; \
unsigned char* __plenaddr = __clen + __cvaladdr; u_int32_t __plen = getint(__plenaddr); \
unsigned char* __pvaladdr = 4 + __plenaddr; \
return funname ## _le_both(__xid, __klen, __kvaladdr, __clen, __cvaladdr, __plen, __pvaladdr, ## __VA_ARGS__); } \
case LE_PROVDEL: { \
unsigned char* __xidaddr = 1+(unsigned char*)le; u_int64_t __xid = getint64(__xidaddr); \
unsigned char* __klenaddr = 8 + __xidaddr; u_int32_t __klen = getint(__klenaddr); \
unsigned char* __kvaladdr = 4 + __klenaddr; \
unsigned char* __dlenaddr = __klen + __kvaladdr; u_int32_t __dlen = getint(__dlenaddr); \
unsigned char* __dvaladdr = 4 + __dlenaddr; \
return funname ## _le_provdel(__xid, __klen, __kvaladdr, __dlen, __dvaladdr, ## __VA_ARGS__); } \
case LE_PROVPAIR: { \
unsigned char* __xidaddr = 1+(unsigned char*)le; u_int64_t __xid = getint64(__xidaddr); \
unsigned char* __klenaddr = 8 + __xidaddr; u_int32_t __klen = getint(__klenaddr); \
unsigned char* __kvaladdr = 4 + __klenaddr; \
unsigned char* __plenaddr = __klen + __kvaladdr; u_int32_t __plen = getint(__plenaddr); \
unsigned char* __pvaladdr = 4 + __plenaddr; \
return funname ## _le_provpair(__xid, __klen, __kvaladdr, __plen, __pvaladdr, ## __VA_ARGS__); } \
} abort(); })
......
......@@ -5,6 +5,7 @@
#include "toku_assert.h"
#include "memory.h"
#include <arpa/inet.h>
struct rbuf {
unsigned char *buf;
......@@ -12,12 +13,18 @@ struct rbuf {
unsigned int ndone;
};
static unsigned int rbuf_char (struct rbuf *r) {
static inline unsigned int rbuf_char (struct rbuf *r) {
assert(r->ndone<r->size);
return r->buf[r->ndone++];
}
static unsigned int rbuf_int (struct rbuf *r) {
#if 1
assert(r->ndone+4 <= r->size);
u_int32_t result = ntohl(*(u_int32_t*)(r->buf+r->ndone)); // This only works on machines where unaligned loads are OK.
r->ndone+=4;
return result;
#else
unsigned char c0 = rbuf_char(r);
unsigned char c1 = rbuf_char(r);
unsigned char c2 = rbuf_char(r);
......@@ -26,6 +33,7 @@ static unsigned int rbuf_int (struct rbuf *r) {
(c1<<16)|
(c2<<8)|
(c3<<0));
#endif
}
static inline void rbuf_literal_bytes (struct rbuf *r, bytevec *bytes, unsigned int n_bytes) {
......
......@@ -74,6 +74,7 @@ REGRESSION_TESTS = \
test-brt-overflow \
test-del-inorder \
test-inc-split \
test-leafentry \
test-primes \
test_oexcl \
test_toku_malloc_plain_free \
......
#include <string.h>
#include "leafentry.h"
static void test_leafentry_1 (void) {
LEAFENTRY l;
int r;
u_int32_t msize, dsize;
r = le_committed(4, "abc", 3, "xy", &msize, &dsize, &l);
assert(r==0);
char expect[] = {LE_COMMITTED,
0, 0, 0, 4,
'a', 'b', 'c', 0,
0, 0, 0, 3,
'x', 'y', 0};
assert(sizeof(expect)==msize);
assert(msize==dsize);
assert(memcmp(l, expect, msize)==0);
toku_free(l);
}
static void test_leafentry_2 (void) {
LEAFENTRY l;
int r;
u_int32_t msize, dsize;
r = le_both(0x0123456789abcdef0LL, 3, "ab", 4, "xyz", 5, "lmno", &msize, &dsize, &l);
assert(r==0);
char expect[] = {LE_BOTH,
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0, 0, 0, 3, 'a', 'b', 0,
0, 0, 0, 4, 'x', 'y', 'z', 0,
0, 0, 0, 5, 'l', 'm', 'n', 'o', 0};
assert(sizeof(expect)==msize);
assert(msize==dsize);
assert(memcmp(l, expect, msize)==0);
toku_free(l);
}
static void test_leafentry_3 (void) {
LEAFENTRY l;
int r;
u_int32_t msize, dsize;
r = le_provdel(0x0123456789abcdef0LL, 3, "ab", 5, "lmno", &msize, &dsize, &l);
assert(r==0);
char expect[] = {LE_PROVDEL,
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0, 0, 0, 3, 'a', 'b', 0,
0, 0, 0, 5, 'l', 'm', 'n', 'o', 0};
assert(sizeof(expect)==msize);
assert(msize==dsize);
assert(memcmp(l, expect, msize)==0);
toku_free(l);
}
static void test_leafentry_4 (void) {
LEAFENTRY l;
int r;
u_int32_t msize, dsize;
r = le_provpair(0x0123456789abcdef0LL, 3, "ab", 5, "lmno", &msize, &dsize, &l);
assert(r==0);
char expect[] = {LE_PROVPAIR,
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0, 0, 0, 3, 'a', 'b', 0,
0, 0, 0, 5, 'l', 'm', 'n', 'o', 0};
assert(sizeof(expect)==msize);
assert(msize==dsize);
assert(memcmp(l, expect, msize)==0);
toku_free(l);
}
char zeros[1026];
#define n5zeros 0,0,0,0,0
#define n10zeros n5zeros,n5zeros
#define n25zeros n5zeros,n10zeros,n10zeros
#define n75zeros n25zeros,n25zeros,n25zeros
#define n125zeros n75zeros,n25zeros,n25zeros
#define n150zeros n75zeros,n75zeros
#define n300zeros n150zeros,n150zeros
#define n301zeros 0,n300zeros
#define n1025zeros n300zeros,n300zeros,n300zeros,n125zeros
char expect_3long[] = {LE_PROVDEL,
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0, 0, 1, 45, n301zeros,
0, 0, 4, 1, n1025zeros};
static void test_leafentry_3long (void) {
LEAFENTRY l;
int r;
u_int32_t msize, dsize;
r = le_provdel(0x0123456789abcdef0LL, 301, zeros, 1025, zeros, &msize, &dsize, &l);
assert(r==0);
assert(sizeof(expect_3long)==msize);
assert(msize==dsize);
assert(memcmp(l, expect_3long, msize)==0);
toku_free(l);
}
int main (int argc __attribute__((__unused__)), char *argv[] __attribute__((__unused__))) {
test_leafentry_1();
test_leafentry_2();
test_leafentry_3();
test_leafentry_4();
test_leafentry_3long();
return 0;
}
......@@ -55,10 +55,14 @@ static void wbuf_int (struct wbuf *w, int32_t i) {
wbuf_char(w, i>>0);
#else
assert(w->ndone + 4 <= w->size);
#if 0
w->buf[w->ndone+0] = i>>24;
w->buf[w->ndone+1] = i>>16;
w->buf[w->ndone+2] = i>>8;
w->buf[w->ndone+3] = i>>0;
#else
*(u_int32_t*)(&w->buf[w->ndone]) = htonl(i);
#endif
#ifdef CRC_INCR
w->crc32 = toku_crc32(w->crc32, &w->buf[w->ndone], 4);
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment