mirror of https://gitee.com/bigwinds/arangodb
828 lines
30 KiB
C++
828 lines
30 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/// 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
|
|
/// @author Max Neunhoeffer
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef ARANGOD_CLUSTER_AGENCY_COMM_H
|
|
#define ARANGOD_CLUSTER_AGENCY_COMM_H 1
|
|
|
|
#include "Basics/Common.h"
|
|
#include "Basics/ReadWriteLock.h"
|
|
#include "Basics/json.h"
|
|
#include "Rest/HttpRequest.h"
|
|
#include <velocypack/Slice.h>
|
|
#include <velocypack/velocypack-aliases.h>
|
|
#include <type_traits>
|
|
|
|
#include <list>
|
|
|
|
namespace arangodb {
|
|
class Endpoint;
|
|
|
|
namespace httpclient {
|
|
class GeneralClientConnection;
|
|
}
|
|
|
|
namespace velocypack {
|
|
class Builder;
|
|
class Slice;
|
|
}
|
|
|
|
class AgencyComm;
|
|
|
|
struct AgencyEndpoint {
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates an agency endpoint
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyEndpoint(Endpoint*,
|
|
arangodb::httpclient::GeneralClientConnection*);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief destroys an agency endpoint
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
~AgencyEndpoint();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief the endpoint
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
Endpoint* _endpoint;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief the connection
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
arangodb::httpclient::GeneralClientConnection* _connection;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief whether or not the endpoint is busy
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool _busy;
|
|
};
|
|
|
|
struct AgencyConnectionOptions {
|
|
double _connectTimeout;
|
|
double _requestTimeout;
|
|
double _lockTimeout;
|
|
size_t _connectRetries;
|
|
};
|
|
|
|
struct AgencyCommResultEntry {
|
|
uint64_t _index;
|
|
std::shared_ptr<arangodb::velocypack::Builder> _vpack;
|
|
bool _isDir;
|
|
};
|
|
|
|
enum class AgencyValueOperationType {
|
|
SET,
|
|
OBSERVE,
|
|
UNOBSERVE,
|
|
PUSH,
|
|
PREPEND
|
|
};
|
|
|
|
enum class AgencySimpleOperationType {
|
|
INCREMENT_OP,
|
|
DECREMENT_OP,
|
|
DELETE_OP,
|
|
POP_OP,
|
|
SHIFT_OP
|
|
};
|
|
|
|
struct AgencyOperationType {
|
|
enum {VALUE, SIMPLE} type;
|
|
union {
|
|
AgencyValueOperationType value;
|
|
AgencySimpleOperationType simple;
|
|
};
|
|
|
|
// mop: hmmm...explicit implementation...maybe use to_string?
|
|
std::string toString() const {
|
|
switch(type) {
|
|
case VALUE:
|
|
switch(value) {
|
|
case AgencyValueOperationType::SET:
|
|
return "set";
|
|
case AgencyValueOperationType::OBSERVE:
|
|
return "observe";
|
|
case AgencyValueOperationType::UNOBSERVE:
|
|
return "unobserve";
|
|
case AgencyValueOperationType::PUSH:
|
|
return "push";
|
|
case AgencyValueOperationType::PREPEND:
|
|
return "prepend";
|
|
default:
|
|
return "unknown_operation_type";
|
|
}
|
|
break;
|
|
case SIMPLE:
|
|
switch(simple) {
|
|
case AgencySimpleOperationType::INCREMENT_OP:
|
|
return "increment";
|
|
case AgencySimpleOperationType::DECREMENT_OP:
|
|
return "decrement";
|
|
case AgencySimpleOperationType::DELETE_OP:
|
|
return "delete";
|
|
case AgencySimpleOperationType::POP_OP:
|
|
return "pop";
|
|
case AgencySimpleOperationType::SHIFT_OP:
|
|
return "shift";
|
|
default:
|
|
return "unknown_operation_type";
|
|
}
|
|
default:
|
|
return "unknown_operation_type";
|
|
}
|
|
}
|
|
};
|
|
|
|
struct AgencyPrecondition {
|
|
|
|
typedef enum {NONE, EMPTY, VALUE} Type;
|
|
|
|
AgencyPrecondition(std::string const& key, Type t, bool e);
|
|
|
|
AgencyPrecondition(std::string const& key, Type t, VPackSlice const s);
|
|
|
|
void toVelocyPack(arangodb::velocypack::Builder& builder) const;
|
|
|
|
std::string key;
|
|
Type type;
|
|
bool empty;
|
|
VPackSlice const value;
|
|
};
|
|
|
|
struct AgencyOperation {
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief constructs an operation
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyOperation(std::string const& key, AgencySimpleOperationType opType);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief constructs an operation with value
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyOperation(
|
|
std::string const& key,
|
|
AgencyValueOperationType opType,
|
|
VPackSlice const value
|
|
);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns to full operation formatted as a vpack slice and put
|
|
/// it into the argument builder
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
void toVelocyPack(arangodb::velocypack::Builder& builder) const;
|
|
|
|
uint32_t _ttl = 0;
|
|
VPackSlice _oldValue;
|
|
|
|
private:
|
|
std::string const _key;
|
|
AgencyOperationType _opType;
|
|
VPackSlice _value;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief AgencyTransaction base class
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
struct AgencyTransaction {
|
|
virtual std::string toJson() const = 0;
|
|
virtual void toVelocyPack(arangodb::velocypack::Builder& builder) const = 0;
|
|
virtual ~AgencyTransaction() {
|
|
}
|
|
virtual bool isWriteTransaction() const = 0;
|
|
};
|
|
|
|
struct AgencyWriteTransaction : public AgencyTransaction {
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief vector of preconditions
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::vector<AgencyPrecondition> preconditions;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief vector of operations
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::vector<AgencyOperation> operations;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief converts the transaction to velocypack
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
void toVelocyPack(arangodb::velocypack::Builder& builder) const override final;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief converts the transaction to json
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::string toJson() const override final;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief shortcut to create a transaction with one operation
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
explicit AgencyWriteTransaction(AgencyOperation const& operation) {
|
|
operations.push_back(operation);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief shortcut to create a transaction with one operation and a
|
|
/// precondition
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
explicit AgencyWriteTransaction(AgencyOperation const& operation,
|
|
AgencyPrecondition const& precondition) {
|
|
operations.push_back(operation);
|
|
preconditions.push_back(precondition);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief default constructor
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyWriteTransaction() = default;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief return type of transaction
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool isWriteTransaction() const override final {
|
|
return true;
|
|
}
|
|
};
|
|
|
|
struct AgencyReadTransaction : public AgencyTransaction {
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief vector of operations
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::vector<std::string> keys;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief converts the transaction to velocypack
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
void toVelocyPack(arangodb::velocypack::Builder& builder) const override final;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief converts the transaction to json
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::string toJson() const override final;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief shortcut to create a transaction with one operation
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
explicit AgencyReadTransaction(std::string const& 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
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyReadTransaction() = default;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief return type of transaction
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool isWriteTransaction() const override final {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
struct AgencyCommResult {
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief constructs a communication result
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief destroys a communication result
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
~AgencyCommResult();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns whether the last request was successful
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
inline bool successful() const {
|
|
return (_statusCode >= 200 && _statusCode <= 299);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief extract the connected flag from the result
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool connected() const;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief extract the http code from the result
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
int httpCode() const;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief extract the error code from the result
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
int errorCode() const;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief extract the error message from the result
|
|
/// if there is no error, an empty string will be returned
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::string errorMessage() const;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief extract the error details from the result
|
|
/// if there is no error, an empty string will be returned
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::string errorDetails() const;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief return the location header (might be empty)
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::string const location() const { return _location; }
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief return the body (might be empty)
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::string const body() const { return _body; }
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief flush the internal result buffer
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
void clear();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief recursively flatten the VelocyPack response into a map
|
|
///
|
|
/// stripKeyPrefix is decoded, as is the _globalPrefix
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//bool parseVelocyPackNode(arangodb::velocypack::Slice const&,
|
|
// std::string const&, bool);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// parse an agency result
|
|
/// note that stripKeyPrefix is a decoded, normal key!
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//bool parse(std::string const&, bool);
|
|
//VPackSlice parse(std::string const&);
|
|
|
|
VPackSlice slice();
|
|
void setVPack(std::shared_ptr<velocypack::Builder> vpack) {
|
|
_vpack = vpack;
|
|
}
|
|
|
|
private:
|
|
std::shared_ptr<velocypack::Builder> _vpack;
|
|
|
|
public:
|
|
std::string _location;
|
|
std::string _message;
|
|
std::string _body;
|
|
std::string _realBody;
|
|
|
|
std::map<std::string, AgencyCommResultEntry> _values;
|
|
int _statusCode;
|
|
bool _connected;
|
|
};
|
|
|
|
class AgencyCommLocker {
|
|
|
|
public:
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief constructs an agency comm locker
|
|
///
|
|
/// The keys mentioned in this class are all not yet encoded.
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommLocker(std::string const&, std::string const&, double = 0.0, double = 0.0);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief destroys an agency comm locker
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
~AgencyCommLocker();
|
|
|
|
public:
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief return whether the locking was successful
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool successful() const { return _isLocked; }
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief unlocks the lock
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
void unlock();
|
|
|
|
private:
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief update a lock version in the agency
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool updateVersion(AgencyComm&);
|
|
|
|
private:
|
|
std::string const _key;
|
|
std::string const _type;
|
|
std::shared_ptr<arangodb::velocypack::Builder> _vpack;
|
|
bool _isLocked;
|
|
};
|
|
|
|
class AgencyComm {
|
|
friend struct AgencyCommResult;
|
|
friend class AgencyCommLocker;
|
|
|
|
public:
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief cleans up all connections
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void cleanup();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief initialize agency comm channel
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool initialize();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief disconnects all communication channels
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void disconnect();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief adds an endpoint to the agents list
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool addEndpoint(std::string const&, bool = false);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief checks if an endpoint is present
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool hasEndpoint(std::string const&);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief get a stringified version of the endpoints
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static std::vector<std::string> getEndpoints();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief get a stringified version of the endpoints
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static std::string getEndpointsString();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief get a stringified version of the endpoints (unique)
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static std::string getUniqueEndpointsString();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets the global prefix for all operations
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool setPrefix(std::string const&);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns the global prefix for all operations
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static std::string prefixPath();
|
|
static std::string prefix();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief generate a timestamp
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static std::string generateStamp();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a new agency endpoint
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static AgencyEndpoint* createAgencyEndpoint(std::string const&);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sends the current server state to the agency
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult sendServerState(double ttl);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief gets the backend version
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::string getVersion();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief update a version number in the agency
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
inline bool increaseVersion(std::string const& key) {
|
|
AgencyCommResult result = increment(key);
|
|
return result.successful();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a directory in the backend
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult createDirectory(std::string const&);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets a value in the back end as string
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult setValue(std::string const&,
|
|
std::string const&, double);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sets a value in the back end
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult setValue(std::string const&,
|
|
arangodb::velocypack::Slice const&, double);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief checks whether a key exists
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool exists(std::string const&);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief gets one or multiple values from the back end
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult getValues(std::string const&);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief increment a value
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult increment(std::string const&);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief removes one or multiple values from the back end
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult removeValues(std::string const&, bool);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief compares and swaps a single value in the backend
|
|
/// the CAS condition is whether or not a previous value existed for the key
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult casValue(std::string const&,
|
|
arangodb::velocypack::Slice const&, bool, double,
|
|
double);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief compares and swaps a single value in the back end
|
|
/// the CAS condition is whether or not the previous value for the key was
|
|
/// identical to `oldValue`
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult casValue(std::string const&,
|
|
arangodb::velocypack::Slice const&,
|
|
arangodb::velocypack::Slice const&, double, double);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief get unique id
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
uint64_t uniqid(uint64_t, double);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief registers a callback on a key
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
bool registerCallback(std::string const& key, std::string const& endpoint);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief unregisters a callback on a key
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
bool unregisterCallback(std::string const& key, std::string const& endpoint);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief acquire a read lock
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool lockRead(std::string const&, double, double);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief acquire a write lock
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool lockWrite(std::string const&, double, double);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief release a read lock
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool unlockRead(std::string const&, double);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief release a write lock
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool unlockWrite(std::string const&, double);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sends a transaction to the agency, handling failover
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult sendTransactionWithFailover(
|
|
AgencyTransaction const&,
|
|
double timeout = 0.0
|
|
);
|
|
|
|
private:
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief acquire a lock
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool lock(std::string const&, double, double,
|
|
arangodb::velocypack::Slice const&);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief release a lock
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool unlock(std::string const&, arangodb::velocypack::Slice const&, double);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief pop an endpoint from the queue
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyEndpoint* popEndpoint(std::string const&);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief reinsert an endpoint into the queue
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
void requeueEndpoint(AgencyEndpoint*, bool);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief construct a URL, without a key
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::string buildUrl() const;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sends a write HTTP request to the agency, handling failover
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult sendWithFailover(
|
|
arangodb::GeneralRequest::RequestType,
|
|
double,
|
|
std::string const&,
|
|
std::string const&,
|
|
bool
|
|
);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief sends data to the URL
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
AgencyCommResult send(arangodb::httpclient::GeneralClientConnection*,
|
|
arangodb::GeneralRequest::RequestType, double,
|
|
std::string const&, std::string const&);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief tries to establish a communication channel
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static bool tryConnect();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief will initialize agency if it is freshly started
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool ensureStructureInitialized();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief will try to initialize a new agency
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool tryInitializeStructure(std::string const& jwtSecret);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief checks if we are responsible for initializing the agency
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool shouldInitializeStructure();
|
|
|
|
private:
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief the static global URL prefix
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static std::string const AGENCY_URL_PREFIX;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief the (variable) global prefix
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static std::string _globalPrefix;
|
|
static std::string _globalPrefixStripped;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief endpoints lock
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static arangodb::basics::ReadWriteLock _globalLock;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief all endpoints
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static std::list<AgencyEndpoint*> _globalEndpoints;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief global connection options
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static AgencyConnectionOptions _globalConnectionOptions;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief number of connections per endpoint
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static size_t const NumConnections = 3;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief initial sleep time
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static unsigned long const InitialSleepTime = 5000;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/// @brief maximum sleep time
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static unsigned long const MaxSleepTime = 50000;
|
|
};
|
|
}
|
|
|
|
#endif
|