Commit 941a2a24 authored by Yoni Fogel's avatar Yoni Fogel

Closes #912

toku_db_set_* (the dbt setting functions)
no longer require atomicity for ENOMEM cases.
Also, in the case of realloc, we only alloc new memory if
the new size is larger than the old size, or the new size is less than
half of the old size.

Code has some simplifications due to lesser atomicity requirements.

Modified src/tests/test_db_dbt_mem_behavior.c to take into account
that DB_DBT_REALLOC now uses the ulen field.

git-svn-id: file:///svn/tokudb@4504 c7de825b-a66e-492c-adef-691d508d4ae1
parent 62af9417
......@@ -16,7 +16,7 @@ DBT *toku_fill_dbt(DBT *dbt, bytevec k, ITEMLEN len) {
return dbt;
}
static inline int dbt_set_preprocess(DBT* ybt, ITEMLEN len, void** staticptrp, void** tmp_data, BOOL input_disposable) {
static inline int dbt_set_preprocess(DBT* ybt, ITEMLEN len, void** staticptrp) {
int r = ENOSYS;
if (ybt) {
if (ybt->flags==DB_DBT_USERMEM) {
......@@ -26,39 +26,61 @@ static inline int dbt_set_preprocess(DBT* ybt, ITEMLEN len, void** staticptrp, v
goto cleanup;
}
}
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; }
if (!input_disposable) {
*tmp_data = toku_malloc(len);
if (!*tmp_data) { r = errno; goto cleanup; }
}
else if (ybt->flags==0) {
if (!staticptrp) { r = -1; goto cleanup; }
}
else if (ybt->flags!=DB_DBT_MALLOC && ybt->flags!=DB_DBT_REALLOC) {
r = EINVAL; goto cleanup;
}
else { r = EINVAL; goto cleanup; }
}
r = 0;
cleanup:
return r;
}
static inline void dbt_set_copy(DBT* ybt, bytevec* datap, ITEMLEN len, void** staticptrp, void** tmp_data, BOOL input_disposable) {
static inline int dbt_set_copy(DBT* ybt, bytevec* datap, ITEMLEN len, void** staticptrp, BOOL input_disposable) {
if (ybt) {
bytevec data = *datap;
if (ybt->flags==DB_DBT_USERMEM) input_disposable = FALSE;
else if (input_disposable) {
*tmp_data = (void*)data;
*datap = NULL;
if (ybt->flags==DB_DBT_USERMEM) {
if ((ybt->size=len) > 0) memcpy(ybt->data, *datap, (size_t)len);
return 0;
}
if (ybt->flags==DB_DBT_REALLOC && ybt->data) toku_free(ybt->data);
else if (ybt->flags==0) {
if (*staticptrp) toku_free(*staticptrp);
*staticptrp = *tmp_data;
void* tempdata;
BOOL do_malloc = TRUE;
if (input_disposable) {
tempdata = (void*)*datap;
do_malloc = FALSE;
}
else if (ybt->flags==DB_DBT_REALLOC) {
if (ybt->data && ybt->ulen>=len && ybt->ulen/2<=len) {
tempdata = ybt->data;
do_malloc = FALSE;
}
}
if (ybt->flags!=DB_DBT_USERMEM) {
if (ybt->flags!=0 || len>0) ybt->data = *tmp_data;
else ybt->data = NULL;
//Malloc new buffer
if (do_malloc) {
tempdata = toku_malloc(len);
if (!tempdata) return errno;
}
if ((ybt->size = len) > 0 && !input_disposable) memcpy(ybt->data, data, (size_t)len);
if (input_disposable || do_malloc) {
//Set ulen
if (ybt->flags==DB_DBT_REALLOC) ybt->ulen = len;
//Freeing
if (ybt->flags==DB_DBT_REALLOC && ybt->data) toku_free(ybt->data);
if (ybt->flags==0) {
if (*staticptrp) toku_free(*staticptrp);
//Set static pointer
*staticptrp = tempdata;
}
}
//Set ybt->data
if (ybt->flags!=0 || len>0) ybt->data = tempdata;
else ybt->data = NULL;
//Set ybt->size and memcpy
if ((ybt->size=len) > 0 && !input_disposable) memcpy(ybt->data, *datap, (size_t)len);
if (input_disposable) *datap = NULL;
}
return 0;
}
/* Atomically set three dbts, such that they either both succeed, or
......@@ -68,27 +90,19 @@ int toku_dbt_set_three_values(
DBT* ybt2, bytevec* ybt2_data, ITEMLEN ybt2_len, void** ybt2_staticptrp, BOOL ybt2_disposable,
DBT* ybt3, bytevec* ybt3_data, ITEMLEN ybt3_len, void** ybt3_staticptrp, BOOL ybt3_disposable) {
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, ybt1_disposable))) goto cleanup;
if ((r = dbt_set_preprocess(ybt2, ybt2_len, ybt2_staticptrp, &tmp_ybt2_data, ybt2_disposable))) goto cleanup;
if ((r = dbt_set_preprocess(ybt3, ybt3_len, ybt3_staticptrp, &tmp_ybt3_data, ybt3_disposable))) goto cleanup;
if ((r = dbt_set_preprocess(ybt1, ybt1_len, ybt1_staticptrp))) goto cleanup;
if ((r = dbt_set_preprocess(ybt2, ybt2_len, ybt2_staticptrp))) goto cleanup;
if ((r = dbt_set_preprocess(ybt3, ybt3_len, ybt3_staticptrp))) goto cleanup;
/* Copy/modify atomically the dbts. */
dbt_set_copy(ybt1, ybt1_data, ybt1_len, ybt1_staticptrp, &tmp_ybt1_data, ybt1_disposable);
dbt_set_copy(ybt2, ybt2_data, ybt2_len, ybt2_staticptrp, &tmp_ybt2_data, ybt2_disposable);
dbt_set_copy(ybt3, ybt3_data, ybt3_len, ybt3_staticptrp, &tmp_ybt3_data, ybt3_disposable);
if ((r = dbt_set_copy(ybt1, ybt1_data, ybt1_len, ybt1_staticptrp, ybt1_disposable))) goto cleanup;
if ((r = dbt_set_copy(ybt2, ybt2_data, ybt2_len, ybt2_staticptrp, ybt2_disposable))) goto cleanup;
if ((r = dbt_set_copy(ybt3, ybt3_data, ybt3_len, ybt3_staticptrp, ybt3_disposable))) goto cleanup;
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;
}
......@@ -102,12 +116,12 @@ int toku_dbt_set_two_values(
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, ybt1_disposable))) goto cleanup;
if ((r = dbt_set_preprocess(ybt2, ybt2_len, ybt2_staticptrp, &tmp_ybt2_data, ybt2_disposable))) goto cleanup;
if ((r = dbt_set_preprocess(ybt1, ybt1_len, ybt1_staticptrp))) goto cleanup;
if ((r = dbt_set_preprocess(ybt2, ybt2_len, ybt2_staticptrp))) goto cleanup;
/* Copy/modify atomically the dbts. */
dbt_set_copy(ybt1, ybt1_data, ybt1_len, ybt1_staticptrp, &tmp_ybt1_data, ybt1_disposable);
dbt_set_copy(ybt2, ybt2_data, ybt2_len, ybt2_staticptrp, &tmp_ybt2_data, ybt2_disposable);
if ((r = dbt_set_copy(ybt1, ybt1_data, ybt1_len, ybt1_staticptrp, ybt1_disposable))) goto cleanup;
if ((r = dbt_set_copy(ybt2, ybt2_data, ybt2_len, ybt2_staticptrp, ybt2_disposable))) goto cleanup;
r = 0;
cleanup:
......@@ -123,10 +137,10 @@ int toku_dbt_set_value(DBT* ybt1, bytevec* ybt1_data, ITEMLEN ybt1_len, void** y
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, ybt1_disposable))) goto cleanup;
if ((r = dbt_set_preprocess(ybt1, ybt1_len, ybt1_staticptrp))) goto cleanup;
/* Copy/modify atomically the dbts. */
dbt_set_copy(ybt1, ybt1_data, ybt1_len, ybt1_staticptrp, &tmp_ybt1_data, ybt1_disposable);
if ((r = dbt_set_copy(ybt1, ybt1_data, ybt1_len, ybt1_staticptrp, ybt1_disposable))) goto cleanup;
r = 0;
cleanup:
......
......@@ -128,7 +128,14 @@ int main(int argc, const char *argv[]) {
}
assert(!was_truncated);
assert(!ulen_changed);
BOOL ulen_should_change = FALSE;
#if defined(USE_TDB)
if (flags[j] == DB_DBT_REALLOC) {
ulen_should_change = old_ulen < sizeof(DATA);
}
#endif
assert(ulen_should_change == ulen_changed);
assert(size_full);
assert(clone == !small_buffer);
}
......
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