From 12d76b83067794e4352d68d1507a2067eec71fd2 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Thu, 15 Nov 2012 09:52:47 +0100 Subject: [PATCH] introduced additional transaction type for import --- arangod/Makefile.files | 6 +- arangod/RestHandler/RestDocumentHandler.cpp | 4 +- arangod/RestHandler/RestImportHandler.cpp | 6 +- arangod/RestHandler/RestVocbaseBaseHandler.h | 2 +- arangod/Utils/ImportTransaction.h | 91 +++++++ arangod/Utils/SelfContainedWriteTransaction.h | 164 +----------- ... => SingleCollectionReadOnlyTransaction.h} | 42 +-- ...action.h => SingleCollectionTransaction.h} | 50 ++-- .../Utils/SingleCollectionWriteTransaction.h | 251 ++++++++++++++++++ arangod/Utils/Transaction.h | 20 +- js/common/bootstrap/errors.js | 1 + lib/BasicsC/errors.dat | 1 + lib/BasicsC/voc-errors.c | 1 + lib/BasicsC/voc-errors.h | 14 + 14 files changed, 429 insertions(+), 224 deletions(-) create mode 100644 arangod/Utils/ImportTransaction.h rename arangod/Utils/{SelfContainedReadTransaction.h => SingleCollectionReadOnlyTransaction.h} (66%) rename arangod/Utils/{SelfContainedTransaction.h => SingleCollectionTransaction.h} (90%) create mode 100644 arangod/Utils/SingleCollectionWriteTransaction.h diff --git a/arangod/Makefile.files b/arangod/Makefile.files index 37dd7fe2e2..b78dd53544 100755 --- a/arangod/Makefile.files +++ b/arangod/Makefile.files @@ -87,14 +87,10 @@ bin_arangod_SOURCES = \ arangod/VocBase/shadow-data.c \ arangod/VocBase/shape-collection.c \ arangod/VocBase/synchroniser.c \ + arangod/VocBase/transaction.c \ arangod/VocBase/voc-shaper.c \ arangod/VocBase/vocbase.c -bin_arangod_SOURCES += \ - arangod/VocBase/versioned-index.c \ - arangod/VocBase/transaction.c - - if ENABLE_MRUBY bin_arangod_LDADD += \ diff --git a/arangod/RestHandler/RestDocumentHandler.cpp b/arangod/RestHandler/RestDocumentHandler.cpp index 613fd0ca27..f812e88055 100644 --- a/arangod/RestHandler/RestDocumentHandler.cpp +++ b/arangod/RestHandler/RestDocumentHandler.cpp @@ -404,7 +404,7 @@ bool RestDocumentHandler::readSingleDocument (bool generateBody) { // find and load collection given by name or identifier Collection c(_vocbase, collection, getCollectionType(), false); - SelfContainedReadTransaction trx(&c); + SingleCollectionReadOnlyTransaction trx(&c); // ............................................................................. // inside read transaction @@ -494,7 +494,7 @@ bool RestDocumentHandler::readAllDocuments () { // find and load collection given by name or identifier Collection c(_vocbase, collection, getCollectionType(), false); - SelfContainedReadTransaction trx(&c); + SingleCollectionReadOnlyTransaction trx(&c); vector ids; diff --git a/arangod/RestHandler/RestImportHandler.cpp b/arangod/RestHandler/RestImportHandler.cpp index 0a3f67831d..775924c12a 100644 --- a/arangod/RestHandler/RestImportHandler.cpp +++ b/arangod/RestHandler/RestImportHandler.cpp @@ -35,6 +35,8 @@ #include "VocBase/document-collection.h" #include "VocBase/vocbase.h" +#include "Utils/ImportTransaction.h" + using namespace std; using namespace triagens::basics; using namespace triagens::rest; @@ -200,7 +202,7 @@ bool RestImportHandler::createByArray () { // find and load collection given by name or identifier Collection c(_vocbase, collection, TRI_COL_TYPE_DOCUMENT, create); - SelfContainedWriteTransaction trx(&c); + ImportTransaction trx(&c); // ............................................................................. // inside write transaction @@ -376,7 +378,7 @@ bool RestImportHandler::createByList () { // find and load collection given by name or identifier Collection c(_vocbase, collection, TRI_COL_TYPE_DOCUMENT, create); - SelfContainedWriteTransaction trx(&c); + ImportTransaction trx(&c); // ............................................................................. // inside write transaction diff --git a/arangod/RestHandler/RestVocbaseBaseHandler.h b/arangod/RestHandler/RestVocbaseBaseHandler.h index d3d19029fb..16f6fcd8e2 100644 --- a/arangod/RestHandler/RestVocbaseBaseHandler.h +++ b/arangod/RestHandler/RestVocbaseBaseHandler.h @@ -36,7 +36,7 @@ #include "Logger/Logger.h" #include "Rest/HttpResponse.h" #include "Utils/Collection.h" -#include "Utils/SelfContainedReadTransaction.h" +#include "Utils/SingleCollectionReadOnlyTransaction.h" #include "Utils/SelfContainedWriteTransaction.h" // ----------------------------------------------------------------------------- diff --git a/arangod/Utils/ImportTransaction.h b/arangod/Utils/ImportTransaction.h new file mode 100644 index 0000000000..2676bf4c7c --- /dev/null +++ b/arangod/Utils/ImportTransaction.h @@ -0,0 +1,91 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @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/CollectionWriteLock.h" +#include "Utils/SingleCollectionWriteTransaction.h" + +namespace triagens { + namespace arango { + +// ----------------------------------------------------------------------------- +// --SECTION-- class ImportTransaction +// ----------------------------------------------------------------------------- + + class ImportTransaction : public SingleCollectionWriteTransaction { + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup ArangoDB +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --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 (Collection* collection) : + SingleCollectionWriteTransaction(collection, "ImportTransaction") { + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief end the transaction +//////////////////////////////////////////////////////////////////////////////// + + ~ImportTransaction () { + } + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + + }; + + } +} + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/arangod/Utils/SelfContainedWriteTransaction.h b/arangod/Utils/SelfContainedWriteTransaction.h index d986b83c56..faaa114106 100644 --- a/arangod/Utils/SelfContainedWriteTransaction.h +++ b/arangod/Utils/SelfContainedWriteTransaction.h @@ -1,5 +1,5 @@ //////////////////////////////////////////////////////////////////////////////// -/// @brief wrapper for self-contained, single collection write transactions +/// @brief wrapper for single collection, single operation write transactions /// /// @file /// @@ -29,16 +29,16 @@ #define TRIAGENS_UTILS_SELF_CONTAINED_WRITE_TRANSACTION_H 1 #include "Utils/CollectionWriteLock.h" -#include "Utils/SelfContainedTransaction.h" +#include "Utils/SingleCollectionWriteTransaction.h" namespace triagens { namespace arango { // ----------------------------------------------------------------------------- -// --SECTION-- class SelfContainedWriteTransaction +// --SECTION-- ass SelfContainedWriteTransaction // ----------------------------------------------------------------------------- - class SelfContainedWriteTransaction : public SelfContainedTransaction { + class SelfContainedWriteTransaction : public SingleCollectionWriteTransaction<1> { //////////////////////////////////////////////////////////////////////////////// /// @addtogroup ArangoDB @@ -58,11 +58,13 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// /// @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 (Collection* collection) : - SelfContainedTransaction(collection), - _synchronous(false) { + SingleCollectionWriteTransaction<1>(collection, "SelfContainedWriteTransaction") { } //////////////////////////////////////////////////////////////////////////////// @@ -72,156 +74,6 @@ namespace triagens { ~SelfContainedWriteTransaction () { } -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup ArangoDB -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- public functions -// ----------------------------------------------------------------------------- - - public: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief return whether the last write in a transaction was synchronous -//////////////////////////////////////////////////////////////////////////////// - - inline bool synchronous () const { - return _synchronous; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief create a single document within a transaction -//////////////////////////////////////////////////////////////////////////////// - - int createDocument (TRI_doc_mptr_t** mptr, - TRI_json_t const* json, - bool forceSync) { - TRI_primary_collection_t* primary = _collection->primary(); - TRI_doc_operation_context_t context; - - TRI_InitContextPrimaryCollection(&context, primary, TRI_DOC_UPDATE_ERROR, forceSync); - _synchronous = context._sync; - - CollectionWriteLock lock(_collection); - - return primary->createJson(&context, TRI_DOC_MARKER_KEY_DOCUMENT, mptr, json, 0); - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief create a single edge within a transaction -//////////////////////////////////////////////////////////////////////////////// - - int createEdge (TRI_doc_mptr_t** mptr, - TRI_json_t const* json, - bool forceSync, - void const* data) { - TRI_primary_collection_t* primary = _collection->primary(); - TRI_doc_operation_context_t context; - - TRI_InitContextPrimaryCollection(&context, primary, TRI_DOC_UPDATE_ERROR, forceSync); - _synchronous = context._sync; - - CollectionWriteLock lock(_collection); - - return primary->createJson(&context, TRI_DOC_MARKER_KEY_EDGE, mptr, json, data); - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief update a single document within a transaction -//////////////////////////////////////////////////////////////////////////////// - - int updateJson (const string& key, - TRI_doc_mptr_t** mptr, - TRI_json_t* const json, - const TRI_doc_update_policy_e policy, - bool forceSync, - const TRI_voc_rid_t expectedRevision, - TRI_voc_rid_t* actualRevision) { - TRI_primary_collection_t* primary = _collection->primary(); - TRI_doc_operation_context_t context; - - TRI_InitContextPrimaryCollection(&context, primary, policy, forceSync); - context._expectedRid = expectedRevision; - context._previousRid = actualRevision; - _synchronous = context._sync; - - CollectionWriteLock lock(_collection); - - return primary->updateJson(&context, mptr, json, (TRI_voc_key_t) key.c_str()); - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief delete a single document within a transaction -//////////////////////////////////////////////////////////////////////////////// - - int destroy (const string& key, - const TRI_doc_update_policy_e policy, - bool forceSync, - const TRI_voc_rid_t expectedRevision, - TRI_voc_rid_t* actualRevision) { - TRI_primary_collection_t* primary = _collection->primary(); - TRI_doc_operation_context_t context; - - TRI_InitContextPrimaryCollection(&context, primary, policy, forceSync); - context._expectedRid = expectedRevision; - context._previousRid = actualRevision; - _synchronous = context._sync; - - CollectionWriteLock lock(_collection); - - return primary->destroy(&context, (TRI_voc_key_t) key.c_str()); - } - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- virtual protected functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup ArangoDB -/// @{ -//////////////////////////////////////////////////////////////////////////////// - - protected: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief get the transaction type -//////////////////////////////////////////////////////////////////////////////// - - TRI_transaction_type_e type () const { - return TRI_TRANSACTION_WRITE; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup ArangoDB -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- private variables -// ----------------------------------------------------------------------------- - - private: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief whether of not the last write action was executed synchronously -//////////////////////////////////////////////////////////////////////////////// - - bool _synchronous; - //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Utils/SelfContainedReadTransaction.h b/arangod/Utils/SingleCollectionReadOnlyTransaction.h similarity index 66% rename from arangod/Utils/SelfContainedReadTransaction.h rename to arangod/Utils/SingleCollectionReadOnlyTransaction.h index 9a52eb1015..7e0492011e 100644 --- a/arangod/Utils/SelfContainedReadTransaction.h +++ b/arangod/Utils/SingleCollectionReadOnlyTransaction.h @@ -25,19 +25,19 @@ /// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// -#ifndef TRIAGENS_UTILS_SELF_CONTAINED_READ_TRANSACTION_H -#define TRIAGENS_UTILS_SELF_CONTAINED_READ_TRANSACTION_H 1 +#ifndef TRIAGENS_UTILS_SINGLE_COLLECTION_READ_ONLY_TRANSACTION_H +#define TRIAGENS_UTILS_SINGLE_COLLECTION_READ_ONLY_TRANSACTION_H 1 -#include "Utils/SelfContainedTransaction.h" +#include "Utils/SingleCollectionTransaction.h" namespace triagens { namespace arango { // ----------------------------------------------------------------------------- -// --SECTION-- class SelfContainedReadTransaction +// --SECTION-- class SingleCollectionReadOnlyTransaction // ----------------------------------------------------------------------------- - class SelfContainedReadTransaction : public SelfContainedTransaction { + class SingleCollectionReadOnlyTransaction : public SingleCollectionTransaction { //////////////////////////////////////////////////////////////////////////////// /// @addtogroup ArangoDB @@ -57,40 +57,20 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// /// @brief create the transaction, using a collection object +/// +/// A self-contained read transaction is a transaction on a single collection +/// that only allows read operations. Write operations are not supported. //////////////////////////////////////////////////////////////////////////////// - SelfContainedReadTransaction (Collection* collection) : - SelfContainedTransaction(collection) { + SingleCollectionReadOnlyTransaction (Collection* collection) : + SingleCollectionTransaction(collection, "SingleCollectionReadOnlyTransaction", TRI_TRANSACTION_READ) { } //////////////////////////////////////////////////////////////////////////////// /// @brief end the transaction //////////////////////////////////////////////////////////////////////////////// - ~SelfContainedReadTransaction () { - } - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- virtual protected functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup ArangoDB -/// @{ -//////////////////////////////////////////////////////////////////////////////// - - protected: - -//////////////////////////////////////////////////////////////////////////////// -/// @brief get the transaction type -//////////////////////////////////////////////////////////////////////////////// - - TRI_transaction_type_e type () const { - return TRI_TRANSACTION_READ; + ~SingleCollectionReadOnlyTransaction () { } //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Utils/SelfContainedTransaction.h b/arangod/Utils/SingleCollectionTransaction.h similarity index 90% rename from arangod/Utils/SelfContainedTransaction.h rename to arangod/Utils/SingleCollectionTransaction.h index 85a3d5ebd2..c894f86217 100644 --- a/arangod/Utils/SelfContainedTransaction.h +++ b/arangod/Utils/SingleCollectionTransaction.h @@ -1,5 +1,5 @@ //////////////////////////////////////////////////////////////////////////////// -/// @brief wrapper for self-contained, single collection transactions +/// @brief wrapper for single collection transactions /// /// @file /// @@ -25,8 +25,8 @@ /// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany //////////////////////////////////////////////////////////////////////////////// -#ifndef TRIAGENS_UTILS_SELF_CONTAINED_TRANSACTION_H -#define TRIAGENS_UTILS_SELF_CONTAINED_TRANSACTION_H 1 +#ifndef TRIAGENS_UTILS_SINGLE_COLLECTION_TRANSACTION_H +#define TRIAGENS_UTILS_SINGLE_COLLECTION_TRANSACTION_H 1 #include "common.h" @@ -41,10 +41,10 @@ namespace triagens { namespace arango { // ----------------------------------------------------------------------------- -// --SECTION-- class SelfContainedTransaction +// --SECTION-- class SingleCollectionTransaction // ----------------------------------------------------------------------------- - class SelfContainedTransaction : public Transaction { + class SingleCollectionTransaction : public Transaction { //////////////////////////////////////////////////////////////////////////////// /// @addtogroup ArangoDB @@ -64,18 +64,25 @@ 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. //////////////////////////////////////////////////////////////////////////////// - SelfContainedTransaction (Collection* collection) : - Transaction(collection->vocbase()), - _collection(collection) { + SingleCollectionTransaction (Collection* collection, + const string& name, + const TRI_transaction_type_e type) : + Transaction(collection->vocbase(), name), + _collection(collection), + _type(type) { } //////////////////////////////////////////////////////////////////////////////// /// @brief end the transaction //////////////////////////////////////////////////////////////////////////////// - ~SelfContainedTransaction () { + ~SingleCollectionTransaction () { if (_trx != 0) { if (status() == TRI_TRANSACTION_RUNNING) { // auto abort @@ -249,26 +256,13 @@ namespace triagens { return TRI_ERROR_NO_ERROR; } -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -// ----------------------------------------------------------------------------- -// --SECTION-- virtual protected functions -// ----------------------------------------------------------------------------- - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup ArangoDB -/// @{ -//////////////////////////////////////////////////////////////////////////////// - - protected: - //////////////////////////////////////////////////////////////////////////////// /// @brief get the transaction type //////////////////////////////////////////////////////////////////////////////// - virtual TRI_transaction_type_e type () const = 0; + inline TRI_transaction_type_e type () const { + return _type; + } //////////////////////////////////////////////////////////////////////////////// /// @} @@ -291,6 +285,12 @@ namespace triagens { Collection* _collection; +//////////////////////////////////////////////////////////////////////////////// +/// @brief transaction type (READ | WRITE) +//////////////////////////////////////////////////////////////////////////////// + + const TRI_transaction_type_e _type; + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Utils/SingleCollectionWriteTransaction.h b/arangod/Utils/SingleCollectionWriteTransaction.h new file mode 100644 index 0000000000..1e8b377db3 --- /dev/null +++ b/arangod/Utils/SingleCollectionWriteTransaction.h @@ -0,0 +1,251 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief wrapper for self-contained, single collection 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_SINGLE_COLLECTION_WRITE_TRANSACTION_H +#define TRIAGENS_UTILS_SINGLE_COLLECTION_WRITE_TRANSACTION_H 1 + +#include "Utils/CollectionWriteLock.h" +#include "Utils/SingleCollectionTransaction.h" + +namespace triagens { + namespace arango { + +// ----------------------------------------------------------------------------- +// --SECTION-- class SingleCollectionWriteTransaction +// ----------------------------------------------------------------------------- + + template + class SingleCollectionWriteTransaction : public SingleCollectionTransaction { + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup ArangoDB +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors and destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup ArangoDB +/// @{ +//////////////////////////////////////////////////////////////////////////////// + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief create the transaction, using a collection object +/// +/// A single collection write transaction must at most execute one write operation +/// on the underlying collection. Whenever it tries to execute more than one +/// write operation, an error is returned. Executing only one operation is +/// sufficient for the basic CRUD operations and allows using the transaction +/// API even for the single CRUD operations. However, much of the transaction +/// overhead can be avoided if the transaction only consists of a single +/// operation on a single collection. +//////////////////////////////////////////////////////////////////////////////// + + SingleCollectionWriteTransaction (Collection* collection, const string& name) : + SingleCollectionTransaction(collection, name, TRI_TRANSACTION_WRITE), + _numWrites(0), + _synchronous(false) { + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief end the transaction +//////////////////////////////////////////////////////////////////////////////// + + ~SingleCollectionWriteTransaction () { + } + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup ArangoDB +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- public functions +// ----------------------------------------------------------------------------- + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief return whether the last write in a transaction was synchronous +//////////////////////////////////////////////////////////////////////////////// + + inline bool synchronous () const { + return _synchronous; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief create a single document within a transaction +//////////////////////////////////////////////////////////////////////////////// + + int createDocument (TRI_doc_mptr_t** mptr, + TRI_json_t const* json, + bool forceSync) { + + if (_numWrites++ > M) { + return TRI_ERROR_TRANSACTION_INTERNAL; + } + + TRI_primary_collection_t* primary = _collection->primary(); + TRI_doc_operation_context_t context; + + TRI_InitContextPrimaryCollection(&context, primary, TRI_DOC_UPDATE_ERROR, forceSync); + _synchronous = context._sync; + + CollectionWriteLock lock(_collection); + + return primary->createJson(&context, TRI_DOC_MARKER_KEY_DOCUMENT, mptr, json, 0); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief create a single edge within a transaction +//////////////////////////////////////////////////////////////////////////////// + + int createEdge (TRI_doc_mptr_t** mptr, + TRI_json_t const* json, + bool forceSync, + void const* data) { + if (_numWrites++ > M) { + return TRI_ERROR_TRANSACTION_INTERNAL; + } + + TRI_primary_collection_t* primary = _collection->primary(); + TRI_doc_operation_context_t context; + + TRI_InitContextPrimaryCollection(&context, primary, TRI_DOC_UPDATE_ERROR, forceSync); + _synchronous = context._sync; + + CollectionWriteLock lock(_collection); + + return primary->createJson(&context, TRI_DOC_MARKER_KEY_EDGE, mptr, json, data); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief update a single document within a transaction +//////////////////////////////////////////////////////////////////////////////// + + int updateJson (const string& key, + TRI_doc_mptr_t** mptr, + TRI_json_t* const json, + const TRI_doc_update_policy_e policy, + bool forceSync, + const TRI_voc_rid_t expectedRevision, + TRI_voc_rid_t* actualRevision) { + if (_numWrites++ > M) { + return TRI_ERROR_TRANSACTION_INTERNAL; + } + + TRI_primary_collection_t* primary = _collection->primary(); + TRI_doc_operation_context_t context; + + TRI_InitContextPrimaryCollection(&context, primary, policy, forceSync); + context._expectedRid = expectedRevision; + context._previousRid = actualRevision; + _synchronous = context._sync; + + CollectionWriteLock lock(_collection); + + return primary->updateJson(&context, mptr, json, (TRI_voc_key_t) key.c_str()); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief delete a single document within a transaction +//////////////////////////////////////////////////////////////////////////////// + + int destroy (const string& key, + const TRI_doc_update_policy_e policy, + bool forceSync, + const TRI_voc_rid_t expectedRevision, + TRI_voc_rid_t* actualRevision) { + if (_numWrites++ > M) { + return TRI_ERROR_TRANSACTION_INTERNAL; + } + + TRI_primary_collection_t* primary = _collection->primary(); + TRI_doc_operation_context_t context; + + TRI_InitContextPrimaryCollection(&context, primary, policy, forceSync); + context._expectedRid = expectedRevision; + context._previousRid = actualRevision; + _synchronous = context._sync; + + CollectionWriteLock lock(_collection); + + return primary->destroy(&context, (TRI_voc_key_t) key.c_str()); + } + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup ArangoDB +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief number of writes the transaction has executed +/// the value should be 0 or 1, but not get any higher because values higher +/// than one indicate internal errors +//////////////////////////////////////////////////////////////////////////////// + + uint64_t _numWrites; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief whether of not the last write action was executed synchronously +//////////////////////////////////////////////////////////////////////////////// + + bool _synchronous; + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + + }; + + } +} + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/arangod/Utils/Transaction.h b/arangod/Utils/Transaction.h index 83cc0b2ac4..5086ff7c91 100644 --- a/arangod/Utils/Transaction.h +++ b/arangod/Utils/Transaction.h @@ -71,8 +71,10 @@ namespace triagens { /// @brief create the transaction //////////////////////////////////////////////////////////////////////////////// - Transaction (const TRI_vocbase_t* const vocbase) : - _vocbase(vocbase), _trx(0) { + Transaction (const TRI_vocbase_t* const vocbase, const string& name) : + _vocbase(vocbase), + _name(name), + _trx(0) { assert(_vocbase != 0); } @@ -101,6 +103,14 @@ namespace triagens { public: +//////////////////////////////////////////////////////////////////////////////// +/// @brief return the name of the transaction +//////////////////////////////////////////////////////////////////////////////// + + inline string name () const { + return _name; + } + //////////////////////////////////////////////////////////////////////////////// /// @brief get the status of the transaction //////////////////////////////////////////////////////////////////////////////// @@ -183,6 +193,12 @@ namespace triagens { const TRI_vocbase_t* const _vocbase; +//////////////////////////////////////////////////////////////////////////////// +/// @brief transaction name +//////////////////////////////////////////////////////////////////////////////// + + string _name; + //////////////////////////////////////////////////////////////////////////////// /// @brief the actual transaction //////////////////////////////////////////////////////////////////////////////// diff --git a/js/common/bootstrap/errors.js b/js/common/bootstrap/errors.js index 4a727a1a0d..77df2914ca 100644 --- a/js/common/bootstrap/errors.js +++ b/js/common/bootstrap/errors.js @@ -103,6 +103,7 @@ "ERROR_TRANSACTION_INCOMPLETE" : { "code" : 1650, "message" : "transaction definition is incomplete" }, "ERROR_TRANSACTION_INVALID_STATE" : { "code" : 1651, "message" : "invalid transaction state" }, "ERROR_TRANSACTION_NESTED" : { "code" : 1652, "message" : "nested write transaction detected" }, + "ERROR_TRANSACTION_INTERNAL" : { "code" : 1653, "message" : "internal transaction error" }, "ERROR_KEYVALUE_INVALID_KEY" : { "code" : 1800, "message" : "invalid key declaration" }, "ERROR_KEYVALUE_KEY_EXISTS" : { "code" : 1801, "message" : "key already exists" }, "ERROR_KEYVALUE_KEY_NOT_FOUND" : { "code" : 1802, "message" : "key not found" }, diff --git a/lib/BasicsC/errors.dat b/lib/BasicsC/errors.dat index c77e21953a..2680f1dd89 100755 --- a/lib/BasicsC/errors.dat +++ b/lib/BasicsC/errors.dat @@ -143,6 +143,7 @@ ERROR_CURSOR_NOT_FOUND,1600,"cursor not found","Will be raised when a cursor is ERROR_TRANSACTION_INCOMPLETE,1650,"transaction definition is incomplete","Will be raised when the transaction definition is incomplete (e.g. lacks collections to use)." ERROR_TRANSACTION_INVALID_STATE,1651,"invalid transaction state","Will be raised when an operation is requested on a transaction that has an incompatible state." ERROR_TRANSACTION_NESTED,1652,"nested write transaction detected","Will be raised when write transactions are nested." +ERROR_TRANSACTION_INTERNAL,1653,"internal transaction error","Will be raised when a wrong usage of transactions is detected. this is an internal error and indicates a bug in ArangoDB." ################################################################################ ## Key value access diff --git a/lib/BasicsC/voc-errors.c b/lib/BasicsC/voc-errors.c index c3f91d6621..228ac90917 100644 --- a/lib/BasicsC/voc-errors.c +++ b/lib/BasicsC/voc-errors.c @@ -99,6 +99,7 @@ void TRI_InitialiseErrorMessages (void) { REG_ERROR(ERROR_TRANSACTION_INCOMPLETE, "transaction definition is incomplete"); REG_ERROR(ERROR_TRANSACTION_INVALID_STATE, "invalid transaction state"); REG_ERROR(ERROR_TRANSACTION_NESTED, "nested write transaction detected"); + REG_ERROR(ERROR_TRANSACTION_INTERNAL, "internal transaction error"); REG_ERROR(ERROR_KEYVALUE_INVALID_KEY, "invalid key declaration"); REG_ERROR(ERROR_KEYVALUE_KEY_EXISTS, "key already exists"); REG_ERROR(ERROR_KEYVALUE_KEY_NOT_FOUND, "key not found"); diff --git a/lib/BasicsC/voc-errors.h b/lib/BasicsC/voc-errors.h index c8379d63e6..b50eece70a 100644 --- a/lib/BasicsC/voc-errors.h +++ b/lib/BasicsC/voc-errors.h @@ -216,6 +216,9 @@ extern "C" { /// an incompatible state. /// - 1652: @CODE{nested write transaction detected} /// Will be raised when write transactions are nested. +/// - 1653: @CODE{internal transaction error} +/// Will be raised when a wrong usage of transactions is detected. this is an +/// internal error and indicates a bug in ArangoDB. /// - 1800: @CODE{invalid key declaration} /// Will be raised when an invalid key specification is passed to the server /// - 1801: @CODE{key already exists} @@ -1236,6 +1239,17 @@ void TRI_InitialiseErrorMessages (void); #define TRI_ERROR_TRANSACTION_NESTED (1652) +//////////////////////////////////////////////////////////////////////////////// +/// @brief 1653: ERROR_TRANSACTION_INTERNAL +/// +/// internal transaction error +/// +/// Will be raised when a wrong usage of transactions is detected. this is an +/// internal error and indicates a bug in ArangoDB. +//////////////////////////////////////////////////////////////////////////////// + +#define TRI_ERROR_TRANSACTION_INTERNAL (1653) + //////////////////////////////////////////////////////////////////////////////// /// @brief 1800: ERROR_KEYVALUE_INVALID_KEY ///