mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:arangodb/arangodb into devel
This commit is contained in:
commit
fa2441cc96
|
@ -774,7 +774,7 @@ if test -n "${TARGET_DIR}"; then
|
|||
${SED} -e "s/.*optimized;//" -e "s/;.*//" -e "s;/lib.*lib;;" -e "s;\([a-zA-Z]*\):;/cygdrive/\1;"
|
||||
)
|
||||
DLLS=$(find "${SSLDIR}" -name \*.dll |grep -i release)
|
||||
cp "${DLLS}" "bin/${BUILD_CONFIG}"
|
||||
cp ${DLLS} "bin/${BUILD_CONFIG}"
|
||||
cp "bin/${BUILD_CONFIG}/"* bin/
|
||||
cp "tests/${BUILD_CONFIG}/"*exe bin/
|
||||
fi
|
||||
|
|
|
@ -547,7 +547,7 @@ void Constituent::run() {
|
|||
// Most recent vote
|
||||
{
|
||||
std::string const aql("FOR l IN election SORT l._key DESC LIMIT 1 RETURN l");
|
||||
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(),
|
||||
arangodb::aql::Query query(false, _vocbase, arangodb::aql::QueryString(aql),
|
||||
bindVars, nullptr, arangodb::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.execute(_queryRegistry);
|
||||
|
|
|
@ -275,7 +275,7 @@ size_t State::removeConflicts(query_t const& transactions) { // Under MUTEX in A
|
|||
stringify(idx) + "' REMOVE l IN log");
|
||||
|
||||
arangodb::aql::Query query(
|
||||
false, _vocbase, aql.c_str(), aql.size(), bindVars, nullptr,
|
||||
false, _vocbase, aql::QueryString(aql), bindVars, nullptr,
|
||||
arangodb::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.execute(_queryRegistry);
|
||||
|
@ -537,7 +537,7 @@ bool State::loadCompacted() {
|
|||
|
||||
std::string const aql(
|
||||
std::string("FOR c IN compact SORT c._key DESC LIMIT 1 RETURN c"));
|
||||
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), bindVars,
|
||||
arangodb::aql::Query query(false, _vocbase, aql::QueryString(aql), bindVars,
|
||||
nullptr, arangodb::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY);
|
||||
|
@ -576,7 +576,7 @@ bool State::loadOrPersistConfiguration() {
|
|||
std::string const aql(
|
||||
std::string("FOR c in configuration FILTER c._key==\"0\" RETURN c.cfg"));
|
||||
|
||||
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), bindVars,
|
||||
arangodb::aql::Query query(false, _vocbase, aql::QueryString(aql), bindVars,
|
||||
nullptr, arangodb::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY);
|
||||
|
@ -652,7 +652,7 @@ bool State::loadRemaining() {
|
|||
bindVars->close();
|
||||
|
||||
std::string const aql(std::string("FOR l IN log SORT l._key RETURN l"));
|
||||
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), bindVars,
|
||||
arangodb::aql::Query query(false, _vocbase, aql::QueryString(aql), bindVars,
|
||||
nullptr, arangodb::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY);
|
||||
|
@ -755,7 +755,7 @@ bool State::compactPersisted(arangodb::consensus::index_t cind) {
|
|||
std::string const aql(std::string("FOR l IN log FILTER l._key < \"") +
|
||||
i_str.str() + "\" REMOVE l IN log");
|
||||
|
||||
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), bindVars,
|
||||
arangodb::aql::Query query(false, _vocbase, aql::QueryString(aql), bindVars,
|
||||
nullptr, arangodb::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY);
|
||||
|
@ -785,7 +785,7 @@ bool State::removeObsolete(arangodb::consensus::index_t cind) {
|
|||
std::string const aql(std::string("FOR c IN compact FILTER c._key < \"") +
|
||||
i_str.str() + "\" REMOVE c IN compact");
|
||||
|
||||
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(),
|
||||
arangodb::aql::Query query(false, _vocbase, aql::QueryString(aql),
|
||||
bindVars, nullptr, arangodb::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY);
|
||||
|
@ -876,9 +876,9 @@ query_t State::allLogs() const {
|
|||
std::string const comp("FOR c IN compact SORT c._key RETURN c");
|
||||
std::string const logs("FOR l IN log SORT l._key RETURN l");
|
||||
|
||||
arangodb::aql::Query compq(false, _vocbase, comp.c_str(), comp.size(),
|
||||
arangodb::aql::Query compq(false, _vocbase, aql::QueryString(comp),
|
||||
bindVars, nullptr, arangodb::aql::PART_MAIN);
|
||||
arangodb::aql::Query logsq(false, _vocbase, logs.c_str(), logs.size(),
|
||||
arangodb::aql::Query logsq(false, _vocbase, aql::QueryString(logs),
|
||||
bindVars, nullptr, arangodb::aql::PART_MAIN);
|
||||
|
||||
auto compqResult = compq.execute(QueryRegistryFeature::QUERY_REGISTRY);
|
||||
|
|
|
@ -34,13 +34,19 @@ Parser::Parser(Query* query)
|
|||
: _query(query),
|
||||
_ast(query->ast()),
|
||||
_scanner(nullptr),
|
||||
_buffer(query->queryString()),
|
||||
_remainingLength(query->queryLength()),
|
||||
_queryStringStart(nullptr),
|
||||
_buffer(nullptr),
|
||||
_remainingLength(0),
|
||||
_offset(0),
|
||||
_marker(nullptr),
|
||||
_stack(),
|
||||
_isModificationQuery(false) {
|
||||
_stack.reserve(4);
|
||||
|
||||
QueryString const& qs = queryString();
|
||||
_queryStringStart = qs.data();
|
||||
_buffer = qs.data();
|
||||
_remainingLength = qs.size();
|
||||
}
|
||||
|
||||
/// @brief destroy the parser
|
||||
|
@ -64,9 +70,7 @@ bool Parser::configureWriteQuery(AstNode const* collectionNode,
|
|||
|
||||
/// @brief parse the query
|
||||
QueryResult Parser::parse(bool withDetails) {
|
||||
char const* q = queryString();
|
||||
|
||||
if (q == nullptr || *q == '\0' || remainingLength() == 0) {
|
||||
if (queryString().empty() || remainingLength() == 0) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_EMPTY);
|
||||
}
|
||||
|
||||
|
@ -137,7 +141,7 @@ void Parser::registerParseError(int errorCode, char const* data, int line,
|
|||
TRI_ASSERT(data != nullptr);
|
||||
|
||||
// extract the query string part where the error happened
|
||||
std::string const region(_query->extractRegion(line, column));
|
||||
std::string const region(queryString().extractRegion(line, column));
|
||||
|
||||
// note: line numbers reported by bison/flex start at 1, columns start at 0
|
||||
std::stringstream errorMessage;
|
||||
|
@ -146,7 +150,7 @@ void Parser::registerParseError(int errorCode, char const* data, int line,
|
|||
<< (column + 1);
|
||||
|
||||
if (_query->verboseErrors()) {
|
||||
errorMessage << std::endl << _query->queryString() << std::endl;
|
||||
errorMessage << std::endl << queryString() << std::endl;
|
||||
|
||||
// create a neat pointer to the location of the error.
|
||||
size_t i;
|
||||
|
|
|
@ -71,9 +71,9 @@ class Parser {
|
|||
|
||||
/// @brief return the scanner
|
||||
inline void* scanner() const { return _scanner; }
|
||||
|
||||
|
||||
/// @brief a pointer to the start of the query string
|
||||
inline char const* queryString() const { return _query->queryString(); }
|
||||
char const* queryStringStart() const { return _queryStringStart; }
|
||||
|
||||
/// @brief return the remaining length of the query string to process
|
||||
inline size_t remainingLength() const { return _remainingLength; }
|
||||
|
@ -148,6 +148,10 @@ class Parser {
|
|||
/// @brief peek at a temporary value from the parser's stack
|
||||
void* peekStack();
|
||||
|
||||
private:
|
||||
/// @brief a pointer to the start of the query string
|
||||
QueryString const& queryString() const { return _query->queryString(); }
|
||||
|
||||
private:
|
||||
/// @brief the query
|
||||
Query* _query;
|
||||
|
@ -158,6 +162,8 @@ class Parser {
|
|||
/// @brief lexer / scanner used when parsing the query (Aql/tokens.ll)
|
||||
void* _scanner;
|
||||
|
||||
char const* _queryStringStart;
|
||||
|
||||
/// @brief currently processed part of the query string
|
||||
char const* _buffer;
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "Aql/Ast.h"
|
||||
#include "Aql/ExecutionPlan.h"
|
||||
#include "Aql/Query.h"
|
||||
#include "Aql/QueryString.h"
|
||||
#include "Basics/ReadLocker.h"
|
||||
#include "Basics/WriteLocker.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
@ -43,9 +44,9 @@ PlanCache::PlanCache() : _lock(), _plans() {}
|
|||
PlanCache::~PlanCache() {}
|
||||
|
||||
/// @brief lookup a plan in the cache
|
||||
std::shared_ptr<PlanCacheEntry> PlanCache::lookup(TRI_vocbase_t* vocbase, uint64_t hash,
|
||||
char const* queryString,
|
||||
size_t queryStringLength) {
|
||||
std::shared_ptr<PlanCacheEntry> PlanCache::lookup(TRI_vocbase_t* vocbase,
|
||||
uint64_t queryHash,
|
||||
QueryString const& queryString) {
|
||||
READ_LOCKER(readLocker, _lock);
|
||||
|
||||
auto it = _plans.find(vocbase);
|
||||
|
@ -55,7 +56,7 @@ std::shared_ptr<PlanCacheEntry> PlanCache::lookup(TRI_vocbase_t* vocbase, uint64
|
|||
return std::shared_ptr<PlanCacheEntry>();
|
||||
}
|
||||
|
||||
auto it2 = (*it).second.find(hash);
|
||||
auto it2 = (*it).second.find(queryHash);
|
||||
|
||||
if (it2 == (*it).second.end()) {
|
||||
// plan not found in cache
|
||||
|
@ -68,10 +69,10 @@ std::shared_ptr<PlanCacheEntry> PlanCache::lookup(TRI_vocbase_t* vocbase, uint64
|
|||
|
||||
/// @brief store a plan in the cache
|
||||
void PlanCache::store(
|
||||
TRI_vocbase_t* vocbase, uint64_t hash, char const* queryString,
|
||||
size_t queryStringLength, ExecutionPlan const* plan) {
|
||||
TRI_vocbase_t* vocbase, uint64_t hash, QueryString const& queryString,
|
||||
ExecutionPlan const* plan) {
|
||||
|
||||
auto entry = std::make_unique<PlanCacheEntry>(std::string(queryString, queryStringLength), plan->toVelocyPack(plan->getAst(), true));
|
||||
auto entry = std::make_unique<PlanCacheEntry>(queryString.extract(SIZE_MAX), plan->toVelocyPack(plan->getAst(), true));
|
||||
|
||||
WRITE_LOCKER(writeLocker, _lock);
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ class Builder;
|
|||
|
||||
namespace aql {
|
||||
class ExecutionPlan;
|
||||
class QueryString;
|
||||
class VariableGenerator;
|
||||
|
||||
struct PlanCacheEntry {
|
||||
|
@ -60,10 +61,10 @@ class PlanCache {
|
|||
|
||||
public:
|
||||
/// @brief lookup a plan in the cache
|
||||
std::shared_ptr<PlanCacheEntry> lookup(TRI_vocbase_t*, uint64_t, char const*, size_t);
|
||||
std::shared_ptr<PlanCacheEntry> lookup(TRI_vocbase_t*, uint64_t, QueryString const&);
|
||||
|
||||
/// @brief store a plan in the cache
|
||||
void store(TRI_vocbase_t*, uint64_t, char const*, size_t, ExecutionPlan const*);
|
||||
void store(TRI_vocbase_t*, uint64_t, QueryString const&, ExecutionPlan const*);
|
||||
|
||||
/// @brief invalidate all plans for a particular database
|
||||
void invalidate(TRI_vocbase_t*);
|
||||
|
|
|
@ -73,7 +73,7 @@ constexpr uint64_t DontCache = 0;
|
|||
|
||||
/// @brief creates a query
|
||||
Query::Query(bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
|
||||
char const* queryString, size_t queryLength,
|
||||
QueryString const& queryString,
|
||||
std::shared_ptr<VPackBuilder> const& bindParameters,
|
||||
std::shared_ptr<VPackBuilder> const& options, QueryPart part)
|
||||
: _id(0),
|
||||
|
@ -82,7 +82,6 @@ Query::Query(bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
|
|||
_vocbase(vocbase),
|
||||
_context(nullptr),
|
||||
_queryString(queryString),
|
||||
_queryStringLength(queryLength),
|
||||
_queryBuilder(),
|
||||
_bindParameters(bindParameters),
|
||||
_options(options),
|
||||
|
@ -109,12 +108,12 @@ Query::Query(bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
|
|||
if (tracing > 0) {
|
||||
LOG_TOPIC(INFO, Logger::QUERIES)
|
||||
<< TRI_microtime() - _startTime << " "
|
||||
<< "Query::Query queryString: " << std::string(queryString, queryLength)
|
||||
<< "Query::Query queryString: " << _queryString
|
||||
<< " this: " << (uintptr_t) this;
|
||||
} else {
|
||||
LOG_TOPIC(DEBUG, Logger::QUERIES)
|
||||
<< TRI_microtime() - _startTime << " "
|
||||
<< "Query::Query queryString: " << std::string(queryString, queryLength)
|
||||
<< "Query::Query queryString: " << _queryString
|
||||
<< " this: " << (uintptr_t) this;
|
||||
}
|
||||
if (bindParameters != nullptr && !bindParameters->isEmpty() &&
|
||||
|
@ -150,8 +149,7 @@ Query::Query(bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
|
|||
_resources(&_resourceMonitor),
|
||||
_vocbase(vocbase),
|
||||
_context(nullptr),
|
||||
_queryString(nullptr),
|
||||
_queryStringLength(0),
|
||||
_queryString(),
|
||||
_queryBuilder(queryStruct),
|
||||
_options(options),
|
||||
_collections(vocbase),
|
||||
|
@ -221,7 +219,7 @@ Query::~Query() {
|
|||
/// the query
|
||||
Query* Query::clone(QueryPart part, bool withPlan) {
|
||||
auto clone =
|
||||
std::make_unique<Query>(false, _vocbase, _queryString, _queryStringLength,
|
||||
std::make_unique<Query>(false, _vocbase, _queryString,
|
||||
std::shared_ptr<VPackBuilder>(), _options, part);
|
||||
|
||||
clone->_resourceMonitor = _resourceMonitor;
|
||||
|
@ -266,62 +264,6 @@ void Query::setExecutionTime() {
|
|||
}
|
||||
}
|
||||
|
||||
/// @brief extract a region from the query
|
||||
std::string Query::extractRegion(int line, int column) const {
|
||||
TRI_ASSERT(_queryString != nullptr);
|
||||
|
||||
// note: line numbers reported by bison/flex start at 1, columns start at 0
|
||||
int currentLine = 1;
|
||||
int currentColumn = 0;
|
||||
|
||||
char c;
|
||||
char const* p = _queryString;
|
||||
|
||||
while ((static_cast<size_t>(p - _queryString) < _queryStringLength) && (c = *p)) {
|
||||
if (currentLine > line ||
|
||||
(currentLine >= line && currentColumn >= column)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '\n') {
|
||||
++p;
|
||||
++currentLine;
|
||||
currentColumn = 0;
|
||||
} else if (c == '\r') {
|
||||
++p;
|
||||
++currentLine;
|
||||
currentColumn = 0;
|
||||
|
||||
// eat a following newline
|
||||
if (*p == '\n') {
|
||||
++p;
|
||||
}
|
||||
} else {
|
||||
++currentColumn;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
// p is pointing at the position in the query the parse error occurred at
|
||||
TRI_ASSERT(p >= _queryString);
|
||||
|
||||
size_t offset = static_cast<size_t>(p - _queryString);
|
||||
|
||||
static int const SNIPPET_LENGTH = 32;
|
||||
static char const* SNIPPET_SUFFIX = "...";
|
||||
|
||||
if (_queryStringLength < offset + SNIPPET_LENGTH) {
|
||||
// return a copy of the region
|
||||
return std::string(_queryString + offset, _queryStringLength - offset);
|
||||
}
|
||||
|
||||
// copy query part
|
||||
std::string result(_queryString + offset, SNIPPET_LENGTH);
|
||||
result.append(SNIPPET_SUFFIX);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @brief register an error, with an optional parameter inserted into printf
|
||||
/// this also makes the query abort
|
||||
void Query::registerError(int code, char const* details) {
|
||||
|
@ -373,7 +315,7 @@ void Query::registerWarning(int code, char const* details) {
|
|||
}
|
||||
}
|
||||
|
||||
void Query::prepare(QueryRegistry* registry, uint64_t queryStringHash) {
|
||||
void Query::prepare(QueryRegistry* registry, uint64_t queryHash) {
|
||||
TRI_ASSERT(registry != nullptr);
|
||||
|
||||
init();
|
||||
|
@ -382,15 +324,15 @@ void Query::prepare(QueryRegistry* registry, uint64_t queryStringHash) {
|
|||
std::unique_ptr<ExecutionPlan> plan;
|
||||
|
||||
#if USE_PLAN_CACHE
|
||||
if (_queryString != nullptr &&
|
||||
queryStringHash != DontCache &&
|
||||
if (!_queryString.empty() &&
|
||||
queryHash != DontCache &&
|
||||
_part == PART_MAIN) {
|
||||
// LOG_TOPIC(INFO, Logger::FIXME) << "trying to find query in execution plan cache: '" << std::string(_queryString, _queryStringLength) << "', hash: " << queryStringHash;
|
||||
// LOG_TOPIC(INFO, Logger::FIXME) << "trying to find query in execution plan cache: '" << _queryString << "', hash: " << queryHash;
|
||||
|
||||
// store & lookup velocypack plans!!
|
||||
std::shared_ptr<PlanCacheEntry> planCacheEntry = PlanCache::instance()->lookup(_vocbase, queryStringHash, _queryString, _queryStringLength);
|
||||
std::shared_ptr<PlanCacheEntry> planCacheEntry = PlanCache::instance()->lookup(_vocbase, queryHash, queryString);
|
||||
if (planCacheEntry != nullptr) {
|
||||
// LOG_TOPIC(INFO, Logger::FIXME) << "query found in execution plan cache: '" << std::string(_queryString, _queryStringLength) << "'";
|
||||
// LOG_TOPIC(INFO, Logger::FIXME) << "query found in execution plan cache: '" << _queryString << "'";
|
||||
|
||||
TRI_ASSERT(_trx == nullptr);
|
||||
TRI_ASSERT(_collections.empty());
|
||||
|
@ -433,13 +375,13 @@ void Query::prepare(QueryRegistry* registry, uint64_t queryStringHash) {
|
|||
TRI_ASSERT(plan != nullptr);
|
||||
|
||||
#if USE_PLAN_CACHE
|
||||
if (_queryString != nullptr &&
|
||||
queryStringHash != DontCache &&
|
||||
if (!_queryString.empty() &&
|
||||
queryHash != DontCache &&
|
||||
_part == PART_MAIN &&
|
||||
_warnings.empty() &&
|
||||
_ast->root()->isCacheable()) {
|
||||
// LOG_TOPIC(INFO, Logger::FIXME) << "storing query in execution plan cache '" << std::string(_queryString, _queryStringLength) << "', hash: " << queryStringHash;
|
||||
PlanCache::instance()->store(_vocbase, queryStringHash, _queryString, _queryStringLength, plan.get());
|
||||
// LOG_TOPIC(INFO, Logger::FIXME) << "storing query in execution plan cache '" << _queryString << "', hash: " << queryHash;
|
||||
PlanCache::instance()->store(_vocbase, queryHash, _queryString, plan.get());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -451,7 +393,7 @@ void Query::prepare(QueryRegistry* registry, uint64_t queryStringHash) {
|
|||
// own _engine attribute (the instanciation procedure may modify us
|
||||
// by calling our engine(ExecutionEngine*) function
|
||||
// this is confusing and should be fixed!
|
||||
std::unique_ptr<ExecutionEngine> engine(ExecutionEngine::instantiateFromPlan(registry, this, plan.get(), _queryString != nullptr));
|
||||
std::unique_ptr<ExecutionEngine> engine(ExecutionEngine::instantiateFromPlan(registry, this, plan.get(), !_queryString.empty()));
|
||||
|
||||
if (_engine == nullptr) {
|
||||
_engine = std::move(engine);
|
||||
|
@ -472,7 +414,7 @@ ExecutionPlan* Query::prepare() {
|
|||
<< " this: " << (uintptr_t) this;
|
||||
std::unique_ptr<ExecutionPlan> plan;
|
||||
|
||||
if (_queryString != nullptr) {
|
||||
if (!_queryString.empty()) {
|
||||
auto parser = std::make_unique<Parser>(this);
|
||||
|
||||
parser->parse(false);
|
||||
|
@ -491,7 +433,7 @@ ExecutionPlan* Query::prepare() {
|
|||
|
||||
// As soon as we start du instantiate the plan we have to clean it
|
||||
// up before killing the unique_ptr
|
||||
if (_queryString != nullptr) {
|
||||
if (!_queryString.empty()) {
|
||||
// we have an AST
|
||||
// optimize the ast
|
||||
enterState(QueryExecutionState::ValueType::AST_OPTIMIZATION);
|
||||
|
@ -575,12 +517,12 @@ QueryResult Query::execute(QueryRegistry* registry) {
|
|||
|
||||
try {
|
||||
bool useQueryCache = canUseQueryCache();
|
||||
uint64_t queryStringHash = hash();
|
||||
uint64_t queryHash = hash();
|
||||
|
||||
if (useQueryCache) {
|
||||
// check the query cache for an existing result
|
||||
auto cacheEntry = arangodb::aql::QueryCache::instance()->lookup(
|
||||
_vocbase, queryStringHash, _queryString, _queryStringLength);
|
||||
_vocbase, queryHash, _queryString);
|
||||
arangodb::aql::QueryCacheResultEntryGuard guard(cacheEntry);
|
||||
|
||||
if (cacheEntry != nullptr) {
|
||||
|
@ -599,14 +541,14 @@ QueryResult Query::execute(QueryRegistry* registry) {
|
|||
}
|
||||
|
||||
// will throw if it fails
|
||||
prepare(registry, queryStringHash);
|
||||
prepare(registry, queryHash);
|
||||
|
||||
if (_queryString == nullptr) {
|
||||
if (_queryString.empty()) {
|
||||
// we don't have query string... now pass query id to WorkMonitor
|
||||
work.reset(new AqlWorkStack(_vocbase, _id));
|
||||
} else {
|
||||
// we do have a query string... pass query to WorkMonitor
|
||||
work.reset(new AqlWorkStack(_vocbase, _id, _queryString, _queryStringLength));
|
||||
work.reset(new AqlWorkStack(_vocbase, _id, _queryString.data(), _queryString.size()));
|
||||
}
|
||||
|
||||
log();
|
||||
|
@ -658,7 +600,7 @@ QueryResult Query::execute(QueryRegistry* registry) {
|
|||
if (_warnings.empty()) {
|
||||
// finally store the generated result in the query cache
|
||||
auto result = QueryCache::instance()->store(
|
||||
_vocbase, queryStringHash, _queryString, _queryStringLength,
|
||||
_vocbase, queryHash, _queryString,
|
||||
resultBuilder, _trx->state()->collectionNames());
|
||||
|
||||
if (result == nullptr) {
|
||||
|
@ -759,12 +701,12 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
|
|||
|
||||
try {
|
||||
bool useQueryCache = canUseQueryCache();
|
||||
uint64_t queryStringHash = hash();
|
||||
uint64_t queryHash = hash();
|
||||
|
||||
if (useQueryCache) {
|
||||
// check the query cache for an existing result
|
||||
auto cacheEntry = arangodb::aql::QueryCache::instance()->lookup(
|
||||
_vocbase, queryStringHash, _queryString, _queryStringLength);
|
||||
_vocbase, queryHash, _queryString);
|
||||
arangodb::aql::QueryCacheResultEntryGuard guard(cacheEntry);
|
||||
|
||||
if (cacheEntry != nullptr) {
|
||||
|
@ -785,14 +727,14 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
|
|||
}
|
||||
|
||||
// will throw if it fails
|
||||
prepare(registry, queryStringHash);
|
||||
prepare(registry, queryHash);
|
||||
|
||||
if (_queryString == nullptr) {
|
||||
if (_queryString.empty()) {
|
||||
// we don't have query string... now pass query id to WorkMonitor
|
||||
work.reset(new AqlWorkStack(_vocbase, _id));
|
||||
} else {
|
||||
// we do have a query string... pass query to WorkMonitor
|
||||
work.reset(new AqlWorkStack(_vocbase, _id, _queryString, _queryStringLength));
|
||||
work.reset(new AqlWorkStack(_vocbase, _id, _queryString.data(), _queryString.size()));
|
||||
}
|
||||
|
||||
log();
|
||||
|
@ -842,8 +784,7 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
|
|||
|
||||
if (_warnings.empty()) {
|
||||
// finally store the generated result in the query cache
|
||||
QueryCache::instance()->store(_vocbase, queryStringHash, _queryString,
|
||||
_queryStringLength, builder,
|
||||
QueryCache::instance()->store(_vocbase, queryHash, _queryString, builder,
|
||||
_trx->state()->collectionNames());
|
||||
}
|
||||
} else {
|
||||
|
@ -1033,7 +974,7 @@ QueryResult Query::explain() {
|
|||
result.result = bestPlan->toVelocyPack(parser.ast(), verbosePlans());
|
||||
|
||||
// cacheability
|
||||
result.cached = (_queryString != nullptr && _queryStringLength > 0 &&
|
||||
result.cached = (!_queryString.empty() &&
|
||||
!_isModificationQuery && _warnings.empty() &&
|
||||
_ast->root()->isCacheable());
|
||||
}
|
||||
|
@ -1239,25 +1180,20 @@ void Query::init() {
|
|||
|
||||
/// @brief log a query
|
||||
void Query::log() {
|
||||
if (_queryString != nullptr) {
|
||||
static size_t const MaxLength = 1024;
|
||||
|
||||
if (!_queryString.empty()) {
|
||||
LOG_TOPIC(TRACE, Logger::QUERIES)
|
||||
<< "executing query " << _id << ": '"
|
||||
<< std::string(_queryString, (std::min)(_queryStringLength, MaxLength))
|
||||
.append(_queryStringLength > MaxLength ? "..." : "") << "'";
|
||||
<< "executing query " << _id << ": '" << _queryString.extract(1024) << "'";
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief calculate a hash value for the query and bind parameters
|
||||
uint64_t Query::hash() const {
|
||||
if (_queryString == nullptr) {
|
||||
uint64_t Query::hash() {
|
||||
if (_queryString.empty()) {
|
||||
return DontCache;
|
||||
}
|
||||
|
||||
// hash the query string first
|
||||
uint64_t hash = arangodb::aql::QueryCache::instance()->hashQueryString(
|
||||
_queryString, _queryStringLength);
|
||||
uint64_t hash = _queryString.hash();
|
||||
|
||||
// handle "fullCount" option. if this option is set, the query result will
|
||||
// be different to when it is not set!
|
||||
|
@ -1288,7 +1224,7 @@ uint64_t Query::hash() const {
|
|||
|
||||
/// @brief whether or not the query cache can be used for the query
|
||||
bool Query::canUseQueryCache() const {
|
||||
if (_queryString == nullptr || _queryStringLength < 8) {
|
||||
if (_queryString.size() < 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1317,9 +1253,9 @@ bool Query::canUseQueryCache() const {
|
|||
std::string Query::buildErrorMessage(int errorCode) const {
|
||||
std::string err(TRI_errno_string(errorCode));
|
||||
|
||||
if (_queryString != nullptr && verboseErrors()) {
|
||||
if (!_queryString.empty() && verboseErrors()) {
|
||||
err += "\nwhile executing:\n";
|
||||
err.append(_queryString, _queryStringLength);
|
||||
_queryString.append(err);
|
||||
err += "\n";
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "Aql/QueryExecutionState.h"
|
||||
#include "Aql/QueryResources.h"
|
||||
#include "Aql/QueryResultV8.h"
|
||||
#include "Aql/QueryString.h"
|
||||
#include "Aql/ResourceUsage.h"
|
||||
#include "Aql/types.h"
|
||||
#include "Basics/Common.h"
|
||||
|
@ -76,7 +77,7 @@ class Query {
|
|||
Query& operator=(Query const&) = delete;
|
||||
|
||||
public:
|
||||
Query(bool, TRI_vocbase_t*, char const*, size_t,
|
||||
Query(bool contextOwnedByExterior, TRI_vocbase_t*, QueryString const& queryString,
|
||||
std::shared_ptr<arangodb::velocypack::Builder> const& bindParameters,
|
||||
std::shared_ptr<arangodb::velocypack::Builder> const& options, QueryPart);
|
||||
|
||||
|
@ -93,6 +94,8 @@ class Query {
|
|||
|
||||
public:
|
||||
|
||||
QueryString const& queryString() const { return _queryString; }
|
||||
|
||||
/// @brief Inject a transaction from outside. Use with care!
|
||||
void injectTransaction (transaction::Methods* trx) {
|
||||
_trx = trx;
|
||||
|
@ -137,12 +140,6 @@ class Query {
|
|||
/// @brief return the query's id
|
||||
TRI_voc_tick_t id() const { return _id; }
|
||||
|
||||
/// @brief get the query string
|
||||
char const* queryString() const { return _queryString; }
|
||||
|
||||
/// @brief get the length of the query string
|
||||
size_t queryLength() const { return _queryStringLength; }
|
||||
|
||||
/// @brief getter for _ast
|
||||
Ast* ast() const {
|
||||
return _ast.get();
|
||||
|
@ -199,7 +196,7 @@ class Query {
|
|||
}
|
||||
|
||||
/// @brief extract a region from the query
|
||||
std::string extractRegion(int, int) const;
|
||||
std::string extractRegion(int line, int column) const;
|
||||
|
||||
/// @brief register an error, with an optional parameter inserted into printf
|
||||
/// this also makes the query abort
|
||||
|
@ -212,7 +209,7 @@ class Query {
|
|||
/// @brief register a warning
|
||||
void registerWarning(int, char const* = nullptr);
|
||||
|
||||
void prepare(QueryRegistry*, uint64_t queryStringHash);
|
||||
void prepare(QueryRegistry*, uint64_t queryHash);
|
||||
|
||||
/// @brief execute an AQL query
|
||||
QueryResult execute(QueryRegistry*);
|
||||
|
@ -297,7 +294,7 @@ class Query {
|
|||
void log();
|
||||
|
||||
/// @brief calculate a hash value for the query and bind parameters
|
||||
uint64_t hash() const;
|
||||
uint64_t hash();
|
||||
|
||||
/// @brief whether or not the query cache can be used for the query
|
||||
bool canUseQueryCache() const;
|
||||
|
@ -369,10 +366,7 @@ class Query {
|
|||
std::unordered_map<std::string, Graph*> _graphs;
|
||||
|
||||
/// @brief the actual query string
|
||||
char const* _queryString;
|
||||
|
||||
/// @brief length of the query string in bytes
|
||||
size_t const _queryStringLength;
|
||||
QueryString _queryString;
|
||||
|
||||
/// @brief query in a VelocyPack structure
|
||||
std::shared_ptr<arangodb::velocypack::Builder> const _queryBuilder;
|
||||
|
|
|
@ -46,10 +46,10 @@ static std::atomic<arangodb::aql::QueryCacheMode> Mode(CACHE_ON_DEMAND);
|
|||
|
||||
/// @brief create a cache entry
|
||||
QueryCacheResultEntry::QueryCacheResultEntry(
|
||||
uint64_t hash, char const* queryString, size_t queryStringLength,
|
||||
uint64_t hash, QueryString const& queryString,
|
||||
std::shared_ptr<VPackBuilder> queryResult, std::vector<std::string> const& collections)
|
||||
: _hash(hash),
|
||||
_queryString(queryString, queryStringLength),
|
||||
_queryString(queryString.data(), queryString.size()),
|
||||
_queryResult(queryResult),
|
||||
_collections(collections),
|
||||
_prev(nullptr),
|
||||
|
@ -105,7 +105,7 @@ QueryCacheDatabaseEntry::~QueryCacheDatabaseEntry() {
|
|||
|
||||
/// @brief lookup a query result in the database-specific cache
|
||||
QueryCacheResultEntry* QueryCacheDatabaseEntry::lookup(
|
||||
uint64_t hash, char const* queryString, size_t queryStringLength) {
|
||||
uint64_t hash, QueryString const& queryString) {
|
||||
auto it = _entriesByHash.find(hash);
|
||||
|
||||
if (it == _entriesByHash.end()) {
|
||||
|
@ -115,8 +115,8 @@ QueryCacheResultEntry* QueryCacheDatabaseEntry::lookup(
|
|||
|
||||
// found some result in cache
|
||||
|
||||
if (queryStringLength != (*it).second->_queryString.size() ||
|
||||
memcmp(queryString, (*it).second->_queryString.c_str(), queryStringLength) != 0) {
|
||||
if (queryString.size() != (*it).second->_queryString.size() ||
|
||||
memcmp(queryString.data(), (*it).second->_queryString.c_str(), queryString.size()) != 0) {
|
||||
// found something, but obviously the result of a different query with the
|
||||
// same hash
|
||||
return nullptr;
|
||||
|
@ -362,8 +362,7 @@ std::string QueryCache::modeString(QueryCacheMode mode) {
|
|||
|
||||
/// @brief lookup a query result in the cache
|
||||
QueryCacheResultEntry* QueryCache::lookup(TRI_vocbase_t* vocbase, uint64_t hash,
|
||||
char const* queryString,
|
||||
size_t queryStringLength) {
|
||||
QueryString const& queryString) {
|
||||
auto const part = getPart(vocbase);
|
||||
READ_LOCKER(readLocker, _entriesLock[part]);
|
||||
|
||||
|
@ -374,18 +373,17 @@ QueryCacheResultEntry* QueryCache::lookup(TRI_vocbase_t* vocbase, uint64_t hash,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return (*it).second->lookup(hash, queryString, queryStringLength);
|
||||
return (*it).second->lookup(hash, queryString);
|
||||
}
|
||||
|
||||
/// @brief store a query in the cache
|
||||
/// if the call is successful, the cache has taken over ownership for the
|
||||
/// query result!
|
||||
QueryCacheResultEntry* QueryCache::store(
|
||||
TRI_vocbase_t* vocbase, uint64_t hash, char const* queryString,
|
||||
size_t queryStringLength, std::shared_ptr<VPackBuilder> result,
|
||||
TRI_vocbase_t* vocbase, uint64_t hash, QueryString const& queryString,
|
||||
std::shared_ptr<VPackBuilder> result,
|
||||
std::vector<std::string> const& collections) {
|
||||
|
||||
|
||||
if (!result->slice().isArray()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -395,7 +393,7 @@ QueryCacheResultEntry* QueryCache::store(
|
|||
|
||||
// create the cache entry outside the lock
|
||||
auto entry = std::make_unique<QueryCacheResultEntry>(
|
||||
hash, queryString, queryStringLength, result, collections);
|
||||
hash, queryString, result, collections);
|
||||
|
||||
WRITE_LOCKER(writeLocker, _entriesLock[part]);
|
||||
|
||||
|
@ -482,14 +480,6 @@ void QueryCache::invalidate() {
|
|||
}
|
||||
}
|
||||
|
||||
/// @brief hashes a query string
|
||||
uint64_t QueryCache::hashQueryString(char const* queryString,
|
||||
size_t queryLength) const {
|
||||
TRI_ASSERT(queryString != nullptr);
|
||||
|
||||
return fasthash64(queryString, queryLength, 0x3123456789abcdef);
|
||||
}
|
||||
|
||||
/// @brief get the query cache instance
|
||||
QueryCache* QueryCache::instance() { return &Instance; }
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#ifndef ARANGOD_AQL_QUERY_CACHE_H
|
||||
#define ARANGOD_AQL_QUERY_CACHE_H 1
|
||||
|
||||
#include "Aql/QueryString.h"
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/Mutex.h"
|
||||
#include "Basics/ReadWriteLock.h"
|
||||
|
@ -42,7 +43,7 @@ enum QueryCacheMode { CACHE_ALWAYS_OFF, CACHE_ALWAYS_ON, CACHE_ON_DEMAND };
|
|||
struct QueryCacheResultEntry {
|
||||
QueryCacheResultEntry() = delete;
|
||||
|
||||
QueryCacheResultEntry(uint64_t, char const*, size_t, std::shared_ptr<arangodb::velocypack::Builder>,
|
||||
QueryCacheResultEntry(uint64_t, QueryString const&, std::shared_ptr<arangodb::velocypack::Builder>,
|
||||
std::vector<std::string> const&);
|
||||
|
||||
~QueryCacheResultEntry() = default;
|
||||
|
@ -99,7 +100,7 @@ struct QueryCacheDatabaseEntry {
|
|||
~QueryCacheDatabaseEntry();
|
||||
|
||||
/// @brief lookup a query result in the database-specific cache
|
||||
QueryCacheResultEntry* lookup(uint64_t, char const*, size_t);
|
||||
QueryCacheResultEntry* lookup(uint64_t, QueryString const&);
|
||||
|
||||
/// @brief store a query result in the database-specific cache
|
||||
void store(uint64_t, QueryCacheResultEntry*);
|
||||
|
@ -176,12 +177,12 @@ class QueryCache {
|
|||
static std::string modeString(QueryCacheMode);
|
||||
|
||||
/// @brief lookup a query result in the cache
|
||||
QueryCacheResultEntry* lookup(TRI_vocbase_t*, uint64_t, char const*, size_t);
|
||||
QueryCacheResultEntry* lookup(TRI_vocbase_t*, uint64_t, QueryString const&);
|
||||
|
||||
/// @brief store a query in the cache
|
||||
/// if the call is successful, the cache has taken over ownership for the
|
||||
/// query result!
|
||||
QueryCacheResultEntry* store(TRI_vocbase_t*, uint64_t, char const*, size_t,
|
||||
QueryCacheResultEntry* store(TRI_vocbase_t*, uint64_t, QueryString const&,
|
||||
std::shared_ptr<arangodb::velocypack::Builder>,
|
||||
std::vector<std::string> const&);
|
||||
|
||||
|
@ -197,9 +198,6 @@ class QueryCache {
|
|||
/// @brief invalidate all queries
|
||||
void invalidate();
|
||||
|
||||
/// @brief hashes a query string
|
||||
uint64_t hashQueryString(char const*, size_t) const;
|
||||
|
||||
/// @brief get the pointer to the global query cache
|
||||
static QueryCache* instance();
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ QueryList::QueryList(TRI_vocbase_t*)
|
|||
/// @brief insert a query
|
||||
bool QueryList::insert(Query* query) {
|
||||
// not enable or no query string
|
||||
if (!_enabled || query == nullptr || query->queryString() == nullptr) {
|
||||
if (!_enabled || query == nullptr || query->queryString().empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ void QueryList::remove(Query* query) {
|
|||
// the list are correct
|
||||
|
||||
// no query string
|
||||
if (query == nullptr || query->queryString() == nullptr) {
|
||||
if (query == nullptr || query->queryString().empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -164,9 +164,7 @@ int QueryList::kill(TRI_voc_tick_t id) {
|
|||
}
|
||||
|
||||
Query* query = (*it).second;
|
||||
StringRef queryString(query->queryString(), query->queryLength());
|
||||
|
||||
LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "killing AQL query " << id << " '" << queryString << "'";
|
||||
LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "killing AQL query " << id << " '" << query->queryString() << "'";
|
||||
|
||||
query->killed(true);
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
|
@ -181,12 +179,10 @@ uint64_t QueryList::killAll(bool silent) {
|
|||
for (auto& it : _current) {
|
||||
Query* query = it.second;
|
||||
|
||||
StringRef queryString(query->queryString(), query->queryLength());
|
||||
|
||||
if (silent) {
|
||||
LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "killing AQL query " << query->id() << " '" << queryString << "'";
|
||||
LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "killing AQL query " << query->id() << " '" << query->queryString() << "'";
|
||||
} else {
|
||||
LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "killing AQL query " << query->id() << " '" << queryString << "'";
|
||||
LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "killing AQL query " << query->id() << " '" << query->queryString() << "'";
|
||||
}
|
||||
|
||||
query->killed(true);
|
||||
|
@ -210,7 +206,7 @@ std::vector<QueryEntryCopy> QueryList::listCurrent() {
|
|||
for (auto const& it : _current) {
|
||||
Query const* query = it.second;
|
||||
|
||||
if (query == nullptr || query->queryString() == nullptr) {
|
||||
if (query == nullptr || query->queryString().empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -251,38 +247,5 @@ void QueryList::clearSlow() {
|
|||
}
|
||||
|
||||
std::string QueryList::extractQueryString(Query const* query, size_t maxLength) const {
|
||||
char const* queryString = query->queryString();
|
||||
size_t length = query->queryLength();
|
||||
|
||||
if (length > maxLength) {
|
||||
std::string q;
|
||||
|
||||
// query string needs truncation
|
||||
length = maxLength;
|
||||
|
||||
// do not create invalid UTF-8 sequences
|
||||
while (length > 0) {
|
||||
uint8_t c = queryString[length - 1];
|
||||
if ((c & 128) == 0) {
|
||||
// single-byte character
|
||||
break;
|
||||
}
|
||||
--length;
|
||||
|
||||
// start of a multi-byte sequence
|
||||
if ((c & 192) == 192) {
|
||||
// decrease length by one more, so we the string contains the
|
||||
// last part of the previous (multi-byte?) sequence
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
q.reserve(length + 3);
|
||||
q.append(queryString, length);
|
||||
q.append("...", 3);
|
||||
return q;
|
||||
}
|
||||
|
||||
// no truncation
|
||||
return std::string(queryString, length);
|
||||
return query->queryString().extract(maxLength);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// 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 Jan Steemann
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "QueryString.h"
|
||||
#include "Basics/fasthash.h"
|
||||
|
||||
using namespace arangodb::aql;
|
||||
|
||||
void QueryString::append(std::string& out) const {
|
||||
if (empty()) {
|
||||
return;
|
||||
}
|
||||
out.append(_data, _length);
|
||||
}
|
||||
|
||||
uint64_t QueryString::hash() {
|
||||
if (!_hashed) {
|
||||
if (_data == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_hash = fasthash64(_data, _length, 0x3123456789abcdef);
|
||||
_hashed = true;
|
||||
}
|
||||
|
||||
return _hash;
|
||||
}
|
||||
|
||||
std::string QueryString::extract(size_t maxLength) const {
|
||||
if (_length <= maxLength) {
|
||||
// no truncation
|
||||
return std::string(_data, _length);
|
||||
}
|
||||
|
||||
// query string needs truncation
|
||||
size_t length = maxLength;
|
||||
|
||||
// do not create invalid UTF-8 sequences
|
||||
while (length > 0) {
|
||||
uint8_t c = _data[length - 1];
|
||||
if ((c & 128) == 0) {
|
||||
// single-byte character
|
||||
break;
|
||||
}
|
||||
--length;
|
||||
|
||||
// start of a multi-byte sequence
|
||||
if ((c & 192) == 192) {
|
||||
// decrease length by one more, so we the string contains the
|
||||
// last part of the previous (multi-byte?) sequence
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string result;
|
||||
result.reserve(length + 3);
|
||||
result.append(_data, length);
|
||||
result.append("...", 3);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @brief extract a region from the query
|
||||
std::string QueryString::extractRegion(int line, int column) const {
|
||||
TRI_ASSERT(_data != nullptr);
|
||||
|
||||
// note: line numbers reported by bison/flex start at 1, columns start at 0
|
||||
int currentLine = 1;
|
||||
int currentColumn = 0;
|
||||
|
||||
char c;
|
||||
char const* p = _data;
|
||||
|
||||
while ((static_cast<size_t>(p - _data) < _length) && (c = *p)) {
|
||||
if (currentLine > line ||
|
||||
(currentLine >= line && currentColumn >= column)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == '\n') {
|
||||
++p;
|
||||
++currentLine;
|
||||
currentColumn = 0;
|
||||
} else if (c == '\r') {
|
||||
++p;
|
||||
++currentLine;
|
||||
currentColumn = 0;
|
||||
|
||||
// eat a following newline
|
||||
if (*p == '\n') {
|
||||
++p;
|
||||
}
|
||||
} else {
|
||||
++currentColumn;
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
// p is pointing at the position in the query the parse error occurred at
|
||||
TRI_ASSERT(p >= _data);
|
||||
|
||||
size_t offset = static_cast<size_t>(p - _data);
|
||||
|
||||
static int const SNIPPET_LENGTH = 32;
|
||||
|
||||
if (_length < offset + SNIPPET_LENGTH) {
|
||||
// return a copy of the region
|
||||
return std::string(_data + offset, _length - offset);
|
||||
}
|
||||
|
||||
// copy query part
|
||||
std::string result;
|
||||
result.reserve(SNIPPET_LENGTH + strlen("..."));
|
||||
result.append(_data + offset, SNIPPET_LENGTH);
|
||||
result.append("...");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace arangodb {
|
||||
namespace aql {
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, QueryString const& queryString) {
|
||||
if (queryString.empty()) {
|
||||
stream << "(empty query)";
|
||||
} else {
|
||||
stream.write(queryString.data(), queryString.length());
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// 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 Jan Steemann
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGOD_AQL_QUERY_STRING_H
|
||||
#define ARANGOD_AQL_QUERY_STRING_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/StringRef.h"
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
namespace arangodb {
|
||||
namespace aql {
|
||||
|
||||
class QueryString {
|
||||
public:
|
||||
QueryString(QueryString const& other) = default;
|
||||
QueryString& operator=(QueryString const& other) = default;
|
||||
|
||||
QueryString(char const* data, size_t length)
|
||||
: _data(data), _length(length), _hash(0), _hashed(false) {}
|
||||
|
||||
explicit QueryString(arangodb::StringRef const& ref)
|
||||
: QueryString(ref.data(), ref.size()) {}
|
||||
|
||||
explicit QueryString(std::string const& val)
|
||||
: QueryString(val.data(), val.size()) {}
|
||||
|
||||
QueryString() : QueryString(nullptr, 0) {}
|
||||
|
||||
~QueryString() = default;
|
||||
|
||||
public:
|
||||
char const* data() const { return _data; }
|
||||
size_t size() const { return _length; }
|
||||
size_t length() const { return _length; }
|
||||
bool empty() const { return (_data == nullptr || _length == 0 || *_data == '\0'); }
|
||||
void append(std::string& out) const;
|
||||
uint64_t hash();
|
||||
std::string extract(size_t maxLength) const;
|
||||
std::string extractRegion(int line, int column) const;
|
||||
|
||||
private:
|
||||
char const* _data;
|
||||
size_t _length;
|
||||
uint64_t _hash;
|
||||
bool _hashed;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream&, QueryString const&);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -170,7 +170,7 @@ void RestAqlHandler::parseQuery() {
|
|||
return;
|
||||
}
|
||||
|
||||
auto query = std::make_unique<Query>(false, _vocbase, queryString.c_str(), queryString.size(),
|
||||
auto query = std::make_unique<Query>(false, _vocbase, QueryString(queryString),
|
||||
std::shared_ptr<VPackBuilder>(), nullptr, PART_MAIN);
|
||||
QueryResult res = query->parse();
|
||||
if (res.code != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -241,8 +241,8 @@ void RestAqlHandler::explainQuery() {
|
|||
VPackBuilder::clone(querySlice.get("options")));
|
||||
|
||||
auto query =
|
||||
std::make_unique<Query>(false, _vocbase, queryString.c_str(),
|
||||
queryString.size(), bindVars, options, PART_MAIN);
|
||||
std::make_unique<Query>(false, _vocbase, QueryString(queryString),
|
||||
bindVars, options, PART_MAIN);
|
||||
QueryResult res = query->explain();
|
||||
if (res.code != TRI_ERROR_NO_ERROR) {
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "failed to instantiate the Query: " << res.details;
|
||||
|
@ -309,8 +309,8 @@ void RestAqlHandler::createQueryFromString() {
|
|||
auto options = std::make_shared<VPackBuilder>(
|
||||
VPackBuilder::clone(querySlice.get("options")));
|
||||
|
||||
auto query = std::make_unique<Query>(false, _vocbase, queryString.c_str(),
|
||||
queryString.size(), bindVars, options,
|
||||
auto query = std::make_unique<Query>(false, _vocbase, QueryString(queryString),
|
||||
bindVars, options,
|
||||
(part == "main" ? PART_MAIN : PART_DEPENDENT));
|
||||
|
||||
try {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#define FLEX_SCANNER
|
||||
#define YY_FLEX_MAJOR_VERSION 2
|
||||
#define YY_FLEX_MINOR_VERSION 6
|
||||
#define YY_FLEX_SUBMINOR_VERSION 0
|
||||
#define YY_FLEX_SUBMINOR_VERSION 1
|
||||
#if YY_FLEX_SUBMINOR_VERSION > 0
|
||||
#define FLEX_BETA
|
||||
#endif
|
||||
|
@ -169,25 +169,13 @@ typedef unsigned int flex_uint32_t;
|
|||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/* The "const" storage-class-modifier is valid. */
|
||||
#define YY_USE_CONST
|
||||
|
||||
#else /* ! __cplusplus */
|
||||
|
||||
/* C99 requires __STDC__ to be defined as 1. */
|
||||
#if defined (__STDC__)
|
||||
|
||||
#define YY_USE_CONST
|
||||
|
||||
#endif /* defined (__STDC__) */
|
||||
#endif /* ! __cplusplus */
|
||||
|
||||
#ifdef YY_USE_CONST
|
||||
/* TODO: this is always defined, so inline it */
|
||||
#define yyconst const
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||
#define yynoreturn __attribute__((__noreturn__))
|
||||
#else
|
||||
#define yyconst
|
||||
#define yynoreturn
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -333,7 +321,7 @@ typedef size_t yy_size_t;
|
|||
|
||||
/* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
|
||||
* access to the local variable yy_act. Since yyless() is a macro, it would break
|
||||
* existing scanners that call yyless() from OUTSIDE Aqllex.
|
||||
* existing scanners that call yyless() from OUTSIDE Aqllex.
|
||||
* One obvious solution it to make yy_act a global. I tried that, and saw
|
||||
* a 5% performance hit in a non-yylineno scanner, because yy_act is
|
||||
* normally declared as a variable-- so it is not worth it.
|
||||
|
@ -389,7 +377,7 @@ struct yy_buffer_state
|
|||
/* Size of input buffer in bytes, not including room for EOB
|
||||
* characters.
|
||||
*/
|
||||
yy_size_t yy_buf_size;
|
||||
int yy_buf_size;
|
||||
|
||||
/* Number of characters read into yy_ch_buf, not including EOB
|
||||
* characters.
|
||||
|
@ -417,7 +405,7 @@ struct yy_buffer_state
|
|||
|
||||
int yy_bs_lineno; /**< The line count. */
|
||||
int yy_bs_column; /**< The column count. */
|
||||
|
||||
|
||||
|
||||
/* Whether to try to fill the input buffer when we reach the
|
||||
* end of it.
|
||||
|
@ -489,7 +477,7 @@ static void Aql_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
|
|||
|
||||
YY_BUFFER_STATE Aql_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
|
||||
YY_BUFFER_STATE Aql_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
|
||||
YY_BUFFER_STATE Aql_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner );
|
||||
YY_BUFFER_STATE Aql_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
|
||||
|
||||
|
||||
void *Aqlalloc (yy_size_t ,yyscan_t yyscanner );
|
||||
|
@ -550,10 +538,7 @@ typedef int yy_state_type;
|
|||
static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
|
||||
static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
|
||||
static int yy_get_next_buffer (yyscan_t yyscanner );
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||
__attribute__((__noreturn__))
|
||||
#endif
|
||||
static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
|
||||
static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
|
||||
|
||||
|
||||
|
||||
|
@ -563,7 +548,7 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
|
|||
*/
|
||||
#define YY_DO_BEFORE_ACTION \
|
||||
yyg->yytext_ptr = yy_bp; \
|
||||
yyleng = (size_t) (yy_cp - yy_bp); \
|
||||
yyleng = (int) (yy_cp - yy_bp); \
|
||||
yyg->yy_hold_char = *yy_cp; \
|
||||
*yy_cp = '\0'; \
|
||||
yyg->yy_c_buf_p = yy_cp;
|
||||
|
@ -987,7 +972,7 @@ struct yyguts_t
|
|||
YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
|
||||
char yy_hold_char;
|
||||
int yy_n_chars;
|
||||
yy_size_t yyleng_r;
|
||||
int yyleng_r;
|
||||
char *yy_c_buf_p;
|
||||
int yy_init;
|
||||
int yy_start;
|
||||
|
@ -1084,7 +1069,7 @@ void Aqlset_out (FILE * _out_str ,yyscan_t yyscanner );
|
|||
|
||||
|
||||
|
||||
yy_size_t Aqlget_leng (yyscan_t yyscanner );
|
||||
int Aqlget_leng (yyscan_t yyscanner );
|
||||
|
||||
|
||||
|
||||
|
@ -1186,7 +1171,7 @@ static int input (yyscan_t yyscanner );
|
|||
/* This used to be an fputs(), but since the string might contain NUL's,
|
||||
* we now use fwrite().
|
||||
*/
|
||||
#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
|
||||
#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1212,7 +1197,7 @@ static int input (yyscan_t yyscanner );
|
|||
else \
|
||||
{ \
|
||||
errno=0; \
|
||||
while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
|
||||
while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
|
||||
{ \
|
||||
if( errno != EINTR) \
|
||||
{ \
|
||||
|
@ -1391,7 +1376,7 @@ yy_match:
|
|||
if ( yy_current_state >= 259 )
|
||||
yy_c = yy_meta[(unsigned int) yy_c];
|
||||
}
|
||||
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
|
||||
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
|
||||
++yy_cp;
|
||||
}
|
||||
while ( yy_current_state != 258 );
|
||||
|
@ -1406,10 +1391,10 @@ yy_find_action:
|
|||
|
||||
if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
|
||||
{
|
||||
yy_size_t yyl;
|
||||
size_t yyl;
|
||||
for ( yyl = 0; yyl < yyleng; ++yyl )
|
||||
if ( yytext[yyl] == '\n' )
|
||||
|
||||
|
||||
do{ yylineno++;
|
||||
yycolumn=0;
|
||||
}while(0)
|
||||
|
@ -1820,7 +1805,7 @@ case 63:
|
|||
YY_RULE_SETUP
|
||||
{
|
||||
/* string enclosed in backticks */
|
||||
yyextra->marker(yyextra->queryString() + yyextra->offset());
|
||||
yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
|
||||
BEGIN(BACKTICK);
|
||||
}
|
||||
YY_BREAK
|
||||
|
@ -1830,7 +1815,7 @@ YY_RULE_SETUP
|
|||
/* end of backtick-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
size_t outLength;
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, outLength);
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 1, outLength);
|
||||
yylval->strval.length = outLength;
|
||||
return T_STRING;
|
||||
}
|
||||
|
@ -1858,7 +1843,7 @@ case 68:
|
|||
YY_RULE_SETUP
|
||||
{
|
||||
/* string enclosed in forwardticks */
|
||||
yyextra->marker(yyextra->queryString() + yyextra->offset());
|
||||
yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
|
||||
BEGIN(FORWARDTICK);
|
||||
}
|
||||
YY_BREAK
|
||||
|
@ -1868,7 +1853,7 @@ YY_RULE_SETUP
|
|||
/* end of forwardtick-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
size_t outLength;
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 2, outLength);
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 2, outLength);
|
||||
yylval->strval.length = outLength;
|
||||
return T_STRING;
|
||||
}
|
||||
|
@ -1898,7 +1883,7 @@ YY_RULE_SETUP
|
|||
case 73:
|
||||
YY_RULE_SETUP
|
||||
{
|
||||
yyextra->marker(yyextra->queryString() + yyextra->offset());
|
||||
yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
|
||||
BEGIN(DOUBLE_QUOTE);
|
||||
}
|
||||
YY_BREAK
|
||||
|
@ -1908,7 +1893,7 @@ YY_RULE_SETUP
|
|||
/* end of quote-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
size_t outLength;
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, outLength);
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 1, outLength);
|
||||
yylval->strval.length = outLength;
|
||||
return T_QUOTED_STRING;
|
||||
}
|
||||
|
@ -1935,7 +1920,7 @@ YY_RULE_SETUP
|
|||
case 78:
|
||||
YY_RULE_SETUP
|
||||
{
|
||||
yyextra->marker(yyextra->queryString() + yyextra->offset());
|
||||
yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
|
||||
BEGIN(SINGLE_QUOTE);
|
||||
}
|
||||
YY_BREAK
|
||||
|
@ -1945,7 +1930,7 @@ YY_RULE_SETUP
|
|||
/* end of quote-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
size_t outLength;
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, outLength);
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 1, outLength);
|
||||
yylval->strval.length = outLength;
|
||||
return T_QUOTED_STRING;
|
||||
}
|
||||
|
@ -2312,7 +2297,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
|
|||
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
|
||||
char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
|
||||
char *source = yyg->yytext_ptr;
|
||||
yy_size_t number_to_move, i;
|
||||
int number_to_move, i;
|
||||
int ret_val;
|
||||
|
||||
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
|
||||
|
@ -2341,7 +2326,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
|
|||
/* Try to read more data. */
|
||||
|
||||
/* First move last chars to start of buffer. */
|
||||
number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
|
||||
number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
|
||||
|
||||
for ( i = 0; i < number_to_move; ++i )
|
||||
*(dest++) = *(source++);
|
||||
|
@ -2354,7 +2339,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
|
|||
|
||||
else
|
||||
{
|
||||
yy_size_t num_to_read =
|
||||
int num_to_read =
|
||||
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
|
||||
|
||||
while ( num_to_read <= 0 )
|
||||
|
@ -2368,7 +2353,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
|
|||
|
||||
if ( b->yy_is_our_buffer )
|
||||
{
|
||||
yy_size_t new_size = b->yy_buf_size * 2;
|
||||
int new_size = b->yy_buf_size * 2;
|
||||
|
||||
if ( new_size <= 0 )
|
||||
b->yy_buf_size += b->yy_buf_size / 8;
|
||||
|
@ -2381,7 +2366,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
|
|||
}
|
||||
else
|
||||
/* Can't grow it, we don't own it. */
|
||||
b->yy_ch_buf = 0;
|
||||
b->yy_ch_buf = NULL;
|
||||
|
||||
if ( ! b->yy_ch_buf )
|
||||
YY_FATAL_ERROR(
|
||||
|
@ -2423,7 +2408,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
|
|||
else
|
||||
ret_val = EOB_ACT_CONTINUE_SCAN;
|
||||
|
||||
if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
|
||||
if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
|
||||
/* Extend the array by 50%, plus the number we really need. */
|
||||
int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
|
||||
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) Aqlrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
|
||||
|
@ -2466,7 +2451,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
|
|||
if ( yy_current_state >= 259 )
|
||||
yy_c = yy_meta[(unsigned int) yy_c];
|
||||
}
|
||||
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
|
||||
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
|
||||
}
|
||||
|
||||
return yy_current_state;
|
||||
|
@ -2496,7 +2481,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
|
|||
if ( yy_current_state >= 259 )
|
||||
yy_c = yy_meta[(unsigned int) yy_c];
|
||||
}
|
||||
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
|
||||
yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
|
||||
yy_is_jam = (yy_current_state == 258);
|
||||
|
||||
(void)yyg;
|
||||
|
@ -2533,7 +2518,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
|
|||
|
||||
else
|
||||
{ /* need more input */
|
||||
yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
|
||||
int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
|
||||
++yyg->yy_c_buf_p;
|
||||
|
||||
switch ( yy_get_next_buffer( yyscanner ) )
|
||||
|
@ -2557,7 +2542,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
|
|||
case EOB_ACT_END_OF_FILE:
|
||||
{
|
||||
if ( Aqlwrap(yyscanner ) )
|
||||
return EOF;
|
||||
return 0;
|
||||
|
||||
if ( ! yyg->yy_did_buffer_switch_on_eof )
|
||||
YY_NEW_FILE;
|
||||
|
@ -2580,7 +2565,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
|
|||
yyg->yy_hold_char = *++yyg->yy_c_buf_p;
|
||||
|
||||
if ( c == '\n' )
|
||||
|
||||
|
||||
do{ yylineno++;
|
||||
yycolumn=0;
|
||||
}while(0)
|
||||
|
@ -2829,7 +2814,7 @@ void Aqlpop_buffer_state (yyscan_t yyscanner)
|
|||
*/
|
||||
static void Aqlensure_buffer_stack (yyscan_t yyscanner)
|
||||
{
|
||||
yy_size_t num_to_alloc;
|
||||
int num_to_alloc;
|
||||
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
|
||||
|
||||
if (!yyg->yy_buffer_stack) {
|
||||
|
@ -2838,16 +2823,16 @@ static void Aqlensure_buffer_stack (yyscan_t yyscanner)
|
|||
* scanner will even need a stack. We use 2 instead of 1 to avoid an
|
||||
* immediate realloc on the next call.
|
||||
*/
|
||||
num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
|
||||
num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
|
||||
yyg->yy_buffer_stack = (struct yy_buffer_state**)Aqlalloc
|
||||
(num_to_alloc * sizeof(struct yy_buffer_state*)
|
||||
, yyscanner);
|
||||
if ( ! yyg->yy_buffer_stack )
|
||||
YY_FATAL_ERROR( "out of dynamic memory in Aqlensure_buffer_stack()" );
|
||||
|
||||
|
||||
|
||||
|
||||
memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
|
||||
|
||||
|
||||
yyg->yy_buffer_stack_max = num_to_alloc;
|
||||
yyg->yy_buffer_stack_top = 0;
|
||||
return;
|
||||
|
@ -2880,7 +2865,7 @@ static void Aqlensure_buffer_stack (yyscan_t yyscanner)
|
|||
* @param base the character buffer
|
||||
* @param size the size in bytes of the character buffer
|
||||
* @param yyscanner The scanner object.
|
||||
* @return the newly allocated buffer state object.
|
||||
* @return the newly allocated buffer state object.
|
||||
*/
|
||||
YY_BUFFER_STATE Aql_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
|
||||
{
|
||||
|
@ -2890,7 +2875,7 @@ YY_BUFFER_STATE Aql_scan_buffer (char * base, yy_size_t size , yyscan_t yyscan
|
|||
base[size-2] != YY_END_OF_BUFFER_CHAR ||
|
||||
base[size-1] != YY_END_OF_BUFFER_CHAR )
|
||||
/* They forgot to leave room for the EOB's. */
|
||||
return 0;
|
||||
return NULL;
|
||||
|
||||
b = (YY_BUFFER_STATE) Aqlalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
|
||||
if ( ! b )
|
||||
|
@ -2899,7 +2884,7 @@ YY_BUFFER_STATE Aql_scan_buffer (char * base, yy_size_t size , yyscan_t yyscan
|
|||
b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
|
||||
b->yy_buf_pos = b->yy_ch_buf = base;
|
||||
b->yy_is_our_buffer = 0;
|
||||
b->yy_input_file = 0;
|
||||
b->yy_input_file = NULL;
|
||||
b->yy_n_chars = b->yy_buf_size;
|
||||
b->yy_is_interactive = 0;
|
||||
b->yy_at_bol = 1;
|
||||
|
@ -2925,7 +2910,7 @@ YY_BUFFER_STATE Aql_scan_buffer (char * base, yy_size_t size , yyscan_t yyscan
|
|||
YY_BUFFER_STATE Aql_scan_string (yyconst char * yystr , yyscan_t yyscanner)
|
||||
{
|
||||
|
||||
return Aql_scan_bytes(yystr,strlen(yystr) ,yyscanner);
|
||||
return Aql_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2938,15 +2923,15 @@ YY_BUFFER_STATE Aql_scan_string (yyconst char * yystr , yyscan_t yyscanner)
|
|||
* @param yyscanner The scanner object.
|
||||
* @return the newly allocated buffer state object.
|
||||
*/
|
||||
YY_BUFFER_STATE Aql_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner)
|
||||
YY_BUFFER_STATE Aql_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
|
||||
{
|
||||
YY_BUFFER_STATE b;
|
||||
char *buf;
|
||||
yy_size_t n;
|
||||
yy_size_t i;
|
||||
int i;
|
||||
|
||||
/* Get memory for full buffer, including space for trailing EOB's. */
|
||||
n = _yybytes_len + 2;
|
||||
n = (yy_size_t) (_yybytes_len + 2);
|
||||
buf = (char *) Aqlalloc(n ,yyscanner );
|
||||
if ( ! buf )
|
||||
YY_FATAL_ERROR( "out of dynamic memory in Aql_scan_bytes()" );
|
||||
|
@ -2982,7 +2967,7 @@ YY_BUFFER_STATE Aql_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len
|
|||
#define YY_EXIT_FAILURE 2
|
||||
#endif
|
||||
|
||||
static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
|
||||
static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
|
||||
{
|
||||
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
|
||||
(void)yyg;
|
||||
|
@ -3029,7 +3014,7 @@ YY_EXTRA_TYPE Aqlget_extra (yyscan_t yyscanner)
|
|||
int Aqlget_lineno (yyscan_t yyscanner)
|
||||
{
|
||||
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
|
||||
|
||||
|
||||
|
||||
if (! YY_CURRENT_BUFFER)
|
||||
return 0;
|
||||
|
@ -3046,7 +3031,7 @@ int Aqlget_lineno (yyscan_t yyscanner)
|
|||
int Aqlget_column (yyscan_t yyscanner)
|
||||
{
|
||||
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
|
||||
|
||||
|
||||
|
||||
if (! YY_CURRENT_BUFFER)
|
||||
return 0;
|
||||
|
@ -3082,7 +3067,7 @@ FILE *Aqlget_out (yyscan_t yyscanner)
|
|||
/** Get the length of the current token.
|
||||
* @param yyscanner The scanner object.
|
||||
*/
|
||||
yy_size_t Aqlget_leng (yyscan_t yyscanner)
|
||||
int Aqlget_leng (yyscan_t yyscanner)
|
||||
{
|
||||
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
|
||||
return yyleng;
|
||||
|
@ -3276,20 +3261,20 @@ int Aqllex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
|
|||
errno = EINVAL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
*ptr_yy_globals = (yyscan_t) Aqlalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
|
||||
|
||||
|
||||
if (*ptr_yy_globals == NULL){
|
||||
errno = ENOMEM;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* By setting to 0xAA, we expose bugs in
|
||||
yy_init_globals. Leave at 0x00 for releases. */
|
||||
memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
|
||||
|
||||
|
||||
Aqlset_extra (yy_user_defined, *ptr_yy_globals);
|
||||
|
||||
|
||||
return yy_init_globals ( *ptr_yy_globals );
|
||||
}
|
||||
|
||||
|
@ -3304,10 +3289,10 @@ static int yy_init_globals (yyscan_t yyscanner)
|
|||
|
||||
|
||||
|
||||
yyg->yy_buffer_stack = 0;
|
||||
yyg->yy_buffer_stack = NULL;
|
||||
yyg->yy_buffer_stack_top = 0;
|
||||
yyg->yy_buffer_stack_max = 0;
|
||||
yyg->yy_c_buf_p = (char *) 0;
|
||||
yyg->yy_c_buf_p = NULL;
|
||||
yyg->yy_init = 0;
|
||||
yyg->yy_start = 0;
|
||||
|
||||
|
@ -3326,8 +3311,8 @@ static int yy_init_globals (yyscan_t yyscanner)
|
|||
yyin = stdin;
|
||||
yyout = stdout;
|
||||
#else
|
||||
yyin = (FILE *) 0;
|
||||
yyout = (FILE *) 0;
|
||||
yyin = NULL;
|
||||
yyout = NULL;
|
||||
#endif
|
||||
|
||||
/* For future reference: Set errno on error, since we are called by
|
||||
|
@ -3410,7 +3395,7 @@ void *Aqlalloc (yy_size_t size , yyscan_t yyscanner)
|
|||
{
|
||||
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
|
||||
(void)yyg;
|
||||
return (void *) malloc( size );
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3427,7 +3412,7 @@ void *Aqlrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
|
|||
* any pointer type to void*, and deal with argument conversions
|
||||
* as though doing an assignment.
|
||||
*/
|
||||
return (void *) realloc( (char *) ptr, size );
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -333,7 +333,7 @@ namespace arangodb {
|
|||
|
||||
<INITIAL>` {
|
||||
/* string enclosed in backticks */
|
||||
yyextra->marker(yyextra->queryString() + yyextra->offset());
|
||||
yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
|
||||
BEGIN(BACKTICK);
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,7 @@ namespace arangodb {
|
|||
/* end of backtick-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
size_t outLength;
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, outLength);
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 1, outLength);
|
||||
yylval->strval.length = outLength;
|
||||
return T_STRING;
|
||||
}
|
||||
|
@ -361,7 +361,7 @@ namespace arangodb {
|
|||
|
||||
<INITIAL>´ {
|
||||
/* string enclosed in forwardticks */
|
||||
yyextra->marker(yyextra->queryString() + yyextra->offset());
|
||||
yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
|
||||
BEGIN(FORWARDTICK);
|
||||
}
|
||||
|
||||
|
@ -369,7 +369,7 @@ namespace arangodb {
|
|||
/* end of forwardtick-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
size_t outLength;
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 2, outLength);
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 2, outLength);
|
||||
yylval->strval.length = outLength;
|
||||
return T_STRING;
|
||||
}
|
||||
|
@ -391,7 +391,7 @@ namespace arangodb {
|
|||
* --------------------------------------------------------------------------- */
|
||||
|
||||
<INITIAL>\" {
|
||||
yyextra->marker(yyextra->queryString() + yyextra->offset());
|
||||
yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
|
||||
BEGIN(DOUBLE_QUOTE);
|
||||
}
|
||||
|
||||
|
@ -399,7 +399,7 @@ namespace arangodb {
|
|||
/* end of quote-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
size_t outLength;
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, outLength);
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 1, outLength);
|
||||
yylval->strval.length = outLength;
|
||||
return T_QUOTED_STRING;
|
||||
}
|
||||
|
@ -417,7 +417,7 @@ namespace arangodb {
|
|||
}
|
||||
|
||||
<INITIAL>' {
|
||||
yyextra->marker(yyextra->queryString() + yyextra->offset());
|
||||
yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
|
||||
BEGIN(SINGLE_QUOTE);
|
||||
}
|
||||
|
||||
|
@ -425,7 +425,7 @@ namespace arangodb {
|
|||
/* end of quote-enclosed string */
|
||||
BEGIN(INITIAL);
|
||||
size_t outLength;
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, outLength);
|
||||
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 1, outLength);
|
||||
yylval->strval.length = outLength;
|
||||
return T_QUOTED_STRING;
|
||||
}
|
||||
|
|
|
@ -153,6 +153,7 @@ SET(ARANGOD_SOURCES
|
|||
Aql/QueryList.cpp
|
||||
Aql/QueryRegistry.cpp
|
||||
Aql/QueryResources.cpp
|
||||
Aql/QueryString.cpp
|
||||
Aql/Range.cpp
|
||||
Aql/RestAqlHandler.cpp
|
||||
Aql/Scopes.cpp
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "Aql/AqlTransaction.h"
|
||||
#include "Aql/Ast.h"
|
||||
#include "Aql/Query.h"
|
||||
#include "Aql/QueryString.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Graph/EdgeCursor.h"
|
||||
#include "Graph/ShortestPathOptions.h"
|
||||
|
@ -105,7 +106,7 @@ BaseEngine::BaseEngine(TRI_vocbase_t* vocbase, VPackSlice info)
|
|||
// created transaction is considered a "MAIN" part and will not switch
|
||||
// off collection locking completely!
|
||||
_query =
|
||||
new aql::Query(true, vocbase, "", 0, params, opts, aql::PART_DEPENDENT);
|
||||
new aql::Query(true, vocbase, aql::QueryString(), params, opts, aql::PART_DEPENDENT);
|
||||
_query->injectTransaction(_trx);
|
||||
|
||||
VPackSlice variablesSlice = info.get(VARIABLES);
|
||||
|
|
|
@ -113,8 +113,8 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
|
|||
VPackValueLength l;
|
||||
char const* queryString = querySlice.getString(l);
|
||||
|
||||
arangodb::aql::Query query(false, _vocbase, queryString,
|
||||
static_cast<size_t>(l), bindVarsBuilder, options,
|
||||
arangodb::aql::Query query(false, _vocbase, arangodb::aql::QueryString(queryString, static_cast<size_t>(l)),
|
||||
bindVarsBuilder, options,
|
||||
arangodb::aql::PART_MAIN);
|
||||
|
||||
registerQuery(&query);
|
||||
|
|
|
@ -128,10 +128,7 @@ bool RestQueryHandler::readQuery(bool slow) {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns AQL query tracking
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestQueryHandler::readQuery() {
|
||||
auto const& suffixes = _request->suffixes();
|
||||
|
||||
|
@ -197,10 +194,7 @@ bool RestQueryHandler::deleteQuery(std::string const& name) {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief interrupts a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestQueryHandler::deleteQuery() {
|
||||
auto const& suffixes = _request->suffixes();
|
||||
|
||||
|
@ -315,7 +309,7 @@ bool RestQueryHandler::parseQuery() {
|
|||
std::string const&& queryString =
|
||||
VelocyPackHelper::checkAndGetStringValue(body, "query");
|
||||
|
||||
Query query(true, _vocbase, queryString.c_str(), queryString.size(),
|
||||
Query query(true, _vocbase, QueryString(queryString),
|
||||
nullptr, nullptr, PART_MAIN);
|
||||
|
||||
auto parseResult = query.parse();
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "RestSimpleHandler.h"
|
||||
#include "Aql/Query.h"
|
||||
#include "Aql/QueryRegistry.h"
|
||||
#include "Aql/QueryString.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Basics/MutexLocker.h"
|
||||
#include "Basics/ScopeGuard.h"
|
||||
|
@ -221,7 +222,7 @@ void RestSimpleHandler::removeByKeys(VPackSlice const& slice) {
|
|||
}
|
||||
}
|
||||
|
||||
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(),
|
||||
arangodb::aql::Query query(false, _vocbase, arangodb::aql::QueryString(aql),
|
||||
bindVars, nullptr, arangodb::aql::PART_MAIN);
|
||||
|
||||
registerQuery(&query);
|
||||
|
@ -333,7 +334,7 @@ void RestSimpleHandler::lookupByKeys(VPackSlice const& slice) {
|
|||
std::string const aql(
|
||||
"FOR doc IN @@collection FILTER doc._key IN @keys RETURN doc");
|
||||
|
||||
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(),
|
||||
arangodb::aql::Query query(false, _vocbase, aql::QueryString(aql),
|
||||
bindVars, nullptr, arangodb::aql::PART_MAIN);
|
||||
|
||||
registerQuery(&query);
|
||||
|
|
|
@ -71,6 +71,34 @@ void uint64ToPersistent(std::string& p, uint64_t value) {
|
|||
} while (++len < sizeof(uint64_t));
|
||||
}
|
||||
|
||||
uint32_t uint32FromPersistent(char const* p) {
|
||||
uint32_t value = 0;
|
||||
uint32_t x = 0;
|
||||
uint8_t const* ptr = reinterpret_cast<uint8_t const*>(p);
|
||||
uint8_t const* end = ptr + sizeof(uint32_t);
|
||||
do {
|
||||
value += static_cast<uint16_t>(*ptr++) << x;
|
||||
x += 8;
|
||||
} while (ptr < end);
|
||||
return value;
|
||||
}
|
||||
|
||||
void uint32ToPersistent(char* p, uint32_t value) {
|
||||
char* end = p + sizeof(uint32_t);
|
||||
do {
|
||||
*p++ = static_cast<uint8_t>(value & 0xffU);
|
||||
value >>= 8;
|
||||
} while (p < end);
|
||||
}
|
||||
|
||||
void uint32ToPersistent(std::string& p, uint32_t value) {
|
||||
size_t len = 0;
|
||||
do {
|
||||
p.push_back(static_cast<char>(value & 0xffU));
|
||||
value >>= 8;
|
||||
} while (++len < sizeof(uint32_t));
|
||||
}
|
||||
|
||||
uint16_t uint16FromPersistent(char const* p) {
|
||||
uint16_t value = 0;
|
||||
uint16_t x = 0;
|
||||
|
|
|
@ -82,6 +82,10 @@ uint64_t uint64FromPersistent(char const* p);
|
|||
void uint64ToPersistent(char* p, uint64_t value);
|
||||
void uint64ToPersistent(std::string& out, uint64_t value);
|
||||
|
||||
uint32_t uint32FromPersistent(char const* p);
|
||||
void uint32ToPersistent(char* p, uint32_t value);
|
||||
void uint32ToPersistent(std::string& out, uint32_t value);
|
||||
|
||||
uint16_t uint16FromPersistent(char const* p);
|
||||
void uint16ToPersistent(char* p, uint16_t value);
|
||||
void uint16ToPersistent(std::string& out, uint16_t value);
|
||||
|
|
|
@ -356,11 +356,20 @@ void RocksDBCounterManager::readIndexEstimates() {
|
|||
iter->value().size() - sizeof(uint64_t));
|
||||
// If this hits we have two estimates for the same index
|
||||
TRI_ASSERT(_estimators.find(objectId) == _estimators.end());
|
||||
_estimators.emplace(
|
||||
objectId,
|
||||
std::make_pair(lastSeqNumber,
|
||||
std::make_unique<RocksDBCuckooIndexEstimator<uint64_t>>(
|
||||
estimateSerialisation)));
|
||||
try {
|
||||
if (RocksDBCuckooIndexEstimator<uint64_t>::isFormatSupported(estimateSerialisation)) {
|
||||
_estimators.emplace(
|
||||
objectId,
|
||||
std::make_pair(
|
||||
lastSeqNumber,
|
||||
std::make_unique<RocksDBCuckooIndexEstimator<uint64_t>>(
|
||||
estimateSerialisation)));
|
||||
}
|
||||
} catch (...) {
|
||||
// Nothing to do, if the estimator fails to create we let it be recreated.
|
||||
// Just validate that no corrupted memory was produced.
|
||||
TRI_ASSERT(_estimators.find(objectId) == _estimators.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -421,11 +430,12 @@ struct WBReader final : public rocksdb::WriteBatch::Handler {
|
|||
uint64_t _maxTick = 0;
|
||||
uint64_t _maxHLC = 0;
|
||||
|
||||
explicit WBReader(std::unordered_map<
|
||||
uint64_t,
|
||||
std::pair<uint64_t,
|
||||
std::unique_ptr<RocksDBCuckooIndexEstimator<uint64_t>>>>*
|
||||
estimators)
|
||||
explicit WBReader(
|
||||
std::unordered_map<
|
||||
uint64_t,
|
||||
std::pair<uint64_t,
|
||||
std::unique_ptr<RocksDBCuckooIndexEstimator<uint64_t>>>>*
|
||||
estimators)
|
||||
: _estimators(estimators), currentSeqNum(0) {}
|
||||
|
||||
~WBReader() {
|
||||
|
|
|
@ -67,13 +67,17 @@ class RocksDBCuckooIndexEstimator {
|
|||
static constexpr uint32_t SlotsPerBucket = 4;
|
||||
|
||||
private:
|
||||
// Helper class to abstract away where which data is stored.
|
||||
// Helper class to hold the finger prints.
|
||||
// Fingerprints are 64bit aligned and we
|
||||
// have 4 slots per 64bit bucket.
|
||||
struct Slot {
|
||||
private:
|
||||
uint16_t* _data;
|
||||
|
||||
uint32_t* _counter;
|
||||
|
||||
public:
|
||||
explicit Slot(uint16_t* data) : _data(data) {}
|
||||
explicit Slot(uint16_t* data) : _data(data), _counter(nullptr) {}
|
||||
|
||||
~Slot() {
|
||||
// Not responsible for anything
|
||||
|
@ -81,9 +85,14 @@ class RocksDBCuckooIndexEstimator {
|
|||
|
||||
bool operator==(const Slot& other) { return _data == other._data; }
|
||||
|
||||
uint16_t* fingerprint() const { return _data; }
|
||||
|
||||
uint16_t* counter() { return _data + 1; }
|
||||
uint16_t* fingerprint() const {
|
||||
TRI_ASSERT(_data != nullptr);
|
||||
return _data;
|
||||
}
|
||||
uint32_t* counter() const {
|
||||
TRI_ASSERT(_counter != nullptr);
|
||||
return _counter;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
*fingerprint() = 0;
|
||||
|
@ -93,22 +102,71 @@ class RocksDBCuckooIndexEstimator {
|
|||
bool isEqual(uint16_t fp) const { return ((*fingerprint()) == fp); }
|
||||
|
||||
bool isEmpty() const { return (*fingerprint()) == 0; }
|
||||
|
||||
// If this returns FALSE we have removed the
|
||||
// last element => we need to remove the fingerprint as well.
|
||||
bool decrease() {
|
||||
if (*counter() > 1) {
|
||||
(*counter())--;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void increase() {
|
||||
if ((*counter()) < UINT32_MAX) {
|
||||
(*counter())++;
|
||||
}
|
||||
}
|
||||
|
||||
void init(uint16_t fp) {
|
||||
// This is the first element
|
||||
*fingerprint() = fp;
|
||||
*counter() = 1;
|
||||
}
|
||||
|
||||
void swap(uint16_t& fp, uint32_t& cnt) {
|
||||
std::swap(*fingerprint(), fp);
|
||||
std::swap(*counter(), cnt);
|
||||
}
|
||||
|
||||
void injectCounter(uint32_t* cnt) { _counter = cnt; }
|
||||
};
|
||||
|
||||
enum SerializeFormat : char {
|
||||
// To describe this format we use | as a seperator for readability, but it
|
||||
// is NOT a printed character in the serialized string
|
||||
// NOCOMPRESSION: type|length|size|nrUsed|nrCuckood|nrTotal|niceSize|logSize|base
|
||||
NOCOMPRESSION = '0'
|
||||
// NOCOMPRESSION:
|
||||
// type|length|size|nrUsed|nrCuckood|nrTotal|niceSize|logSize|base|counters
|
||||
NOCOMPRESSION = '1'
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
static bool isFormatSupported(StringRef serialized) {
|
||||
switch (serialized.front()) {
|
||||
case SerializeFormat::NOCOMPRESSION:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RocksDBCuckooIndexEstimator(uint64_t size)
|
||||
: _randState(0x2636283625154737ULL),
|
||||
_slotSize(2 * sizeof(uint16_t)), // Sort out offsets and alignments
|
||||
_slotSize(sizeof(uint16_t)), // Sort out offsets and alignments
|
||||
_counterSize(sizeof(uint32_t)), // Sort out offsets and alignments
|
||||
_logSize(0),
|
||||
_size(0),
|
||||
_niceSize(0),
|
||||
_sizeMask(0),
|
||||
_sizeShift(0),
|
||||
_slotAllocSize(0),
|
||||
_counterAllocSize(0),
|
||||
_base(nullptr),
|
||||
_allocBase(nullptr),
|
||||
_slotBase(nullptr),
|
||||
_counters(nullptr),
|
||||
_counterBase(nullptr),
|
||||
_nrUsed(0),
|
||||
_nrCuckood(0),
|
||||
_nrTotal(0),
|
||||
|
@ -125,9 +183,19 @@ class RocksDBCuckooIndexEstimator {
|
|||
|
||||
RocksDBCuckooIndexEstimator(arangodb::StringRef const serialized)
|
||||
: _randState(0x2636283625154737ULL),
|
||||
_slotSize(2 * sizeof(uint16_t)), // Sort out offsets and alignments
|
||||
_slotSize(sizeof(uint16_t)), // Sort out offsets and alignments
|
||||
_counterSize(sizeof(uint32_t)), // Sort out offsets and alignments
|
||||
_logSize(0),
|
||||
_size(0),
|
||||
_niceSize(0),
|
||||
_sizeMask(0),
|
||||
_sizeShift(0),
|
||||
_slotAllocSize(0),
|
||||
_counterAllocSize(0),
|
||||
_base(nullptr),
|
||||
_allocBase(nullptr),
|
||||
_slotBase(nullptr),
|
||||
_counters(nullptr),
|
||||
_counterBase(nullptr),
|
||||
_nrUsed(0),
|
||||
_nrCuckood(0),
|
||||
_nrTotal(0),
|
||||
|
@ -138,14 +206,18 @@ class RocksDBCuckooIndexEstimator {
|
|||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_TOPIC(ERR, arangodb::Logger::ENGINES) <<
|
||||
"unable to restore index estimates: invalid format found";
|
||||
initializeDefault();
|
||||
LOG_TOPIC(WARN, arangodb::Logger::ENGINES)
|
||||
<< "unable to restore index estimates: invalid format found";
|
||||
// Do not construct from serialisation, use other constructor instead
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~RocksDBCuckooIndexEstimator() { delete[] _allocBase; }
|
||||
~RocksDBCuckooIndexEstimator() {
|
||||
delete[] _slotBase;
|
||||
delete[] _counterBase;
|
||||
}
|
||||
|
||||
RocksDBCuckooIndexEstimator(RocksDBCuckooIndexEstimator const&) = delete;
|
||||
RocksDBCuckooIndexEstimator(RocksDBCuckooIndexEstimator&&) = delete;
|
||||
|
@ -162,16 +234,19 @@ class RocksDBCuckooIndexEstimator {
|
|||
serialized += SerializeFormat::NOCOMPRESSION;
|
||||
|
||||
uint64_t serialLength =
|
||||
(sizeof(SerializeFormat) + sizeof(uint64_t) + sizeof(_size) + sizeof(_nrUsed) +
|
||||
sizeof(_nrCuckood) + sizeof(_nrTotal) + sizeof(_niceSize) +
|
||||
sizeof(_logSize) + (_size * _slotSize * SlotsPerBucket));
|
||||
(sizeof(SerializeFormat) + sizeof(uint64_t) + sizeof(_size) +
|
||||
sizeof(_nrUsed) + sizeof(_nrCuckood) + sizeof(_nrTotal) +
|
||||
sizeof(_niceSize) + sizeof(_logSize) +
|
||||
(_size * _slotSize * SlotsPerBucket)) +
|
||||
(_size * _counterSize * SlotsPerBucket);
|
||||
|
||||
serialized.reserve(sizeof(uint64_t) + serialLength);
|
||||
// We always prepend the length, so parsing is easier
|
||||
rocksutils::uint64ToPersistent(serialized, serialLength);
|
||||
|
||||
{
|
||||
// Sorry we need a consistent state, so we have to read-lock from here on...
|
||||
// Sorry we need a consistent state, so we have to read-lock from here
|
||||
// on...
|
||||
READ_LOCKER(locker, _bucketLock);
|
||||
// Add all member variables
|
||||
rocksutils::uint64ToPersistent(serialized, _size);
|
||||
|
@ -183,12 +258,22 @@ class RocksDBCuckooIndexEstimator {
|
|||
|
||||
// Add the data blob
|
||||
// Size is as follows: nrOfBuckets * SlotsPerBucket * SlotSize
|
||||
TRI_ASSERT((_size * _slotSize * SlotsPerBucket) <= _allocSize);
|
||||
|
||||
for (uint64_t i = 0; i < (_size * _slotSize * SlotsPerBucket) / sizeof(uint16_t);
|
||||
++i) {
|
||||
rocksutils::uint16ToPersistent(serialized, *(reinterpret_cast<uint16_t*>(_base + i * 2)));
|
||||
TRI_ASSERT((_size * _slotSize * SlotsPerBucket) <= _slotAllocSize);
|
||||
|
||||
for (uint64_t i = 0;
|
||||
i < (_size * _slotSize * SlotsPerBucket) ; i += _slotSize) {
|
||||
rocksutils::uint16ToPersistent(
|
||||
serialized, *(reinterpret_cast<uint16_t*>(_base + i)));
|
||||
}
|
||||
|
||||
TRI_ASSERT((_size * _counterSize * SlotsPerBucket) <= _counterAllocSize);
|
||||
|
||||
for (uint64_t i = 0;
|
||||
i < (_size * _counterSize * SlotsPerBucket) ; i += _counterSize) {
|
||||
rocksutils::uint32ToPersistent(
|
||||
serialized, *(reinterpret_cast<uint32_t*>(_counters + i)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,6 +289,7 @@ class RocksDBCuckooIndexEstimator {
|
|||
for (uint32_t b = 0; b < _size; ++b) {
|
||||
for (size_t i = 0; i < SlotsPerBucket; ++i) {
|
||||
Slot f = findSlot(b, i);
|
||||
f.injectCounter(findCounter(b, i));
|
||||
f.reset();
|
||||
}
|
||||
}
|
||||
|
@ -262,16 +348,11 @@ class RocksDBCuckooIndexEstimator {
|
|||
Slot slot = findSlotCuckoo(pos1, pos2, fingerprint);
|
||||
if (slot.isEmpty()) {
|
||||
// Free slot insert ourself.
|
||||
*slot.fingerprint() = fingerprint;
|
||||
*slot.counter() = 1; // We are the first element
|
||||
slot.init(fingerprint);
|
||||
_nrUsed++;
|
||||
} else {
|
||||
TRI_ASSERT(slot.isEqual(fingerprint));
|
||||
// TODO replace with constant uint16_t max
|
||||
if (*slot.counter() < 65536) {
|
||||
// just to avoid overflow...
|
||||
(*slot.counter())++;
|
||||
}
|
||||
slot.increase();
|
||||
}
|
||||
_nrTotal++;
|
||||
}
|
||||
|
@ -297,18 +378,15 @@ class RocksDBCuckooIndexEstimator {
|
|||
_nrTotal--;
|
||||
Slot slot = findSlotNoCuckoo(pos1, pos2, fingerprint, found);
|
||||
if (found) {
|
||||
if (*slot.counter() <= 1) {
|
||||
// We remove the last one of those, free slot
|
||||
if (!slot.decrease()) {
|
||||
// Removed last element. Have to remove
|
||||
slot.reset();
|
||||
_nrUsed--;
|
||||
} else {
|
||||
// Just decrease the counter
|
||||
(*slot.counter())--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// If we get here we assume that the element was once inserted, but removed
|
||||
// by cuckoo
|
||||
// If we get here we assume that the element was once inserted, but
|
||||
// removed by cuckoo
|
||||
// Reduce nrCuckood;
|
||||
if (_nrCuckood > 0) {
|
||||
--_nrCuckood;
|
||||
|
@ -316,19 +394,19 @@ class RocksDBCuckooIndexEstimator {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint64_t capacity() const { return _size * SlotsPerBucket; }
|
||||
|
||||
// not thread safe. called only during tests
|
||||
// not thread safe. called only during tests
|
||||
uint64_t nrUsed() const { return _nrUsed; }
|
||||
|
||||
// not thread safe. called only during tests
|
||||
// not thread safe. called only during tests
|
||||
uint64_t nrCuckood() const { return _nrCuckood; }
|
||||
|
||||
private: // methods
|
||||
|
||||
uint64_t memoryUsage() const {
|
||||
return sizeof(RocksDBCuckooIndexEstimator) + _allocSize;
|
||||
return sizeof(RocksDBCuckooIndexEstimator) + _slotAllocSize +
|
||||
_counterAllocSize;
|
||||
}
|
||||
|
||||
Slot findSlotNoCuckoo(uint64_t pos1, uint64_t pos2, uint16_t fp,
|
||||
|
@ -359,9 +437,11 @@ class RocksDBCuckooIndexEstimator {
|
|||
Slot slot = findSlot(pos1, i);
|
||||
if (slot.isEqual(fp)) {
|
||||
// Found we are done, short-circuit.
|
||||
slot.injectCounter(findCounter(pos1, i));
|
||||
return slot;
|
||||
}
|
||||
if (!foundEmpty && slot.isEmpty()) {
|
||||
slot.injectCounter(findCounter(pos1, i));
|
||||
foundEmpty = true;
|
||||
firstEmpty = slot;
|
||||
}
|
||||
|
@ -371,9 +451,11 @@ class RocksDBCuckooIndexEstimator {
|
|||
Slot slot = findSlot(pos2, i);
|
||||
if (slot.isEqual(fp)) {
|
||||
// Found we are done, short-circuit.
|
||||
slot.injectCounter(findCounter(pos2, i));
|
||||
return slot;
|
||||
}
|
||||
if (!foundEmpty && slot.isEmpty()) {
|
||||
slot.injectCounter(findCounter(pos2, i));
|
||||
foundEmpty = true;
|
||||
firstEmpty = slot;
|
||||
}
|
||||
|
@ -388,9 +470,10 @@ class RocksDBCuckooIndexEstimator {
|
|||
|
||||
// We also did not find an empty slot, now the cuckoo goes...
|
||||
|
||||
uint16_t counter =
|
||||
0; // We initially write a 0 in here, because the caller will
|
||||
// Increase the counter by one
|
||||
// We initially write a 0 in here, because the caller will
|
||||
// Increase the counter by one
|
||||
uint32_t counter = 0;
|
||||
|
||||
uint8_t r = pseudoRandomChoice();
|
||||
if ((r & 1) != 0) {
|
||||
std::swap(pos1, pos2);
|
||||
|
@ -402,12 +485,8 @@ class RocksDBCuckooIndexEstimator {
|
|||
r = pseudoRandomChoice();
|
||||
uint64_t i = r & (SlotsPerBucket - 1);
|
||||
firstEmpty = findSlot(pos1, i);
|
||||
uint16_t fDummy = *firstEmpty.fingerprint();
|
||||
uint16_t cDummy = *firstEmpty.counter();
|
||||
*firstEmpty.fingerprint() = fp;
|
||||
*firstEmpty.counter() = counter;
|
||||
fp = fDummy;
|
||||
counter = cDummy;
|
||||
firstEmpty.injectCounter(findCounter(pos1, i));
|
||||
firstEmpty.swap(fp, counter);
|
||||
|
||||
uint64_t hash2 = _hasherPosFingerprint(pos1, fp);
|
||||
pos2 = hashToPos(hash2);
|
||||
|
@ -417,6 +496,7 @@ class RocksDBCuckooIndexEstimator {
|
|||
for (uint64_t i = 0; i < SlotsPerBucket; ++i) {
|
||||
Slot slot = findSlot(pos2, i);
|
||||
if (slot.isEmpty()) {
|
||||
slot.injectCounter(findCounter(pos2, i));
|
||||
// Yeah we found an empty place already
|
||||
*slot.fingerprint() = fp;
|
||||
*slot.counter() = counter;
|
||||
|
@ -439,12 +519,8 @@ class RocksDBCuckooIndexEstimator {
|
|||
i = (i + 1) % SlotsPerBucket;
|
||||
slot = findSlot(pos1, i);
|
||||
}
|
||||
fDummy = *slot.fingerprint();
|
||||
cDummy = *slot.counter();
|
||||
*slot.fingerprint() = fp;
|
||||
*slot.counter() = counter;
|
||||
fp = fDummy;
|
||||
counter = cDummy;
|
||||
slot.injectCounter(findCounter(pos1, i));
|
||||
slot.swap(fp, counter);
|
||||
|
||||
hash2 = _hasherPosFingerprint(pos1, fp);
|
||||
pos2 = hashToPos(hash2);
|
||||
|
@ -452,6 +528,7 @@ class RocksDBCuckooIndexEstimator {
|
|||
for (uint64_t i = 0; i < SlotsPerBucket; ++i) {
|
||||
Slot slot = findSlot(pos2, i);
|
||||
if (slot.isEmpty()) {
|
||||
slot.injectCounter(findCounter(pos2, i));
|
||||
// Finally an empty place
|
||||
*slot.fingerprint() = fp;
|
||||
*slot.counter() = counter;
|
||||
|
@ -472,6 +549,7 @@ class RocksDBCuckooIndexEstimator {
|
|||
for (uint64_t i = 0; i < SlotsPerBucket; ++i) {
|
||||
Slot slot = findSlot(pos, i);
|
||||
if (fp == *slot.fingerprint()) {
|
||||
slot.injectCounter(findCounter(pos, i));
|
||||
found = true;
|
||||
return slot;
|
||||
}
|
||||
|
@ -480,11 +558,18 @@ class RocksDBCuckooIndexEstimator {
|
|||
}
|
||||
|
||||
Slot findSlot(uint64_t pos, uint64_t slot) const {
|
||||
TRI_ASSERT(_slotSize * (pos * SlotsPerBucket + slot) <= _slotAllocSize );
|
||||
char* address = _base + _slotSize * (pos * SlotsPerBucket + slot);
|
||||
auto ret = reinterpret_cast<uint16_t*>(address);
|
||||
return Slot(ret);
|
||||
}
|
||||
|
||||
uint32_t* findCounter(uint64_t pos, uint64_t slot) const {
|
||||
TRI_ASSERT(_counterSize * (pos * SlotsPerBucket + slot) <= _counterAllocSize );
|
||||
char* address = _counters + _counterSize * (pos * SlotsPerBucket + slot);
|
||||
return reinterpret_cast<uint32_t*>(address);
|
||||
}
|
||||
|
||||
uint64_t hashToPos(uint64_t hash) const {
|
||||
uint64_t relevantBits = (hash >> _sizeShift) & _sizeMask;
|
||||
return ((relevantBits < _size) ? relevantBits : (relevantBits - _size));
|
||||
|
@ -508,53 +593,72 @@ class RocksDBCuckooIndexEstimator {
|
|||
|
||||
void deserializeUncompressed(arangodb::StringRef const& serialized) {
|
||||
// Assert that we have at least the member variables
|
||||
TRI_ASSERT(serialized.size() >= (sizeof(SerializeFormat) + sizeof(uint64_t) + sizeof(_size) + sizeof(_nrUsed) +
|
||||
sizeof(_nrCuckood) + sizeof(_nrTotal) + sizeof(_niceSize) +
|
||||
sizeof(_logSize) ));
|
||||
TRI_ASSERT(serialized.size() >=
|
||||
(sizeof(SerializeFormat) + sizeof(uint64_t) + sizeof(_size) +
|
||||
sizeof(_nrUsed) + sizeof(_nrCuckood) + sizeof(_nrTotal) +
|
||||
sizeof(_niceSize) + sizeof(_logSize)));
|
||||
char const* current = serialized.data();
|
||||
TRI_ASSERT(*current == SerializeFormat::NOCOMPRESSION);
|
||||
current++; // Skip format char
|
||||
|
||||
uint64_t length = rocksutils::uint64FromPersistent(current);
|
||||
current += sizeof(uint64_t);
|
||||
// Validate that the serialized format is exactly as long as we expect it to be
|
||||
// Validate that the serialized format is exactly as long as we expect it to
|
||||
// be
|
||||
TRI_ASSERT(serialized.size() == length);
|
||||
|
||||
_size = rocksutils::uint64FromPersistent(current);
|
||||
current += sizeof(_size);
|
||||
current += sizeof(uint64_t);
|
||||
|
||||
if (_size <= 256) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
_nrUsed = rocksutils::uint64FromPersistent(current);
|
||||
current += sizeof(_nrUsed);
|
||||
current += sizeof(uint64_t);
|
||||
|
||||
_nrCuckood = rocksutils::uint64FromPersistent(current);
|
||||
current += sizeof(_nrCuckood);
|
||||
current += sizeof(uint64_t);
|
||||
|
||||
_nrTotal = rocksutils::uint64FromPersistent(current);
|
||||
current += sizeof(_nrTotal);
|
||||
current += sizeof(uint64_t);
|
||||
|
||||
_niceSize = rocksutils::uint64FromPersistent(current);
|
||||
current += sizeof(_niceSize);
|
||||
current += sizeof(uint64_t);
|
||||
|
||||
_logSize = rocksutils::uint64FromPersistent(current);
|
||||
current += sizeof(_logSize);
|
||||
current += sizeof(uint64_t);
|
||||
|
||||
deriveSizesAndAlloc();
|
||||
|
||||
|
||||
// Validate that we have enough data in the serialized format.
|
||||
TRI_ASSERT(serialized.size() ==
|
||||
(sizeof(SerializeFormat) + sizeof( uint64_t) + sizeof(_size) + sizeof(_nrUsed) +
|
||||
sizeof(_nrCuckood) + sizeof(_nrTotal) + sizeof(_niceSize) +
|
||||
sizeof(_logSize) + (_size * _slotSize * SlotsPerBucket)));
|
||||
(sizeof(SerializeFormat) + sizeof(uint64_t) + sizeof(_size) +
|
||||
sizeof(_nrUsed) + sizeof(_nrCuckood) + sizeof(_nrTotal) +
|
||||
sizeof(_niceSize) + sizeof(_logSize) +
|
||||
(_size * _slotSize * SlotsPerBucket)) +
|
||||
(_size * _counterSize * SlotsPerBucket));
|
||||
|
||||
// Insert the raw data
|
||||
// Size is as follows: nrOfBuckets * SlotsPerBucket * SlotSize
|
||||
TRI_ASSERT((_size * _slotSize * SlotsPerBucket) <= _allocSize);
|
||||
TRI_ASSERT((_size * _slotSize * SlotsPerBucket) <= _slotAllocSize);
|
||||
|
||||
for (uint64_t i = 0; i < (_size * _slotSize * SlotsPerBucket) / sizeof(uint16_t);
|
||||
++i) {
|
||||
*(reinterpret_cast<uint16_t*>(_base + i * 2)) = rocksutils::uint16FromPersistent(current + (i * sizeof(uint16_t)));
|
||||
for (uint64_t i = 0;
|
||||
i < (_size * _slotSize * SlotsPerBucket) ; i += _slotSize) {
|
||||
*(reinterpret_cast<uint16_t*>(_base + i)) =
|
||||
rocksutils::uint16FromPersistent(current);
|
||||
current += _slotSize;
|
||||
}
|
||||
|
||||
TRI_ASSERT((_size * _counterSize * SlotsPerBucket) <= _counterAllocSize);
|
||||
|
||||
for (uint64_t i = 0;
|
||||
i < (_size * _counterSize * SlotsPerBucket); i += _counterSize) {
|
||||
*(reinterpret_cast<uint32_t*>(_counters + i)) =
|
||||
rocksutils::uint32FromPersistent(current);
|
||||
current += _counterSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void initializeDefault() {
|
||||
|
@ -571,6 +675,7 @@ class RocksDBCuckooIndexEstimator {
|
|||
for (uint32_t b = 0; b < _size; ++b) {
|
||||
for (size_t i = 0; i < SlotsPerBucket; ++i) {
|
||||
Slot f = findSlot(b, i);
|
||||
f.injectCounter(findCounter(b, i));
|
||||
f.reset();
|
||||
}
|
||||
}
|
||||
|
@ -579,12 +684,24 @@ class RocksDBCuckooIndexEstimator {
|
|||
void deriveSizesAndAlloc() {
|
||||
_sizeMask = _niceSize - 1;
|
||||
_sizeShift = static_cast<uint32_t>((64 - _logSize) / 2);
|
||||
_allocSize = _size * _slotSize * SlotsPerBucket +
|
||||
64; // give 64 bytes padding to enable 64-byte alignment
|
||||
_allocBase = new char[_allocSize];
|
||||
|
||||
// give 64 bytes padding to enable 64-byte alignment
|
||||
_slotAllocSize = _size * _slotSize * SlotsPerBucket + 64;
|
||||
|
||||
_slotBase = new char[_slotAllocSize];
|
||||
|
||||
_base = reinterpret_cast<char*>(
|
||||
(reinterpret_cast<uintptr_t>(_allocBase) + 63) &
|
||||
(reinterpret_cast<uintptr_t>(_slotBase) + 63) &
|
||||
~((uintptr_t)0x3fu)); // to actually implement the 64-byte alignment,
|
||||
// shift base pointer within allocated space to
|
||||
// 64-byte boundary
|
||||
|
||||
// give 64 bytes padding to enable 64-byte alignment
|
||||
_counterAllocSize = _size * _counterSize * SlotsPerBucket + 64;
|
||||
_counterBase = new char[_counterAllocSize];
|
||||
|
||||
_counters = reinterpret_cast<char*>(
|
||||
(reinterpret_cast<uintptr_t>(_counterBase) + 63) &
|
||||
~((uintptr_t)0x3fu)); // to actually implement the 64-byte alignment,
|
||||
// shift base pointer within allocated space to
|
||||
// 64-byte boundary
|
||||
|
@ -593,7 +710,8 @@ class RocksDBCuckooIndexEstimator {
|
|||
private: // member variables
|
||||
uint64_t _randState; // pseudo random state for expunging
|
||||
|
||||
size_t _slotSize; // total size of a slot
|
||||
size_t _slotSize; // total size of a slot
|
||||
size_t _counterSize; // total size of a counter
|
||||
|
||||
uint64_t _logSize; // logarithm (base 2) of number of buckets
|
||||
uint64_t _size; // actual number of buckets
|
||||
|
@ -601,11 +719,15 @@ class RocksDBCuckooIndexEstimator {
|
|||
// 2^_logSize
|
||||
uint64_t _sizeMask; // used to mask out some bits from the hash
|
||||
uint32_t _sizeShift; // used to shift the bits down to get a position
|
||||
uint64_t _allocSize; // number of allocated bytes,
|
||||
// == _size * SlotsPerBucket * _slotSize + 64
|
||||
char* _base; // pointer to allocated space, 64-byte aligned
|
||||
char* _allocBase; // base of original allocation
|
||||
uint64_t _nrUsed; // number of pairs stored in the table
|
||||
uint64_t _slotAllocSize; // number of allocated bytes for the slots,
|
||||
// == _size * SlotsPerBucket * _slotSize + 64
|
||||
uint64_t _counterAllocSize; // number of allocated bytes ofr the counters,
|
||||
// == _size * SlotsPerBucket * _counterSize + 64
|
||||
char* _base; // pointer to allocated space, 64-byte aligned
|
||||
char* _slotBase; // base of original allocation
|
||||
char* _counters; // pointer to allocated space, 64-byte aligned
|
||||
char* _counterBase; // base of original counter allocation
|
||||
uint64_t _nrUsed; // number of pairs stored in the table
|
||||
uint64_t _nrCuckood; // number of elements that have been removed by cuckoo
|
||||
uint64_t _nrTotal; // number of elements included in total
|
||||
unsigned _maxRounds; // maximum number of cuckoo rounds on insertion
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "v8-query.h"
|
||||
#include "Aql/Query.h"
|
||||
#include "Aql/QueryResultV8.h"
|
||||
#include "Aql/QueryString.h"
|
||||
#include "Basics/StaticStrings.h"
|
||||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "Basics/fasthash.h"
|
||||
|
@ -61,7 +62,7 @@ aql::QueryResultV8 AqlQuery(
|
|||
TRI_ASSERT(col != nullptr);
|
||||
|
||||
TRI_GET_GLOBALS();
|
||||
arangodb::aql::Query query(true, col->vocbase(), aql.c_str(), aql.size(),
|
||||
arangodb::aql::Query query(true, col->vocbase(), arangodb::aql::QueryString(aql),
|
||||
bindVars, nullptr, arangodb::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.executeV8(
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "Aql/QueryExecutionState.h"
|
||||
#include "Aql/QueryList.h"
|
||||
#include "Aql/QueryRegistry.h"
|
||||
#include "Aql/QueryString.h"
|
||||
#include "Basics/HybridLogicalClock.h"
|
||||
#include "Basics/MutexLocker.h"
|
||||
#include "Basics/ScopeGuard.h"
|
||||
|
@ -744,8 +745,8 @@ static void JS_ParseAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
|||
|
||||
std::string const queryString(TRI_ObjectToString(args[0]));
|
||||
|
||||
arangodb::aql::Query query(true, vocbase, queryString.c_str(),
|
||||
queryString.size(), nullptr, nullptr,
|
||||
arangodb::aql::Query query(true, vocbase, aql::QueryString(queryString),
|
||||
nullptr, nullptr,
|
||||
arangodb::aql::PART_MAIN);
|
||||
|
||||
auto parseResult = query.parse();
|
||||
|
@ -882,8 +883,8 @@ static void JS_ExplainAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
|||
}
|
||||
|
||||
// bind parameters will be freed by the query later
|
||||
arangodb::aql::Query query(true, vocbase, queryString.c_str(),
|
||||
queryString.size(), bindVars, options,
|
||||
arangodb::aql::Query query(true, vocbase, aql::QueryString(queryString),
|
||||
bindVars, options,
|
||||
arangodb::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.explain();
|
||||
|
@ -1070,8 +1071,8 @@ static void JS_ExecuteAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
|||
|
||||
// bind parameters will be freed by the query later
|
||||
TRI_GET_GLOBALS();
|
||||
arangodb::aql::Query query(true, vocbase, queryString.c_str(),
|
||||
queryString.size(), bindVars, options,
|
||||
arangodb::aql::Query query(true, vocbase, aql::QueryString(queryString),
|
||||
bindVars, options,
|
||||
arangodb::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.executeV8(
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "AuthInfo.h"
|
||||
|
||||
#include "Aql/Query.h"
|
||||
#include "Aql/QueryString.h"
|
||||
#include "Basics/ReadLocker.h"
|
||||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "Basics/WriteLocker.h"
|
||||
|
@ -266,8 +267,8 @@ void AuthInfo::reload() {
|
|||
std::string const queryStr("FOR user IN _users RETURN user");
|
||||
auto emptyBuilder = std::make_shared<VPackBuilder>();
|
||||
|
||||
arangodb::aql::Query query(false, vocbase, queryStr.c_str(),
|
||||
queryStr.size(), emptyBuilder, emptyBuilder,
|
||||
arangodb::aql::Query query(false, vocbase, arangodb::aql::QueryString(queryStr),
|
||||
emptyBuilder, emptyBuilder,
|
||||
arangodb::aql::PART_MAIN);
|
||||
|
||||
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "starting to load authentication and authorization information";
|
||||
|
@ -448,9 +449,9 @@ AuthResult AuthInfo::checkPassword(std::string const& username,
|
|||
binds.close(); // user
|
||||
binds.close(); // obj
|
||||
|
||||
arangodb::aql::Query query(false, vocbase, queryStr.c_str(),
|
||||
queryStr.size(), std::make_shared<VPackBuilder>(binds), emptyBuilder,
|
||||
arangodb::aql::PART_MAIN);
|
||||
arangodb::aql::Query query(false, vocbase, arangodb::aql::QueryString(queryStr),
|
||||
std::make_shared<VPackBuilder>(binds), emptyBuilder,
|
||||
arangodb::aql::PART_MAIN);
|
||||
|
||||
TRI_ASSERT(_queryRegistry != nullptr);
|
||||
auto queryResult = query.execute(_queryRegistry);
|
||||
|
|
|
@ -1657,33 +1657,30 @@ std::string TRI_BinaryName(char const* argv0) {
|
|||
|
||||
std::string TRI_LocateBinaryPath(char const* argv0) {
|
||||
#if _WIN32
|
||||
char buff[4096];
|
||||
int res = GetModuleFileName(NULL, buff, sizeof(buff));
|
||||
|
||||
if (argv0 == nullptr) {
|
||||
char buff[4096];
|
||||
int res = GetModuleFileName(NULL, buff, sizeof(buff));
|
||||
if (res != 0) {
|
||||
buff[4095] = '\0';
|
||||
|
||||
if (res != 0) {
|
||||
buff[4095] = '\0';
|
||||
char* q = buff + res;
|
||||
|
||||
char* q = buff + res;
|
||||
|
||||
while (buff < q) {
|
||||
if (*q == '\\' || *q == '/') {
|
||||
*q = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
--q;
|
||||
while (buff < q) {
|
||||
if (*q == '\\' || *q == '/') {
|
||||
*q = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
return std::string(buff);
|
||||
--q;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return std::string(buff);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return std::string();
|
||||
|
||||
#else
|
||||
|
||||
std::string binaryPath;
|
||||
|
||||
// check if name contains a '/' ( or '\' for windows)
|
||||
|
@ -1736,6 +1733,7 @@ std::string TRI_LocateBinaryPath(char const* argv0) {
|
|||
}
|
||||
|
||||
return binaryPath;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string TRI_GetInstallRoot(std::string const& binaryPath,
|
||||
|
|
Loading…
Reference in New Issue