mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:arangodb/arangodb into devel
This commit is contained in:
commit
eeebfe94d8
|
@ -22,6 +22,7 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "Node.h"
|
#include "Node.h"
|
||||||
|
#include "Store.h"
|
||||||
|
|
||||||
#include "Basics/StringUtils.h"
|
#include "Basics/StringUtils.h"
|
||||||
|
|
||||||
|
@ -58,13 +59,20 @@ inline std::vector<std::string> split(const std::string& value, char separator)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct with node name
|
// Construct with node name
|
||||||
Node::Node (std::string const& name) : _node_name(name), _parent(nullptr) {
|
Node::Node (std::string const& name) : _node_name(name), _parent(nullptr),
|
||||||
|
_store(nullptr) {
|
||||||
_value.clear();
|
_value.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct with node name in tree structure
|
// Construct with node name in tree structure
|
||||||
Node::Node (std::string const& name, Node* parent) :
|
Node::Node (std::string const& name, Node* parent) :
|
||||||
_node_name(name), _parent(parent) {
|
_node_name(name), _parent(parent), _store(nullptr) {
|
||||||
|
_value.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct for store
|
||||||
|
Node::Node (std::string const& name, Store* store) :
|
||||||
|
_node_name(name), _parent(nullptr), _store(store) {
|
||||||
_value.clear();
|
_value.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +223,14 @@ Node& Node::root() {
|
||||||
return *tmp;
|
return *tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Store& Node::store() {
|
||||||
|
return *(root()._store);
|
||||||
|
}
|
||||||
|
|
||||||
|
Store const& Node::store() const {
|
||||||
|
return *(root()._store);
|
||||||
|
}
|
||||||
|
|
||||||
// velocypack value type of this node
|
// velocypack value type of this node
|
||||||
ValueType Node::valueType() const {
|
ValueType Node::valueType() const {
|
||||||
return slice().type();
|
return slice().type();
|
||||||
|
@ -224,7 +240,7 @@ ValueType Node::valueType() const {
|
||||||
bool Node::addTimeToLive (long millis) {
|
bool Node::addTimeToLive (long millis) {
|
||||||
auto tkey = std::chrono::system_clock::now() +
|
auto tkey = std::chrono::system_clock::now() +
|
||||||
std::chrono::milliseconds(millis);
|
std::chrono::milliseconds(millis);
|
||||||
root()._timeTable.insert(
|
store().timeTable().insert(
|
||||||
std::pair<TimePoint,std::shared_ptr<Node>>(
|
std::pair<TimePoint,std::shared_ptr<Node>>(
|
||||||
tkey, _parent->_children[_node_name]));
|
tkey, _parent->_children[_node_name]));
|
||||||
_ttl = tkey;
|
_ttl = tkey;
|
||||||
|
@ -234,10 +250,10 @@ bool Node::addTimeToLive (long millis) {
|
||||||
// remove time to live entry for this node
|
// remove time to live entry for this node
|
||||||
bool Node::removeTimeToLive () {
|
bool Node::removeTimeToLive () {
|
||||||
if (_ttl != std::chrono::system_clock::time_point()) {
|
if (_ttl != std::chrono::system_clock::time_point()) {
|
||||||
auto ret = root()._timeTable.equal_range(_ttl);
|
auto ret = store().timeTable().equal_range(_ttl);
|
||||||
for (auto it = ret.first; it!=ret.second;) {
|
for (auto it = ret.first; it!=ret.second;) {
|
||||||
if (it->second == _parent->_children[_node_name]) {
|
if (it->second == _parent->_children[_node_name]) {
|
||||||
root()._timeTable.erase(it);
|
store().timeTable().erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++it;
|
++it;
|
||||||
|
@ -247,7 +263,7 @@ bool Node::removeTimeToLive () {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Node::observedBy (std::string const& url) const {
|
inline bool Node::observedBy (std::string const& url) const {
|
||||||
auto ret = root()._observerTable.equal_range(url);
|
auto ret = store().observerTable().equal_range(url);
|
||||||
for (auto it = ret.first; it!=ret.second; ++it) {
|
for (auto it = ret.first; it!=ret.second; ++it) {
|
||||||
if (it->second == uri()) {
|
if (it->second == uri()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -406,8 +422,8 @@ template<> bool Node::handle<OBSERVE> (VPackSlice const& slice) {
|
||||||
|
|
||||||
// check if such entry exists
|
// check if such entry exists
|
||||||
if (!observedBy(url)) {
|
if (!observedBy(url)) {
|
||||||
root()._observerTable.emplace(std::pair<std::string,std::string>(url,uri));
|
store().observerTable().emplace(std::pair<std::string,std::string>(url,uri));
|
||||||
root()._observedTable.emplace(std::pair<std::string,std::string>(uri,url));
|
store().observedTable().emplace(std::pair<std::string,std::string>(uri,url));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,17 +442,17 @@ template<> bool Node::handle<UNOBSERVE> (VPackSlice const& slice) {
|
||||||
|
|
||||||
// delete in both cases a single entry (ensured above)
|
// delete in both cases a single entry (ensured above)
|
||||||
// breaking the iterators is fine then
|
// breaking the iterators is fine then
|
||||||
auto ret = root()._observerTable.equal_range(url);
|
auto ret = store().observerTable().equal_range(url);
|
||||||
for (auto it = ret.first; it!=ret.second; ++it) {
|
for (auto it = ret.first; it!=ret.second; ++it) {
|
||||||
if (it->second == uri) {
|
if (it->second == uri) {
|
||||||
root()._observerTable.erase(it);
|
store().observerTable().erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = root()._observedTable.equal_range(uri);
|
ret = store().observedTable().equal_range(uri);
|
||||||
for (auto it = ret.first; it!=ret.second; ++it) {
|
for (auto it = ret.first; it!=ret.second; ++it) {
|
||||||
if (it->second == url) {
|
if (it->second == url) {
|
||||||
root()._observedTable.erase(it);
|
store().observedTable().erase(it);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -555,12 +571,6 @@ std::ostream& Node::print (std::ostream& o) const {
|
||||||
o << std::endl;
|
o << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_timeTable.empty()) {
|
|
||||||
for (auto const& i : _timeTable) {
|
|
||||||
o << i.second.get() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,8 @@ class Node;
|
||||||
typedef std::chrono::system_clock::time_point TimePoint;
|
typedef std::chrono::system_clock::time_point TimePoint;
|
||||||
typedef std::multimap<TimePoint, std::shared_ptr<Node>> TimeTable;
|
typedef std::multimap<TimePoint, std::shared_ptr<Node>> TimeTable;
|
||||||
|
|
||||||
|
class Store;
|
||||||
|
|
||||||
/// @brief Simple tree implementation
|
/// @brief Simple tree implementation
|
||||||
class Node {
|
class Node {
|
||||||
|
|
||||||
|
@ -80,6 +82,9 @@ public:
|
||||||
/// @brief Construct with name and introduce to tree under parent
|
/// @brief Construct with name and introduce to tree under parent
|
||||||
Node (std::string const& name, Node* parent);
|
Node (std::string const& name, Node* parent);
|
||||||
|
|
||||||
|
/// @brief Construct with name and introduce to tree under parent
|
||||||
|
Node (std::string const& name, Store* store);
|
||||||
|
|
||||||
/// @brief Default dtor
|
/// @brief Default dtor
|
||||||
virtual ~Node ();
|
virtual ~Node ();
|
||||||
|
|
||||||
|
@ -157,6 +162,9 @@ public:
|
||||||
/// @brief Is this node being observed by url
|
/// @brief Is this node being observed by url
|
||||||
bool observedBy (std::string const& url) const;
|
bool observedBy (std::string const& url) const;
|
||||||
|
|
||||||
|
Store& store();
|
||||||
|
Store const& store() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/// @brief Add time to live entry
|
/// @brief Add time to live entry
|
||||||
|
@ -168,17 +176,11 @@ protected:
|
||||||
std::string _node_name; /**< @brief my name */
|
std::string _node_name; /**< @brief my name */
|
||||||
|
|
||||||
Node* _parent; /**< @brief parent */
|
Node* _parent; /**< @brief parent */
|
||||||
|
Store* _store; /**< @brief Store */
|
||||||
Children _children; /**< @brief child nodes */
|
Children _children; /**< @brief child nodes */
|
||||||
TimePoint _ttl; /**< @brief my expiry */
|
TimePoint _ttl; /**< @brief my expiry */
|
||||||
Buffer<uint8_t> _value; /**< @brief my value */
|
Buffer<uint8_t> _value; /**< @brief my value */
|
||||||
|
|
||||||
/// @brief Table of expiries in tree (only used in root node)
|
|
||||||
std::multimap<TimePoint, std::shared_ptr<Node>> _timeTable;
|
|
||||||
|
|
||||||
/// @brief Table of observers in tree (only used in root node)
|
|
||||||
std::multimap <std::string,std::string> _observerTable;
|
|
||||||
std::multimap <std::string,std::string> _observedTable;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<< (std::ostream& o, Node const& n) {
|
inline std::ostream& operator<< (std::ostream& o, Node const& n) {
|
||||||
|
|
|
@ -99,7 +99,7 @@ inline static bool endpointPathFromUrl (
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create with name
|
// Create with name
|
||||||
Store::Store (std::string const& name) : Node(name), Thread(name) {}
|
Store::Store (std::string const& name) : Thread(name), _node(name,this) {}
|
||||||
|
|
||||||
// Default ctor
|
// Default ctor
|
||||||
Store::~Store () {}
|
Store::~Store () {}
|
||||||
|
@ -459,3 +459,53 @@ void Store::run() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Store::applies (arangodb::velocypack::Slice const& slice) {
|
||||||
|
return _node.applies(slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Store::toBuilder (Builder& b) const {
|
||||||
|
_node.toBuilder(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node Store::operator ()(std::vector<std::string> const& pv) {
|
||||||
|
return _node(pv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node const Store::operator ()(std::vector<std::string> const& pv) const {
|
||||||
|
return _node(pv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Node Store::operator ()(std::string const& path) {
|
||||||
|
return _node(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Node const Store::operator ()(std::string const& path) const {
|
||||||
|
return _node(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::multimap<TimePoint, std::shared_ptr<Node>>& Store::timeTable () {
|
||||||
|
return _timeTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::multimap<TimePoint, std::shared_ptr<Node>>& Store::timeTable () const {
|
||||||
|
return _timeTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::multimap <std::string,std::string>& Store::observerTable() {
|
||||||
|
return _observerTable;
|
||||||
|
}
|
||||||
|
std::multimap <std::string,std::string> const& Store::observerTable() const {
|
||||||
|
return _observerTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::multimap <std::string,std::string>& Store::observedTable() {
|
||||||
|
return _observedTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::multimap <std::string,std::string> const& Store::observedTable() const {
|
||||||
|
return _observedTable;
|
||||||
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace consensus {
|
||||||
class Agent;
|
class Agent;
|
||||||
|
|
||||||
/// @brief Key value tree
|
/// @brief Key value tree
|
||||||
class Store : public Node, public arangodb::Thread {
|
class Store : public arangodb::Thread {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -76,7 +76,33 @@ public:
|
||||||
/// @brief See how far the path matches anything in store
|
/// @brief See how far the path matches anything in store
|
||||||
size_t matchPath (std::vector<std::string> const& pv) const;
|
size_t matchPath (std::vector<std::string> const& pv) const;
|
||||||
|
|
||||||
|
/// @brief Get node specified by path vector
|
||||||
|
Node operator ()(std::vector<std::string> const& pv);
|
||||||
|
/// @brief Get node specified by path vector
|
||||||
|
Node const operator ()(std::vector<std::string> const& pv) const;
|
||||||
|
|
||||||
|
/// @brief Get node specified by path string
|
||||||
|
Node operator ()(std::string const& path);
|
||||||
|
/// @brief Get node specified by path string
|
||||||
|
Node const operator ()(std::string const& path) const;
|
||||||
|
|
||||||
|
/// @brief Apply single slice
|
||||||
|
bool applies (arangodb::velocypack::Slice const&);
|
||||||
|
|
||||||
|
/// @brief Create Builder representing this store
|
||||||
|
void toBuilder (Builder&) const;
|
||||||
|
|
||||||
|
friend class Node;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
std::multimap<TimePoint, std::shared_ptr<Node>>& timeTable ();
|
||||||
|
std::multimap<TimePoint, std::shared_ptr<Node>> const& timeTable () const;
|
||||||
|
std::multimap <std::string,std::string>& observerTable();
|
||||||
|
std::multimap <std::string,std::string> const& observerTable() const;
|
||||||
|
std::multimap <std::string,std::string>& observedTable();
|
||||||
|
std::multimap <std::string,std::string> const& observedTable() const;
|
||||||
|
|
||||||
/// @brief Read individual entry specified in slice into builder
|
/// @brief Read individual entry specified in slice into builder
|
||||||
bool read (arangodb::velocypack::Slice const&,
|
bool read (arangodb::velocypack::Slice const&,
|
||||||
arangodb::velocypack::Builder&) const;
|
arangodb::velocypack::Builder&) const;
|
||||||
|
@ -99,6 +125,16 @@ private:
|
||||||
/// @brief My own agent
|
/// @brief My own agent
|
||||||
Agent* _agent;
|
Agent* _agent;
|
||||||
|
|
||||||
|
/// @brief Table of expiries in tree (only used in root node)
|
||||||
|
std::multimap<TimePoint, std::shared_ptr<Node>> _timeTable;
|
||||||
|
|
||||||
|
/// @brief Table of observers in tree (only used in root node)
|
||||||
|
std::multimap <std::string,std::string> _observerTable;
|
||||||
|
std::multimap <std::string,std::string> _observedTable;
|
||||||
|
|
||||||
|
/// @brief Root node
|
||||||
|
Node _node;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -74,55 +74,67 @@ AgencyOperation::AgencyOperation(std::string const& key, AgencyValueOperationTyp
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief returns to full operation formatted as a vpack slice
|
/// @brief adds the operation formatted as an attribute in a vpack object
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::shared_ptr<VPackBuilder> AgencyOperation::toVelocyPack() const {
|
void AgencyOperation::toVelocyPack(VPackBuilder& builder) const {
|
||||||
auto builder = std::make_shared<VPackBuilder>();
|
builder.add(VPackValue(_key));
|
||||||
{
|
{
|
||||||
VPackArrayBuilder operation(builder.get());
|
VPackObjectBuilder valueOperation(&builder);
|
||||||
{
|
builder.add("op", VPackValue(_opType.toString()));
|
||||||
VPackObjectBuilder keyVPack(builder.get());
|
if (_opType.type == AgencyOperationType::VALUE) {
|
||||||
builder->add(VPackValue(_key));
|
if (_opType.value == AgencyValueOperationType::OBSERVE
|
||||||
{
|
|| _opType.value == AgencyValueOperationType::UNOBSERVE) {
|
||||||
VPackObjectBuilder valueOperation(builder.get());
|
builder.add("url", _value);
|
||||||
builder->add("op", VPackValue(_opType.toString()));
|
} else {
|
||||||
if (_opType.type == AgencyOperationType::VALUE) {
|
builder.add("new", _value);
|
||||||
if (_opType.value == AgencyValueOperationType::OBSERVE
|
|
||||||
|| _opType.value == AgencyValueOperationType::UNOBSERVE) {
|
|
||||||
builder->add("url", _value);
|
|
||||||
} else {
|
|
||||||
builder->add("new", _value);
|
|
||||||
}
|
|
||||||
if (_ttl > 0) {
|
|
||||||
builder->add("ttl", VPackValue(_ttl));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
if (_ttl > 0) {
|
||||||
if (_precondition.type != AgencyOperationPrecondition::NONE) {
|
builder.add("ttl", VPackValue(_ttl));
|
||||||
VPackObjectBuilder precondition(builder.get());
|
|
||||||
builder->add(VPackValue(_key));
|
|
||||||
{
|
|
||||||
VPackObjectBuilder preconditionDefinition(builder.get());
|
|
||||||
{
|
|
||||||
switch(_precondition.type) {
|
|
||||||
case AgencyOperationPrecondition::EMPTY:
|
|
||||||
builder->add("oldEmpty", VPackValue(_precondition.empty));
|
|
||||||
break;
|
|
||||||
case AgencyOperationPrecondition::VALUE:
|
|
||||||
builder->add("old", _precondition.value);
|
|
||||||
break;
|
|
||||||
// mop: useless compiler warning :S
|
|
||||||
case AgencyOperationPrecondition::NONE:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return builder;
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief constructs a precondition
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
AgencyPrecondition::AgencyPrecondition(std::string const& key, Type t, bool e)
|
||||||
|
: key(AgencyComm::prefix() + key), type(t), empty(e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief constructs a precondition
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
AgencyPrecondition::AgencyPrecondition(std::string const& key, Type t,
|
||||||
|
VPackSlice s)
|
||||||
|
: key(AgencyComm::prefix() + key), type(t), value(s) {
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief adds the precondition formatted as an attribute in a vpack obj
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void AgencyPrecondition::toVelocyPack(VPackBuilder& builder) const {
|
||||||
|
if (type != AgencyPrecondition::NONE) {
|
||||||
|
builder.add(VPackValue(key));
|
||||||
|
{
|
||||||
|
VPackObjectBuilder preconditionDefinition(&builder);
|
||||||
|
switch(type) {
|
||||||
|
case AgencyPrecondition::EMPTY:
|
||||||
|
builder.add("oldEmpty", VPackValue(empty));
|
||||||
|
break;
|
||||||
|
case AgencyPrecondition::VALUE:
|
||||||
|
builder.add("old", value);
|
||||||
|
break;
|
||||||
|
// mop: useless compiler warning :S
|
||||||
|
case AgencyPrecondition::NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -132,17 +144,32 @@ std::shared_ptr<VPackBuilder> AgencyOperation::toVelocyPack() const {
|
||||||
std::string AgencyTransaction::toJson() const {
|
std::string AgencyTransaction::toJson() const {
|
||||||
VPackBuilder builder;
|
VPackBuilder builder;
|
||||||
{
|
{
|
||||||
VPackArrayBuilder transaction(&builder);
|
VPackArrayBuilder guard(&builder);
|
||||||
{
|
toVelocyPack(builder);
|
||||||
for (AgencyOperation const& operation: operations) {
|
|
||||||
auto opBuilder = operation.toVelocyPack();
|
|
||||||
builder.add(opBuilder->slice());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return builder.toJson();
|
return builder.toJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief converts the transaction to velocypack
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void AgencyTransaction::toVelocyPack(VPackBuilder& builder) const {
|
||||||
|
VPackArrayBuilder guard(&builder);
|
||||||
|
{
|
||||||
|
VPackObjectBuilder guard2(&builder);
|
||||||
|
for (AgencyOperation const& operation: operations) {
|
||||||
|
operation.toVelocyPack(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (preconditions.size() > 0) {
|
||||||
|
VPackObjectBuilder guard3(&builder);
|
||||||
|
for (AgencyPrecondition const& precondition: preconditions) {
|
||||||
|
precondition.toVelocyPack(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief creates an agency endpoint
|
/// @brief creates an agency endpoint
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1300,7 +1327,8 @@ AgencyCommResult AgencyComm::removeValues(std::string const& key,
|
||||||
bool recursive) {
|
bool recursive) {
|
||||||
AgencyCommResult result;
|
AgencyCommResult result;
|
||||||
AgencyTransaction transaction(
|
AgencyTransaction transaction(
|
||||||
AgencyOperation(key, AgencySimpleOperationType::DELETE_OP)
|
AgencyOperation(key, AgencySimpleOperationType::DELETE_OP),
|
||||||
|
AgencyPrecondition(key, AgencyPrecondition::EMPTY, false)
|
||||||
);
|
);
|
||||||
|
|
||||||
sendTransactionWithFailover(result, transaction);
|
sendTransactionWithFailover(result, transaction);
|
||||||
|
@ -1323,8 +1351,7 @@ AgencyCommResult AgencyComm::casValue(std::string const& key,
|
||||||
newBuilder.add(VPackValue(json.toJson()));
|
newBuilder.add(VPackValue(json.toJson()));
|
||||||
|
|
||||||
AgencyOperation operation(key, AgencyValueOperationType::SET, newBuilder.slice());
|
AgencyOperation operation(key, AgencyValueOperationType::SET, newBuilder.slice());
|
||||||
operation._precondition.type = AgencyOperationPrecondition::EMPTY;
|
AgencyPrecondition precondition(key, AgencyPrecondition::EMPTY, !prevExist);
|
||||||
operation._precondition.empty = !prevExist;
|
|
||||||
if (ttl >= 0.0) {
|
if (ttl >= 0.0) {
|
||||||
operation._ttl = static_cast<uint32_t>(ttl);
|
operation._ttl = static_cast<uint32_t>(ttl);
|
||||||
}
|
}
|
||||||
|
@ -1333,7 +1360,7 @@ AgencyCommResult AgencyComm::casValue(std::string const& key,
|
||||||
|
|
||||||
url += "/write";
|
url += "/write";
|
||||||
|
|
||||||
AgencyTransaction transaction(operation);
|
AgencyTransaction transaction(operation, precondition);
|
||||||
|
|
||||||
sendWithFailover(
|
sendWithFailover(
|
||||||
arangodb::GeneralRequest::RequestType::POST,
|
arangodb::GeneralRequest::RequestType::POST,
|
||||||
|
@ -1363,8 +1390,8 @@ AgencyCommResult AgencyComm::casValue(std::string const& key,
|
||||||
oldBuilder.add(VPackValue(oldJson.toJson()));
|
oldBuilder.add(VPackValue(oldJson.toJson()));
|
||||||
|
|
||||||
AgencyOperation operation(key, AgencyValueOperationType::SET, newBuilder.slice());
|
AgencyOperation operation(key, AgencyValueOperationType::SET, newBuilder.slice());
|
||||||
operation._precondition.type = AgencyOperationPrecondition::VALUE;
|
AgencyPrecondition precondition(key, AgencyPrecondition::VALUE,
|
||||||
operation._precondition.value = oldBuilder.slice();
|
oldBuilder.slice());
|
||||||
if (ttl >= 0.0) {
|
if (ttl >= 0.0) {
|
||||||
operation._ttl = static_cast<uint32_t>(ttl);
|
operation._ttl = static_cast<uint32_t>(ttl);
|
||||||
}
|
}
|
||||||
|
@ -1373,7 +1400,7 @@ AgencyCommResult AgencyComm::casValue(std::string const& key,
|
||||||
|
|
||||||
url += "/write";
|
url += "/write";
|
||||||
|
|
||||||
AgencyTransaction transaction(operation);
|
AgencyTransaction transaction(operation, precondition);
|
||||||
|
|
||||||
sendWithFailover(
|
sendWithFailover(
|
||||||
arangodb::GeneralRequest::RequestType::POST,
|
arangodb::GeneralRequest::RequestType::POST,
|
||||||
|
|
|
@ -159,27 +159,20 @@ struct AgencyOperationType {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AgencyOperationPrecondition {
|
struct AgencyPrecondition {
|
||||||
AgencyOperationPrecondition() : type(NONE) {}
|
|
||||||
AgencyOperationPrecondition(AgencyOperationPrecondition const& other) {
|
|
||||||
type = other.type;
|
|
||||||
switch(type) {
|
|
||||||
case NONE:
|
|
||||||
break;
|
|
||||||
case EMPTY:
|
|
||||||
empty = other.empty;
|
|
||||||
break;
|
|
||||||
case VALUE:
|
|
||||||
value = other.value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum {NONE, EMPTY, VALUE} type;
|
typedef enum {NONE, EMPTY, VALUE} Type;
|
||||||
union {
|
|
||||||
bool empty;
|
AgencyPrecondition(std::string const& key, Type t, bool e);
|
||||||
VPackSlice value;
|
|
||||||
};
|
AgencyPrecondition(std::string const& key, Type t, VPackSlice s);
|
||||||
|
|
||||||
|
void toVelocyPack(arangodb::velocypack::Builder& builder) const;
|
||||||
|
|
||||||
|
std::string key;
|
||||||
|
Type type;
|
||||||
|
bool empty;
|
||||||
|
VPackSlice value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AgencyOperation {
|
struct AgencyOperation {
|
||||||
|
@ -201,13 +194,14 @@ struct AgencyOperation {
|
||||||
);
|
);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief returns to full operation formatted as a vpack slice
|
/// @brief returns to full operation formatted as a vpack slice and put
|
||||||
|
/// it into the argument builder
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::shared_ptr<arangodb::velocypack::Builder> toVelocyPack() const;
|
void toVelocyPack(arangodb::velocypack::Builder& builder) const;
|
||||||
|
|
||||||
uint32_t _ttl = 0;
|
uint32_t _ttl = 0;
|
||||||
VPackSlice _oldValue;
|
VPackSlice _oldValue;
|
||||||
AgencyOperationPrecondition _precondition;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string const _key;
|
std::string const _key;
|
||||||
|
@ -217,12 +211,24 @@ private:
|
||||||
|
|
||||||
struct AgencyTransaction {
|
struct AgencyTransaction {
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief vector of preconditions
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
std::vector<AgencyPrecondition> preconditions;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief vector of operations
|
/// @brief vector of operations
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::vector<AgencyOperation> operations;
|
std::vector<AgencyOperation> operations;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief converts the transaction to velocypack
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void toVelocyPack(arangodb::velocypack::Builder& builder) const;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief converts the transaction to json
|
/// @brief converts the transaction to json
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -232,10 +238,22 @@ struct AgencyTransaction {
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief shortcut to create a transaction with one operation
|
/// @brief shortcut to create a transaction with one operation
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
explicit AgencyTransaction(AgencyOperation const& operation) {
|
explicit AgencyTransaction(AgencyOperation const& operation) {
|
||||||
operations.push_back(operation);
|
operations.push_back(operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief shortcut to create a transaction with one operation and a
|
||||||
|
/// precondition
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
explicit AgencyTransaction(AgencyOperation const& operation,
|
||||||
|
AgencyPrecondition const& precondition) {
|
||||||
|
operations.push_back(operation);
|
||||||
|
preconditions.push_back(precondition);
|
||||||
|
}
|
||||||
|
|
||||||
explicit AgencyTransaction() {
|
explicit AgencyTransaction() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1368,6 +1368,11 @@ int ClusterInfo::dropCollectionCoordinator(std::string const& databaseName,
|
||||||
while (TRI_microtime() <= endTime) {
|
while (TRI_microtime() <= endTime) {
|
||||||
res.clear();
|
res.clear();
|
||||||
res = ac.getValues(where, true);
|
res = ac.getValues(where, true);
|
||||||
|
if (!res.successful()) {
|
||||||
|
// It seems the collection is already gone, do not wait further
|
||||||
|
errorMsg = "Collection already gone.";
|
||||||
|
return setErrormsg(TRI_ERROR_NO_ERROR, errorMsg);
|
||||||
|
}
|
||||||
if (res.successful() && res.parse(where + "/", false)) {
|
if (res.successful() && res.parse(where + "/", false)) {
|
||||||
// if there are no more active shards for the collection...
|
// if there are no more active shards for the collection...
|
||||||
if (res._values.size() == 0) {
|
if (res._values.size() == 0) {
|
||||||
|
|
|
@ -54,6 +54,10 @@ DispatcherFeature::DispatcherFeature(
|
||||||
startsAfter("WorkMonitor");
|
startsAfter("WorkMonitor");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DispatcherFeature::~DispatcherFeature() {
|
||||||
|
delete _dispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
void DispatcherFeature::collectOptions(
|
void DispatcherFeature::collectOptions(
|
||||||
std::shared_ptr<ProgramOptions> options) {
|
std::shared_ptr<ProgramOptions> options) {
|
||||||
LOG_TOPIC(TRACE, Logger::STARTUP) << name() << "::collectOptions";
|
LOG_TOPIC(TRACE, Logger::STARTUP) << name() << "::collectOptions";
|
||||||
|
|
|
@ -40,6 +40,7 @@ class DispatcherFeature final
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DispatcherFeature(application_features::ApplicationServer* server);
|
explicit DispatcherFeature(application_features::ApplicationServer* server);
|
||||||
|
~DispatcherFeature();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void collectOptions(std::shared_ptr<options::ProgramOptions>) override final;
|
void collectOptions(std::shared_ptr<options::ProgramOptions>) override final;
|
||||||
|
|
|
@ -365,6 +365,7 @@
|
||||||
|
|
||||||
.dashboard-bar-chart-chart {
|
.dashboard-bar-chart-chart {
|
||||||
@extend %pull-left;
|
@extend %pull-left;
|
||||||
|
padding-top: 10px;
|
||||||
|
|
||||||
.nv-bar rect {
|
.nv-bar rect {
|
||||||
fill-opacity: .8;
|
fill-opacity: .8;
|
||||||
|
|
|
@ -319,7 +319,7 @@
|
||||||
.absolut {
|
.absolut {
|
||||||
//line-height: ($int-height2 * 2 / 3) - 10px;
|
//line-height: ($int-height2 * 2 / 3) - 10px;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
padding-top: 10px;
|
padding-top: 15px;
|
||||||
width: ($int-width - (($int-width / 2) * 1.4)) - 6px;
|
width: ($int-width - (($int-width / 2) * 1.4)) - 6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ uint32_t RandomDevice::interval(uint32_t left, uint32_t right) {
|
||||||
int32_t l = left + INT32_MIN;
|
int32_t l = left + INT32_MIN;
|
||||||
int32_t r = right + INT32_MIN;
|
int32_t r = right + INT32_MIN;
|
||||||
|
|
||||||
return static_cast<uint32_t>(random(l, r) - INT32_MIN);
|
return static_cast<uint32_t>(static_cast<int64_t>(random(l, r)) - INT32_MIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t RandomDevice::random(int32_t left, int32_t right) {
|
int32_t RandomDevice::random(int32_t left, int32_t right) {
|
||||||
|
|
|
@ -37,7 +37,7 @@ fi
|
||||||
rm -rf cluster
|
rm -rf cluster
|
||||||
mkdir cluster
|
mkdir cluster
|
||||||
echo Starting agency...
|
echo Starting agency...
|
||||||
build/bin/arangod -c etc/relative/arangod.conf \
|
build/bin/arangod \
|
||||||
-c none \
|
-c none \
|
||||||
--agency.endpoint tcp://127.0.0.1:4001 \
|
--agency.endpoint tcp://127.0.0.1:4001 \
|
||||||
--agency.id 0 \
|
--agency.id 0 \
|
||||||
|
@ -67,7 +67,7 @@ start() {
|
||||||
PORT=$2
|
PORT=$2
|
||||||
mkdir cluster/data$PORT
|
mkdir cluster/data$PORT
|
||||||
echo Starting $TYPE on port $PORT
|
echo Starting $TYPE on port $PORT
|
||||||
build/bin/arangod -c etc/relative/arangod.conf \
|
build/bin/arangod -c none \
|
||||||
--database.directory cluster/data$PORT \
|
--database.directory cluster/data$PORT \
|
||||||
--cluster.agency-endpoint tcp://127.0.0.1:4001 \
|
--cluster.agency-endpoint tcp://127.0.0.1:4001 \
|
||||||
--cluster.my-address tcp://127.0.0.1:$PORT \
|
--cluster.my-address tcp://127.0.0.1:$PORT \
|
||||||
|
@ -93,7 +93,7 @@ startTerminal() {
|
||||||
PORT=$2
|
PORT=$2
|
||||||
mkdir cluster/data$PORT
|
mkdir cluster/data$PORT
|
||||||
echo Starting $TYPE on port $PORT
|
echo Starting $TYPE on port $PORT
|
||||||
xterm $XTERMOPTIONS -e build/bin/arangod -c etc/relative/arangod.conf \
|
xterm $XTERMOPTIONS -e build/bin/arangod -c none \
|
||||||
--database.directory cluster/data$PORT \
|
--database.directory cluster/data$PORT \
|
||||||
--cluster.agency-endpoint tcp://127.0.0.1:4001 \
|
--cluster.agency-endpoint tcp://127.0.0.1:4001 \
|
||||||
--cluster.my-address tcp://127.0.0.1:$PORT \
|
--cluster.my-address tcp://127.0.0.1:$PORT \
|
||||||
|
@ -118,7 +118,7 @@ startDebugger() {
|
||||||
PORT=$2
|
PORT=$2
|
||||||
mkdir cluster/data$PORT
|
mkdir cluster/data$PORT
|
||||||
echo Starting $TYPE on port $PORT with debugger
|
echo Starting $TYPE on port $PORT with debugger
|
||||||
build/bin/arangod -c etc/relative/arangod.conf \
|
build/bin/arangod -c none \
|
||||||
--database.directory cluster/data$PORT \
|
--database.directory cluster/data$PORT \
|
||||||
--cluster.agency-endpoint tcp://127.0.0.1:4001 \
|
--cluster.agency-endpoint tcp://127.0.0.1:4001 \
|
||||||
--cluster.my-address tcp://127.0.0.1:$PORT \
|
--cluster.my-address tcp://127.0.0.1:$PORT \
|
||||||
|
@ -144,7 +144,7 @@ startRR() {
|
||||||
mkdir cluster/data$PORT
|
mkdir cluster/data$PORT
|
||||||
echo Starting $TYPE on port $PORT with rr tracer
|
echo Starting $TYPE on port $PORT with rr tracer
|
||||||
xterm $XTERMOPTIONS -title "$TYPE $PORT" -e rr build/bin/arangod \
|
xterm $XTERMOPTIONS -title "$TYPE $PORT" -e rr build/bin/arangod \
|
||||||
-c etc/relative/arangod.conf \
|
-c none \
|
||||||
--database.directory cluster/data$PORT \
|
--database.directory cluster/data$PORT \
|
||||||
--cluster.agency-endpoint tcp://127.0.0.1:4001 \
|
--cluster.agency-endpoint tcp://127.0.0.1:4001 \
|
||||||
--cluster.my-address tcp://127.0.0.1:$PORT \
|
--cluster.my-address tcp://127.0.0.1:$PORT \
|
||||||
|
@ -221,7 +221,7 @@ if [ -n "$SECONDARIES" ]; then
|
||||||
echo Registering secondary $CLUSTER_ID for "DBServer$index"
|
echo Registering secondary $CLUSTER_ID for "DBServer$index"
|
||||||
curl -f -X PUT --data "{\"primary\": \"DBServer$index\", \"oldSecondary\": \"none\", \"newSecondary\": \"$CLUSTER_ID\"}" -H "Content-Type: application/json" localhost:8530/_admin/cluster/replaceSecondary
|
curl -f -X PUT --data "{\"primary\": \"DBServer$index\", \"oldSecondary\": \"none\", \"newSecondary\": \"$CLUSTER_ID\"}" -H "Content-Type: application/json" localhost:8530/_admin/cluster/replaceSecondary
|
||||||
echo Starting Secondary $CLUSTER_ID on port $PORT
|
echo Starting Secondary $CLUSTER_ID on port $PORT
|
||||||
build/bin/arangod -c etc/relative/arangod.conf \
|
build/bin/arangod -c none \
|
||||||
--database.directory cluster/data$PORT \
|
--database.directory cluster/data$PORT \
|
||||||
--cluster.agency-endpoint tcp://127.0.0.1:4001 \
|
--cluster.agency-endpoint tcp://127.0.0.1:4001 \
|
||||||
--cluster.my-address tcp://127.0.0.1:$PORT \
|
--cluster.my-address tcp://127.0.0.1:$PORT \
|
||||||
|
|
Loading…
Reference in New Issue