1
0
Fork 0

fetch commands for server from agency

This commit is contained in:
Jan Steemann 2013-12-09 17:44:19 +01:00
parent 2b06a0778d
commit 996be652f1
8 changed files with 332 additions and 42 deletions

View File

@ -27,6 +27,7 @@
#include "Sharding/AgencyComm.h" #include "Sharding/AgencyComm.h"
#include "Basics/ReadLocker.h" #include "Basics/ReadLocker.h"
#include "Basics/StringUtils.h"
#include "Basics/WriteLocker.h" #include "Basics/WriteLocker.h"
#include "BasicsC/json.h" #include "BasicsC/json.h"
#include "BasicsC/logging.h" #include "BasicsC/logging.h"
@ -105,7 +106,8 @@ AgencyCommResult::~AgencyCommResult () {
bool AgencyCommResult::processJsonNode (TRI_json_t const* node, bool AgencyCommResult::processJsonNode (TRI_json_t const* node,
std::map<std::string, std::string>& out, std::map<std::string, std::string>& out,
std::string const& stripPrefix) { std::string const& stripKeyPrefix,
bool returnIndex) const {
if (! TRI_IsArrayJson(node)) { if (! TRI_IsArrayJson(node)) {
return true; return true;
} }
@ -118,7 +120,7 @@ bool AgencyCommResult::processJsonNode (TRI_json_t const* node,
} }
// make sure we don't strip more bytes than the key is long // make sure we don't strip more bytes than the key is long
const size_t offset = AgencyComm::_globalPrefix.size() + stripPrefix.size(); const size_t offset = AgencyComm::_globalPrefix.size() + stripKeyPrefix.size();
const size_t length = key->_value._string.length - 1; const size_t length = key->_value._string.length - 1;
std::string prefix; std::string prefix;
@ -146,7 +148,10 @@ bool AgencyCommResult::processJsonNode (TRI_json_t const* node,
const size_t n = TRI_LengthVector(&nodes->_value._objects); const size_t n = TRI_LengthVector(&nodes->_value._objects);
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
if (! processJsonNode((TRI_json_t const*) TRI_AtVector(&nodes->_value._objects, i), out, stripPrefix)) { if (! processJsonNode((TRI_json_t const*) TRI_AtVector(&nodes->_value._objects, i),
out,
stripKeyPrefix,
returnIndex)) {
return false; return false;
} }
} }
@ -162,7 +167,21 @@ bool AgencyCommResult::processJsonNode (TRI_json_t const* node,
} }
if (! prefix.empty()) { if (! prefix.empty()) {
out[prefix] = std::string(value->_value._string.data, value->_value._string.length - 1); if (returnIndex) {
// return "modifiedIndex"
TRI_json_t const* modifiedIndex = TRI_LookupArrayJson(node, "modifiedIndex");
if (! TRI_IsNumberJson(modifiedIndex)) {
return false;
}
// convert the number to an integer
out[prefix] = triagens::basics::StringUtils::itoa((uint64_t) modifiedIndex->_value._number);
}
else {
// otherwise return value
out[prefix] = std::string(value->_value._string.data, value->_value._string.length - 1);
}
} }
} }
@ -174,7 +193,8 @@ bool AgencyCommResult::processJsonNode (TRI_json_t const* node,
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool AgencyCommResult::flattenJson (std::map<std::string, std::string>& out, bool AgencyCommResult::flattenJson (std::map<std::string, std::string>& out,
std::string const& stripPrefix) { std::string const& stripKeyPrefix,
bool returnIndex) const {
TRI_json_t* json = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, _body.c_str()); TRI_json_t* json = TRI_JsonString(TRI_UNKNOWN_MEM_ZONE, _body.c_str());
if (! TRI_IsArrayJson(json)) { if (! TRI_IsArrayJson(json)) {
@ -187,7 +207,7 @@ bool AgencyCommResult::flattenJson (std::map<std::string, std::string>& out,
// get "node" attribute // get "node" attribute
TRI_json_t const* node = TRI_LookupArrayJson(json, "node"); TRI_json_t const* node = TRI_LookupArrayJson(json, "node");
const bool result = processJsonNode(node, out, stripPrefix); const bool result = processJsonNode(node, out, stripKeyPrefix, returnIndex);
TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json); TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
return result; return result;
@ -547,6 +567,7 @@ bool AgencyComm::setValue (std::string const& key,
send(agencyEndpoint->_connection, send(agencyEndpoint->_connection,
triagens::rest::HttpRequest::HTTP_REQUEST_PUT, triagens::rest::HttpRequest::HTTP_REQUEST_PUT,
_globalConnectionOptions._requestTimeout,
result, result,
buildUrl(key), buildUrl(key),
"value=" + value); "value=" + value);
@ -590,6 +611,7 @@ AgencyCommResult AgencyComm::getValues (std::string const& key,
send(agencyEndpoint->_connection, send(agencyEndpoint->_connection,
triagens::rest::HttpRequest::HTTP_REQUEST_GET, triagens::rest::HttpRequest::HTTP_REQUEST_GET,
_globalConnectionOptions._requestTimeout * 1000.0 * 1000.0,
result, result,
url); url);
@ -632,6 +654,7 @@ bool AgencyComm::removeValues (std::string const& key,
send(agencyEndpoint->_connection, send(agencyEndpoint->_connection,
triagens::rest::HttpRequest::HTTP_REQUEST_DELETE, triagens::rest::HttpRequest::HTTP_REQUEST_DELETE,
_globalConnectionOptions._requestTimeout,
result, result,
url); url);
@ -664,12 +687,45 @@ int AgencyComm::casValue (std::string const& key,
/// @brief blocks on a change of a single value in the backend /// @brief blocks on a change of a single value in the backend
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
AgencyCommResult AgencyComm::watchValues (std::string const& key, AgencyCommResult AgencyComm::watchValue (std::string const& key,
double timeout) { uint64_t waitIndex,
double timeout) {
std::string url(buildUrl(key));
url += "?wait=true";
if (waitIndex > 0) {
url += "&waitIndex=" + triagens::basics::StringUtils::itoa(waitIndex);
}
AgencyCommResult result; AgencyCommResult result;
size_t numEndpoints;
// TODO {
READ_LOCKER(AgencyComm::_globalLock);
numEndpoints = AgencyComm::_globalEndpoints.size();
assert(numEndpoints > 0);
}
size_t tries = 0;
while (tries++ < numEndpoints) {
AgencyEndpoint* agencyEndpoint = popEndpoint();
send(agencyEndpoint->_connection,
triagens::rest::HttpRequest::HTTP_REQUEST_GET,
timeout == 0.0 ? _globalConnectionOptions._requestTimeout : timeout,
result,
url);
if (requeueEndpoint(agencyEndpoint, result.successful())) {
// we're done
break;
}
// otherwise, try next
}
// if we get here, we could not send data to any endpoint successfully
return result; return result;
} }
@ -765,6 +821,7 @@ std::string AgencyComm::buildUrl (std::string const& relativePart) const {
bool AgencyComm::send (triagens::httpclient::GeneralClientConnection* connection, bool AgencyComm::send (triagens::httpclient::GeneralClientConnection* connection,
triagens::rest::HttpRequest::HttpRequestType method, triagens::rest::HttpRequest::HttpRequestType method,
double timeout,
AgencyCommResult& result, AgencyCommResult& result,
std::string const& url) { std::string const& url) {
// only these methods can be called without a body // only these methods can be called without a body
@ -772,7 +829,7 @@ bool AgencyComm::send (triagens::httpclient::GeneralClientConnection* connection
method == triagens::rest::HttpRequest::HTTP_REQUEST_GET || method == triagens::rest::HttpRequest::HTTP_REQUEST_GET ||
method == triagens::rest::HttpRequest::HTTP_REQUEST_HEAD); method == triagens::rest::HttpRequest::HTTP_REQUEST_HEAD);
return send(connection, method, result, url, ""); return send(connection, method, timeout, result, url, "");
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -781,6 +838,7 @@ bool AgencyComm::send (triagens::httpclient::GeneralClientConnection* connection
bool AgencyComm::send (triagens::httpclient::GeneralClientConnection* connection, bool AgencyComm::send (triagens::httpclient::GeneralClientConnection* connection,
triagens::rest::HttpRequest::HttpRequestType method, triagens::rest::HttpRequest::HttpRequestType method,
double timeout,
AgencyCommResult& result, AgencyCommResult& result,
std::string const& url, std::string const& url,
std::string const& body) { std::string const& body) {
@ -795,8 +853,8 @@ bool AgencyComm::send (triagens::httpclient::GeneralClientConnection* connection
url.c_str(), url.c_str(),
body.c_str()); body.c_str());
triagens::httpclient::SimpleHttpClient client(connection, triagens::httpclient::SimpleHttpClient client(connection,
_globalConnectionOptions._requestTimeout, timeout,
false); false);
// set up headers // set up headers

View File

@ -121,10 +121,12 @@ namespace triagens {
bool processJsonNode (struct TRI_json_s const*, bool processJsonNode (struct TRI_json_s const*,
std::map<std::string, std::string>&, std::map<std::string, std::string>&,
std::string const&); std::string const&,
bool) const;
bool flattenJson (std::map<std::string, std::string>&, bool flattenJson (std::map<std::string, std::string>&,
std::string const&); std::string const&,
bool) const;
std::string _message; std::string _message;
std::string _body; std::string _body;
@ -226,37 +228,38 @@ namespace triagens {
/// @brief sets a value in the back end /// @brief sets a value in the back end
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool setValue (std::string const& key, bool setValue (std::string const&,
std::string const& value); std::string const&);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief gets one or multiple values from the back end /// @brief gets one or multiple values from the back end
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
AgencyCommResult getValues (std::string const& key, AgencyCommResult getValues (std::string const&,
bool recursive); bool);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief removes one or multiple values from the back end /// @brief removes one or multiple values from the back end
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool removeValues (std::string const& key, bool removeValues (std::string const&,
bool recursive); bool);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief compares and swaps a single value in the back end /// @brief compares and swaps a single value in the back end
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int casValue (std::string const& key, int casValue (std::string const&,
std::string const& oldValue, std::string const&,
std::string const& newValue); std::string const&);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief blocks on a change of a single value in the back end /// @brief blocks on a change of a single value in the back end
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
AgencyCommResult watchValues (std::string const& key, AgencyCommResult watchValue (std::string const&,
double timeout); uint64_t,
double);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- private methods // --SECTION-- private methods
@ -289,6 +292,7 @@ namespace triagens {
bool send (triagens::httpclient::GeneralClientConnection*, bool send (triagens::httpclient::GeneralClientConnection*,
triagens::rest::HttpRequest::HttpRequestType, triagens::rest::HttpRequest::HttpRequestType,
double,
AgencyCommResult&, AgencyCommResult&,
std::string const&); std::string const&);
@ -298,6 +302,7 @@ namespace triagens {
bool send (triagens::httpclient::GeneralClientConnection*, bool send (triagens::httpclient::GeneralClientConnection*,
triagens::rest::HttpRequest::HttpRequestType, triagens::rest::HttpRequest::HttpRequestType,
double,
AgencyCommResult&, AgencyCommResult&,
std::string const&, std::string const&,
std::string const&); std::string const&);

View File

@ -89,7 +89,7 @@ void ApplicationSharding::setupOptions (map<string, basics::ProgramOptionsDescri
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc} /// @brief prepare validate the startup options
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool ApplicationSharding::prepare () { bool ApplicationSharding::prepare () {
@ -119,7 +119,8 @@ bool ApplicationSharding::prepare () {
const string unified = triagens::rest::Endpoint::getUnifiedForm(_agencyEndpoints[i]); const string unified = triagens::rest::Endpoint::getUnifiedForm(_agencyEndpoints[i]);
if (unified.empty()) { if (unified.empty()) {
LOG_FATAL_AND_EXIT("invalid endpoint '%s' specified for --cluster.agency-endpoint", _agencyEndpoints[i].c_str()); LOG_FATAL_AND_EXIT("invalid endpoint '%s' specified for --cluster.agency-endpoint",
_agencyEndpoints[i].c_str());
} }
AgencyComm::addEndpoint(unified); AgencyComm::addEndpoint(unified);
@ -172,16 +173,38 @@ bool ApplicationSharding::start () {
if (role == ServerState::ROLE_UNDEFINED) { if (role == ServerState::ROLE_UNDEFINED) {
// no role found // no role found
LOG_FATAL_AND_EXIT("unable to determine unambiguous role for server '%s'. No role configured at endpoints (%s)", LOG_FATAL_AND_EXIT("unable to determine unambiguous role for server '%s'. No role configured in agency (%s)",
_myId.c_str(), _myId.c_str(),
endpoints.c_str()); endpoints.c_str());
} }
// check if my-address is set
if (_myAddress.empty()) {
// no address given, now ask the agency for out address
_myAddress = getEndpointForId();
}
if (_myAddress.empty()) {
LOG_FATAL_AND_EXIT("unable to determine internal address for server '%s'. "
"Please specify --cluster.my-address or configure the address for this server in the agency.",
_myId.c_str());
}
// now we can validate --cluster.my-address
const string unified = triagens::rest::Endpoint::getUnifiedForm(_myAddress);
if (unified.empty()) {
LOG_FATAL_AND_EXIT("invalid endpoint '%s' specified for --cluster.my-address",
_myAddress.c_str());
}
ServerState::instance()->setRole(role); ServerState::instance()->setRole(role);
ServerState::instance()->setState(ServerState::STATE_STARTUP); ServerState::instance()->setState(ServerState::STATE_STARTUP);
LOG_INFO("Cluster feature is turned on. Server id: '%s', role: %s, agency endpoints: %s", LOG_INFO("Cluster feature is turned on. Server id: '%s', internal address: %s, role: %s, agency endpoints: %s",
_myId.c_str(), _myId.c_str(),
_myAddress.c_str(),
ServerState::roleToString(role).c_str(), ServerState::roleToString(role).c_str(),
endpoints.c_str()); endpoints.c_str());
@ -230,6 +253,38 @@ void ApplicationSharding::stop () {
// --SECTION-- private methods // --SECTION-- private methods
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief lookup the server's endpoint by scanning Config/MapIDToEnpdoint for
/// our id
////////////////////////////////////////////////////////////////////////////////
std::string ApplicationSharding::getEndpointForId () const {
// fetch value at Config/MapIDToEndpoint
AgencyComm comm;
AgencyCommResult result = comm.getValues("Config/MapIDToEndpoint/" + _myId, false);
if (result.successful()) {
std::map<std::string, std::string> out;
if (! result.flattenJson(out, "Config/MapIDToEndpoint/", false)) {
LOG_FATAL_AND_EXIT("Got an invalid JSON response for Config/MapIDToEndpoint");
}
// check if we can find ourselves in the list returned by the agency
std::map<std::string, std::string>::const_iterator it = out.find(_myId);
if (it != out.end()) {
LOG_TRACE("using remote value '%s' for --cluster.my-address",
(*it).second.c_str());
return (*it).second;
}
}
// not found
return "";
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief lookup the server role by scanning TmpConfig/Coordinators for our id /// @brief lookup the server role by scanning TmpConfig/Coordinators for our id
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -249,7 +304,7 @@ ServerState::RoleEnum ApplicationSharding::checkCoordinatorsList () const {
} }
std::map<std::string, std::string> out; std::map<std::string, std::string> out;
if (! result.flattenJson(out, "TmpConfig/Coordinators/")) { if (! result.flattenJson(out, "TmpConfig/Coordinators/", false)) {
LOG_FATAL_AND_EXIT("Got an invalid JSON response for TmpConfig/Coordinators"); LOG_FATAL_AND_EXIT("Got an invalid JSON response for TmpConfig/Coordinators");
} }
@ -283,7 +338,7 @@ ServerState::RoleEnum ApplicationSharding::checkServersList () const {
} }
std::map<std::string, std::string> out; std::map<std::string, std::string> out;
if (! result.flattenJson(out, "TmpConfig/DBServers/")) { if (! result.flattenJson(out, "TmpConfig/DBServers/", false)) {
LOG_FATAL_AND_EXIT("Got an invalid JSON response for TmpConfig/DBServers"); LOG_FATAL_AND_EXIT("Got an invalid JSON response for TmpConfig/DBServers");
} }

View File

@ -114,6 +114,13 @@ namespace triagens {
// --SECTION-- private methods // --SECTION-- private methods
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief lookup the server's endpoint by scanning Config/MapIDToEnpdoint for
/// our id
////////////////////////////////////////////////////////////////////////////////
std::string getEndpointForId () const;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief lookup the server role by scanning TmpConfig/Coordinators for our id /// @brief lookup the server role by scanning TmpConfig/Coordinators for our id
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -72,21 +72,66 @@ HeartbeatThread::~HeartbeatThread () {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief heartbeat main loop /// @brief heartbeat main loop
/// the heartbeat thread constantly reports the current server status to the
/// agency. it does so by sending the current state string to the key
/// "State/ServerStates/" + my-id.
/// after transferring the current state to the agency, the heartbeat thread
/// will wait for changes on the "Commands/" + my-id key. If no changes occur,
/// then the request it aborted and the heartbeat thread will go on with
/// reporting its state to the agency again. If it notices a change when
/// watching the command key, it will wake up and apply the change locally.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void HeartbeatThread::run () { void HeartbeatThread::run () {
LOG_TRACE("starting heartbeat thread"); LOG_TRACE("starting heartbeat thread");
while (! _stop) { // convert timeout to seconds
LOG_TRACE("sending heartbeat"); const double interval = (double) _interval / 1000.0 / 1000.0;
// value of /Commands/my-id at startup
uint64_t lastCommandIndex = getLastCommandIndex();
while (! _stop) {
LOG_TRACE("sending heartbeat to agency");
// send our state to the agency.
// we don't care if this fails
sendState(); sendState();
if (_stop) {
break;
}
// watch Commands/my-id for changes
// TODO: check if this is CPU-intensive and whether we need to sleep
AgencyCommResult result = _agency.watchValue("Commands/" + _myId,
lastCommandIndex + 1,
interval);
if (_stop) {
break;
}
if (result.successful()) {
// value has changed!
handleStateChange(result, lastCommandIndex);
// sleep a while
CONDITION_LOCKER(guard, _condition);
guard.wait(_interval);
CONDITION_LOCKER(guard, _condition); }
guard.wait(_interval); else {
// value did not change, but we already blocked waiting for a change...
// nothing to do here
}
} }
// another thread is waiting for this value to shut down properly
_stop = 2;
LOG_TRACE("stopping heartbeat thread"); LOG_TRACE("stopped heartbeat thread");
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -107,16 +152,94 @@ bool HeartbeatThread::init () {
return true; return true;
} }
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief fetch the index id of the value of /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("Commands/" + _myId, false);
if (result.successful()) {
std::map<std::string, std::string> out;
if (result.flattenJson(out, "Commands/", true)) {
// check if we can find ourselves in the list returned by the agency
std::map<std::string, std::string>::const_iterator it = out.find(_myId);
if (it != out.end()) {
// found something
LOG_TRACE("last command index was: '%s'", (*it).second.c_str());
return triagens::basics::StringUtils::uint64((*it).second);
}
}
}
// nothing found. this is not an error
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief handles a state change
/// this is triggered if the watch command reports a change
/// when this is called, it will update the index value of the last command
/// (we'll pass the updated index value to the next watches so we don't get
/// notified about this particular change again).
////////////////////////////////////////////////////////////////////////////////
bool HeartbeatThread::handleStateChange (AgencyCommResult const& result,
uint64_t& lastCommandIndex) {
std::map<std::string, std::string> out;
if (result.flattenJson(out, "Commands/", true)) {
// get the new value of "modifiedIndex"
std::map<std::string, std::string>::const_iterator it = out.find(_myId);
if (it != out.end()) {
lastCommandIndex = triagens::basics::StringUtils::uint64((*it).second);
}
}
out.clear();
if (result.flattenJson(out, "Commands/", false)) {
// get the new value!
std::map<std::string, std::string>::const_iterator it = out.find(_myId);
if (it != out.end()) {
const std::string command = (*it).second;
ServerState::StateEnum newState = ServerState::stringToState(command);
if (newState != ServerState::STATE_UNDEFINED) {
// state change.
ServerState::instance()->setState(newState);
return true;
}
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief sends the current server's state to the agency /// @brief sends the current server's state to the agency
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool HeartbeatThread::sendState () { bool HeartbeatThread::sendState () {
const std::string value = ServerState::stateToString(ServerState::instance()->getState()) + ":" + AgencyComm::generateStamp(); const std::string value = ServerState::stateToString(ServerState::instance()->getState()) +
":" +
AgencyComm::generateStamp();
// return value is intentionally not handled // return value is intentionally not handled
// if sending the current state fails, we'll just try again in the next iteration // if sending the current state fails, we'll just try again in the next iteration
bool result = _agency.setValue("state/servers/state/" + _myId, value); bool result = _agency.setValue("State/ServerStates/" + _myId, value);
if (result) { if (result) {
_numFails = 0; _numFails = 0;

View File

@ -31,6 +31,7 @@
#include "Basics/Common.h" #include "Basics/Common.h"
#include "Basics/ConditionVariable.h" #include "Basics/ConditionVariable.h"
#include "Basics/Thread.h" #include "Basics/Thread.h"
#include "BasicsC/logging.h"
#include "Sharding/AgencyComm.h" #include "Sharding/AgencyComm.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -88,8 +89,18 @@ namespace triagens {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void stop () { void stop () {
if (_stop > 0) {
return;
}
LOG_TRACE("stopping heartbeat thread");
_stop = 1; _stop = 1;
_condition.signal(); _condition.signal();
while (_stop != 2) {
usleep(1000);
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -110,6 +121,19 @@ namespace triagens {
private: private:
////////////////////////////////////////////////////////////////////////////////
/// @brief handles a state change
////////////////////////////////////////////////////////////////////////////////
bool handleStateChange (AgencyCommResult const&,
uint64_t&);
////////////////////////////////////////////////////////////////////////////////
/// @brief fetch the last value of /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

@ -99,6 +99,19 @@ std::string ServerState::roleToString (RoleEnum role) {
return ""; return "";
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief convert a string representation to a state
////////////////////////////////////////////////////////////////////////////////
ServerState::StateEnum ServerState::stringToState (std::string const& value) {
if (value == "SHUTDOWN") {
return STATE_SHUTDOWN;
}
// TODO: do we need to understand other states, too?
return STATE_UNDEFINED;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief get the string representation of a state /// @brief get the string representation of a state
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -166,10 +179,10 @@ void ServerState::setState (StateEnum state) {
} }
if (result) { if (result) {
LOG_TRACE("changing state of %s server from %s to %s", LOG_INFO("changing state of %s server from %s to %s",
ServerState::roleToString(_role).c_str(), ServerState::roleToString(_role).c_str(),
ServerState::stateToString(_state).c_str(), ServerState::stateToString(_state).c_str(),
ServerState::stateToString(state).c_str()); ServerState::stateToString(state).c_str());
_state = state; _state = state;
} }

View File

@ -124,6 +124,11 @@ namespace triagens {
static std::string stateToString (StateEnum); static std::string stateToString (StateEnum);
////////////////////////////////////////////////////////////////////////////////
/// @brief convert a string representation to a state
////////////////////////////////////////////////////////////////////////////////
static StateEnum stringToState (std::string const&);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- public methods // --SECTION-- public methods