Commit d42e6c85 authored by John Esmet's avatar John Esmet Committed by Yoni Fogel

[t:5133] properly fix the memory leak introduced earlier today.

the big idea is that we need to allocate space for a leaf entry and keep it around if we want to create a ULE for it. so now the provisional info holds a pointer to both the le and the ule so the caller can free it later.


git-svn-id: file:///svn/toku/tokudb@45071 c7de825b-a66e-492c-adef-691d508d4ae1
parent e91fc623
...@@ -516,7 +516,8 @@ ule_cleanup(ULE ule) { ...@@ -516,7 +516,8 @@ ule_cleanup(ULE ule) {
} }
} }
// Purpose of le_unpack() is to populate our private workspace with the contents of the given le. // populate an unpacked leafentry using pointers into the given leafentry.
// thus, the memory referenced by 'le' must live as long as the ULE.
void void
le_unpack(ULE ule, LEAFENTRY le) { le_unpack(ULE ule, LEAFENTRY le) {
//Read the keylen //Read the keylen
......
...@@ -28,7 +28,12 @@ struct indexer_commit_keys { ...@@ -28,7 +28,12 @@ struct indexer_commit_keys {
// a cursor callback that provides exclusive access to the source DB // a cursor callback that provides exclusive access to the source DB
// with respect to txn commit and abort // with respect to txn commit and abort
struct ule_prov_info { struct ule_prov_info {
// these are pointers to the allocated leafentry and ule needed to calculate
// provisional info. we only borrow them - whoever created the provisional info
// is responsible for cleaning up the leafentry and ule when done.
LEAFENTRY le;
ULEHANDLE ule; ULEHANDLE ule;
// provisional txn info for the ule
uint32_t num_provisional; uint32_t num_provisional;
uint32_t num_committed; uint32_t num_committed;
TXNID *prov_ids; TXNID *prov_ids;
......
...@@ -279,12 +279,12 @@ toku_indexer_is_key_right_of_le_cursor(DB_INDEXER *indexer, const DBT *key) { ...@@ -279,12 +279,12 @@ toku_indexer_is_key_right_of_le_cursor(DB_INDEXER *indexer, const DBT *key) {
return toku_le_cursor_is_key_greater(indexer->i->lec, key); return toku_le_cursor_is_key_greater(indexer->i->lec, key);
} }
// initialize provisional info by allocating enough space to // initialize provisional info by allocating enough space to hold provisional
// hold provisional ids, states, and txns for each of the // ids, states, and txns for each of the provisional entries in the ule. the
// provisional entries in the ule. the ule remains owned by // ule and le remain owned by the caller, not this struct.
// the caller, not the prov info.
static void static void
ule_prov_info_init(struct ule_prov_info *prov_info, ULEHANDLE ule) { ule_prov_info_init(struct ule_prov_info *prov_info, LEAFENTRY le, ULEHANDLE ule) {
prov_info->le = le;
prov_info->ule = ule; prov_info->ule = ule;
prov_info->num_provisional = ule_get_num_provisional(ule); prov_info->num_provisional = ule_get_num_provisional(ule);
prov_info->num_committed = ule_get_num_committed(ule); prov_info->num_committed = ule_get_num_committed(ule);
...@@ -370,15 +370,16 @@ le_cursor_callback(ITEMLEN UU(keylen), bytevec UU(key), ITEMLEN UU(vallen), byte ...@@ -370,15 +370,16 @@ le_cursor_callback(ITEMLEN UU(keylen), bytevec UU(key), ITEMLEN UU(vallen), byte
} else { } else {
struct le_cursor_extra *cursor_extra = extra; struct le_cursor_extra *cursor_extra = extra;
struct ule_prov_info *prov_info = cursor_extra->prov_info; struct ule_prov_info *prov_info = cursor_extra->prov_info;
// the val here is a leafentry. ule_create copies the contents of a // the val here is a leafentry. ule_create does not copy the entire
// leafentry into its own buffers, so we don't need to malloc space // contents of the leafentry it is given into its own buffers, so we
// for this value to exist outside the callback. // must allocate space for a leafentry and keep it around with the ule.
// LEAFENTRY le = toku_xmemdup(val, vallen);
// blast away the const from bytevec by casting to LEAFENTRY
LEAFENTRY le = (LEAFENTRY) val;
ULEHANDLE ule = toku_ule_create(le); ULEHANDLE ule = toku_ule_create(le);
invariant(ule); invariant(ule);
ule_prov_info_init(prov_info, ule); // when we initialize prov info, we also pass in the leafentry and ule
// pointers so the caller can access them later. it's their job to free
// them when they're not needed.
ule_prov_info_init(prov_info, le, ule);
indexer_fill_prov_info(cursor_extra->indexer, prov_info); indexer_fill_prov_info(cursor_extra->indexer, prov_info);
} }
return 0; return 0;
...@@ -425,7 +426,9 @@ build_index(DB_INDEXER *indexer) { ...@@ -425,7 +426,9 @@ build_index(DB_INDEXER *indexer) {
} }
} }
else { else {
invariant(prov_info.le);
invariant(prov_info.ule); invariant(prov_info.ule);
LEAFENTRY le = prov_info.le;
ULEHANDLE ule = prov_info.ule; ULEHANDLE ule = prov_info.ule;
for (int which_db = 0; (which_db < indexer->i->N) && (result == 0); which_db++) { for (int which_db = 0; (which_db < indexer->i->N) && (result == 0); which_db++) {
DB *db = indexer->i->dest_dbs[which_db]; DB *db = indexer->i->dest_dbs[which_db];
...@@ -437,8 +440,11 @@ build_index(DB_INDEXER *indexer) { ...@@ -437,8 +440,11 @@ build_index(DB_INDEXER *indexer) {
indexer->i->error_callback(db, which_db, result, &key, NULL, indexer->i->error_extra); indexer->i->error_callback(db, which_db, result, &key, NULL, indexer->i->error_extra);
toku_destroy_dbt(&key); toku_destroy_dbt(&key);
} }
toku_ule_free(prov_info.ule);
} }
// the leafentry and ule are not owned by the prov_info,
// and are still our responsibility to free
toku_free(prov_info.le);
toku_ule_free(prov_info.ule);
} }
toku_indexer_unlock(indexer); toku_indexer_unlock(indexer);
...@@ -579,7 +585,8 @@ static int ...@@ -579,7 +585,8 @@ static int
test_indexer_undo_do(DB_INDEXER *indexer, DB *hotdb, ULEHANDLE ule) { test_indexer_undo_do(DB_INDEXER *indexer, DB *hotdb, ULEHANDLE ule) {
struct ule_prov_info prov_info; struct ule_prov_info prov_info;
memset(&prov_info, 0, sizeof(prov_info)); memset(&prov_info, 0, sizeof(prov_info));
ule_prov_info_init(&prov_info, ule); // pass null for the leafentry - we don't need it, neither does the info
ule_prov_info_init(&prov_info, NULL, ule);
indexer_fill_prov_info(indexer, &prov_info); indexer_fill_prov_info(indexer, &prov_info);
int r = indexer_undo_do(indexer, hotdb, ule, &prov_info); int r = indexer_undo_do(indexer, hotdb, ule, &prov_info);
ule_prov_info_destroy(&prov_info); ule_prov_info_destroy(&prov_info);
......
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