mirror of https://gitee.com/bigwinds/arangodb
fix collection name handling in the face of parallel renames
This commit is contained in:
parent
3b547f9416
commit
ca8935ae2a
|
|
@ -280,12 +280,13 @@ bool RestDocumentHandler::createDocument () {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (! checkCreateCollection(collection, getCollectionType())) {
|
||||
CollectionNameResolver resolver(_vocbase);
|
||||
if (! checkCreateCollection(resolver, collection, getCollectionType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// find and load collection given by name or identifier
|
||||
SelfContainedWriteTransaction<RestTransactionContext> trx(_vocbase, collection);
|
||||
SingleCollectionWriteTransaction<StandaloneTransaction<RestTransactionContext>, 1> trx(_vocbase, resolver.getCollectionId(collection));
|
||||
|
||||
// .............................................................................
|
||||
// inside write transaction
|
||||
|
|
@ -407,7 +408,8 @@ bool RestDocumentHandler::readSingleDocument (bool generateBody) {
|
|||
string key = suffix[1];
|
||||
|
||||
// find and load collection given by name or identifier
|
||||
SingleCollectionReadOnlyTransaction<StandaloneTransaction<RestTransactionContext> > trx(_vocbase, collection);
|
||||
CollectionNameResolver resolver(_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<StandaloneTransaction<RestTransactionContext> > trx(_vocbase, resolver.getCollectionId(collection));
|
||||
|
||||
// .............................................................................
|
||||
// inside read transaction
|
||||
|
|
@ -445,7 +447,7 @@ bool RestDocumentHandler::readSingleDocument (bool generateBody) {
|
|||
|
||||
if (ifNoneRid == 0) {
|
||||
if (ifRid == 0 || ifRid == rid) {
|
||||
generateDocument(collection, document, trx.vocbase(), trx.shaper(), generateBody);
|
||||
generateDocument(resolver, collection, document, trx.shaper(), generateBody);
|
||||
}
|
||||
else {
|
||||
generatePreconditionFailed(collection, document->_key, rid);
|
||||
|
|
@ -461,7 +463,7 @@ bool RestDocumentHandler::readSingleDocument (bool generateBody) {
|
|||
}
|
||||
else {
|
||||
if (ifRid == 0 || ifRid == rid) {
|
||||
generateDocument(collection, document, trx.vocbase(), trx.shaper(), generateBody);
|
||||
generateDocument(resolver, collection, document, trx.shaper(), generateBody);
|
||||
}
|
||||
else {
|
||||
generatePreconditionFailed(collection, document->_key, rid);
|
||||
|
|
@ -491,7 +493,8 @@ bool RestDocumentHandler::readAllDocuments () {
|
|||
string collection = _request->value("collection", found);
|
||||
|
||||
// find and load collection given by name or identifier
|
||||
SingleCollectionReadOnlyTransaction<StandaloneTransaction<RestTransactionContext> > trx(_vocbase, collection);
|
||||
CollectionNameResolver resolver(_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<StandaloneTransaction<RestTransactionContext> > trx(_vocbase, resolver.getCollectionId(collection));
|
||||
|
||||
vector<string> ids;
|
||||
|
||||
|
|
@ -522,7 +525,7 @@ bool RestDocumentHandler::readAllDocuments () {
|
|||
string result("{ \"documents\" : [\n");
|
||||
|
||||
bool first = true;
|
||||
string prefix = '"' + DOCUMENT_PATH + '/' + trx.collectionName() + '/';
|
||||
string prefix = '"' + DOCUMENT_PATH + '/' + collection + '/';
|
||||
|
||||
for (vector<string>::iterator i = ids.begin(); i != ids.end(); ++i) {
|
||||
// collection names do not need to be JSON-escaped
|
||||
|
|
@ -764,11 +767,12 @@ bool RestDocumentHandler::modifyDocument (bool isPatch) {
|
|||
|
||||
// extract or chose the update policy
|
||||
TRI_doc_update_policy_e policy = extractUpdatePolicy();
|
||||
|
||||
// find and load collection given by name or identifier
|
||||
SelfContainedWriteTransaction<RestTransactionContext> trx(_vocbase, collection);
|
||||
|
||||
TRI_doc_mptr_t* document = 0;
|
||||
|
||||
// find and load collection given by name or identifier
|
||||
CollectionNameResolver resolver(_vocbase);
|
||||
SingleCollectionWriteTransaction<StandaloneTransaction<RestTransactionContext>, 1> trx(_vocbase, resolver.getCollectionId(collection));
|
||||
|
||||
// .............................................................................
|
||||
// inside write transaction
|
||||
|
|
@ -915,7 +919,7 @@ bool RestDocumentHandler::deleteDocument () {
|
|||
// extract the revision
|
||||
TRI_voc_rid_t revision = extractRevision("if-match", "rev");
|
||||
|
||||
// extract or chose the update policy
|
||||
// extract or choose the update policy
|
||||
TRI_doc_update_policy_e policy = extractUpdatePolicy();
|
||||
|
||||
if (policy == TRI_DOC_UPDATE_ILLEGAL) {
|
||||
|
|
@ -925,7 +929,8 @@ bool RestDocumentHandler::deleteDocument () {
|
|||
return false;
|
||||
}
|
||||
|
||||
SelfContainedWriteTransaction<RestTransactionContext> trx(_vocbase, collection);
|
||||
CollectionNameResolver resolver(_vocbase);
|
||||
SingleCollectionWriteTransaction<StandaloneTransaction<RestTransactionContext>, 1> trx(_vocbase, resolver.getCollectionId(collection));
|
||||
|
||||
// .............................................................................
|
||||
// inside write transaction
|
||||
|
|
|
|||
|
|
@ -153,12 +153,13 @@ bool RestEdgeHandler::createDocument () {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (! checkCreateCollection(collection, getCollectionType())) {
|
||||
CollectionNameResolver resolver(_vocbase);
|
||||
if (! checkCreateCollection(resolver, collection, getCollectionType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// find and load collection given by name or identifier
|
||||
SelfContainedWriteTransaction<RestTransactionContext> trx(_vocbase, collection);
|
||||
SingleCollectionWriteTransaction<StandaloneTransaction<RestTransactionContext>, 1> trx(_vocbase, resolver.getCollectionId(collection));
|
||||
|
||||
// .............................................................................
|
||||
// inside write transaction
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include "BasicsC/string-buffer.h"
|
||||
#include "BasicsC/strings.h"
|
||||
#include "Rest/HttpRequest.h"
|
||||
#include "Utils/ImportTransaction.h"
|
||||
#include "Utilities/ResourceHolder.h"
|
||||
#include "VocBase/document-collection.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
|
@ -215,12 +214,13 @@ bool RestImportHandler::createByDocumentsLines () {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (! checkCreateCollection(collection, TRI_COL_TYPE_DOCUMENT)) {
|
||||
CollectionNameResolver resolver(_vocbase);
|
||||
if (! checkCreateCollection(resolver, collection, TRI_COL_TYPE_DOCUMENT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// find and load collection given by name or identifier
|
||||
ImportTransaction<StandaloneTransaction<RestTransactionContext> > trx(_vocbase, collection);
|
||||
SingleCollectionWriteTransaction<StandaloneTransaction<RestTransactionContext>, UINT64_MAX> trx(_vocbase, resolver.getCollectionId(collection));
|
||||
|
||||
// .............................................................................
|
||||
// inside write transaction
|
||||
|
|
@ -362,12 +362,13 @@ bool RestImportHandler::createByDocumentsList () {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (! checkCreateCollection(collection, TRI_COL_TYPE_DOCUMENT)) {
|
||||
CollectionNameResolver resolver(_vocbase);
|
||||
if (! checkCreateCollection(resolver, collection, TRI_COL_TYPE_DOCUMENT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// find and load collection given by name or identifier
|
||||
ImportTransaction<StandaloneTransaction<RestTransactionContext> > trx(_vocbase, collection);
|
||||
SingleCollectionWriteTransaction<StandaloneTransaction<RestTransactionContext>, UINT64_MAX> trx(_vocbase, resolver.getCollectionId(collection));
|
||||
|
||||
// .............................................................................
|
||||
// inside write transaction
|
||||
|
|
@ -513,12 +514,13 @@ bool RestImportHandler::createByKeyValueList () {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (! checkCreateCollection(collection, TRI_COL_TYPE_DOCUMENT)) {
|
||||
CollectionNameResolver resolver(_vocbase);
|
||||
if (! checkCreateCollection(resolver, collection, TRI_COL_TYPE_DOCUMENT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// find and load collection given by name or identifier
|
||||
ImportTransaction<StandaloneTransaction<RestTransactionContext> > trx(_vocbase, collection);
|
||||
SingleCollectionWriteTransaction<StandaloneTransaction<RestTransactionContext>, UINT64_MAX> trx(_vocbase, resolver.getCollectionId(collection));
|
||||
|
||||
// .............................................................................
|
||||
// inside write transaction
|
||||
|
|
|
|||
|
|
@ -164,7 +164,8 @@ RestVocbaseBaseHandler::~RestVocbaseBaseHandler () {
|
|||
/// happen, and the collection name will not be checked
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RestVocbaseBaseHandler::checkCreateCollection (const string& name,
|
||||
bool RestVocbaseBaseHandler::checkCreateCollection (const CollectionNameResolver& resolver,
|
||||
const string& name,
|
||||
const TRI_col_type_e type) {
|
||||
bool found;
|
||||
char const* valueStr = _request->value("createCollection", found);
|
||||
|
|
@ -355,9 +356,9 @@ void RestVocbaseBaseHandler::generateNotModified (const string& etag) {
|
|||
/// @brief generates next entry from a result set
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RestVocbaseBaseHandler::generateDocument (const string& collectionName,
|
||||
void RestVocbaseBaseHandler::generateDocument (const triagens::arango::CollectionNameResolver& resolver,
|
||||
const string& collectionName,
|
||||
TRI_doc_mptr_t const* document,
|
||||
TRI_vocbase_t* const vocbase,
|
||||
TRI_shaper_t* shaper,
|
||||
const bool generateBody) {
|
||||
if (document == 0) {
|
||||
|
|
@ -399,8 +400,8 @@ void RestVocbaseBaseHandler::generateDocument (const string& collectionName,
|
|||
|
||||
if (type == TRI_DOC_MARKER_KEY_EDGE) {
|
||||
TRI_doc_edge_key_marker_t* marker = (TRI_doc_edge_key_marker_t*) document->_data;
|
||||
const string from = DocumentHelper::assembleDocumentId(vocbase, marker->_fromCid, string((char*) marker + marker->_offsetFromKey));
|
||||
const string to = DocumentHelper::assembleDocumentId(vocbase, marker->_toCid, string((char*) marker + marker->_offsetToKey));
|
||||
const string from = DocumentHelper::assembleDocumentId(resolver.getCollectionName(marker->_fromCid), string((char*) marker + marker->_offsetFromKey));
|
||||
const string to = DocumentHelper::assembleDocumentId(resolver.getCollectionName(marker->_toCid), string((char*) marker + marker->_offsetToKey));
|
||||
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, &augmented, "_from", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, from.c_str()));
|
||||
TRI_Insert3ArrayJson(TRI_UNKNOWN_MEM_ZONE, &augmented, "_to", TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, to.c_str()));
|
||||
|
|
|
|||
|
|
@ -35,9 +35,10 @@
|
|||
|
||||
#include "Logger/Logger.h"
|
||||
#include "Rest/HttpResponse.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "Utils/RestTransactionContext.h"
|
||||
#include "Utils/SelfContainedWriteTransaction.h"
|
||||
#include "Utils/SingleCollectionReadOnlyTransaction.h"
|
||||
#include "Utils/SingleCollectionWriteTransaction.h"
|
||||
#include "Utils/StandaloneTransaction.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -173,7 +174,9 @@ namespace triagens {
|
|||
/// happen, and the collection name will not be checked
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool checkCreateCollection (const string&, const TRI_col_type_e);
|
||||
bool checkCreateCollection (const triagens::arango::CollectionNameResolver&,
|
||||
const string&,
|
||||
const TRI_col_type_e);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates a HTTP 201 or 202 response
|
||||
|
|
@ -256,9 +259,9 @@ namespace triagens {
|
|||
/// @brief generates first entry from a result set
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void generateDocument (const string&,
|
||||
void generateDocument (const triagens::arango::CollectionNameResolver&,
|
||||
const string&,
|
||||
TRI_doc_mptr_t const*,
|
||||
TRI_vocbase_t* const,
|
||||
TRI_shaper_t*,
|
||||
const bool);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,188 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief collection name resolver
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2004-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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIAGENS_ARANGOD_UTILS_COLLECTION_NAME_RESOLVER_H
|
||||
#define TRIAGENS_ARANGOD_UTILS_COLLECTION_NAME_RESOLVER_H 1
|
||||
|
||||
#include "BasicsC/common.h"
|
||||
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
namespace triagens {
|
||||
namespace arango {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class CollectionNameResolver
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class CollectionNameResolver {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup ArangoDB
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the resolver
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CollectionNameResolver (TRI_vocbase_t* vocbase) :
|
||||
_vocbase(vocbase), _resolvedNames(), _resolvedIds() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroy the resolver
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~CollectionNameResolver () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup ArangoDB
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief look up a collection id for a collection name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_voc_cid_t getCollectionId (const string& name) {
|
||||
const TRI_vocbase_col_t* collection = getCollectionStruct(name);
|
||||
|
||||
if (collection != 0) {
|
||||
return collection->_cid;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief look up a collection struct for a collection name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const TRI_vocbase_col_t* getCollectionStruct (const string& name) const {
|
||||
map<string, const TRI_vocbase_col_t*>::iterator it = _resolvedNames.find(name);
|
||||
|
||||
if (it != _resolvedNames.end()) {
|
||||
return (*it).second;
|
||||
}
|
||||
|
||||
const TRI_vocbase_col_t* collection = TRI_LookupCollectionByNameVocBase(_vocbase, name.c_str());
|
||||
if (collection != 0) {
|
||||
_resolvedNames[name] = collection;
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief look up a collection name for a collection id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string getCollectionName (const TRI_voc_cid_t cid) const {
|
||||
map<TRI_voc_cid_t, string>::iterator it = _resolvedIds.find(cid);
|
||||
|
||||
if (it != _resolvedIds.end()) {
|
||||
return (*it).second;
|
||||
}
|
||||
|
||||
char* n = TRI_GetCollectionNameByIdVocBase(_vocbase, cid);
|
||||
if (n == 0) {
|
||||
return "_unknown";
|
||||
}
|
||||
|
||||
string name(n);
|
||||
|
||||
_resolvedIds[cid] = name;
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, n);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup ArangoDB
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief vocbase base pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vocbase_t* _vocbase;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief collection id => collection struct map
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
mutable std::map<std::string, const TRI_vocbase_col_t*> _resolvedNames;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief collection id => collection name map
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
mutable std::map<TRI_voc_cid_t, std::string> _resolvedIds;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief document utilitiy functions
|
||||
/// @brief document utility functions
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
|
|
@ -28,8 +28,6 @@
|
|||
#ifndef TRIAGENS_ARANGOD_UTILS_DOCUMENT_HELPER_H
|
||||
#define TRIAGENS_ARANGOD_UTILS_DOCUMENT_HELPER_H 1
|
||||
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
namespace triagens {
|
||||
namespace arango {
|
||||
|
||||
|
|
@ -93,40 +91,6 @@ namespace triagens {
|
|||
return assembleDocumentId(collectionName, string(key));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief assemble a document id from a collection id and a string key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static string assembleDocumentId (TRI_vocbase_t* const vocbase,
|
||||
const TRI_voc_cid_t cid,
|
||||
const string& key) {
|
||||
static const string UnknownCollection = "_unknown";
|
||||
|
||||
TRI_vocbase_col_t const* collection = TRI_LookupCollectionByIdVocBase(vocbase, cid);
|
||||
if (collection == 0) {
|
||||
return assembleDocumentId(UnknownCollection, key);
|
||||
}
|
||||
|
||||
// TODO: can the name be deleted while we're using it?
|
||||
return assembleDocumentId(collection->_name, key);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief assemble a document id from a collection id and a char* key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static string assembleDocumentId (TRI_vocbase_t* const vocbase,
|
||||
const TRI_voc_cid_t cid,
|
||||
const TRI_voc_key_t key) {
|
||||
static const string UnknownKey = "_deleted";
|
||||
|
||||
if (key == 0) {
|
||||
return assembleDocumentId(vocbase, cid, UnknownKey);
|
||||
}
|
||||
|
||||
return assembleDocumentId(vocbase, cid, string(key));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -1,89 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief wrapper for single collection, multi-operation write transactions
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2004-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 2011-2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIAGENS_UTILS_IMPORT_TRANSACTION_H
|
||||
#define TRIAGENS_UTILS_IMPORT_TRANSACTION_H 1
|
||||
|
||||
#include "Utils/SingleCollectionWriteTransaction.h"
|
||||
|
||||
struct TRI_vocbase_s;
|
||||
|
||||
namespace triagens {
|
||||
namespace arango {
|
||||
|
||||
template<typename T>
|
||||
class ImportTransaction : public SingleCollectionWriteTransaction<T, UINT64_MAX> {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class ImportTransaction
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup ArangoDB
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the transaction, using a collection object
|
||||
///
|
||||
/// An import transaction operates on a single collection and may execute any
|
||||
/// number of writes on it.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ImportTransaction (struct TRI_vocbase_s* const vocbase,
|
||||
const string& name) :
|
||||
SingleCollectionWriteTransaction<T, UINT64_MAX>(vocbase, name) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief end the transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~ImportTransaction () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief wrapper for single collection, single operation write transactions
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2004-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 2011-2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIAGENS_UTILS_SELF_CONTAINED_WRITE_TRANSACTION_H
|
||||
#define TRIAGENS_UTILS_SELF_CONTAINED_WRITE_TRANSACTION_H 1
|
||||
|
||||
#include "Utils/SingleCollectionWriteTransaction.h"
|
||||
|
||||
#include "Utils/StandaloneTransaction.h"
|
||||
|
||||
struct TRI_vocbase_s;
|
||||
|
||||
namespace triagens {
|
||||
namespace arango {
|
||||
|
||||
template<typename C>
|
||||
class SelfContainedWriteTransaction : public SingleCollectionWriteTransaction<StandaloneTransaction<C>, 1> {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class SelfContainedWriteTransaction
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup ArangoDB
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create the transaction, using a collection object
|
||||
///
|
||||
/// A self contained write transaction operates on a single collection and may
|
||||
/// execute at most one write operation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SelfContainedWriteTransaction (struct TRI_vocbase_s* const vocbase,
|
||||
const string& name) :
|
||||
SingleCollectionWriteTransaction<StandaloneTransaction<C>, 1>(vocbase, name) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief end the transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~SelfContainedWriteTransaction () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
||||
|
|
@ -63,8 +63,8 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SingleCollectionReadOnlyTransaction (struct TRI_vocbase_s* const vocbase,
|
||||
const string& name) :
|
||||
SingleCollectionTransaction<T>(vocbase, name, TRI_TRANSACTION_READ) {
|
||||
const TRI_transaction_cid_t cid) :
|
||||
SingleCollectionTransaction<T>(vocbase, cid, TRI_TRANSACTION_READ) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -66,18 +66,16 @@ namespace triagens {
|
|||
/// @brief create the transaction, using a collection object
|
||||
///
|
||||
/// A single collection transaction operates on a single collection (you guessed
|
||||
/// it), and may execute at most one write operation if it is a write
|
||||
/// transaction. It may execute multiple reads, though.
|
||||
/// it)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SingleCollectionTransaction (TRI_vocbase_t* const vocbase,
|
||||
const string& name,
|
||||
const TRI_transaction_cid_t cid,
|
||||
const TRI_transaction_type_e accessType) :
|
||||
Transaction<T>(vocbase, new TransactionCollectionsList(vocbase, name, accessType)),
|
||||
_name(name),
|
||||
_collection(0) {
|
||||
Transaction<T>(vocbase, new TransactionCollectionsList(vocbase, cid, accessType)),
|
||||
_cid(cid) {
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief end the transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -100,27 +98,25 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the name of the underlying collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const string collectionName () const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the underlying primary collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline TRI_primary_collection_t* primaryCollection () {
|
||||
if (_collection == 0) {
|
||||
const vector<TransactionCollection*> collections = this->_collections->getCollections();
|
||||
_collection = TRI_GetCollectionTransaction(this->_trx, collections[0]->getName().c_str());
|
||||
}
|
||||
assert(this->_cid > 0);
|
||||
TRI_vocbase_col_t* collection = TRI_LookupCollectionByIdVocBase(this->_vocbase, this->_cid);
|
||||
|
||||
assert(_collection != 0);
|
||||
assert(_collection->_collection != 0);
|
||||
return _collection->_collection;
|
||||
assert(collection != 0);
|
||||
assert(collection->_collection != 0);
|
||||
return collection->_collection;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the underlying collection's id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline TRI_voc_cid_t cid () {
|
||||
return this->_cid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -139,19 +135,6 @@ namespace triagens {
|
|||
return &primaryCollection()->_barrierList;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the underlying collection's id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline TRI_voc_cid_t cid () {
|
||||
if (_collection == 0) {
|
||||
_collection = TRI_GetCollectionTransaction(this->_trx, this->collectionName().c_str());
|
||||
}
|
||||
|
||||
assert(_collection != 0);
|
||||
return _collection->_cid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief read any (random) document within a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -211,17 +194,7 @@ namespace triagens {
|
|||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief name of the collection used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string _name;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief data structure for the single collection used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vocbase_col_t* _collection;
|
||||
TRI_transaction_cid_t _cid;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SingleCollectionWriteTransaction (TRI_vocbase_t* const vocbase,
|
||||
const string& name) :
|
||||
SingleCollectionTransaction<T>(vocbase, name, TRI_TRANSACTION_WRITE),
|
||||
const TRI_transaction_cid_t cid) :
|
||||
SingleCollectionTransaction<T>(vocbase, cid, TRI_TRANSACTION_WRITE),
|
||||
_numWrites(0),
|
||||
_synchronous(false) {
|
||||
|
||||
|
|
@ -182,6 +182,9 @@ namespace triagens {
|
|||
return this->createCollectionShaped(primary, TRI_DOC_MARKER_KEY_EDGE, key, mptr, shaped, data, forceSync);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief update (replace!) a single document within a transaction,
|
||||
/// using json
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int updateDocument (const string& key,
|
||||
|
|
|
|||
|
|
@ -262,14 +262,6 @@ namespace triagens {
|
|||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the "vocbase"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline TRI_vocbase_t* vocbase () const {
|
||||
return this->_vocbase;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the status of the transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -653,7 +645,7 @@ namespace triagens {
|
|||
|
||||
for (size_t i = 0; i < collections.size(); ++i) {
|
||||
TransactionCollection* c = collections[i];
|
||||
TRI_vocbase_col_t* collection = TRI_CheckCollectionTransaction(this->_trx, c->getName().c_str(), c->getAccessType());
|
||||
TRI_vocbase_col_t* collection = TRI_CheckCollectionTransaction(this->_trx, c->getId(), c->getAccessType());
|
||||
|
||||
if (collection == 0) {
|
||||
return TRI_ERROR_TRANSACTION_UNREGISTERED_COLLECTION;
|
||||
|
|
@ -681,8 +673,8 @@ namespace triagens {
|
|||
for (size_t i = 0; i < collections.size(); ++i) {
|
||||
TransactionCollection* c = collections[i];
|
||||
|
||||
TRX_LOG << "adding collection " << c->getName();
|
||||
int res = TRI_AddCollectionTransaction(this->_trx, c->getName().c_str(), c->getAccessType());
|
||||
TRX_LOG << "adding collection " << c->getId();
|
||||
int res = TRI_AddCollectionTransaction(this->_trx, c->getId(), c->getAccessType());
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -65,9 +65,9 @@ namespace triagens {
|
|||
/// @brief create a collection instance
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TransactionCollection (const string& name,
|
||||
TransactionCollection (const TRI_transaction_cid_t cid,
|
||||
TRI_transaction_type_e accessType) :
|
||||
_name(name),
|
||||
_cid(cid),
|
||||
_accessType(accessType) {
|
||||
}
|
||||
|
||||
|
|
@ -94,11 +94,11 @@ namespace triagens {
|
|||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the name of the collection
|
||||
/// @brief get the id of the collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline const string getName () const {
|
||||
return _name;
|
||||
inline const TRI_transaction_cid_t getId () const {
|
||||
return _cid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -133,10 +133,10 @@ namespace triagens {
|
|||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief collection name
|
||||
/// @brief collection id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const string _name;
|
||||
const TRI_transaction_cid_t _cid;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief collection access type (read or write)
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ namespace triagens {
|
|||
/// @brief typedef for contained collections list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef map<string, TransactionCollection*> ListType;
|
||||
typedef map<TRI_transaction_cid_t, TransactionCollection*> ListType;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
@ -93,11 +93,25 @@ namespace triagens {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a list with a single collection
|
||||
/// @brief create a list with a single collection, based on the collection id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TransactionCollectionsList (TRI_vocbase_t* const vocbase,
|
||||
const string& name,
|
||||
const TRI_transaction_cid_t cid,
|
||||
TRI_transaction_type_e accessType) :
|
||||
_vocbase(vocbase),
|
||||
_collections(),
|
||||
_error(TRI_ERROR_NO_ERROR) {
|
||||
|
||||
addCollection(cid, accessType);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a list with a single collection, based on the collection name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TransactionCollectionsList (TRI_vocbase_t* const vocbase,
|
||||
const string& name,
|
||||
TRI_transaction_type_e accessType) :
|
||||
_vocbase(vocbase),
|
||||
_collections(),
|
||||
|
|
@ -107,7 +121,27 @@ namespace triagens {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a list with multiple collections
|
||||
/// @brief create a list from multiple collection ids
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TransactionCollectionsList (TRI_vocbase_t* const vocbase,
|
||||
const vector<TRI_transaction_cid_t>& readCollections,
|
||||
const vector<TRI_transaction_cid_t>& writeCollections) :
|
||||
_vocbase(vocbase),
|
||||
_collections(),
|
||||
_error(TRI_ERROR_NO_ERROR) {
|
||||
|
||||
for (size_t i = 0; i < readCollections.size(); ++i) {
|
||||
addCollection(readCollections[i], TRI_TRANSACTION_READ);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < writeCollections.size(); ++i) {
|
||||
addCollection(writeCollections[i], TRI_TRANSACTION_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a list with multiple collection names
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TransactionCollectionsList (TRI_vocbase_t* const vocbase,
|
||||
|
|
@ -178,6 +212,14 @@ namespace triagens {
|
|||
return collections;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the number of collections
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline size_t size () const {
|
||||
return _collections.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -194,42 +236,15 @@ namespace triagens {
|
|||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add a collection to the list
|
||||
/// @brief add a collection to the list, using the collection id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void addCollection (const string& name,
|
||||
TRI_transaction_type_e type) {
|
||||
TransactionCollection* addCollection (const TRI_transaction_cid_t cid,
|
||||
TRI_transaction_type_e type) {
|
||||
ListType::iterator it;
|
||||
string realName;
|
||||
|
||||
if (name.empty()) {
|
||||
_error = TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
|
||||
return;
|
||||
}
|
||||
|
||||
const char c = name[0];
|
||||
if (c >= '0' && c <= '9') {
|
||||
// name is passed as a string with the collection id inside
|
||||
|
||||
// look up the collection name for the id
|
||||
TRI_voc_cid_t id = triagens::basics::StringUtils::uint64(name);
|
||||
|
||||
char* n = TRI_GetCollectionNameByIdVocBase(_vocbase, id);
|
||||
if (n == 0) {
|
||||
_error = TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
|
||||
return;
|
||||
}
|
||||
|
||||
realName = string(n);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, n);
|
||||
}
|
||||
else {
|
||||
// name is passed as a "real" name
|
||||
realName = name;
|
||||
}
|
||||
|
||||
// check if we already have the collection in our list
|
||||
it = _collections.find(realName);
|
||||
it = _collections.find(cid);
|
||||
if (it != _collections.end()) {
|
||||
// yes, now update the collection in the list
|
||||
TransactionCollection* c = (*it).second;
|
||||
|
|
@ -239,14 +254,60 @@ namespace triagens {
|
|||
c->setAccessType(type);
|
||||
}
|
||||
|
||||
// TODO: we probably prefer raising an error here
|
||||
return c;
|
||||
}
|
||||
else {
|
||||
// collection not yet contained in our list
|
||||
_collections[realName] = new TransactionCollection(realName, type);
|
||||
// collection not yet contained in the list
|
||||
_collections[cid] = new TransactionCollection(cid, type);
|
||||
|
||||
return _collections[cid];
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add a collection to the list, using the collection name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TransactionCollection* addCollection (const string& name,
|
||||
TRI_transaction_type_e type) {
|
||||
|
||||
if (name.empty()) {
|
||||
_error = TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRI_transaction_cid_t cid;
|
||||
|
||||
// look at the first character in the collection name
|
||||
const char first = name[0];
|
||||
if (first >= '0' && first <= '9') {
|
||||
// name is passed as a string with the collection id inside
|
||||
|
||||
// look up the collection name for the id
|
||||
cid = triagens::basics::StringUtils::uint64(name);
|
||||
|
||||
char* n = TRI_GetCollectionNameByIdVocBase(_vocbase, cid);
|
||||
if (n == 0) {
|
||||
_error = TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, n);
|
||||
}
|
||||
else {
|
||||
// name is passed as a "real" name
|
||||
TRI_vocbase_col_t* col = TRI_LookupCollectionByNameVocBase(_vocbase, name.c_str());
|
||||
if (col == 0) {
|
||||
_error = TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
|
||||
return 0;
|
||||
}
|
||||
|
||||
cid = col->_cid;
|
||||
}
|
||||
|
||||
return addCollection(cid, type);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "HashIndex/hashindex.h"
|
||||
#include "SkipLists/skiplistIndex.h"
|
||||
#include "Utilities/ResourceHolder.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "Utils/EmbeddableTransaction.h"
|
||||
#include "Utils/SingleCollectionReadOnlyTransaction.h"
|
||||
#include "Utils/V8TransactionContext.h"
|
||||
|
|
@ -929,8 +930,7 @@ static int SetupExampleObjectIndex (TRI_hash_index_t* hashIndex,
|
|||
|
||||
static v8::Handle<v8::Value> ExecuteSkiplistQuery (v8::Arguments const& argv,
|
||||
std::string const& signature,
|
||||
const query_t type,
|
||||
const bool lock) {
|
||||
const query_t type) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// extract and use the simple collection
|
||||
|
|
@ -938,24 +938,19 @@ static v8::Handle<v8::Value> ExecuteSkiplistQuery (v8::Arguments const& argv,
|
|||
TRI_vocbase_col_t const* collection;
|
||||
TRI_document_collection_t* document = 0;
|
||||
|
||||
if (lock) {
|
||||
document = TRI_ExtractAndUseSimpleCollection(argv, collection, &err);
|
||||
}
|
||||
else {
|
||||
document = TRI_ExtractSimpleCollection(argv, collection, &err);
|
||||
}
|
||||
document = TRI_ExtractAndUseSimpleCollection(argv, collection, &err);
|
||||
|
||||
if (document == 0) {
|
||||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
assert(collection != 0);
|
||||
|
||||
TRI_primary_collection_t* primary = &document->base;
|
||||
|
||||
// expecting index, example, skip, and limit
|
||||
if (argv.Length() < 2) {
|
||||
if (lock) {
|
||||
TRI_ReleaseCollection(collection);
|
||||
}
|
||||
TRI_ReleaseCollection(collection);
|
||||
|
||||
std::string usage("Usage: ");
|
||||
usage += signature;
|
||||
|
|
@ -965,9 +960,7 @@ static v8::Handle<v8::Value> ExecuteSkiplistQuery (v8::Arguments const& argv,
|
|||
}
|
||||
|
||||
if (! argv[1]->IsObject()) {
|
||||
if (lock) {
|
||||
TRI_ReleaseCollection(collection);
|
||||
}
|
||||
TRI_ReleaseCollection(collection);
|
||||
std::string msg;
|
||||
|
||||
if (type == QUERY_EXAMPLE) {
|
||||
|
|
@ -993,33 +986,28 @@ static v8::Handle<v8::Value> ExecuteSkiplistQuery (v8::Arguments const& argv,
|
|||
|
||||
v8::Handle<v8::Array> documents = v8::Array::New();
|
||||
result->Set(v8::String::New("documents"), documents);
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// inside a read transaction
|
||||
// .............................................................................
|
||||
|
||||
if (lock) {
|
||||
primary->beginRead(primary);
|
||||
}
|
||||
primary->beginRead(primary);
|
||||
|
||||
// extract the index
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(document->base.base._vocbase, collection, argv[0], false, &err);
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(resolver, document->base.base._vocbase, collection, argv[0], false, &err);
|
||||
|
||||
if (idx == 0) {
|
||||
primary->endRead(primary);
|
||||
|
||||
if (lock) {
|
||||
TRI_ReleaseCollection(collection);
|
||||
}
|
||||
TRI_ReleaseCollection(collection);
|
||||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
if (idx->_type != TRI_IDX_TYPE_SKIPLIST_INDEX) {
|
||||
if (lock) {
|
||||
primary->endRead(primary);
|
||||
primary->endRead(primary);
|
||||
TRI_ReleaseCollection(collection);
|
||||
|
||||
TRI_ReleaseCollection(collection);
|
||||
}
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_BAD_PARAMETER, "index must be a skiplist index")));
|
||||
}
|
||||
|
||||
|
|
@ -1033,11 +1021,9 @@ static v8::Handle<v8::Value> ExecuteSkiplistQuery (v8::Arguments const& argv,
|
|||
}
|
||||
|
||||
if (! skiplistOperator) {
|
||||
if (lock) {
|
||||
primary->endRead(primary);
|
||||
primary->endRead(primary);
|
||||
TRI_ReleaseCollection(collection);
|
||||
|
||||
TRI_ReleaseCollection(collection);
|
||||
}
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_BAD_PARAMETER, "setting up skiplist operator failed")));
|
||||
}
|
||||
|
||||
|
|
@ -1066,7 +1052,7 @@ static v8::Handle<v8::Value> ExecuteSkiplistQuery (v8::Arguments const& argv,
|
|||
}
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(collection, (TRI_doc_mptr_t const*) indexElement->data, barrier);
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(resolver, collection, (TRI_doc_mptr_t const*) indexElement->data, barrier);
|
||||
|
||||
if (doc.IsEmpty()) {
|
||||
error = true;
|
||||
|
|
@ -1080,9 +1066,7 @@ static v8::Handle<v8::Value> ExecuteSkiplistQuery (v8::Arguments const& argv,
|
|||
}
|
||||
}
|
||||
|
||||
if (lock) {
|
||||
primary->endRead(primary);
|
||||
}
|
||||
primary->endRead(primary);
|
||||
|
||||
// .............................................................................
|
||||
// outside a write transaction
|
||||
|
|
@ -1094,9 +1078,7 @@ static v8::Handle<v8::Value> ExecuteSkiplistQuery (v8::Arguments const& argv,
|
|||
result->Set(v8::String::New("total"), v8::Number::New((double) total));
|
||||
result->Set(v8::String::New("count"), v8::Number::New(count));
|
||||
|
||||
if (lock) {
|
||||
TRI_ReleaseCollection(collection);
|
||||
}
|
||||
TRI_ReleaseCollection(collection);
|
||||
|
||||
if (error) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_OUT_OF_MEMORY)));
|
||||
|
|
@ -1141,8 +1123,7 @@ static bool BitarrayFilterExample(TRI_index_iterator_t* indexIterator) {
|
|||
|
||||
static v8::Handle<v8::Value> ExecuteBitarrayQuery (v8::Arguments const& argv,
|
||||
std::string const& signature,
|
||||
const query_t type,
|
||||
const bool lock) {
|
||||
const query_t type) {
|
||||
v8::HandleScope scope;
|
||||
v8::Handle<v8::Object> err;
|
||||
const TRI_vocbase_col_t* collection;
|
||||
|
|
@ -1155,19 +1136,15 @@ static v8::Handle<v8::Value> ExecuteBitarrayQuery (v8::Arguments const& argv,
|
|||
|
||||
TRI_document_collection_t* document = 0;
|
||||
|
||||
if (lock) {
|
||||
document = TRI_ExtractAndUseSimpleCollection(argv, collection, &err);
|
||||
}
|
||||
else {
|
||||
document = TRI_ExtractSimpleCollection(argv, collection, &err);
|
||||
}
|
||||
document = TRI_ExtractAndUseSimpleCollection(argv, collection, &err);
|
||||
|
||||
if (document == 0) {
|
||||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
assert(collection != 0);
|
||||
|
||||
TRI_primary_collection_t* primary = &document->base;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Check the parameters, expecting index, example, skip, and limit
|
||||
|
|
@ -1175,9 +1152,7 @@ static v8::Handle<v8::Value> ExecuteBitarrayQuery (v8::Arguments const& argv,
|
|||
// ...........................................................................
|
||||
|
||||
if (argv.Length() < 2) {
|
||||
if (lock) {
|
||||
TRI_ReleaseCollection(collection);
|
||||
}
|
||||
TRI_ReleaseCollection(collection);
|
||||
|
||||
std::string usage("Usage: ");
|
||||
usage += signature;
|
||||
|
|
@ -1190,9 +1165,8 @@ static v8::Handle<v8::Value> ExecuteBitarrayQuery (v8::Arguments const& argv,
|
|||
// ...........................................................................
|
||||
|
||||
if (! argv[1]->IsObject()) {
|
||||
if (lock) {
|
||||
TRI_ReleaseCollection(collection);
|
||||
}
|
||||
TRI_ReleaseCollection(collection);
|
||||
|
||||
std::string msg;
|
||||
|
||||
if (type == QUERY_EXAMPLE) {
|
||||
|
|
@ -1234,32 +1208,26 @@ static v8::Handle<v8::Value> ExecuteBitarrayQuery (v8::Arguments const& argv,
|
|||
// inside a read transaction
|
||||
// .............................................................................
|
||||
|
||||
if (lock) {
|
||||
primary->beginRead(primary);
|
||||
}
|
||||
primary->beginRead(primary);
|
||||
|
||||
// .............................................................................
|
||||
// extract the index
|
||||
// .............................................................................
|
||||
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(document->base.base._vocbase, collection, argv[0], false, &err);
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(resolver, document->base.base._vocbase, collection, argv[0], false, &err);
|
||||
|
||||
if (idx == 0) {
|
||||
primary->endRead(primary);
|
||||
TRI_ReleaseCollection(collection);
|
||||
|
||||
if (lock) {
|
||||
TRI_ReleaseCollection(collection);
|
||||
}
|
||||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
|
||||
if (idx->_type != TRI_IDX_TYPE_BITARRAY_INDEX) {
|
||||
if (lock) {
|
||||
primary->endRead(primary);
|
||||
|
||||
TRI_ReleaseCollection(collection);
|
||||
}
|
||||
primary->endRead(primary);
|
||||
TRI_ReleaseCollection(collection);
|
||||
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_BAD_PARAMETER, "index must be a skiplist index")));
|
||||
}
|
||||
|
||||
|
|
@ -1275,11 +1243,8 @@ static v8::Handle<v8::Value> ExecuteBitarrayQuery (v8::Arguments const& argv,
|
|||
|
||||
|
||||
if (indexOperator == 0) { // something wrong
|
||||
if (lock) {
|
||||
primary->endRead(primary);
|
||||
|
||||
TRI_ReleaseCollection(collection);
|
||||
}
|
||||
primary->endRead(primary);
|
||||
TRI_ReleaseCollection(collection);
|
||||
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_BAD_PARAMETER, "setting up bitarray index operator failed")));
|
||||
}
|
||||
|
|
@ -1324,7 +1289,7 @@ static v8::Handle<v8::Value> ExecuteBitarrayQuery (v8::Arguments const& argv,
|
|||
}
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(collection, data, barrier);
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(resolver, collection, data, barrier);
|
||||
|
||||
if (doc.IsEmpty()) {
|
||||
error = true;
|
||||
|
|
@ -1348,9 +1313,7 @@ static v8::Handle<v8::Value> ExecuteBitarrayQuery (v8::Arguments const& argv,
|
|||
// return an empty list
|
||||
}
|
||||
|
||||
if (lock) {
|
||||
primary->endRead(primary);
|
||||
}
|
||||
primary->endRead(primary);
|
||||
|
||||
// .............................................................................
|
||||
// outside a write transaction
|
||||
|
|
@ -1360,9 +1323,7 @@ static v8::Handle<v8::Value> ExecuteBitarrayQuery (v8::Arguments const& argv,
|
|||
result->Set(v8::String::New("total"), v8::Number::New((double) total));
|
||||
result->Set(v8::String::New("count"), v8::Number::New(count));
|
||||
|
||||
if (lock) {
|
||||
TRI_ReleaseCollection(collection);
|
||||
}
|
||||
TRI_ReleaseCollection(collection);
|
||||
|
||||
if (error) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_OUT_OF_MEMORY)));
|
||||
|
|
@ -1464,10 +1425,12 @@ static int StoreGeoResult (TRI_vocbase_col_t const* collection,
|
|||
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
|
||||
// copy the documents
|
||||
for (gtr = tmp, i = 0; gtr < gnd; ++gtr, ++i) {
|
||||
documents->Set(i, TRI_WrapShapedJson(collection, (TRI_doc_mptr_t const*) gtr->_data, barrier));
|
||||
documents->Set(i, TRI_WrapShapedJson(resolver, collection, (TRI_doc_mptr_t const*) gtr->_data, barrier));
|
||||
distances->Set(i, v8::Number::New(gtr->_distance));
|
||||
}
|
||||
|
||||
|
|
@ -1509,6 +1472,8 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
|
|||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
assert(collection != 0);
|
||||
|
||||
TRI_primary_collection_t* primary = &document->base;
|
||||
|
||||
if (collection->_type != TRI_COL_TYPE_EDGE) {
|
||||
|
|
@ -1555,6 +1520,8 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
|
|||
TRI_barrier_t* barrier = 0;
|
||||
uint32_t count = 0;
|
||||
bool error = false;
|
||||
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
|
||||
// argument is a list of vertices
|
||||
if (argv[0]->IsArray()) {
|
||||
|
|
@ -1568,13 +1535,9 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
|
|||
TRI_voc_key_t key = 0;
|
||||
|
||||
TRI_vocbase_col_t const* vertexCollection = 0;
|
||||
v8::Handle<v8::Value> errMsg = TRI_ParseDocumentOrDocumentHandle(collection->_vocbase, vertexCollection, key, rid, true, vertices->Get(i));
|
||||
v8::Handle<v8::Value> errMsg = TRI_ParseDocumentOrDocumentHandle(resolver, vertexCollection, key, rid, vertices->Get(i));
|
||||
|
||||
if (! errMsg.IsEmpty()) {
|
||||
if (vertexCollection != 0) {
|
||||
TRI_ReleaseCollection(vertexCollection);
|
||||
}
|
||||
|
||||
if (key) {
|
||||
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
|
||||
key = 0;
|
||||
|
|
@ -1583,8 +1546,9 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
|
|||
continue;
|
||||
}
|
||||
|
||||
assert(vertexCollection != 0);
|
||||
|
||||
cid = vertexCollection->_cid;
|
||||
TRI_ReleaseCollection(vertexCollection);
|
||||
|
||||
edges = TRI_LookupEdgesDocumentCollection(document, direction, cid, key);
|
||||
|
||||
|
|
@ -1601,7 +1565,7 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
|
|||
}
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(collection, (TRI_doc_mptr_t const*) edges._buffer[j], barrier);
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(resolver, collection, (TRI_doc_mptr_t const*) edges._buffer[j], barrier);
|
||||
|
||||
if (doc.IsEmpty()) {
|
||||
// error
|
||||
|
|
@ -1631,28 +1595,27 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
|
|||
TRI_voc_key_t key = 0;
|
||||
|
||||
TRI_vocbase_col_t const* vertexCollection = 0;
|
||||
v8::Handle<v8::Value> errMsg = TRI_ParseDocumentOrDocumentHandle(collection->_vocbase, vertexCollection, key, rid, true, argv[0]);
|
||||
v8::Handle<v8::Value> errMsg = TRI_ParseDocumentOrDocumentHandle(resolver, vertexCollection, key, rid, argv[0]);
|
||||
|
||||
if (! errMsg.IsEmpty()) {
|
||||
if (vertexCollection != 0) {
|
||||
TRI_ReleaseCollection(vertexCollection);
|
||||
}
|
||||
|
||||
primary->endRead(primary);
|
||||
TRI_ReleaseCollection(collection);
|
||||
|
||||
if (key) {
|
||||
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
|
||||
}
|
||||
TRI_ReleaseCollection(collection);
|
||||
return scope.Close(v8::ThrowException(errMsg));
|
||||
}
|
||||
|
||||
assert(vertexCollection != 0);
|
||||
|
||||
cid = vertexCollection->_cid;
|
||||
TRI_ReleaseCollection(vertexCollection);
|
||||
|
||||
edges = TRI_LookupEdgesDocumentCollection(document, direction, cid, key);
|
||||
|
||||
if (key) TRI_FreeString(TRI_CORE_MEM_ZONE, key);
|
||||
if (key) {
|
||||
TRI_FreeString(TRI_CORE_MEM_ZONE, key);
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < edges._length; ++j) {
|
||||
if (barrier == 0) {
|
||||
|
|
@ -1663,7 +1626,7 @@ static v8::Handle<v8::Value> EdgesQuery (TRI_edge_direction_e direction, v8::Arg
|
|||
}
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(collection, (TRI_doc_mptr_t const*) edges._buffer[j], barrier);
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(resolver, collection, (TRI_doc_mptr_t const*) edges._buffer[j], barrier);
|
||||
|
||||
if (doc.IsEmpty()) {
|
||||
error = true;
|
||||
|
|
@ -1735,7 +1698,8 @@ static v8::Handle<v8::Value> JS_AllQuery (v8::Arguments const& argv) {
|
|||
uint32_t total = 0;
|
||||
vector<TRI_doc_mptr_t*> docs;
|
||||
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, col->_name);
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
|
@ -1759,7 +1723,7 @@ static v8::Handle<v8::Value> JS_AllQuery (v8::Arguments const& argv) {
|
|||
result->Set(v8::String::New("documents"), documents);
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
v8::Handle<v8::Value> document = TRI_WrapShapedJson(col, docs[i], barrier);
|
||||
v8::Handle<v8::Value> document = TRI_WrapShapedJson(resolver, col, docs[i], barrier);
|
||||
|
||||
if (document.IsEmpty()) {
|
||||
// error
|
||||
|
|
@ -1804,7 +1768,8 @@ static v8::Handle<v8::Value> JS_AnyQuery (v8::Arguments const& argv) {
|
|||
TRI_barrier_t* barrier = 0;
|
||||
TRI_doc_mptr_t* doc = 0;
|
||||
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, col->_name);
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(col->_vocbase, col->_cid);
|
||||
int res = trx.begin();
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot fetch document", true)));
|
||||
|
|
@ -1821,7 +1786,7 @@ static v8::Handle<v8::Value> JS_AnyQuery (v8::Arguments const& argv) {
|
|||
return scope.Close(v8::Null());
|
||||
}
|
||||
else {
|
||||
return scope.Close(TRI_WrapShapedJson(col, doc, barrier));
|
||||
return scope.Close(TRI_WrapShapedJson(resolver, col, doc, barrier));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1831,7 +1796,7 @@ static v8::Handle<v8::Value> JS_AnyQuery (v8::Arguments const& argv) {
|
|||
|
||||
static v8::Handle<v8::Value> JS_ByExampleQuery (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
|
||||
// extract and use the simple collection
|
||||
v8::Handle<v8::Object> err;
|
||||
TRI_vocbase_col_t const* collection;
|
||||
|
|
@ -1841,6 +1806,8 @@ static v8::Handle<v8::Value> JS_ByExampleQuery (v8::Arguments const& argv) {
|
|||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
assert(collection != 0);
|
||||
|
||||
TRI_shaper_t* shaper = document->base._shaper;
|
||||
|
||||
// expecting example, skip, limit
|
||||
|
|
@ -1859,6 +1826,7 @@ static v8::Handle<v8::Value> JS_ByExampleQuery (v8::Arguments const& argv) {
|
|||
"<example> must be an object")));
|
||||
}
|
||||
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
v8::Handle<v8::Object> example = argv[0]->ToObject();
|
||||
|
||||
// extract skip and limit
|
||||
|
|
@ -1919,7 +1887,7 @@ static v8::Handle<v8::Value> JS_ByExampleQuery (v8::Arguments const& argv) {
|
|||
else {
|
||||
for (size_t j = s; j < e; ++j) {
|
||||
TRI_doc_mptr_t* mptr = (TRI_doc_mptr_t*) TRI_AtVector(&filtered, j);
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(collection, mptr, barrier);
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(resolver, collection, mptr, barrier);
|
||||
|
||||
if (doc.IsEmpty()) {
|
||||
error = true;
|
||||
|
|
@ -1996,9 +1964,10 @@ static v8::Handle<v8::Value> ByExampleHashIndexQuery (TRI_document_collection_t*
|
|||
|
||||
v8::Handle<v8::Array> documents = v8::Array::New();
|
||||
result->Set(v8::String::New("documents"), documents);
|
||||
|
||||
|
||||
// extract the index
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(document->base.base._vocbase, collection, argv[0], false, err);
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(resolver, document->base.base._vocbase, collection, argv[0], false, err);
|
||||
|
||||
if (idx == 0) {
|
||||
return scope.Close(v8::ThrowException(*err));
|
||||
|
|
@ -2020,7 +1989,7 @@ static v8::Handle<v8::Value> ByExampleHashIndexQuery (TRI_document_collection_t*
|
|||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return scope.Close(v8::ThrowException(*err));
|
||||
}
|
||||
|
||||
|
||||
// find the matches
|
||||
TRI_hash_index_elements_t* list = TRI_LookupShapedJsonHashIndex(idx, values);
|
||||
|
||||
|
|
@ -2042,7 +2011,7 @@ static v8::Handle<v8::Value> ByExampleHashIndexQuery (TRI_document_collection_t*
|
|||
}
|
||||
else {
|
||||
for (size_t i = s; i < e; ++i) {
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(collection, (TRI_doc_mptr_t const*) list->_elements[i].data, barrier);
|
||||
v8::Handle<v8::Value> doc = TRI_WrapShapedJson(resolver, collection, (TRI_doc_mptr_t const*) list->_elements[i].data, barrier);
|
||||
|
||||
if (doc.IsEmpty()) {
|
||||
error = true;
|
||||
|
|
@ -2088,6 +2057,8 @@ static v8::Handle<v8::Value> JS_ByExampleHashIndex (v8::Arguments const& argv) {
|
|||
if (document == 0) {
|
||||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
assert(collection != 0);
|
||||
|
||||
// .............................................................................
|
||||
// inside a read transaction
|
||||
|
|
@ -2115,7 +2086,7 @@ static v8::Handle<v8::Value> JS_ByExampleHashIndex (v8::Arguments const& argv) {
|
|||
static v8::Handle<v8::Value> JS_ByConditionSkiplist (v8::Arguments const& argv) {
|
||||
std::string signature("BY_CONDITION_SKIPLIST(<index>, <conditions>, <skip>, <limit>)");
|
||||
|
||||
return ExecuteSkiplistQuery(argv, signature, QUERY_CONDITION, true);
|
||||
return ExecuteSkiplistQuery(argv, signature, QUERY_CONDITION);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -2125,7 +2096,7 @@ static v8::Handle<v8::Value> JS_ByConditionSkiplist (v8::Arguments const& argv)
|
|||
static v8::Handle<v8::Value> JS_ByExampleSkiplist (v8::Arguments const& argv) {
|
||||
std::string signature("BY_EXAMPLE_SKIPLIST(<index>, <example>, <skip>, <limit>)");
|
||||
|
||||
return ExecuteSkiplistQuery(argv, signature, QUERY_EXAMPLE, true);
|
||||
return ExecuteSkiplistQuery(argv, signature, QUERY_EXAMPLE);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -2135,13 +2106,13 @@ static v8::Handle<v8::Value> JS_ByExampleSkiplist (v8::Arguments const& argv) {
|
|||
static v8::Handle<v8::Value> JS_ByExampleBitarray (v8::Arguments const& argv) {
|
||||
std::string signature("BY_EXAMPLE_BITARRAY(<index>, <example>, <skip>, <limit>)");
|
||||
|
||||
return ExecuteBitarrayQuery(argv, signature, QUERY_EXAMPLE, true);
|
||||
return ExecuteBitarrayQuery(argv, signature, QUERY_EXAMPLE);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> JS_ByConditionBitarray (v8::Arguments const& argv) {
|
||||
std::string signature("BY_CONDITION_BITARRAY(<index>, <conditions>, <skip>, <limit>)");
|
||||
|
||||
return ExecuteBitarrayQuery(argv, signature, QUERY_CONDITION, true);
|
||||
return ExecuteBitarrayQuery(argv, signature, QUERY_CONDITION);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -2208,7 +2179,8 @@ static v8::Handle<v8::Value> FulltextQuery (TRI_document_collection_t* document,
|
|||
}
|
||||
|
||||
// extract the index
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(document->base.base._vocbase, collection, argv[0], false, err);
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(resolver, document->base.base._vocbase, collection, argv[0], false, err);
|
||||
|
||||
if (idx == 0) {
|
||||
return scope.Close(v8::ThrowException(*err));
|
||||
|
|
@ -2217,7 +2189,7 @@ static v8::Handle<v8::Value> FulltextQuery (TRI_document_collection_t* document,
|
|||
if (idx->_type != TRI_IDX_TYPE_FULLTEXT_INDEX) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_BAD_PARAMETER, "index must be a fulltext index")));
|
||||
}
|
||||
|
||||
|
||||
const string queryString = TRI_ObjectToString(argv[1]);
|
||||
bool isSubstringQuery = false;
|
||||
|
||||
|
|
@ -2257,7 +2229,7 @@ static v8::Handle<v8::Value> FulltextQuery (TRI_document_collection_t* document,
|
|||
result->Set(v8::String::New("documents"), documents);
|
||||
|
||||
for (uint32_t i = 0; i < queryResult->_numDocuments; ++i) {
|
||||
documents->Set(i, TRI_WrapShapedJson(collection, (TRI_doc_mptr_t const*) queryResult->_documents[i], barrier));
|
||||
documents->Set(i, TRI_WrapShapedJson(resolver, collection, (TRI_doc_mptr_t const*) queryResult->_documents[i], barrier));
|
||||
}
|
||||
|
||||
TRI_FreeResultFulltextIndex(queryResult);
|
||||
|
|
@ -2299,6 +2271,8 @@ static v8::Handle<v8::Value> JS_FulltextQuery (v8::Arguments const& argv) {
|
|||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
assert(collection != 0);
|
||||
|
||||
// .............................................................................
|
||||
// inside a read transaction
|
||||
// .............................................................................
|
||||
|
|
@ -2338,7 +2312,8 @@ static v8::Handle<v8::Value> NearQuery (TRI_document_collection_t* document,
|
|||
}
|
||||
|
||||
// extract the index
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(document->base.base._vocbase, collection, argv[0], false, err);
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(resolver, document->base.base._vocbase, collection, argv[0], false, err);
|
||||
|
||||
if (idx == 0) {
|
||||
return scope.Close(v8::ThrowException(*err));
|
||||
|
|
@ -2392,6 +2367,8 @@ static v8::Handle<v8::Value> JS_NearQuery (v8::Arguments const& argv) {
|
|||
if (document == 0) {
|
||||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
assert(collection != 0);
|
||||
|
||||
// .............................................................................
|
||||
// inside a read transaction
|
||||
|
|
@ -2454,7 +2431,8 @@ static v8::Handle<v8::Value> WithinQuery (TRI_document_collection_t* document,
|
|||
}
|
||||
|
||||
// extract the index
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(document->base.base._vocbase, collection, argv[0], false, err);
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(resolver, document->base.base._vocbase, collection, argv[0], false, err);
|
||||
|
||||
if (idx == 0) {
|
||||
return scope.Close(v8::ThrowException(*err));
|
||||
|
|
@ -2509,6 +2487,8 @@ static v8::Handle<v8::Value> JS_WithinQuery (v8::Arguments const& argv) {
|
|||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
assert(collection != 0);
|
||||
|
||||
// .............................................................................
|
||||
// inside a read transaction
|
||||
// .............................................................................
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "ShapedJson/shape-accessor.h"
|
||||
#include "ShapedJson/shaped-json.h"
|
||||
#include "Utils/AhuacatlGuard.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "Utils/DocumentHelper.h"
|
||||
#include "Utils/EmbeddableTransaction.h"
|
||||
#include "Utils/SingleCollectionReadOnlyTransaction.h"
|
||||
|
|
@ -206,22 +207,6 @@ static inline v8::Handle<v8::Value> V8DocumentId (const string& collectionName,
|
|||
return scope.Close(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a v8 document id value from the parameters
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> V8DocumentId (TRI_vocbase_t* const vocbase,
|
||||
const TRI_voc_cid_t cid,
|
||||
const string& key) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
const string id = DocumentHelper::assembleDocumentId(vocbase, cid, key);
|
||||
|
||||
v8::Handle<v8::Value> result = v8::String::New(id.c_str(), id.size());
|
||||
|
||||
return scope.Close(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract the forceSync flag from the arguments
|
||||
/// must specify the argument index starting from 1
|
||||
|
|
@ -319,10 +304,9 @@ static inline TRI_vocbase_t* GetContextVocBase () {
|
|||
/// @brief checks if argument is a document identifier
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool IsDocumentHandle (TRI_vocbase_t* const vocbase,
|
||||
v8::Handle<v8::Value> arg,
|
||||
string& collectionName,
|
||||
TRI_voc_key_t& key) {
|
||||
static bool ParseDocumentHandle (v8::Handle<v8::Value> arg,
|
||||
string& collectionName,
|
||||
TRI_voc_key_t& key) {
|
||||
assert(collectionName == "");
|
||||
|
||||
if (! arg->IsString()) {
|
||||
|
|
@ -786,7 +770,8 @@ static v8::Handle<v8::Value> DocumentVocbaseCol (const bool useCollection,
|
|||
|
||||
assert(vocbase);
|
||||
|
||||
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(vocbase, col, key, rid, false, argv[0]);
|
||||
CollectionNameResolver resolver(vocbase);
|
||||
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]);
|
||||
if (! holder.registerString(TRI_CORE_MEM_ZONE, key)) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD)));
|
||||
}
|
||||
|
|
@ -799,7 +784,7 @@ static v8::Handle<v8::Value> DocumentVocbaseCol (const bool useCollection,
|
|||
assert(key);
|
||||
|
||||
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(vocbase, col->_name);
|
||||
SingleCollectionReadOnlyTransaction<EmbeddableTransaction<V8TransactionContext> > trx(vocbase, col->_cid);
|
||||
int res = trx.begin();
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot fetch document", true)));
|
||||
|
|
@ -813,7 +798,7 @@ static v8::Handle<v8::Value> DocumentVocbaseCol (const bool useCollection,
|
|||
assert(document);
|
||||
|
||||
TRI_barrier_t* barrier = TRI_CreateBarrierElement(trx.barrierList());
|
||||
result = TRI_WrapShapedJson(col, document, barrier);
|
||||
result = TRI_WrapShapedJson(resolver, col, document, barrier);
|
||||
}
|
||||
|
||||
res = trx.finish(res);
|
||||
|
|
@ -871,7 +856,8 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (const bool useCollection,
|
|||
|
||||
assert(vocbase);
|
||||
|
||||
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(vocbase, col, key, rid, false, argv[0]);
|
||||
CollectionNameResolver resolver(vocbase);
|
||||
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]);
|
||||
if (! holder.registerString(TRI_CORE_MEM_ZONE, key)) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD)));
|
||||
}
|
||||
|
|
@ -884,7 +870,7 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (const bool useCollection,
|
|||
assert(key);
|
||||
|
||||
|
||||
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1> trx(vocbase, col->_name);
|
||||
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1> trx(vocbase, col->_cid);
|
||||
int res = trx.begin();
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot replace document", true)));
|
||||
|
|
@ -911,7 +897,7 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (const bool useCollection,
|
|||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
|
||||
v8::Handle<v8::Object> result = v8::Object::New();
|
||||
result->Set(v8g->DidKey, V8DocumentId(trx.collectionName(), document->_key));
|
||||
result->Set(v8g->DidKey, V8DocumentId(resolver.getCollectionName(col->_cid), document->_key));
|
||||
result->Set(v8g->RevKey, V8RevisionId(document->_rid));
|
||||
result->Set(v8g->OldRevKey, V8RevisionId(actualRevision));
|
||||
result->Set(v8g->KeyKey, v8::String::New(document->_key));
|
||||
|
|
@ -952,6 +938,7 @@ static v8::Handle<v8::Value> ReplaceVocbaseCol (const bool useCollection,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> SaveVocbaseCol (SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1>* trx,
|
||||
TRI_vocbase_col_t* col,
|
||||
v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
|
|
@ -961,11 +948,12 @@ static v8::Handle<v8::Value> SaveVocbaseCol (SingleCollectionWriteTransaction<Em
|
|||
"usage: save(<data>, <waitForSync>)")));
|
||||
}
|
||||
|
||||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
ResourceHolder holder;
|
||||
|
||||
// set document key
|
||||
TRI_voc_key_t key = 0;
|
||||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
|
||||
if (argv[0]->IsObject()) {
|
||||
v8::Handle<v8::Object> obj = argv[0]->ToObject();
|
||||
|
|
@ -999,7 +987,7 @@ static v8::Handle<v8::Value> SaveVocbaseCol (SingleCollectionWriteTransaction<Em
|
|||
assert(document->_key);
|
||||
|
||||
v8::Handle<v8::Object> result = v8::Object::New();
|
||||
result->Set(v8g->DidKey, V8DocumentId(trx->collectionName(), document->_key));
|
||||
result->Set(v8g->DidKey, V8DocumentId(resolver.getCollectionName(col->_cid), document->_key));
|
||||
result->Set(v8g->RevKey, V8RevisionId(document->_rid));
|
||||
result->Set(v8g->KeyKey, v8::String::New(document->_key));
|
||||
|
||||
|
|
@ -1033,6 +1021,7 @@ static v8::Handle<v8::Value> SaveVocbaseCol (SingleCollectionWriteTransaction<Em
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> SaveEdgeCol (SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1>* trx,
|
||||
TRI_vocbase_col_t* col,
|
||||
v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
|
|
@ -1043,6 +1032,7 @@ static v8::Handle<v8::Value> SaveEdgeCol (SingleCollectionWriteTransaction<Embed
|
|||
"usage: save(<from>, <to>, <data>, <waitForSync>)")));
|
||||
}
|
||||
|
||||
CollectionNameResolver resolver(col->_vocbase);
|
||||
ResourceHolder holder;
|
||||
|
||||
// set document key
|
||||
|
|
@ -1073,7 +1063,7 @@ static v8::Handle<v8::Value> SaveEdgeCol (SingleCollectionWriteTransaction<Embed
|
|||
TRI_vocbase_col_t const* fromCollection = 0;
|
||||
TRI_voc_rid_t fromRid;
|
||||
|
||||
err = TRI_ParseDocumentOrDocumentHandle(trx->vocbase(), fromCollection, edge._fromKey, fromRid, false, argv[0]);
|
||||
err = TRI_ParseDocumentOrDocumentHandle(resolver, fromCollection, edge._fromKey, fromRid, argv[0]);
|
||||
holder.registerString(TRI_CORE_MEM_ZONE, edge._fromKey);
|
||||
|
||||
if (! err.IsEmpty()) {
|
||||
|
|
@ -1085,7 +1075,7 @@ static v8::Handle<v8::Value> SaveEdgeCol (SingleCollectionWriteTransaction<Embed
|
|||
TRI_vocbase_col_t const* toCollection = 0;
|
||||
TRI_voc_rid_t toRid;
|
||||
|
||||
err = TRI_ParseDocumentOrDocumentHandle(trx->vocbase(), toCollection, edge._toKey, toRid, false, argv[1]);
|
||||
err = TRI_ParseDocumentOrDocumentHandle(resolver, toCollection, edge._toKey, toRid, argv[1]);
|
||||
holder.registerString(TRI_CORE_MEM_ZONE, edge._toKey);
|
||||
|
||||
if (! err.IsEmpty()) {
|
||||
|
|
@ -1114,7 +1104,7 @@ static v8::Handle<v8::Value> SaveEdgeCol (SingleCollectionWriteTransaction<Embed
|
|||
assert(document->_key);
|
||||
|
||||
v8::Handle<v8::Object> result = v8::Object::New();
|
||||
result->Set(v8g->DidKey, V8DocumentId(trx->collectionName(), document->_key));
|
||||
result->Set(v8g->DidKey, V8DocumentId(resolver.getCollectionName(col->_cid), document->_key));
|
||||
result->Set(v8g->RevKey, V8RevisionId(document->_rid));
|
||||
result->Set(v8g->KeyKey, v8::String::New(document->_key));
|
||||
|
||||
|
|
@ -1166,7 +1156,8 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (const bool useCollection,
|
|||
|
||||
assert(vocbase);
|
||||
|
||||
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(vocbase, col, key, rid, false, argv[0]);
|
||||
CollectionNameResolver resolver(vocbase);
|
||||
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]);
|
||||
if (! holder.registerString(TRI_CORE_MEM_ZONE, key)) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD)));
|
||||
}
|
||||
|
|
@ -1185,7 +1176,7 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (const bool useCollection,
|
|||
}
|
||||
|
||||
|
||||
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1> trx(vocbase, col->_name);
|
||||
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1> trx(vocbase, col->_cid);
|
||||
int res = trx.begin();
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot update document", true)));
|
||||
|
|
@ -1225,7 +1216,7 @@ static v8::Handle<v8::Value> UpdateVocbaseCol (const bool useCollection,
|
|||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
|
||||
v8::Handle<v8::Object> result = v8::Object::New();
|
||||
result->Set(v8g->DidKey, V8DocumentId(trx.collectionName(), document->_key));
|
||||
result->Set(v8g->DidKey, V8DocumentId(resolver.getCollectionName(col->_cid), document->_key));
|
||||
result->Set(v8g->RevKey, V8RevisionId(document->_rid));
|
||||
result->Set(v8g->OldRevKey, V8RevisionId(actualRevision));
|
||||
result->Set(v8g->KeyKey, v8::String::New(document->_key));
|
||||
|
|
@ -1273,7 +1264,8 @@ static v8::Handle<v8::Value> RemoveVocbaseCol (const bool useCollection,
|
|||
|
||||
assert(vocbase);
|
||||
|
||||
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(vocbase, col, key, rid, false, argv[0]);
|
||||
CollectionNameResolver resolver(vocbase);
|
||||
v8::Handle<v8::Value> err = TRI_ParseDocumentOrDocumentHandle(resolver, col, key, rid, argv[0]);
|
||||
if (! holder.registerString(TRI_CORE_MEM_ZONE, key)) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD)));
|
||||
}
|
||||
|
|
@ -1286,7 +1278,7 @@ static v8::Handle<v8::Value> RemoveVocbaseCol (const bool useCollection,
|
|||
assert(key);
|
||||
|
||||
|
||||
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1> trx(vocbase, col->_name);
|
||||
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1> trx(vocbase, col->_cid);
|
||||
int res = trx.begin();
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot delete document", true)));
|
||||
|
|
@ -3445,6 +3437,8 @@ static v8::Handle<v8::Value> JS_DropIndexVocbaseCol (v8::Arguments const& argv)
|
|||
return scope.Close(v8::ThrowException(err));
|
||||
}
|
||||
|
||||
CollectionNameResolver resolver(collection->_vocbase);
|
||||
|
||||
TRI_primary_collection_t* primary = collection->_collection;
|
||||
|
||||
if (! TRI_IS_DOCUMENT_COLLECTION(collection->_type)) {
|
||||
|
|
@ -3459,7 +3453,7 @@ static v8::Handle<v8::Value> JS_DropIndexVocbaseCol (v8::Arguments const& argv)
|
|||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_ILLEGAL_OPTION, "usage: dropIndex(<index-handle>)")));
|
||||
}
|
||||
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(collection->_vocbase, collection, argv[0], true, &err);
|
||||
TRI_index_t* idx = TRI_LookupIndexByHandle(resolver, collection->_vocbase, collection, argv[0], true, &err);
|
||||
|
||||
if (idx == 0) {
|
||||
if (err.IsEmpty()) {
|
||||
|
|
@ -4514,8 +4508,18 @@ static v8::Handle<v8::Value> JS_NameVocbaseCol (v8::Arguments const& argv) {
|
|||
return scope.Close(v8::ThrowException(v8::String::New("illegal collection pointer")));
|
||||
}
|
||||
|
||||
// TODO: protect this against race conditions (parallel rename operation)
|
||||
return scope.Close(v8::String::New(collection->_name));
|
||||
// this copies the name into a new place so we can safely access it later
|
||||
// if we wouldn't do this, we would risk other threads modifying the name while
|
||||
// we're reading it
|
||||
char* name = TRI_GetCollectionNameByIdVocBase(collection->_vocbase, collection->_cid);
|
||||
if (name == 0) {
|
||||
return scope.Close(v8::Undefined());
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> result = v8::String::New(name);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, name);
|
||||
|
||||
return scope.Close(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -4933,7 +4937,7 @@ static v8::Handle<v8::Value> JS_SaveVocbaseCol (v8::Arguments const& argv) {
|
|||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_INTERNAL)));
|
||||
}
|
||||
|
||||
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1> trx(col->_vocbase, col->_name);
|
||||
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, 1> trx(col->_vocbase, col->_cid);
|
||||
|
||||
int res = trx.begin();
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
|
@ -4943,10 +4947,10 @@ static v8::Handle<v8::Value> JS_SaveVocbaseCol (v8::Arguments const& argv) {
|
|||
v8::Handle<v8::Value> result;
|
||||
|
||||
if ((TRI_col_type_e) col->_type == TRI_COL_TYPE_DOCUMENT) {
|
||||
result = SaveVocbaseCol(&trx, argv);
|
||||
result = SaveVocbaseCol(&trx, col, argv);
|
||||
}
|
||||
else if ((TRI_col_type_e) col->_type == TRI_COL_TYPE_EDGE) {
|
||||
result = SaveEdgeCol(&trx, argv);
|
||||
result = SaveEdgeCol(&trx, col, argv);
|
||||
}
|
||||
|
||||
return scope.Close(result);
|
||||
|
|
@ -5083,7 +5087,7 @@ static v8::Handle<v8::Value> JS_TruncateVocbaseCol (v8::Arguments const& argv) {
|
|||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(TRI_ERROR_INTERNAL)));
|
||||
}
|
||||
|
||||
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, UINT64_MAX> trx(col->_vocbase, col->_name);
|
||||
SingleCollectionWriteTransaction<EmbeddableTransaction<V8TransactionContext>, UINT64_MAX> trx(col->_vocbase, col->_cid);
|
||||
int res = trx.begin();
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return scope.Close(v8::ThrowException(TRI_CreateErrorObject(res, "cannot truncate collection", true)));
|
||||
|
|
@ -5425,6 +5429,7 @@ static v8::Handle<v8::Value> JS_CompletionsVocbase (v8::Arguments const& argv) {
|
|||
if (vocbase == 0) {
|
||||
return scope.Close(v8::Array::New());
|
||||
}
|
||||
|
||||
|
||||
TRI_vector_pointer_t colls = TRI_CollectionsVocBase(vocbase);
|
||||
|
||||
|
|
@ -5435,8 +5440,15 @@ static v8::Handle<v8::Value> JS_CompletionsVocbase (v8::Arguments const& argv) {
|
|||
// add collection names
|
||||
for (uint32_t i = 0; i < n; ++i) {
|
||||
TRI_vocbase_col_t const* collection = (TRI_vocbase_col_t const*) colls._buffer[i];
|
||||
|
||||
result->Set(j++, v8::String::New(collection->_name));
|
||||
|
||||
// this copies the name into a new place so we can safely access it later
|
||||
// if we wouldn't do this, we would risk other threads modifying the name while
|
||||
// we're reading it
|
||||
char* name = TRI_GetCollectionNameByIdVocBase(collection->_vocbase, collection->_cid);
|
||||
if (name != 0) {
|
||||
result->Set(j++, v8::String::New(name));
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, name);
|
||||
}
|
||||
}
|
||||
|
||||
TRI_DestroyVectorPointer(&colls);
|
||||
|
|
@ -6088,17 +6100,54 @@ void TRI_ReleaseCollection (TRI_vocbase_col_t const* collection) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief parse document or document handle
|
||||
///
|
||||
/// @note this will lock (aka "use") the collection. You must release the
|
||||
/// collection yourself.
|
||||
/// @brief parse document or document handle from a v8 value (string | object)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Handle<v8::Value> TRI_ParseDocumentOrDocumentHandle (TRI_vocbase_t* vocbase,
|
||||
bool ExtractDocumentHandle (v8::Handle<v8::Value> val,
|
||||
string& collectionName,
|
||||
TRI_voc_key_t& key,
|
||||
TRI_voc_rid_t& rid) {
|
||||
// reset the collection identifier and the revision
|
||||
collectionName = "";
|
||||
rid = 0;
|
||||
|
||||
// extract the document identifier and revision from a string
|
||||
if (val->IsString() || val->IsStringObject()) {
|
||||
return ParseDocumentHandle(val, collectionName, key);
|
||||
}
|
||||
|
||||
// extract the document identifier and revision from a document object
|
||||
if (val->IsObject()) {
|
||||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
|
||||
v8::Handle<v8::Object> obj = val->ToObject();
|
||||
v8::Handle<v8::Value> didVal = obj->Get(v8g->DidKey);
|
||||
|
||||
if (! ParseDocumentHandle(didVal, collectionName, key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rid = TRI_ObjectToUInt64(obj->Get(v8g->RevKey), true);
|
||||
|
||||
if (rid == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// unknown value type. give up
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief parse document or document handle from a v8 value (string | object)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Handle<v8::Value> TRI_ParseDocumentOrDocumentHandle (const CollectionNameResolver& resolver,
|
||||
TRI_vocbase_col_t const*& collection,
|
||||
TRI_voc_key_t& key,
|
||||
TRI_voc_rid_t& rid,
|
||||
const bool use,
|
||||
v8::Handle<v8::Value> val) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
|
|
@ -6108,57 +6157,34 @@ v8::Handle<v8::Value> TRI_ParseDocumentOrDocumentHandle (TRI_vocbase_t* vocbase,
|
|||
string collectionName = "";
|
||||
rid = 0;
|
||||
|
||||
// extract the document identifier and revision from a string
|
||||
if (val->IsString() || val->IsStringObject()) {
|
||||
if (! IsDocumentHandle(vocbase, val, collectionName, key)) {
|
||||
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD,
|
||||
"<document-handle> must be a document-handle"));
|
||||
}
|
||||
}
|
||||
|
||||
// extract the document identifier and revision from a string
|
||||
else if (val->IsObject()) {
|
||||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
|
||||
v8::Handle<v8::Object> obj = val->ToObject();
|
||||
v8::Handle<v8::Value> didVal = obj->Get(v8g->DidKey);
|
||||
|
||||
if (! IsDocumentHandle(vocbase, didVal, collectionName, key)) {
|
||||
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD,
|
||||
"expecting a document-handle in _id"));
|
||||
}
|
||||
|
||||
rid = TRI_ObjectToUInt64(obj->Get(v8g->RevKey), true);
|
||||
|
||||
if (rid == 0) {
|
||||
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD,
|
||||
"expecting a revision identifier in _rev"));
|
||||
}
|
||||
}
|
||||
|
||||
// give up
|
||||
else {
|
||||
// try to extract the collection name, key, and revision from the object passed
|
||||
if (! ExtractDocumentHandle(val, collectionName, key, rid)) {
|
||||
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD,
|
||||
"<document-handle> must be a document-handle"));
|
||||
"<document-handle> must be a valid document-handle"));
|
||||
}
|
||||
|
||||
// we have at least a key, we also might have a collection name
|
||||
assert(key != 0);
|
||||
|
||||
|
||||
if (collectionName == "") {
|
||||
// only a document id without collection name was passed
|
||||
// only a document key without collection name was passed
|
||||
if (collection == 0) {
|
||||
// we do not know the collection
|
||||
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD,
|
||||
"<document-handle> must be a document-handle"));
|
||||
}
|
||||
|
||||
// we use the current collection
|
||||
collectionName = collection->_name;
|
||||
// we use the current collection's name
|
||||
collectionName = resolver.getCollectionName(collection->_cid);
|
||||
}
|
||||
else {
|
||||
// we read a collection name from the document id
|
||||
// check cross-collection requests
|
||||
if (collection != 0 && collectionName != collection->_name) {
|
||||
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_CROSS_COLLECTION_REQUEST,
|
||||
"cannot execute cross collection query"));
|
||||
if (collection != 0) {
|
||||
if (collectionName != resolver.getCollectionName(collection->_cid)) {
|
||||
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_CROSS_COLLECTION_REQUEST,
|
||||
"cannot execute cross collection query"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6166,30 +6192,17 @@ v8::Handle<v8::Value> TRI_ParseDocumentOrDocumentHandle (TRI_vocbase_t* vocbase,
|
|||
|
||||
if (collection == 0) {
|
||||
// no collection object was passed, now check the user-supplied collection name
|
||||
TRI_vocbase_col_t* const col = TRI_LookupCollectionByNameVocBase(vocbase, collectionName.c_str());
|
||||
const TRI_vocbase_col_t* col = resolver.getCollectionStruct(collectionName);
|
||||
if (col == 0) {
|
||||
// collection not found
|
||||
return scope.Close(TRI_CreateErrorObject(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND,
|
||||
"collection of <document-handle> is unknown"));;
|
||||
}
|
||||
|
||||
if (use) {
|
||||
// use the collection
|
||||
int res = TRI_UseCollectionVocBase(vocbase, col);
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR && col->_collection == 0) {
|
||||
res = TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return scope.Close(TRI_CreateErrorObject(res, "cannot use/load collection", true));
|
||||
}
|
||||
}
|
||||
|
||||
collection = col;
|
||||
}
|
||||
|
||||
assert(collection);
|
||||
assert(collection != 0);
|
||||
|
||||
v8::Handle<v8::Value> empty;
|
||||
return scope.Close(empty);
|
||||
|
|
@ -6199,7 +6212,8 @@ v8::Handle<v8::Value> TRI_ParseDocumentOrDocumentHandle (TRI_vocbase_t* vocbase,
|
|||
/// @brief looks up an index identifier
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_index_t* TRI_LookupIndexByHandle (TRI_vocbase_t* vocbase,
|
||||
TRI_index_t* TRI_LookupIndexByHandle (const CollectionNameResolver& resolver,
|
||||
TRI_vocbase_t* vocbase,
|
||||
TRI_vocbase_col_t const*& collection,
|
||||
v8::Handle<v8::Value> val,
|
||||
bool ignoreNotFound,
|
||||
|
|
@ -6208,6 +6222,10 @@ TRI_index_t* TRI_LookupIndexByHandle (TRI_vocbase_t* vocbase,
|
|||
string collectionName = "";
|
||||
TRI_idx_iid_t iid = 0;
|
||||
|
||||
// assume we are already loaded
|
||||
assert(collection != 0);
|
||||
assert(collection->_collection != 0);
|
||||
|
||||
// extract the document identifier and revision from a string
|
||||
if (val->IsString() || val->IsStringObject()) {
|
||||
if (! IsIndexHandle(val, collectionName, iid)) {
|
||||
|
|
@ -6232,17 +6250,14 @@ TRI_index_t* TRI_LookupIndexByHandle (TRI_vocbase_t* vocbase,
|
|||
}
|
||||
|
||||
if (collectionName == "") {
|
||||
assert(false);
|
||||
// no collection name passed by user
|
||||
if (collection == 0) {
|
||||
*err = TRI_CreateErrorObject(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND,
|
||||
"collection of <index-handle> unknown");
|
||||
return 0;
|
||||
}
|
||||
|
||||
collectionName = collection->_name;
|
||||
*err = TRI_CreateErrorObject(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND,
|
||||
"collection of <index-handle> unknown");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
if (collection != 0 && collectionName != collection->_name) {
|
||||
if (collectionName != collection->_name) {
|
||||
// I wish this error provided me with more information!
|
||||
// e.g. 'cannot access index outside the collection it was defined in'
|
||||
*err = TRI_CreateErrorObject(TRI_ERROR_ARANGO_CROSS_COLLECTION_REQUEST,
|
||||
|
|
@ -6253,35 +6268,6 @@ TRI_index_t* TRI_LookupIndexByHandle (TRI_vocbase_t* vocbase,
|
|||
|
||||
assert(collectionName != "");
|
||||
|
||||
// lookup the collection
|
||||
if (collection == 0) {
|
||||
TRI_vocbase_col_t* const col = TRI_LookupCollectionByNameVocBase(vocbase, collectionName.c_str());
|
||||
|
||||
if (col == 0) {
|
||||
*err = TRI_CreateErrorObject(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND,
|
||||
"collection of <index-handle> is unknown");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// use the collection
|
||||
int res = TRI_UseCollectionVocBase(vocbase, col);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
*err = TRI_CreateErrorObject(res, "cannot use/load collection", true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (col->_collection == 0) {
|
||||
*err = TRI_CreateErrorObject(TRI_ERROR_INTERNAL, "cannot use/load collection");
|
||||
return 0;
|
||||
}
|
||||
|
||||
collection = col;
|
||||
}
|
||||
|
||||
assert(collection);
|
||||
assert(collection->_collection);
|
||||
|
||||
TRI_index_t* idx = TRI_LookupIndex(collection->_collection, iid);
|
||||
|
||||
if (idx == 0) {
|
||||
|
|
@ -6333,7 +6319,8 @@ v8::Handle<v8::Object> TRI_WrapCollection (TRI_vocbase_col_t const* collection)
|
|||
/// @brief wraps a TRI_shaped_json_t
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Handle<v8::Value> TRI_WrapShapedJson (TRI_vocbase_col_t const* collection,
|
||||
v8::Handle<v8::Value> TRI_WrapShapedJson (const CollectionNameResolver& resolver,
|
||||
TRI_vocbase_col_t const* collection,
|
||||
TRI_doc_mptr_t const* document,
|
||||
TRI_barrier_t* barrier) {
|
||||
v8::HandleScope scope;
|
||||
|
|
@ -6369,8 +6356,7 @@ v8::Handle<v8::Value> TRI_WrapShapedJson (TRI_vocbase_col_t const* collection,
|
|||
// store the document reference
|
||||
TRI_voc_rid_t rid = document->_rid;
|
||||
|
||||
// TODO: protect this against race conditions (parallel rename)
|
||||
result->Set(v8g->DidKey, V8DocumentId(collection->_name, document->_key), v8::ReadOnly);
|
||||
result->Set(v8g->DidKey, V8DocumentId(resolver.getCollectionName(collection->_cid), document->_key), v8::ReadOnly);
|
||||
result->Set(v8g->RevKey, V8RevisionId(rid), v8::ReadOnly);
|
||||
result->Set(v8g->KeyKey, v8::String::New(document->_key), v8::ReadOnly);
|
||||
|
||||
|
|
@ -6378,11 +6364,9 @@ v8::Handle<v8::Value> TRI_WrapShapedJson (TRI_vocbase_col_t const* collection,
|
|||
|
||||
if (type == TRI_DOC_MARKER_KEY_EDGE) {
|
||||
TRI_doc_edge_key_marker_t* marker = (TRI_doc_edge_key_marker_t*) document->_data;
|
||||
TRI_vocbase_t* const vocbase = collection->_vocbase;
|
||||
|
||||
// unidirectional edge
|
||||
result->Set(v8g->FromKey, V8DocumentId(vocbase, marker->_fromCid, ((char*) marker) + marker->_offsetFromKey));
|
||||
result->Set(v8g->ToKey, V8DocumentId(vocbase, marker->_toCid, ((char*) marker) + marker->_offsetToKey));
|
||||
|
||||
result->Set(v8g->FromKey, V8DocumentId(resolver.getCollectionName(marker->_fromCid), ((char*) marker) + marker->_offsetFromKey));
|
||||
result->Set(v8g->ToKey, V8DocumentId(resolver.getCollectionName(marker->_toCid), ((char*) marker) + marker->_offsetToKey));
|
||||
}
|
||||
|
||||
// and return
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "V8/v8-globals.h"
|
||||
#include "ShapedJson/shaped-json.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "VocBase/document-collection.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
@ -71,18 +72,18 @@ void TRI_ReleaseCollection (TRI_vocbase_col_t const*);
|
|||
/// @brief parse document or document handle
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Handle<v8::Value> TRI_ParseDocumentOrDocumentHandle (TRI_vocbase_t*,
|
||||
v8::Handle<v8::Value> TRI_ParseDocumentOrDocumentHandle (const triagens::arango::CollectionNameResolver&,
|
||||
TRI_vocbase_col_t const*&,
|
||||
TRI_voc_key_t&,
|
||||
TRI_voc_rid_t&,
|
||||
const bool,
|
||||
v8::Handle<v8::Value>);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up a index identifier
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_index_t* TRI_LookupIndexByHandle (TRI_vocbase_t*,
|
||||
TRI_index_t* TRI_LookupIndexByHandle (const triagens::arango::CollectionNameResolver&,
|
||||
TRI_vocbase_t*,
|
||||
TRI_vocbase_col_t const*&,
|
||||
v8::Handle<v8::Value>,
|
||||
bool,
|
||||
|
|
@ -104,7 +105,8 @@ v8::Handle<v8::Object> TRI_WrapCollection (TRI_vocbase_col_t const*);
|
|||
/// @brief wraps a TRI_shaped_json_t
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Handle<v8::Value> TRI_WrapShapedJson (TRI_vocbase_col_t const*,
|
||||
v8::Handle<v8::Value> TRI_WrapShapedJson (const triagens::arango::CollectionNameResolver&,
|
||||
TRI_vocbase_col_t const*,
|
||||
TRI_doc_mptr_t const*,
|
||||
TRI_barrier_t*);
|
||||
|
||||
|
|
|
|||
|
|
@ -53,19 +53,19 @@ static uint64_t HashCollection (TRI_associative_pointer_t* array,
|
|||
void const* element) {
|
||||
TRI_transaction_collection_global_t* collection = (TRI_transaction_collection_global_t*) element;
|
||||
|
||||
return TRI_FnvHashString(collection->_name);
|
||||
return TRI_FnvHashPointer((void const*) &(collection->_cid), sizeof(TRI_transaction_cid_t));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief comparison function used to determine collection equality
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool IsEqualCollectionName (TRI_associative_pointer_t* array,
|
||||
void const* key,
|
||||
void const* element) {
|
||||
static bool IsEqualCollectionId (TRI_associative_pointer_t* array,
|
||||
void const* key,
|
||||
void const* element) {
|
||||
TRI_transaction_collection_global_t* collection = (TRI_transaction_collection_global_t*) element;
|
||||
|
||||
return TRI_EqualString(key, collection->_name);
|
||||
return *((TRI_transaction_cid_t*) key) == collection->_cid;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -314,13 +314,7 @@ TRI_transaction_collection_global_t* CreateCollectionGlobalInstance (const TRI_t
|
|||
return NULL;
|
||||
}
|
||||
|
||||
globalInstance->_name = TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, collection->_name);
|
||||
if (globalInstance->_name == NULL) {
|
||||
// OOM
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, globalInstance);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
globalInstance->_cid = collection->_cid;
|
||||
|
||||
TRI_InitMutex(&globalInstance->_writeLock);
|
||||
InitTransactionList(&globalInstance->_writeTransactions);
|
||||
|
|
@ -336,8 +330,6 @@ void FreeCollectionGlobalInstance (TRI_transaction_collection_global_t* const gl
|
|||
DestroyTransactionList(&globalInstance->_writeTransactions);
|
||||
TRI_DestroyMutex(&globalInstance->_writeLock);
|
||||
|
||||
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, (char*) globalInstance->_name);
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, globalInstance);
|
||||
}
|
||||
|
||||
|
|
@ -375,7 +367,7 @@ TRI_transaction_context_t* TRI_CreateTransactionContext (TRI_vocbase_t* const vo
|
|||
TRI_UNKNOWN_MEM_ZONE,
|
||||
TRI_HashStringKeyAssociativePointer,
|
||||
HashCollection,
|
||||
IsEqualCollectionName,
|
||||
IsEqualCollectionId,
|
||||
NULL);
|
||||
|
||||
// setup global transaction lists
|
||||
|
|
@ -438,14 +430,14 @@ void TRI_FreeTransactionContext (TRI_transaction_context_t* const context) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_RemoveCollectionTransactionContext (TRI_transaction_context_t* const context,
|
||||
const char* const name) {
|
||||
const TRI_transaction_cid_t cid) {
|
||||
TRI_transaction_collection_global_t* collection;
|
||||
|
||||
// start critical section -----------------------------------------
|
||||
TRI_LockMutex(&context->_collectionLock);
|
||||
|
||||
// TODO: must not remove collections with transactions going on
|
||||
collection = (TRI_transaction_collection_global_t*) TRI_RemoveKeyAssociativePointer(&context->_collections, name);
|
||||
collection = (TRI_transaction_collection_global_t*) TRI_RemoveKeyAssociativePointer(&context->_collections, &cid);
|
||||
|
||||
TRI_UnlockMutex(&context->_collectionLock);
|
||||
// end critical section -----------------------------------------
|
||||
|
|
@ -504,7 +496,7 @@ void TRI_DumpTransactionContext (TRI_transaction_context_t* const context) {
|
|||
/// @brief create a transaction collection container
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_transaction_collection_t* CreateCollection (const char* const name,
|
||||
static TRI_transaction_collection_t* CreateCollection (const TRI_transaction_cid_t cid,
|
||||
const TRI_transaction_type_e type) {
|
||||
TRI_transaction_collection_t* collection;
|
||||
|
||||
|
|
@ -514,15 +506,8 @@ static TRI_transaction_collection_t* CreateCollection (const char* const name,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
collection->_name = TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, name);
|
||||
if (collection->_name == NULL) {
|
||||
// OOM
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// initialise collection properties
|
||||
collection->_cid = cid;
|
||||
collection->_type = type;
|
||||
collection->_collection = NULL;
|
||||
collection->_globalInstance = NULL;
|
||||
|
|
@ -540,10 +525,7 @@ static TRI_transaction_collection_t* CreateCollection (const char* const name,
|
|||
|
||||
static void FreeCollection (TRI_transaction_collection_t* collection) {
|
||||
assert(collection);
|
||||
assert(collection->_name);
|
||||
|
||||
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, (char*) collection->_name);
|
||||
|
||||
DestroyTransactionList(&collection->_writeTransactions);
|
||||
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection);
|
||||
|
|
@ -561,11 +543,11 @@ static TRI_transaction_collection_global_t* GetGlobalCollection (TRI_transaction
|
|||
// start critical section -----------------------------------------
|
||||
TRI_LockMutex(&context->_collectionLock);
|
||||
|
||||
globalInstance = (TRI_transaction_collection_global_t*) TRI_LookupByKeyAssociativePointer(&context->_collections, collection->_name);
|
||||
globalInstance = (TRI_transaction_collection_global_t*) TRI_LookupByKeyAssociativePointer(&context->_collections, &(collection->_cid));
|
||||
if (globalInstance == NULL) {
|
||||
globalInstance = CreateCollectionGlobalInstance(collection);
|
||||
if (globalInstance != NULL) {
|
||||
TRI_InsertKeyAssociativePointer(&context->_collections, collection->_name, globalInstance, false);
|
||||
TRI_InsertKeyAssociativePointer(&context->_collections, &(collection->_cid), globalInstance, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -576,10 +558,10 @@ static TRI_transaction_collection_global_t* GetGlobalCollection (TRI_transaction
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief acquire collection locks for a transaction
|
||||
/// @brief use all participating collections of a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int AcquireCollectionLocks (TRI_transaction_t* const trx) {
|
||||
static int UseCollections (TRI_transaction_t* const trx) {
|
||||
TRI_transaction_context_t* context;
|
||||
size_t i, n;
|
||||
|
||||
|
|
@ -594,12 +576,13 @@ static int AcquireCollectionLocks (TRI_transaction_t* const trx) {
|
|||
TRI_transaction_collection_t* collection;
|
||||
|
||||
collection = (TRI_transaction_collection_t*) TRI_AtVectorPointer(&trx->_collections, i);
|
||||
collection->_collection = TRI_UseCollectionByNameVocBase(trx->_context->_vocbase, collection->_name);
|
||||
|
||||
LOG_DEBUG("using collection %llu", (unsigned long long) collection->_cid);
|
||||
collection->_collection = TRI_UseCollectionByIdVocBase(trx->_context->_vocbase, collection->_cid);
|
||||
|
||||
if (collection->_collection == NULL) {
|
||||
return TRI_errno();
|
||||
}
|
||||
|
||||
|
||||
collection->_globalInstance = GetGlobalCollection(context, collection);
|
||||
if (collection->_globalInstance == NULL) {
|
||||
|
|
@ -607,7 +590,7 @@ static int AcquireCollectionLocks (TRI_transaction_t* const trx) {
|
|||
}
|
||||
|
||||
if (collection->_type == TRI_TRANSACTION_WRITE) {
|
||||
LOG_DEBUG("acquiring write-lock on collection '%s'", collection->_name);
|
||||
LOG_DEBUG("acquiring write-lock on collection %llu", (unsigned long long) collection->_cid);
|
||||
|
||||
// acquire write-lock on collection
|
||||
TRI_LockMutex(&collection->_globalInstance->_writeLock);
|
||||
|
|
@ -622,11 +605,11 @@ static int AcquireCollectionLocks (TRI_transaction_t* const trx) {
|
|||
/// @brief release collection locks for a transaction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int ReleaseCollectionLocks (TRI_transaction_t* const trx) {
|
||||
static int ReleaseCollections (TRI_transaction_t* const trx) {
|
||||
size_t i;
|
||||
int res;
|
||||
|
||||
LOG_DEBUG("releasing collection locks");
|
||||
LOG_DEBUG("releasing collections");
|
||||
|
||||
res = TRI_ERROR_NO_ERROR;
|
||||
|
||||
|
|
@ -642,7 +625,7 @@ static int ReleaseCollectionLocks (TRI_transaction_t* const trx) {
|
|||
}
|
||||
|
||||
if (collection->_type == TRI_TRANSACTION_WRITE && collection->_locked) {
|
||||
LOG_DEBUG("releasing write-lock on collection '%s'", collection->_name);
|
||||
LOG_DEBUG("releasing trx exclusive lock on collection %llu", (unsigned long long) collection->_cid);
|
||||
|
||||
// release write-lock on collection
|
||||
TRI_UnlockMutex(&collection->_globalInstance->_writeLock);
|
||||
|
|
@ -651,6 +634,7 @@ static int ReleaseCollectionLocks (TRI_transaction_t* const trx) {
|
|||
}
|
||||
|
||||
// unuse collection
|
||||
LOG_DEBUG("unusing collection %llu", (unsigned long long) collection->_cid);
|
||||
TRI_ReleaseCollectionVocBase(trx->_context->_vocbase, collection->_collection);
|
||||
|
||||
collection->_collection = NULL;
|
||||
|
|
@ -930,7 +914,7 @@ void TRI_FreeTransaction (TRI_transaction_t* const trx) {
|
|||
TRI_AbortTransaction(trx);
|
||||
}
|
||||
|
||||
ReleaseCollectionLocks(trx);
|
||||
ReleaseCollections(trx);
|
||||
|
||||
// free all collections
|
||||
i = trx->_collections._length;
|
||||
|
|
@ -1025,7 +1009,7 @@ void TRI_DumpTransaction (TRI_transaction_t* const trx) {
|
|||
|
||||
TRI_transaction_collection_t* collection = TRI_AtVectorPointer(&trx->_collections, i);
|
||||
|
||||
LOG_INFO("- collection: %s, type: %s", collection->_name, TypeString(collection->_type));
|
||||
LOG_INFO("- collection: %llu, type: %s", (unsigned long long) collection->_cid, TypeString(collection->_type));
|
||||
for (j = 0; j < collection->_writeTransactions._vector._length; ++j) {
|
||||
TRI_transaction_list_entry_t* entry;
|
||||
|
||||
|
|
@ -1042,29 +1026,26 @@ void TRI_DumpTransaction (TRI_transaction_t* const trx) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vocbase_col_t* TRI_CheckCollectionTransaction (TRI_transaction_t* const trx,
|
||||
const char* const name,
|
||||
const TRI_transaction_cid_t cid,
|
||||
const TRI_transaction_type_e type) {
|
||||
TRI_transaction_collection_t* collection;
|
||||
size_t i, n;
|
||||
|
||||
assert(trx->_status == TRI_TRANSACTION_CREATED ||
|
||||
trx->_status == TRI_TRANSACTION_RUNNING);
|
||||
assert(name);
|
||||
|
||||
// check if we already have got this collection in the _collections vector
|
||||
// the vector is sorted by collection names
|
||||
n = trx->_collections._length;
|
||||
for (i = 0; i < n; ++i) {
|
||||
int res;
|
||||
|
||||
collection = TRI_AtVectorPointer(&trx->_collections, i);
|
||||
res = strcmp(name, collection->_name);
|
||||
|
||||
if (res < 0) {
|
||||
if (cid < collection->_cid) {
|
||||
// collection is not contained in vector
|
||||
break;
|
||||
}
|
||||
else if (res == 0) {
|
||||
else if (cid == collection->_cid) {
|
||||
// collection is already contained in vector
|
||||
|
||||
// check if access type matches
|
||||
|
|
@ -1084,13 +1065,12 @@ TRI_vocbase_col_t* TRI_CheckCollectionTransaction (TRI_transaction_t* const trx,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_AddCollectionTransaction (TRI_transaction_t* const trx,
|
||||
const char* const name,
|
||||
const TRI_transaction_cid_t cid,
|
||||
const TRI_transaction_type_e type) {
|
||||
TRI_transaction_collection_t* collection;
|
||||
size_t i, n;
|
||||
|
||||
assert(trx->_status == TRI_TRANSACTION_CREATED);
|
||||
assert(name);
|
||||
|
||||
// upgrade transaction type if required
|
||||
if (type == TRI_TRANSACTION_WRITE && trx->_type == TRI_TRANSACTION_READ) {
|
||||
|
|
@ -1102,14 +1082,11 @@ int TRI_AddCollectionTransaction (TRI_transaction_t* const trx,
|
|||
// the vector is sorted by collection names
|
||||
n = trx->_collections._length;
|
||||
for (i = 0; i < n; ++i) {
|
||||
int res;
|
||||
|
||||
collection = TRI_AtVectorPointer(&trx->_collections, i);
|
||||
res = strcmp(name, collection->_name);
|
||||
|
||||
if (res < 0) {
|
||||
if (cid < collection->_cid) {
|
||||
// collection is not contained in vector
|
||||
collection = CreateCollection(name, type);
|
||||
collection = CreateCollection(cid, type);
|
||||
if (collection == NULL) {
|
||||
// out of memory
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
|
|
@ -1119,7 +1096,7 @@ int TRI_AddCollectionTransaction (TRI_transaction_t* const trx,
|
|||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
else if (res == 0) {
|
||||
else if (cid == collection->_cid) {
|
||||
// collection is already contained in vector
|
||||
|
||||
// upgrade collection type if required
|
||||
|
|
@ -1132,7 +1109,7 @@ int TRI_AddCollectionTransaction (TRI_transaction_t* const trx,
|
|||
}
|
||||
|
||||
// collection was not contained. now insert it
|
||||
collection = CreateCollection(name, type);
|
||||
collection = CreateCollection(cid, type);
|
||||
if (collection == NULL) {
|
||||
// out of memory
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
|
|
@ -1154,11 +1131,11 @@ int TRI_StartTransaction (TRI_transaction_t* const trx, TRI_transaction_hint_t h
|
|||
|
||||
trx->_hints = hints;
|
||||
|
||||
res = AcquireCollectionLocks(trx);
|
||||
res = UseCollections(trx);
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
// free what we have got so far
|
||||
trx->_status = TRI_TRANSACTION_FAILED;
|
||||
ReleaseCollectionLocks(trx);
|
||||
ReleaseCollections(trx);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1167,7 +1144,7 @@ int TRI_StartTransaction (TRI_transaction_t* const trx, TRI_transaction_hint_t h
|
|||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
// free what we have got so far
|
||||
trx->_status = TRI_TRANSACTION_FAILED;
|
||||
ReleaseCollectionLocks(trx);
|
||||
ReleaseCollections(trx);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1187,7 +1164,7 @@ int TRI_CommitTransaction (TRI_transaction_t* const trx) {
|
|||
assert(trx->_status == TRI_TRANSACTION_RUNNING);
|
||||
|
||||
res = UpdateTransactionStatus(trx, TRI_TRANSACTION_COMMITTED);
|
||||
ReleaseCollectionLocks(trx);
|
||||
ReleaseCollections(trx);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1202,7 +1179,7 @@ int TRI_AbortTransaction (TRI_transaction_t* const trx) {
|
|||
assert(trx->_status == TRI_TRANSACTION_RUNNING);
|
||||
|
||||
res = UpdateTransactionStatus(trx, TRI_TRANSACTION_ABORTED);
|
||||
ReleaseCollectionLocks(trx);
|
||||
ReleaseCollections(trx);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1228,7 +1205,7 @@ int TRI_FinishTransaction (TRI_transaction_t* const trx) {
|
|||
|
||||
res = UpdateTransactionStatus(trx, status);
|
||||
|
||||
ReleaseCollectionLocks(trx);
|
||||
ReleaseCollections(trx);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1238,7 +1215,7 @@ int TRI_FinishTransaction (TRI_transaction_t* const trx) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vocbase_col_t* TRI_GetCollectionTransaction (const TRI_transaction_t* const trx,
|
||||
const char* const name) {
|
||||
const TRI_transaction_cid_t cid) {
|
||||
size_t i, n;
|
||||
|
||||
assert(trx->_status == TRI_TRANSACTION_RUNNING);
|
||||
|
|
@ -1250,7 +1227,7 @@ TRI_vocbase_col_t* TRI_GetCollectionTransaction (const TRI_transaction_t* const
|
|||
TRI_transaction_collection_t* collection;
|
||||
|
||||
collection = (TRI_transaction_collection_t*) TRI_AtVectorPointer(&trx->_collections, i);
|
||||
if (TRI_EqualString(name, collection->_name)) {
|
||||
if (cid == collection->_cid) {
|
||||
return collection->_collection;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ struct TRI_vocbase_col_s;
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef uint64_t TRI_transaction_cid_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief local transaction id typedef
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -196,7 +198,7 @@ TRI_transaction_context_t;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_transaction_collection_global_s {
|
||||
const char* _name; // collection name
|
||||
TRI_transaction_cid_t _cid; // collection id
|
||||
TRI_transaction_list_t _writeTransactions; // list of write-transactions currently going on for the collection
|
||||
TRI_mutex_t _writeLock; // write lock for the collection, used to serialize writes on the same collection
|
||||
}
|
||||
|
|
@ -247,7 +249,7 @@ void TRI_FreeTransactionContext (TRI_transaction_context_t*);
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_RemoveCollectionTransactionContext (TRI_transaction_context_t* const,
|
||||
const char* const);
|
||||
const TRI_transaction_cid_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief dump transaction context data
|
||||
|
|
@ -277,7 +279,7 @@ void TRI_DumpTransactionContext (TRI_transaction_context_t* const);
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_transaction_collection_s {
|
||||
const char* _name; // collection name
|
||||
TRI_transaction_cid_t _cid; // collection id
|
||||
TRI_transaction_type_e _type; // access type (read|write)
|
||||
TRI_transaction_list_t _writeTransactions; // private copy of other write transactions at transaction start
|
||||
struct TRI_vocbase_col_s* _collection; // vocbase collection pointer
|
||||
|
|
@ -385,7 +387,7 @@ void TRI_DumpTransaction (TRI_transaction_t* const);
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TRI_vocbase_col_s* TRI_CheckCollectionTransaction (TRI_transaction_t* const,
|
||||
const char* const,
|
||||
const TRI_transaction_cid_t,
|
||||
const TRI_transaction_type_e);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -393,7 +395,7 @@ struct TRI_vocbase_col_s* TRI_CheckCollectionTransaction (TRI_transaction_t* con
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_AddCollectionTransaction (TRI_transaction_t* const,
|
||||
const char* const,
|
||||
const TRI_transaction_cid_t,
|
||||
const TRI_transaction_type_e);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -425,7 +427,7 @@ int TRI_FinishTransaction (TRI_transaction_t* const);
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TRI_vocbase_col_s* TRI_GetCollectionTransaction (const TRI_transaction_t* const,
|
||||
const char* const);
|
||||
const TRI_transaction_cid_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
|
|||
|
|
@ -1885,6 +1885,38 @@ int TRI_UseCollectionVocBase (TRI_vocbase_t* vocbase, TRI_vocbase_col_t* collect
|
|||
return LoadCollectionVocBase(vocbase, collection);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief locks a (document) collection for usage by id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vocbase_col_t* TRI_UseCollectionByIdVocBase (TRI_vocbase_t* vocbase, const TRI_voc_cid_t cid) {
|
||||
union { TRI_vocbase_col_t const* c; TRI_vocbase_col_t* v; } cnv;
|
||||
TRI_vocbase_col_t const* collection;
|
||||
int res;
|
||||
|
||||
// .............................................................................
|
||||
// check that we have an existing name
|
||||
// .............................................................................
|
||||
|
||||
TRI_READ_LOCK_COLLECTIONS_VOCBASE(vocbase);
|
||||
collection = TRI_LookupByKeyAssociativePointer(&vocbase->_collectionsById, &cid);
|
||||
TRI_READ_UNLOCK_COLLECTIONS_VOCBASE(vocbase);
|
||||
|
||||
if (collection == NULL) {
|
||||
TRI_set_errno(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// .............................................................................
|
||||
// try to load the collection
|
||||
// .............................................................................
|
||||
|
||||
cnv.c = collection;
|
||||
res = LoadCollectionVocBase(vocbase, cnv.v);
|
||||
|
||||
return res == TRI_ERROR_NO_ERROR ? cnv.v : NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief locks a (document) collection for usage by name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -570,6 +570,16 @@ int TRI_RenameCollectionVocBase (TRI_vocbase_t*, TRI_vocbase_col_t*, char const*
|
|||
|
||||
int TRI_UseCollectionVocBase (TRI_vocbase_t*, TRI_vocbase_col_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief locks a (document) collection for usage by id
|
||||
///
|
||||
/// Note that this will READ lock the collection you have to release the
|
||||
/// collection lock by yourself and call @ref TRI_ReleaseCollectionVocBase
|
||||
/// when you are done with the collection.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vocbase_col_t* TRI_UseCollectionByIdVocBase (TRI_vocbase_t*, const TRI_voc_cid_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief locks a (document) collection for usage by name
|
||||
///
|
||||
|
|
|
|||
|
|
@ -290,6 +290,41 @@ function CollectionEdgeSuite () {
|
|||
|
||||
assertTypeOf("string", doc._id);
|
||||
assertTypeOf("string", doc._rev);
|
||||
assertMatch(/^UnitTestsCollectionEdge\//, doc._id);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an edge that reference non-existing vertex collections
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testSaveEdgeInvalidVertexCollection : function () {
|
||||
[ "UnitTestsCollectionNonExistingVertex/12345", "UnitTestsCollectionNonExistingVertex/456745" ].forEach(function(key) {
|
||||
try {
|
||||
edge.save(key, key, { });
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(ERRORS.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, err.errorNum);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create an edge that reference an unloaded collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testSaveEdgeUnloadedVertexCollection : function () {
|
||||
vertex.unload();
|
||||
wait(4);
|
||||
|
||||
var e = edge.save(v1._id, v2._id, { });
|
||||
|
||||
assertMatch(/^UnitTestsCollectionEdge\//, e._id);
|
||||
var doc = edge.document(e._id);
|
||||
|
||||
assertMatch(/^UnitTestsCollectionEdge\//, doc._id);
|
||||
assertMatch(/^UnitTestsCollectionVertex\//, doc._from);
|
||||
assertMatch(/^UnitTestsCollectionVertex\//, doc._to);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -462,6 +497,54 @@ function CollectionEdgeSuite () {
|
|||
assertEqual(1, e.length);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief edges query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testReadEdgesUnloaded : function () {
|
||||
var d1 = edge.save(v1, v2, { "Hallo" : "World" })._id;
|
||||
var d2 = edge.save(v2, v1, { "World" : "Hallo" })._id;
|
||||
|
||||
var e1 = edge.document(d1);
|
||||
var e2 = edge.document(d2);
|
||||
|
||||
assertMatch(/^UnitTestsCollectionEdge\//, e1._id);
|
||||
assertMatch(/^UnitTestsCollectionVertex\//, e1._from);
|
||||
assertMatch(/^UnitTestsCollectionVertex\//, e1._to);
|
||||
|
||||
assertMatch(/^UnitTestsCollectionEdge\//, e2._id);
|
||||
assertMatch(/^UnitTestsCollectionVertex\//, e2._from);
|
||||
assertMatch(/^UnitTestsCollectionVertex\//, e2._to);
|
||||
|
||||
e1 = null;
|
||||
e2 = null;
|
||||
|
||||
vertex.unload();
|
||||
edge.unload();
|
||||
wait(4);
|
||||
|
||||
var e = edge.edges(v1);
|
||||
|
||||
assertEqual(2, e.length);
|
||||
|
||||
if (e[0]._id == d1) {
|
||||
assertEqual(v2._id, e[0]._to);
|
||||
assertEqual(v1._id, e[0]._from);
|
||||
|
||||
assertEqual(d2, e[1]._id);
|
||||
assertEqual(v1._id, e[1]._to);
|
||||
assertEqual(v2._id, e[1]._from);
|
||||
}
|
||||
else {
|
||||
assertEqual(v1._id, e[0]._to);
|
||||
assertEqual(v2._id, e[0]._from);
|
||||
|
||||
assertEqual(d1, e[1]._id);
|
||||
assertEqual(v2._id, e[1]._to);
|
||||
assertEqual(v1._id, e[1]._from);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief edges query invalid
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
var jsunity = require("jsunity");
|
||||
var internal = require("internal");
|
||||
var console = require("console");
|
||||
var errors = internal.errors;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- basic methods
|
||||
|
|
@ -204,7 +205,37 @@ function HashIndexSuite() {
|
|||
assertEqual(2, s.total);
|
||||
assertEqual(2, s.count);
|
||||
assertEqual([d11,d12], s.documents.map(fun));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test: documents of an unloaded collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testReadDocumentsUnloaded : function () {
|
||||
var idx = collection.ensureHashIndex("a");
|
||||
|
||||
var d1 = collection.save({ a : 1, b : 1 })._id;
|
||||
var d2 = collection.save({ a : 2, b : 1 })._id;
|
||||
var d3 = collection.save({ a : 3, b : 1 })._id;
|
||||
|
||||
collection.unload();
|
||||
internal.wait(4);
|
||||
|
||||
var s = collection.BY_EXAMPLE_HASH(idx.id, { a : 2, b : 1 });
|
||||
assertEqual(1, s.total);
|
||||
assertEqual(d2, s.documents[0]._id);
|
||||
|
||||
collection.drop();
|
||||
|
||||
try {
|
||||
s = collection.BY_EXAMPLE_HASH(idx.id, { a : 2, b : 1 });
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, err.errorNum);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
var jsunity = require("jsunity");
|
||||
var internal = require("internal");
|
||||
var console = require("console");
|
||||
var errors = internal.errors;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- basic methods
|
||||
|
|
@ -133,7 +134,60 @@ function indexSuite() {
|
|||
|
||||
res = internal.db._dropIndex(id);
|
||||
assertEqual(false, res);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief access a non-existing index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testGetNonExistingIndexes : function () {
|
||||
tests = [ "yippie", "9999999999999", -1 ].forEach(function (id) {
|
||||
var idx = collection.index(id);
|
||||
|
||||
assertEqual(null, idx);
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief access an existing index of an unloaded collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testGetIndexUnloaded : function () {
|
||||
var idx = collection.ensureHashIndex("test");
|
||||
|
||||
collection.unload();
|
||||
internal.wait(4);
|
||||
|
||||
assertEqual(idx.id, collection.index(idx.id).id);
|
||||
assertEqual(idx.id, collection.getIndexes()[1].id);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief access an existing index of a dropped collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testGetIndexDropped : function () {
|
||||
var idx = collection.ensureHashIndex("test");
|
||||
|
||||
collection.drop();
|
||||
|
||||
try {
|
||||
collection.index(idx.id).id;
|
||||
fail();
|
||||
}
|
||||
catch (e1) {
|
||||
assertEqual(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, e1.errorNum);
|
||||
}
|
||||
|
||||
try {
|
||||
collection.getIndexes();
|
||||
fail();
|
||||
}
|
||||
catch (e2) {
|
||||
assertEqual(errors.ERROR_ARANGO_COLLECTION_NOT_FOUND.code, e2.errorNum);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue