mirror of https://gitee.com/bigwinds/arangodb
fixed cached lookups of collections on the server, which may have caused spurious problems after collection rename operations
This commit is contained in:
parent
d2b86de370
commit
ff80fafba5
11
CHANGELOG
11
CHANGELOG
|
@ -104,6 +104,17 @@ v2.3.0 (XXXX-XX-XX)
|
||||||
storing JavaScript date objects in the database in a sensible manner.
|
storing JavaScript date objects in the database in a sensible manner.
|
||||||
|
|
||||||
|
|
||||||
|
v2.2.x (????-??-??)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
* fixed issue #961: allow non-JSON values in undocument request bodies
|
||||||
|
|
||||||
|
* fixed issue 1028: libicu is now statically linked
|
||||||
|
|
||||||
|
* fixed cached lookups of collections on the server, which may have caused spurious
|
||||||
|
problems after collection rename operations
|
||||||
|
|
||||||
|
|
||||||
v2.2.4 (2014-XX-XX)
|
v2.2.4 (2014-XX-XX)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|
|
@ -433,6 +433,7 @@ SHELL_COMMON = \
|
||||||
@top_srcdir@/js/common/tests/shell-keygen.js \
|
@top_srcdir@/js/common/tests/shell-keygen.js \
|
||||||
@top_srcdir@/js/common/tests/shell-keygen-noncluster.js \
|
@top_srcdir@/js/common/tests/shell-keygen-noncluster.js \
|
||||||
@top_srcdir@/js/common/tests/shell-index-ensure.js \
|
@top_srcdir@/js/common/tests/shell-index-ensure.js \
|
||||||
|
@top_srcdir@/js/common/tests/shell-rename-noncluster.js \
|
||||||
@top_srcdir@/js/common/tests/shell-simple-query.js \
|
@top_srcdir@/js/common/tests/shell-simple-query.js \
|
||||||
@top_srcdir@/js/common/tests/shell-statement.js \
|
@top_srcdir@/js/common/tests/shell-statement.js \
|
||||||
@top_srcdir@/js/common/tests/shell-transactions.js \
|
@top_srcdir@/js/common/tests/shell-transactions.js \
|
||||||
|
|
|
@ -214,6 +214,7 @@ v8::Handle<v8::Object> WrapCollection (TRI_vocbase_col_t const* collection) {
|
||||||
|
|
||||||
result->Set(v8g->_IdKey, V8CollectionId(collection->_cid), v8::ReadOnly);
|
result->Set(v8g->_IdKey, V8CollectionId(collection->_cid), v8::ReadOnly);
|
||||||
result->Set(v8g->_DbNameKey, v8::String::New(collection->_dbName));
|
result->Set(v8g->_DbNameKey, v8::String::New(collection->_dbName));
|
||||||
|
result->Set(v8g->VersionKey, v8::Number::New((double) collection->_internalVersion), v8::DontEnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
return scope.Close(result);
|
return scope.Close(result);
|
||||||
|
|
|
@ -39,22 +39,26 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief free a coordinator collection
|
/// @brief free a coordinator collection
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void FreeCoordinatorCollection (TRI_vocbase_col_t* collection);
|
void FreeCoordinatorCollection (TRI_vocbase_col_t* collection);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief releases a collection
|
/// @brief releases a collection
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ReleaseCollection (TRI_vocbase_col_t const* collection);
|
void ReleaseCollection (TRI_vocbase_col_t const* collection);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief convert a collection info into a TRI_vocbase_col_t
|
/// @brief convert a collection info into a TRI_vocbase_col_t
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TRI_vocbase_col_t* CoordinatorCollection (TRI_vocbase_t* vocbase,
|
TRI_vocbase_col_t* CoordinatorCollection (TRI_vocbase_t* vocbase,
|
||||||
triagens::arango::CollectionInfo const& ci);
|
triagens::arango::CollectionInfo const& ci);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief check if a name belongs to a collection
|
/// @brief check if a name belongs to a collection
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool EqualCollection (triagens::arango::CollectionNameResolver const* resolver,
|
bool EqualCollection (triagens::arango::CollectionNameResolver const* resolver,
|
||||||
std::string const& collectionName,
|
std::string const& collectionName,
|
||||||
TRI_vocbase_col_t const* collection);
|
TRI_vocbase_col_t const* collection);
|
||||||
|
@ -62,6 +66,7 @@ bool EqualCollection (triagens::arango::CollectionNameResolver const* resolver,
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief wraps a TRI_vocbase_col_t
|
/// @brief wraps a TRI_vocbase_col_t
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
v8::Handle<v8::Object> WrapCollection (TRI_vocbase_col_t const* collection);
|
v8::Handle<v8::Object> WrapCollection (TRI_vocbase_col_t const* collection);
|
||||||
|
|
||||||
void TRI_InitV8collection (v8::Handle<v8::Context> context,
|
void TRI_InitV8collection (v8::Handle<v8::Context> context,
|
||||||
|
|
|
@ -1414,7 +1414,7 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> const name,
|
||||||
|
|
||||||
if (*key == '_') {
|
if (*key == '_') {
|
||||||
// special treatment for all properties starting with _
|
// special treatment for all properties starting with _
|
||||||
v8::Local<v8::String> const l = v8::String::New(key);
|
v8::Local<v8::String> const l = v8::String::New(key, keyLength);
|
||||||
|
|
||||||
if (holder->HasRealNamedProperty(l)) {
|
if (holder->HasRealNamedProperty(l)) {
|
||||||
// some internal function inside db
|
// some internal function inside db
|
||||||
|
@ -1442,6 +1442,7 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> const name,
|
||||||
TRI_READ_LOCK_STATUS_VOCBASE_COL(collection);
|
TRI_READ_LOCK_STATUS_VOCBASE_COL(collection);
|
||||||
TRI_vocbase_col_status_e status = collection->_status;
|
TRI_vocbase_col_status_e status = collection->_status;
|
||||||
TRI_voc_cid_t cid = collection->_cid;
|
TRI_voc_cid_t cid = collection->_cid;
|
||||||
|
uint32_t internalVersion = collection->_internalVersion;
|
||||||
TRI_READ_UNLOCK_STATUS_VOCBASE_COL(collection);
|
TRI_READ_UNLOCK_STATUS_VOCBASE_COL(collection);
|
||||||
|
|
||||||
// check if the collection is still alive
|
// check if the collection is still alive
|
||||||
|
@ -1450,13 +1451,17 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> const name,
|
||||||
|
|
||||||
if (value->Has(v8g->_IdKey)) {
|
if (value->Has(v8g->_IdKey)) {
|
||||||
TRI_voc_cid_t cachedCid = static_cast<TRI_voc_cid_t>(TRI_ObjectToUInt64(value->Get(v8g->_IdKey), true));
|
TRI_voc_cid_t cachedCid = static_cast<TRI_voc_cid_t>(TRI_ObjectToUInt64(value->Get(v8g->_IdKey), true));
|
||||||
|
uint32_t cachedVersion = (uint32_t) TRI_ObjectToInt64(value->Get(v8g->VersionKey));
|
||||||
|
|
||||||
if (cachedCid == cid) {
|
if (cachedCid == cid && cachedVersion == internalVersion) {
|
||||||
// cache hit
|
// cache hit
|
||||||
return scope.Close(value);
|
return scope.Close(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cid has changed (i.e. collection has been dropped and re-created)
|
// store the updated version number in the object for future comparisons
|
||||||
|
value->Set(v8g->VersionKey, v8::Number::New((double) internalVersion), v8::DontEnum);
|
||||||
|
|
||||||
|
// cid has changed (i.e. collection has been dropped and re-created) or version has changed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,18 +476,19 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
|
||||||
// create the init object
|
// create the init object
|
||||||
TRI_vocbase_col_t init;
|
TRI_vocbase_col_t init;
|
||||||
|
|
||||||
init._vocbase = vocbase;
|
init._vocbase = vocbase;
|
||||||
init._cid = cid;
|
init._cid = cid;
|
||||||
init._planId = 0;
|
init._planId = 0;
|
||||||
init._type = static_cast<TRI_col_type_t>(type);
|
init._type = static_cast<TRI_col_type_t>(type);
|
||||||
|
init._internalVersion = 0;
|
||||||
|
|
||||||
init._status = TRI_VOC_COL_STATUS_CORRUPTED;
|
init._status = TRI_VOC_COL_STATUS_CORRUPTED;
|
||||||
init._collection = nullptr;
|
init._collection = nullptr;
|
||||||
|
|
||||||
// default flags: everything is allowed
|
// default flags: everything is allowed
|
||||||
init._canDrop = true;
|
init._canDrop = true;
|
||||||
init._canRename = true;
|
init._canRename = true;
|
||||||
init._canUnload = true;
|
init._canUnload = true;
|
||||||
|
|
||||||
// check for special system collection names
|
// check for special system collection names
|
||||||
if (TRI_IsSystemNameCollection(name)) {
|
if (TRI_IsSystemNameCollection(name)) {
|
||||||
|
@ -809,6 +810,9 @@ static int RenameCollection (TRI_vocbase_t* vocbase,
|
||||||
|
|
||||||
TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
|
TRI_WRITE_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
|
||||||
|
|
||||||
|
// to prevent caching
|
||||||
|
collection->_internalVersion++;
|
||||||
|
|
||||||
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
|
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
|
||||||
|
|
||||||
if (! writeMarker) {
|
if (! writeMarker) {
|
||||||
|
@ -1159,6 +1163,7 @@ static int LoadCollectionVocBase (TRI_vocbase_t* vocbase,
|
||||||
return TRI_set_errno(TRI_ERROR_ARANGO_CORRUPTED_COLLECTION);
|
return TRI_set_errno(TRI_ERROR_ARANGO_CORRUPTED_COLLECTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
collection->_internalVersion = 0;
|
||||||
collection->_collection = document;
|
collection->_collection = document;
|
||||||
collection->_status = TRI_VOC_COL_STATUS_LOADED;
|
collection->_status = TRI_VOC_COL_STATUS_LOADED;
|
||||||
TRI_CopyString(collection->_path, document->_directory, sizeof(collection->_path) - 1);
|
TRI_CopyString(collection->_path, document->_directory, sizeof(collection->_path) - 1);
|
||||||
|
|
|
@ -382,6 +382,9 @@ typedef struct TRI_vocbase_col_s {
|
||||||
|
|
||||||
TRI_read_write_lock_t _lock; // lock protecting the status and name
|
TRI_read_write_lock_t _lock; // lock protecting the status and name
|
||||||
|
|
||||||
|
uint32_t _internalVersion; // is incremented when a collection is renamed
|
||||||
|
// this is used to prevent caching of collection objects
|
||||||
|
// with "wrong" names in the "db" object
|
||||||
TRI_vocbase_col_status_e _status; // status of the collection
|
TRI_vocbase_col_status_e _status; // status of the collection
|
||||||
struct TRI_document_collection_t* _collection; // NULL or pointer to loaded collection
|
struct TRI_document_collection_t* _collection; // NULL or pointer to loaded collection
|
||||||
char _name[TRI_COL_NAME_LENGTH + 1]; // name of the collection
|
char _name[TRI_COL_NAME_LENGTH + 1]; // name of the collection
|
||||||
|
|
|
@ -731,7 +731,7 @@
|
||||||
var result;
|
var result;
|
||||||
if (this.type === 'document') {
|
if (this.type === 'document') {
|
||||||
result = this.documentStore.deleteDocument(
|
result = this.documentStore.deleteDocument(
|
||||||
this.collection.collectionID, this.docid
|
this.collection.collectionID, this.docid
|
||||||
);
|
);
|
||||||
if (result) {
|
if (result) {
|
||||||
//on success
|
//on success
|
||||||
|
@ -759,7 +759,7 @@
|
||||||
$('#documentsTableID').dataTable().fnGetPosition(row)
|
$('#documentsTableID').dataTable().fnGetPosition(row)
|
||||||
);
|
);
|
||||||
$('#documentsTableID').dataTable().fnClearTable();
|
$('#documentsTableID').dataTable().fnClearTable();
|
||||||
this.collection.getDocuments(this.getDocsCallback.bind(this));
|
this.collection.getDocuments(this.getDocsCallback.bind(this));
|
||||||
$('#docDeleteModal').modal('hide');
|
$('#docDeleteModal').modal('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test the random document selector
|
||||||
|
///
|
||||||
|
/// @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 arangodb = require("org/arangodb");
|
||||||
|
var db = arangodb.db;
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// --SECTION-- RenameSuite
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test suite
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
function RenameSuite () {
|
||||||
|
var cn1 = "UnitTestsRename1";
|
||||||
|
var cn2 = "UnitTestsRename2";
|
||||||
|
|
||||||
|
return {
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief set up
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
setUp : function () {
|
||||||
|
db._drop(cn1);
|
||||||
|
db._drop(cn2);
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief tear down
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
tearDown : function () {
|
||||||
|
db._drop(cn2);
|
||||||
|
db._drop(cn1);
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief check AQL query after renaming collection
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testAqlAfterRename : function () {
|
||||||
|
var c = db._create(cn1);
|
||||||
|
for (var i = 0; i < 100000; ++i) {
|
||||||
|
db.UnitTestsRename1.save({ value: i });
|
||||||
|
}
|
||||||
|
c.rename(cn2);
|
||||||
|
db._create(cn1);
|
||||||
|
for (i = 0; i < 100; ++i) {
|
||||||
|
db.UnitTestsRename1.save({ value: i });
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = db._query("FOR i IN " + cn1 + " LIMIT 99, 2 RETURN i").toArray();
|
||||||
|
assertEqual(1, result.length);
|
||||||
|
assertMatch(/^UnitTestsRename1\//, result[0]._id);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// --SECTION-- main
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief executes the test suite
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
jsunity.run(RenameSuite);
|
||||||
|
|
||||||
|
return jsunity.done();
|
||||||
|
|
||||||
|
// Local Variables:
|
||||||
|
// mode: outline-minor
|
||||||
|
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||||
|
// End:
|
||||||
|
|
|
@ -115,6 +115,7 @@ TRI_v8_global_s::TRI_v8_global_s (v8::Isolate* isolate)
|
||||||
UrlKey(),
|
UrlKey(),
|
||||||
UserKey(),
|
UserKey(),
|
||||||
ValueKey(),
|
ValueKey(),
|
||||||
|
VersionKey(),
|
||||||
WaitForSyncKey(),
|
WaitForSyncKey(),
|
||||||
|
|
||||||
_FromKey(),
|
_FromKey(),
|
||||||
|
@ -198,6 +199,7 @@ TRI_v8_global_s::TRI_v8_global_s (v8::Isolate* isolate)
|
||||||
UrlKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("url"));
|
UrlKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("url"));
|
||||||
UserKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("user"));
|
UserKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("user"));
|
||||||
ValueKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("value"));
|
ValueKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("value"));
|
||||||
|
VersionKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("version"));
|
||||||
WaitForSyncKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("waitForSync"));
|
WaitForSyncKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("waitForSync"));
|
||||||
|
|
||||||
_FromKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("_from"));
|
_FromKey = v8::Persistent<v8::String>::New(isolate, TRI_V8_SYMBOL("_from"));
|
||||||
|
|
|
@ -700,6 +700,12 @@ typedef struct TRI_v8_global_s {
|
||||||
|
|
||||||
v8::Persistent<v8::String> ValueKey;
|
v8::Persistent<v8::String> ValueKey;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief "version" key
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
v8::Persistent<v8::String> VersionKey;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief "waitForSync" key name
|
/// @brief "waitForSync" key name
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue