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
This commit is contained in:
Yoni Fogel 2008-06-12 23:07:04 +00:00
parent fe3cd46d32
commit acf688ef2e
2 changed files with 64 additions and 43 deletions

View file

@ -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;
}
if (ybt->flags!=DB_DBT_USERMEM) {
if (ybt->flags!=0 || len>0) ybt->data = *tmp_data;
else ybt->data = NULL;
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->size = len) > 0 && !input_disposable) memcpy(ybt->data, data, (size_t)len);
//Malloc new buffer
if (do_malloc) {
tempdata = toku_malloc(len);
if (!tempdata) return errno;
}
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:

View file

@ -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);
}