1
0
Fork 0

Improve cluster in various ways.

Finish implementation of AgencyReadTransaction.
Use AgencyReadTransaction in HeartbeatThread of coordinator (less requests).
Repair ClusterInfo::uniqid.
Repair AgencyComm::uniqid.
Remove x-etcd-index header.
Remove _index in AgencyCommResult.
Streamline HeartbeatThread of coordinator.
Remove lastCommandIndex from AgencyComm.
Fix HeartbeatThread::handleStateChange.
This commit is contained in:
Max Neunhoeffer 2016-05-06 22:30:27 +02:00
parent 5690c0410c
commit 0fbc48b83e
7 changed files with 200 additions and 229 deletions

View File

@ -137,8 +137,8 @@ void AgencyCallback::executeByCallbackOrTimeout(double maxTimeout) {
compareBuilder = _lastData; compareBuilder = _lastData;
} }
_useCv = true;
CONDITION_LOCKER(locker, _cv); CONDITION_LOCKER(locker, _cv);
_useCv = true;
locker.wait(static_cast<uint64_t>(maxTimeout * 1000000.0)); locker.wait(static_cast<uint64_t>(maxTimeout * 1000000.0));
_useCv = false; _useCv = false;

View File

@ -144,10 +144,7 @@ void AgencyPrecondition::toVelocyPack(VPackBuilder& builder) const {
std::string AgencyWriteTransaction::toJson() const { std::string AgencyWriteTransaction::toJson() const {
VPackBuilder builder; VPackBuilder builder;
{ toVelocyPack(builder);
VPackArrayBuilder guard(&builder);
toVelocyPack(builder);
}
return builder.toJson(); return builder.toJson();
} }
@ -177,10 +174,7 @@ void AgencyWriteTransaction::toVelocyPack(VPackBuilder& builder) const {
std::string AgencyReadTransaction::toJson() const { std::string AgencyReadTransaction::toJson() const {
VPackBuilder builder; VPackBuilder builder;
{ toVelocyPack(builder);
VPackArrayBuilder guard(&builder);
toVelocyPack(builder);
}
return builder.toJson(); return builder.toJson();
} }
@ -189,12 +183,9 @@ std::string AgencyReadTransaction::toJson() const {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void AgencyReadTransaction::toVelocyPack(VPackBuilder& builder) const { void AgencyReadTransaction::toVelocyPack(VPackBuilder& builder) const {
VPackArrayBuilder guard(&builder); VPackArrayBuilder guard2(&builder);
{ for (std::string const& key: keys) {
VPackArrayBuilder guard2(&builder); builder.add(VPackValue(key));
for (std::string const& key: keys) {
builder.add(VPackValue(key));
}
} }
} }
@ -225,7 +216,6 @@ AgencyCommResult::AgencyCommResult()
_message(), _message(),
_body(), _body(),
_values(), _values(),
_index(0),
_statusCode(0), _statusCode(0),
_connected(false) {} _connected(false) {}
@ -328,7 +318,6 @@ void AgencyCommResult::clear() {
_location = ""; _location = "";
_message = ""; _message = "";
_body = ""; _body = "";
_index = 0;
_statusCode = 0; _statusCode = 0;
} }
@ -658,7 +647,7 @@ bool AgencyComm::tryInitializeStructure() {
builder.add(VPackValue("Sync")); builder.add(VPackValue("Sync"));
{ {
VPackObjectBuilder c(&builder); VPackObjectBuilder c(&builder);
builder.add("LatestID", VPackValue("1")); builder.add("LatestID", VPackValue(1));
addEmptyVPackObject("Problems", builder); addEmptyVPackObject("Problems", builder);
builder.add("UserVersion", VPackValue(1)); builder.add("UserVersion", VPackValue(1));
addEmptyVPackObject("ServerStates", builder); addEmptyVPackObject("ServerStates", builder);
@ -1566,76 +1555,69 @@ bool AgencyComm::unlockWrite(std::string const& key, double timeout) {
/// @brief get unique id /// @brief get unique id
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
AgencyCommResult AgencyComm::uniqid(std::string const& key, uint64_t count, uint64_t AgencyComm::uniqid(uint64_t count, double timeout) {
double timeout) { static int const maxTries = 1000000;
static int const maxTries = 10; // this is pretty much forever, but we simply cannot continue at all
// if we do not get a unique id from the agency.
int tries = 0; int tries = 0;
AgencyCommResult result; AgencyCommResult result;
while (tries++ < maxTries) { uint64_t oldValue = 0;
result.clear();
result = getValues(key, false);
if (result.httpCode() == while (tries++ < maxTries) {
(int)arangodb::GeneralResponse::ResponseCode::NOT_FOUND) { result = getValues2("Sync/LatestID");
if (!result.successful()) {
usleep(500000);
continue;
}
VPackSlice oldSlice = result.slice()[0].get(std::vector<std::string>(
{prefixStripped(), "Sync", "LatestID"}));
if (!(oldSlice.isSmallInt() || oldSlice.isUInt())) {
LOG(WARN) << "Sync/LatestID in agency is not an unsigned integer, fixing...";
try { try {
VPackBuilder builder; VPackBuilder builder;
builder.add(VPackValue(0)); builder.add(VPackValue(0));
// create the key on the fly // create the key on the fly
setValue(key, builder.slice(), 0.0); setValue("Sync/LatestID", builder.slice(), 0.0);
tries--;
continue;
} catch (...) { } catch (...) {
// Could not build local key. Try again // Could not build local key. Try again
} }
continue;
} }
if (!result.successful()) { // If we get here, slice is pointing to an unsigned integer, which
return result; // is the value in the agency.
} oldValue = 0;
result.parse("", false);
std::shared_ptr<VPackBuilder> oldBuilder;
std::map<std::string, AgencyCommResultEntry>::iterator it =
result._values.begin();
try { try {
if (it != result._values.end()) { oldValue = oldSlice.getUInt();
// steal the velocypack }
oldBuilder.swap((*it).second._vpack); catch (...) {
} else {
oldBuilder->add(VPackValue(0));
}
} catch (...) {
return AgencyCommResult();
} }
VPackSlice oldSlice = oldBuilder->slice();
uint64_t const oldValue = arangodb::basics::VelocyPackHelper::stringUInt64(oldSlice) + count;
uint64_t const newValue = oldValue + count; uint64_t const newValue = oldValue + count;
VPackBuilder newBuilder; VPackBuilder newBuilder;
try { try {
newBuilder.add(VPackValue(newValue)); newBuilder.add(VPackValue(newValue));
} catch (...) { } catch (...) {
return AgencyCommResult(); usleep(500000);
continue;
} }
result.clear(); result = casValue("Sync/LatestID", oldSlice, newBuilder.slice(),
result = casValue(key, oldSlice, newBuilder.slice(), 0.0, timeout); 0.0, timeout);
if (result.successful()) { if (result.successful()) {
result._index = oldValue + 1;
break; break;
} }
// The cas did not work, simply try again!
} }
return result; return oldValue;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1841,11 +1823,56 @@ AgencyCommResult AgencyComm::sendTransactionWithFailover(
std::string url(buildUrl()); std::string url(buildUrl());
url += "/write"; url += transaction.isWriteTransaction() ? "/write" : "/read";
return sendWithFailover(arangodb::GeneralRequest::RequestType::POST, VPackBuilder builder;
{
VPackArrayBuilder guard(&builder);
transaction.toVelocyPack(builder);
}
AgencyCommResult result = sendWithFailover(
arangodb::GeneralRequest::RequestType::POST,
timeout == 0.0 ? _globalConnectionOptions._requestTimeout : timeout, url, timeout == 0.0 ? _globalConnectionOptions._requestTimeout : timeout, url,
transaction.toJson(), false); builder.slice().toJson(), false);
try {
result.setVPack(VPackParser::fromJson(result.body().c_str()));
if (transaction.isWriteTransaction()) {
if (!result.slice().isObject() ||
!result.slice().get("results").isArray()) {
result._statusCode = 500;
return result;
}
if (result.slice().get("results").length() != 1) {
result._statusCode = 500;
return result;
}
} else {
if (!result.slice().isArray()) {
result._statusCode = 500;
return result;
}
if (result.slice().length() != 1) {
result._statusCode = 500;
return result;
}
}
result._body.clear();
result._statusCode = 200;
} catch(std::exception &e) {
LOG(ERR) << "Error transforming result. " << e.what();
result.clear();
} catch(...) {
LOG(ERR) << "Error transforming result. Out of memory";
result.clear();
}
return result;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -2061,15 +2088,8 @@ AgencyCommResult AgencyComm::send(
result._message = response->getHttpReturnMessage(); result._message = response->getHttpReturnMessage();
basics::StringBuffer& sb = response->getBody(); basics::StringBuffer& sb = response->getBody();
result._body = std::string(sb.c_str(), sb.length()); result._body = std::string(sb.c_str(), sb.length());
result._index = 0;
result._statusCode = response->getHttpReturnCode(); result._statusCode = response->getHttpReturnCode();
bool found = false;
std::string lastIndex = response->getHeaderField("x-etcd-index", found);
if (found) {
result._index = arangodb::basics::StringUtils::uint64(lastIndex);
}
LOG(TRACE) << "request to agency returned status code " << result._statusCode LOG(TRACE) << "request to agency returned status code " << result._statusCode
<< ", message: '" << result._message << "', body: '" << ", message: '" << result._message << "', body: '"
<< result._body << "'"; << result._body << "'";

View File

@ -215,8 +215,10 @@ private:
struct AgencyTransaction { struct AgencyTransaction {
virtual std::string toJson() const = 0; virtual std::string toJson() const = 0;
virtual void toVelocyPack(arangodb::velocypack::Builder& builder) const = 0;
virtual ~AgencyTransaction() { virtual ~AgencyTransaction() {
} }
virtual bool isWriteTransaction() const = 0;
}; };
struct AgencyWriteTransaction : public AgencyTransaction { struct AgencyWriteTransaction : public AgencyTransaction {
@ -237,7 +239,7 @@ struct AgencyWriteTransaction : public AgencyTransaction {
/// @brief converts the transaction to velocypack /// @brief converts the transaction to velocypack
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void toVelocyPack(arangodb::velocypack::Builder& builder) const; void toVelocyPack(arangodb::velocypack::Builder& builder) const override final;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief converts the transaction to json /// @brief converts the transaction to json
@ -270,6 +272,13 @@ struct AgencyWriteTransaction : public AgencyTransaction {
AgencyWriteTransaction() = default; AgencyWriteTransaction() = default;
//////////////////////////////////////////////////////////////////////////////
/// @brief return type of transaction
//////////////////////////////////////////////////////////////////////////////
bool isWriteTransaction() const override final {
return true;
}
}; };
struct AgencyReadTransaction : public AgencyTransaction { struct AgencyReadTransaction : public AgencyTransaction {
@ -284,7 +293,7 @@ struct AgencyReadTransaction : public AgencyTransaction {
/// @brief converts the transaction to velocypack /// @brief converts the transaction to velocypack
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
void toVelocyPack(arangodb::velocypack::Builder& builder) const; void toVelocyPack(arangodb::velocypack::Builder& builder) const override final;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief converts the transaction to json /// @brief converts the transaction to json
@ -300,12 +309,27 @@ struct AgencyReadTransaction : public AgencyTransaction {
keys.push_back(key); keys.push_back(key);
} }
//////////////////////////////////////////////////////////////////////////////
/// @brief shortcut to create a transaction with more than one operation
//////////////////////////////////////////////////////////////////////////////
explicit AgencyReadTransaction(std::vector<std::string>&& k)
: keys(k) {
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief default constructor /// @brief default constructor
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
AgencyReadTransaction() = default; AgencyReadTransaction() = default;
//////////////////////////////////////////////////////////////////////////////
/// @brief return type of transaction
//////////////////////////////////////////////////////////////////////////////
bool isWriteTransaction() const override final {
return false;
}
}; };
struct AgencyCommResult { struct AgencyCommResult {
@ -342,12 +366,6 @@ struct AgencyCommResult {
int httpCode() const; int httpCode() const;
//////////////////////////////////////////////////////////////////////////////
/// @brief extract the "index" attribute from the result
//////////////////////////////////////////////////////////////////////////////
uint64_t index() const { return _index; }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief extract the error code from the result /// @brief extract the error code from the result
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -418,7 +436,6 @@ struct AgencyCommResult {
std::string _realBody; std::string _realBody;
std::map<std::string, AgencyCommResultEntry> _values; std::map<std::string, AgencyCommResultEntry> _values;
uint64_t _index;
int _statusCode; int _statusCode;
bool _connected; bool _connected;
}; };
@ -635,7 +652,7 @@ class AgencyComm {
/// @brief get unique id /// @brief get unique id
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
AgencyCommResult uniqid(std::string const&, uint64_t, double); uint64_t uniqid(uint64_t, double);
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief registers a callback on a key /// @brief registers a callback on a key

View File

@ -302,31 +302,44 @@ ClusterInfo::~ClusterInfo() {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
uint64_t ClusterInfo::uniqid(uint64_t count) { uint64_t ClusterInfo::uniqid(uint64_t count) {
MUTEX_LOCKER(mutexLocker, _idLock); while (true) {
uint64_t oldValue;
{
// The quick path, we have enough in our private reserve:
MUTEX_LOCKER(mutexLocker, _idLock);
if (_uniqid._currentValue + count - 1 <= _uniqid._upperValue) {
uint64_t result = _uniqid._currentValue;
_uniqid._currentValue += count;
return result;
}
oldValue = _uniqid._currentValue;
}
// We need to fetch from the agency
if (_uniqid._currentValue + count - 1 >= _uniqid._upperValue) {
uint64_t fetch = count; uint64_t fetch = count;
if (fetch < MinIdsPerBatch) { if (fetch < MinIdsPerBatch) {
fetch = MinIdsPerBatch; fetch = MinIdsPerBatch;
} }
AgencyCommResult result = _agency.uniqid("Sync/LatestID", fetch, 0.0); uint64_t result = _agency.uniqid(fetch, 0.0);
if (!result.successful() || result._index == 0) { {
return 0; MUTEX_LOCKER(mutexLocker, _idLock);
if (oldValue == _uniqid._currentValue) {
_uniqid._currentValue = result + count;
_uniqid._upperValue = result + fetch - 1;
return result;
}
// If we get here, somebody else tried succeeded in doing the same,
// so we just try again.
} }
_uniqid._currentValue = result._index + count;
_uniqid._upperValue = _uniqid._currentValue + fetch - 1;
return result._index;
} }
uint64_t result = _uniqid._currentValue;
_uniqid._currentValue += count;
return result;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -113,9 +113,6 @@ void HeartbeatThread::runDBServer() {
// convert timeout to seconds // convert timeout to seconds
double const interval = (double)_interval / 1000.0 / 1000.0; double const interval = (double)_interval / 1000.0 / 1000.0;
// value of Sync/Commands/my-id at startup
uint64_t lastCommandIndex = getLastCommandIndex();
std::function<bool(VPackSlice const& result)> updatePlan = [&]( std::function<bool(VPackSlice const& result)> updatePlan = [&](
VPackSlice const& result) { VPackSlice const& result) {
if (!result.isNumber()) { if (!result.isNumber()) {
@ -170,23 +167,23 @@ void HeartbeatThread::runDBServer() {
break; break;
} }
{
// send an initial GET request to Sync/Commands/my-id
AgencyCommResult result =
_agency.getValues("Sync/Commands/" + _myId, false);
if (result.successful()) {
handleStateChange(result, lastCommandIndex);
}
}
if (isStopping()) {
break;
}
if (--currentCount == 0) { if (--currentCount == 0) {
currentCount = currentCountStart; currentCount = currentCountStart;
// send an initial GET request to Sync/Commands/my-id
LOG(TRACE) << "Looking at Sync/Commands/" + _myId;
AgencyCommResult result =
_agency.getValues2("Sync/Commands/" + _myId);
if (result.successful()) {
handleStateChange(result);
}
if (isStopping()) {
break;
}
LOG(TRACE) << "Refetching Current/Version..."; LOG(TRACE) << "Refetching Current/Version...";
AgencyCommResult res = _agency.getValues2("Current/Version"); AgencyCommResult res = _agency.getValues2("Current/Version");
if (!res.successful()) { if (!res.successful()) {
@ -286,9 +283,6 @@ void HeartbeatThread::runCoordinator() {
// last value of current which we have noticed: // last value of current which we have noticed:
uint64_t lastCurrentVersionNoticed = 0; uint64_t lastCurrentVersionNoticed = 0;
// value of Sync/Commands/my-id at startup
uint64_t lastCommandIndex = getLastCommandIndex();
setReady(); setReady();
while (!isStopping()) { while (!isStopping()) {
@ -303,28 +297,20 @@ void HeartbeatThread::runCoordinator() {
break; break;
} }
{ AgencyReadTransaction trx(std::vector<std::string>({
_agency.prefix() + "Plan/Version",
_agency.prefix() + "Current/Version",
_agency.prefix() + "Sync/Commands/" + _myId,
_agency.prefix() + "Sync/UserVersion"}));
AgencyCommResult result = _agency.sendTransactionWithFailover(trx);
// send an initial GET request to Sync/Commands/my-id if (!result.successful()) {
AgencyCommResult result = LOG(WARN) << "Heartbeat: Could not read from agency!";
_agency.getValues("Sync/Commands/" + _myId, false); } else {
LOG(TRACE) << "Looking at Sync/Commands/" + _myId;
if (result.successful()) { handleStateChange(result);
handleStateChange(result, lastCommandIndex);
}
}
if (isStopping()) {
break;
}
bool shouldSleep = true;
// get the current version of the Plan
AgencyCommResult result = _agency.getValues2("Plan/Version");
if (result.successful()) {
VPackSlice versionSlice VPackSlice versionSlice
= result.slice()[0].get(std::vector<std::string>( = result.slice()[0].get(std::vector<std::string>(
{_agency.prefixStripped(), "Plan", "Version"})); {_agency.prefixStripped(), "Plan", "Version"}));
@ -345,15 +331,8 @@ void HeartbeatThread::runCoordinator() {
} }
} }
} }
}
result.clear(); VPackSlice slice =
result = _agency.getValues2("Sync/UserVersion");
if (result.successful()) {
velocypack::Slice slice =
result.slice()[0].get(std::vector<std::string>( result.slice()[0].get(std::vector<std::string>(
{_agency.prefixStripped(), "Sync", "UserVersion"})); {_agency.prefixStripped(), "Sync", "UserVersion"}));
@ -395,14 +374,9 @@ void HeartbeatThread::runCoordinator() {
} }
} }
} }
}
result = _agency.getValues2("Current/Version"); versionSlice = result.slice()[0].get(std::vector<std::string>(
if (result.successful()) { {_agency.prefixStripped(), "Plan", "Version"}));
VPackSlice versionSlice
= result.slice()[0].get(std::vector<std::string>(
{_agency.prefixStripped(), "Plan", "Version"}));
if (versionSlice.isInteger()) { if (versionSlice.isInteger()) {
uint64_t currentVersion = 0; uint64_t currentVersion = 0;
@ -419,19 +393,19 @@ void HeartbeatThread::runCoordinator() {
} }
} }
if (shouldSleep) { double remain = interval - (TRI_microtime() - start);
double remain = interval - (TRI_microtime() - start);
// sleep for a while if appropriate, on some systems usleep does not LOG(INFO) << "HeartbeatThread: remain is " << remain;
// like arguments greater than 1000000
while (remain > 0.0) { // sleep for a while if appropriate, on some systems usleep does not
if (remain >= 0.5) { // like arguments greater than 1000000
usleep(500000); while (remain > 0.0) {
remain -= 0.5; if (remain >= 0.5) {
} else { usleep(500000);
usleep((unsigned long)(remain * 1000.0 * 1000.0)); remain -= 0.5;
remain = 0.0; } else {
} usleep((unsigned long)(remain * 1000.0 * 1000.0));
remain = 0.0;
} }
} }
@ -477,39 +451,6 @@ void HeartbeatThread::removeDispatchedJob(ServerJobResult result) {
_condition.signal(); _condition.signal();
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief fetch the index id of the value of Sync/Commands/my-id from the
/// agency this index value is determined initially and it is passed to the
/// watch command (we're waiting for an entry with a higher id)
////////////////////////////////////////////////////////////////////////////////
uint64_t HeartbeatThread::getLastCommandIndex() {
// get the initial command state
AgencyCommResult result = _agency.getValues("Sync/Commands/" + _myId, false);
if (result.successful()) {
result.parse("Sync/Commands/", false);
std::map<std::string, AgencyCommResultEntry>::iterator it =
result._values.find(_myId);
if (it != result._values.end()) {
// found something
LOG(TRACE) << "last command index was: '" << (*it).second._index << "'";
return (*it).second._index;
}
}
if (result._index > 0) {
// use the value returned in header X-Etcd-Index
return result._index;
}
// nothing found. this is not an error
return 0;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief handles a plan version change, coordinator case /// @brief handles a plan version change, coordinator case
/// this is triggered if the heartbeat thread finds a new plan version number /// this is triggered if the heartbeat thread finds a new plan version number
@ -648,7 +589,8 @@ bool HeartbeatThread::handlePlanChangeCoordinator(uint64_t currentPlanVersion) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief handles a plan version change, DBServer case /// @brief handles a plan version change, DBServer case
/// this is triggered if the heartbeat thread finds a new plan version number /// this is triggered if the heartbeat thread finds a new plan version number,
/// and every few heartbeats if the Current/Version has changed.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool HeartbeatThread::syncDBServerStatusQuo() { bool HeartbeatThread::syncDBServerStatusQuo() {
@ -716,21 +658,12 @@ bool HeartbeatThread::syncDBServerStatusQuo() {
/// notified about this particular change again). /// notified about this particular change again).
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool HeartbeatThread::handleStateChange(AgencyCommResult& result, bool HeartbeatThread::handleStateChange(AgencyCommResult& result) {
uint64_t& lastCommandIndex) { VPackSlice const slice = result.slice()[0].get(
result.parse("Sync/Commands/", false); std::vector<std::string>({ AgencyComm::prefixStripped(), "Sync",
"Commands", _myId }));
std::map<std::string, AgencyCommResultEntry>::const_iterator it = if (slice.isString()) {
result._values.find(_myId); std::string command = slice.copyString();
if (it != result._values.end()) {
lastCommandIndex = (*it).second._index;
std::string command = "";
VPackSlice const slice = it->second._vpack->slice();
if (slice.isString()) {
command = slice.copyString();
}
ServerState::StateEnum newState = ServerState::stringToState(command); ServerState::StateEnum newState = ServerState::stringToState(command);
if (newState != ServerState::STATE_UNDEFINED) { if (newState != ServerState::STATE_UNDEFINED) {

View File

@ -128,13 +128,7 @@ class HeartbeatThread : public Thread {
/// @brief handles a state change /// @brief handles a state change
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
bool handleStateChange(AgencyCommResult&, uint64_t&); bool handleStateChange(AgencyCommResult&);
//////////////////////////////////////////////////////////////////////////////
/// @brief fetch the last value of Sync/Commands/my-id from the agency
//////////////////////////////////////////////////////////////////////////////
uint64_t getLastCommandIndex();
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief sends the current server's state to the agency /// @brief sends the current server's state to the agency

View File

@ -608,15 +608,13 @@ static void JS_UniqidAgency(v8::FunctionCallbackInfo<v8::Value> const& args) {
TRI_V8_TRY_CATCH_BEGIN(isolate); TRI_V8_TRY_CATCH_BEGIN(isolate);
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
if (args.Length() < 1 || args.Length() > 3) { if (args.Length() > 2) {
TRI_V8_THROW_EXCEPTION_USAGE("uniqid(<key>, <count>, <timeout>)"); TRI_V8_THROW_EXCEPTION_USAGE("uniqid(<count>, <timeout>)");
} }
std::string const key = TRI_ObjectToString(args[0]);
uint64_t count = 1; uint64_t count = 1;
if (args.Length() > 1) { if (args.Length() > 0) {
count = TRI_ObjectToUInt64(args[1], true); count = TRI_ObjectToUInt64(args[0], true);
} }
if (count < 1 || count > 10000000) { if (count < 1 || count > 10000000) {
@ -624,18 +622,14 @@ static void JS_UniqidAgency(v8::FunctionCallbackInfo<v8::Value> const& args) {
} }
double timeout = 0.0; double timeout = 0.0;
if (args.Length() > 2) { if (args.Length() > 1) {
timeout = TRI_ObjectToDouble(args[2]); timeout = TRI_ObjectToDouble(args[1]);
} }
AgencyComm comm; AgencyComm comm;
AgencyCommResult result = comm.uniqid(key, count, timeout); uint64_t result = comm.uniqid(count, timeout);
if (!result.successful() || result._index == 0) { std::string const value = StringUtils::itoa(result);
THROW_AGENCY_EXCEPTION(result);
}
std::string const value = StringUtils::itoa(result._index);
TRI_V8_RETURN_STD_STRING(value); TRI_V8_RETURN_STD_STRING(value);
TRI_V8_TRY_CATCH_END TRI_V8_TRY_CATCH_END
@ -1070,7 +1064,7 @@ static void JS_UniqidClusterInfo(
TRI_V8_THROW_EXCEPTION_PARAMETER("<count> is invalid"); TRI_V8_THROW_EXCEPTION_PARAMETER("<count> is invalid");
} }
uint64_t value = ClusterInfo::instance()->uniqid(); uint64_t value = ClusterInfo::instance()->uniqid(count);
if (value == 0) { if (value == 0) {
TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,