From ae751e73604c9d49245cdc3636ea8c9c7e13460f Mon Sep 17 00:00:00 2001 From: jsteemann Date: Mon, 27 Feb 2017 17:05:30 +0100 Subject: [PATCH] create engine-specific transaction context data --- arangod/CMakeLists.txt | 1 + arangod/MMFiles/MMFilesEngine.cpp | 15 ++-- arangod/MMFiles/MMFilesEngine.h | 5 ++ .../MMFiles/MMFilesTransactionContextData.cpp | 75 +++++++++++++++++++ .../MMFiles/MMFilesTransactionContextData.h | 53 +++++++++++++ arangod/MMFiles/MMFilesTransactionState.h | 1 - arangod/StorageEngine/StorageEngine.h | 5 ++ arangod/Transaction/Context.cpp | 51 ++++--------- arangod/Transaction/Context.h | 10 ++- arangod/Transaction/ContextData.h | 59 +++++++++++++++ 10 files changed, 228 insertions(+), 47 deletions(-) create mode 100644 arangod/MMFiles/MMFilesTransactionContextData.cpp create mode 100644 arangod/MMFiles/MMFilesTransactionContextData.h create mode 100644 arangod/Transaction/ContextData.h diff --git a/arangod/CMakeLists.txt b/arangod/CMakeLists.txt index b78ff98547..c85f77f4eb 100644 --- a/arangod/CMakeLists.txt +++ b/arangod/CMakeLists.txt @@ -250,6 +250,7 @@ SET(ARANGOD_SOURCES MMFiles/MMFilesSkiplistIndex.cpp MMFiles/MMFilesSynchronizerThread.cpp MMFiles/MMFilesTransactionCollection.cpp + MMFiles/MMFilesTransactionContextData.cpp MMFiles/MMFilesTransactionState.cpp MMFiles/MMFilesWalLogfile.cpp MMFiles/MMFilesWalRecoverState.cpp diff --git a/arangod/MMFiles/MMFilesEngine.cpp b/arangod/MMFiles/MMFilesEngine.cpp index 50108c2b8b..0cc0803a2a 100644 --- a/arangod/MMFiles/MMFilesEngine.cpp +++ b/arangod/MMFiles/MMFilesEngine.cpp @@ -31,10 +31,6 @@ #include "Basics/WriteLocker.h" #include "Basics/encoding.h" #include "Basics/files.h" -#include "Random/RandomGenerator.h" -#include "RestServer/DatabaseFeature.h" -#include "RestServer/DatabasePathFeature.h" -#include "StorageEngine/EngineSelectorFeature.h" #include "MMFiles/MMFilesAqlFunctions.h" #include "MMFiles/MMFilesCleanupThread.h" #include "MMFiles/MMFilesCompactorThread.h" @@ -45,7 +41,12 @@ #include "MMFiles/MMFilesPersistentIndex.h" #include "MMFiles/MMFilesPersistentIndexFeature.h" #include "MMFiles/MMFilesTransactionCollection.h" +#include "MMFiles/MMFilesTransactionContextData.h" #include "MMFiles/MMFilesTransactionState.h" +#include "Random/RandomGenerator.h" +#include "RestServer/DatabaseFeature.h" +#include "RestServer/DatabasePathFeature.h" +#include "StorageEngine/EngineSelectorFeature.h" #include "VocBase/LogicalCollection.h" #include "VocBase/ticks.h" #include "VocBase/vocbase.h" @@ -223,7 +224,11 @@ void MMFilesEngine::stop() { logfileManager->flush(true, true, false); logfileManager->waitForCollector(); } - + +transaction::ContextData* MMFilesEngine::createTransactionContextData() { + return new MMFilesTransactionContextData; +} + TransactionState* MMFilesEngine::createTransactionState(TRI_vocbase_t* vocbase) { return new MMFilesTransactionState(vocbase); } diff --git a/arangod/MMFiles/MMFilesEngine.h b/arangod/MMFiles/MMFilesEngine.h index 1db00601ce..c48ca93434 100644 --- a/arangod/MMFiles/MMFilesEngine.h +++ b/arangod/MMFiles/MMFilesEngine.h @@ -40,6 +40,10 @@ class MMFilesCompactorThread; class TransactionCollection; class TransactionState; +namespace transaction { +class ContextData; +} + /// @brief collection file structure struct MMFilesEngineCollectionFiles { std::vector journals; @@ -75,6 +79,7 @@ class MMFilesEngine final : public StorageEngine { // flush wal wait for collector void stop() override; + transaction::ContextData* createTransactionContextData() override; TransactionState* createTransactionState(TRI_vocbase_t*) override; TransactionCollection* createTransactionCollection(TransactionState* state, TRI_voc_cid_t cid, AccessMode::Type accessType, int nestingLevel) override; diff --git a/arangod/MMFiles/MMFilesTransactionContextData.cpp b/arangod/MMFiles/MMFilesTransactionContextData.cpp new file mode 100644 index 0000000000..ea52507a72 --- /dev/null +++ b/arangod/MMFiles/MMFilesTransactionContextData.cpp @@ -0,0 +1,75 @@ +//////////////////////////////////////////////////////////////////////////////// +/// DISCLAIMER +/// +/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany +/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Jan Steemann +//////////////////////////////////////////////////////////////////////////////// + +#include "MMFilesTransactionContextData.h" +#include "MMFiles/MMFilesCollection.h" +#include "MMFiles/MMFilesDitch.h" +#include "VocBase/LogicalCollection.h" + +using namespace arangodb; + +MMFilesTransactionContextData::MMFilesTransactionContextData() {} + +MMFilesTransactionContextData::~MMFilesTransactionContextData() { + for (auto& it : _ditches) { + // we're done with this ditch + auto& ditch = it.second; + ditch->ditches()->freeMMFilesDocumentDitch(ditch, true /* fromTransaction */); + // If some external entity is still using the ditch, it is kept! + } +} + +/// @brief pin data for the collection +void MMFilesTransactionContextData::pinData(LogicalCollection* collection) { + TRI_voc_cid_t cid = collection->cid(); + + auto it = _ditches.find(cid); + + if (it != _ditches.end()) { + // tell everyone else this ditch is still in use, + // at least until the transaction is over + TRI_ASSERT((*it).second->usedByTransaction()); + // ditch already exists + return; + } + + // this method will not throw, but may return a nullptr + auto ditch = arangodb::MMFilesCollection::toMMFilesCollection(collection)->ditches()->createMMFilesDocumentDitch(true, __FILE__, __LINE__); + + if (ditch == nullptr) { + THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); + } + + try { + _ditches.emplace(cid, ditch); + } + catch (...) { + ditch->ditches()->freeMMFilesDocumentDitch(ditch, true); + throw; + } +} + +/// @brief whether or not the data for the collection is pinned +bool MMFilesTransactionContextData::isPinned(TRI_voc_cid_t cid) const { + return (_ditches.find(cid) != _ditches.end()); +} diff --git a/arangod/MMFiles/MMFilesTransactionContextData.h b/arangod/MMFiles/MMFilesTransactionContextData.h new file mode 100644 index 0000000000..1ecf840e47 --- /dev/null +++ b/arangod/MMFiles/MMFilesTransactionContextData.h @@ -0,0 +1,53 @@ +//////////////////////////////////////////////////////////////////////////////// +/// DISCLAIMER +/// +/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany +/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Jan Steemann +//////////////////////////////////////////////////////////////////////////////// + +#ifndef ARANGOD_MMFILES_TRANSACTION_CONTEXT_DATA_H +#define ARANGOD_MMFILES_TRANSACTION_CONTEXT_DATA_H 1 + +#include "Basics/Common.h" +#include "Transaction/ContextData.h" +#include "VocBase/voc-types.h" + +namespace arangodb { +class LogicalCollection; +class MMFilesDocumentDitch; + +/// @brief transaction type +class MMFilesTransactionContextData final : public transaction::ContextData { + public: + MMFilesTransactionContextData(); + ~MMFilesTransactionContextData(); + + /// @brief pin data for the collection + void pinData(arangodb::LogicalCollection*) override; + + /// @brief whether or not the data for the collection is pinned + bool isPinned(TRI_voc_cid_t) const override; + + private: + std::unordered_map _ditches; +}; + +} + +#endif diff --git a/arangod/MMFiles/MMFilesTransactionState.h b/arangod/MMFiles/MMFilesTransactionState.h index 764658aff0..3770e12773 100644 --- a/arangod/MMFiles/MMFilesTransactionState.h +++ b/arangod/MMFiles/MMFilesTransactionState.h @@ -45,7 +45,6 @@ class MMFilesWalMarker; namespace transaction { class Methods; } -; class TransactionCollection; /// @brief transaction type diff --git a/arangod/StorageEngine/StorageEngine.h b/arangod/StorageEngine/StorageEngine.h index 6a7a9fca3e..c5e072eb64 100644 --- a/arangod/StorageEngine/StorageEngine.h +++ b/arangod/StorageEngine/StorageEngine.h @@ -45,6 +45,10 @@ class PhysicalCollection; class TransactionCollection; class TransactionState; +namespace transaction { +class ContextData; +} + class StorageEngine : public application_features::ApplicationFeature { public: @@ -71,6 +75,7 @@ class StorageEngine : public application_features::ApplicationFeature { virtual void start() {} virtual void stop() {} + virtual transaction::ContextData* createTransactionContextData() = 0; virtual TransactionState* createTransactionState(TRI_vocbase_t*) = 0; virtual TransactionCollection* createTransactionCollection(TransactionState*, TRI_voc_cid_t, AccessMode::Type, int nestingLevel) = 0; diff --git a/arangod/Transaction/Context.cpp b/arangod/Transaction/Context.cpp index 3a3576c708..42765d68a1 100644 --- a/arangod/Transaction/Context.cpp +++ b/arangod/Transaction/Context.cpp @@ -27,6 +27,9 @@ #include "MMFiles/MMFilesCollection.h" #include "MMFiles/MMFilesDitch.h" #include "RestServer/TransactionManagerFeature.h" +#include "StorageEngine/EngineSelectorFeature.h" +#include "StorageEngine/StorageEngine.h" +#include "Transaction/ContextData.h" #include "Transaction/Helpers.h" #include "Transaction/Methods.h" #include "Utils/CollectionNameResolver.h" @@ -68,7 +71,6 @@ transaction::Context::Context(TRI_vocbase_t* vocbase) : _vocbase(vocbase), _resolver(nullptr), _customTypeHandler(), - _ditches(), _builders{_arena}, _stringBuffer(), _options(arangodb::velocypack::Options::Defaults), @@ -85,13 +87,6 @@ transaction::Context::~Context() { TransactionManagerFeature::MANAGER->unregisterTransaction(_transaction.id, _transaction.hasFailedOperations); } - for (auto& it : _ditches) { - // we're done with this ditch - auto& ditch = it.second; - ditch->ditches()->freeMMFilesDocumentDitch(ditch, true /* fromTransaction */); - // If some external entity is still using the ditch, it is kept! - } - // free all VPackBuilders we handed out for (auto& it : _builders) { delete it; @@ -111,37 +106,12 @@ VPackCustomTypeHandler* transaction::Context::createCustomTypeHandler(TRI_vocbas /// @brief pin data for the collection void transaction::Context::pinData(LogicalCollection* collection) { - TRI_voc_cid_t cid = collection->cid(); - - auto it = _ditches.find(cid); - - if (it != _ditches.end()) { - // tell everyone else this ditch is still in use, - // at least until the transaction is over - TRI_ASSERT((*it).second->usedByTransaction()); - // ditch already exists - return; - } - - // this method will not throw, but may return a nullptr - auto ditch = arangodb::MMFilesCollection::toMMFilesCollection(collection)->ditches()->createMMFilesDocumentDitch(true, __FILE__, __LINE__); - - if (ditch == nullptr) { - THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); - } - - try { - _ditches.emplace(cid, ditch); - } - catch (...) { - ditch->ditches()->freeMMFilesDocumentDitch(ditch, true); - throw; - } + contextData()->pinData(collection); } /// @brief whether or not the data for the collection is pinned -bool transaction::Context::isPinned(TRI_voc_cid_t cid) const { - return (_ditches.find(cid) != _ditches.end()); +bool transaction::Context::isPinned(TRI_voc_cid_t cid) { + return contextData()->isPinned(cid); } /// @brief temporarily lease a StringBuffer object @@ -220,4 +190,11 @@ void transaction::Context::storeTransactionResult(TRI_voc_tid_t id, bool hasFail _transaction.id = id; _transaction.hasFailedOperations = hasFailedOperations; } - + +transaction::ContextData* transaction::Context::contextData() { + if (_contextData == nullptr) { + StorageEngine* engine = EngineSelectorFeature::ENGINE; + _contextData.reset(engine->createTransactionContextData()); + } + return _contextData.get(); +} diff --git a/arangod/Transaction/Context.h b/arangod/Transaction/Context.h index 94c7207208..58695a7df6 100644 --- a/arangod/Transaction/Context.h +++ b/arangod/Transaction/Context.h @@ -43,11 +43,11 @@ struct CustomTypeHandler; } class CollectionNameResolver; -class MMFilesDocumentDitch; class LogicalCollection; class TransactionState; namespace transaction { +class ContextData; class Methods; class Context { @@ -77,7 +77,7 @@ class Context { void pinData(arangodb::LogicalCollection*); /// @brief whether or not the data for the collection is pinned - bool isPinned(TRI_voc_cid_t) const; + bool isPinned(TRI_voc_cid_t); /// @brief temporarily lease a StringBuffer object basics::StringBuffer* leaseStringBuffer(size_t initialSize); @@ -124,6 +124,8 @@ class Context { /// @brief create a resolver CollectionNameResolver const* createResolver(); + + transaction::ContextData* contextData(); protected: @@ -133,8 +135,6 @@ class Context { std::shared_ptr _customTypeHandler; - std::unordered_map _ditches; - SmallVector::allocator_type::arena_type _arena; SmallVector _builders; @@ -142,6 +142,8 @@ class Context { arangodb::velocypack::Options _options; arangodb::velocypack::Options _dumpOptions; + + std::unique_ptr _contextData; struct { TRI_voc_tid_t id; diff --git a/arangod/Transaction/ContextData.h b/arangod/Transaction/ContextData.h new file mode 100644 index 0000000000..2c9e54726b --- /dev/null +++ b/arangod/Transaction/ContextData.h @@ -0,0 +1,59 @@ +//////////////////////////////////////////////////////////////////////////////// +/// DISCLAIMER +/// +/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany +/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is ArangoDB GmbH, Cologne, Germany +/// +/// @author Jan Steemann +//////////////////////////////////////////////////////////////////////////////// + +#ifndef ARANGOD_TRANSACTION_CONTEXT_DATA_H +#define ARANGOD_TRANSACTION_CONTEXT_DATA_H 1 + +#include "Basics/Common.h" +#include "VocBase/voc-types.h" + +namespace arangodb { +class LogicalCollection; + +namespace transaction { +class ContextData { + public: + ContextData(ContextData const&) = delete; + ContextData& operator=(ContextData const&) = delete; + + protected: + + /// @brief create the context data + ContextData() = default; + + public: + + /// @brief destroy the context data + virtual ~ContextData() = default; + + /// @brief pin data for the collection + virtual void pinData(arangodb::LogicalCollection*) = 0; + + /// @brief whether or not the data for the collection is pinned + virtual bool isPinned(TRI_voc_cid_t) const = 0; +}; + +} +} + +#endif