From 5acdc36d0784e5933bf7cbf777b0bb44ea0cc070 Mon Sep 17 00:00:00 2001 From: Kaveh Vahedipour Date: Wed, 16 Mar 2016 23:40:53 +0100 Subject: [PATCH] Construct builder with prefilled buffer. Agency store increment, decrement, push pop --- .../velocypack/include/velocypack/Builder.h | 2 +- arangod/Agency/Store.cpp | 123 +++++++++++++----- arangod/Agency/Store.h | 19 +-- 3 files changed, 94 insertions(+), 50 deletions(-) diff --git a/3rdParty/velocypack/include/velocypack/Builder.h b/3rdParty/velocypack/include/velocypack/Builder.h index 8fb4576078..b520f8677f 100644 --- a/3rdParty/velocypack/include/velocypack/Builder.h +++ b/3rdParty/velocypack/include/velocypack/Builder.h @@ -161,7 +161,7 @@ class Builder { explicit Builder(Buffer& buffer, Options const* options = &Options::Defaults) - : _pos(0), _keyWritten(false), options(options) { + : _pos(buffer.size()), _keyWritten(false), options(options) { _buffer.reset(&buffer, BufferNonDeleter()); _start = _buffer->data(); _size = _buffer->size(); diff --git a/arangod/Agency/Store.cpp b/arangod/Agency/Store.cpp index a7464a548f..4af3d700ff 100644 --- a/arangod/Agency/Store.cpp +++ b/arangod/Agency/Store.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -55,7 +56,7 @@ std::vector split(const std::string& value, char separator) { Node::Node (std::string const& name) : _parent(nullptr), _name(name) { _value.clear(); } -Node::Node (std::string const& name, Node const* parent) : +Node::Node (std::string const& name, Node* parent) : _parent(parent), _name(name) { _value.clear(); } @@ -89,21 +90,12 @@ bool Node::operator== (arangodb::velocypack::Slice const& rhs) const { return rhs.equals(slice()); } -/*Node& Node::parent () { - return *_parent; - } - -Node const& Node::parent () const { - return *_parent; - }*/ - bool Node::remove (std::string const& path) { std::vector pv = split(path, '/'); std::string key(pv.back()); pv.pop_back(); try { Node& parent = (*this)(pv); - return parent.removeChild(key); } catch (StoreException const& e) { return false; @@ -182,17 +174,74 @@ Node& Node::write (std::string const& path) { return this->operator()(pv); } -bool Node::apply (arangodb::velocypack::Slice const& slice) { +bool Node::applies (arangodb::velocypack::Slice const& slice) { if (slice.type() == ValueType::Object) { - for (auto const& i : VPackObjectIterator(slice)) { - std::string key = i.key.toString(); - key = key.substr(1,key.length()-2); + VPackObjectIterator sit (slice); + + auto b = sit.begin(); + auto i = *b; + std::string key = i.key.toString(); + key = key.substr(1,key.length()-2); + if (key == "op") { + std::string oper = i.value.toString(); + oper = oper.substr(1,oper.length()-2); + Slice const& self = this->slice(); + if (oper == "delete") { + return _parent->removeChild(_name); + } else if (oper == "increment") { // Increment + if (self.isInt() || self.isUInt()) { + Builder tmp; + tmp.add(Value(self.isInt() ? int64_t(self.getInt()+1) : uint64_t(self.getUInt()+1))); + *this = tmp.slice(); + return true; + } else { + return false; + } + } else if (oper == "increment") { // Decrement + if (self.isInt() || self.isUInt()) { + Builder tmp; + tmp.add(Value(self.isInt() ? int64_t(self.getInt()-1) : uint64_t(self.getUInt()-1))); + *this = tmp.slice(); + return true; + } else { + return false; + } + } else if (oper == "push") { // Push + if (self.isArray()) { + Builder tmp; + tmp.openArray(); + for (auto const& old : VPackArrayIterator(self)) + tmp.add(old); + tmp.close(); + auto nval = *++b; + std::cout << nval.value.toString() << std::endl; + *this = tmp.slice(); + } + } else if (oper == "pop") { // Pop + if (self.isArray()) { + Builder tmp; + tmp.openArray(); + VPackArrayIterator it(self); + size_t j = it.size()-1; + for (auto old : it) { + tmp.add(old); + if (--j==0) + break; + } + tmp.close(); + *this = tmp.slice(); + } + } + } else if (key.find('/')!=std::string::npos) { + (*this)(key).applies(i.value); + } else { auto found = _children.find(key); if (found == _children.end()) { _children[key] = std::make_shared(key, this); } - _children[key]->apply(i.value); + _children[key]->applies(i.value); } + } else { *this = slice; } @@ -216,25 +265,25 @@ void Node::toBuilder (Builder& builder) const { } Store::Store (std::string const& name) : Node(name) {} + Store::~Store () {} std::vector Store::apply (query_t const& query) { std::vector applied; - std::vector path; MUTEX_LOCKER(storeLocker, _storeLock); for (auto const& i : VPackArrayIterator(query->slice())) { switch (i.length()) { case 1: - applied.push_back(this->apply(i[0])); break; // no precond + applied.push_back(applies(i[0])); break; // no precond case 2: if (check(i[1])) { - applied.push_back(this->apply(i[0])); // precondition + applied.push_back(applies(i[0])); // precondition } else { LOG(WARN) << "Precondition failed!"; applied.push_back(false); } break; - default: // wrong + default: // wrong LOG(FATAL) << "We can only handle log entry with or without precondition!"; applied.push_back(false); break; @@ -243,14 +292,6 @@ std::vector Store::apply (query_t const& query) { return applied; } -bool Store::apply (arangodb::velocypack::Slice const& slice) { - return Node::apply(slice); -} - -Node const& Store::read (std::string const& path) const { - return Node::read(path); -} - bool Store::check (arangodb::velocypack::Slice const& slice) const { if (slice.type() != VPackValueType::Object) { LOG(WARN) << "Cannot check precondition: " << slice.toJson(); @@ -259,28 +300,40 @@ bool Store::check (arangodb::velocypack::Slice const& slice) const { for (auto const& precond : VPackObjectIterator(slice)) { std::string path = precond.key.toString(); path = path.substr(1,path.size()-2); - if (precond.value.type() == VPackValueType::Object) { //"old", "oldEmpty", "isArray" + + bool found = false; + Node node ("precond"); + try { + node = (*this)(path); + found = true; + } catch (StoreException const&) {} + + if (precond.value.type() == VPackValueType::Object) { for (auto const& op : VPackObjectIterator(precond.value)) { std::string const& oper = op.key.copyString(); - Node const& node = (*this)(path); - if (oper == "old") { + if (oper == "old") { // old return (node == op.value); - } else if ("isArray") { - if (op.value.type()!=VPackValueType::Bool) { + } else if (oper == "isArray") { // isArray + if (op.value.type()!=VPackValueType::Bool) { + LOG (FATAL) << "Non boolsh expression for 'isArray' precondition"; return false; } bool isArray = (node.type() == LEAF && node.slice().type() == VPackValueType::Array); return op.value.getBool() ? isArray : !isArray; + } else if (oper == "oldEmpty") { // isEmpty + if (op.value.type()!=VPackValueType::Bool) { + LOG (FATAL) << "Non boolsh expression for 'oldEmpty' precondition"; + return false; + } + return op.value.getBool() ? !found : found; } } - } else { - + return node == precond.value; } } - // return true; } diff --git a/arangod/Agency/Store.h b/arangod/Agency/Store.h index 0935c033db..d6dfb25993 100644 --- a/arangod/Agency/Store.h +++ b/arangod/Agency/Store.h @@ -67,7 +67,7 @@ public: Node (std::string const& name); - Node (std::string const& name, Node const* parent); + Node (std::string const& name, Node* parent); virtual ~Node (); @@ -98,16 +98,12 @@ public: Node& write (std::string const& path); -/* Node& parent (); - - Node const& parent () const;*/ - bool remove (std::string const& path); bool removeChild (std::string const& key); friend std::ostream& operator<<(std::ostream& os, const Node& n) { - Node const* par = n._parent; + Node* par = n._parent; while (par != 0) { par = par->_parent; os << " "; @@ -123,7 +119,7 @@ public: return os; } - virtual bool apply (arangodb::velocypack::Slice const&); + bool applies (arangodb::velocypack::Slice const&); void toBuilder (Builder&) const; @@ -133,15 +129,12 @@ public: Slice slice() const; - - protected: - Node const* _parent; + Node* _parent; Children _children; Buffer _value; std::chrono::system_clock::time_point _ttl; - -private: + NodeType _type; std::string _name; @@ -156,8 +149,6 @@ public: std::vector apply (query_t const& query); query_t read (query_t const& query) const; - virtual bool apply (arangodb::velocypack::Slice const&); - Node const& read (std::string const&) const; private: bool read (arangodb::velocypack::Slice const&,