Commit 21ccfb87 authored by Yoni Fogel's avatar Yoni Fogel

Addresses #394

Merge branch tokudb.394 back into trunk

git-svn-id: file:///svn/tokudb@3841 c7de825b-a66e-492c-adef-691d508d4ae1
parent a7b1545a
...@@ -2506,13 +2506,35 @@ int show_brt_blocknumbers (BRT brt) { ...@@ -2506,13 +2506,35 @@ int show_brt_blocknumbers (BRT brt) {
#endif #endif
int toku_brt_dbt_set_key(BRT brt, DBT *ybt, bytevec val, ITEMLEN vallen) { int toku_brt_dbt_set_both(BRT brt, DBT* key, DBT* key_source,
int r = toku_dbt_set_value(ybt, val, vallen, &brt->skey); DBT* val, DBT* val_source) {
int r = toku_dbt_set_two_values(key, key_source->data, key_source->size, &brt->skey,
val, val_source->data, val_source->size, &brt->sval);
return r; return r;
} }
int toku_brt_dbt_set_value(BRT brt, DBT *ybt, bytevec val, ITEMLEN vallen) { int toku_brt_dbt_set_three(BRT brt_primary, BRT brt_secondary,
int r = toku_dbt_set_value(ybt, val, vallen, &brt->sval); DBT* key, DBT* key_source,
DBT* pkey, DBT* pkey_source,
DBT* val, DBT* val_source) {
int r = toku_dbt_set_three_values(key, key_source->data, key_source->size, &brt_secondary->skey,
pkey, pkey_source->data, pkey_source->size, &brt_secondary->sval,
val, val_source->data, val_source->size, &brt_primary->sval);
return r;
}
int toku_brt_dbt_set(DBT* key, DBT* key_source) {
int r = toku_dbt_set_value(key, key_source->data, key_source->size, NULL);
return r;
}
int toku_brt_dbt_set_key(BRT brt, DBT* key, DBT* key_source) {
int r = toku_dbt_set_value(key, key_source->data, key_source->size, &brt->skey);
return r;
}
int toku_brt_dbt_set_val(BRT brt, DBT* val, DBT* val_source) {
int r = toku_dbt_set_value(val, val_source->data, val_source->size, &brt->sval);
return r; return r;
} }
...@@ -2685,11 +2707,16 @@ static int brt_search_leaf_node(BRT brt, BRTNODE node, brt_search_t *search, DBT ...@@ -2685,11 +2707,16 @@ static int brt_search_leaf_node(BRT brt, BRTNODE node, brt_search_t *search, DBT
} }
} }
got_a_good_value: got_a_good_value:
if (newkey) { if (newkey && newval) {
r = toku_dbt_set_two_values(newkey, le_latest_key(le), le_latest_keylen(le), &brt->skey,
newval, le_latest_val(le), le_latest_vallen(le), &brt->sval);
if (r!=0) return r;
}
else if (newkey) {
r = toku_dbt_set_value(newkey, le_latest_key(le), le_latest_keylen(le), &brt->skey); r = toku_dbt_set_value(newkey, le_latest_key(le), le_latest_keylen(le), &brt->skey);
if (r!=0) return r; if (r!=0) return r;
} }
if (newval) { else if (newval) {
r = toku_dbt_set_value(newval, le_latest_val(le), le_latest_vallen(le), &brt->sval); r = toku_dbt_set_value(newval, le_latest_val(le), le_latest_vallen(le), &brt->sval);
if (r!=0) return r; if (r!=0) return r;
} }
...@@ -2776,6 +2803,11 @@ static inline void brt_cursor_set_key_val(BRT_CURSOR cursor, DBT *newkey, DBT *n ...@@ -2776,6 +2803,11 @@ static inline void brt_cursor_set_key_val(BRT_CURSOR cursor, DBT *newkey, DBT *n
cursor->val = *newval; memset(newval, 0, sizeof *newval); cursor->val = *newval; memset(newval, 0, sizeof *newval);
} }
/* Used to restore the state of a cursor. */
void brt_cursor_set_key_val_manually(BRT_CURSOR cursor, DBT* key, DBT* val) {
brt_cursor_set_key_val(cursor, key, val);
}
int toku_brt_cursor (BRT brt, BRT_CURSOR *cursorptr, int is_temporary_cursor) { int toku_brt_cursor (BRT brt, BRT_CURSOR *cursorptr, int is_temporary_cursor) {
BRT_CURSOR cursor = toku_malloc(sizeof *cursor); BRT_CURSOR cursor = toku_malloc(sizeof *cursor);
if (cursor == 0) if (cursor == 0)
...@@ -2816,13 +2848,38 @@ static inline int compare_kv_xy(BRT brt, DBT *k, DBT *v, DBT *x, DBT *y) { ...@@ -2816,13 +2848,38 @@ static inline int compare_kv_xy(BRT brt, DBT *k, DBT *v, DBT *x, DBT *y) {
static inline int brt_cursor_copyout(BRT_CURSOR cursor, DBT *key, DBT *val) { static inline int brt_cursor_copyout(BRT_CURSOR cursor, DBT *key, DBT *val) {
int r = 0; int r = 0;
if (key) void** key_staticp = cursor->is_temporary_cursor ? &cursor->brt->skey : &cursor->skey;
r = toku_dbt_set_value(key, cursor->key.data, cursor->key.size, cursor->is_temporary_cursor ? &cursor->brt->skey : &cursor->skey); void** val_staticp = cursor->is_temporary_cursor ? &cursor->brt->sval : &cursor->sval;
if (r == 0 && val) r = toku_dbt_set_two_values(key, cursor->key.data, cursor->key.size, key_staticp,
r = toku_dbt_set_value(val, cursor->val.data, cursor->val.size, cursor->is_temporary_cursor ? &cursor->brt->sval : &cursor->sval); val, cursor->val.data, cursor->val.size, val_staticp);
return r;
}
int toku_brt_cursor_copyout(BRT_CURSOR cursor, DBT *key, DBT *val) {
int r = brt_cursor_copyout(cursor, key, val);
return r; return r;
} }
/* Used to save the state of a cursor. */
int brt_cursor_save_key_val(BRT_CURSOR cursor, DBT* key, DBT* val) {
if (brt_cursor_not_set(cursor)) {
if (key) { *key = cursor->key; }
if (val) { *val = cursor->val; }
return 0;
}
else {
assert(!key || key->flags == DB_DBT_MALLOC);
assert(!val || val->flags == DB_DBT_MALLOC);
int r;
if ((r = brt_cursor_copyout(cursor, key, val))) { return r; }
/* An initialized cursor cannot have NULL key->data or
* val->data. */
assert(key==NULL || key->data!=NULL);
assert(val==NULL || val->data!=NULL);
return 0;
}
}
static int brt_cursor_compare_set(brt_search_t *search, DBT *x, DBT *y) { static int brt_cursor_compare_set(brt_search_t *search, DBT *x, DBT *y) {
BRT brt = search->context; BRT brt = search->context;
return compare_kv_xy(brt, search->k, search->v, x, y) <= 0; /* return min xy: kv <= xy */ return compare_kv_xy(brt, search->k, search->v, x, y) <= 0; /* return min xy: kv <= xy */
......
...@@ -59,8 +59,16 @@ int brtenv_checkpoint (BRTENV env); ...@@ -59,8 +59,16 @@ int brtenv_checkpoint (BRTENV env);
extern int toku_brt_do_push_cmd; // control whether push occurs eagerly. extern int toku_brt_do_push_cmd; // control whether push occurs eagerly.
int toku_brt_dbt_set_key (BRT, DBT*, bytevec val, ITEMLEN vallen); int toku_brt_dbt_set_three(BRT brt_primary, BRT brt_secondary,
int toku_brt_dbt_set_value (BRT, DBT*, bytevec val, ITEMLEN vallen); DBT* key, DBT* key_source,
DBT* pkey, DBT* pkey_source,
DBT* val, DBT* val_source);
int toku_brt_dbt_set_both(BRT brt, DBT* key, DBT* key_source,
DBT* val, DBT* val_source);
int toku_brt_dbt_set_key(BRT brt, DBT* key, DBT* key_source);
int toku_brt_dbt_set_val(BRT brt, DBT* val, DBT* val_source);
int toku_brt_dbt_set(DBT* key, DBT* key_source);
int toku_brt_cursor_copyout(BRT_CURSOR cursor, DBT *key, DBT *val);
int toku_brt_get_fd(BRT, int *); int toku_brt_get_fd(BRT, int *);
......
...@@ -150,10 +150,8 @@ static int toku_pma_cursor_get_current(PMA_CURSOR cursor, DBT *key, DBT *val, in ...@@ -150,10 +150,8 @@ static int toku_pma_cursor_get_current(PMA_CURSOR cursor, DBT *key, DBT *val, in
if (r != 0) if (r != 0)
return r; return r;
if (key) r = toku_dbt_set_two_values(key, cursor->key.data, cursor->key.size, cursor->sskey,
r = toku_dbt_set_value(key, cursor->key.data, cursor->key.size, cursor->sskey); val, cursor->val.data, cursor->val.size, cursor->ssval);
if (val && r == 0)
r = toku_dbt_set_value(val, cursor->val.data, cursor->val.size, cursor->ssval);
return r; return r;
} }
......
...@@ -16,44 +16,115 @@ DBT *toku_fill_dbt(DBT *dbt, bytevec k, ITEMLEN len) { ...@@ -16,44 +16,115 @@ DBT *toku_fill_dbt(DBT *dbt, bytevec k, ITEMLEN len) {
return dbt; return dbt;
} }
int toku_dbt_set_value (DBT *ybt, bytevec val, ITEMLEN vallen, void **staticptrp) { static inline int dbt_set_preprocess(DBT* ybt, ITEMLEN len, void** staticptrp, void** tmp_data) {
int r = ENOSYS; int r = ENOSYS;
if (ybt->flags==DB_DBT_MALLOC) { if (ybt) {
domalloc: if (ybt->flags==DB_DBT_USERMEM) {
ybt->data = toku_malloc((size_t)vallen); if (ybt->ulen < len) {
if (!ybt->data && vallen > 0) { r = errno; goto cleanup; } ybt->size = len;
} else if (ybt->flags==DB_DBT_REALLOC) { r = DB_BUFFER_SMALL;
if (ybt->data==0) goto domalloc; goto cleanup;
/* tmp is used to prevent a memory leak if realloc fails */
void* tmp = toku_realloc(ybt->data, (size_t)vallen);
if (!tmp && vallen > 0) { r = errno; goto cleanup; }
ybt->data = tmp;
} else if (ybt->flags==DB_DBT_USERMEM) {
ybt->size = vallen;
if (ybt->ulen < vallen) { r = DB_BUFFER_SMALL; goto cleanup; }
} else {
if (staticptrp==0) return -1;
void *staticptr=*staticptrp;
//void *old=staticptr;
if (staticptr==0) {
staticptr = toku_malloc((size_t)vallen);
if (!staticptr && vallen > 0) { r = errno; goto cleanup; }
} else {
/* tmp is used to prevent a memory leak if realloc fails */
void* tmp = toku_realloc(staticptr, vallen);
if (!tmp && vallen > 0) { r = errno; goto cleanup; }
staticptr = tmp;
}
//if (old!=staticptr) printf("%s:%d MALLOC --> %p\n", __FILE__, __LINE__, staticptr);
*staticptrp = staticptr;
ybt->data = vallen > 0 ? staticptr : 0;
}
ybt->size = vallen;
if (ybt->size>0) {
memcpy(ybt->data, val, (size_t)vallen);
} }
}
else if (ybt->flags==DB_DBT_MALLOC || ybt->flags==DB_DBT_REALLOC || ybt->flags==0) {
if (ybt->flags==0 && staticptrp==NULL) { r = -1; goto cleanup; }
*tmp_data = toku_malloc(len);
if (!*tmp_data && len > 0) { r = errno; goto cleanup; }
}
else { r = EINVAL; goto cleanup; }
}
r = 0;
cleanup:
return r;
}
static inline void dbt_set_copy(DBT* ybt, bytevec data, ITEMLEN len, void** staticptrp, void* tmp_data) {
if (ybt) {
if (ybt->flags==DB_DBT_REALLOC && ybt->data) toku_free(ybt->data);
else if (ybt->flags==0) {
toku_free(*staticptrp);
*staticptrp = tmp_data;
}
if (ybt->flags!=DB_DBT_USERMEM) {
if (ybt->flags!=0 || len>0) ybt->data = tmp_data;
else ybt->data = NULL;
}
if ((ybt->size = len) > 0) memcpy(ybt->data, data, (size_t)len);
}
}
/* Atomically set three dbts, such that they either both succeed, or
* there is no side effect. */
int toku_dbt_set_three_values(
DBT* ybt1, bytevec ybt1_data, ITEMLEN ybt1_len, void** ybt1_staticptrp,
DBT* ybt2, bytevec ybt2_data, ITEMLEN ybt2_len, void** ybt2_staticptrp,
DBT* ybt3, bytevec ybt3_data, ITEMLEN ybt3_len, void** ybt3_staticptrp) {
int r = ENOSYS;
void* tmp_ybt1_data = NULL;
void* tmp_ybt2_data = NULL;
void* tmp_ybt3_data = NULL;
/* Do all mallocs and check for all possible errors. */
if ((r = dbt_set_preprocess(ybt1, ybt1_len, ybt1_staticptrp, &tmp_ybt1_data))) goto cleanup;
if ((r = dbt_set_preprocess(ybt2, ybt2_len, ybt2_staticptrp, &tmp_ybt2_data))) goto cleanup;
if ((r = dbt_set_preprocess(ybt3, ybt3_len, ybt3_staticptrp, &tmp_ybt3_data))) goto cleanup;
/* Copy/modify atomically the dbts. */
dbt_set_copy(ybt1, ybt1_data, ybt1_len, ybt1_staticptrp, tmp_ybt1_data);
dbt_set_copy(ybt2, ybt2_data, ybt2_len, ybt2_staticptrp, tmp_ybt2_data);
dbt_set_copy(ybt3, ybt3_data, ybt3_len, ybt3_staticptrp, tmp_ybt3_data);
r = 0;
cleanup:
if (r!=0) {
if (tmp_ybt1_data) toku_free(tmp_ybt1_data);
if (tmp_ybt2_data) toku_free(tmp_ybt2_data);
if (tmp_ybt3_data) toku_free(tmp_ybt3_data);
}
return r;
}
/* Atomically set two dbts, such that they either both succeed, or
* there is no side effect. */
int toku_dbt_set_two_values(
DBT* ybt1, bytevec ybt1_data, ITEMLEN ybt1_len, void** ybt1_staticptrp,
DBT* ybt2, bytevec ybt2_data, ITEMLEN ybt2_len, void** ybt2_staticptrp) {
int r = ENOSYS;
void* tmp_ybt1_data = NULL;
void* tmp_ybt2_data = NULL;
/* Do all mallocs and check for all possible errors. */
if ((r = dbt_set_preprocess(ybt1, ybt1_len, ybt1_staticptrp, &tmp_ybt1_data))) goto cleanup;
if ((r = dbt_set_preprocess(ybt2, ybt2_len, ybt2_staticptrp, &tmp_ybt2_data))) goto cleanup;
/* Copy/modify atomically the dbts. */
dbt_set_copy(ybt1, ybt1_data, ybt1_len, ybt1_staticptrp, tmp_ybt1_data);
dbt_set_copy(ybt2, ybt2_data, ybt2_len, ybt2_staticptrp, tmp_ybt2_data);
r = 0; r = 0;
cleanup: cleanup:
if (r!=0) {
if (tmp_ybt1_data) toku_free(tmp_ybt1_data);
if (tmp_ybt2_data) toku_free(tmp_ybt2_data);
}
return r;
}
int toku_dbt_set_value(DBT* ybt1, bytevec ybt1_data, ITEMLEN ybt1_len, void** ybt1_staticptrp) {
int r = ENOSYS;
void* tmp_ybt1_data = NULL;
/* Do all mallocs and check for all possible errors. */
if ((r = dbt_set_preprocess(ybt1, ybt1_len, ybt1_staticptrp, &tmp_ybt1_data))) goto cleanup;
/* Copy/modify atomically the dbts. */
dbt_set_copy(ybt1, ybt1_data, ybt1_len, ybt1_staticptrp, tmp_ybt1_data);
r = 0;
cleanup:
if (r!=0) {
if (tmp_ybt1_data) toku_free(tmp_ybt1_data);
}
return r; return r;
} }
...@@ -11,6 +11,12 @@ ...@@ -11,6 +11,12 @@
DBT* toku_init_dbt (DBT *); DBT* toku_init_dbt (DBT *);
DBT *toku_fill_dbt(DBT *dbt, bytevec k, ITEMLEN len); DBT *toku_fill_dbt(DBT *dbt, bytevec k, ITEMLEN len);
int toku_dbt_set_value (DBT *, bytevec val, ITEMLEN vallen, void **staticptrp); int toku_dbt_set_value (DBT *, bytevec val, ITEMLEN vallen, void **staticptrp);
int toku_dbt_set_two_values(DBT* key, bytevec key_data, ITEMLEN key_len, void** key_staticptrp,
DBT* val, bytevec val_data, ITEMLEN val_len, void** val_staticptrp);
int toku_dbt_set_three_values(
DBT* ybt1, bytevec ybt1_data, ITEMLEN ybt1_len, void** ybt1_staticptrp,
DBT* ybt2, bytevec ybt2_data, ITEMLEN ybt2_len, void** ybt2_staticptrp,
DBT* ybt3, bytevec ybt3_data, ITEMLEN ybt3_len, void** ybt3_staticptrp);
......
This diff is collapsed.
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