1
0
Fork 0

Construct builder with prefilled buffer. Agency store increment, decrement, push pop

This commit is contained in:
Kaveh Vahedipour 2016-03-16 23:40:53 +01:00
parent 7355cde795
commit 5acdc36d07
3 changed files with 94 additions and 50 deletions

View File

@ -161,7 +161,7 @@ class Builder {
explicit Builder(Buffer<uint8_t>& buffer,
Options const* options = &Options::Defaults)
: _pos(0), _keyWritten(false), options(options) {
: _pos(buffer.size()), _keyWritten(false), options(options) {
_buffer.reset(&buffer, BufferNonDeleter<uint8_t>());
_start = _buffer->data();
_size = _buffer->size();

View File

@ -26,6 +26,7 @@
#include <velocypack/Buffer.h>
#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>
#include <velocypack/Hexdump.h>
#include <iostream>
@ -55,7 +56,7 @@ std::vector<std::string> 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<std::string> 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<Node>(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<bool> Store::apply (query_t const& query) {
std::vector<bool> applied;
std::vector<std::string> 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<bool> 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;
}

View File

@ -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<uint8_t> _value;
std::chrono::system_clock::time_point _ttl;
private:
NodeType _type;
std::string _name;
@ -156,8 +149,6 @@ public:
std::vector<bool> 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&,