1
0
Fork 0

fix invalidation

This commit is contained in:
Jan Steemann 2015-06-25 16:46:04 +02:00
parent e86ed5c685
commit 66eec2ac7e
9 changed files with 295 additions and 148 deletions

View File

@ -622,6 +622,7 @@ SHELL_SERVER_AQL = @top_srcdir@/js/server/tests/aql-arithmetic.js \
@top_srcdir@/js/server/tests/aql-queries-optimiser-sort-noncluster.js \ @top_srcdir@/js/server/tests/aql-queries-optimiser-sort-noncluster.js \
@top_srcdir@/js/server/tests/aql-queries-simple.js \ @top_srcdir@/js/server/tests/aql-queries-simple.js \
@top_srcdir@/js/server/tests/aql-queries-variables.js \ @top_srcdir@/js/server/tests/aql-queries-variables.js \
@top_srcdir@/js/server/tests/aql-query-cache.js \
@top_srcdir@/js/server/tests/aql-range.js \ @top_srcdir@/js/server/tests/aql-range.js \
@top_srcdir@/js/server/tests/aql-ranges.js \ @top_srcdir@/js/server/tests/aql-ranges.js \
@top_srcdir@/js/server/tests/aql-refaccess-attribute.js \ @top_srcdir@/js/server/tests/aql-refaccess-attribute.js \

View File

@ -55,8 +55,8 @@ namespace triagens {
} }
~Collections () { ~Collections () {
for (auto it = _collections.begin(); it != _collections.end(); ++it) { for (auto& it : _collections) {
delete (*it).second; delete it.second;
} }
} }
@ -83,15 +83,10 @@ namespace triagens {
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_TOO_MANY_COLLECTIONS); THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_TOO_MANY_COLLECTIONS);
} }
auto collection = new Collection(name, _vocbase, accessType); std::unique_ptr<Collection> collection(new Collection(name, _vocbase, accessType));
try { _collections.emplace(name, collection.get());
_collections.emplace(std::make_pair(name, collection));
} return collection.release();
catch (...) {
delete collection;
throw;
}
return collection;
} }
else { else {
// note that the collection is used in both read & write ops // note that the collection is used in both read & write ops
@ -112,8 +107,8 @@ namespace triagens {
std::vector<std::string> result; std::vector<std::string> result;
result.reserve(_collections.size()); result.reserve(_collections.size());
for (auto it = _collections.begin(); it != _collections.end(); ++it) { for (auto const& it : _collections) {
result.emplace_back((*it).first); result.emplace_back(it.first);
} }
return result; return result;
} }

View File

@ -648,6 +648,7 @@ QueryResult Query::execute (QueryRegistry* registry) {
res.warnings = warningsToJson(TRI_UNKNOWN_MEM_ZONE); res.warnings = warningsToJson(TRI_UNKNOWN_MEM_ZONE);
res.json = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, cacheResult.get()->_queryResult); res.json = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, cacheResult.get()->_queryResult);
res.stats = nullptr; res.stats = nullptr;
res.cached = true;
return res; return res;
} }
@ -695,7 +696,14 @@ QueryResult Query::execute (QueryRegistry* registry) {
} }
// finally store the generated result in the query cache // finally store the generated result in the query cache
QueryCache::instance()->store(_vocbase, queryStringHash, _queryString, _queryLength, TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, jsonResult.json()), std::vector<std::string>()); QueryCache::instance()->store(
_vocbase,
queryStringHash,
_queryString,
_queryLength,
TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, jsonResult.json()),
collections()->collectionNames()
);
} }
else { else {
// iterate over result and return it // iterate over result and return it
@ -782,6 +790,7 @@ QueryResultV8 Query::executeV8 (v8::Isolate* isolate,
// got a result from the query cache // got a result from the query cache
QueryResultV8 res(TRI_ERROR_NO_ERROR); QueryResultV8 res(TRI_ERROR_NO_ERROR);
res.result = v8::Handle<v8::Array>::Cast(TRI_ObjectJson(isolate, cacheResult.get()->_queryResult)); res.result = v8::Handle<v8::Array>::Cast(TRI_ObjectJson(isolate, cacheResult.get()->_queryResult));
res.cached = true;
return res; return res;
} }
} }
@ -831,7 +840,14 @@ QueryResultV8 Query::executeV8 (v8::Isolate* isolate,
} }
// finally store the generated result in the query cache // finally store the generated result in the query cache
QueryCache::instance()->store(_vocbase, queryStringHash, _queryString, _queryLength, cacheResult.get(), std::vector<std::string>()); QueryCache::instance()->store(
_vocbase,
queryStringHash,
_queryString,
_queryLength,
cacheResult.get(),
collections()->collectionNames()
);
cacheResult.release(); cacheResult.release();
} }
else { else {

View File

@ -220,8 +220,7 @@ void QueryCacheDatabaseEntry::invalidate (char const* collection) {
QueryCache::QueryCache () QueryCache::QueryCache ()
: _lock(), : _lock(),
_entries(), _entries() {
_active(true) {
} }
@ -236,12 +235,25 @@ QueryCache::~QueryCache () {
// --SECTION-- public methods // --SECTION-- public methods
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief return the query cache properties
////////////////////////////////////////////////////////////////////////////////
triagens::basics::Json QueryCache::properties () const {
triagens::basics::Json json(triagens::basics::Json::Object, 2);
json("mode", triagens::basics::Json(modeString(mode())));
return json;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief test whether the cache might be active /// @brief test whether the cache might be active
/// this is a quick test that may save the caller from further bothering
/// about the query cache if case it returns `false`
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool QueryCache::mayBeActive () const { bool QueryCache::mayBeActive () const {
return (_active && (mode() != CACHE_ALWAYS_OFF)); return (mode() != CACHE_ALWAYS_OFF);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -249,11 +261,6 @@ bool QueryCache::mayBeActive () const {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
QueryCacheMode QueryCache::mode () const { QueryCacheMode QueryCache::mode () const {
if (! _active) {
// override whatever was stored in mode
return CACHE_ALWAYS_OFF;
}
return Mode.load(std::memory_order_relaxed); return Mode.load(std::memory_order_relaxed);
} }
@ -290,6 +297,24 @@ void QueryCache::mode (std::string const& value) {
} }
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief return a string version of the mode
////////////////////////////////////////////////////////////////////////////////
std::string QueryCache::modeString (QueryCacheMode mode) {
switch (mode) {
case CACHE_ALWAYS_OFF:
return "off";
case CACHE_ALWAYS_ON:
return "on";
case CACHE_ON_DEMAND:
return "demand";
}
TRI_ASSERT(false);
return "off";
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief lookup a query result in the cache /// @brief lookup a query result in the cache
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -323,6 +348,10 @@ void QueryCache::store (TRI_vocbase_t* vocbase,
TRI_json_t* result, TRI_json_t* result,
std::vector<std::string> const& collections) { std::vector<std::string> const& collections) {
if (result == nullptr) {
return;
}
std::shared_ptr<QueryCacheResultEntry> entry(new QueryCacheResultEntry(queryString, queryStringLength, result, collections)); std::shared_ptr<QueryCacheResultEntry> entry(new QueryCacheResultEntry(queryString, queryStringLength, result, collections));
WRITE_LOCKER(_lock); WRITE_LOCKER(_lock);
@ -348,20 +377,14 @@ void QueryCache::invalidate (triagens::basics::ReadWriteLock& lock,
std::vector<char const*> const& collections) { std::vector<char const*> const& collections) {
TRI_ASSERT(&lock == &_lock); // this should be our lock TRI_ASSERT(&lock == &_lock); // this should be our lock
try { auto it = _entries.find(vocbase);
auto it = _entries.find(vocbase);
if (it == _entries.end()) { if (it == _entries.end()) {
return; return;
} }
// invalidate while holding the lock // invalidate while holding the lock
(*it).second->invalidate(collections); (*it).second->invalidate(collections);
}
catch (...) {
// something is really wrong. now disable ourselves
disable();
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -370,22 +393,16 @@ void QueryCache::invalidate (triagens::basics::ReadWriteLock& lock,
void QueryCache::invalidate (TRI_vocbase_t* vocbase, void QueryCache::invalidate (TRI_vocbase_t* vocbase,
std::vector<char const*> const& collections) { std::vector<char const*> const& collections) {
try { WRITE_LOCKER(_lock);
WRITE_LOCKER(_lock);
auto it = _entries.find(vocbase); auto it = _entries.find(vocbase);
if (it == _entries.end()) { if (it == _entries.end()) {
return; return;
} }
// invalidate while holding the lock // invalidate while holding the lock
(*it).second->invalidate(collections); (*it).second->invalidate(collections);
}
catch (...) {
// something is really wrong. now disable ourselves
disable();
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -394,22 +411,16 @@ void QueryCache::invalidate (TRI_vocbase_t* vocbase,
void QueryCache::invalidate (TRI_vocbase_t* vocbase, void QueryCache::invalidate (TRI_vocbase_t* vocbase,
char const* collection) { char const* collection) {
try { WRITE_LOCKER(_lock);
WRITE_LOCKER(_lock);
auto it = _entries.find(vocbase); auto it = _entries.find(vocbase);
if (it == _entries.end()) { if (it == _entries.end()) {
return; return;
} }
// invalidate while holding the lock // invalidate while holding the lock
(*it).second->invalidate(collection); (*it).second->invalidate(collection);
}
catch (...) {
// something is really wrong. now disable ourselves
disable();
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -422,20 +433,14 @@ void QueryCache::invalidate (triagens::basics::ReadWriteLock& lock,
char const* collection) { char const* collection) {
TRI_ASSERT(&lock == &_lock); // this should be our lock TRI_ASSERT(&lock == &_lock); // this should be our lock
try { auto it = _entries.find(vocbase);
auto it = _entries.find(vocbase);
if (it == _entries.end()) { if (it == _entries.end()) {
return; return;
} }
// invalidate while holding the lock // invalidate while holding the lock
(*it).second->invalidate(collection); (*it).second->invalidate(collection);
}
catch (...) {
// something is really wrong. now disable ourselves
disable();
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -445,28 +450,22 @@ void QueryCache::invalidate (triagens::basics::ReadWriteLock& lock,
void QueryCache::invalidate (TRI_vocbase_t* vocbase) { void QueryCache::invalidate (TRI_vocbase_t* vocbase) {
QueryCacheDatabaseEntry* databaseQueryCache = nullptr; QueryCacheDatabaseEntry* databaseQueryCache = nullptr;
try { {
{ WRITE_LOCKER(_lock);
WRITE_LOCKER(_lock);
auto it = _entries.find(vocbase); auto it = _entries.find(vocbase);
if (it == _entries.end()) { if (it == _entries.end()) {
return; return;
} }
databaseQueryCache = (*it).second; databaseQueryCache = (*it).second;
_entries.erase(it); _entries.erase(it);
}
// delete without holding the lock
TRI_ASSERT(databaseQueryCache != nullptr);
delete databaseQueryCache;
}
catch (...) {
// something is really wrong. now disable ourselves
disable();
} }
// delete without holding the lock
TRI_ASSERT(databaseQueryCache != nullptr);
delete databaseQueryCache;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -478,35 +477,20 @@ void QueryCache::invalidate (triagens::basics::ReadWriteLock& lock,
TRI_vocbase_t* vocbase) { TRI_vocbase_t* vocbase) {
TRI_ASSERT(&lock == &_lock); // this should be our lock TRI_ASSERT(&lock == &_lock); // this should be our lock
try { QueryCacheDatabaseEntry* databaseQueryCache = nullptr;
QueryCacheDatabaseEntry* databaseQueryCache = nullptr;
auto it = _entries.find(vocbase); auto it = _entries.find(vocbase);
if (it == _entries.end()) { if (it == _entries.end()) {
return; return;
} }
databaseQueryCache = (*it).second; databaseQueryCache = (*it).second;
_entries.erase(it); _entries.erase(it);
// delete without holding the lock // delete without holding the lock
TRI_ASSERT(databaseQueryCache != nullptr); TRI_ASSERT(databaseQueryCache != nullptr);
delete databaseQueryCache; delete databaseQueryCache;
}
catch (...) {
// something is really wrong. now disable ourselves
disable();
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief disable ourselves in case of emergency
////////////////////////////////////////////////////////////////////////////////
void QueryCache::disable () {
_active = false;
mode(CACHE_ALWAYS_OFF);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -31,6 +31,7 @@
#define ARANGODB_AQL_QUERY_CACHE_H 1 #define ARANGODB_AQL_QUERY_CACHE_H 1
#include "Basics/Common.h" #include "Basics/Common.h"
#include "Basics/JsonHelper.h"
#include "Basics/ReadWriteLock.h" #include "Basics/ReadWriteLock.h"
struct TRI_json_t; struct TRI_json_t;
@ -177,8 +178,16 @@ namespace triagens {
public: public:
////////////////////////////////////////////////////////////////////////////////
/// @brief return the query cache properties
////////////////////////////////////////////////////////////////////////////////
triagens::basics::Json properties () const;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief test whether the cache might be active /// @brief test whether the cache might be active
/// this is a quick test that may save the caller from further bothering
/// about the query cache if case it returns `false`
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool mayBeActive () const; bool mayBeActive () const;
@ -201,6 +210,12 @@ namespace triagens {
void mode (std::string const&); void mode (std::string const&);
////////////////////////////////////////////////////////////////////////////////
/// @brief return a string version of the mode
////////////////////////////////////////////////////////////////////////////////
static std::string modeString (QueryCacheMode);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief lookup a query result in the cache /// @brief lookup a query result in the cache
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -277,12 +292,6 @@ namespace triagens {
return _lock; return _lock;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief disable ourselves in case of emergency
////////////////////////////////////////////////////////////////////////////////
void disable ();
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief get the pointer to the global query cache /// @brief get the pointer to the global query cache
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -318,13 +327,6 @@ namespace triagens {
std::unordered_map<struct TRI_vocbase_s*, QueryCacheDatabaseEntry*> _entries; std::unordered_map<struct TRI_vocbase_s*, QueryCacheDatabaseEntry*> _entries;
////////////////////////////////////////////////////////////////////////////////
/// @brief activity flag. will be toggled to false only in case of something
/// going terribly wrong
////////////////////////////////////////////////////////////////////////////////
bool _active;
}; };
} }

View File

@ -45,6 +45,7 @@ namespace triagens {
QueryResult (QueryResult&& other) { QueryResult (QueryResult&& other) {
code = other.code; code = other.code;
cached = other.cached;
details = other.details; details = other.details;
warnings = other.warnings; warnings = other.warnings;
json = other.json; json = other.json;
@ -65,6 +66,7 @@ namespace triagens {
QueryResult (int code, QueryResult (int code,
std::string const& details) std::string const& details)
: code(code), : code(code),
cached(false),
details(details), details(details),
zone(TRI_UNKNOWN_MEM_ZONE), zone(TRI_UNKNOWN_MEM_ZONE),
warnings(nullptr), warnings(nullptr),
@ -98,6 +100,7 @@ namespace triagens {
} }
int code; int code;
bool cached;
std::string details; std::string details;
std::unordered_set<std::string> bindParameters; std::unordered_set<std::string> bindParameters;
std::vector<std::string> collectionNames; std::vector<std::string> collectionNames;

View File

@ -1199,20 +1199,21 @@ static void JS_ExecuteAqlJson (const v8::FunctionCallbackInfo<v8::Value>& args)
// return the array value as it is. this is a performance optimisation // return the array value as it is. this is a performance optimisation
v8::Handle<v8::Object> result = v8::Object::New(isolate); v8::Handle<v8::Object> result = v8::Object::New(isolate);
if (queryResult.json != nullptr) { if (queryResult.json != nullptr) {
result->Set(TRI_V8_ASCII_STRING("json"), TRI_ObjectJson(isolate, queryResult.json)); result->ForceSet(TRI_V8_ASCII_STRING("json"), TRI_ObjectJson(isolate, queryResult.json));
} }
if (queryResult.stats != nullptr) { if (queryResult.stats != nullptr) {
result->Set(TRI_V8_ASCII_STRING("stats"), TRI_ObjectJson(isolate, queryResult.stats)); result->ForceSet(TRI_V8_ASCII_STRING("stats"), TRI_ObjectJson(isolate, queryResult.stats));
} }
if (queryResult.profile != nullptr) { if (queryResult.profile != nullptr) {
result->Set(TRI_V8_ASCII_STRING("profile"), TRI_ObjectJson(isolate, queryResult.profile)); result->ForceSet(TRI_V8_ASCII_STRING("profile"), TRI_ObjectJson(isolate, queryResult.profile));
} }
if (queryResult.warnings == nullptr) { if (queryResult.warnings == nullptr) {
result->Set(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate)); result->ForceSet(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate));
} }
else { else {
result->Set(TRI_V8_ASCII_STRING("warnings"), TRI_ObjectJson(isolate, queryResult.warnings)); result->ForceSet(TRI_V8_ASCII_STRING("warnings"), TRI_ObjectJson(isolate, queryResult.warnings));
} }
result->ForceSet(TRI_V8_ASCII_STRING("cached"), v8::Boolean::New(isolate, queryResult.cached));
TRI_V8_RETURN(result); TRI_V8_RETURN(result);
TRI_V8_TRY_CATCH_END TRI_V8_TRY_CATCH_END
@ -1299,20 +1300,21 @@ static void JS_ExecuteAql (const v8::FunctionCallbackInfo<v8::Value>& args) {
// return the array value as it is. this is a performance optimisation // return the array value as it is. this is a performance optimisation
v8::Handle<v8::Object> result = v8::Object::New(isolate); v8::Handle<v8::Object> result = v8::Object::New(isolate);
result->Set(TRI_V8_ASCII_STRING("json"), queryResult.result); result->ForceSet(TRI_V8_ASCII_STRING("json"), queryResult.result);
if (queryResult.stats != nullptr) { if (queryResult.stats != nullptr) {
result->Set(TRI_V8_ASCII_STRING("stats"), TRI_ObjectJson(isolate, queryResult.stats)); result->ForceSet(TRI_V8_ASCII_STRING("stats"), TRI_ObjectJson(isolate, queryResult.stats));
} }
if (queryResult.profile != nullptr) { if (queryResult.profile != nullptr) {
result->Set(TRI_V8_ASCII_STRING("profile"), TRI_ObjectJson(isolate, queryResult.profile)); result->ForceSet(TRI_V8_ASCII_STRING("profile"), TRI_ObjectJson(isolate, queryResult.profile));
} }
if (queryResult.warnings == nullptr) { if (queryResult.warnings == nullptr) {
result->Set(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate)); result->ForceSet(TRI_V8_ASCII_STRING("warnings"), v8::Array::New(isolate));
} }
else { else {
result->Set(TRI_V8_ASCII_STRING("warnings"), TRI_ObjectJson(isolate, queryResult.warnings)); result->ForceSet(TRI_V8_ASCII_STRING("warnings"), TRI_ObjectJson(isolate, queryResult.warnings));
} }
result->ForceSet(TRI_V8_ASCII_STRING("cached"), v8::Boolean::New(isolate, queryResult.cached));
TRI_V8_RETURN(result); TRI_V8_RETURN(result);
TRI_V8_TRY_CATCH_END TRI_V8_TRY_CATCH_END
@ -1532,7 +1534,7 @@ static void JS_QueryIsKilledAql (const v8::FunctionCallbackInfo<v8::Value>& args
/// @brief configures the AQL query cache /// @brief configures the AQL query cache
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static void JS_QueryCacheConfigAql (const v8::FunctionCallbackInfo<v8::Value>& args) { static void JS_QueryCachePropertiesAql (const v8::FunctionCallbackInfo<v8::Value>& args) {
TRI_V8_TRY_CATCH_BEGIN(isolate); TRI_V8_TRY_CATCH_BEGIN(isolate);
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
@ -1542,17 +1544,26 @@ static void JS_QueryCacheConfigAql (const v8::FunctionCallbackInfo<v8::Value>& a
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND); TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
} }
if (args.Length() != 1 || ! args[0]->IsObject()) { if (args.Length() > 1 || (args.Length() == 1 && ! args[0]->IsObject())) {
TRI_V8_THROW_EXCEPTION_USAGE("AQL_QUERY_CACHE_CONFIG(<options>)"); TRI_V8_THROW_EXCEPTION_USAGE("AQL_QUERY_CACHE_PROPERTIES(<options>)");
} }
auto obj = args[0]->ToObject(); if (args.Length() == 1) {
// called with options
auto obj = args[0]->ToObject();
if (obj->Has(TRI_V8_ASCII_STRING("mode"))) { if (obj->Has(TRI_V8_ASCII_STRING("mode"))) {
auto mode = TRI_ObjectToString(obj->Get(TRI_V8_ASCII_STRING("mode"))); auto mode = TRI_ObjectToString(obj->Get(TRI_V8_ASCII_STRING("mode")));
triagens::aql::QueryCache::instance()->mode(mode); // set mode
triagens::aql::QueryCache::instance()->mode(mode);
}
} }
auto properties = triagens::aql::QueryCache::instance()->properties();
TRI_V8_RETURN(TRI_ObjectJson(isolate, properties.json()));
// fetch current configuration and return it
TRI_V8_TRY_CATCH_END TRI_V8_TRY_CATCH_END
} }
@ -3753,7 +3764,7 @@ void TRI_InitV8VocBridge (v8::Isolate* isolate,
TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERIES_KILL"), JS_QueriesKillAql, true); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERIES_KILL"), JS_QueriesKillAql, true);
TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_SLEEP"), JS_QuerySleepAql, true); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_SLEEP"), JS_QuerySleepAql, true);
TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_IS_KILLED"), JS_QueryIsKilledAql, true); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_IS_KILLED"), JS_QueryIsKilledAql, true);
TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_CACHE_CONFIG"), JS_QueryCacheConfigAql, true); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_CACHE_PROPERTIES"), JS_QueryCachePropertiesAql, true);
TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_CACHE_INVALIDATE"), JS_QueryCacheInvalidateAql, true); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("AQL_QUERY_CACHE_INVALIDATE"), JS_QueryCacheInvalidateAql, true);
TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("CPP_SHORTEST_PATH"), JS_QueryShortestPath, true); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("CPP_SHORTEST_PATH"), JS_QueryShortestPath, true);

View File

@ -149,7 +149,7 @@ void ClearQueryCache (TRI_transaction_t* trx) {
} }
catch (...) { catch (...) {
// in case something goes wrong, we have to disable the query cache // in case something goes wrong, we have to disable the query cache
triagens::aql::QueryCache::instance()->disable(); triagens::aql::QueryCache::instance()->invalidate(trx->_vocbase);
} }
} }
@ -1268,7 +1268,7 @@ int TRI_AddOperationTransaction (triagens::wal::DocumentOperation& operation,
if (isSingleOperationTransaction) { if (isSingleOperationTransaction) {
// operation is directly executed // operation is directly executed
operation.handle(); operation.handle();
triagens::aql::QueryCache::instance()->invalidate(trx->_vocbase, document->_info._name); triagens::aql::QueryCache::instance()->invalidate(trx->_vocbase, document->_info._name);
++document->_uncollectedLogfileEntries; ++document->_uncollectedLogfileEntries;

View File

@ -0,0 +1,135 @@
/*jshint globalstrict:false, strict:false, maxlen: 500 */
/*global assertEqual, assertTrue, assertFalse, AQL_EXECUTE,
AQL_QUERY_CACHE_PROPERTIES, AQL_QUERY_CACHE_INVALIDATE */
////////////////////////////////////////////////////////////////////////////////
/// @brief tests for query language, bind parameters
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 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 triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
var jsunity = require("jsunity");
var db = require("org/arangodb").db;
////////////////////////////////////////////////////////////////////////////////
/// @brief test suite
////////////////////////////////////////////////////////////////////////////////
function ahuacatlQueryCacheTestSuite () {
var cacheProperties;
var c1, c2;
return {
////////////////////////////////////////////////////////////////////////////////
/// @brief set up
////////////////////////////////////////////////////////////////////////////////
setUp : function () {
cacheProperties = AQL_QUERY_CACHE_PROPERTIES();
AQL_QUERY_CACHE_INVALIDATE();
db._drop("UnitTestsAhuacatlQueryCache1");
db._drop("UnitTestsAhuacatlQueryCache2");
c1 = db._create("UnitTestsAhuacatlQueryCache1");
c2 = db._create("UnitTestsAhuacatlQueryCache2");
},
////////////////////////////////////////////////////////////////////////////////
/// @brief tear down
////////////////////////////////////////////////////////////////////////////////
tearDown : function () {
db._drop("UnitTestsAhuacatlQueryCache1");
db._drop("UnitTestsAhuacatlQueryCache2");
c1 = null;
c2 = null;
AQL_QUERY_CACHE_PROPERTIES(cacheProperties);
AQL_QUERY_CACHE_INVALIDATE();
},
////////////////////////////////////////////////////////////////////////////////
/// @brief test setting modes
////////////////////////////////////////////////////////////////////////////////
testModes : function () {
var result;
result = AQL_QUERY_CACHE_PROPERTIES({ mode: "off" });
assertEqual("off", result.mode);
result = AQL_QUERY_CACHE_PROPERTIES();
assertEqual("off", result.mode);
result = AQL_QUERY_CACHE_PROPERTIES({ mode: "on" });
assertEqual("on", result.mode);
result = AQL_QUERY_CACHE_PROPERTIES();
assertEqual("on", result.mode);
result = AQL_QUERY_CACHE_PROPERTIES({ mode: "demand" });
assertEqual("demand", result.mode);
result = AQL_QUERY_CACHE_PROPERTIES();
assertEqual("demand", result.mode);
},
testInvalidationAfterInsertSingle : function () {
var query = "FOR doc IN @@collection SORT doc.value RETURN doc.value";
var result;
c1.save({ value: 1 });
AQL_QUERY_CACHE_PROPERTIES({ mode: "on" });
result = AQL_EXECUTE(query, { "@collection": c1.name() });
assertFalse(result.cached);
assertEqual([ 1 ], result.json);
result = AQL_EXECUTE(query, { "@collection": c1.name() });
assertTrue(result.cached);
assertEqual([ 1 ], result.json);
c1.save({ value: 2 }); // this will invalidate cache
result = AQL_EXECUTE(query, { "@collection": c1.name() });
assertFalse(result.cached);
assertEqual([ 1, 2 ], result.json);
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the test suite
////////////////////////////////////////////////////////////////////////////////
jsunity.run(ahuacatlQueryCacheTestSuite);
return jsunity.done();
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
// End: