1
0
Fork 0

use bulk allocator for index elements

This commit is contained in:
jsteemann 2016-12-09 21:40:49 +01:00
parent fe8301cd31
commit f0a4d69b69
32 changed files with 288 additions and 146 deletions

View File

@ -84,7 +84,7 @@ V8Expression* Executor::generateExpression(AstNode const* node) {
v8::Handle<v8::Script> compiled = v8::Script::Compile( v8::Handle<v8::Script> compiled = v8::Script::Compile(
TRI_V8_STD_STRING((*_buffer)), TRI_V8_ASCII_STRING("--script--")); TRI_V8_STD_STRING((*_buffer)), TRI_V8_ASCII_STRING("--script--"));
if (! compiled.IsEmpty()) { if (!compiled.IsEmpty()) {
v8::Handle<v8::Value> func(compiled->Run()); v8::Handle<v8::Value> func(compiled->Run());
// exit early if an error occurred // exit early if an error occurred
@ -108,7 +108,7 @@ V8Expression* Executor::generateExpression(AstNode const* node) {
HandleV8Error(tryCatch, empty, _buffer, true); HandleV8Error(tryCatch, empty, _buffer, true);
// well we're almost sure we never reach this since the above call should throw: // well we're almost sure we never reach this since the above call should throw:
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to compile AQL script code");
} }
} }
@ -133,7 +133,7 @@ int Executor::executeExpression(Query* query, AstNode const* node,
v8::Handle<v8::Script> compiled = v8::Script::Compile( v8::Handle<v8::Script> compiled = v8::Script::Compile(
TRI_V8_STD_STRING((*_buffer)), TRI_V8_ASCII_STRING("--script--")); TRI_V8_STD_STRING((*_buffer)), TRI_V8_ASCII_STRING("--script--"));
if (! compiled.IsEmpty()) { if (!compiled.IsEmpty()) {
v8::Handle<v8::Value> func(compiled->Run()); v8::Handle<v8::Value> func(compiled->Run());
@ -175,7 +175,7 @@ int Executor::executeExpression(Query* query, AstNode const* node,
HandleV8Error(tryCatch, empty, _buffer, true); HandleV8Error(tryCatch, empty, _buffer, true);
// well we're almost sure we never reach this since the above call should throw: // well we're almost sure we never reach this since the above call should throw:
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to compile AQL script code");
} }
} }

View File

@ -4010,7 +4010,7 @@ AqlValue Functions::Fulltext(arangodb::aql::Query* query,
TRI_QueryFulltextIndex(fulltextIndex->internals(), ft); TRI_QueryFulltextIndex(fulltextIndex->internals(), ft);
if (queryResult == nullptr) { if (queryResult == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
} }
TRI_ASSERT(trx->hasDitch(cid)); TRI_ASSERT(trx->hasDitch(cid));

View File

@ -499,7 +499,7 @@ void RestAqlHandler::getInfoQuery(std::string const& operation,
auto block = static_cast<BlockWithClients*>(query->engine()->root()); auto block = static_cast<BlockWithClients*>(query->engine()->root());
if (block->getPlanNode()->getType() != ExecutionNode::SCATTER && if (block->getPlanNode()->getType() != ExecutionNode::SCATTER &&
block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) { block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unexpected node type");
} }
number = block->remainingForShard(shardId); number = block->remainingForShard(shardId);
} }
@ -516,7 +516,7 @@ void RestAqlHandler::getInfoQuery(std::string const& operation,
auto block = static_cast<BlockWithClients*>(query->engine()->root()); auto block = static_cast<BlockWithClients*>(query->engine()->root());
if (block->getPlanNode()->getType() != ExecutionNode::SCATTER && if (block->getPlanNode()->getType() != ExecutionNode::SCATTER &&
block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) { block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unexpected node type");
} }
hasMore = block->hasMoreForShard(shardId); hasMore = block->hasMoreForShard(shardId);
} }
@ -719,7 +719,7 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
auto block = static_cast<BlockWithClients*>(query->engine()->root()); auto block = static_cast<BlockWithClients*>(query->engine()->root());
if (block->getPlanNode()->getType() != ExecutionNode::SCATTER && if (block->getPlanNode()->getType() != ExecutionNode::SCATTER &&
block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) { block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unexpected node type");
} }
items.reset(block->getSomeForShard(atLeast, atMost, shardId)); items.reset(block->getSomeForShard(atLeast, atMost, shardId));
} }
@ -755,7 +755,7 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
static_cast<BlockWithClients*>(query->engine()->root()); static_cast<BlockWithClients*>(query->engine()->root());
if (block->getPlanNode()->getType() != ExecutionNode::SCATTER && if (block->getPlanNode()->getType() != ExecutionNode::SCATTER &&
block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) { block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unexpected node type");
} }
skipped = block->skipSomeForShard(atLeast, atMost, shardId); skipped = block->skipSomeForShard(atLeast, atMost, shardId);
} }
@ -783,7 +783,7 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
static_cast<BlockWithClients*>(query->engine()->root()); static_cast<BlockWithClients*>(query->engine()->root());
if (block->getPlanNode()->getType() != ExecutionNode::SCATTER && if (block->getPlanNode()->getType() != ExecutionNode::SCATTER &&
block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) { block->getPlanNode()->getType() != ExecutionNode::DISTRIBUTE) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unexpected node type");
} }
exhausted = block->skipForShard(number, shardId); exhausted = block->skipForShard(number, shardId);
} }

View File

@ -203,7 +203,7 @@ void Scopes::replaceVariable(Variable* variable) {
} }
} }
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to find AQL variable in scopes");
} }
/// @brief checks whether a variable exists in any scope /// @brief checks whether a variable exists in any scope

View File

@ -60,7 +60,7 @@ static AstNode* createGlobalCondition(Ast* ast, AstNode const* condition) {
type = NODE_TYPE_OPERATOR_BINARY_NIN; type = NODE_TYPE_OPERATOR_BINARY_NIN;
break; break;
default: default:
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unsupported operator type");
} }
auto quantifier = condition->getMemberUnchecked(2); auto quantifier = condition->getMemberUnchecked(2);
TRI_ASSERT(quantifier->type == NODE_TYPE_QUANTIFIER); TRI_ASSERT(quantifier->type == NODE_TYPE_QUANTIFIER);
@ -69,7 +69,7 @@ static AstNode* createGlobalCondition(Ast* ast, AstNode const* condition) {
if (val == Quantifier::NONE) { if (val == Quantifier::NONE) {
auto it = Ast::NegatedOperators.find(type); auto it = Ast::NegatedOperators.find(type);
if (it == Ast::NegatedOperators.end()) { if (it == Ast::NegatedOperators.end()) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unsupported operator type");
} }
type = it->second; type = it->second;
} }

View File

@ -699,7 +699,7 @@ void ClusterComm::asyncAnswer(std::string& coordinatorHeader,
// FIXME - generalize for VPP // FIXME - generalize for VPP
HttpResponse* responseToSend = dynamic_cast<HttpResponse*>(response); HttpResponse* responseToSend = dynamic_cast<HttpResponse*>(response);
if (responseToSend == nullptr) { if (responseToSend == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid response type");
} }
// First take apart the header to get the coordinatorID: // First take apart the header to get the coordinatorID:

View File

@ -1641,7 +1641,7 @@ static void Return_PrepareClusterCommResultForJS(
// FIXME HANDLE VPP // FIXME HANDLE VPP
auto httpRequest = std::dynamic_pointer_cast<HttpRequest>(res.answer); auto httpRequest = std::dynamic_pointer_cast<HttpRequest>(res.answer);
if (httpRequest == nullptr) { if (httpRequest == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
// The headers: // The headers:

View File

@ -85,7 +85,7 @@ FulltextIndex::FulltextIndex(TRI_idx_iid_t iid,
_sparse = true; _sparse = true;
if (_fields.size() != 1) { if (_fields.size() != 1) {
// We need exactly 1 attribute // We need exactly 1 attribute
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "fulltext index definition should have exactly one attribute");
} }
auto& attribute = _fields[0]; auto& attribute = _fields[0];
_attr.reserve(attribute.size()); _attr.reserve(attribute.size());

View File

@ -26,6 +26,7 @@
#include "Aql/AstNode.h" #include "Aql/AstNode.h"
#include "Aql/SortCondition.h" #include "Aql/SortCondition.h"
#include "Basics/Exceptions.h" #include "Basics/Exceptions.h"
#include "Basics/FixedSizeAllocator.h"
#include "Basics/VelocyPackHelper.h" #include "Basics/VelocyPackHelper.h"
#include "Indexes/IndexLookupContext.h" #include "Indexes/IndexLookupContext.h"
#include "Indexes/SimpleAttributeEqualityMatcher.h" #include "Indexes/SimpleAttributeEqualityMatcher.h"
@ -432,13 +433,6 @@ HashIndex::UniqueArray::UniqueArray(
/// @brief destroy the unique array /// @brief destroy the unique array
HashIndex::UniqueArray::~UniqueArray() { HashIndex::UniqueArray::~UniqueArray() {
if (_hashArray != nullptr) {
auto cb = [this](HashIndexElement* element) -> bool {
element->free(); return true;
};
_hashArray->invokeOnAllElements(cb);
}
delete _hashArray; delete _hashArray;
delete _hashElement; delete _hashElement;
delete _isEqualElElByKey; delete _isEqualElElByKey;
@ -460,13 +454,6 @@ HashIndex::MultiArray::MultiArray(size_t numPaths,
/// @brief destroy the multi array /// @brief destroy the multi array
HashIndex::MultiArray::~MultiArray() { HashIndex::MultiArray::~MultiArray() {
if (_hashArray != nullptr) {
auto cb = [this](HashIndexElement* element) -> bool {
element->free(); return true;
};
_hashArray->invokeOnAllElements(cb);
}
delete _hashArray; delete _hashArray;
delete _hashElement; delete _hashElement;
delete _isEqualElElByKey; delete _isEqualElElByKey;
@ -474,7 +461,7 @@ HashIndex::MultiArray::~MultiArray() {
HashIndex::HashIndex(TRI_idx_iid_t iid, LogicalCollection* collection, HashIndex::HashIndex(TRI_idx_iid_t iid, LogicalCollection* collection,
VPackSlice const& info) VPackSlice const& info)
: PathBasedIndex(iid, collection, info, false), _uniqueArray(nullptr) { : PathBasedIndex(iid, collection, info, sizeof(TRI_voc_rid_t) + sizeof(uint32_t), false), _uniqueArray(nullptr) {
uint32_t indexBuckets = 1; uint32_t indexBuckets = 1;
if (collection != nullptr) { if (collection != nullptr) {
@ -650,7 +637,7 @@ int HashIndex::remove(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
for (auto& hashElement : elements) { for (auto& hashElement : elements) {
hashElement->free(); _allocator->deallocate(hashElement);
} }
return res; return res;
} }
@ -668,7 +655,7 @@ int HashIndex::remove(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
if (result != TRI_ERROR_NO_ERROR) { if (result != TRI_ERROR_NO_ERROR) {
res = result; res = result;
} }
hashElement->free(); _allocator->deallocate(hashElement);
} }
return res; return res;
@ -686,10 +673,11 @@ int HashIndex::batchInsert(arangodb::Transaction* trx,
int HashIndex::unload() { int HashIndex::unload() {
if (_unique) { if (_unique) {
_uniqueArray->_hashArray->truncate([](HashIndexElement* element) -> bool { element->free(); return true; }); _uniqueArray->_hashArray->truncate([](HashIndexElement*) -> bool { return true; });
} else { } else {
_multiArray->_hashArray->truncate([](HashIndexElement* element) -> bool { element->free(); return true; }); _multiArray->_hashArray->truncate([](HashIndexElement*) -> bool { return true; });
} }
_allocator->deallocateAll();
return TRI_ERROR_NO_ERROR; return TRI_ERROR_NO_ERROR;
} }
@ -751,7 +739,7 @@ int HashIndex::insertUnique(arangodb::Transaction* trx, TRI_voc_rid_t revisionId
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
for (auto& it : elements) { for (auto& it : elements) {
// free all elements to prevent leak // free all elements to prevent leak
it->free(); _allocator->deallocate(it);
} }
return res; return res;
@ -775,7 +763,7 @@ int HashIndex::insertUnique(arangodb::Transaction* trx, TRI_voc_rid_t revisionId
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
for (size_t j = i; j < n; ++j) { for (size_t j = i; j < n; ++j) {
// Free all elements that are not yet in the index // Free all elements that are not yet in the index
elements[j]->free(); _allocator->deallocate(elements[j]);
} }
// Already indexed elements will be removed by the rollback // Already indexed elements will be removed by the rollback
break; break;
@ -796,7 +784,7 @@ int HashIndex::batchInsertUnique(arangodb::Transaction* trx,
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
for (auto& it : elements) { for (auto& it : elements) {
// free all elements to prevent leak // free all elements to prevent leak
it->free(); _allocator->deallocate(it);
} }
return res; return res;
} }
@ -823,7 +811,7 @@ int HashIndex::batchInsertUnique(arangodb::Transaction* trx,
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
for (auto& it : elements) { for (auto& it : elements) {
// free all elements to prevent leak // free all elements to prevent leak
it->free(); _allocator->deallocate(it);
} }
} }
@ -837,7 +825,7 @@ int HashIndex::insertMulti(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
for (auto& hashElement : elements) { for (auto& hashElement : elements) {
hashElement->free(); _allocator->deallocate(hashElement);
} }
return res; return res;
} }
@ -855,7 +843,7 @@ int HashIndex::insertMulti(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
if (found != nullptr) { if (found != nullptr) {
// already got the exact same index entry. now free our local element... // already got the exact same index entry. now free our local element...
element->free(); _allocator->deallocate(element);
} }
}; };
@ -875,7 +863,7 @@ int HashIndex::insertMulti(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
for (size_t j = i; j < n; ++j) { for (size_t j = i; j < n; ++j) {
// Free all elements that are not yet in the index // Free all elements that are not yet in the index
elements[j]->free(); _allocator->deallocate(elements[j]);
} }
for (size_t j = 0; j < i; ++j) { for (size_t j = 0; j < i; ++j) {
// Remove all already indexed elements and free them // Remove all already indexed elements and free them
@ -903,7 +891,7 @@ int HashIndex::batchInsertMulti(arangodb::Transaction* trx,
// Filling the elements failed for some reason. Assume loading as failed // Filling the elements failed for some reason. Assume loading as failed
for (auto& el : elements) { for (auto& el : elements) {
// Free all elements that are not yet in the index // Free all elements that are not yet in the index
el->free(); _allocator->deallocate(el);
} }
return res; return res;
} }
@ -943,7 +931,7 @@ int HashIndex::removeUniqueElement(arangodb::Transaction* trx,
} }
return TRI_ERROR_INTERNAL; return TRI_ERROR_INTERNAL;
} }
old->free(); _allocator->deallocate(old);
return TRI_ERROR_NO_ERROR; return TRI_ERROR_NO_ERROR;
} }
@ -963,7 +951,7 @@ int HashIndex::removeMultiElement(arangodb::Transaction* trx,
} }
return TRI_ERROR_INTERNAL; return TRI_ERROR_INTERNAL;
} }
old->free(); _allocator->deallocate(old);
return TRI_ERROR_NO_ERROR; return TRI_ERROR_NO_ERROR;
} }

View File

@ -35,24 +35,11 @@ HashIndexElement::HashIndexElement(TRI_voc_rid_t revisionId, std::vector<std::pa
} }
} }
HashIndexElement* HashIndexElement::create(TRI_voc_rid_t revisionId, std::vector<std::pair<arangodb::velocypack::Slice, uint32_t>> const& values) { HashIndexElement* HashIndexElement::initialize(HashIndexElement* element,
TRI_voc_rid_t revisionId,
std::vector<std::pair<arangodb::velocypack::Slice, uint32_t>> const& values) {
TRI_ASSERT(!values.empty()); TRI_ASSERT(!values.empty());
void* space = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, baseMemoryUsage(values.size()), false); return new (element) HashIndexElement(revisionId, values);
if (space == nullptr) {
return nullptr;
}
try {
return new (space) HashIndexElement(revisionId, values);
} catch (...) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, space);
return nullptr;
}
}
void HashIndexElement::free() {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, this);
} }
/// @brief velocypack sub-object (for indexes, as part of IndexElement, /// @brief velocypack sub-object (for indexes, as part of IndexElement,
@ -126,24 +113,11 @@ SkiplistIndexElement::SkiplistIndexElement(TRI_voc_rid_t revisionId, std::vector
} }
} }
SkiplistIndexElement* SkiplistIndexElement::create(TRI_voc_rid_t revisionId, std::vector<std::pair<arangodb::velocypack::Slice, uint32_t>> const& values) { SkiplistIndexElement* SkiplistIndexElement::initialize(SkiplistIndexElement* element,
TRI_voc_rid_t revisionId,
std::vector<std::pair<arangodb::velocypack::Slice, uint32_t>> const& values) {
TRI_ASSERT(!values.empty()); TRI_ASSERT(!values.empty());
void* space = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, baseMemoryUsage(values.size()), false); return new (element) SkiplistIndexElement(revisionId, values);
if (space == nullptr) {
return nullptr;
}
try {
return new (space) SkiplistIndexElement(revisionId, values);
} catch (...) {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, space);
return nullptr;
}
}
void SkiplistIndexElement::free() {
TRI_Free(TRI_UNKNOWN_MEM_ZONE, this);
} }
/// @brief velocypack sub-object (for indexes, as part of IndexElement, /// @brief velocypack sub-object (for indexes, as part of IndexElement,

View File

@ -140,9 +140,9 @@ struct HashIndexElement {
static uint64_t hash(std::vector<std::pair<arangodb::velocypack::Slice, uint32_t>> const& values); static uint64_t hash(std::vector<std::pair<arangodb::velocypack::Slice, uint32_t>> const& values);
/// @brief allocate a new index element from a vector of slices /// @brief allocate a new index element from a vector of slices
static HashIndexElement* create(TRI_voc_rid_t revisionId, std::vector<std::pair<arangodb::velocypack::Slice, uint32_t>> const& values); static HashIndexElement* initialize(HashIndexElement* memory,
TRI_voc_rid_t revisionId,
void free(); std::vector<std::pair<arangodb::velocypack::Slice, uint32_t>> const& values);
private: private:
inline IndexElementValue* subObject(size_t position) { inline IndexElementValue* subObject(size_t position) {
@ -188,9 +188,9 @@ struct SkiplistIndexElement {
arangodb::velocypack::Slice slice(IndexLookupContext* context, size_t position) const; arangodb::velocypack::Slice slice(IndexLookupContext* context, size_t position) const;
/// @brief allocate a new index element from a vector of slices /// @brief allocate a new index element from a vector of slices
static SkiplistIndexElement* create(TRI_voc_rid_t revisionId, std::vector<std::pair<arangodb::velocypack::Slice, uint32_t>> const& values); static SkiplistIndexElement* initialize(SkiplistIndexElement* element,
TRI_voc_rid_t revisionId,
void free(); std::vector<std::pair<arangodb::velocypack::Slice, uint32_t>> const& values);
private: private:
inline IndexElementValue* subObject(size_t position) { inline IndexElementValue* subObject(size_t position) {

View File

@ -23,6 +23,7 @@
#include "PathBasedIndex.h" #include "PathBasedIndex.h"
#include "Aql/AstNode.h" #include "Aql/AstNode.h"
#include "Basics/FixedSizeAllocator.h"
#include "Basics/VelocyPackHelper.h" #include "Basics/VelocyPackHelper.h"
#include "Logger/Logger.h" #include "Logger/Logger.h"
@ -53,7 +54,7 @@ arangodb::aql::AstNode const* PathBasedIndex::PermutationState::getValue()
/// @brief create the index /// @brief create the index
PathBasedIndex::PathBasedIndex(TRI_idx_iid_t iid, PathBasedIndex::PathBasedIndex(TRI_idx_iid_t iid,
arangodb::LogicalCollection* collection, arangodb::LogicalCollection* collection,
VPackSlice const& info, bool allowPartialIndex) VPackSlice const& info, size_t baseSize, bool allowPartialIndex)
: Index(iid, collection, info), : Index(iid, collection, info),
_useExpansion(false), _useExpansion(false),
_allowPartialIndex(allowPartialIndex) { _allowPartialIndex(allowPartialIndex) {
@ -69,10 +70,14 @@ PathBasedIndex::PathBasedIndex(TRI_idx_iid_t iid,
break; break;
} }
} }
_allocator.reset(new FixedSizeAllocator(baseSize + sizeof(IndexElementValue) * numPaths()));
} }
/// @brief destroy the index /// @brief destroy the index
PathBasedIndex::~PathBasedIndex() {} PathBasedIndex::~PathBasedIndex() {
_allocator->deallocateAll();
}
/// @brief whether or not the index is implicitly unique /// @brief whether or not the index is implicitly unique
/// this can be the case if the index is not declared as unique, but contains a /// this can be the case if the index is not declared as unique, but contains a
@ -121,14 +126,16 @@ int PathBasedIndex::fillElement(std::vector<T*>& elements,
if (slices.size() == n) { if (slices.size() == n) {
// if shapes.size() != n, then the value is not inserted into the index // if shapes.size() != n, then the value is not inserted into the index
// because of index sparsity! // because of index sparsity!
T* element = T::create(revisionId, slices); T* element = static_cast<T*>(_allocator->allocate());
TRI_ASSERT(element != nullptr);
element = T::initialize(element, revisionId, slices);
if (element == nullptr) { if (element == nullptr) {
return TRI_ERROR_OUT_OF_MEMORY; return TRI_ERROR_OUT_OF_MEMORY;
} }
TRI_IF_FAILURE("FillElementOOM") { TRI_IF_FAILURE("FillElementOOM") {
// clean up manually // clean up manually
element->free(); _allocator->deallocate(element);
return TRI_ERROR_OUT_OF_MEMORY; return TRI_ERROR_OUT_OF_MEMORY;
} }
@ -139,7 +146,7 @@ int PathBasedIndex::fillElement(std::vector<T*>& elements,
elements.emplace_back(element); elements.emplace_back(element);
} catch (...) { } catch (...) {
element->free(); _allocator->deallocate(element);
return TRI_ERROR_OUT_OF_MEMORY; return TRI_ERROR_OUT_OF_MEMORY;
} }
} }
@ -155,14 +162,16 @@ int PathBasedIndex::fillElement(std::vector<T*>& elements,
for (auto& info : toInsert) { for (auto& info : toInsert) {
TRI_ASSERT(info.size() == n); TRI_ASSERT(info.size() == n);
T* element = T::create(revisionId, info); T* element = static_cast<T*>(_allocator->allocate());
TRI_ASSERT(element != nullptr);
element = T::initialize(element, revisionId, info);
if (element == nullptr) { if (element == nullptr) {
return TRI_ERROR_OUT_OF_MEMORY; return TRI_ERROR_OUT_OF_MEMORY;
} }
TRI_IF_FAILURE("FillElementOOM") { TRI_IF_FAILURE("FillElementOOM") {
// clean up manually // clean up manually
element->free(); _allocator->deallocate(element);
return TRI_ERROR_OUT_OF_MEMORY; return TRI_ERROR_OUT_OF_MEMORY;
} }
@ -173,7 +182,7 @@ int PathBasedIndex::fillElement(std::vector<T*>& elements,
elements.emplace_back(element); elements.emplace_back(element);
} catch (...) { } catch (...) {
element->free(); _allocator->deallocate(element);
return TRI_ERROR_OUT_OF_MEMORY; return TRI_ERROR_OUT_OF_MEMORY;
} }
} }

View File

@ -34,6 +34,8 @@ namespace aql {
enum AstNodeType : uint32_t; enum AstNodeType : uint32_t;
} }
class FixedSizeAllocator;
class PathBasedIndex : public Index { class PathBasedIndex : public Index {
protected: protected:
struct PermutationState { struct PermutationState {
@ -61,7 +63,7 @@ class PathBasedIndex : public Index {
PathBasedIndex() = delete; PathBasedIndex() = delete;
PathBasedIndex(TRI_idx_iid_t, arangodb::LogicalCollection*, PathBasedIndex(TRI_idx_iid_t, arangodb::LogicalCollection*,
arangodb::velocypack::Slice const&, bool allowPartialIndex); arangodb::velocypack::Slice const&, size_t baseSize, bool allowPartialIndex);
~PathBasedIndex(); ~PathBasedIndex();
@ -105,6 +107,8 @@ class PathBasedIndex : public Index {
std::vector<std::pair<VPackSlice, uint32_t>>& sliceStack); std::vector<std::pair<VPackSlice, uint32_t>>& sliceStack);
protected: protected:
std::unique_ptr<FixedSizeAllocator> _allocator;
/// @brief the attribute paths /// @brief the attribute paths
std::vector<std::vector<std::string>> _paths; std::vector<std::vector<std::string>> _paths;

View File

@ -25,6 +25,7 @@
#include "Aql/AstNode.h" #include "Aql/AstNode.h"
#include "Aql/SortCondition.h" #include "Aql/SortCondition.h"
#include "Basics/AttributeNameParser.h" #include "Basics/AttributeNameParser.h"
#include "Basics/FixedSizeAllocator.h"
#include "Basics/StaticStrings.h" #include "Basics/StaticStrings.h"
#include "Basics/VelocyPackHelper.h" #include "Basics/VelocyPackHelper.h"
#include "Indexes/IndexLookupContext.h" #include "Indexes/IndexLookupContext.h"
@ -206,7 +207,7 @@ IndexLookupResult RocksDBIterator::next() {
RocksDBIndex::RocksDBIndex(TRI_idx_iid_t iid, RocksDBIndex::RocksDBIndex(TRI_idx_iid_t iid,
arangodb::LogicalCollection* collection, arangodb::LogicalCollection* collection,
arangodb::velocypack::Slice const& info) arangodb::velocypack::Slice const& info)
: PathBasedIndex(iid, collection, info, true), : PathBasedIndex(iid, collection, info, 0, true),
_db(RocksDBFeature::instance()->db()) {} _db(RocksDBFeature::instance()->db()) {}
/// @brief destroy the index /// @brief destroy the index
@ -246,7 +247,7 @@ int RocksDBIndex::insert(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
// make sure we clean up before we leave this method // make sure we clean up before we leave this method
auto cleanup = [this, &elements] { auto cleanup = [this, &elements] {
for (auto& it : elements) { for (auto& it : elements) {
it->free(); _allocator->deallocate(it);
} }
}; };
@ -402,7 +403,7 @@ int RocksDBIndex::remove(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
// make sure we clean up before we leave this method // make sure we clean up before we leave this method
auto cleanup = [this, &elements] { auto cleanup = [this, &elements] {
for (auto& it : elements) { for (auto& it : elements) {
it->free(); _allocator->deallocate(it);
} }
}; };

View File

@ -25,6 +25,7 @@
#include "Aql/AstNode.h" #include "Aql/AstNode.h"
#include "Aql/SortCondition.h" #include "Aql/SortCondition.h"
#include "Basics/AttributeNameParser.h" #include "Basics/AttributeNameParser.h"
#include "Basics/FixedSizeAllocator.h"
#include "Basics/StaticStrings.h" #include "Basics/StaticStrings.h"
#include "Basics/VelocyPackHelper.h" #include "Basics/VelocyPackHelper.h"
#include "Indexes/IndexLookupContext.h" #include "Indexes/IndexLookupContext.h"
@ -715,12 +716,12 @@ void SkiplistIterator2::initNextInterval() {
SkiplistIndex::SkiplistIndex(TRI_idx_iid_t iid, SkiplistIndex::SkiplistIndex(TRI_idx_iid_t iid,
arangodb::LogicalCollection* collection, arangodb::LogicalCollection* collection,
VPackSlice const& info) VPackSlice const& info)
: PathBasedIndex(iid, collection, info, true), : PathBasedIndex(iid, collection, info, sizeof(TRI_voc_rid_t), true),
CmpElmElm(this), CmpElmElm(this),
CmpKeyElm(this), CmpKeyElm(this),
_skiplistIndex(nullptr) { _skiplistIndex(nullptr) {
_skiplistIndex = _skiplistIndex =
new TRI_Skiplist(CmpElmElm, CmpKeyElm, [this](SkiplistIndexElement* element) { element->free(); }, _unique, _useExpansion); new TRI_Skiplist(CmpElmElm, CmpKeyElm, [this](SkiplistIndexElement* element) { _allocator->deallocate(element); }, _unique, _useExpansion);
} }
/// @brief destroy the skiplist index /// @brief destroy the skiplist index
@ -761,7 +762,7 @@ int SkiplistIndex::insert(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
for (auto& element : elements) { for (auto& element : elements) {
// free all elements to prevent leak // free all elements to prevent leak
element->free(); _allocator->deallocate(element);
} }
return res; return res;
} }
@ -779,7 +780,7 @@ int SkiplistIndex::insert(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
// Note: this element is freed already // Note: this element is freed already
for (size_t j = i; j < count; ++j) { for (size_t j = i; j < count; ++j) {
elements[j]->free(); _allocator->deallocate(elements[j]);
} }
for (size_t j = 0; j < i; ++j) { for (size_t j = 0; j < i; ++j) {
_skiplistIndex->remove(&context, elements[j]); _skiplistIndex->remove(&context, elements[j]);
@ -812,7 +813,7 @@ int SkiplistIndex::remove(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
if (res != TRI_ERROR_NO_ERROR) { if (res != TRI_ERROR_NO_ERROR) {
for (auto& element : elements) { for (auto& element : elements) {
// free all elements to prevent leak // free all elements to prevent leak
element->free(); _allocator->deallocate(element);
} }
return res; return res;
} }
@ -833,7 +834,7 @@ int SkiplistIndex::remove(arangodb::Transaction* trx, TRI_voc_rid_t revisionId,
res = result; res = result;
} }
elements[i]->free(); _allocator->deallocate(elements[i]);
} }
return res; return res;

View File

@ -72,7 +72,7 @@ RestStatus RestBatchHandler::executeHttp() {
if (httpResponse == nullptr) { if (httpResponse == nullptr) {
std::cout << "please fix this for vpack" << std::endl; std::cout << "please fix this for vpack" << std::endl;
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid response type");
} }
HttpRequest const* httpRequest = HttpRequest const* httpRequest =
@ -80,7 +80,7 @@ RestStatus RestBatchHandler::executeHttp() {
if (httpRequest == nullptr) { if (httpRequest == nullptr) {
std::cout << "please fix this for vpack" << std::endl; std::cout << "please fix this for vpack" << std::endl;
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
// extract the request type // extract the request type
@ -290,7 +290,7 @@ bool RestBatchHandler::getBoundaryBody(std::string* result) {
HttpRequest const* req = dynamic_cast<HttpRequest const*>(_request.get()); HttpRequest const* req = dynamic_cast<HttpRequest const*>(_request.get());
if (req == nullptr) { if (req == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
std::string const& bodyStr = req->body(); std::string const& bodyStr = req->body();

View File

@ -276,7 +276,7 @@ int RestImportHandler::handleSingleDocument(SingleCollectionTransaction& trx,
bool RestImportHandler::createFromJson(std::string const& type) { bool RestImportHandler::createFromJson(std::string const& type) {
if (_request == nullptr) { if (_request == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request");
} }
RestImportResult result; RestImportResult result;
@ -319,7 +319,7 @@ bool RestImportHandler::createFromJson(std::string const& type) {
linewise = true; linewise = true;
if (_response == nullptr) { if (_response == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid response");
} }
// auto detect import type by peeking at first non-whitespace character // auto detect import type by peeking at first non-whitespace character
@ -328,7 +328,7 @@ bool RestImportHandler::createFromJson(std::string const& type) {
HttpRequest* req = dynamic_cast<HttpRequest*>(_request.get()); HttpRequest* req = dynamic_cast<HttpRequest*>(_request.get());
if (req == nullptr) { if (req == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
std::string const& body = req->body(); std::string const& body = req->body();
@ -388,7 +388,7 @@ bool RestImportHandler::createFromJson(std::string const& type) {
HttpRequest* req = dynamic_cast<HttpRequest*>(_request.get()); HttpRequest* req = dynamic_cast<HttpRequest*>(_request.get());
if (req == nullptr) { if (req == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
// each line is a separate JSON document // each line is a separate JSON document
@ -529,7 +529,7 @@ bool RestImportHandler::createFromJson(std::string const& type) {
bool RestImportHandler::createFromVPack(std::string const& type) { bool RestImportHandler::createFromVPack(std::string const& type) {
if (_request == nullptr) { if (_request == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request");
} }
RestImportResult result; RestImportResult result;
@ -637,7 +637,7 @@ bool RestImportHandler::createFromVPack(std::string const& type) {
bool RestImportHandler::createFromKeyValueList() { bool RestImportHandler::createFromKeyValueList() {
if (_request == nullptr) { if (_request == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request");
} }
RestImportResult result; RestImportResult result;
@ -679,7 +679,7 @@ bool RestImportHandler::createFromKeyValueList() {
HttpRequest* httpRequest = dynamic_cast<HttpRequest*>(_request.get()); HttpRequest* httpRequest = dynamic_cast<HttpRequest*>(_request.get());
if (httpRequest == nullptr) { if (httpRequest == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
std::string const& bodyStr = httpRequest->body(); std::string const& bodyStr = httpRequest->body();

View File

@ -40,7 +40,7 @@ RestStatus RestPleaseUpgradeHandler::execute() {
auto response = dynamic_cast<HttpResponse*>(_response.get()); auto response = dynamic_cast<HttpResponse*>(_response.get());
if (response == nullptr) { if (response == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid response type");
} }
resetResponse(rest::ResponseCode::OK); resetResponse(rest::ResponseCode::OK);

View File

@ -744,7 +744,7 @@ void RestReplicationHandler::handleTrampolineCoordinator() {
useVpp = true; useVpp = true;
} }
if (_request == nullptr) { if (_request == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request");
} }
// First check the DBserver component of the body json: // First check the DBserver component of the body json:
@ -783,7 +783,7 @@ void RestReplicationHandler::handleTrampolineCoordinator() {
if (!useVpp) { if (!useVpp) {
HttpRequest* httpRequest = dynamic_cast<HttpRequest*>(_request.get()); HttpRequest* httpRequest = dynamic_cast<HttpRequest*>(_request.get());
if (httpRequest == nullptr) { if (httpRequest == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
// Send a synchronous request to that shard using ClusterComm: // Send a synchronous request to that shard using ClusterComm:
@ -833,7 +833,7 @@ void RestReplicationHandler::handleTrampolineCoordinator() {
if (!useVpp) { if (!useVpp) {
HttpResponse* httpResponse = dynamic_cast<HttpResponse*>(_response.get()); HttpResponse* httpResponse = dynamic_cast<HttpResponse*>(_response.get());
if (_response == nullptr) { if (_response == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid response type");
} }
httpResponse->body().swap(&(res->result->getBody())); httpResponse->body().swap(&(res->result->getBody()));
} else { } else {
@ -1014,7 +1014,7 @@ void RestReplicationHandler::handleCommandLoggerFollow() {
dynamic_cast<HttpResponse*>(_response.get()); dynamic_cast<HttpResponse*>(_response.get());
if (httpResponse == nullptr) { if (httpResponse == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid response type");
} }
if (length > 0) { if (length > 0) {
@ -1086,7 +1086,7 @@ void RestReplicationHandler::handleCommandDetermineOpenTransactions() {
HttpResponse* httpResponse = dynamic_cast<HttpResponse*>(_response.get()); HttpResponse* httpResponse = dynamic_cast<HttpResponse*>(_response.get());
if (_response == nullptr) { if (_response == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid response type");
} }
_response->setContentType(rest::ContentType::DUMP); _response->setContentType(rest::ContentType::DUMP);
@ -2132,7 +2132,7 @@ int RestReplicationHandler::processRestoreDataBatch(
HttpRequest* httpRequest = dynamic_cast<HttpRequest*>(_request.get()); HttpRequest* httpRequest = dynamic_cast<HttpRequest*>(_request.get());
if (httpRequest == nullptr) { if (httpRequest == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
std::string const& bodyStr = httpRequest->body(); std::string const& bodyStr = httpRequest->body();
@ -2466,12 +2466,12 @@ void RestReplicationHandler::handleCommandRestoreDataCoordinator() {
VPackBuilder builder; VPackBuilder builder;
if (_request == nullptr) { if (_request == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
HttpRequest* httpRequest = dynamic_cast<HttpRequest*>(_request.get()); HttpRequest* httpRequest = dynamic_cast<HttpRequest*>(_request.get());
if (httpRequest == nullptr) { if (httpRequest == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
std::string const& bodyStr = httpRequest->body(); std::string const& bodyStr = httpRequest->body();
@ -3099,7 +3099,7 @@ void RestReplicationHandler::handleCommandDump() {
auto response = dynamic_cast<HttpResponse*>(_response.get()); auto response = dynamic_cast<HttpResponse*>(_response.get());
if (response == nullptr) { if (response == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid response type");
} }
response->setContentType(rest::ContentType::DUMP); response->setContentType(rest::ContentType::DUMP);

View File

@ -287,7 +287,7 @@ void RestSimpleHandler::lookupByKeys(VPackSlice const& slice) {
auto response = _response.get(); auto response = _response.get();
if (response == nullptr) { if (response == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid response");
} }
try { try {

View File

@ -46,7 +46,7 @@ RestStatus RestUploadHandler::execute() {
HttpRequest* request = dynamic_cast<HttpRequest*>(_request.get()); HttpRequest* request = dynamic_cast<HttpRequest*>(_request.get());
if (request == nullptr) { if (request == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
// extract the request type // extract the request type
@ -152,7 +152,7 @@ bool RestUploadHandler::parseMultiPart(char const*& body, size_t& length) {
HttpRequest* request = dynamic_cast<HttpRequest*>(_request.get()); HttpRequest* request = dynamic_cast<HttpRequest*>(_request.get());
if (request == nullptr) { if (request == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
std::string const& bodyStr = request->body(); std::string const& bodyStr = request->body();

View File

@ -159,7 +159,7 @@ void VelocyPackCursor::dump(VPackBuilder& builder) {
} catch (std::exception const& ex) { } catch (std::exception const& ex) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, ex.what()); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, ex.what());
} catch (...) { } catch (...) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "internal error during VPackCursor::dump");
} }
} }
@ -298,7 +298,7 @@ void ExportCursor::dump(VPackBuilder& builder) {
} catch (std::exception const& ex) { } catch (std::exception const& ex) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, ex.what()); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, ex.what());
} catch (...) { } catch (...) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "internal error during ExportCursor::dump");
} }
builder.options = oldOptions; builder.options = oldOptions;
} }

View File

@ -649,7 +649,7 @@ DocumentDitch* Transaction::orderDitch(TRI_voc_cid_t cid) {
TRI_transaction_collection_t* trxCollection = TRI_GetCollectionTransaction(_trx, cid, TRI_TRANSACTION_READ); TRI_transaction_collection_t* trxCollection = TRI_GetCollectionTransaction(_trx, cid, TRI_TRANSACTION_READ);
if (trxCollection == nullptr) { if (trxCollection == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to determine transaction collection");
} }
TRI_ASSERT(trxCollection->_collection != nullptr); TRI_ASSERT(trxCollection->_collection != nullptr);

View File

@ -407,7 +407,7 @@ static v8::Handle<v8::Object> RequestCppToV8(v8::Isolate* isolate,
if (rest::ContentType::JSON == request->contentType()) { if (rest::ContentType::JSON == request->contentType()) {
auto httpreq = dynamic_cast<HttpRequest*>(request); auto httpreq = dynamic_cast<HttpRequest*>(request);
if (httpreq == nullptr) { if (httpreq == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} }
std::string const& body = httpreq->body(); std::string const& body = httpreq->body();
req->ForceSet(RequestBodyKey, TRI_V8_STD_STRING(body)); req->ForceSet(RequestBodyKey, TRI_V8_STD_STRING(body));
@ -516,7 +516,7 @@ static v8::Handle<v8::Object> RequestCppToV8(v8::Isolate* isolate,
HttpRequest* httpRequest = dynamic_cast<HttpRequest*>(request); HttpRequest* httpRequest = dynamic_cast<HttpRequest*>(request);
if (httpRequest == nullptr) { if (httpRequest == nullptr) {
// maybe we can just continue // maybe we can just continue
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid request type");
} else { } else {
for (auto& it : httpRequest->cookieValues()) { for (auto& it : httpRequest->cookieValues()) {
cookiesObject->ForceSet(TRI_V8_STD_STRING(it.first), cookiesObject->ForceSet(TRI_V8_STD_STRING(it.first),
@ -832,7 +832,7 @@ static TRI_action_result_t ExecuteActionVocbase(
v8::TryCatch tryCatch; v8::TryCatch tryCatch;
if (response == nullptr) { if (response == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid response");
} }
TRI_GET_GLOBALS(); TRI_GET_GLOBALS();

View File

@ -111,7 +111,7 @@ static void EdgesQuery(TRI_edge_direction_e direction,
return "FILTER doc._from " + op + " @value || doc._to " + op + " @value"; return "FILTER doc._from " + op + " @value || doc._to " + op + " @value";
} }
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid edge index direction");
}; };
arangodb::LogicalCollection const* collection = arangodb::LogicalCollection const* collection =

View File

@ -433,7 +433,7 @@ static void JS_ConfigureApplierReplication(
} }
if (vocbase->replicationApplier() == nullptr) { if (vocbase->replicationApplier() == nullptr) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_INTERNAL); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to find replicationApplier");
} }
if (args.Length() == 0) { if (args.Length() == 0) {
@ -702,7 +702,7 @@ static void JS_StartApplierReplication(
} }
if (vocbase->replicationApplier() == nullptr) { if (vocbase->replicationApplier() == nullptr) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_INTERNAL); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to find replicationApplier");
} }
if (args.Length() > 2) { if (args.Length() > 2) {
@ -753,7 +753,7 @@ static void JS_ShutdownApplierReplication(
} }
if (vocbase->replicationApplier() == nullptr) { if (vocbase->replicationApplier() == nullptr) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_INTERNAL); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to find replicationApplier");
} }
int res = vocbase->replicationApplier()->shutdown(); int res = vocbase->replicationApplier()->shutdown();
@ -786,7 +786,7 @@ static void JS_StateApplierReplication(
} }
if (vocbase->replicationApplier() == nullptr) { if (vocbase->replicationApplier() == nullptr) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_INTERNAL); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to find replicationApplier");
} }
std::shared_ptr<VPackBuilder> builder = vocbase->replicationApplier()->toVelocyPack(); std::shared_ptr<VPackBuilder> builder = vocbase->replicationApplier()->toVelocyPack();
@ -817,7 +817,7 @@ static void JS_ForgetApplierReplication(
} }
if (vocbase->replicationApplier() == nullptr) { if (vocbase->replicationApplier() == nullptr) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_INTERNAL); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to find replicationApplier");
} }
int res = vocbase->replicationApplier()->forget(); int res = vocbase->replicationApplier()->forget();

View File

@ -286,7 +286,7 @@ static void JS_Transaction(v8::FunctionCallbackInfo<v8::Value> const& args) {
} }
if (params.IsEmpty()) { if (params.IsEmpty()) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_INTERNAL); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to decode function parameters");
} }
bool embed = false; bool embed = false;
@ -375,7 +375,7 @@ static void JS_Transaction(v8::FunctionCallbackInfo<v8::Value> const& args) {
} catch (std::exception const& ex) { } catch (std::exception const& ex) {
TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, ex.what()); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, ex.what());
} catch (...) { } catch (...) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_INTERNAL); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "caught unknown exception during transaction");
} }
res = trx.commit(); res = trx.commit();
@ -2044,7 +2044,7 @@ static void JS_UseDatabase(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_vocbase_t* vocbase = GetContextVocBase(isolate); TRI_vocbase_t* vocbase = GetContextVocBase(isolate);
if (vocbase == nullptr) { if (vocbase == nullptr) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_INTERNAL); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to find database");
} }
if (vocbase->isDropped()) { if (vocbase->isDropped()) {
@ -2270,7 +2270,7 @@ static void CreateDatabaseCoordinator(
} }
if (vocbase == nullptr) { if (vocbase == nullptr) {
TRI_V8_THROW_EXCEPTION(TRI_ERROR_INTERNAL); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unable to find database");
} }
// now run upgrade and copy users into context // now run upgrade and copy users into context

View File

@ -599,7 +599,7 @@ static void EnsureIndex(v8::FunctionCallbackInfo<v8::Value> const& args,
VPackSlice f = flds.at(i); VPackSlice f = flds.at(i);
if (!f.isString()) { if (!f.isString()) {
// index attributes must be strings // index attributes must be strings
TRI_V8_THROW_EXCEPTION(TRI_ERROR_INTERNAL); TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "index field names should be strings");
} }
indexKeys.emplace(f.copyString()); indexKeys.emplace(f.copyString());
} }

View File

@ -244,7 +244,7 @@ static std::shared_ptr<Index> PrepareIndexFromSlice(VPackSlice info,
switch (type) { switch (type) {
case arangodb::Index::TRI_IDX_TYPE_UNKNOWN: { case arangodb::Index::TRI_IDX_TYPE_UNKNOWN: {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid index type");
} }
case arangodb::Index::TRI_IDX_TYPE_PRIMARY_INDEX: { case arangodb::Index::TRI_IDX_TYPE_PRIMARY_INDEX: {
if (!isClusterConstructor) { if (!isClusterConstructor) {

View File

@ -52,7 +52,7 @@ template <typename T>
static inline T NumericValue(VPackSlice const& slice, char const* attribute) { static inline T NumericValue(VPackSlice const& slice, char const* attribute) {
if (!slice.isObject()) { if (!slice.isObject()) {
LOG(ERR) << "invalid value type when looking for attribute '" << attribute << "': expecting object"; LOG(ERR) << "invalid value type when looking for attribute '" << attribute << "': expecting object";
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "invalid attribute value: expecting object");
} }
VPackSlice v = slice.get(attribute); VPackSlice v = slice.get(attribute);
if (v.isString()) { if (v.isString()) {
@ -63,7 +63,7 @@ static inline T NumericValue(VPackSlice const& slice, char const* attribute) {
} }
LOG(ERR) << "invalid value for attribute '" << attribute << "'"; LOG(ERR) << "invalid value for attribute '" << attribute << "'";
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, "invalid attribute value");
} }
/// @brief creates the recover state /// @brief creates the recover state

View File

@ -108,6 +108,8 @@ char const* Exception::what() const throw() { return _errorMessage.c_str(); }
void Exception::appendLocation () { void Exception::appendLocation () {
if (_code == TRI_ERROR_INTERNAL) { if (_code == TRI_ERROR_INTERNAL) {
_errorMessage += std::string(" (exception location: ") + _file + ":" + std::to_string(_line) + "). Please report this error to arangodb.com"; _errorMessage += std::string(" (exception location: ") + _file + ":" + std::to_string(_line) + "). Please report this error to arangodb.com";
} else if (_code == TRI_ERROR_OUT_OF_MEMORY) {
_errorMessage += std::string(" (exception location: ") + _file + ":" + std::to_string(_line) + ").";
} }
#ifdef ARANGODB_ENABLE_MAINTAINER_MODE #ifdef ARANGODB_ENABLE_MAINTAINER_MODE

View File

@ -0,0 +1,163 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Max Neunhoeffer
/// @author Jan Steemann
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGODB_BASICS_FIXED_SIZE_ALLOCATOR_H
#define ARANGODB_BASICS_FIXED_SIZE_ALLOCATOR_H 1
#include "Basics/Common.h"
#include "Logger/Logger.h"
namespace arangodb {
class FixedSizeAllocator {
private:
class MemoryBlock {
public:
MemoryBlock(MemoryBlock const&) = delete;
MemoryBlock& operator=(MemoryBlock const&) = delete;
MemoryBlock(size_t itemSize, size_t nrItems)
: _itemSize(itemSize), _nrAlloc(nrItems), _nrUsed(0), _alloc(nullptr), _data(nullptr) {
_alloc = new char[(itemSize * nrItems) + 64];
// adjust to cache line offset (assumed to be 64 bytes)
_data = reinterpret_cast<char*>(
(reinterpret_cast<uintptr_t>(_alloc) + 63) & ~((uintptr_t)0x3fu));
}
MemoryBlock(MemoryBlock&& other)
: _itemSize(other._itemSize), _nrAlloc(other._nrAlloc), _nrUsed(other._nrUsed), _alloc(other._alloc), _data(other._data) {
other._nrAlloc = 0;
other._nrUsed = 0;
other._alloc = nullptr;
other._data = nullptr;
}
MemoryBlock& operator=(MemoryBlock&& other) {
if (this != &other) {
TRI_ASSERT(_itemSize == other._itemSize);
delete [] _alloc;
_nrAlloc = other._nrAlloc;
_nrUsed = other._nrUsed;
_alloc = other._alloc;
_data = other._data;
other._nrAlloc = 0;
other._nrUsed = 0;
other._alloc = nullptr;
other._data = nullptr;
}
return *this;
}
~MemoryBlock() {
delete[] _alloc;
}
void* next() {
TRI_ASSERT(_nrUsed < _nrAlloc);
return static_cast<void*>(_data + (_itemSize * _nrUsed++));
}
inline bool full() const {
return _nrUsed == _nrAlloc;
}
size_t memoryUsage() const {
return (_data - _alloc) + _itemSize * _nrAlloc;
}
private:
size_t const _itemSize;
size_t _nrAlloc;
size_t _nrUsed;
char* _alloc;
char* _data;
};
public:
FixedSizeAllocator(FixedSizeAllocator const&) = delete;
FixedSizeAllocator& operator=(FixedSizeAllocator const&) = delete;
explicit FixedSizeAllocator(size_t itemSize)
: _itemSize(itemSize), _freelist(nullptr) {
_blocks.reserve(4);
}
~FixedSizeAllocator() {}
void* allocate() {
if (_freelist != nullptr) {
void* element = _freelist;
_freelist = *reinterpret_cast<void**>(_freelist);
return element;
}
if (_blocks.empty() || _blocks.back()->full()) {
allocateBlock();
}
TRI_ASSERT(!_blocks.empty());
TRI_ASSERT(!_blocks.back()->full());
return _blocks.back()->next();
}
void deallocateAll() {
_blocks.clear();
_freelist = nullptr;
}
void deallocate(void* value) noexcept {
*reinterpret_cast<void**>(value) = _freelist;
_freelist = value;
}
size_t memoryUsage() const {
size_t total = 0;
for (auto const& it : _blocks) {
total += it->memoryUsage();
}
return total;
}
private:
void allocateBlock() {
size_t const size = 128 << (std::min)(size_t(8), _blocks.size());
auto block = std::make_unique<MemoryBlock>(_itemSize, size);
_blocks.emplace_back(block.get());
block.release();
}
std::vector<std::unique_ptr<MemoryBlock>> _blocks;
size_t _itemSize;
void* _freelist;
};
}
#endif