1
0
Fork 0

fixed memleaks that occurred during failure testing only

This commit is contained in:
Jan Steemann 2015-12-23 20:48:46 +01:00
parent a8e822edce
commit f1ed7cdf46
3 changed files with 164 additions and 131 deletions

View File

@ -319,6 +319,7 @@ bool IndexBlock::initIndexes () {
}
if (_currentIndex < _indexes.size()) {
// This check will work as long as _indexes.size() < MAX_SIZE_T
TRI_ASSERT(_iterator == nullptr);
_iterator = createIterator();
}
else {
@ -364,6 +365,7 @@ void IndexBlock::startNextIterator () {
}
if (_currentIndex < _indexes.size()) {
// This check will work as long as _indexes.size() < MAX_SIZE_T
TRI_ASSERT(_iterator == nullptr);
_iterator = createIterator();
}
}

View File

@ -904,65 +904,76 @@ IndexIterator* HashIndex::iteratorForCondition (IndexIteratorContext* context,
std::vector<TRI_hash_index_search_value_t*> searchValues;
searchValues.reserve(maxPermutations);
// create all permutations
auto shaper = _collection->getShaper();
size_t current = 0;
bool done = false;
while (! done) {
auto searchValue = std::make_unique<TRI_hash_index_search_value_t>();
searchValue->reserve(n);
try {
// create all permutations
auto shaper = _collection->getShaper();
size_t current = 0;
bool done = false;
while (! done) {
auto searchValue = std::make_unique<TRI_hash_index_search_value_t>();
searchValue->reserve(n);
bool valid = true;
for (size_t i = 0; i < n; ++i) {
auto& state = permutationStates[i];
std::unique_ptr<TRI_json_t> json(state.getValue()->toJsonValue(TRI_UNKNOWN_MEM_ZONE));
bool valid = true;
for (size_t i = 0; i < n; ++i) {
auto& state = permutationStates[i];
std::unique_ptr<TRI_json_t> json(state.getValue()->toJsonValue(TRI_UNKNOWN_MEM_ZONE));
if (json == nullptr) {
valid = false;
break;
if (json == nullptr) {
valid = false;
break;
}
auto shaped = TRI_ShapedJsonJson(shaper, json.get(), false);
if (shaped == nullptr) {
// no such shape exists. this means we won't find this value and can go on with the next permutation
valid = false;
break;
}
searchValue->_values[state.attributePosition] = *shaped;
TRI_Free(shaper->memoryZone(), shaped);
}
auto shaped = TRI_ShapedJsonJson(shaper, json.get(), false);
if (shaped == nullptr) {
// no such shape exists. this means we won't find this value and can go on with the next permutation
valid = false;
break;
if (valid) {
searchValues.push_back(searchValue.get());
searchValue.release();
}
// now permute
while (true) {
if (++permutationStates[current].current < permutationStates[current].n) {
current = 0;
// abort inner iteration
break;
}
permutationStates[current].current = 0;
if (++current >= n) {
done = true;
break;
}
// next inner iteration
}
}
TRI_ASSERT(searchValues.size() <= maxPermutations);
searchValue->_values[state.attributePosition] = *shaped;
TRI_Free(shaper->memoryZone(), shaped);
// Create the iterator
TRI_IF_FAILURE("HashIndex::noIterator") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
if (valid) {
searchValues.push_back(searchValue.get());
searchValue.release();
}
// now permute
while (true) {
if (++permutationStates[current].current < permutationStates[current].n) {
current = 0;
// abort inner iteration
break;
}
permutationStates[current].current = 0;
if (++current >= n) {
done = true;
break;
}
// next inner iteration
}
catch (...) {
// prevent a leak here
for (auto& it : searchValues) {
delete it;
}
throw;
}
TRI_ASSERT(searchValues.size() <= maxPermutations);
// Create the iterator
TRI_IF_FAILURE("HashIndex::noIterator") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
return new HashIndexIterator(this, searchValues);
}

View File

@ -154,7 +154,7 @@ static TRI_index_operator_t* buildRangeOperator (TRI_json_t const* lowerBound,
lowerOperator.release();
upperOperator.release();
return rangeOperator.release();
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief frees an element in the skiplist
@ -1331,12 +1331,17 @@ IndexIterator* SkiplistIndex::iteratorForCondition (IndexIteratorContext* contex
nullArray.add(Json(Json::Null));
std::unique_ptr<TRI_index_operator_t> unboundOperator(TRI_CreateIndexOperator(TRI_GE_INDEX_OPERATOR, nullptr,
nullptr, nullArray.steal(), _shaper, 1));
std::vector<TRI_index_operator_t*> searchValues({unboundOperator.get()});
std::vector<TRI_index_operator_t*> searchValues({ unboundOperator.get() });
unboundOperator.release();
TRI_IF_FAILURE("SkiplistIndex::noSortIterator") {
TRI_IF_FAILURE("SkiplistIndex::noSortIterator") {
// prevent a (false-positive) memleak here
for (auto& it : searchValues) {
delete it;
}
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
return new SkiplistIndexIterator(this, searchValues, reverse);
}
@ -1477,102 +1482,117 @@ IndexIterator* SkiplistIndex::iteratorForCondition (IndexIteratorContext* contex
std::vector<TRI_index_operator_t*> searchValues;
searchValues.reserve(maxPermutations);
if (usedFields == 0) {
// We have a range query based on the first _field
auto op = buildRangeOperator(lower.get(), includeLower, upper.get(), includeUpper, nullptr, _shaper);
if (op != nullptr) {
searchValues.emplace_back(op);
TRI_IF_FAILURE("SkiplistIndex::onlyRangeOperator") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
try {
if (usedFields == 0) {
// We have a range query based on the first _field
std::unique_ptr<TRI_index_operator_t> op(buildRangeOperator(lower.get(), includeLower, upper.get(), includeUpper, nullptr, _shaper));
if (op != nullptr) {
searchValues.emplace_back(op.get());
op.release();
TRI_IF_FAILURE("SkiplistIndex::onlyRangeOperator") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
}
}
}
else {
bool done = false;
// create all permutations
while (! done) {
std::unique_ptr<TRI_json_t> parameter(TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE, usedFields));
else {
bool done = false;
// create all permutations
while (! done) {
std::unique_ptr<TRI_json_t> parameter(TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE, usedFields));
bool valid = true;
for (size_t i = 0; i < usedFields; ++i) {
TRI_ASSERT(i < permutationStates.size());
auto& state = permutationStates[i];
std::unique_ptr<TRI_json_t> json(state.getValue()->toJsonValue(TRI_UNKNOWN_MEM_ZONE));
bool valid = true;
for (size_t i = 0; i < usedFields; ++i) {
TRI_ASSERT(i < permutationStates.size());
auto& state = permutationStates[i];
std::unique_ptr<TRI_json_t> json(state.getValue()->toJsonValue(TRI_UNKNOWN_MEM_ZONE));
if (json == nullptr) {
valid = false;
break;
}
TRI_PushBack3ArrayJson(TRI_UNKNOWN_MEM_ZONE, parameter.get(), json.release());
}
if (valid) {
std::unique_ptr<TRI_index_operator_t> tmpOp(TRI_CreateIndexOperator(TRI_EQ_INDEX_OPERATOR,
nullptr,
nullptr,
parameter.get(),
_shaper,
usedFields));
// Note we create a new RangeOperator always.
std::unique_ptr<TRI_index_operator_t> rangeOperator(buildRangeOperator(lower.get(), includeLower, upper.get(), includeUpper, parameter.get(), _shaper));
parameter.release();
if (rangeOperator != nullptr) {
std::unique_ptr<TRI_index_operator_t> combinedOp(TRI_CreateIndexOperator(TRI_AND_INDEX_OPERATOR,
tmpOp.get(),
rangeOperator.get(),
nullptr,
_shaper,
2));
rangeOperator.release();
tmpOp.release();
searchValues.emplace_back(combinedOp.get());
TRI_IF_FAILURE("SkiplistIndex::rangeOperatorNoTmp") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
if (json == nullptr) {
valid = false;
break;
}
combinedOp.release();
TRI_PushBack3ArrayJson(TRI_UNKNOWN_MEM_ZONE, parameter.get(), json.release());
}
else {
if (tmpOp != nullptr) {
searchValues.emplace_back(tmpOp.get());
TRI_IF_FAILURE("SkiplistIndex::rangeOperatorTmp") {
if (valid) {
std::unique_ptr<TRI_index_operator_t> tmpOp(TRI_CreateIndexOperator(TRI_EQ_INDEX_OPERATOR,
nullptr,
nullptr,
parameter.get(),
_shaper,
usedFields));
// Note we create a new RangeOperator always.
std::unique_ptr<TRI_index_operator_t> rangeOperator(buildRangeOperator(lower.get(), includeLower, upper.get(), includeUpper, parameter.get(), _shaper));
parameter.release();
if (rangeOperator != nullptr) {
std::unique_ptr<TRI_index_operator_t> combinedOp(TRI_CreateIndexOperator(TRI_AND_INDEX_OPERATOR,
tmpOp.get(),
rangeOperator.get(),
nullptr,
_shaper,
2));
rangeOperator.release();
tmpOp.release();
searchValues.emplace_back(combinedOp.get());
combinedOp.release();
TRI_IF_FAILURE("SkiplistIndex::rangeOperatorNoTmp") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
tmpOp.release();
}
else {
if (tmpOp != nullptr) {
searchValues.emplace_back(tmpOp.get());
tmpOp.release();
TRI_IF_FAILURE("SkiplistIndex::rangeOperatorTmp") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
}
}
}
}
size_t const np = permutationStates.size() - 1;
size_t current = 0;
// now permute
while (true) {
if (++permutationStates[np - current].current < permutationStates[np - current].n) {
current = 0;
// abort inner iteration
break;
size_t const np = permutationStates.size() - 1;
size_t current = 0;
// now permute
while (true) {
if (++permutationStates[np - current].current < permutationStates[np - current].n) {
current = 0;
// abort inner iteration
break;
}
permutationStates[np - current].current = 0;
if (++current >= usedFields) {
done = true;
break;
}
// next inner iteration
}
permutationStates[np - current].current = 0;
if (++current >= usedFields) {
done = true;
break;
}
// next inner iteration
}
}
if (searchValues.empty()) {
return nullptr;
}
if (reverse) {
std::reverse(searchValues.begin(), searchValues.end());
}
TRI_IF_FAILURE("SkiplistIndex::noIterator") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
}
if (searchValues.empty()) {
return nullptr;
}
if (reverse) {
std::reverse(searchValues.begin(), searchValues.end());
catch (...) {
// prevent memleak here
for (auto& it : searchValues) {
delete it;
}
throw;
}
TRI_IF_FAILURE("SkiplistIndex::noIterator") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
}
return new SkiplistIndexIterator(this, searchValues, reverse);
}