1
0
Fork 0

fixed memleaks

This commit is contained in:
Jan Steemann 2015-10-07 16:12:20 +02:00
parent a1de2bfcc1
commit 85eacaa458
4 changed files with 158 additions and 74 deletions

View File

@ -481,16 +481,23 @@ void IndexBlock::freeCondition () {
}
void IndexBlock::startNextIterator () {
delete _iterator;
_iterator = nullptr;
++_currentIndex;
if (_currentIndex < _indexes.size()) {
auto outVariable = static_cast<IndexNode const*>(getPlanNode())->outVariable();
auto ast = static_cast<IndexNode const*>(getPlanNode())->_plan->getAst();
_iterator = _indexes[_currentIndex]->getIterator(_context, ast, _condition->getMember(_currentIndex), outVariable);
}
/*
else {
// If all indexes have been exhausted we set _iterator to nullptr;
delete _iterator;
_iterator = nullptr;
}
*/
}
// this is called every time everything in _documents has been passed on

View File

@ -2057,19 +2057,15 @@ int triagens::aql::useIndexesRule (Optimizer* opt,
std::cout << "Candidates to replace " << changes.size() << std::endl;
if (! changes.empty()) {
// clone the original plan
std::unique_ptr<ExecutionPlan> newPlan(plan->clone());
for (auto& it : changes) {
ExecutionNode* newNode = it.second->clone(newPlan.get(), true, false);
newPlan->registerNode(newNode);
newPlan->replaceNode(newPlan->getNodeById(it.first), newNode);
plan->registerNode(it.second);
plan->replaceNode(plan->getNodeById(it.first), it.second);
// prevent double deletion by cleanupChanges()
it.second = nullptr;
}
changes.clear();
opt->addPlan(newPlan.release(), rule, true);
opt->addPlan(plan, rule, true);
plan->findVarUsage();
}
else {
opt->addPlan(plan, rule, false);

View File

@ -122,23 +122,37 @@ static bool IsEqualKeyElementHash (TRI_hash_index_search_value_t const* left,
// -----------------------------------------------------------------------------
TRI_doc_mptr_t* HashIndexIterator::next () {
if (_buffer.empty()) {
_index->lookup(_searchValue, _buffer);
if (_buffer.empty()) {
while (true) {
if (_position >= _keys.size()) {
// we're at the end of the lookup values
return nullptr;
}
}
if (_posInBuffer < _buffer.size()) {
return _buffer[_posInBuffer++];
}
if (_posInBuffer >= _buffer.size()) {
// We have to refill the buffer
_buffer.clear();
return nullptr;
_posInBuffer = 0;
int res = _index->lookup(_keys[_position++], _buffer);
if (res != TRI_ERROR_NO_ERROR) {
THROW_ARANGO_EXCEPTION(res);
}
}
if (! _buffer.empty()) {
// found something
return _buffer.at(_posInBuffer++);
}
// found no result. now go to next lookup value in _keys
// ++_position;
}
}
void HashIndexIterator::reset () {
_buffer.clear();
_position = 0;
_posInBuffer = 0;
}
@ -784,68 +798,130 @@ IndexIterator* HashIndex::iteratorForCondition (IndexIteratorContext* context,
triagens::aql::AstNode const* node,
triagens::aql::Variable const* reference) const {
TRI_ASSERT(node->type == aql::NODE_TYPE_OPERATOR_NARY_AND);
SimpleAttributeEqualityMatcher matcher(fields());
size_t const n = fields().size();
triagens::aql::AstNode* allVals = matcher.getAll(ast, this, node, reference);
TRI_ASSERT(allVals->numMembers() == n);
// setup storage
std::unique_ptr<TRI_hash_index_search_value_t> searchValue(new TRI_hash_index_search_value_t);
searchValue->reserve(n);
if (searchValue->_values == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
auto flds = fields();
auto shaper = _collection->getShaper();
// Convert AstNode -> TRI_hash_index_search_value_t
for (size_t i = 0; i < n; ++i) {
auto comp = allVals->getMember(i);
TRI_ASSERT(comp->numMembers() == 2);
std::pair<triagens::aql::Variable const*, std::vector<triagens::basics::AttributeName>> paramPair;
auto access = comp->getMember(0);
auto value = comp->getMember(1);
if (! (access->isAttributeAccessForVariable(paramPair) && paramPair.first == reference)) {
access = comp->getMember(1);
value = comp->getMember(0);
if (! (access->isAttributeAccessForVariable(paramPair) && paramPair.first == reference)) {
// Both side do not have a correct AttributeAccess, this should not happen and indicates
// an error in the optimizer
TRI_ASSERT(false);
return nullptr;
}
struct PermutationState {
PermutationState (triagens::aql::AstNode const* op, triagens::aql::AstNode const* value, size_t current, size_t n)
: op(op),
value(value),
current(current),
n(n) {
}
bool filled = false;
// value is the value node-side and paramPair.second contains this attributes access.
// Now iterator through the paths and fill searchValue
for (size_t j = 0; j < n; ++j) {
auto f = flds[j];
if (f == paramPair.second) {
filled = true;
auto shaped = TRI_ShapedJsonJson(shaper, value->toJsonValue(TRI_UNKNOWN_MEM_ZONE), false);
if (shaped == nullptr) {
TRI_ASSERT(false);
return nullptr;
}
searchValue->_values[j] = *shaped;
TRI_Free(shaper->memoryZone(), shaped);
break;
triagens::aql::AstNode const* getValue () const {
if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_EQ) {
TRI_ASSERT(current == 0);
return value;
}
}
if (! filled) {
// We have an attribute access this index does not cover, should not happen
else if (op->type == triagens::aql::NODE_TYPE_OPERATOR_BINARY_IN) {
TRI_ASSERT(current < n);
return value->getMember(current);
}
TRI_ASSERT(false);
return nullptr;
}
triagens::aql::AstNode const* op;
triagens::aql::AstNode const* value;
size_t current;
size_t const n;
};
// initialize permutations
std::vector<PermutationState> permutationStates;
permutationStates.reserve(n);
size_t maxPermutations = 1;
for (size_t i = 0; i < n; ++i) {
auto comp = allVals->getMemberUnchecked(i);
auto attrNode = comp->getMember(0);
auto valNode = comp->getMember(1);
if (attrNode->type != aql::NODE_TYPE_ATTRIBUTE_ACCESS) {
// value == a.b -> flip the two sides
attrNode = comp->getMember(1);
valNode = comp->getMember(0);
}
TRI_ASSERT(attrNode->type == aql::NODE_TYPE_ATTRIBUTE_ACCESS);
if (comp->type == aql::NODE_TYPE_OPERATOR_BINARY_EQ) {
permutationStates.emplace_back(PermutationState(comp, valNode, 0, 1));
}
else if (comp->type == aql::NODE_TYPE_OPERATOR_BINARY_IN) {
permutationStates.emplace_back(PermutationState(comp, valNode, 0, valNode->numMembers()));
}
else {
return nullptr;
}
maxPermutations *= permutationStates.back().n;
}
// We have successfully build a searchValue by now.
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) {
std::unique_ptr<TRI_hash_index_search_value_t> searchValue(new 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));
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[i] = *shaped;
TRI_Free(shaper->memoryZone(), shaped);
}
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);
// Create the iterator
auto result = new HashIndexIterator(this, searchValue.get());
searchValue.release();
return result;
return new HashIndexIterator(this, searchValues);
}
// -----------------------------------------------------------------------------

View File

@ -74,14 +74,18 @@ namespace triagens {
public:
HashIndexIterator (HashIndex const* index,
TRI_hash_index_search_value_t* searchValue)
std::vector<TRI_hash_index_search_value_t*>& keys)
: _index(index),
_searchValue(searchValue),
_keys(keys),
_position(0),
_buffer(),
_posInBuffer(0) {
}
~HashIndexIterator() {
delete _searchValue;
for (auto& it : _keys) {
delete it;
}
}
TRI_doc_mptr_t* next () override;
@ -90,10 +94,11 @@ namespace triagens {
private:
HashIndex const* _index;
TRI_hash_index_search_value_t* _searchValue;
std::vector<TRI_doc_mptr_t*> _buffer;
size_t _posInBuffer;
HashIndex const* _index;
std::vector<TRI_hash_index_search_value_t*> _keys;
size_t _position;
std::vector<TRI_doc_mptr_t*> _buffer;
size_t _posInBuffer;
};