mirror of https://gitee.com/bigwinds/arangodb
Refactorings from cluster trx improvement branch (#8391)
This commit is contained in:
parent
8d649903f7
commit
49cc3bcd1e
|
@ -855,7 +855,7 @@ arangodb::Result MoveShard::abort() {
|
|||
// Current preconditions for all shards
|
||||
doForAllShards(
|
||||
_snapshot, _database, shardsLikeMe,
|
||||
[this, &trx](
|
||||
[&trx](
|
||||
Slice plan, Slice current, std::string& planPath, std::string& curPath) {
|
||||
// Current still as is
|
||||
trx.add(curPath, current);
|
||||
|
|
|
@ -695,9 +695,9 @@ bool Supervision::updateSnapshot() {
|
|||
// All checks, guarded by main thread
|
||||
bool Supervision::doChecks() {
|
||||
_lock.assertLockedByCurrentThread();
|
||||
TRI_ASSERT(ServerState::roleToAgencyListKey(ServerState::ROLE_PRIMARY) ==
|
||||
TRI_ASSERT(ServerState::roleToAgencyListKey(ServerState::ROLE_DBSERVER) ==
|
||||
"DBServers");
|
||||
check(ServerState::roleToAgencyListKey(ServerState::ROLE_PRIMARY));
|
||||
check(ServerState::roleToAgencyListKey(ServerState::ROLE_DBSERVER));
|
||||
TRI_ASSERT(ServerState::roleToAgencyListKey(ServerState::ROLE_COORDINATOR) ==
|
||||
"Coordinators");
|
||||
check(ServerState::roleToAgencyListKey(ServerState::ROLE_COORDINATOR));
|
||||
|
|
|
@ -157,7 +157,7 @@ ExecutionEngineResult EngineInfoContainerCoordinator::buildEngines(
|
|||
Query* localQuery = query;
|
||||
try {
|
||||
bool first = true;
|
||||
for (auto const& info : _engines) {
|
||||
for (EngineInfo const& info : _engines) {
|
||||
if (!first) {
|
||||
// need a new query instance on the coordinator
|
||||
localQuery = query->clone(PART_DEPENDENT, false);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "Graph/BaseOptions.h"
|
||||
#include "RestServer/QueryRegistryFeature.h"
|
||||
#include "StorageEngine/TransactionState.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "VocBase/LogicalCollection.h"
|
||||
#include "VocBase/ticks.h"
|
||||
#ifdef USE_IRESEARCH
|
||||
|
|
|
@ -1466,6 +1466,7 @@ AqlValue Functions::LevenshteinDistance(ExpressionContext*, transaction::Methods
|
|||
AqlValue const& value1 = extractFunctionParameterValue(parameters, 0);
|
||||
AqlValue const& value2 = extractFunctionParameterValue(parameters, 1);
|
||||
|
||||
// FIXME: there is only one shared stringbuffer instance
|
||||
transaction::StringBufferLeaser buffer1(trx);
|
||||
transaction::StringBufferLeaser buffer2(trx);
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/StorageEngine.h"
|
||||
#include "Transaction/Methods.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "VocBase/Methods/Collections.h"
|
||||
|
||||
#ifdef USE_IRESEARCH
|
||||
|
|
|
@ -358,6 +358,7 @@ void Query::prepare(QueryRegistry* registry) {
|
|||
// create the transaction object, but do not start it yet
|
||||
_trx = AqlTransaction::create(createTransactionContext(), _collections.collections(),
|
||||
_queryOptions.transactionOptions, _part == PART_MAIN);
|
||||
_trx->addHint(transaction::Hints::Hint::FROM_TOPLEVEL_AQL); // only used on toplevel
|
||||
|
||||
VPackBuilder* builder = planCacheEntry->builder.get();
|
||||
VPackSlice slice = builder->slice();
|
||||
|
@ -368,10 +369,6 @@ void Query::prepare(QueryRegistry* registry) {
|
|||
|
||||
int res = trx->addCollections(*_collections.collections());
|
||||
|
||||
if (!trx->transactionContextPtr()->getParentTransaction()) {
|
||||
trx->addHint(transaction::Hints::Hint::FROM_TOPLEVEL_AQL);
|
||||
}
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
res = _trx->begin();
|
||||
}
|
||||
|
@ -470,10 +467,7 @@ ExecutionPlan* Query::preparePlan() {
|
|||
TRI_DEFER(trx.release());
|
||||
// create the transaction object, but do not start it yet
|
||||
_trx = trx.get();
|
||||
|
||||
if (!trx->transactionContextPtr()->getParentTransaction()) {
|
||||
trx->addHint(transaction::Hints::Hint::FROM_TOPLEVEL_AQL);
|
||||
}
|
||||
_trx->addHint(transaction::Hints::Hint::FROM_TOPLEVEL_AQL); // only used on toplevel
|
||||
|
||||
// As soon as we start to instantiate the plan we have to clean it
|
||||
// up before killing the unique_ptr
|
||||
|
|
|
@ -494,7 +494,6 @@ SET(ARANGOD_SOURCES
|
|||
RestServer/ServerFeature.cpp
|
||||
RestServer/ServerIdFeature.cpp
|
||||
RestServer/SystemDatabaseFeature.cpp
|
||||
RestServer/TransactionManagerFeature.cpp
|
||||
RestServer/TraverserEngineRegistryFeature.cpp
|
||||
RestServer/TtlFeature.cpp
|
||||
RestServer/UpgradeFeature.cpp
|
||||
|
@ -527,6 +526,8 @@ SET(ARANGOD_SOURCES
|
|||
Transaction/SmartContext.cpp
|
||||
Transaction/StandaloneContext.cpp
|
||||
Transaction/Status.cpp
|
||||
Transaction/Manager.cpp
|
||||
Transaction/ManagerFeature.cpp
|
||||
Transaction/V8Context.cpp
|
||||
Utils/CollectionKeys.cpp
|
||||
Utils/CollectionKeysRepository.cpp
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
/// @author Max Neunhoeffer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ClusterMethods.h"
|
||||
|
||||
#include "Basics/NumberUtils.h"
|
||||
#include "Basics/StaticStrings.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
|
@ -29,7 +31,6 @@
|
|||
#include "Basics/tri-strings.h"
|
||||
#include "Cluster/ClusterComm.h"
|
||||
#include "Cluster/ClusterInfo.h"
|
||||
#include "ClusterMethods.h"
|
||||
#include "Graph/Traverser.h"
|
||||
#include "Indexes/Index.h"
|
||||
#include "RestServer/TtlFeature.h"
|
||||
|
@ -50,6 +51,7 @@
|
|||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
using namespace arangodb;
|
||||
using namespace arangodb::basics;
|
||||
using namespace arangodb::rest;
|
||||
|
||||
|
@ -174,32 +176,6 @@ static std::unique_ptr<std::unordered_map<std::string, std::string>> CreateNoLoc
|
|||
|
||||
namespace arangodb {
|
||||
|
||||
static int handleGeneralCommErrors(ClusterCommResult const* res) {
|
||||
// This function creates an error code from a ClusterCommResult,
|
||||
// but only if it is a communication error. If the communication
|
||||
// was successful and there was an HTTP error code, this function
|
||||
// returns TRI_ERROR_NO_ERROR.
|
||||
// If TRI_ERROR_NO_ERROR is returned, then the result was CL_COMM_RECEIVED
|
||||
// and .answer can safely be inspected.
|
||||
if (res->status == CL_COMM_TIMEOUT) {
|
||||
// No reply, we give up:
|
||||
return TRI_ERROR_CLUSTER_TIMEOUT;
|
||||
} else if (res->status == CL_COMM_ERROR) {
|
||||
return TRI_ERROR_CLUSTER_CONNECTION_LOST;
|
||||
} else if (res->status == CL_COMM_BACKEND_UNAVAILABLE) {
|
||||
if (res->result == nullptr) {
|
||||
return TRI_ERROR_CLUSTER_CONNECTION_LOST;
|
||||
}
|
||||
if (!res->result->isComplete()) {
|
||||
// there is no result
|
||||
return TRI_ERROR_CLUSTER_CONNECTION_LOST;
|
||||
}
|
||||
return TRI_ERROR_CLUSTER_BACKEND_UNAVAILABLE;
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extracts a numeric value from an hierarchical VelocyPack
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -636,6 +612,33 @@ static std::shared_ptr<std::unordered_map<std::string, std::vector<std::string>>
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @brief convert ClusterComm error into arango error code
|
||||
int handleGeneralCommErrors(arangodb::ClusterCommResult const* res) {
|
||||
// This function creates an error code from a ClusterCommResult,
|
||||
// but only if it is a communication error. If the communication
|
||||
// was successful and there was an HTTP error code, this function
|
||||
// returns TRI_ERROR_NO_ERROR.
|
||||
// If TRI_ERROR_NO_ERROR is returned, then the result was CL_COMM_RECEIVED
|
||||
// and .answer can safely be inspected.
|
||||
if (res->status == CL_COMM_TIMEOUT) {
|
||||
// No reply, we give up:
|
||||
return TRI_ERROR_CLUSTER_TIMEOUT;
|
||||
} else if (res->status == CL_COMM_ERROR) {
|
||||
return TRI_ERROR_CLUSTER_CONNECTION_LOST;
|
||||
} else if (res->status == CL_COMM_BACKEND_UNAVAILABLE) {
|
||||
if (res->result == nullptr) {
|
||||
return TRI_ERROR_CLUSTER_CONNECTION_LOST;
|
||||
}
|
||||
if (!res->result->isComplete()) {
|
||||
// there is no result
|
||||
return TRI_ERROR_CLUSTER_CONNECTION_LOST;
|
||||
}
|
||||
return TRI_ERROR_CLUSTER_BACKEND_UNAVAILABLE;
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a copy of all HTTP headers to forward
|
||||
|
@ -742,7 +745,7 @@ int revisionOnCoordinator(std::string const& dbname,
|
|||
|
||||
// If we get here, the sharding attributes are not only _key, therefore
|
||||
// we have to contact everybody:
|
||||
auto shards = collinfo->shardIds();
|
||||
std::shared_ptr<ShardMap> shards = collinfo->shardIds();
|
||||
CoordTransactionID coordTransactionID = TRI_NewTickServer();
|
||||
|
||||
std::unordered_map<std::string, std::string> headers;
|
||||
|
@ -810,7 +813,7 @@ int warmupOnCoordinator(std::string const& dbname, std::string const& cid) {
|
|||
|
||||
// If we get here, the sharding attributes are not only _key, therefore
|
||||
// we have to contact everybody:
|
||||
auto shards = collinfo->shardIds();
|
||||
std::shared_ptr<ShardMap> shards = collinfo->shardIds();
|
||||
CoordTransactionID coordTransactionID = TRI_NewTickServer();
|
||||
|
||||
std::unordered_map<std::string, std::string> headers;
|
||||
|
@ -855,7 +858,7 @@ int figuresOnCoordinator(std::string const& dbname, std::string const& collname,
|
|||
|
||||
// If we get here, the sharding attributes are not only _key, therefore
|
||||
// we have to contact everybody:
|
||||
auto shards = collinfo->shardIds();
|
||||
std::shared_ptr<ShardMap> shards = collinfo->shardIds();
|
||||
CoordTransactionID coordTransactionID = TRI_NewTickServer();
|
||||
|
||||
std::unordered_map<std::string, std::string> headers;
|
||||
|
@ -902,8 +905,7 @@ int figuresOnCoordinator(std::string const& dbname, std::string const& collname,
|
|||
/// @brief counts number of documents in a coordinator, by shard
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int countOnCoordinator(std::string const& dbname, std::string const& cname,
|
||||
transaction::Methods const& trx,
|
||||
int countOnCoordinator(transaction::Methods& trx, std::string const& cname,
|
||||
std::vector<std::pair<std::string, uint64_t>>& result) {
|
||||
// Set a few variables needed for our work:
|
||||
ClusterInfo* ci = ClusterInfo::instance();
|
||||
|
@ -915,17 +917,18 @@ int countOnCoordinator(std::string const& dbname, std::string const& cname,
|
|||
|
||||
result.clear();
|
||||
|
||||
std::string const& dbname = trx.vocbase().name();
|
||||
// First determine the collection ID from the name:
|
||||
std::shared_ptr<LogicalCollection> collinfo;
|
||||
collinfo = ci->getCollectionNT(dbname, cname);
|
||||
if (collinfo == nullptr) {
|
||||
return TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND;
|
||||
}
|
||||
|
||||
auto shards = collinfo->shardIds();
|
||||
|
||||
std::shared_ptr<ShardMap> shards = collinfo->shardIds();
|
||||
std::vector<ClusterCommRequest> requests;
|
||||
auto body = std::make_shared<std::string>();
|
||||
for (auto const& p : *shards) {
|
||||
for (std::pair<ShardID, std::vector<ServerID>> const& p : *shards) {
|
||||
requests.emplace_back("shard:" + p.first, arangodb::rest::RequestType::GET,
|
||||
"/_db/" + StringUtils::urlEncode(dbname) +
|
||||
"/_api/collection/" +
|
||||
|
@ -983,7 +986,7 @@ int selectivityEstimatesOnCoordinator(std::string const& dbname, std::string con
|
|||
return TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND;
|
||||
}
|
||||
|
||||
auto shards = collinfo->shardIds();
|
||||
std::shared_ptr<ShardMap> shards = collinfo->shardIds();
|
||||
std::vector<ClusterCommRequest> requests;
|
||||
std::string requestsUrl;
|
||||
auto body = std::make_shared<std::string>();
|
||||
|
@ -1082,8 +1085,7 @@ int selectivityEstimatesOnCoordinator(std::string const& dbname, std::string con
|
|||
/// for their documents.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Result createDocumentOnCoordinator(std::string const& dbname, std::string const& collname,
|
||||
transaction::Methods const& trx,
|
||||
Result createDocumentOnCoordinator(transaction::Methods& trx, std::string const& collname,
|
||||
arangodb::OperationOptions const& options,
|
||||
VPackSlice const& slice,
|
||||
arangodb::rest::ResponseCode& responseCode,
|
||||
|
@ -1098,6 +1100,7 @@ Result createDocumentOnCoordinator(std::string const& dbname, std::string const&
|
|||
ClusterInfo* ci = ClusterInfo::instance();
|
||||
TRI_ASSERT(ci != nullptr);
|
||||
|
||||
std::string const& dbname = trx.vocbase().name();
|
||||
// First determine the collection ID from the name:
|
||||
std::shared_ptr<LogicalCollection> collinfo;
|
||||
collinfo = ci->getCollectionNT(dbname, collname);
|
||||
|
@ -1105,6 +1108,7 @@ Result createDocumentOnCoordinator(std::string const& dbname, std::string const&
|
|||
return TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND;
|
||||
}
|
||||
auto collid = std::to_string(collinfo->id());
|
||||
std::shared_ptr<ShardMap> shards = collinfo->shardIds();
|
||||
|
||||
// create vars used in this function
|
||||
bool const useMultiple = slice.isArray(); // insert more than one document
|
||||
|
@ -1224,9 +1228,8 @@ Result createDocumentOnCoordinator(std::string const& dbname, std::string const&
|
|||
/// @brief deletes a document in a coordinator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int deleteDocumentOnCoordinator(std::string const& dbname, std::string const& collname,
|
||||
arangodb::transaction::Methods const& trx,
|
||||
VPackSlice const slice,
|
||||
int deleteDocumentOnCoordinator(arangodb::transaction::Methods& trx,
|
||||
std::string const& collname, VPackSlice const slice,
|
||||
arangodb::OperationOptions const& options,
|
||||
arangodb::rest::ResponseCode& responseCode,
|
||||
std::unordered_map<int, size_t>& errorCounter,
|
||||
|
@ -1239,6 +1242,7 @@ int deleteDocumentOnCoordinator(std::string const& dbname, std::string const& co
|
|||
return TRI_ERROR_SHUTTING_DOWN;
|
||||
}
|
||||
|
||||
std::string const& dbname = trx.vocbase().name();
|
||||
// First determine the collection ID from the name:
|
||||
std::shared_ptr<LogicalCollection> collinfo;
|
||||
collinfo = ci->getCollectionNT(dbname, collname);
|
||||
|
@ -1247,6 +1251,7 @@ int deleteDocumentOnCoordinator(std::string const& dbname, std::string const& co
|
|||
}
|
||||
bool useDefaultSharding = collinfo->usesDefaultShardKeys();
|
||||
auto collid = std::to_string(collinfo->id());
|
||||
std::shared_ptr<ShardMap> shards = collinfo->shardIds();
|
||||
bool useMultiple = slice.isArray();
|
||||
|
||||
std::string const baseUrl =
|
||||
|
@ -1458,7 +1463,7 @@ int deleteDocumentOnCoordinator(std::string const& dbname, std::string const& co
|
|||
/// @brief truncate a cluster collection on a coordinator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int truncateCollectionOnCoordinator(std::string const& dbname, std::string const& collname) {
|
||||
Result truncateCollectionOnCoordinator(transaction::Methods& trx, std::string const& collname) {
|
||||
// Set a few variables needed for our work:
|
||||
ClusterInfo* ci = ClusterInfo::instance();
|
||||
auto cc = ClusterComm::instance();
|
||||
|
@ -1467,6 +1472,7 @@ int truncateCollectionOnCoordinator(std::string const& dbname, std::string const
|
|||
return TRI_ERROR_SHUTTING_DOWN;
|
||||
}
|
||||
|
||||
std::string const& dbname = trx.vocbase().name();
|
||||
// First determine the collection ID from the name:
|
||||
std::shared_ptr<LogicalCollection> collinfo;
|
||||
collinfo = ci->getCollectionNT(dbname, collname);
|
||||
|
@ -1476,7 +1482,8 @@ int truncateCollectionOnCoordinator(std::string const& dbname, std::string const
|
|||
|
||||
// Some stuff to prepare cluster-intern requests:
|
||||
// We have to contact everybody:
|
||||
auto shards = collinfo->shardIds();
|
||||
std::shared_ptr<ShardMap> shards = collinfo->shardIds();
|
||||
|
||||
CoordTransactionID coordTransactionID = TRI_NewTickServer();
|
||||
std::unordered_map<std::string, std::string> headers;
|
||||
for (auto const& p : *shards) {
|
||||
|
@ -1494,6 +1501,11 @@ int truncateCollectionOnCoordinator(std::string const& dbname, std::string const
|
|||
if (res.status == CL_COMM_RECEIVED) {
|
||||
if (res.answer_code == arangodb::rest::ResponseCode::OK) {
|
||||
nrok++;
|
||||
} else if (res.answer->payload().isObject()) {
|
||||
VPackSlice answer = res.answer->payload();
|
||||
return Result(VelocyPackHelper::readNumericValue(answer, StaticStrings::ErrorNum,
|
||||
TRI_ERROR_TRANSACTION_INTERNAL),
|
||||
VelocyPackHelper::getStringValue(answer, StaticStrings::ErrorMessage, ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1502,15 +1514,14 @@ int truncateCollectionOnCoordinator(std::string const& dbname, std::string const
|
|||
if (nrok < shards->size()) {
|
||||
return TRI_ERROR_CLUSTER_COULD_NOT_TRUNCATE_COLLECTION;
|
||||
}
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
return Result();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a document in a coordinator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int getDocumentOnCoordinator(std::string const& dbname, std::string const& collname,
|
||||
arangodb::transaction::Methods const& trx,
|
||||
int getDocumentOnCoordinator(arangodb::transaction::Methods& trx, std::string const& collname,
|
||||
VPackSlice slice, OperationOptions const& options,
|
||||
arangodb::rest::ResponseCode& responseCode,
|
||||
std::unordered_map<int, size_t>& errorCounter,
|
||||
|
@ -1523,6 +1534,7 @@ int getDocumentOnCoordinator(std::string const& dbname, std::string const& colln
|
|||
return TRI_ERROR_SHUTTING_DOWN;
|
||||
}
|
||||
|
||||
std::string const& dbname = trx.vocbase().name();
|
||||
// First determine the collection ID from the name:
|
||||
std::shared_ptr<LogicalCollection> collinfo;
|
||||
collinfo = ci->getCollectionNT(dbname, collname);
|
||||
|
@ -1531,6 +1543,7 @@ int getDocumentOnCoordinator(std::string const& dbname, std::string const& colln
|
|||
}
|
||||
|
||||
auto collid = std::to_string(collinfo->id());
|
||||
std::shared_ptr<ShardMap> shards = collinfo->shardIds();
|
||||
|
||||
// If _key is the one and only sharding attribute, we can do this quickly,
|
||||
// because we can easily determine which shard is responsible for the
|
||||
|
@ -2057,9 +2070,8 @@ void fetchVerticesFromEngines(
|
|||
/// @brief get all edges on coordinator using a Traverser Filter
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int getFilteredEdgesOnCoordinator(std::string const& dbname, std::string const& collname,
|
||||
arangodb::transaction::Methods const& trx,
|
||||
std::string const& vertex,
|
||||
int getFilteredEdgesOnCoordinator(arangodb::transaction::Methods const& trx,
|
||||
std::string const& collname, std::string const& vertex,
|
||||
TRI_edge_direction_e const& direction,
|
||||
arangodb::rest::ResponseCode& responseCode,
|
||||
VPackBuilder& result) {
|
||||
|
@ -2073,8 +2085,12 @@ int getFilteredEdgesOnCoordinator(std::string const& dbname, std::string const&
|
|||
return TRI_ERROR_SHUTTING_DOWN;
|
||||
}
|
||||
|
||||
std::string const& dbname = trx.vocbase().name();
|
||||
// First determine the collection ID from the name:
|
||||
std::shared_ptr<LogicalCollection> collinfo = ci->getCollection(dbname, collname);
|
||||
std::shared_ptr<LogicalCollection> collinfo = ci->getCollectionNT(dbname, collname);
|
||||
if (collinfo == nullptr) {
|
||||
return TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND;
|
||||
}
|
||||
|
||||
std::shared_ptr<std::unordered_map<std::string, std::vector<std::string>>> shards;
|
||||
if (collinfo->isSmart() && collinfo->type() == TRI_COL_TYPE_EDGE) {
|
||||
|
@ -2181,8 +2197,7 @@ int getFilteredEdgesOnCoordinator(std::string const& dbname, std::string const&
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int modifyDocumentOnCoordinator(
|
||||
std::string const& dbname, std::string const& collname,
|
||||
arangodb::transaction::Methods const& trx, VPackSlice const& slice,
|
||||
transaction::Methods& trx, std::string const& collname, VPackSlice const& slice,
|
||||
arangodb::OperationOptions const& options, bool isPatch,
|
||||
std::unique_ptr<std::unordered_map<std::string, std::string>>& headers,
|
||||
arangodb::rest::ResponseCode& responseCode, std::unordered_map<int, size_t>& errorCounter,
|
||||
|
@ -2195,9 +2210,11 @@ int modifyDocumentOnCoordinator(
|
|||
return TRI_ERROR_SHUTTING_DOWN;
|
||||
}
|
||||
|
||||
std::string const& dbname = trx.vocbase().name();
|
||||
// First determine the collection ID from the name:
|
||||
std::shared_ptr<LogicalCollection> collinfo = ci->getCollection(dbname, collname);
|
||||
auto collid = std::to_string(collinfo->id());
|
||||
std::shared_ptr<ShardMap> shards = collinfo->shardIds();
|
||||
|
||||
// We have a fast path and a slow path. The fast path only asks one shard
|
||||
// to do the job and the slow path asks them all and expects to get
|
||||
|
@ -2482,7 +2499,7 @@ int flushWalOnAllDBServers(bool waitForSync, bool waitForCollector, double maxWa
|
|||
if (resSlice.isObject()) {
|
||||
int code = arangodb::basics::VelocyPackHelper::getNumericValue<int>(
|
||||
resSlice, "errorNum", TRI_ERROR_INTERNAL);
|
||||
|
||||
|
||||
if (code != TRI_ERROR_NO_ERROR) {
|
||||
globalErrorCode = code;
|
||||
}
|
||||
|
|
|
@ -40,12 +40,16 @@ namespace velocypack {
|
|||
template <typename T>
|
||||
class Buffer;
|
||||
class Builder;
|
||||
class Slice;
|
||||
} // namespace velocypack
|
||||
|
||||
struct ClusterCommResult;
|
||||
struct OperationOptions;
|
||||
class TransactionState;
|
||||
struct TtlStatistics;
|
||||
|
||||
/// @brief convert ClusterComm error into arango error code
|
||||
int handleGeneralCommErrors(arangodb::ClusterCommResult const* res);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a copy of all HTTP headers to forward
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -84,8 +88,7 @@ int figuresOnCoordinator(std::string const& dbname, std::string const& collname,
|
|||
/// @brief counts number of documents in a coordinator, by shard
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int countOnCoordinator(std::string const& dbname, std::string const& collname,
|
||||
transaction::Methods const& trx,
|
||||
int countOnCoordinator(transaction::Methods& trx, std::string const& collname,
|
||||
std::vector<std::pair<std::string, uint64_t>>& result);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -99,8 +102,8 @@ int selectivityEstimatesOnCoordinator(std::string const& dbname, std::string con
|
|||
/// @brief creates a document in a coordinator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Result createDocumentOnCoordinator(std::string const& dbname, std::string const& collname,
|
||||
transaction::Methods const& trx,
|
||||
Result createDocumentOnCoordinator(transaction::Methods& trx,
|
||||
std::string const& collname,
|
||||
OperationOptions const& options,
|
||||
arangodb::velocypack::Slice const& slice,
|
||||
arangodb::rest::ResponseCode& responseCode,
|
||||
|
@ -111,8 +114,7 @@ Result createDocumentOnCoordinator(std::string const& dbname, std::string const&
|
|||
/// @brief delete a document in a coordinator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int deleteDocumentOnCoordinator(std::string const& dbname, std::string const& collname,
|
||||
transaction::Methods const& trx,
|
||||
int deleteDocumentOnCoordinator(transaction::Methods& trx, std::string const& collname,
|
||||
VPackSlice const slice, OperationOptions const& options,
|
||||
arangodb::rest::ResponseCode& responseCode,
|
||||
std::unordered_map<int, size_t>& errorCounters,
|
||||
|
@ -122,9 +124,8 @@ int deleteDocumentOnCoordinator(std::string const& dbname, std::string const& co
|
|||
/// @brief get a document in a coordinator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int getDocumentOnCoordinator(std::string const& dbname, std::string const& collname,
|
||||
transaction::Methods const& trx, VPackSlice slice,
|
||||
OperationOptions const& options,
|
||||
int getDocumentOnCoordinator(transaction::Methods& trx, std::string const& collname,
|
||||
VPackSlice slice, OperationOptions const& options,
|
||||
arangodb::rest::ResponseCode& responseCode,
|
||||
std::unordered_map<int, size_t>& errorCounter,
|
||||
std::shared_ptr<arangodb::velocypack::Builder>& resultBody);
|
||||
|
@ -206,8 +207,8 @@ void fetchVerticesFromEngines(
|
|||
/// Also returns the result in VelocyPack
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int getFilteredEdgesOnCoordinator(std::string const& dbname, std::string const& collname,
|
||||
transaction::Methods const& trx, std::string const& vertex,
|
||||
int getFilteredEdgesOnCoordinator(transaction::Methods const& trx,
|
||||
std::string const& collname, std::string const& vertex,
|
||||
TRI_edge_direction_e const& direction,
|
||||
arangodb::rest::ResponseCode& responseCode,
|
||||
arangodb::velocypack::Builder& result);
|
||||
|
@ -217,8 +218,8 @@ int getFilteredEdgesOnCoordinator(std::string const& dbname, std::string const&
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int modifyDocumentOnCoordinator(
|
||||
std::string const& dbname, std::string const& collname,
|
||||
transaction::Methods const& trx, arangodb::velocypack::Slice const& slice,
|
||||
transaction::Methods& trx, std::string const& collname,
|
||||
arangodb::velocypack::Slice const& slice,
|
||||
OperationOptions const& options, bool isPatch,
|
||||
std::unique_ptr<std::unordered_map<std::string, std::string>>& headers,
|
||||
arangodb::rest::ResponseCode& responseCode, std::unordered_map<int, size_t>& errorCounter,
|
||||
|
@ -228,7 +229,8 @@ int modifyDocumentOnCoordinator(
|
|||
/// @brief truncate a cluster collection on a coordinator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int truncateCollectionOnCoordinator(std::string const& dbname, std::string const& collname);
|
||||
Result truncateCollectionOnCoordinator(transaction::Methods& trx,
|
||||
std::string const& collname);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief flush Wal on all DBservers
|
||||
|
@ -267,7 +269,7 @@ class ClusterMethods {
|
|||
TRI_col_type_e collectionType, TRI_vocbase_t& vocbase,
|
||||
arangodb::velocypack::Slice parameters, bool ignoreDistributeShardsLikeErrors,
|
||||
bool waitForSyncReplication, bool enforceReplicationFactor);
|
||||
|
||||
|
||||
private:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Persist collection in Agency and trigger shard creation process
|
||||
|
|
|
@ -90,7 +90,7 @@ Result DBServerAgencySync::getLocalCollections(VPackBuilder& collections) {
|
|||
|
||||
collections.add(VPackValue(colname));
|
||||
VPackObjectBuilder col(&collections);
|
||||
collection->properties(collections, true, false);
|
||||
collection->properties(collections, /*detailed*/true, false);
|
||||
|
||||
auto const& folls = collection->followers();
|
||||
std::string const theLeader = folls->getLeader();
|
||||
|
|
|
@ -298,3 +298,17 @@ void FollowerInfo::clear() {
|
|||
auto v = std::make_shared<std::vector<ServerID>>();
|
||||
_followers = v; // will cast to std::vector<ServerID> const
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check whether the given server is a follower
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool FollowerInfo::contains(ServerID const& sid) const {
|
||||
MUTEX_LOCKER(locker, _mutex);
|
||||
for (auto const& s : *_followers) {
|
||||
if (s == sid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -76,6 +76,12 @@ class FollowerInfo {
|
|||
|
||||
void clear();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check whether the given server is a follower
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool contains(ServerID const& s) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set leadership
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -143,7 +143,7 @@ std::string ServerState::roleToString(ServerState::RoleEnum role) {
|
|||
return "UNDEFINED";
|
||||
case ROLE_SINGLE:
|
||||
return "SINGLE";
|
||||
case ROLE_PRIMARY:
|
||||
case ROLE_DBSERVER:
|
||||
return "PRIMARY";
|
||||
case ROLE_COORDINATOR:
|
||||
return "COORDINATOR";
|
||||
|
@ -161,7 +161,7 @@ std::string ServerState::roleToShortString(ServerState::RoleEnum role) {
|
|||
return "NONE";
|
||||
case ROLE_SINGLE:
|
||||
return "SNGL";
|
||||
case ROLE_PRIMARY:
|
||||
case ROLE_DBSERVER:
|
||||
return "PRMR";
|
||||
case ROLE_COORDINATOR:
|
||||
return "CRDN";
|
||||
|
@ -184,7 +184,7 @@ ServerState::RoleEnum ServerState::stringToRole(std::string const& value) {
|
|||
// note: DBSERVER is an alias for PRIMARY
|
||||
// internally and in all API values returned we will still use PRIMARY
|
||||
// for compatibility reasons
|
||||
return ROLE_PRIMARY;
|
||||
return ROLE_DBSERVER;
|
||||
} else if (value == "COORDINATOR") {
|
||||
return ROLE_COORDINATOR;
|
||||
} else if (value == "AGENT") {
|
||||
|
@ -396,7 +396,7 @@ std::string ServerState::roleToAgencyListKey(ServerState::RoleEnum role) {
|
|||
|
||||
std::string ServerState::roleToAgencyKey(ServerState::RoleEnum role) {
|
||||
switch (role) {
|
||||
case ROLE_PRIMARY:
|
||||
case ROLE_DBSERVER:
|
||||
return "DBServer";
|
||||
case ROLE_COORDINATOR:
|
||||
return "Coordinator";
|
||||
|
@ -768,7 +768,7 @@ void ServerState::setState(StateEnum state) {
|
|||
}
|
||||
|
||||
auto role = getRole();
|
||||
if (role == ROLE_PRIMARY) {
|
||||
if (role == ROLE_DBSERVER) {
|
||||
result = checkPrimaryState(state);
|
||||
} else if (role == ROLE_COORDINATOR) {
|
||||
result = checkCoordinatorState(state);
|
||||
|
|
|
@ -38,7 +38,7 @@ class ServerState {
|
|||
enum RoleEnum : int {
|
||||
ROLE_UNDEFINED = 0, // initial value
|
||||
ROLE_SINGLE, // is set when cluster feature is off
|
||||
ROLE_PRIMARY,
|
||||
ROLE_DBSERVER,
|
||||
ROLE_COORDINATOR,
|
||||
ROLE_AGENT
|
||||
};
|
||||
|
@ -146,13 +146,13 @@ class ServerState {
|
|||
/// running in cluster mode.
|
||||
static bool isDBServer(ServerState::RoleEnum role) {
|
||||
TRI_ASSERT(role != ServerState::ROLE_UNDEFINED);
|
||||
return (role == ServerState::ROLE_PRIMARY);
|
||||
return (role == ServerState::ROLE_DBSERVER);
|
||||
}
|
||||
|
||||
/// @brief whether or not the role is a cluster-related role
|
||||
static bool isClusterRole(ServerState::RoleEnum role) {
|
||||
TRI_ASSERT(role != ServerState::ROLE_UNDEFINED);
|
||||
return (role == ServerState::ROLE_PRIMARY || role == ServerState::ROLE_COORDINATOR);
|
||||
return (role == ServerState::ROLE_DBSERVER || role == ServerState::ROLE_COORDINATOR);
|
||||
}
|
||||
|
||||
/// @brief whether or not the role is a cluster-related role
|
||||
|
|
|
@ -15,7 +15,6 @@ set(CLUSTER_ENGINE_SOURCES
|
|||
ClusterEngine/ClusterRestWalHandler.cpp
|
||||
ClusterEngine/ClusterSelectivityEstimates.cpp
|
||||
ClusterEngine/ClusterTransactionCollection.cpp
|
||||
ClusterEngine/ClusterTransactionContextData.h
|
||||
ClusterEngine/ClusterTransactionState.cpp
|
||||
ClusterEngine/ClusterV8Functions.cpp
|
||||
ClusterEngine/MMFilesMethods.cpp
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
#include "ClusterEngine/ClusterIndexFactory.h"
|
||||
#include "ClusterEngine/ClusterRestHandlers.h"
|
||||
#include "ClusterEngine/ClusterTransactionCollection.h"
|
||||
#include "ClusterEngine/ClusterTransactionContextData.h"
|
||||
#include "ClusterEngine/ClusterTransactionManager.h"
|
||||
#include "ClusterEngine/ClusterTransactionState.h"
|
||||
#include "ClusterEngine/ClusterV8Functions.h"
|
||||
#include "GeneralServer/RestHandlerFactory.h"
|
||||
|
@ -53,6 +51,8 @@
|
|||
#include "RocksDBEngine/RocksDBEngine.h"
|
||||
#include "RocksDBEngine/RocksDBOptimizerRules.h"
|
||||
#include "Transaction/Context.h"
|
||||
#include "Transaction/ContextData.h"
|
||||
#include "Transaction/Manager.h"
|
||||
#include "Transaction/Options.h"
|
||||
#include "VocBase/LogicalView.h"
|
||||
#include "VocBase/ticks.h"
|
||||
|
@ -126,17 +126,18 @@ void ClusterEngine::start() {
|
|||
TRI_ASSERT(ServerState::instance()->isCoordinator());
|
||||
}
|
||||
|
||||
std::unique_ptr<TransactionManager> ClusterEngine::createTransactionManager() {
|
||||
return std::unique_ptr<TransactionManager>(new ClusterTransactionManager());
|
||||
std::unique_ptr<transaction::Manager> ClusterEngine::createTransactionManager() {
|
||||
return std::make_unique<transaction::Manager>(/*keepData*/ false);
|
||||
}
|
||||
|
||||
std::unique_ptr<transaction::ContextData> ClusterEngine::createTransactionContextData() {
|
||||
return std::unique_ptr<transaction::ContextData>(new ClusterTransactionContextData());
|
||||
return std::unique_ptr<transaction::ContextData>(); // not used by coordinator
|
||||
}
|
||||
|
||||
std::unique_ptr<TransactionState> ClusterEngine::createTransactionState(
|
||||
TRI_vocbase_t& vocbase, transaction::Options const& options) {
|
||||
return std::make_unique<ClusterTransactionState>(vocbase, TRI_NewTickServer(), options);
|
||||
std::unique_ptr<TransactionState> ClusterEngine::createTransactionState(TRI_vocbase_t& vocbase,
|
||||
TRI_voc_tid_t tid,
|
||||
transaction::Options const& options) {
|
||||
return std::make_unique<ClusterTransactionState>(vocbase, tid, options);
|
||||
}
|
||||
|
||||
std::unique_ptr<TransactionCollection> ClusterEngine::createTransactionCollection(
|
||||
|
@ -361,4 +362,4 @@ std::unique_ptr<TRI_vocbase_t> ClusterEngine::openExistingDatabase(
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -34,19 +34,6 @@
|
|||
#include <velocypack/Slice.h>
|
||||
|
||||
namespace arangodb {
|
||||
class PhysicalCollection;
|
||||
class PhysicalView;
|
||||
class TransactionCollection;
|
||||
class TransactionState;
|
||||
|
||||
namespace rest {
|
||||
class RestHandlerFactory;
|
||||
}
|
||||
|
||||
namespace transaction {
|
||||
class ContextData;
|
||||
struct Options;
|
||||
} // namespace transaction
|
||||
|
||||
class ClusterEngine final : public StorageEngine {
|
||||
public:
|
||||
|
@ -82,9 +69,9 @@ class ClusterEngine final : public StorageEngine {
|
|||
bool supportsDfdb() const override { return false; }
|
||||
bool useRawDocumentPointers() override { return false; }
|
||||
|
||||
std::unique_ptr<TransactionManager> createTransactionManager() override;
|
||||
std::unique_ptr<transaction::Manager> createTransactionManager() override;
|
||||
std::unique_ptr<transaction::ContextData> createTransactionContextData() override;
|
||||
std::unique_ptr<TransactionState> createTransactionState(TRI_vocbase_t& vocbase,
|
||||
std::unique_ptr<TransactionState> createTransactionState(TRI_vocbase_t& vocbase, TRI_voc_tid_t tid,
|
||||
transaction::Options const& options) override;
|
||||
std::unique_ptr<TransactionCollection> createTransactionCollection(
|
||||
TransactionState& state, TRI_voc_cid_t cid, AccessMode::Type accessType,
|
||||
|
@ -272,4 +259,4 @@ class ClusterEngine final : public StorageEngine {
|
|||
|
||||
} // namespace arangodb
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -20,15 +20,15 @@
|
|||
/// @author Jan Steemann
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ClusterRestWalHandler.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "Cluster/ClusterMethods.h"
|
||||
#include "Cluster/ServerState.h"
|
||||
#include "RestServer/TransactionManagerFeature.h"
|
||||
#include "ClusterRestWalHandler.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/StorageEngine.h"
|
||||
#include "StorageEngine/TransactionManager.h"
|
||||
#include "Transaction/Manager.h"
|
||||
#include "Transaction/ManagerFeature.h"
|
||||
#include "Utils/ExecContext.h"
|
||||
|
||||
#include <rocksdb/utilities/transaction_db.h>
|
||||
|
@ -152,7 +152,7 @@ void ClusterRestWalHandler::flush() {
|
|||
}
|
||||
|
||||
void ClusterRestWalHandler::transactions() {
|
||||
TransactionManager* mngr = TransactionManagerFeature::manager();
|
||||
auto* mngr = transaction::ManagerFeature::manager();
|
||||
VPackBuilder builder;
|
||||
builder.openObject();
|
||||
builder.add("runningTransactions", VPackValue(mngr->getActiveTransactionCount()));
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
/// @author Simon Grätzer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ClusterTransactionCollection.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Cluster/ClusterInfo.h"
|
||||
#include "ClusterTransactionCollection.h"
|
||||
#include "Logger/Logger.h"
|
||||
#include "StorageEngine/TransactionState.h"
|
||||
#include "Transaction/Hints.h"
|
||||
|
@ -37,8 +37,7 @@ ClusterTransactionCollection::ClusterTransactionCollection(TransactionState* trx
|
|||
int nestingLevel)
|
||||
: TransactionCollection(trx, cid, accessType),
|
||||
_lockType(AccessMode::Type::NONE),
|
||||
_nestingLevel(nestingLevel),
|
||||
_usageLocked(false) {}
|
||||
_nestingLevel(nestingLevel) {}
|
||||
|
||||
ClusterTransactionCollection::~ClusterTransactionCollection() {}
|
||||
|
||||
|
@ -107,7 +106,6 @@ int ClusterTransactionCollection::use(int nestingLevel) {
|
|||
!_transaction->hasHint(transaction::Hints::Hint::NO_USAGE_LOCK)) {
|
||||
// use and usage-lock
|
||||
LOG_TRX(_transaction, nestingLevel) << "using collection " << _cid;
|
||||
_usageLocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,11 +141,6 @@ void ClusterTransactionCollection::release() {
|
|||
if (_collection != nullptr) {
|
||||
// unuse collection, remove usage-lock
|
||||
LOG_TRX(_transaction, 0) << "unusing collection " << _cid;
|
||||
|
||||
if (_usageLocked) {
|
||||
_transaction->vocbase().releaseCollection(_collection.get());
|
||||
_usageLocked = false;
|
||||
}
|
||||
_collection = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -169,12 +162,6 @@ int ClusterTransactionCollection::doLock(AccessMode::Type type, int nestingLevel
|
|||
|
||||
TRI_ASSERT(_collection != nullptr);
|
||||
|
||||
std::string collName(_collection->name());
|
||||
if (_transaction->isLockedShard(collName)) {
|
||||
// do not lock by command
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
TRI_ASSERT(!isLocked());
|
||||
|
||||
TRI_ASSERT(_collection);
|
||||
|
@ -200,14 +187,7 @@ int ClusterTransactionCollection::doUnlock(AccessMode::Type type, int nestingLev
|
|||
|
||||
TRI_ASSERT(_collection != nullptr);
|
||||
|
||||
std::string collName(_collection->name());
|
||||
if (_transaction->isLockedShard(collName)) {
|
||||
// do not lock by command
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
TRI_ASSERT(isLocked());
|
||||
|
||||
if (_nestingLevel < nestingLevel) {
|
||||
// only process our own collections
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
|
|
|
@ -65,7 +65,6 @@ class ClusterTransactionCollection final : public TransactionCollection {
|
|||
private:
|
||||
AccessMode::Type _lockType; // collection lock type, used for exclusive locks
|
||||
int _nestingLevel; // the transaction level that added this collection
|
||||
bool _usageLocked; // is this already locked
|
||||
};
|
||||
} // namespace arangodb
|
||||
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2018 ArangoDB 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 Simon Grätzer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGOD_CLUSTER_CLUSTER_TRANSACTION_CONTEXT_DATA_H
|
||||
#define ARANGOD_CLUSTER_CLUSTER_TRANSACTION_CONTEXT_DATA_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Transaction/ContextData.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
namespace arangodb {
|
||||
class LogicalCollection;
|
||||
|
||||
/// @brief transaction type
|
||||
class ClusterTransactionContextData final : public transaction::ContextData {
|
||||
public:
|
||||
ClusterTransactionContextData() = default;
|
||||
~ClusterTransactionContextData() = default;
|
||||
|
||||
/// @brief pin data for the collection
|
||||
/// there is nothing to do for the RocksDB engine
|
||||
void pinData(arangodb::LogicalCollection*) override {}
|
||||
|
||||
/// @brief whether or not the data for the collection is pinned
|
||||
/// note that this is always true in RocksDB
|
||||
bool isPinned(TRI_voc_cid_t) const override { return true; }
|
||||
};
|
||||
} // namespace arangodb
|
||||
|
||||
#endif
|
|
@ -1,74 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2018 ArangoDB 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 Simon Grätzer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGOD_CLUSTER_CLUSTER_TRANSACTION_MANAGER_H
|
||||
#define ARANGOD_CLUSTER_CLUSTER_TRANSACTION_MANAGER_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/ReadWriteLock.h"
|
||||
#include "StorageEngine/TransactionManager.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
namespace arangodb {
|
||||
|
||||
class ClusterTransactionManager final : public TransactionManager {
|
||||
public:
|
||||
ClusterTransactionManager() : TransactionManager(), _nrRunning(0) {}
|
||||
~ClusterTransactionManager() {}
|
||||
|
||||
// register a list of failed transactions
|
||||
void registerFailedTransactions(std::unordered_set<TRI_voc_tid_t> const& failedTransactions) override {
|
||||
}
|
||||
|
||||
// unregister a list of failed transactions
|
||||
void unregisterFailedTransactions(std::unordered_set<TRI_voc_tid_t> const& failedTransactions) override {
|
||||
}
|
||||
|
||||
// return the set of failed transactions
|
||||
std::unordered_set<TRI_voc_tid_t> getFailedTransactions() override {
|
||||
return std::unordered_set<TRI_voc_tid_t>();
|
||||
}
|
||||
|
||||
// register a transaction
|
||||
void registerTransaction(TRI_voc_tid_t transactionId,
|
||||
std::unique_ptr<TransactionData> data) override {
|
||||
TRI_ASSERT(data == nullptr);
|
||||
++_nrRunning;
|
||||
}
|
||||
|
||||
// unregister a transaction
|
||||
void unregisterTransaction(TRI_voc_tid_t transactionId, bool markAsFailed) override {
|
||||
--_nrRunning;
|
||||
}
|
||||
|
||||
// iterate all the active transactions
|
||||
void iterateActiveTransactions(
|
||||
std::function<void(TRI_voc_tid_t, TransactionData const*)> const& callback) override {}
|
||||
|
||||
uint64_t getActiveTransactionCount() override { return _nrRunning; }
|
||||
|
||||
private:
|
||||
std::atomic<uint64_t> _nrRunning;
|
||||
};
|
||||
} // namespace arangodb
|
||||
|
||||
#endif
|
|
@ -21,12 +21,15 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ClusterTransactionState.h"
|
||||
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Logger/Logger.h"
|
||||
#include "RestServer/TransactionManagerFeature.h"
|
||||
#include "StorageEngine/StorageEngine.h"
|
||||
#include "Cluster/ClusterMethods.h"
|
||||
#include "ClusterEngine/ClusterEngine.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/TransactionCollection.h"
|
||||
#include "StorageEngine/TransactionManager.h"
|
||||
#include "Transaction/Manager.h"
|
||||
#include "Transaction/ManagerFeature.h"
|
||||
#include "Transaction/Methods.h"
|
||||
#include "Utils/ExecContext.h"
|
||||
#include "VocBase/LogicalCollection.h"
|
||||
|
@ -34,52 +37,46 @@
|
|||
|
||||
using namespace arangodb;
|
||||
|
||||
// for the Cluster engine we do not need any additional data
|
||||
struct ClusterTransactionData final : public TransactionData {};
|
||||
|
||||
/// @brief transaction type
|
||||
ClusterTransactionState::ClusterTransactionState(TRI_vocbase_t& vocbase, TRI_voc_tid_t tid,
|
||||
ClusterTransactionState::ClusterTransactionState(TRI_vocbase_t& vocbase,
|
||||
TRI_voc_tid_t tid,
|
||||
transaction::Options const& options)
|
||||
: TransactionState(vocbase, tid, options) {}
|
||||
|
||||
/// @brief free a transaction container
|
||||
ClusterTransactionState::~ClusterTransactionState() {}
|
||||
|
||||
/// @brief start a transaction
|
||||
Result ClusterTransactionState::beginTransaction(transaction::Hints hints) {
|
||||
LOG_TRX(this, _nestingLevel)
|
||||
LOG_TRX(this, nestingLevel())
|
||||
<< "beginning " << AccessMode::typeString(_type) << " transaction";
|
||||
|
||||
TRI_ASSERT(!hasHint(transaction::Hints::Hint::NO_USAGE_LOCK) ||
|
||||
!AccessMode::isWriteOrExclusive(_type));
|
||||
|
||||
if (_nestingLevel == 0) {
|
||||
if (nestingLevel() == 0) {
|
||||
// set hints
|
||||
_hints = hints;
|
||||
}
|
||||
|
||||
Result result = useCollections(_nestingLevel);
|
||||
Result result = useCollections(nestingLevel());
|
||||
if (result.ok()) {
|
||||
// all valid
|
||||
if (_nestingLevel == 0) {
|
||||
if (nestingLevel() == 0) {
|
||||
updateStatus(transaction::Status::RUNNING);
|
||||
}
|
||||
} else {
|
||||
// something is wrong
|
||||
if (_nestingLevel == 0) {
|
||||
if (nestingLevel() == 0) {
|
||||
updateStatus(transaction::Status::ABORTED);
|
||||
}
|
||||
|
||||
// free what we have got so far
|
||||
unuseCollections(_nestingLevel);
|
||||
unuseCollections(nestingLevel());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (_nestingLevel == 0) {
|
||||
// register a protector (intentionally empty)
|
||||
TransactionManagerFeature::manager()->registerTransaction(
|
||||
_id, std::unique_ptr<ClusterTransactionData>());
|
||||
if (nestingLevel() == 0) {
|
||||
transaction::ManagerFeature::manager()->registerTransaction(id(), nullptr);
|
||||
setRegistered();
|
||||
} else {
|
||||
TRI_ASSERT(_status == transaction::Status::RUNNING);
|
||||
}
|
||||
|
@ -89,7 +86,7 @@ Result ClusterTransactionState::beginTransaction(transaction::Hints hints) {
|
|||
|
||||
/// @brief commit a transaction
|
||||
Result ClusterTransactionState::commitTransaction(transaction::Methods* activeTrx) {
|
||||
LOG_TRX(this, _nestingLevel)
|
||||
LOG_TRX(this, nestingLevel())
|
||||
<< "committing " << AccessMode::typeString(_type) << " transaction";
|
||||
|
||||
TRI_ASSERT(_status == transaction::Status::RUNNING);
|
||||
|
@ -98,28 +95,23 @@ Result ClusterTransactionState::commitTransaction(transaction::Methods* activeTr
|
|||
}
|
||||
|
||||
arangodb::Result res;
|
||||
if (_nestingLevel == 0) {
|
||||
if (true) {
|
||||
updateStatus(transaction::Status::COMMITTED);
|
||||
// cleanupTransaction(); // deletes trx
|
||||
} else {
|
||||
abortTransaction(activeTrx); // deletes trx
|
||||
}
|
||||
if (nestingLevel() == 0) {
|
||||
updateStatus(transaction::Status::COMMITTED);
|
||||
}
|
||||
|
||||
unuseCollections(_nestingLevel);
|
||||
unuseCollections(nestingLevel());
|
||||
return res;
|
||||
}
|
||||
|
||||
/// @brief abort and rollback a transaction
|
||||
Result ClusterTransactionState::abortTransaction(transaction::Methods* activeTrx) {
|
||||
LOG_TRX(this, _nestingLevel) << "aborting " << AccessMode::typeString(_type) << " transaction";
|
||||
LOG_TRX(this, nestingLevel()) << "aborting " << AccessMode::typeString(_type) << " transaction";
|
||||
TRI_ASSERT(_status == transaction::Status::RUNNING);
|
||||
Result result;
|
||||
if (_nestingLevel == 0) {
|
||||
Result res;
|
||||
if (nestingLevel() == 0) {
|
||||
updateStatus(transaction::Status::ABORTED);
|
||||
}
|
||||
|
||||
unuseCollections(_nestingLevel);
|
||||
return result;
|
||||
unuseCollections(nestingLevel());
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -23,35 +23,16 @@
|
|||
#ifndef ARANGOD_CLUSTER_CLUSTER_TRANSACTION_STATE_H
|
||||
#define ARANGOD_CLUSTER_CLUSTER_TRANSACTION_STATE_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/SmallVector.h"
|
||||
#include "StorageEngine/TransactionState.h"
|
||||
#include "Transaction/Hints.h"
|
||||
#include "Transaction/Methods.h"
|
||||
#include "VocBase/AccessMode.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
struct TRI_vocbase_t;
|
||||
|
||||
namespace arangodb {
|
||||
|
||||
class LogicalCollection;
|
||||
|
||||
namespace transaction {
|
||||
|
||||
class Methods;
|
||||
struct Options;
|
||||
|
||||
} // namespace transaction
|
||||
|
||||
class TransactionCollection;
|
||||
|
||||
/// @brief transaction type
|
||||
class ClusterTransactionState final : public TransactionState {
|
||||
public:
|
||||
ClusterTransactionState(TRI_vocbase_t& vocbase, TRI_voc_tid_t tid,
|
||||
transaction::Options const& options);
|
||||
~ClusterTransactionState();
|
||||
~ClusterTransactionState() {}
|
||||
|
||||
/// @brief begin a transaction
|
||||
Result beginTransaction(transaction::Hints hints) override;
|
||||
|
|
|
@ -36,7 +36,6 @@ EdgeCollectionInfo::EdgeCollectionInfo(transaction::Methods* trx,
|
|||
_collectionName(collectionName),
|
||||
_searchBuilder(),
|
||||
_weightAttribute(weightAttribute),
|
||||
_defaultWeight(defaultWeight),
|
||||
_dir(direction) {
|
||||
TRI_ASSERT(_dir == TRI_EDGE_OUT || _dir == TRI_EDGE_IN);
|
||||
|
||||
|
@ -85,81 +84,6 @@ std::unique_ptr<arangodb::OperationCursor> EdgeCollectionInfo::getEdges(
|
|||
_forwardIndexId, cond, _searchBuilder.getVariable(), opts));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get edges for the given direction and start vertex. On Coordinator.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int EdgeCollectionInfo::getEdgesCoordinator(VPackSlice const& vertexId, VPackBuilder& result) {
|
||||
TRI_ASSERT(result.isEmpty());
|
||||
arangodb::rest::ResponseCode responseCode;
|
||||
|
||||
result.openObject();
|
||||
|
||||
int res = getFilteredEdgesOnCoordinator(_trx->vocbase().name(), _collectionName,
|
||||
*_trx, vertexId.copyString(), _dir,
|
||||
responseCode, result);
|
||||
|
||||
result.close();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get edges for the given direction and start vertex. Reverse version
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unique_ptr<arangodb::OperationCursor> EdgeCollectionInfo::getReverseEdges(
|
||||
std::string const& vertexId) {
|
||||
_searchBuilder.setVertexId(vertexId);
|
||||
arangodb::aql::AstNode const* cond;
|
||||
if (_dir == TRI_EDGE_OUT) {
|
||||
cond = _searchBuilder.getInboundCondition();
|
||||
} else {
|
||||
cond = _searchBuilder.getOutboundCondition();
|
||||
}
|
||||
|
||||
IndexIteratorOptions opts;
|
||||
return std::make_unique<OperationCursor>(_trx->indexScanForCondition(
|
||||
_backwardIndexId, cond, _searchBuilder.getVariable(), opts));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get edges for the given direction and start vertex. Reverse version
|
||||
/// on Coordinator.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int EdgeCollectionInfo::getReverseEdgesCoordinator(VPackSlice const& vertexId,
|
||||
VPackBuilder& result) {
|
||||
TRI_ASSERT(result.isEmpty());
|
||||
arangodb::rest::ResponseCode responseCode;
|
||||
|
||||
result.openObject();
|
||||
|
||||
TRI_edge_direction_e dir = TRI_EDGE_OUT;
|
||||
|
||||
if (_dir == TRI_EDGE_OUT) {
|
||||
dir = TRI_EDGE_IN;
|
||||
}
|
||||
|
||||
int res = getFilteredEdgesOnCoordinator(_trx->vocbase().name(), _collectionName,
|
||||
*_trx, vertexId.copyString(), dir,
|
||||
responseCode, result);
|
||||
|
||||
result.close();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Compute the weight of an edge
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
double EdgeCollectionInfo::weightEdge(VPackSlice const edge) {
|
||||
TRI_ASSERT(!_weightAttribute.empty());
|
||||
return arangodb::basics::VelocyPackHelper::getNumericValue<double>(
|
||||
edge, _weightAttribute.c_str(), _defaultWeight);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return name of the wrapped collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -66,8 +66,6 @@ class EdgeCollectionInfo {
|
|||
|
||||
std::string _weightAttribute;
|
||||
|
||||
double _defaultWeight;
|
||||
|
||||
TRI_edge_direction_e _dir;
|
||||
|
||||
public:
|
||||
|
@ -81,28 +79,6 @@ class EdgeCollectionInfo {
|
|||
|
||||
std::unique_ptr<arangodb::OperationCursor> getEdges(std::string const&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get edges for the given direction and start vertex. On Coordinator.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int getEdgesCoordinator(arangodb::velocypack::Slice const&, arangodb::velocypack::Builder&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get edges for the given direction and start vertex. Reverse version
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unique_ptr<arangodb::OperationCursor> getReverseEdges(std::string const&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get edges for the given direction and start vertex. Reverse version
|
||||
/// on Coordinator.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int getReverseEdgesCoordinator(arangodb::velocypack::Slice const&,
|
||||
arangodb::velocypack::Builder&);
|
||||
|
||||
double weightEdge(arangodb::velocypack::Slice const);
|
||||
|
||||
transaction::Methods* trx() const { return _trx; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -39,8 +39,10 @@
|
|||
#include "IResearchViewBlock.h"
|
||||
#include "IResearchViewCoordinator.h"
|
||||
#include "StorageEngine/TransactionState.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "VocBase/LogicalCollection.h"
|
||||
#include "velocypack/Iterator.h"
|
||||
|
||||
#include <velocypack/Iterator.h>
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ set(MMFILES_SOURCES
|
|||
MMFiles/MMFilesSynchronizerThread.cpp
|
||||
MMFiles/MMFilesTransactionCollection.cpp
|
||||
MMFiles/MMFilesTransactionContextData.cpp
|
||||
MMFiles/MMFilesTransactionManager.cpp
|
||||
MMFiles/MMFilesTransactionState.cpp
|
||||
MMFiles/MMFilesTtlIndex.cpp
|
||||
MMFiles/MMFilesV8Functions.cpp
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "MMFilesCollectorThread.h"
|
||||
|
||||
#include "Basics/ConditionLocker.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Basics/MutexLocker.h"
|
||||
|
@ -40,9 +41,9 @@
|
|||
#include "MMFiles/MMFilesPersistentIndex.h"
|
||||
#include "MMFiles/MMFilesPrimaryIndex.h"
|
||||
#include "MMFiles/MMFilesWalLogfile.h"
|
||||
#include "RestServer/TransactionManagerFeature.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/StorageEngine.h"
|
||||
#include "Transaction/ManagerFeature.h"
|
||||
#include "Transaction/Helpers.h"
|
||||
#include "Transaction/Hints.h"
|
||||
#include "Transaction/StandaloneContext.h"
|
||||
|
@ -836,7 +837,7 @@ int MMFilesCollectorThread::collect(MMFilesWalLogfile* logfile) {
|
|||
// transactions
|
||||
CollectorState state;
|
||||
state.failedTransactions =
|
||||
TransactionManagerFeature::manager()->getFailedTransactions();
|
||||
transaction::ManagerFeature::manager()->getFailedTransactions();
|
||||
|
||||
// scan all markers in logfile, this will fill the state
|
||||
bool result = TRI_IterateDatafile(df, &ScanMarker, static_cast<void*>(&state));
|
||||
|
@ -962,7 +963,7 @@ int MMFilesCollectorThread::collect(MMFilesWalLogfile* logfile) {
|
|||
|
||||
// remove all handled transactions from failedTransactions list
|
||||
if (!state.handledTransactions.empty()) {
|
||||
TransactionManagerFeature::manager()->unregisterFailedTransactions(state.handledTransactions);
|
||||
transaction::ManagerFeature::manager()->unregisterFailedTransactions(state.handledTransactions);
|
||||
}
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
|
|
|
@ -325,7 +325,7 @@ void MMFilesEdgeIndex::batchInsert(transaction::Methods& trx,
|
|||
toElements->reserve(documents.size());
|
||||
|
||||
// functions that will be called for each thread
|
||||
auto creator = [&trx, this]() -> void* {
|
||||
auto creator = [this]() -> void* {
|
||||
return new MMFilesIndexLookupContext(&_collection, nullptr, 1);
|
||||
};
|
||||
auto destroyer = [](void* userData) {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "MMFiles/MMFilesEngine.h"
|
||||
|
||||
#include "ApplicationFeatures/ApplicationServer.h"
|
||||
#include "Basics/FileUtils.h"
|
||||
#include "Basics/MutexLocker.h"
|
||||
|
@ -48,7 +49,6 @@
|
|||
#include "MMFiles/MMFilesRestHandlers.h"
|
||||
#include "MMFiles/MMFilesTransactionCollection.h"
|
||||
#include "MMFiles/MMFilesTransactionContextData.h"
|
||||
#include "MMFiles/MMFilesTransactionManager.h"
|
||||
#include "MMFiles/MMFilesTransactionState.h"
|
||||
#include "MMFiles/MMFilesV8Functions.h"
|
||||
#include "MMFiles/MMFilesWalAccess.h"
|
||||
|
@ -277,18 +277,17 @@ void MMFilesEngine::stop() {
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<TransactionManager> MMFilesEngine::createTransactionManager() {
|
||||
return std::unique_ptr<TransactionManager>(new MMFilesTransactionManager());
|
||||
std::unique_ptr<transaction::Manager> MMFilesEngine::createTransactionManager() {
|
||||
return std::make_unique<transaction::Manager>(/*keepData*/ true);
|
||||
}
|
||||
|
||||
std::unique_ptr<transaction::ContextData> MMFilesEngine::createTransactionContextData() {
|
||||
return std::unique_ptr<transaction::ContextData>(new MMFilesTransactionContextData());
|
||||
return std::make_unique<MMFilesTransactionContextData>();
|
||||
}
|
||||
|
||||
std::unique_ptr<TransactionState> MMFilesEngine::createTransactionState(
|
||||
TRI_vocbase_t& vocbase, transaction::Options const& options) {
|
||||
return std::unique_ptr<TransactionState>(
|
||||
new MMFilesTransactionState(vocbase, TRI_NewTickServer(), options));
|
||||
TRI_vocbase_t& vocbase, TRI_voc_tick_t tid, transaction::Options const& options) {
|
||||
return std::make_unique<MMFilesTransactionState>(vocbase, tid, options);
|
||||
}
|
||||
|
||||
std::unique_ptr<TransactionCollection> MMFilesEngine::createTransactionCollection(
|
||||
|
@ -301,7 +300,6 @@ std::unique_ptr<TransactionCollection> MMFilesEngine::createTransactionCollectio
|
|||
std::unique_ptr<PhysicalCollection> MMFilesEngine::createPhysicalCollection(
|
||||
LogicalCollection& collection, velocypack::Slice const& info) {
|
||||
TRI_ASSERT(EngineSelectorFeature::ENGINE == this);
|
||||
|
||||
return std::unique_ptr<PhysicalCollection>(new MMFilesCollection(collection, info));
|
||||
}
|
||||
|
||||
|
|
|
@ -39,22 +39,6 @@ namespace arangodb {
|
|||
class MMFilesCleanupThread;
|
||||
class MMFilesCompactorThread;
|
||||
class MMFilesWalAccess;
|
||||
class PhysicalCollection;
|
||||
class PhysicalView;
|
||||
class TransactionCollection;
|
||||
class TransactionState;
|
||||
|
||||
namespace rest {
|
||||
|
||||
class RestHandlerFactory;
|
||||
}
|
||||
|
||||
namespace transaction {
|
||||
|
||||
class ContextData;
|
||||
struct Options;
|
||||
|
||||
} // namespace transaction
|
||||
|
||||
class MMFilesRecoveryHelper {
|
||||
public:
|
||||
|
@ -124,10 +108,10 @@ class MMFilesEngine final : public StorageEngine {
|
|||
std::shared_ptr<VPackBuilder>& builderSPtr) override;
|
||||
WalAccess const* walAccess() const override;
|
||||
|
||||
std::unique_ptr<TransactionManager> createTransactionManager() override;
|
||||
std::unique_ptr<transaction::Manager> createTransactionManager() override;
|
||||
std::unique_ptr<transaction::ContextData> createTransactionContextData() override;
|
||||
std::unique_ptr<TransactionState> createTransactionState(TRI_vocbase_t& vocbase,
|
||||
transaction::Options const& options) override;
|
||||
std::unique_ptr<TransactionState> createTransactionState(
|
||||
TRI_vocbase_t& vocbase, TRI_voc_tick_t, transaction::Options const& options) override;
|
||||
std::unique_ptr<TransactionCollection> createTransactionCollection(
|
||||
TransactionState& state, TRI_voc_cid_t cid, AccessMode::Type accessType,
|
||||
int nestingLevel) override;
|
||||
|
@ -531,4 +515,4 @@ class MMFilesEngine final : public StorageEngine {
|
|||
|
||||
} // namespace arangodb
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -655,7 +655,7 @@ void MMFilesHashIndex::batchInsertUnique(
|
|||
}
|
||||
|
||||
// functions that will be called for each thread
|
||||
auto creator = [&trx, this]() -> void* {
|
||||
auto creator = [this]() -> void* {
|
||||
return new MMFilesIndexLookupContext(&_collection, nullptr, numPaths());
|
||||
};
|
||||
auto destroyer = [](void* userData) {
|
||||
|
@ -774,7 +774,7 @@ void MMFilesHashIndex::batchInsertMulti(
|
|||
}
|
||||
|
||||
// functions that will be called for each thread
|
||||
auto creator = [&trx, this]() -> void* {
|
||||
auto creator = [this]() -> void* {
|
||||
return new MMFilesIndexLookupContext(&_collection, nullptr, numPaths());
|
||||
};
|
||||
auto destroyer = [](void* userData) {
|
||||
|
|
|
@ -48,9 +48,10 @@
|
|||
#include "RestServer/DatabaseFeature.h"
|
||||
#include "RestServer/DatabasePathFeature.h"
|
||||
#include "RestServer/FlushFeature.h"
|
||||
#include "RestServer/TransactionManagerFeature.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/StorageEngine.h"
|
||||
#include "Transaction/ManagerFeature.h"
|
||||
#include "StorageEngine/TransactionState.h"
|
||||
|
||||
using namespace arangodb;
|
||||
using namespace arangodb::application_features;
|
||||
|
@ -355,7 +356,7 @@ bool MMFilesLogfileManager::open() {
|
|||
for (auto const& it : _recoverState->failedTransactions) {
|
||||
failedTransactions.emplace(it.first);
|
||||
}
|
||||
TransactionManagerFeature::manager()->registerFailedTransactions(failedTransactions);
|
||||
transaction::ManagerFeature::manager()->registerFailedTransactions(failedTransactions);
|
||||
_droppedDatabases = _recoverState->droppedDatabases;
|
||||
_droppedCollections = _recoverState->droppedCollections;
|
||||
|
||||
|
@ -598,8 +599,7 @@ int MMFilesLogfileManager::registerTransaction(TRI_voc_tid_t transactionId,
|
|||
|
||||
try {
|
||||
auto data = std::make_unique<MMFilesTransactionData>(lastCollectedId, lastSealedId);
|
||||
TransactionManagerFeature::manager()->registerTransaction(transactionId,
|
||||
std::move(data));
|
||||
transaction::ManagerFeature::manager()->registerTransaction(transactionId, std::move(data));
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
} catch (...) {
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -1425,7 +1425,7 @@ MMFilesWalLogfile* MMFilesLogfileManager::getCollectableLogfile() {
|
|||
};
|
||||
|
||||
// iterate over all active transactions and find their minimum used logfile id
|
||||
TransactionManagerFeature::manager()->iterateActiveTransactions(cb);
|
||||
transaction::ManagerFeature::manager()->iterateActiveTransactions(cb);
|
||||
|
||||
{
|
||||
READ_LOCKER(readLocker, _logfilesLock);
|
||||
|
@ -1488,7 +1488,7 @@ MMFilesWalLogfile* MMFilesLogfileManager::getRemovableLogfile() {
|
|||
}
|
||||
};
|
||||
|
||||
TransactionManagerFeature::manager()->iterateActiveTransactions(cb);
|
||||
transaction::ManagerFeature::manager()->iterateActiveTransactions(cb);
|
||||
|
||||
{
|
||||
uint32_t numberOfLogfiles = 0;
|
||||
|
@ -1691,7 +1691,7 @@ std::tuple<size_t, MMFilesWalLogfile::IdType, MMFilesWalLogfile::IdType> MMFiles
|
|||
};
|
||||
|
||||
// iterate over all active transactions
|
||||
TransactionManagerFeature::manager()->iterateActiveTransactions(cb);
|
||||
transaction::ManagerFeature::manager()->iterateActiveTransactions(cb);
|
||||
|
||||
return std::tuple<size_t, MMFilesWalLogfile::IdType, MMFilesWalLogfile::IdType>(
|
||||
count, lastCollectedId, lastSealedId);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "Basics/ReadWriteLock.h"
|
||||
#include "MMFiles/MMFilesWalLogfile.h"
|
||||
#include "MMFiles/MMFilesWalSlots.h"
|
||||
#include "StorageEngine/TransactionManager.h"
|
||||
#include "Transaction/Manager.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
namespace arangodb {
|
||||
|
@ -236,7 +236,8 @@ class MMFilesLogfileManager final : public application_features::ApplicationFeat
|
|||
}
|
||||
|
||||
// registers a transaction
|
||||
int registerTransaction(TRI_voc_tid_t id, bool isReadOnlyTransaction);
|
||||
int registerTransaction(TRI_voc_tid_t transactionId,
|
||||
bool isReadOnlyTransaction);
|
||||
|
||||
// return the set of dropped collections
|
||||
/// this is used during recovery and not used afterwards
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "MMFilesTransactionState.h"
|
||||
|
||||
#include "Aql/QueryCache.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Basics/RocksDBUtils.h"
|
||||
|
@ -73,11 +74,11 @@ rocksdb::Transaction* MMFilesTransactionState::rocksTransaction() {
|
|||
|
||||
/// @brief start a transaction
|
||||
Result MMFilesTransactionState::beginTransaction(transaction::Hints hints) {
|
||||
LOG_TRX(this, _nestingLevel)
|
||||
LOG_TRX(this, nestingLevel())
|
||||
<< "beginning " << AccessMode::typeString(_type) << " transaction";
|
||||
Result result;
|
||||
|
||||
if (_nestingLevel == 0) {
|
||||
if (nestingLevel() == 0) {
|
||||
TRI_ASSERT(_status == transaction::Status::CREATED);
|
||||
|
||||
auto logfileManager = MMFilesLogfileManager::instance();
|
||||
|
@ -102,7 +103,7 @@ Result MMFilesTransactionState::beginTransaction(transaction::Hints hints) {
|
|||
_hints = hints;
|
||||
|
||||
// register a protector
|
||||
int res = logfileManager->registerTransaction(_id, isReadOnlyTransaction());
|
||||
int res = logfileManager->registerTransaction(id(), isReadOnlyTransaction());
|
||||
result.reset(res);
|
||||
|
||||
if (!result.ok()) {
|
||||
|
@ -115,23 +116,23 @@ Result MMFilesTransactionState::beginTransaction(transaction::Hints hints) {
|
|||
TRI_ASSERT(_status == transaction::Status::RUNNING);
|
||||
}
|
||||
|
||||
result = useCollections(_nestingLevel);
|
||||
result = useCollections(nestingLevel());
|
||||
|
||||
if (result.ok()) {
|
||||
// all valid
|
||||
if (_nestingLevel == 0) {
|
||||
if (nestingLevel() == 0) {
|
||||
updateStatus(transaction::Status::RUNNING);
|
||||
|
||||
// defer writing of the begin marker until necessary!
|
||||
}
|
||||
} else {
|
||||
// something is wrong
|
||||
if (_nestingLevel == 0) {
|
||||
if (nestingLevel() == 0) {
|
||||
updateStatus(transaction::Status::ABORTED);
|
||||
}
|
||||
|
||||
// free what we have got so far
|
||||
unuseCollections(_nestingLevel);
|
||||
unuseCollections(nestingLevel());
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -139,12 +140,12 @@ Result MMFilesTransactionState::beginTransaction(transaction::Hints hints) {
|
|||
|
||||
/// @brief commit a transaction
|
||||
Result MMFilesTransactionState::commitTransaction(transaction::Methods* activeTrx) {
|
||||
LOG_TRX(this, _nestingLevel)
|
||||
LOG_TRX(this, nestingLevel())
|
||||
<< "committing " << AccessMode::typeString(_type) << " transaction";
|
||||
TRI_ASSERT(_status == transaction::Status::RUNNING);
|
||||
|
||||
Result result;
|
||||
if (_nestingLevel == 0) {
|
||||
if (nestingLevel() == 0) {
|
||||
if (_rocksTransaction != nullptr) {
|
||||
auto status = _rocksTransaction->Commit();
|
||||
result = rocksutils::convertStatus(status);
|
||||
|
@ -177,20 +178,20 @@ Result MMFilesTransactionState::commitTransaction(transaction::Methods* activeTr
|
|||
freeOperations(activeTrx);
|
||||
}
|
||||
|
||||
unuseCollections(_nestingLevel);
|
||||
unuseCollections(nestingLevel());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// @brief abort and rollback a transaction
|
||||
Result MMFilesTransactionState::abortTransaction(transaction::Methods* activeTrx) {
|
||||
LOG_TRX(this, _nestingLevel) << "aborting " << AccessMode::typeString(_type) << " transaction";
|
||||
LOG_TRX(this, nestingLevel()) << "aborting " << AccessMode::typeString(_type) << " transaction";
|
||||
|
||||
TRI_ASSERT(_status == transaction::Status::RUNNING);
|
||||
|
||||
Result result;
|
||||
|
||||
if (_nestingLevel == 0) {
|
||||
if (nestingLevel() == 0) {
|
||||
int res = writeAbortMarker();
|
||||
result.reset(res);
|
||||
|
||||
|
@ -205,7 +206,7 @@ Result MMFilesTransactionState::abortTransaction(transaction::Methods* activeTrx
|
|||
freeOperations(activeTrx);
|
||||
}
|
||||
|
||||
unuseCollections(_nestingLevel);
|
||||
unuseCollections(nestingLevel());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -497,7 +498,7 @@ int MMFilesTransactionState::writeCommitMarker() {
|
|||
// also sync RocksDB WAL if required
|
||||
bool hasPersistentIndex = false;
|
||||
|
||||
allCollections([&hasPersistentIndex](TransactionCollection& collection)->bool {
|
||||
allCollections([&hasPersistentIndex](TransactionCollection& collection) -> bool {
|
||||
auto* c = static_cast<MMFilesTransactionCollection*>(&collection);
|
||||
|
||||
if (c->canAccess(AccessMode::Type::WRITE) &&
|
||||
|
|
|
@ -26,36 +26,19 @@
|
|||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/Result.h"
|
||||
#include "Basics/SmallVector.h"
|
||||
#include "StorageEngine/TransactionState.h"
|
||||
#include "Transaction/Hints.h"
|
||||
#include "Transaction/Methods.h"
|
||||
#include "VocBase/AccessMode.h"
|
||||
#include "VocBase/LocalDocumentId.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
struct TRI_vocbase_t;
|
||||
|
||||
namespace rocksdb {
|
||||
|
||||
class Transaction;
|
||||
}
|
||||
|
||||
namespace arangodb {
|
||||
|
||||
class LocalDocumentId;
|
||||
class LogicalCollection;
|
||||
struct MMFilesDocumentOperation;
|
||||
class MMFilesWalMarker;
|
||||
|
||||
namespace transaction {
|
||||
|
||||
class Methods;
|
||||
struct Options;
|
||||
|
||||
} // namespace transaction
|
||||
|
||||
class TransactionCollection;
|
||||
|
||||
/// @brief transaction type
|
||||
class MMFilesTransactionState final : public TransactionState {
|
||||
public:
|
||||
|
@ -98,7 +81,7 @@ class MMFilesTransactionState final : public TransactionState {
|
|||
return (!isReadOnlyTransaction() && !isSingleOperation());
|
||||
}
|
||||
|
||||
return (_nestingLevel == 0 && _beginWritten && !isReadOnlyTransaction() &&
|
||||
return (isTopLevelTransaction() && _beginWritten && !isReadOnlyTransaction() &&
|
||||
!isSingleOperation());
|
||||
}
|
||||
|
||||
|
|
|
@ -379,16 +379,14 @@ void RestCollectionHandler::handleCommandPut() {
|
|||
opts.isSynchronousReplicationFrom =
|
||||
_request->value("isSynchronousReplication");
|
||||
|
||||
auto ctx = transaction::StandaloneContext::Create(_vocbase);
|
||||
SingleCollectionTransaction trx(ctx, *coll, AccessMode::Type::EXCLUSIVE);
|
||||
trx.addHint(transaction::Hints::Hint::INTERMEDIATE_COMMITS);
|
||||
trx.addHint(transaction::Hints::Hint::ALLOW_RANGE_DELETE);
|
||||
res = trx.begin();
|
||||
auto trx = createTransaction(coll->name(), AccessMode::Type::EXCLUSIVE);
|
||||
trx->addHint(transaction::Hints::Hint::INTERMEDIATE_COMMITS);
|
||||
trx->addHint(transaction::Hints::Hint::ALLOW_RANGE_DELETE);
|
||||
res = trx->begin();
|
||||
|
||||
if (res.ok()) {
|
||||
auto result = trx.truncate(coll->name(), opts);
|
||||
|
||||
res = trx.finish(result.result);
|
||||
auto result = trx->truncate(coll->name(), opts);
|
||||
res = trx->finish(result.result);
|
||||
}
|
||||
|
||||
if (res.ok()) {
|
||||
|
|
|
@ -194,8 +194,7 @@ bool RestEdgesHandler::readEdges() {
|
|||
VPackBuffer<uint8_t> buffer;
|
||||
VPackBuilder resultDocument(buffer);
|
||||
resultDocument.openObject();
|
||||
int res = getFilteredEdgesOnCoordinator(_vocbase.name(), collectionName,
|
||||
*(trx.get()), vertexString, direction,
|
||||
int res = getFilteredEdgesOnCoordinator(*trx, collectionName, vertexString, direction,
|
||||
responseCode, resultDocument);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -335,8 +334,7 @@ bool RestEdgesHandler::readEdgesForMultipleVertices() {
|
|||
for (auto const& it : VPackArrayIterator(body)) {
|
||||
if (it.isString()) {
|
||||
std::string vertexString(it.copyString());
|
||||
int res = getFilteredEdgesOnCoordinator(_vocbase.name(), collectionName,
|
||||
*(trx.get()), vertexString, direction,
|
||||
int res = getFilteredEdgesOnCoordinator(*trx, collectionName, vertexString, direction,
|
||||
responseCode, resultDocument);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
|
|
@ -1007,17 +1007,21 @@ Result RestReplicationHandler::processRestoreCollectionCoordinator(
|
|||
|| TRI_ERROR_CLUSTER_MUST_NOT_DROP_COLL_OTHER_DISTRIBUTESHARDSLIKE ==
|
||||
result.errorNumber()) {
|
||||
// some collections must not be dropped
|
||||
auto res = truncateCollectionOnCoordinator(dbName, name);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return Result(
|
||||
res,
|
||||
std::string(
|
||||
"unable to truncate collection (dropping is forbidden): '") +
|
||||
name + "'");
|
||||
auto ctx = transaction::StandaloneContext::Create(_vocbase);
|
||||
SingleCollectionTransaction trx(ctx, name, AccessMode::Type::EXCLUSIVE);
|
||||
|
||||
Result res = trx.begin();
|
||||
if (res.fail()) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return Result(res);
|
||||
|
||||
OperationOptions options;
|
||||
OperationResult result = trx.truncate(name, options);
|
||||
res = trx.finish(result.result);
|
||||
if (res.fail()) {
|
||||
res.appendErrorMessage(". Unable to truncate collection (dropping is forbidden)");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
if (!result.ok()) {
|
||||
|
|
|
@ -89,7 +89,6 @@
|
|||
#include "RestServer/ServerFeature.h"
|
||||
#include "RestServer/ServerIdFeature.h"
|
||||
#include "RestServer/SystemDatabaseFeature.h"
|
||||
#include "RestServer/TransactionManagerFeature.h"
|
||||
#include "RestServer/TraverserEngineRegistryFeature.h"
|
||||
#include "RestServer/TtlFeature.h"
|
||||
#include "RestServer/UpgradeFeature.h"
|
||||
|
@ -101,6 +100,7 @@
|
|||
#include "Statistics/StatisticsFeature.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/StorageEngineFeature.h"
|
||||
#include "Transaction/ManagerFeature.h"
|
||||
#include "V8Server/FoxxQueuesFeature.h"
|
||||
#include "V8Server/V8DealerFeature.h"
|
||||
|
||||
|
@ -213,7 +213,7 @@ static int runServer(int argc, char** argv, ArangoGlobalContext& context) {
|
|||
server.addFeature(new StorageEngineFeature(server));
|
||||
server.addFeature(new SystemDatabaseFeature(server));
|
||||
server.addFeature(new TempFeature(server, name));
|
||||
server.addFeature(new TransactionManagerFeature(server));
|
||||
server.addFeature(new transaction::ManagerFeature(server));
|
||||
server.addFeature(new TraverserEngineRegistryFeature(server));
|
||||
server.addFeature(new TtlFeature(server));
|
||||
server.addFeature(new UpgradeFeature(server, &ret, nonServerFeatures));
|
||||
|
|
|
@ -65,8 +65,6 @@
|
|||
#include "RocksDBEngine/RocksDBSyncThread.h"
|
||||
#include "RocksDBEngine/RocksDBThrottle.h"
|
||||
#include "RocksDBEngine/RocksDBTransactionCollection.h"
|
||||
#include "RocksDBEngine/RocksDBTransactionContextData.h"
|
||||
#include "RocksDBEngine/RocksDBTransactionManager.h"
|
||||
#include "RocksDBEngine/RocksDBTransactionState.h"
|
||||
#include "RocksDBEngine/RocksDBTypes.h"
|
||||
#include "RocksDBEngine/RocksDBUpgrade.h"
|
||||
|
@ -74,6 +72,8 @@
|
|||
#include "RocksDBEngine/RocksDBValue.h"
|
||||
#include "RocksDBEngine/RocksDBWalAccess.h"
|
||||
#include "Transaction/Context.h"
|
||||
#include "Transaction/ContextData.h"
|
||||
#include "Transaction/Manager.h"
|
||||
#include "Transaction/Options.h"
|
||||
#include "Transaction/StandaloneContext.h"
|
||||
#include "VocBase/LogicalView.h"
|
||||
|
@ -503,6 +503,7 @@ void RocksDBEngine::start() {
|
|||
static_cast<int>(opts->_blockCacheShardBits),
|
||||
/*strict_capacity_limit*/ opts->_enforceBlockCacheSizeLimit);
|
||||
// tableOptions.cache_index_and_filter_blocks =
|
||||
// tableOptions.pin_l0_filter_and_index_blocks_in_cache
|
||||
// opts->_compactionReadaheadSize > 0;
|
||||
} else {
|
||||
tableOptions.no_block_cache = true;
|
||||
|
@ -783,18 +784,17 @@ void RocksDBEngine::unprepare() {
|
|||
shutdownRocksDBInstance();
|
||||
}
|
||||
|
||||
std::unique_ptr<TransactionManager> RocksDBEngine::createTransactionManager() {
|
||||
return std::unique_ptr<TransactionManager>(new RocksDBTransactionManager());
|
||||
std::unique_ptr<transaction::Manager> RocksDBEngine::createTransactionManager() {
|
||||
return std::make_unique<transaction::Manager>(/*keepData*/ false);
|
||||
}
|
||||
|
||||
std::unique_ptr<transaction::ContextData> RocksDBEngine::createTransactionContextData() {
|
||||
return std::unique_ptr<transaction::ContextData>(new RocksDBTransactionContextData());
|
||||
return std::unique_ptr<transaction::ContextData>(nullptr); // not used by rocksdb
|
||||
}
|
||||
|
||||
std::unique_ptr<TransactionState> RocksDBEngine::createTransactionState(
|
||||
TRI_vocbase_t& vocbase, transaction::Options const& options) {
|
||||
return std::unique_ptr<TransactionState>(
|
||||
new RocksDBTransactionState(vocbase, TRI_NewTickServer(), options));
|
||||
TRI_vocbase_t& vocbase, TRI_voc_tid_t tid, transaction::Options const& options) {
|
||||
return std::make_unique<RocksDBTransactionState>(vocbase, tid, options);
|
||||
}
|
||||
|
||||
std::unique_ptr<TransactionCollection> RocksDBEngine::createTransactionCollection(
|
||||
|
|
|
@ -149,10 +149,10 @@ class RocksDBEngine final : public StorageEngine {
|
|||
bool supportsDfdb() const override { return false; }
|
||||
bool useRawDocumentPointers() override { return false; }
|
||||
|
||||
std::unique_ptr<TransactionManager> createTransactionManager() override;
|
||||
std::unique_ptr<transaction::Manager> createTransactionManager() override;
|
||||
std::unique_ptr<transaction::ContextData> createTransactionContextData() override;
|
||||
std::unique_ptr<TransactionState> createTransactionState(TRI_vocbase_t& vocbase,
|
||||
transaction::Options const& options) override;
|
||||
std::unique_ptr<TransactionState> createTransactionState(
|
||||
TRI_vocbase_t& vocbase, TRI_voc_tid_t, transaction::Options const& options) override;
|
||||
std::unique_ptr<TransactionCollection> createTransactionCollection(
|
||||
TransactionState& state, TRI_voc_cid_t cid, AccessMode::Type accessType,
|
||||
int nestingLevel) override;
|
||||
|
|
|
@ -244,11 +244,11 @@ void RocksDBAnyIndexIterator::reset() {
|
|||
return;
|
||||
}
|
||||
uint64_t steps = RandomGenerator::interval(_total - 1) % 500;
|
||||
auto initialKey = RocksDBKey();
|
||||
|
||||
initialKey.constructDocument(_objectId,
|
||||
LocalDocumentId(RandomGenerator::interval(UINT64_MAX)));
|
||||
_iterator->Seek(initialKey.string());
|
||||
|
||||
RocksDBKeyLeaser key(_trx);
|
||||
key->constructDocument(_objectId,
|
||||
LocalDocumentId(RandomGenerator::interval(UINT64_MAX)));
|
||||
_iterator->Seek(key->string());
|
||||
|
||||
if (checkIter()) {
|
||||
if (_forward) {
|
||||
|
|
|
@ -45,7 +45,7 @@ bool RocksDBKey::containsLocalDocumentId(LocalDocumentId const& documentId) cons
|
|||
std::string buffer;
|
||||
uint64ToPersistent(buffer, documentId.id());
|
||||
// and now check if the key actually contains this local document id
|
||||
return _buffer.find(buffer) != std::string::npos;
|
||||
return _buffer->find(buffer) != std::string::npos;
|
||||
}
|
||||
|
||||
default: {
|
||||
|
@ -61,37 +61,34 @@ void RocksDBKey::constructDatabase(TRI_voc_tick_t databaseId) {
|
|||
TRI_ASSERT(databaseId != 0);
|
||||
_type = RocksDBEntryType::Database;
|
||||
size_t keyLength = sizeof(char) + sizeof(uint64_t);
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
_buffer.push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(_buffer, databaseId);
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
_buffer->push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(*_buffer, databaseId);
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructCollection(TRI_voc_tick_t databaseId, TRI_voc_cid_t collectionId) {
|
||||
TRI_ASSERT(databaseId != 0 && collectionId != 0);
|
||||
_type = RocksDBEntryType::Collection;
|
||||
size_t keyLength = sizeof(char) + 2 * sizeof(uint64_t);
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
_buffer.push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(_buffer, databaseId);
|
||||
uint64ToPersistent(_buffer, collectionId);
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
_buffer->push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(*_buffer, databaseId);
|
||||
uint64ToPersistent(*_buffer, collectionId);
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructDocument(uint64_t objectId, LocalDocumentId documentId) {
|
||||
TRI_ASSERT(objectId != 0);
|
||||
_type = RocksDBEntryType::Document;
|
||||
size_t keyLength = 2 * sizeof(uint64_t);
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
uint64ToPersistent(_buffer, objectId);
|
||||
uint64ToPersistent(_buffer, documentId.id());
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
uint64ToPersistent(*_buffer, objectId);
|
||||
uint64ToPersistent(*_buffer, documentId.id());
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructPrimaryIndexValue(uint64_t indexId,
|
||||
|
@ -99,12 +96,11 @@ void RocksDBKey::constructPrimaryIndexValue(uint64_t indexId,
|
|||
TRI_ASSERT(indexId != 0 && !primaryKey.empty());
|
||||
_type = RocksDBEntryType::PrimaryIndexValue;
|
||||
size_t keyLength = sizeof(uint64_t) + primaryKey.size();
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
uint64ToPersistent(_buffer, indexId);
|
||||
_buffer.append(primaryKey.data(), primaryKey.size());
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
uint64ToPersistent(*_buffer, indexId);
|
||||
_buffer->append(primaryKey.data(), primaryKey.size());
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructPrimaryIndexValue(uint64_t indexId, char const* primaryKey) {
|
||||
|
@ -118,15 +114,14 @@ void RocksDBKey::constructEdgeIndexValue(uint64_t indexId, arangodb::velocypack:
|
|||
TRI_ASSERT(indexId != 0 && !vertexId.empty());
|
||||
_type = RocksDBEntryType::EdgeIndexValue;
|
||||
size_t keyLength = (sizeof(uint64_t) + sizeof(char)) * 2 + vertexId.size();
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
uint64ToPersistent(_buffer, indexId);
|
||||
_buffer.append(vertexId.data(), vertexId.length());
|
||||
_buffer.push_back(_stringSeparator);
|
||||
uint64ToPersistent(_buffer, documentId.id());
|
||||
_buffer.push_back(0xFFU); // high-byte for prefix extractor
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
uint64ToPersistent(*_buffer, indexId);
|
||||
_buffer->append(vertexId.data(), vertexId.length());
|
||||
_buffer->push_back(_stringSeparator);
|
||||
uint64ToPersistent(*_buffer, documentId.id());
|
||||
_buffer->push_back(0xFFU); // high-byte for prefix extractor
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructVPackIndexValue(uint64_t indexId, VPackSlice const& indexValues,
|
||||
|
@ -135,13 +130,12 @@ void RocksDBKey::constructVPackIndexValue(uint64_t indexId, VPackSlice const& in
|
|||
_type = RocksDBEntryType::VPackIndexValue;
|
||||
size_t const byteSize = static_cast<size_t>(indexValues.byteSize());
|
||||
size_t keyLength = 2 * sizeof(uint64_t) + byteSize;
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
uint64ToPersistent(_buffer, indexId);
|
||||
_buffer.append(reinterpret_cast<char const*>(indexValues.begin()), byteSize);
|
||||
uint64ToPersistent(_buffer, documentId.id());
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
uint64ToPersistent(*_buffer, indexId);
|
||||
_buffer->append(reinterpret_cast<char const*>(indexValues.begin()), byteSize);
|
||||
uint64ToPersistent(*_buffer, documentId.id());
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructUniqueVPackIndexValue(uint64_t indexId, VPackSlice const& indexValues) {
|
||||
|
@ -149,12 +143,11 @@ void RocksDBKey::constructUniqueVPackIndexValue(uint64_t indexId, VPackSlice con
|
|||
_type = RocksDBEntryType::UniqueVPackIndexValue;
|
||||
size_t const byteSize = static_cast<size_t>(indexValues.byteSize());
|
||||
size_t keyLength = sizeof(uint64_t) + byteSize;
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
uint64ToPersistent(_buffer, indexId);
|
||||
_buffer.append(reinterpret_cast<char const*>(indexValues.begin()), byteSize);
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
uint64ToPersistent(*_buffer, indexId);
|
||||
_buffer->append(reinterpret_cast<char const*>(indexValues.begin()), byteSize);
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructFulltextIndexValue(uint64_t indexId,
|
||||
|
@ -163,14 +156,13 @@ void RocksDBKey::constructFulltextIndexValue(uint64_t indexId,
|
|||
TRI_ASSERT(indexId != 0 && !word.empty());
|
||||
_type = RocksDBEntryType::FulltextIndexValue;
|
||||
size_t keyLength = sizeof(uint64_t) * 2 + word.size() + sizeof(char);
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
uint64ToPersistent(_buffer, indexId);
|
||||
_buffer.append(word.data(), word.length());
|
||||
_buffer.push_back(_stringSeparator);
|
||||
uint64ToPersistent(_buffer, documentId.id());
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
uint64ToPersistent(*_buffer, indexId);
|
||||
_buffer->append(word.data(), word.length());
|
||||
_buffer->push_back(_stringSeparator);
|
||||
uint64ToPersistent(*_buffer, documentId.id());
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -181,92 +173,85 @@ void RocksDBKey::constructGeoIndexValue(uint64_t indexId, uint64_t value,
|
|||
TRI_ASSERT(indexId != 0);
|
||||
_type = RocksDBEntryType::GeoIndexValue;
|
||||
size_t keyLength = 3 * sizeof(uint64_t);
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
uint64ToPersistent(_buffer, indexId);
|
||||
uintToPersistentBigEndian<uint64_t>(_buffer, value);
|
||||
uint64ToPersistent(_buffer, documentId.id());
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
uint64ToPersistent(*_buffer, indexId);
|
||||
uintToPersistentBigEndian<uint64_t>(*_buffer, value); // always big endian
|
||||
uint64ToPersistent(*_buffer, documentId.id());
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructView(TRI_voc_tick_t databaseId, TRI_voc_cid_t viewId) {
|
||||
TRI_ASSERT(databaseId != 0 && viewId != 0);
|
||||
_type = RocksDBEntryType::View;
|
||||
size_t keyLength = sizeof(char) + 2 * sizeof(uint64_t);
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
_buffer.push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(_buffer, databaseId);
|
||||
uint64ToPersistent(_buffer, viewId);
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
_buffer->push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(*_buffer, databaseId);
|
||||
uint64ToPersistent(*_buffer, viewId);
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructCounterValue(uint64_t objectId) {
|
||||
TRI_ASSERT(objectId != 0);
|
||||
_type = RocksDBEntryType::CounterValue;
|
||||
size_t keyLength = sizeof(char) + sizeof(uint64_t);
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
_buffer.push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(_buffer, objectId);
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
_buffer->push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(*_buffer, objectId);
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructSettingsValue(RocksDBSettingsType st) {
|
||||
TRI_ASSERT(st != RocksDBSettingsType::Invalid);
|
||||
_type = RocksDBEntryType::SettingsValue;
|
||||
size_t keyLength = 2;
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
_buffer.push_back(static_cast<char>(_type));
|
||||
_buffer.push_back(static_cast<char>(st));
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
_buffer->push_back(static_cast<char>(_type));
|
||||
_buffer->push_back(static_cast<char>(st));
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructReplicationApplierConfig(TRI_voc_tick_t databaseId) {
|
||||
// databaseId may be 0 for global applier config
|
||||
_type = RocksDBEntryType::ReplicationApplierConfig;
|
||||
size_t keyLength = sizeof(char) + sizeof(uint64_t);
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
_buffer.push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(_buffer, databaseId);
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
_buffer->push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(*_buffer, databaseId);
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructIndexEstimateValue(uint64_t collectionObjectId) {
|
||||
TRI_ASSERT(collectionObjectId != 0);
|
||||
_type = RocksDBEntryType::IndexEstimateValue;
|
||||
size_t keyLength = sizeof(char) + sizeof(uint64_t);
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
_buffer.push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(_buffer, collectionObjectId);
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
_buffer->push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(*_buffer, collectionObjectId);
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
void RocksDBKey::constructKeyGeneratorValue(uint64_t objectId) {
|
||||
TRI_ASSERT(objectId != 0);
|
||||
_type = RocksDBEntryType::KeyGeneratorValue;
|
||||
size_t keyLength = sizeof(char) + sizeof(uint64_t);
|
||||
_buffer.clear();
|
||||
_buffer.reserve(keyLength);
|
||||
_buffer.push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(_buffer, objectId);
|
||||
TRI_ASSERT(_buffer.size() == keyLength);
|
||||
_slice = rocksdb::Slice(_buffer.data(), keyLength);
|
||||
_buffer->clear();
|
||||
_buffer->reserve(keyLength);
|
||||
_buffer->push_back(static_cast<char>(_type));
|
||||
uint64ToPersistent(*_buffer, objectId);
|
||||
TRI_ASSERT(_buffer->size() == keyLength);
|
||||
}
|
||||
|
||||
// ========================= Member methods ===========================
|
||||
|
||||
RocksDBEntryType RocksDBKey::type(RocksDBKey const& key) {
|
||||
return type(key._buffer.data(), key._buffer.size());
|
||||
return type(key._buffer->data(), key._buffer->size());
|
||||
}
|
||||
|
||||
uint64_t RocksDBKey::definitionsObjectId(rocksdb::Slice const& s) {
|
||||
|
@ -275,7 +260,7 @@ uint64_t RocksDBKey::definitionsObjectId(rocksdb::Slice const& s) {
|
|||
}
|
||||
|
||||
TRI_voc_tick_t RocksDBKey::databaseId(RocksDBKey const& key) {
|
||||
return databaseId(key._buffer.data(), key._buffer.size());
|
||||
return databaseId(key._buffer->data(), key._buffer->size());
|
||||
}
|
||||
|
||||
TRI_voc_tick_t RocksDBKey::databaseId(rocksdb::Slice const& slice) {
|
||||
|
@ -283,7 +268,7 @@ TRI_voc_tick_t RocksDBKey::databaseId(rocksdb::Slice const& slice) {
|
|||
}
|
||||
|
||||
TRI_voc_cid_t RocksDBKey::collectionId(RocksDBKey const& key) {
|
||||
return collectionId(key._buffer.data(), key._buffer.size());
|
||||
return collectionId(key._buffer->data(), key._buffer->size());
|
||||
}
|
||||
|
||||
TRI_voc_cid_t RocksDBKey::collectionId(rocksdb::Slice const& slice) {
|
||||
|
@ -291,7 +276,7 @@ TRI_voc_cid_t RocksDBKey::collectionId(rocksdb::Slice const& slice) {
|
|||
}
|
||||
|
||||
uint64_t RocksDBKey::objectId(RocksDBKey const& key) {
|
||||
return objectId(key._buffer.data(), key._buffer.size());
|
||||
return objectId(key._buffer->data(), key._buffer->size());
|
||||
}
|
||||
|
||||
uint64_t RocksDBKey::objectId(rocksdb::Slice const& slice) {
|
||||
|
@ -299,7 +284,7 @@ uint64_t RocksDBKey::objectId(rocksdb::Slice const& slice) {
|
|||
}
|
||||
|
||||
TRI_voc_cid_t RocksDBKey::viewId(RocksDBKey const& key) {
|
||||
return viewId(key._buffer.data(), key._buffer.size());
|
||||
return viewId(key._buffer->data(), key._buffer->size());
|
||||
}
|
||||
|
||||
TRI_voc_cid_t RocksDBKey::viewId(rocksdb::Slice const& slice) {
|
||||
|
@ -340,7 +325,7 @@ LocalDocumentId RocksDBKey::indexDocumentId(RocksDBEntryType type,
|
|||
}
|
||||
|
||||
arangodb::velocypack::StringRef RocksDBKey::primaryKey(RocksDBKey const& key) {
|
||||
return primaryKey(key._buffer.data(), key._buffer.size());
|
||||
return primaryKey(key._buffer->data(), key._buffer->size());
|
||||
}
|
||||
|
||||
arangodb::velocypack::StringRef RocksDBKey::primaryKey(rocksdb::Slice const& slice) {
|
||||
|
@ -348,7 +333,7 @@ arangodb::velocypack::StringRef RocksDBKey::primaryKey(rocksdb::Slice const& sli
|
|||
}
|
||||
|
||||
arangodb::velocypack::StringRef RocksDBKey::vertexId(RocksDBKey const& key) {
|
||||
return vertexId(key._buffer.data(), key._buffer.size());
|
||||
return vertexId(key._buffer->data(), key._buffer->size());
|
||||
}
|
||||
|
||||
arangodb::velocypack::StringRef RocksDBKey::vertexId(rocksdb::Slice const& slice) {
|
||||
|
@ -356,7 +341,7 @@ arangodb::velocypack::StringRef RocksDBKey::vertexId(rocksdb::Slice const& slice
|
|||
}
|
||||
|
||||
VPackSlice RocksDBKey::indexedVPack(RocksDBKey const& key) {
|
||||
return indexedVPack(key._buffer.data(), key._buffer.size());
|
||||
return indexedVPack(key._buffer->data(), key._buffer->size());
|
||||
}
|
||||
|
||||
VPackSlice RocksDBKey::indexedVPack(rocksdb::Slice const& slice) {
|
||||
|
|
|
@ -42,22 +42,34 @@ class RocksDBKey {
|
|||
public:
|
||||
RocksDBKey()
|
||||
: _type(RocksDBEntryType::Document), // placeholder
|
||||
_buffer(),
|
||||
_slice() {}
|
||||
_local(),
|
||||
_buffer(&_local) {}
|
||||
|
||||
/// @brief construct a leased RocksDBKey
|
||||
/// @param leased will use _local std::string if nullptr
|
||||
explicit RocksDBKey(std::string* leased)
|
||||
: _type(RocksDBEntryType::Document), // placeholder
|
||||
_local(),
|
||||
_buffer(leased != nullptr ? leased : &_local) {}
|
||||
|
||||
explicit RocksDBKey(rocksdb::Slice slice)
|
||||
: _type(static_cast<RocksDBEntryType>(slice.data()[0])),
|
||||
_buffer(slice.data(), slice.size()),
|
||||
_slice(_buffer) {}
|
||||
_local(slice.data(), slice.size()),
|
||||
_buffer(&_local) {}
|
||||
|
||||
RocksDBKey(RocksDBKey&& other) noexcept
|
||||
: _type(other._type),
|
||||
_buffer(std::move(other._buffer)),
|
||||
_slice(_buffer.data(), other._slice.size()) {}
|
||||
_local(),
|
||||
_buffer(&_local) {
|
||||
_local.assign(std::move(*(other._buffer)));
|
||||
other._buffer = &(other._local);
|
||||
}
|
||||
|
||||
RocksDBKey& operator=(RocksDBKey const& other) = delete;
|
||||
RocksDBKey& operator=(RocksDBKey&& other) = delete;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/// @brief verify that a key actually contains the given local document id
|
||||
bool containsLocalDocumentId(LocalDocumentId const& id) const;
|
||||
|
||||
|
@ -264,12 +276,22 @@ class RocksDBKey {
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Returns a reference to the full, constructed key
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
rocksdb::Slice const& string() const { return _slice; }
|
||||
rocksdb::Slice string() const { return rocksdb::Slice(*_buffer); }
|
||||
|
||||
inline size_t size() const { return _slice.size(); }
|
||||
inline size_t size() const { return _buffer->size(); }
|
||||
|
||||
bool operator==(RocksDBKey const& other) const {
|
||||
return _type == other._type && _slice == other._slice;
|
||||
return _type == other._type && *_buffer == *(other._buffer);
|
||||
}
|
||||
|
||||
/// @brief does this use the inline buffer or a leased one
|
||||
inline bool usesInlineBuffer() const {
|
||||
return &_local == _buffer;
|
||||
}
|
||||
|
||||
/// @brief internal buffer string, unmanaged use carefully
|
||||
inline std::string* buffer() const {
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -309,9 +331,10 @@ class RocksDBKey {
|
|||
|
||||
private:
|
||||
static const char _stringSeparator;
|
||||
|
||||
RocksDBEntryType _type;
|
||||
std::string _buffer;
|
||||
rocksdb::Slice _slice;
|
||||
std::string _local; // local inline buffer
|
||||
std::string* _buffer;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream&, RocksDBKey const&);
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "Transaction/Context.h"
|
||||
#include "Transaction/Helpers.h"
|
||||
#include "Transaction/Methods.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "VocBase/LogicalCollection.h"
|
||||
|
||||
#include "RocksDBEngine/RocksDBPrefixExtractor.h"
|
||||
|
|
|
@ -48,6 +48,9 @@ class Snapshot;
|
|||
} // namespace rocksdb
|
||||
|
||||
namespace arangodb {
|
||||
namespace basics {
|
||||
class StringBuffer;
|
||||
}
|
||||
|
||||
class RocksDBReplicationContext {
|
||||
private:
|
||||
|
|
|
@ -21,16 +21,16 @@
|
|||
/// @author Jan Steemann
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RocksDBRestWalHandler.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "Cluster/ClusterMethods.h"
|
||||
#include "Cluster/ServerState.h"
|
||||
#include "RestServer/TransactionManagerFeature.h"
|
||||
#include "RocksDBEngine/RocksDBCommon.h"
|
||||
#include "RocksDBEngine/RocksDBEngine.h"
|
||||
#include "RocksDBRestWalHandler.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/TransactionManager.h"
|
||||
#include "Transaction/Manager.h"
|
||||
#include "Transaction/ManagerFeature.h"
|
||||
#include "Utils/ExecContext.h"
|
||||
|
||||
#include <rocksdb/utilities/transaction_db.h>
|
||||
|
@ -146,7 +146,7 @@ void RocksDBRestWalHandler::flush() {
|
|||
}
|
||||
|
||||
void RocksDBRestWalHandler::transactions() {
|
||||
TransactionManager* mngr = TransactionManagerFeature::manager();
|
||||
transaction::Manager* mngr = transaction::ManagerFeature::manager();
|
||||
VPackBuilder builder;
|
||||
builder.openObject();
|
||||
builder.add("runningTransactions", VPackValue(mngr->getActiveTransactionCount()));
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// 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_ROCKSDB_ROCKSDB_TRANSACTION_CONTEXT_DATA_H
|
||||
#define ARANGOD_ROCKSDB_ROCKSDB_TRANSACTION_CONTEXT_DATA_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Transaction/ContextData.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
namespace arangodb {
|
||||
class LogicalCollection;
|
||||
|
||||
/// @brief transaction type
|
||||
class RocksDBTransactionContextData final : public transaction::ContextData {
|
||||
public:
|
||||
RocksDBTransactionContextData() = default;
|
||||
~RocksDBTransactionContextData() = default;
|
||||
|
||||
/// @brief pin data for the collection
|
||||
/// there is nothing to do for the RocksDB engine
|
||||
void pinData(arangodb::LogicalCollection*) override {}
|
||||
|
||||
/// @brief whether or not the data for the collection is pinned
|
||||
/// note that this is always true in RocksDB
|
||||
bool isPinned(TRI_voc_cid_t) const override { return true; }
|
||||
};
|
||||
} // namespace arangodb
|
||||
|
||||
#endif
|
|
@ -1,76 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// 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_ROCKSDB_ROCKSDB_TRANSACTION_MANAGER_H
|
||||
#define ARANGOD_ROCKSDB_ROCKSDB_TRANSACTION_MANAGER_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/ReadWriteLock.h"
|
||||
#include "StorageEngine/TransactionManager.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
namespace arangodb {
|
||||
|
||||
class RocksDBTransactionManager final : public TransactionManager {
|
||||
public:
|
||||
RocksDBTransactionManager() : TransactionManager(), _nrRunning(0) {}
|
||||
~RocksDBTransactionManager() {}
|
||||
|
||||
// register a list of failed transactions
|
||||
void registerFailedTransactions(std::unordered_set<TRI_voc_tid_t> const& failedTransactions) override {
|
||||
}
|
||||
|
||||
// unregister a list of failed transactions
|
||||
void unregisterFailedTransactions(std::unordered_set<TRI_voc_tid_t> const& failedTransactions) override {
|
||||
}
|
||||
|
||||
// return the set of failed transactions
|
||||
std::unordered_set<TRI_voc_tid_t> getFailedTransactions() override {
|
||||
return std::unordered_set<TRI_voc_tid_t>();
|
||||
}
|
||||
|
||||
// register a transaction
|
||||
void registerTransaction(TRI_voc_tid_t transactionId,
|
||||
std::unique_ptr<TransactionData> data) override {
|
||||
TRI_ASSERT(data == nullptr);
|
||||
++_nrRunning;
|
||||
}
|
||||
|
||||
// unregister a transaction
|
||||
void unregisterTransaction(TRI_voc_tid_t transactionId, bool markAsFailed) override {
|
||||
TRI_ASSERT(_nrRunning > 0);
|
||||
--_nrRunning;
|
||||
}
|
||||
|
||||
// iterate all the active transactions
|
||||
void iterateActiveTransactions(
|
||||
std::function<void(TRI_voc_tid_t, TransactionData const*)> const& callback) override {}
|
||||
|
||||
uint64_t getActiveTransactionCount() override { return _nrRunning; }
|
||||
|
||||
private:
|
||||
std::atomic<uint64_t> _nrRunning;
|
||||
};
|
||||
} // namespace arangodb
|
||||
|
||||
#endif
|
|
@ -22,13 +22,13 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RocksDBTransactionState.h"
|
||||
|
||||
#include "Aql/QueryCache.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Cache/CacheManagerFeature.h"
|
||||
#include "Cache/Manager.h"
|
||||
#include "Cache/Transaction.h"
|
||||
#include "Logger/Logger.h"
|
||||
#include "RestServer/TransactionManagerFeature.h"
|
||||
#include "RocksDBEngine/RocksDBCollection.h"
|
||||
#include "RocksDBEngine/RocksDBCommon.h"
|
||||
#include "RocksDBEngine/RocksDBEngine.h"
|
||||
|
@ -39,7 +39,9 @@
|
|||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/StorageEngine.h"
|
||||
#include "StorageEngine/TransactionCollection.h"
|
||||
#include "StorageEngine/TransactionManager.h"
|
||||
#include "Transaction/Context.h"
|
||||
#include "Transaction/Manager.h"
|
||||
#include "Transaction/ManagerFeature.h"
|
||||
#include "Transaction/Methods.h"
|
||||
#include "Utils/ExecContext.h"
|
||||
#include "VocBase/LogicalCollection.h"
|
||||
|
@ -53,9 +55,6 @@
|
|||
|
||||
using namespace arangodb;
|
||||
|
||||
// for the RocksDB engine we do not need any additional data
|
||||
struct RocksDBTransactionData final : public TransactionData {};
|
||||
|
||||
/// @brief transaction type
|
||||
RocksDBTransactionState::RocksDBTransactionState(TRI_vocbase_t& vocbase, TRI_voc_tid_t tid,
|
||||
transaction::Options const& options)
|
||||
|
@ -67,52 +66,43 @@ RocksDBTransactionState::RocksDBTransactionState(TRI_vocbase_t& vocbase, TRI_voc
|
|||
_numInserts(0),
|
||||
_numUpdates(0),
|
||||
_numRemoves(0),
|
||||
_keys{_arena},
|
||||
_parallel(false) {}
|
||||
|
||||
/// @brief free a transaction container
|
||||
RocksDBTransactionState::~RocksDBTransactionState() {
|
||||
cleanupTransaction();
|
||||
for (auto& it : _keys) {
|
||||
delete it;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief start a transaction
|
||||
Result RocksDBTransactionState::beginTransaction(transaction::Hints hints) {
|
||||
LOG_TRX(this, _nestingLevel)
|
||||
LOG_TRX(this, nestingLevel())
|
||||
<< "beginning " << AccessMode::typeString(_type) << " transaction";
|
||||
|
||||
TRI_ASSERT(!hasHint(transaction::Hints::Hint::NO_USAGE_LOCK) ||
|
||||
!AccessMode::isWriteOrExclusive(_type));
|
||||
|
||||
if (_nestingLevel == 0) {
|
||||
// set hints
|
||||
_hints = hints;
|
||||
if (nestingLevel() == 0) {
|
||||
_hints = hints; // set hints before useCollections
|
||||
}
|
||||
|
||||
Result result = useCollections(_nestingLevel);
|
||||
|
||||
Result result = useCollections(nestingLevel());
|
||||
if (result.fail()) {
|
||||
// something is wrong
|
||||
if (_nestingLevel == 0) {
|
||||
if (nestingLevel() == 0) {
|
||||
updateStatus(transaction::Status::ABORTED);
|
||||
}
|
||||
|
||||
// free what we have got so far
|
||||
unuseCollections(_nestingLevel);
|
||||
unuseCollections(nestingLevel());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// all valid
|
||||
if (_nestingLevel == 0) {
|
||||
if (nestingLevel() == 0) { // result is valid
|
||||
// register with manager
|
||||
transaction::ManagerFeature::manager()->registerTransaction(id(), nullptr);
|
||||
updateStatus(transaction::Status::RUNNING);
|
||||
|
||||
// register a protector (intentionally empty)
|
||||
TransactionManagerFeature::manager()->registerTransaction(
|
||||
_id, std::unique_ptr<RocksDBTransactionData>());
|
||||
|
||||
setRegistered();
|
||||
|
||||
TRI_ASSERT(_rocksTransaction == nullptr);
|
||||
|
@ -383,7 +373,7 @@ arangodb::Result RocksDBTransactionState::internalCommit() {
|
|||
|
||||
/// @brief commit a transaction
|
||||
Result RocksDBTransactionState::commitTransaction(transaction::Methods* activeTrx) {
|
||||
LOG_TRX(this, _nestingLevel)
|
||||
LOG_TRX(this, nestingLevel())
|
||||
<< "committing " << AccessMode::typeString(_type) << " transaction";
|
||||
|
||||
TRI_ASSERT(_status == transaction::Status::RUNNING);
|
||||
|
@ -392,7 +382,7 @@ Result RocksDBTransactionState::commitTransaction(transaction::Methods* activeTr
|
|||
}
|
||||
|
||||
arangodb::Result res;
|
||||
if (_nestingLevel == 0) {
|
||||
if (nestingLevel() == 0) {
|
||||
if (_rocksTransaction != nullptr) {
|
||||
res = internalCommit();
|
||||
}
|
||||
|
@ -405,16 +395,16 @@ Result RocksDBTransactionState::commitTransaction(transaction::Methods* activeTr
|
|||
TRI_ASSERT(!_rocksTransaction && !_cacheTx && !_readSnapshot);
|
||||
}
|
||||
|
||||
unuseCollections(_nestingLevel);
|
||||
unuseCollections(nestingLevel());
|
||||
return res;
|
||||
}
|
||||
|
||||
/// @brief abort and rollback a transaction
|
||||
Result RocksDBTransactionState::abortTransaction(transaction::Methods* activeTrx) {
|
||||
LOG_TRX(this, _nestingLevel) << "aborting " << AccessMode::typeString(_type) << " transaction";
|
||||
LOG_TRX(this, nestingLevel()) << "aborting " << AccessMode::typeString(_type) << " transaction";
|
||||
TRI_ASSERT(_status == transaction::Status::RUNNING);
|
||||
Result result;
|
||||
if (_nestingLevel == 0) {
|
||||
if (nestingLevel() == 0) {
|
||||
if (_rocksTransaction != nullptr) {
|
||||
rocksdb::Status status = _rocksTransaction->Rollback();
|
||||
result = rocksutils::convertStatus(status);
|
||||
|
@ -430,7 +420,7 @@ Result RocksDBTransactionState::abortTransaction(transaction::Methods* activeTrx
|
|||
TRI_ASSERT(!_rocksTransaction && !_cacheTx && !_readSnapshot);
|
||||
}
|
||||
|
||||
unuseCollections(_nestingLevel);
|
||||
unuseCollections(nestingLevel());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -625,31 +615,6 @@ Result RocksDBTransactionState::checkIntermediateCommit(uint64_t newSize, bool&
|
|||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
/// @brief temporarily lease a RocksDBKey object
|
||||
RocksDBKey* RocksDBTransactionState::leaseRocksDBKey() {
|
||||
if (_keys.empty()) {
|
||||
// create a new key and return it
|
||||
return new RocksDBKey();
|
||||
}
|
||||
|
||||
// re-use an existing builder
|
||||
RocksDBKey* k = _keys.back();
|
||||
_keys.pop_back();
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
/// @brief return a temporary RocksDBKey object
|
||||
void RocksDBTransactionState::returnRocksDBKey(RocksDBKey* key) noexcept {
|
||||
try {
|
||||
// put key back into our vector of keys
|
||||
_keys.emplace_back(key);
|
||||
} catch (...) {
|
||||
// no harm done. just wipe the key
|
||||
delete key;
|
||||
}
|
||||
}
|
||||
|
||||
void RocksDBTransactionState::trackIndexInsert(TRI_voc_cid_t cid,
|
||||
TRI_idx_iid_t idxId, uint64_t hash) {
|
||||
auto col = findCollection(cid);
|
||||
|
@ -672,15 +637,15 @@ void RocksDBTransactionState::trackIndexRemove(TRI_voc_cid_t cid,
|
|||
|
||||
/// @brief constructor, leases a builder
|
||||
RocksDBKeyLeaser::RocksDBKeyLeaser(transaction::Methods* trx)
|
||||
: _rtrx(RocksDBTransactionState::toState(trx)),
|
||||
_parallel(_rtrx->inParallelMode()),
|
||||
_key(_parallel ? &_internal : _rtrx->leaseRocksDBKey()) {
|
||||
TRI_ASSERT(_key != nullptr);
|
||||
: _ctx(trx->transactionContextPtr()),
|
||||
_key(RocksDBTransactionState::toState(trx)->inParallelMode() ? nullptr : _ctx->leaseString()) {
|
||||
TRI_ASSERT(_ctx != nullptr);
|
||||
TRI_ASSERT(_key.buffer() != nullptr);
|
||||
}
|
||||
|
||||
/// @brief destructor
|
||||
RocksDBKeyLeaser::~RocksDBKeyLeaser() {
|
||||
if (!_parallel && _key != nullptr) {
|
||||
_rtrx->returnRocksDBKey(_key);
|
||||
if (!_key.usesInlineBuffer()) {
|
||||
_ctx->returnString(_key.buffer());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,20 +49,11 @@ class Iterator;
|
|||
namespace arangodb {
|
||||
|
||||
namespace cache {
|
||||
|
||||
struct Transaction;
|
||||
}
|
||||
|
||||
class LogicalCollection;
|
||||
struct RocksDBDocumentOperation;
|
||||
|
||||
namespace transaction {
|
||||
|
||||
class Methods;
|
||||
struct Options;
|
||||
|
||||
} // namespace transaction
|
||||
|
||||
class RocksDBMethods;
|
||||
|
||||
/// @brief transaction type
|
||||
|
@ -144,10 +135,6 @@ class RocksDBTransactionState final : public TransactionState {
|
|||
void prepareForParallelReads() { _parallel = true; }
|
||||
/// @brief in parallel mode. READ-ONLY transactions
|
||||
bool inParallelMode() const { return _parallel; }
|
||||
/// @brief temporarily lease a Builder object. Not thread safe
|
||||
RocksDBKey* leaseRocksDBKey();
|
||||
/// @brief return a temporary RocksDBKey object. Not thread safe
|
||||
void returnRocksDBKey(RocksDBKey* key) noexcept;
|
||||
|
||||
/// @brief Every index can track hashes inserted into this index
|
||||
/// Used to update the estimate after the trx committed
|
||||
|
@ -202,9 +189,7 @@ class RocksDBTransactionState final : public TransactionState {
|
|||
uint64_t _numUpdates;
|
||||
uint64_t _numRemoves;
|
||||
|
||||
SmallVector<RocksDBKey*, 32>::allocator_type::arena_type _arena;
|
||||
SmallVector<RocksDBKey*, 32> _keys;
|
||||
/// @brief if true the key buffers will no longer be shared
|
||||
/// @brief if true there key buffers will no longer be shared
|
||||
bool _parallel;
|
||||
};
|
||||
|
||||
|
@ -212,16 +197,14 @@ class RocksDBKeyLeaser {
|
|||
public:
|
||||
explicit RocksDBKeyLeaser(transaction::Methods*);
|
||||
~RocksDBKeyLeaser();
|
||||
inline RocksDBKey* builder() const { return _key; }
|
||||
inline RocksDBKey* operator->() const { return _key; }
|
||||
inline RocksDBKey* get() const { return _key; }
|
||||
inline RocksDBKey& ref() const { return *_key; }
|
||||
inline RocksDBKey* builder() { return &_key; }
|
||||
inline RocksDBKey* operator->() { return &_key; }
|
||||
inline RocksDBKey* get() { return &_key; }
|
||||
inline RocksDBKey& ref() { return _key; }
|
||||
|
||||
private:
|
||||
RocksDBTransactionState* _rtrx;
|
||||
bool _parallel;
|
||||
RocksDBKey* _key;
|
||||
RocksDBKey _internal;
|
||||
transaction::Context* _ctx;
|
||||
RocksDBKey _key;
|
||||
};
|
||||
|
||||
} // namespace arangodb
|
||||
|
|
|
@ -679,7 +679,7 @@ Result RocksDBVPackIndex::insert(transaction::Methods& trx, RocksDBMethods* mthd
|
|||
}
|
||||
}
|
||||
|
||||
IndexingDisabler guard(mthds, !_unique && trx.hasHint(transaction::Hints::Hint::FROM_TOPLEVEL_AQL));
|
||||
IndexingDisabler guard(mthds, !_unique && trx.state()->hasHint(transaction::Hints::Hint::FROM_TOPLEVEL_AQL));
|
||||
|
||||
// now we are going to construct the value to insert into rocksdb
|
||||
// unique indexes have a different key structure
|
||||
|
@ -831,7 +831,7 @@ Result RocksDBVPackIndex::remove(transaction::Methods& trx, RocksDBMethods* mthd
|
|||
}
|
||||
}
|
||||
|
||||
IndexingDisabler guard(mthds, !_unique && trx.hasHint(transaction::Hints::Hint::FROM_TOPLEVEL_AQL));
|
||||
IndexingDisabler guard(mthds, !_unique && trx.state()->hasHint(transaction::Hints::Hint::FROM_TOPLEVEL_AQL));
|
||||
|
||||
size_t const count = elements.size();
|
||||
|
||||
|
|
|
@ -47,12 +47,10 @@ class PhysicalCollection;
|
|||
class PhysicalView;
|
||||
class Result;
|
||||
class TransactionCollection;
|
||||
class TransactionManager;
|
||||
class TransactionState;
|
||||
class WalAccess;
|
||||
|
||||
namespace rest {
|
||||
|
||||
class RestHandlerFactory;
|
||||
}
|
||||
|
||||
|
@ -60,6 +58,7 @@ namespace transaction {
|
|||
|
||||
class Context;
|
||||
class ContextData;
|
||||
class Manager;
|
||||
struct Options;
|
||||
|
||||
} // namespace transaction
|
||||
|
@ -88,10 +87,10 @@ class StorageEngine : public application_features::ApplicationFeature {
|
|||
|
||||
virtual bool supportsDfdb() const = 0;
|
||||
|
||||
virtual std::unique_ptr<TransactionManager> createTransactionManager() = 0;
|
||||
virtual std::unique_ptr<transaction::Manager> createTransactionManager() = 0;
|
||||
virtual std::unique_ptr<transaction::ContextData> createTransactionContextData() = 0;
|
||||
virtual std::unique_ptr<TransactionState> createTransactionState(
|
||||
TRI_vocbase_t& vocbase, transaction::Options const& options) = 0;
|
||||
TRI_vocbase_t& vocbase, TRI_voc_tid_t, transaction::Options const& options) = 0;
|
||||
virtual std::unique_ptr<TransactionCollection> createTransactionCollection(
|
||||
TransactionState& state, TRI_voc_cid_t cid, AccessMode::Type accessType,
|
||||
int nestingLevel) = 0;
|
||||
|
|
|
@ -54,7 +54,7 @@ class TransactionCollection {
|
|||
inline TRI_voc_cid_t id() const { return _cid; }
|
||||
|
||||
std::shared_ptr<LogicalCollection> const& collection() const {
|
||||
return _collection; // vocbase collection pointer
|
||||
return _collection; // vocbase collection pointer
|
||||
}
|
||||
|
||||
std::string collectionName() const;
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// 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_STORAGE_ENGINE_TRANSACTION_MANAGER_H
|
||||
#define ARANGOD_STORAGE_ENGINE_TRANSACTION_MANAGER_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
namespace arangodb {
|
||||
|
||||
// to be derived by storage engines
|
||||
struct TransactionData {
|
||||
virtual ~TransactionData() = default;
|
||||
};
|
||||
|
||||
class TransactionManager {
|
||||
public:
|
||||
TransactionManager() {}
|
||||
virtual ~TransactionManager() {}
|
||||
|
||||
// register a list of failed transactions
|
||||
virtual void registerFailedTransactions(std::unordered_set<TRI_voc_tid_t> const& failedTransactions) = 0;
|
||||
|
||||
// unregister a list of failed transactions
|
||||
virtual void unregisterFailedTransactions(std::unordered_set<TRI_voc_tid_t> const& failedTransactions) = 0;
|
||||
|
||||
// return the set of failed transactions
|
||||
virtual std::unordered_set<TRI_voc_tid_t> getFailedTransactions() = 0;
|
||||
|
||||
// register a transaction
|
||||
virtual void registerTransaction(TRI_voc_tid_t transactionId,
|
||||
std::unique_ptr<TransactionData> data) = 0;
|
||||
|
||||
// unregister a transaction
|
||||
virtual void unregisterTransaction(TRI_voc_tid_t transactionId, bool markAsFailed) = 0;
|
||||
|
||||
// iterate all the active transactions
|
||||
virtual void iterateActiveTransactions(
|
||||
std::function<void(TRI_voc_tid_t, TransactionData const*)> const& callback) = 0;
|
||||
|
||||
virtual uint64_t getActiveTransactionCount() = 0;
|
||||
};
|
||||
|
||||
} // namespace arangodb
|
||||
|
||||
#endif
|
|
@ -22,12 +22,14 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "TransactionState.h"
|
||||
|
||||
#include "Aql/QueryCache.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Logger/Logger.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/StorageEngine.h"
|
||||
#include "StorageEngine/TransactionCollection.h"
|
||||
#include "Transaction/Context.h"
|
||||
#include "Transaction/Methods.h"
|
||||
#include "Transaction/Options.h"
|
||||
#include "Utils/ExecContext.h"
|
||||
|
@ -47,9 +49,9 @@ TransactionState::TransactionState(TRI_vocbase_t& vocbase, TRI_voc_tid_t tid,
|
|||
_collections{_arena}, // assign arena to vector
|
||||
_serverRole(ServerState::instance()->getRole()),
|
||||
_hints(),
|
||||
_options(options),
|
||||
_nestingLevel(0),
|
||||
_registeredTransaction(false),
|
||||
_options(options) {}
|
||||
_registeredTransaction(false) {}
|
||||
|
||||
/// @brief free a transaction container
|
||||
TransactionState::~TransactionState() {
|
||||
|
@ -124,7 +126,7 @@ int TransactionState::addCollection(TRI_voc_cid_t cid, std::string const& cname,
|
|||
"AccessMode::Type total order fail");
|
||||
// we may need to recheck permissions here
|
||||
if (trxCollection->accessType() < accessType) {
|
||||
int res = checkCollectionPermission(cid, cname, accessType);
|
||||
int res = checkCollectionPermission(cname, accessType);
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
@ -146,7 +148,7 @@ int TransactionState::addCollection(TRI_voc_cid_t cid, std::string const& cname,
|
|||
}
|
||||
|
||||
// now check the permissions
|
||||
int res = checkCollectionPermission(cid, cname, accessType);
|
||||
int res = checkCollectionPermission(cname, accessType);
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
@ -179,11 +181,11 @@ Result TransactionState::ensureCollections(int nestingLevel) {
|
|||
}
|
||||
|
||||
/// @brief run a callback on all collections
|
||||
void TransactionState::allCollections( // iterate
|
||||
std::function<bool(TransactionCollection&)> const& cb // callback to invoke
|
||||
void TransactionState::allCollections( // iterate
|
||||
std::function<bool(TransactionCollection&)> const& cb // callback to invoke
|
||||
) {
|
||||
for (auto& trxCollection : _collections) {
|
||||
TRI_ASSERT(trxCollection); // ensured by addCollection(...)
|
||||
TRI_ASSERT(trxCollection); // ensured by addCollection(...)
|
||||
if (!cb(*trxCollection)) {
|
||||
// abort early
|
||||
return;
|
||||
|
@ -321,8 +323,9 @@ bool TransactionState::isOnlyExclusiveTransaction() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
int TransactionState::checkCollectionPermission(TRI_voc_cid_t cid, std::string const& cname,
|
||||
int TransactionState::checkCollectionPermission(std::string const& cname,
|
||||
AccessMode::Type accessType) const {
|
||||
TRI_ASSERT(!cname.empty());
|
||||
ExecContext const* exec = ExecContext::CURRENT;
|
||||
|
||||
// no need to check for superuser, cluster_sync tests break otherwise
|
||||
|
@ -376,10 +379,10 @@ void TransactionState::clearQueryCache() {
|
|||
std::vector<std::string> collections;
|
||||
|
||||
for (auto& trxCollection : _collections) {
|
||||
if (trxCollection // valid instance
|
||||
&& trxCollection->collection() // has a valid collection
|
||||
&& trxCollection->hasOperations() // may have been modified
|
||||
) {
|
||||
if (trxCollection // valid instance
|
||||
&& trxCollection->collection() // has a valid collection
|
||||
&& trxCollection->hasOperations() // may have been modified
|
||||
) {
|
||||
// we're only interested in collections that may have been modified
|
||||
collections.emplace_back(trxCollection->collection()->guid());
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "Transaction/Hints.h"
|
||||
#include "Transaction/Options.h"
|
||||
#include "Transaction/Status.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "VocBase/AccessMode.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
|
@ -54,10 +53,9 @@ struct TRI_vocbase_t;
|
|||
namespace arangodb {
|
||||
|
||||
namespace transaction {
|
||||
|
||||
class Context;
|
||||
class Methods;
|
||||
struct Options;
|
||||
|
||||
} // namespace transaction
|
||||
|
||||
class ExecContext;
|
||||
|
@ -108,11 +106,11 @@ class TransactionState {
|
|||
|
||||
int increaseNesting() { return ++_nestingLevel; }
|
||||
int decreaseNesting() {
|
||||
TRI_ASSERT(_nestingLevel > 0);
|
||||
TRI_ASSERT(nestingLevel() > 0);
|
||||
return --_nestingLevel;
|
||||
}
|
||||
int nestingLevel() const { return _nestingLevel; }
|
||||
bool isTopLevelTransaction() const { return _nestingLevel == 0; }
|
||||
bool isTopLevelTransaction() const { return nestingLevel() == 0; }
|
||||
bool isEmbeddedTransaction() const { return !isTopLevelTransaction(); }
|
||||
|
||||
double timeout() const { return _options.lockTimeout; }
|
||||
|
@ -220,8 +218,7 @@ class TransactionState {
|
|||
TransactionCollection* findCollection(TRI_voc_cid_t cid, size_t& position) const;
|
||||
|
||||
/// @brief check if current user can access this collection
|
||||
int checkCollectionPermission(TRI_voc_cid_t cid, std::string const& cname,
|
||||
AccessMode::Type) const;
|
||||
int checkCollectionPermission(std::string const& cname, AccessMode::Type) const;
|
||||
|
||||
/// @brief release collection locks for a transaction
|
||||
int releaseCollections();
|
||||
|
@ -230,11 +227,10 @@ class TransactionState {
|
|||
/// the transaction
|
||||
void clearQueryCache();
|
||||
|
||||
/// @brief vocbase for this transaction
|
||||
TRI_vocbase_t& _vocbase;
|
||||
protected:
|
||||
TRI_vocbase_t& _vocbase; /// @brief vocbase for this transaction
|
||||
TRI_voc_tid_t const _id; /// @brief local trx id
|
||||
|
||||
/// @brief local trx id
|
||||
TRI_voc_tid_t const _id;
|
||||
/// @brief access type (read|write)
|
||||
AccessMode::Type _type;
|
||||
/// @brief current status
|
||||
|
@ -243,11 +239,9 @@ class TransactionState {
|
|||
SmallVector<TransactionCollection*>::allocator_type::arena_type _arena; // memory for collections
|
||||
SmallVector<TransactionCollection*> _collections; // list of participating collections
|
||||
|
||||
ServerState::RoleEnum const _serverRole; // role of the server
|
||||
ServerState::RoleEnum const _serverRole; /// role of the server
|
||||
|
||||
transaction::Hints _hints; // hints;
|
||||
int _nestingLevel;
|
||||
bool _registeredTransaction;
|
||||
transaction::Hints _hints; // hints; set on _nestingLevel == 0
|
||||
|
||||
transaction::Options _options;
|
||||
|
||||
|
@ -257,6 +251,10 @@ class TransactionState {
|
|||
|
||||
/// the list of locked shards (cluster only)
|
||||
std::unordered_set<std::string> _lockedShards;
|
||||
/// @brief reference counter of # of 'Methods' instances using this object
|
||||
int _nestingLevel;
|
||||
|
||||
bool _registeredTransaction;
|
||||
};
|
||||
|
||||
} // namespace arangodb
|
||||
|
|
|
@ -22,13 +22,15 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Context.h"
|
||||
|
||||
#include "Basics/StringBuffer.h"
|
||||
#include "RestServer/TransactionManagerFeature.h"
|
||||
#include "Cluster/ClusterInfo.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/StorageEngine.h"
|
||||
#include "StorageEngine/TransactionManager.h"
|
||||
#include "Transaction/ContextData.h"
|
||||
#include "Transaction/Helpers.h"
|
||||
#include "Transaction/Manager.h"
|
||||
#include "Transaction/ManagerFeature.h"
|
||||
#include "Transaction/Methods.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "VocBase/LogicalCollection.h"
|
||||
|
@ -69,7 +71,7 @@ transaction::Context::Context(TRI_vocbase_t& vocbase)
|
|||
_stringBuffer(),
|
||||
_options(arangodb::velocypack::Options::Defaults),
|
||||
_dumpOptions(arangodb::velocypack::Options::Defaults),
|
||||
_transaction{0, false, false},
|
||||
_transaction{0, false},
|
||||
_ownsResolver(false) {
|
||||
/// dump options contain have the escapeUnicode attribute set to true
|
||||
/// this allows dumping of string values as plain 7-bit ASCII values.
|
||||
|
@ -78,14 +80,16 @@ transaction::Context::Context(TRI_vocbase_t& vocbase)
|
|||
/// which speculate on ASCII strings first and only fall back to slower
|
||||
/// multibyte strings on first actual occurrence of a multibyte character.
|
||||
_dumpOptions.escapeUnicode = true;
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
_contextData = engine->createTransactionContextData();
|
||||
}
|
||||
|
||||
/// @brief destroy the context
|
||||
transaction::Context::~Context() {
|
||||
// unregister the transaction from the logfile manager
|
||||
if (_transaction.id > 0 && _transaction.wasRegistered) {
|
||||
TransactionManagerFeature::manager()->unregisterTransaction(_transaction.id,
|
||||
_transaction.hasFailedOperations);
|
||||
if (_transaction.id > 0) {
|
||||
transaction::ManagerFeature::manager()->unregisterTransaction(_transaction.id,
|
||||
_transaction.hasFailedOperations);
|
||||
}
|
||||
|
||||
// free all VPackBuilders we handed out
|
||||
|
@ -108,12 +112,17 @@ VPackCustomTypeHandler* transaction::Context::createCustomTypeHandler(
|
|||
|
||||
/// @brief pin data for the collection
|
||||
void transaction::Context::pinData(LogicalCollection* collection) {
|
||||
contextData()->pinData(collection);
|
||||
if (_contextData) {
|
||||
_contextData->pinData(collection);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief whether or not the data for the collection is pinned
|
||||
bool transaction::Context::isPinned(TRI_voc_cid_t cid) {
|
||||
return contextData()->isPinned(cid);
|
||||
if (_contextData) {
|
||||
return _contextData->isPinned(cid);
|
||||
}
|
||||
return true; // storage engine does not need pinning
|
||||
}
|
||||
|
||||
/// @brief temporarily lease a StringBuffer object
|
||||
|
@ -132,6 +141,22 @@ void transaction::Context::returnStringBuffer(basics::StringBuffer* stringBuffer
|
|||
_stringBuffer.reset(stringBuffer);
|
||||
}
|
||||
|
||||
/// @brief temporarily lease a std::string
|
||||
std::string* transaction::Context::leaseString() {
|
||||
if (_stdString == nullptr) {
|
||||
_stdString.reset(new std::string());
|
||||
} else {
|
||||
_stdString->clear();
|
||||
}
|
||||
|
||||
return _stdString.release();
|
||||
}
|
||||
|
||||
/// @brief return a temporary std::string object
|
||||
void transaction::Context::returnString(std::string* str) {
|
||||
_stdString.reset(str);
|
||||
}
|
||||
|
||||
/// @brief temporarily lease a Builder object
|
||||
VPackBuilder* transaction::Context::leaseBuilder() {
|
||||
if (_builders.empty()) {
|
||||
|
@ -195,22 +220,16 @@ CollectionNameResolver const* transaction::Context::createResolver() {
|
|||
|
||||
/// @brief unregister the transaction
|
||||
/// this will save the transaction's id and status locally
|
||||
void transaction::Context::storeTransactionResult(TRI_voc_tid_t id,
|
||||
bool hasFailedOperations,
|
||||
void transaction::Context::storeTransactionResult(TRI_voc_tid_t id, bool hasFailedOperations,
|
||||
bool wasRegistered) noexcept {
|
||||
TRI_ASSERT(_transaction.id == 0);
|
||||
|
||||
_transaction.id = id;
|
||||
_transaction.hasFailedOperations = hasFailedOperations;
|
||||
_transaction.wasRegistered = wasRegistered;
|
||||
}
|
||||
|
||||
transaction::ContextData* transaction::Context::contextData() {
|
||||
if (_contextData == nullptr) {
|
||||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
|
||||
_contextData = engine->createTransactionContextData();
|
||||
if (wasRegistered) {
|
||||
_transaction.id = id;
|
||||
_transaction.hasFailedOperations = hasFailedOperations;
|
||||
}
|
||||
|
||||
return _contextData.get();
|
||||
}
|
||||
|
||||
TRI_voc_tid_t transaction::Context::generateId() const {
|
||||
return TRI_NewTickServer();
|
||||
}
|
||||
|
|
|
@ -84,6 +84,12 @@ class Context {
|
|||
/// @brief return a temporary StringBuffer object
|
||||
void returnStringBuffer(basics::StringBuffer* stringBuffer);
|
||||
|
||||
/// @brief temporarily lease a std::string
|
||||
std::string* leaseString();
|
||||
|
||||
/// @brief return a temporary std::string object
|
||||
void returnString(std::string* str);
|
||||
|
||||
/// @brief temporarily lease a Builder object
|
||||
arangodb::velocypack::Builder* leaseBuilder();
|
||||
|
||||
|
@ -98,12 +104,14 @@ class Context {
|
|||
|
||||
/// @brief unregister the transaction
|
||||
/// this will save the transaction's id and status locally
|
||||
void storeTransactionResult(TRI_voc_tid_t id, bool hasFailedOperations, bool wasRegistered) noexcept;
|
||||
void storeTransactionResult(TRI_voc_tid_t id, bool hasFailedOperations,
|
||||
bool wasRegistered) noexcept;
|
||||
|
||||
public:
|
||||
/// @brief get a custom type handler
|
||||
virtual std::shared_ptr<arangodb::velocypack::CustomTypeHandler> orderCustomTypeHandler() = 0;
|
||||
|
||||
/// @brief get parent transaction (if any)
|
||||
/// @brief get parent transaction (if any) increase nesting
|
||||
virtual TransactionState* getParentTransaction() const = 0;
|
||||
|
||||
/// @brief whether or not the transaction is embeddable
|
||||
|
@ -117,12 +125,14 @@ class Context {
|
|||
/// @brief unregister the transaction
|
||||
virtual void unregisterTransaction() noexcept = 0;
|
||||
|
||||
/// @brief generate persisted transaction ID
|
||||
virtual TRI_voc_tid_t generateId() const;
|
||||
|
||||
protected:
|
||||
/// @brief create a resolver
|
||||
CollectionNameResolver const* createResolver();
|
||||
|
||||
transaction::ContextData* contextData();
|
||||
|
||||
protected:
|
||||
TRI_vocbase_t& _vocbase;
|
||||
CollectionNameResolver const* _resolver;
|
||||
std::shared_ptr<velocypack::CustomTypeHandler> _customTypeHandler;
|
||||
|
@ -131,16 +141,17 @@ class Context {
|
|||
SmallVector<arangodb::velocypack::Builder*, 32> _builders;
|
||||
|
||||
std::unique_ptr<arangodb::basics::StringBuffer> _stringBuffer;
|
||||
std::unique_ptr<std::string> _stdString;
|
||||
|
||||
arangodb::velocypack::Options _options;
|
||||
arangodb::velocypack::Options _dumpOptions;
|
||||
|
||||
private:
|
||||
std::unique_ptr<transaction::ContextData> _contextData;
|
||||
|
||||
struct {
|
||||
TRI_voc_tid_t id;
|
||||
bool hasFailedOperations;
|
||||
bool wasRegistered;
|
||||
} _transaction;
|
||||
|
||||
bool _ownsResolver;
|
||||
|
|
|
@ -31,6 +31,9 @@ namespace arangodb {
|
|||
class LogicalCollection;
|
||||
|
||||
namespace transaction {
|
||||
|
||||
/// Storage engine specific data that shares the lifetime
|
||||
/// of the transaction::Context
|
||||
class ContextData {
|
||||
public:
|
||||
ContextData(ContextData const&) = delete;
|
||||
|
|
|
@ -424,6 +424,8 @@ std::string transaction::helpers::makeIdFromCustom(CollectionNameResolver const*
|
|||
return resolved;
|
||||
}
|
||||
|
||||
// ============== StringBufferLeaser ==============
|
||||
|
||||
/// @brief constructor, leases a StringBuffer
|
||||
transaction::StringBufferLeaser::StringBufferLeaser(transaction::Methods* trx)
|
||||
: _transactionContext(trx->transactionContextPtr()),
|
||||
|
@ -439,6 +441,25 @@ transaction::StringBufferLeaser::~StringBufferLeaser() {
|
|||
_transactionContext->returnStringBuffer(_stringBuffer);
|
||||
}
|
||||
|
||||
// ============== StringLeaser ==============
|
||||
|
||||
/// @brief constructor, leases a std::string
|
||||
transaction::StringLeaser::StringLeaser(transaction::Methods* trx)
|
||||
: _transactionContext(trx->transactionContextPtr()),
|
||||
_string(_transactionContext->leaseString()) {}
|
||||
|
||||
/// @brief constructor, leases a StringBuffer
|
||||
transaction::StringLeaser::StringLeaser(transaction::Context* transactionContext)
|
||||
: _transactionContext(transactionContext),
|
||||
_string(_transactionContext->leaseString()) {}
|
||||
|
||||
/// @brief destructor
|
||||
transaction::StringLeaser::~StringLeaser() {
|
||||
_transactionContext->returnString(_string);
|
||||
}
|
||||
|
||||
// ============== BuilderLeaser ==============
|
||||
|
||||
/// @brief constructor, leases a builder
|
||||
transaction::BuilderLeaser::BuilderLeaser(transaction::Methods* trx)
|
||||
: _transactionContext(trx->transactionContextPtr()),
|
||||
|
|
|
@ -96,6 +96,8 @@ std::string makeIdFromCustom(CollectionNameResolver const* resolver,
|
|||
VPackSlice const& idPart, VPackSlice const& keyPart);
|
||||
}; // namespace helpers
|
||||
|
||||
/// @brief basics::StringBuffer leaser
|
||||
/// @deprecated rather use StringLeaser for a shared std::string
|
||||
class StringBufferLeaser {
|
||||
public:
|
||||
explicit StringBufferLeaser(Methods*);
|
||||
|
@ -110,6 +112,21 @@ class StringBufferLeaser {
|
|||
arangodb::basics::StringBuffer* _stringBuffer;
|
||||
};
|
||||
|
||||
/// @brief std::string leaser
|
||||
class StringLeaser {
|
||||
public:
|
||||
explicit StringLeaser(Methods*);
|
||||
explicit StringLeaser(transaction::Context*);
|
||||
~StringLeaser();
|
||||
std::string* string() const { return _string; }
|
||||
std::string* operator->() const { return _string; }
|
||||
std::string* get() const { return _string; }
|
||||
|
||||
private:
|
||||
transaction::Context* _transactionContext;
|
||||
std::string* _string;
|
||||
};
|
||||
|
||||
class BuilderLeaser {
|
||||
public:
|
||||
explicit BuilderLeaser(transaction::Methods*);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2014-2018 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -21,70 +21,88 @@
|
|||
/// @author Jan Steemann
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "MMFilesTransactionManager.h"
|
||||
#include "Manager.h"
|
||||
|
||||
#include "Basics/ReadLocker.h"
|
||||
#include "Basics/WriteLocker.h"
|
||||
#include "Logger/Logger.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/StorageEngine.h"
|
||||
#include "StorageEngine/TransactionState.h"
|
||||
#include "Transaction/Helpers.h"
|
||||
#include "Transaction/Methods.h"
|
||||
#include "Transaction/SmartContext.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
|
||||
using namespace arangodb;
|
||||
#include <velocypack/Iterator.h>
|
||||
#include <velocypack/velocypack-aliases.h>
|
||||
|
||||
namespace arangodb {
|
||||
namespace transaction {
|
||||
|
||||
// register a list of failed transactions
|
||||
void MMFilesTransactionManager::registerFailedTransactions(
|
||||
std::unordered_set<TRI_voc_tid_t> const& failedTransactions) {
|
||||
void Manager::registerFailedTransactions(std::unordered_set<TRI_voc_tid_t> const& failedTransactions) {
|
||||
TRI_ASSERT(_keepTransactionData);
|
||||
READ_LOCKER(allTransactionsLocker, _allTransactionsLock);
|
||||
|
||||
for (auto const& it : failedTransactions) {
|
||||
size_t bucket = getBucket(it);
|
||||
|
||||
const size_t bucket = getBucket(it);
|
||||
WRITE_LOCKER(locker, _transactions[bucket]._lock);
|
||||
|
||||
_transactions[bucket]._failedTransactions.emplace(it);
|
||||
}
|
||||
}
|
||||
|
||||
// unregister a list of failed transactions
|
||||
void MMFilesTransactionManager::unregisterFailedTransactions(
|
||||
std::unordered_set<TRI_voc_tid_t> const& failedTransactions) {
|
||||
void Manager::unregisterFailedTransactions(std::unordered_set<TRI_voc_tid_t> const& failedTransactions) {
|
||||
TRI_ASSERT(_keepTransactionData);
|
||||
READ_LOCKER(allTransactionsLocker, _allTransactionsLock);
|
||||
|
||||
for (size_t bucket = 0; bucket < numBuckets; ++bucket) {
|
||||
WRITE_LOCKER(locker, _transactions[bucket]._lock);
|
||||
|
||||
std::for_each(failedTransactions.begin(), failedTransactions.end(), [&](TRI_voc_tid_t id) {
|
||||
_transactions[bucket]._failedTransactions.erase(id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void MMFilesTransactionManager::registerTransaction(TRI_voc_tid_t transactionId,
|
||||
std::unique_ptr<TransactionData> data) {
|
||||
TRI_ASSERT(data != nullptr);
|
||||
void Manager::registerTransaction(TRI_voc_tid_t transactionId,
|
||||
std::unique_ptr<TransactionData> data) {
|
||||
_nrRunning.fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
size_t bucket = getBucket(transactionId);
|
||||
READ_LOCKER(allTransactionsLocker, _allTransactionsLock);
|
||||
|
||||
WRITE_LOCKER(writeLocker, _transactions[bucket]._lock);
|
||||
|
||||
// insert into currently running list of transactions
|
||||
_transactions[bucket]._activeTransactions.emplace(transactionId, std::move(data));
|
||||
if (_keepTransactionData) {
|
||||
TRI_ASSERT(data != nullptr);
|
||||
const size_t bucket = getBucket(transactionId);
|
||||
READ_LOCKER(allTransactionsLocker, _allTransactionsLock);
|
||||
WRITE_LOCKER(writeLocker, _transactions[bucket]._lock);
|
||||
|
||||
try {
|
||||
// insert into currently running list of transactions
|
||||
_transactions[bucket]._activeTransactions.emplace(transactionId, std::move(data));
|
||||
} catch (...) {
|
||||
_nrRunning.fetch_sub(1, std::memory_order_relaxed);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unregisters a transaction
|
||||
void MMFilesTransactionManager::unregisterTransaction(TRI_voc_tid_t transactionId,
|
||||
bool markAsFailed) {
|
||||
size_t bucket = getBucket(transactionId);
|
||||
READ_LOCKER(allTransactionsLocker, _allTransactionsLock);
|
||||
void Manager::unregisterTransaction(TRI_voc_tid_t transactionId, bool markAsFailed) {
|
||||
uint64_t r = _nrRunning.fetch_sub(1, std::memory_order_relaxed);
|
||||
TRI_ASSERT(r > 0);
|
||||
|
||||
WRITE_LOCKER(writeLocker, _transactions[bucket]._lock);
|
||||
if (_keepTransactionData) {
|
||||
const size_t bucket = getBucket(transactionId);
|
||||
READ_LOCKER(allTransactionsLocker, _allTransactionsLock);
|
||||
|
||||
_transactions[bucket]._activeTransactions.erase(transactionId);
|
||||
WRITE_LOCKER(writeLocker, _transactions[bucket]._lock);
|
||||
|
||||
if (markAsFailed) {
|
||||
_transactions[bucket]._failedTransactions.emplace(transactionId);
|
||||
_transactions[bucket]._activeTransactions.erase(transactionId);
|
||||
if (markAsFailed) {
|
||||
_transactions[bucket]._failedTransactions.emplace(transactionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return the set of failed transactions
|
||||
std::unordered_set<TRI_voc_tid_t> MMFilesTransactionManager::getFailedTransactions() {
|
||||
std::unordered_set<TRI_voc_tid_t> Manager::getFailedTransactions() const {
|
||||
std::unordered_set<TRI_voc_tid_t> failedTransactions;
|
||||
|
||||
{
|
||||
|
@ -102,8 +120,11 @@ std::unordered_set<TRI_voc_tid_t> MMFilesTransactionManager::getFailedTransactio
|
|||
return failedTransactions;
|
||||
}
|
||||
|
||||
void MMFilesTransactionManager::iterateActiveTransactions(
|
||||
void Manager::iterateActiveTransactions(
|
||||
std::function<void(TRI_voc_tid_t, TransactionData const*)> const& callback) {
|
||||
if (!_keepTransactionData) {
|
||||
return;
|
||||
}
|
||||
WRITE_LOCKER(allTransactionsLocker, _allTransactionsLock);
|
||||
|
||||
// iterate over all active transactions
|
||||
|
@ -117,14 +138,9 @@ void MMFilesTransactionManager::iterateActiveTransactions(
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t MMFilesTransactionManager::getActiveTransactionCount() {
|
||||
WRITE_LOCKER(allTransactionsLocker, _allTransactionsLock);
|
||||
|
||||
uint64_t count = 0;
|
||||
// iterate over all active transactions
|
||||
for (size_t bucket = 0; bucket < numBuckets; ++bucket) {
|
||||
READ_LOCKER(locker, _transactions[bucket]._lock);
|
||||
count += _transactions[bucket]._activeTransactions.size();
|
||||
}
|
||||
return count;
|
||||
uint64_t Manager::getActiveTransactionCount() {
|
||||
return _nrRunning.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
} // namespace transaction
|
||||
} // namespace arangodb
|
|
@ -1,7 +1,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2014-2018 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -21,57 +21,77 @@
|
|||
/// @author Jan Steemann
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGOD_MMFILES_MMFILES_TRANSACTION_MANAGER_H
|
||||
#define ARANGOD_MMFILES_MMFILES_TRANSACTION_MANAGER_H 1
|
||||
#ifndef ARANGOD_TRANSACTION_MANAGER_H
|
||||
#define ARANGOD_TRANSACTION_MANAGER_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/ReadWriteLock.h"
|
||||
#include "StorageEngine/TransactionManager.h"
|
||||
#include "Basics/ReadWriteSpinLock.h"
|
||||
#include "Basics/Result.h"
|
||||
#include "Transaction/Status.h"
|
||||
#include "VocBase/AccessMode.h"
|
||||
#include "VocBase/voc-types.h"
|
||||
|
||||
namespace arangodb {
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
class MMFilesTransactionManager final : public TransactionManager {
|
||||
namespace arangodb {
|
||||
class TransactionState;
|
||||
// to be derived by storage engines
|
||||
struct TransactionData {
|
||||
virtual ~TransactionData() = default;
|
||||
};
|
||||
|
||||
namespace transaction {
|
||||
class Context;
|
||||
|
||||
class Manager final {
|
||||
static constexpr size_t numBuckets = 16;
|
||||
static constexpr double defaultTTL = 10.0 * 60.0; // 10 minutes
|
||||
static constexpr double tombstoneTTL = 5.0 * 60.0; // 5 minutes
|
||||
|
||||
public:
|
||||
MMFilesTransactionManager() : TransactionManager() {}
|
||||
~MMFilesTransactionManager() {}
|
||||
explicit Manager(bool keepData) : _keepTransactionData(keepData), _nrRunning(0) {}
|
||||
|
||||
public:
|
||||
typedef std::function<void(TRI_voc_tid_t, TransactionData const*)> TrxCallback;
|
||||
|
||||
public:
|
||||
// register a list of failed transactions
|
||||
void registerFailedTransactions(std::unordered_set<TRI_voc_tid_t> const& failedTransactions) override;
|
||||
void registerFailedTransactions(std::unordered_set<TRI_voc_tid_t> const& failedTransactions);
|
||||
|
||||
// unregister a list of failed transactions
|
||||
void unregisterFailedTransactions(std::unordered_set<TRI_voc_tid_t> const& failedTransactions) override;
|
||||
void unregisterFailedTransactions(std::unordered_set<TRI_voc_tid_t> const& failedTransactions);
|
||||
|
||||
// return the set of failed transactions
|
||||
std::unordered_set<TRI_voc_tid_t> getFailedTransactions() override;
|
||||
std::unordered_set<TRI_voc_tid_t> getFailedTransactions() const;
|
||||
|
||||
// register a transaction
|
||||
void registerTransaction(TRI_voc_tid_t transactionId,
|
||||
std::unique_ptr<TransactionData> data) override;
|
||||
void registerTransaction(TRI_voc_tid_t, std::unique_ptr<TransactionData> data);
|
||||
|
||||
// unregister a transaction
|
||||
void unregisterTransaction(TRI_voc_tid_t transactionId, bool markAsFailed) override;
|
||||
void unregisterTransaction(TRI_voc_tid_t transactionId, bool markAsFailed);
|
||||
|
||||
// iterate all the active transactions
|
||||
void iterateActiveTransactions(
|
||||
std::function<void(TRI_voc_tid_t, TransactionData const*)> const& callback) override;
|
||||
void iterateActiveTransactions(TrxCallback const&);
|
||||
|
||||
uint64_t getActiveTransactionCount() override;
|
||||
uint64_t getActiveTransactionCount();
|
||||
|
||||
private:
|
||||
// hashes the transaction id into a bucket
|
||||
inline size_t getBucket(TRI_voc_tid_t id) const {
|
||||
return std::hash<TRI_voc_cid_t>()(id) % numBuckets;
|
||||
inline size_t getBucket(TRI_voc_tid_t tid) const {
|
||||
return std::hash<TRI_voc_cid_t>()(tid) % numBuckets;
|
||||
}
|
||||
|
||||
private:
|
||||
const bool _keepTransactionData;
|
||||
|
||||
// a lock protecting ALL buckets in _transactions
|
||||
basics::ReadWriteLock _allTransactionsLock;
|
||||
mutable basics::ReadWriteLock _allTransactionsLock;
|
||||
|
||||
struct {
|
||||
// a lock protecting _activeTransactions and _failedTransactions
|
||||
basics::ReadWriteLock _lock;
|
||||
mutable basics::ReadWriteLock _lock;
|
||||
|
||||
// currently ongoing transactions
|
||||
std::unordered_map<TRI_voc_tid_t, std::unique_ptr<TransactionData>> _activeTransactions;
|
||||
|
@ -79,8 +99,11 @@ class MMFilesTransactionManager final : public TransactionManager {
|
|||
// set of failed transactions
|
||||
std::unordered_set<TRI_voc_tid_t> _failedTransactions;
|
||||
} _transactions[numBuckets];
|
||||
};
|
||||
|
||||
/// Nr of running transactions
|
||||
std::atomic<uint64_t> _nrRunning;
|
||||
};
|
||||
} // namespace transaction
|
||||
} // namespace arangodb
|
||||
|
||||
#endif
|
|
@ -20,22 +20,24 @@
|
|||
/// @author Jan Steemann
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "TransactionManagerFeature.h"
|
||||
#include "ManagerFeature.h"
|
||||
|
||||
#include "ApplicationFeatures/ApplicationServer.h"
|
||||
#include "Scheduler/SchedulerFeature.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/StorageEngine.h"
|
||||
#include "StorageEngine/TransactionManager.h"
|
||||
#include "Transaction/Manager.h"
|
||||
|
||||
using namespace arangodb::application_features;
|
||||
using namespace arangodb::basics;
|
||||
using namespace arangodb::options;
|
||||
|
||||
namespace arangodb {
|
||||
namespace transaction {
|
||||
|
||||
std::unique_ptr<TransactionManager> TransactionManagerFeature::MANAGER;
|
||||
std::unique_ptr<transaction::Manager> ManagerFeature::MANAGER;
|
||||
|
||||
TransactionManagerFeature::TransactionManagerFeature(application_features::ApplicationServer& server)
|
||||
ManagerFeature::ManagerFeature(application_features::ApplicationServer& server)
|
||||
: ApplicationFeature(server, "TransactionManager") {
|
||||
setOptional(false);
|
||||
startsAfter("BasicsPhase");
|
||||
|
@ -43,12 +45,13 @@ TransactionManagerFeature::TransactionManagerFeature(application_features::Appli
|
|||
startsAfter("EngineSelector");
|
||||
}
|
||||
|
||||
void TransactionManagerFeature::prepare() {
|
||||
void ManagerFeature::prepare() {
|
||||
TRI_ASSERT(MANAGER == nullptr);
|
||||
TRI_ASSERT(EngineSelectorFeature::ENGINE != nullptr);
|
||||
MANAGER = EngineSelectorFeature::ENGINE->createTransactionManager();
|
||||
}
|
||||
|
||||
void TransactionManagerFeature::unprepare() { MANAGER.reset(); }
|
||||
void ManagerFeature::unprepare() { MANAGER.reset(); }
|
||||
|
||||
} // namespace transaction
|
||||
} // namespace arangodb
|
|
@ -20,31 +20,33 @@
|
|||
/// @author Jan Steemann
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGODB_REST_SERVER_TRANSACTION_MANAGER_FEATURE_H
|
||||
#define ARANGODB_REST_SERVER_TRANSACTION_MANAGER_FEATURE_H 1
|
||||
#ifndef ARANGODB_TRANSACTION_MANAGER_FEATURE_H
|
||||
#define ARANGODB_TRANSACTION_MANAGER_FEATURE_H 1
|
||||
|
||||
#include "ApplicationFeatures/ApplicationFeature.h"
|
||||
|
||||
namespace arangodb {
|
||||
namespace transaction {
|
||||
|
||||
class TransactionManager;
|
||||
class Manager;
|
||||
|
||||
class TransactionManagerFeature final : public application_features::ApplicationFeature {
|
||||
class ManagerFeature final : public application_features::ApplicationFeature {
|
||||
public:
|
||||
explicit TransactionManagerFeature(application_features::ApplicationServer& server);
|
||||
explicit ManagerFeature(application_features::ApplicationServer& server);
|
||||
|
||||
void prepare() override final;
|
||||
void unprepare() override final;
|
||||
|
||||
static TransactionManager* manager() {
|
||||
static transaction::Manager* manager() {
|
||||
TRI_ASSERT(MANAGER != nullptr);
|
||||
return MANAGER.get();
|
||||
}
|
||||
|
||||
private:
|
||||
static std::unique_ptr<TransactionManager> MANAGER;
|
||||
static std::unique_ptr<transaction::Manager> MANAGER;
|
||||
};
|
||||
|
||||
} // namespace transaction
|
||||
} // namespace arangodb
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -22,6 +22,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Methods.h"
|
||||
|
||||
#include "ApplicationFeatures/ApplicationServer.h"
|
||||
#include "Aql/Ast.h"
|
||||
#include "Aql/AstNode.h"
|
||||
|
@ -343,7 +344,7 @@ bool transaction::Methods::sortOrs(arangodb::aql::Ast* ast, arangodb::aql::AstNo
|
|||
|
||||
std::vector<arangodb::aql::ConditionPart> parts;
|
||||
parts.reserve(n);
|
||||
|
||||
|
||||
std::pair<arangodb::aql::Variable const*, std::vector<arangodb::basics::AttributeName>> result;
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
|
@ -431,7 +432,7 @@ bool transaction::Methods::sortOrs(arangodb::aql::Ast* ast, arangodb::aql::AstNo
|
|||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
auto& p = parts[i];
|
||||
|
||||
|
||||
if (p.operatorType == arangodb::aql::AstNodeType::NODE_TYPE_OPERATOR_BINARY_IN &&
|
||||
p.valueNode->isArray()) {
|
||||
TRI_ASSERT(p.valueNode->isConstant());
|
||||
|
@ -442,15 +443,15 @@ bool transaction::Methods::sortOrs(arangodb::aql::Ast* ast, arangodb::aql::AstNo
|
|||
auto emptyArray = ast->createNodeArray();
|
||||
auto mergedIn =
|
||||
ast->createNodeUnionizedArray(parts[previousIn].valueNode, p.valueNode);
|
||||
|
||||
|
||||
arangodb::aql::AstNode* clone = ast->clone(root->getMember(previousIn));
|
||||
root->changeMember(previousIn, clone);
|
||||
static_cast<ConditionData*>(parts[previousIn].data)->first = clone;
|
||||
|
||||
|
||||
clone = ast->clone(root->getMember(i));
|
||||
root->changeMember(i, clone);
|
||||
static_cast<ConditionData*>(parts[i].data)->first = clone;
|
||||
|
||||
|
||||
// can now edit nodes in place...
|
||||
parts[previousIn].valueNode = mergedIn;
|
||||
{
|
||||
|
@ -459,7 +460,7 @@ bool transaction::Methods::sortOrs(arangodb::aql::Ast* ast, arangodb::aql::AstNo
|
|||
TEMPORARILY_UNLOCK_NODE(n1);
|
||||
n1->changeMember(1, mergedIn);
|
||||
}
|
||||
|
||||
|
||||
p.valueNode = emptyArray;
|
||||
{
|
||||
auto n2 = root->getMember(i)->getMember(0);
|
||||
|
@ -467,14 +468,14 @@ bool transaction::Methods::sortOrs(arangodb::aql::Ast* ast, arangodb::aql::AstNo
|
|||
TEMPORARILY_UNLOCK_NODE(n2);
|
||||
n2->changeMember(1, emptyArray);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
// note first IN
|
||||
previousIn = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now sort all conditions by variable name, attribute name, attribute value
|
||||
std::sort(parts.begin(), parts.end(),
|
||||
[](arangodb::aql::ConditionPart const& lhs,
|
||||
|
@ -526,7 +527,7 @@ bool transaction::Methods::sortOrs(arangodb::aql::Ast* ast, arangodb::aql::AstNo
|
|||
});
|
||||
|
||||
TRI_ASSERT(parts.size() == conditionData.size());
|
||||
|
||||
|
||||
// clean up
|
||||
while (root->numMembers()) {
|
||||
root->removeMemberUnchecked(0);
|
||||
|
@ -567,7 +568,7 @@ bool transaction::Methods::sortOrs(arangodb::aql::Ast* ast, arangodb::aql::AstNo
|
|||
usedIndexes.emplace_back(conditionData->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -764,7 +765,6 @@ transaction::Methods::Methods(std::shared_ptr<transaction::Context> const& trans
|
|||
}
|
||||
|
||||
_state = parent;
|
||||
|
||||
TRI_ASSERT(_state != nullptr);
|
||||
_state->increaseNesting();
|
||||
} else { // non-embedded
|
||||
|
@ -772,10 +772,10 @@ transaction::Methods::Methods(std::shared_ptr<transaction::Context> const& trans
|
|||
StorageEngine* engine = EngineSelectorFeature::ENGINE;
|
||||
|
||||
_state = engine
|
||||
->createTransactionState(_transactionContextPtr->vocbase(), options)
|
||||
->createTransactionState(_transactionContextPtr->vocbase(),
|
||||
_transactionContextPtr->generateId(), options)
|
||||
.release();
|
||||
TRI_ASSERT(_state != nullptr);
|
||||
TRI_ASSERT(_state->isTopLevelTransaction());
|
||||
TRI_ASSERT(_state != nullptr && _state->isTopLevelTransaction());
|
||||
|
||||
// register the transaction in the context
|
||||
_transactionContextPtr->registerTransaction(_state);
|
||||
|
@ -806,9 +806,10 @@ transaction::Methods::Methods(std::shared_ptr<transaction::Context> const& ctx,
|
|||
|
||||
/// @brief destroy the transaction
|
||||
transaction::Methods::~Methods() {
|
||||
if (_state->isEmbeddedTransaction()) {
|
||||
_state->decreaseNesting();
|
||||
} else {
|
||||
if (_state->isTopLevelTransaction()) { // _nestingLevel == 0
|
||||
// unregister transaction from context
|
||||
_transactionContextPtr->unregisterTransaction();
|
||||
|
||||
if (_state->status() == transaction::Status::RUNNING) {
|
||||
// auto abort a running transaction
|
||||
try {
|
||||
|
@ -821,14 +822,16 @@ transaction::Methods::~Methods() {
|
|||
|
||||
// free the state associated with the transaction
|
||||
TRI_ASSERT(_state->status() != transaction::Status::RUNNING);
|
||||
// store result
|
||||
|
||||
// store result in context
|
||||
_transactionContextPtr->storeTransactionResult(_state->id(),
|
||||
_state->hasFailedOperations(),
|
||||
_state->wasRegistered());
|
||||
_transactionContextPtr->unregisterTransaction();
|
||||
|
||||
delete _state;
|
||||
_state = nullptr;
|
||||
} else {
|
||||
_state->decreaseNesting(); // return transaction
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1460,9 +1463,8 @@ OperationResult transaction::Methods::documentCoordinator(std::string const& col
|
|||
}
|
||||
}
|
||||
|
||||
int res = arangodb::getDocumentOnCoordinator(vocbase().name(), collectionName,
|
||||
*this, value, options, responseCode,
|
||||
errorCounter, resultBody);
|
||||
int res = arangodb::getDocumentOnCoordinator(*this, collectionName, value, options,
|
||||
responseCode, errorCounter, resultBody);
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
return clusterResultDocument(responseCode, resultBody, errorCounter);
|
||||
|
@ -1587,8 +1589,8 @@ OperationResult transaction::Methods::insertCoordinator(std::string const& colle
|
|||
std::unordered_map<int, size_t> errorCounter;
|
||||
auto resultBody = std::make_shared<VPackBuilder>();
|
||||
|
||||
Result res = arangodb::createDocumentOnCoordinator(vocbase().name(), collectionName,
|
||||
*this, options, value, responseCode,
|
||||
Result res = arangodb::createDocumentOnCoordinator(*this, collectionName,
|
||||
options, value, responseCode,
|
||||
errorCounter, resultBody);
|
||||
|
||||
if (res.ok()) {
|
||||
|
@ -1677,7 +1679,7 @@ OperationResult transaction::Methods::insertLocal(std::string const& collectionN
|
|||
std::function<Result(void)> updateFollowers = nullptr;
|
||||
|
||||
if (needsToGetFollowersUnderLock) {
|
||||
auto const& followerInfo = *collection->followers();
|
||||
FollowerInfo const& followerInfo = *collection->followers();
|
||||
|
||||
updateFollowers = [&followerInfo, &followers]() -> Result {
|
||||
TRI_ASSERT(followers == nullptr);
|
||||
|
@ -1890,10 +1892,9 @@ OperationResult transaction::Methods::updateCoordinator(std::string const& colle
|
|||
rest::ResponseCode responseCode;
|
||||
std::unordered_map<int, size_t> errorCounter;
|
||||
auto resultBody = std::make_shared<VPackBuilder>();
|
||||
int res = arangodb::modifyDocumentOnCoordinator(vocbase().name(), collectionName,
|
||||
*this, newValue, options,
|
||||
true /* isPatch */, headers, responseCode,
|
||||
errorCounter, resultBody);
|
||||
int res = arangodb::modifyDocumentOnCoordinator(*this, collectionName, newValue,
|
||||
options, true /* isPatch */, headers,
|
||||
responseCode, errorCounter, resultBody);
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
return clusterResultModify(responseCode, resultBody, errorCounter);
|
||||
|
@ -1939,9 +1940,9 @@ OperationResult transaction::Methods::replaceCoordinator(std::string const& coll
|
|||
rest::ResponseCode responseCode;
|
||||
std::unordered_map<int, size_t> errorCounter;
|
||||
auto resultBody = std::make_shared<VPackBuilder>();
|
||||
int res = arangodb::modifyDocumentOnCoordinator(vocbase().name(), collectionName,
|
||||
*this, newValue, options,
|
||||
false /* isPatch */, headers, responseCode,
|
||||
int res = arangodb::modifyDocumentOnCoordinator(*this, collectionName, newValue,
|
||||
options, false /* isPatch */,
|
||||
headers, responseCode,
|
||||
errorCounter, resultBody);
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
|
@ -2214,8 +2215,8 @@ OperationResult transaction::Methods::removeCoordinator(std::string const& colle
|
|||
rest::ResponseCode responseCode;
|
||||
std::unordered_map<int, size_t> errorCounter;
|
||||
auto resultBody = std::make_shared<VPackBuilder>();
|
||||
int res = arangodb::deleteDocumentOnCoordinator(vocbase().name(), collectionName,
|
||||
*this, value, options, responseCode,
|
||||
int res = arangodb::deleteDocumentOnCoordinator(*this, collectionName, value,
|
||||
options, responseCode,
|
||||
errorCounter, resultBody);
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
|
@ -2514,8 +2515,7 @@ OperationResult transaction::Methods::truncate(std::string const& collectionName
|
|||
#ifndef USE_ENTERPRISE
|
||||
OperationResult transaction::Methods::truncateCoordinator(std::string const& collectionName,
|
||||
OperationOptions& options) {
|
||||
return OperationResult(
|
||||
arangodb::truncateCollectionOnCoordinator(vocbase().name(), collectionName));
|
||||
return OperationResult(arangodb::truncateCollectionOnCoordinator(*this, collectionName));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2696,7 +2696,7 @@ OperationResult transaction::Methods::countCoordinatorHelper(
|
|||
if (documents == CountCache::NotPopulated) {
|
||||
// no cache hit, or detailed results requested
|
||||
std::vector<std::pair<std::string, uint64_t>> count;
|
||||
auto res = arangodb::countOnCoordinator(vocbase().name(), collectionName, *this, count);
|
||||
auto res = arangodb::countOnCoordinator(*this, collectionName, count);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return OperationResult(res);
|
||||
|
@ -2917,8 +2917,7 @@ bool transaction::Methods::getIndexForSortCondition(
|
|||
/// calling this method
|
||||
std::unique_ptr<IndexIterator> transaction::Methods::indexScanForCondition(
|
||||
IndexHandle const& indexId, arangodb::aql::AstNode const* condition,
|
||||
arangodb::aql::Variable const* var,
|
||||
IndexIteratorOptions const& opts) {
|
||||
arangodb::aql::Variable const* var, IndexIteratorOptions const& opts) {
|
||||
if (_state->isCoordinator()) {
|
||||
// The index scan is only available on DBServers and Single Server.
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_CLUSTER_ONLY_ON_DBSERVER);
|
||||
|
@ -2970,7 +2969,7 @@ std::unique_ptr<IndexIterator> transaction::Methods::indexScan(std::string const
|
|||
}
|
||||
}
|
||||
|
||||
// the above methods must always return a valid iterator or throw!
|
||||
// the above methods must always return a valid iterator or throw!
|
||||
TRI_ASSERT(iterator != nullptr);
|
||||
return iterator;
|
||||
}
|
||||
|
@ -3153,14 +3152,11 @@ std::vector<std::shared_ptr<Index>> transaction::Methods::indexesForCollection(
|
|||
LogicalCollection* document = documentCollection(trxCollection(cid));
|
||||
std::vector<std::shared_ptr<Index>> indexes = document->getIndexes();
|
||||
if (!withHidden) {
|
||||
auto it = indexes.begin();
|
||||
while (it != indexes.end()) {
|
||||
if ((*it)->isHidden()) {
|
||||
it = indexes.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
indexes.erase(std::remove_if(indexes.begin(), indexes.end(),
|
||||
[](std::shared_ptr<Index> x) {
|
||||
return x->isHidden();
|
||||
}),
|
||||
indexes.end());
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
@ -3287,14 +3283,15 @@ Result Methods::replicateOperations(LogicalCollection const& collection,
|
|||
VPackBuilder& resultBuilder) {
|
||||
TRI_ASSERT(followers != nullptr);
|
||||
|
||||
Result res;
|
||||
if (followers->empty()) {
|
||||
return Result{};
|
||||
return res;
|
||||
}
|
||||
|
||||
// nullptr only happens on controlled shutdown
|
||||
auto cc = arangodb::ClusterComm::instance();
|
||||
if (cc == nullptr) {
|
||||
return Result{};
|
||||
return res.reset(TRI_ERROR_SHUTTING_DOWN);
|
||||
};
|
||||
|
||||
// path and requestType are different for insert/remove/modify.
|
||||
|
@ -3371,7 +3368,7 @@ Result Methods::replicateOperations(LogicalCollection const& collection,
|
|||
|
||||
if (count == 0) {
|
||||
// nothing to do
|
||||
return Result{};
|
||||
return res;
|
||||
}
|
||||
|
||||
auto body = std::make_shared<std::string>();
|
||||
|
@ -3430,8 +3427,8 @@ Result Methods::replicateOperations(LogicalCollection const& collection,
|
|||
}
|
||||
|
||||
if (findRefusal(requests)) {
|
||||
return Result{TRI_ERROR_CLUSTER_SHARD_LEADER_RESIGNED};
|
||||
return res.reset(TRI_ERROR_CLUSTER_SHARD_LEADER_RESIGNED);
|
||||
}
|
||||
|
||||
return Result{};
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ namespace arangodb {
|
|||
|
||||
namespace basics {
|
||||
struct AttributeName;
|
||||
class StringBuffer;
|
||||
} // namespace basics
|
||||
|
||||
namespace velocypack {
|
||||
|
@ -199,9 +198,6 @@ class Methods {
|
|||
|
||||
/// @brief add a transaction hint
|
||||
void addHint(transaction::Hints::Hint hint) { _localHints.set(hint); }
|
||||
bool hasHint(transaction::Hints::Hint hint) const {
|
||||
return _localHints.has(hint);
|
||||
}
|
||||
|
||||
/// @brief whether or not the transaction consists of a single operation only
|
||||
bool isSingleOperationTransaction() const;
|
||||
|
@ -363,15 +359,17 @@ class Methods {
|
|||
/// @brief Gets the best fitting index for an AQL sort condition
|
||||
/// note: the caller must have read-locked the underlying collection when
|
||||
/// calling this method
|
||||
ENTERPRISE_VIRT bool getIndexForSortCondition(
|
||||
std::string const&, arangodb::aql::SortCondition const*,
|
||||
arangodb::aql::Variable const*, size_t, std::vector<IndexHandle>&,
|
||||
size_t& coveredAttributes);
|
||||
ENTERPRISE_VIRT bool getIndexForSortCondition(std::string const&,
|
||||
arangodb::aql::SortCondition const*,
|
||||
arangodb::aql::Variable const*,
|
||||
size_t, std::vector<IndexHandle>&,
|
||||
size_t& coveredAttributes);
|
||||
|
||||
/// @brief factory for IndexIterator objects from AQL
|
||||
/// note: the caller must have read-locked the underlying collection when
|
||||
/// calling this method
|
||||
std::unique_ptr<IndexIterator> indexScanForCondition(IndexHandle const&, arangodb::aql::AstNode const*,
|
||||
std::unique_ptr<IndexIterator> indexScanForCondition(IndexHandle const&,
|
||||
arangodb::aql::AstNode const*,
|
||||
arangodb::aql::Variable const*,
|
||||
IndexIteratorOptions const&);
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "SmartContext.h"
|
||||
#include "StorageEngine/TransactionManager.h"
|
||||
#include "StorageEngine/TransactionState.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
|
||||
struct TRI_vocbase_t;
|
||||
|
|
|
@ -24,8 +24,9 @@
|
|||
#ifndef ARANGOD_TRANSACTION_STANDALONE_CONTEXT_H
|
||||
#define ARANGOD_TRANSACTION_STANDALONE_CONTEXT_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Context.h"
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
struct TRI_vocbase_t;
|
||||
|
|
|
@ -25,7 +25,26 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
using namespace arangodb::transaction;
|
||||
namespace arangodb {
|
||||
namespace transaction {
|
||||
Status statusFromString(char const* str, size_t len) {
|
||||
if (len == 9 && memcmp(str, "undefined", len) == 0) {
|
||||
return Status::UNDEFINED;
|
||||
} else if (len == 7 && memcmp(str, "created", len) == 0) {
|
||||
return Status::CREATED;
|
||||
} else if (len == 7 && memcmp(str, "running", len) == 0) {
|
||||
return Status::RUNNING;
|
||||
} else if (len == 9 && memcmp(str, "committed", len) == 0) {
|
||||
return Status::COMMITTED;
|
||||
} else if (len == 7 && memcmp(str, "aborted", len) == 0) {
|
||||
return Status::ABORTED;
|
||||
}
|
||||
|
||||
TRI_ASSERT(false);
|
||||
return Status::UNDEFINED;
|
||||
}
|
||||
} // namespace transaction
|
||||
} // namespace arangodb
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, arangodb::transaction::Status const& s) {
|
||||
stream << arangodb::transaction::statusString(s);
|
||||
|
|
|
@ -59,6 +59,8 @@ static inline char const* statusString(Status status) {
|
|||
return "unknown";
|
||||
}
|
||||
|
||||
Status statusFromString(char const* str, size_t len);
|
||||
|
||||
} // namespace transaction
|
||||
} // namespace arangodb
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "V8Context.h"
|
||||
|
||||
#include "StorageEngine/TransactionState.h"
|
||||
#include "Transaction/StandaloneContext.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
|
|
|
@ -97,4 +97,4 @@ class V8Context final : public Context {
|
|||
} // namespace transaction
|
||||
} // namespace arangodb
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -182,7 +182,7 @@ void V8DealerFeature::validateOptions(std::shared_ptr<ProgramOptions> options) {
|
|||
ProgramOptions::ProcessingResult const& result = options->processingResult();
|
||||
|
||||
// DBServer and Agent don't need JS. Agent role handled in AgencyFeature
|
||||
if (ServerState::instance()->getRole() == ServerState::RoleEnum::ROLE_PRIMARY &&
|
||||
if (ServerState::instance()->getRole() == ServerState::RoleEnum::ROLE_DBSERVER &&
|
||||
(!result.touched("console") ||
|
||||
!*(options->get<BooleanParameter>("console")->ptr))) {
|
||||
// specifiying --console requires JavaScript, so we can only turn it off
|
||||
|
|
|
@ -121,6 +121,7 @@ class ReadWriteSpinLock {
|
|||
|
||||
void writeUnlock() { unlockWrite(); }
|
||||
void unlockWrite() {
|
||||
TRI_ASSERT(isWriteLocked());
|
||||
_state.fetch_sub(WRITE_LOCK, std::memory_order_release);
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ class FakeResponse : public GeneralResponse {
|
|||
SCENARIO("Successful query setup", "[aql][restaqlhandler]") {
|
||||
|
||||
// We always work on DBServer
|
||||
ServerState::instance()->setRole(ServerState::ROLE_PRIMARY);
|
||||
ServerState::instance()->setRole(ServerState::ROLE_DBSERVER);
|
||||
auto body = std::make_shared<VPackBuilder>();
|
||||
|
||||
std::string dbName = "UnitTestDB";
|
||||
|
|
|
@ -492,7 +492,7 @@ SECTION("test_upgrade0_1") {
|
|||
auto versionJson = arangodb::velocypack::Parser::fromJson("{ \"version\": 0, \"tasks\": {} }");
|
||||
|
||||
auto serverRoleBefore = arangodb::ServerState::instance()->getRole();
|
||||
arangodb::ServerState::instance()->setRole(arangodb::ServerState::ROLE_PRIMARY);
|
||||
arangodb::ServerState::instance()->setRole(arangodb::ServerState::ROLE_DBSERVER);
|
||||
auto serverRoleRestore = irs::make_finally([&serverRoleBefore]()->void { arangodb::ServerState::instance()->setRole(serverRoleBefore); });
|
||||
|
||||
// create a new instance of an ApplicationServer and fill it with the required features
|
||||
|
@ -572,7 +572,7 @@ SECTION("test_upgrade0_1") {
|
|||
auto versionJson = arangodb::velocypack::Parser::fromJson("{ \"version\": 0, \"tasks\": {} }");
|
||||
|
||||
auto serverRoleBefore = arangodb::ServerState::instance()->getRole();
|
||||
arangodb::ServerState::instance()->setRole(arangodb::ServerState::ROLE_PRIMARY);
|
||||
arangodb::ServerState::instance()->setRole(arangodb::ServerState::ROLE_DBSERVER);
|
||||
auto serverRoleRestore = irs::make_finally([&serverRoleBefore]()->void { arangodb::ServerState::instance()->setRole(serverRoleBefore); });
|
||||
|
||||
// create a new instance of an ApplicationServer and fill it with the required features
|
||||
|
|
|
@ -5221,9 +5221,9 @@ SECTION("test_update_partial") {
|
|||
"{ \"links\": { \"testCollection\": {} } }"
|
||||
);
|
||||
|
||||
auto before = StorageEngineMock::inRecoveryResult;
|
||||
auto beforeRec = StorageEngineMock::inRecoveryResult;
|
||||
StorageEngineMock::inRecoveryResult = true;
|
||||
auto restore = irs::make_finally([&before]()->void { StorageEngineMock::inRecoveryResult = before; });
|
||||
auto restore = irs::make_finally([&beforeRec]()->void { StorageEngineMock::inRecoveryResult = beforeRec; });
|
||||
persisted = false;
|
||||
CHECK((view->properties(updateJson->slice(), true).ok()));
|
||||
CHECK((false == persisted));
|
||||
|
@ -6415,4 +6415,4 @@ SECTION("test_update_partial") {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -88,7 +88,7 @@ struct IResearchViewDBServerSetup {
|
|||
agency = agencyCommManager->addConnection<GeneralClientConnectionAgencyMock>(_agencyStore); // need 2 connections or Agency callbacks will fail
|
||||
arangodb::AgencyCommManager::MANAGER.reset(agencyCommManager);
|
||||
|
||||
arangodb::ServerState::instance()->setRole(arangodb::ServerState::RoleEnum::ROLE_PRIMARY);
|
||||
arangodb::ServerState::instance()->setRole(arangodb::ServerState::RoleEnum::ROLE_DBSERVER);
|
||||
arangodb::EngineSelectorFeature::ENGINE = &engine;
|
||||
|
||||
// suppress INFO {authentication} Authentication is turned on (system only), authentication for unix sockets is turned on
|
||||
|
@ -1510,4 +1510,4 @@ SECTION("test_visitCollections") {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
#include "Indexes/SimpleAttributeEqualityMatcher.h"
|
||||
#include "RestServer/FlushFeature.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/TransactionManager.h"
|
||||
#include "Transaction/Helpers.h"
|
||||
#include "Transaction/Manager.h"
|
||||
#include "Transaction/Methods.h"
|
||||
#include "Transaction/StandaloneContext.h"
|
||||
#include "Utils/OperationOptions.h"
|
||||
|
@ -434,16 +434,6 @@ struct IndexFactoryMock : arangodb::IndexFactory {
|
|||
|
||||
} // namespace
|
||||
|
||||
void ContextDataMock::pinData(arangodb::LogicalCollection* collection) {
|
||||
if (collection) {
|
||||
pinned.emplace(collection->id());
|
||||
}
|
||||
}
|
||||
|
||||
bool ContextDataMock::isPinned(TRI_voc_cid_t cid) const {
|
||||
return pinned.find(cid) != pinned.end();
|
||||
}
|
||||
|
||||
std::function<void()> PhysicalCollectionMock::before = []() -> void {};
|
||||
|
||||
PhysicalCollectionMock::PhysicalCollectionMock(arangodb::LogicalCollection& collection,
|
||||
|
@ -1061,18 +1051,22 @@ std::unique_ptr<arangodb::TransactionCollection> StorageEngineMock::createTransa
|
|||
}
|
||||
|
||||
std::unique_ptr<arangodb::transaction::ContextData> StorageEngineMock::createTransactionContextData() {
|
||||
before();
|
||||
return std::unique_ptr<arangodb::transaction::ContextData>(new ContextDataMock());
|
||||
return std::unique_ptr<arangodb::transaction::ContextData>();
|
||||
}
|
||||
|
||||
std::unique_ptr<arangodb::TransactionManager> StorageEngineMock::createTransactionManager() {
|
||||
std::unique_ptr<arangodb::transaction::Manager> StorageEngineMock::createTransactionManager() {
|
||||
TRI_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<arangodb::TransactionState> StorageEngineMock::createTransactionState(
|
||||
TRI_vocbase_t& vocbase, arangodb::transaction::Options const& options) {
|
||||
return std::unique_ptr<arangodb::TransactionState>(new TransactionStateMock(vocbase, options));
|
||||
TRI_vocbase_t& vocbase,
|
||||
TRI_voc_tid_t tid,
|
||||
arangodb::transaction::Options const& options
|
||||
) {
|
||||
return std::unique_ptr<arangodb::TransactionState>(
|
||||
new TransactionStateMock(vocbase, options)
|
||||
);
|
||||
}
|
||||
|
||||
arangodb::Result StorageEngineMock::createView(TRI_vocbase_t& vocbase, TRI_voc_cid_t id,
|
||||
|
@ -1443,9 +1437,9 @@ TransactionStateMock::TransactionStateMock(TRI_vocbase_t& vocbase,
|
|||
arangodb::Result TransactionStateMock::abortTransaction(arangodb::transaction::Methods* trx) {
|
||||
++abortTransactionCount;
|
||||
updateStatus(arangodb::transaction::Status::ABORTED);
|
||||
unuseCollections(_nestingLevel);
|
||||
const_cast<TRI_voc_tid_t&>(_id) =
|
||||
0; // avoid use of TransactionManagerFeature::manager()->unregisterTransaction(...)
|
||||
unuseCollections(nestingLevel());
|
||||
// avoid use of TransactionManagerFeature::manager()->unregisterTransaction(...)
|
||||
const_cast<TRI_voc_tid_t&>(_id) = 0;
|
||||
|
||||
return arangodb::Result();
|
||||
}
|
||||
|
@ -1455,7 +1449,7 @@ arangodb::Result TransactionStateMock::beginTransaction(arangodb::transaction::H
|
|||
++beginTransactionCount;
|
||||
_hints = hints;
|
||||
|
||||
auto res = useCollections(_nestingLevel);
|
||||
auto res = useCollections(nestingLevel());
|
||||
|
||||
if (!res.ok()) {
|
||||
updateStatus(arangodb::transaction::Status::ABORTED);
|
||||
|
@ -1474,9 +1468,9 @@ arangodb::Result TransactionStateMock::beginTransaction(arangodb::transaction::H
|
|||
arangodb::Result TransactionStateMock::commitTransaction(arangodb::transaction::Methods* trx) {
|
||||
++commitTransactionCount;
|
||||
updateStatus(arangodb::transaction::Status::COMMITTED);
|
||||
unuseCollections(_nestingLevel);
|
||||
const_cast<TRI_voc_tid_t&>(_id) =
|
||||
0; // avoid use of TransactionManagerFeature::manager()->unregisterTransaction(...)
|
||||
unuseCollections(nestingLevel());
|
||||
// avoid use of TransactionManagerFeature::manager()->unregisterTransaction(...)
|
||||
const_cast<TRI_voc_tid_t&>(_id) = 0;
|
||||
|
||||
return arangodb::Result();
|
||||
}
|
||||
|
|
|
@ -43,14 +43,6 @@ class WalAccess;
|
|||
|
||||
} // arangodb
|
||||
|
||||
class ContextDataMock: public arangodb::transaction::ContextData {
|
||||
public:
|
||||
std::set<TRI_voc_cid_t> pinned;
|
||||
|
||||
void pinData(arangodb::LogicalCollection* collection) override;
|
||||
bool isPinned(TRI_voc_cid_t cid) const override;
|
||||
};
|
||||
|
||||
class PhysicalCollectionMock: public arangodb::PhysicalCollection {
|
||||
public:
|
||||
static std::function<void()> before;
|
||||
|
@ -183,8 +175,8 @@ class StorageEngineMock: public arangodb::StorageEngine {
|
|||
virtual arangodb::Result createTickRanges(VPackBuilder&) override;
|
||||
virtual std::unique_ptr<arangodb::TransactionCollection> createTransactionCollection(arangodb::TransactionState& state, TRI_voc_cid_t cid, arangodb::AccessMode::Type, int nestingLevel) override;
|
||||
virtual std::unique_ptr<arangodb::transaction::ContextData> createTransactionContextData() override;
|
||||
virtual std::unique_ptr<arangodb::TransactionManager> createTransactionManager() override;
|
||||
virtual std::unique_ptr<arangodb::TransactionState> createTransactionState(TRI_vocbase_t& vocbase, arangodb::transaction::Options const& options) override;
|
||||
virtual std::unique_ptr<arangodb::transaction::Manager> createTransactionManager() override;
|
||||
virtual std::unique_ptr<arangodb::TransactionState> createTransactionState(TRI_vocbase_t& vocbase, TRI_voc_tid_t tid, arangodb::transaction::Options const& options) override;
|
||||
virtual arangodb::Result createView(TRI_vocbase_t& vocbase, TRI_voc_cid_t id, arangodb::LogicalView const& view) override;
|
||||
virtual void getViewProperties(TRI_vocbase_t& vocbase, arangodb::LogicalView const& view, VPackBuilder& builder) override;
|
||||
virtual TRI_voc_tick_t currentTick() const override;
|
||||
|
|
Loading…
Reference in New Issue