diff --git a/arangod/Cluster/ServerState.cpp b/arangod/Cluster/ServerState.cpp index 2ab3e0857b..de154a33a3 100644 --- a/arangod/Cluster/ServerState.cpp +++ b/arangod/Cluster/ServerState.cpp @@ -29,6 +29,7 @@ #include "Basics/ReadLocker.h" #include "Basics/WriteLocker.h" #include "BasicsC/logging.h" +#include "Cluster/AgencyComm.h" using namespace triagens::arango; @@ -55,8 +56,10 @@ ServerState::ServerState () _address(), _lock(), _role(ROLE_UNDEFINED), - _state(STATE_UNDEFINED) { - + _state(STATE_UNDEFINED), + _uniqid() { + + _uniqid._currentValue = _uniqid._upperValue = 0; } //////////////////////////////////////////////////////////////////////////////// @@ -152,6 +155,28 @@ std::string ServerState::stateToString (StateEnum state) { // --SECTION-- public methods // ----------------------------------------------------------------------------- +//////////////////////////////////////////////////////////////////////////////// +/// @brief gets a unique id +//////////////////////////////////////////////////////////////////////////////// + +uint64_t ServerState::uniqid () { + WRITE_LOCKER(_lock); + + if (_uniqid._currentValue >= _uniqid._upperValue) { + AgencyComm comm; + AgencyCommResult result = comm.uniqid("Sync/LatestID", ValuesPerBatch); + + if (! result.successful() || result._index == 0) { + return 0; + } + + _uniqid._currentValue = result._index; + _uniqid._upperValue = _uniqid._currentValue + ValuesPerBatch; + } + + return _uniqid._currentValue++; +} + //////////////////////////////////////////////////////////////////////////////// /// @brief get the current state //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/Cluster/ServerState.h b/arangod/Cluster/ServerState.h index 2641a892b8..4ba8efa05a 100644 --- a/arangod/Cluster/ServerState.h +++ b/arangod/Cluster/ServerState.h @@ -136,6 +136,12 @@ namespace triagens { public: +//////////////////////////////////////////////////////////////////////////////// +/// @brief gets a unique id +//////////////////////////////////////////////////////////////////////////////// + + uint64_t uniqid (); + //////////////////////////////////////////////////////////////////////////////// /// @brief get the server role //////////////////////////////////////////////////////////////////////////////// @@ -259,6 +265,28 @@ namespace triagens { StateEnum _state; +//////////////////////////////////////////////////////////////////////////////// +/// @brief uniqid sequence +//////////////////////////////////////////////////////////////////////////////// + + struct { + uint64_t _currentValue; + uint64_t _upperValue; + } + _uniqid; + +// ----------------------------------------------------------------------------- +// --SECTION-- private static variables +// ----------------------------------------------------------------------------- + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief how big a batch is for unique values +//////////////////////////////////////////////////////////////////////////////// + + static const uint64_t ValuesPerBatch = 1000; + }; } } diff --git a/arangod/Cluster/v8-cluster.cpp b/arangod/Cluster/v8-cluster.cpp index b50e18de25..10770161c4 100644 --- a/arangod/Cluster/v8-cluster.cpp +++ b/arangod/Cluster/v8-cluster.cpp @@ -453,6 +453,28 @@ static v8::Handle JS_StatusServerState (v8::Arguments const& argv) { return scope.Close(v8::String::New(state.c_str(), state.size())); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates a uniqid +//////////////////////////////////////////////////////////////////////////////// + +static v8::Handle JS_UniqidServerState (v8::Arguments const& argv) { + v8::HandleScope scope; + + if (argv.Length() != 0) { + TRI_V8_EXCEPTION_USAGE(scope, "uniqid()"); + } + + uint64_t value = ServerState::instance()->uniqid(); + + if (value == 0) { + TRI_V8_EXCEPTION_MESSAGE(scope, TRI_ERROR_INTERNAL, "unable to generate unique id"); + } + + const std::string id = StringUtils::itoa(value); + + return scope.Close(v8::String::New(id.c_str(), id.size())); +} + // ----------------------------------------------------------------------------- // --SECTION-- public functions // ----------------------------------------------------------------------------- @@ -509,6 +531,7 @@ void TRI_InitV8Cluster (v8::Handle context) { TRI_AddMethodVocbase(rt, "isCoordinator", JS_IsCoordinatorServerState); TRI_AddMethodVocbase(rt, "role", JS_RoleServerState); TRI_AddMethodVocbase(rt, "status", JS_StatusServerState); + TRI_AddMethodVocbase(rt, "uniqid", JS_UniqidServerState); v8g->ServerStateTempl = v8::Persistent::New(isolate, rt); TRI_AddGlobalFunctionVocbase(context, "ArangoServerState", ft->GetFunction());