1
0
Fork 0

updated vpack library

This commit is contained in:
Jan Steemann 2016-02-12 16:33:26 +01:00
parent 80433b23bb
commit 0089b0fcf6
20 changed files with 299 additions and 335 deletions

View File

@ -33,6 +33,7 @@
#include <memory>
#include "velocypack/velocypack-common.h"
#include "velocypack/Slice.h"
namespace arangodb {
namespace velocypack {
@ -71,6 +72,30 @@ class AttributeTranslator {
size_t _count;
};
class AttributeTranslatorScope {
private:
AttributeTranslatorScope(AttributeTranslatorScope const&) = delete;
AttributeTranslatorScope& operator= (AttributeTranslatorScope const&) = delete;
public:
explicit AttributeTranslatorScope(AttributeTranslator* translator)
: _old(Slice::attributeTranslator) {
Slice::attributeTranslator = translator;
}
~AttributeTranslatorScope() {
revert();
}
// prematurely revert the change
void revert() {
Slice::attributeTranslator = _old;
}
private:
AttributeTranslator* _old;
};
} // namespace arangodb::velocypack
} // namespace arangodb

View File

@ -115,20 +115,16 @@ class Builder {
// at position base, also determine the length len of the attribute.
// This takes into account the different possibilities for the format
// of attribute names:
static uint8_t const* findAttrName(uint8_t const* base, uint64_t& len,
Options const*);
static uint8_t const* findAttrName(uint8_t const* base, uint64_t& len);
static void sortObjectIndexShort(uint8_t* objBase,
std::vector<ValueLength>& offsets,
Options const*);
std::vector<ValueLength>& offsets);
static void sortObjectIndexLong(uint8_t* objBase,
std::vector<ValueLength>& offsets,
Options const*);
std::vector<ValueLength>& offsets);
static void sortObjectIndex(uint8_t* objBase,
std::vector<ValueLength>& offsets,
Options const*);
std::vector<ValueLength>& offsets);
public:
Options const* options;
@ -301,7 +297,7 @@ class Builder {
if (isEmpty()) {
return Slice();
}
return Slice(start(), options);
return Slice(start());
}
// Compute the actual size here, but only when sealed

View File

@ -71,7 +71,7 @@ class ArrayIterator {
ArrayIterator& operator++() {
++_position;
if (_position <= _size && _current != nullptr) {
_current += Slice(_current, _slice.options).byteSize();
_current += Slice(_current).byteSize();
} else {
_current = nullptr;
}
@ -91,7 +91,7 @@ class ArrayIterator {
Slice operator*() const {
if (_current != nullptr) {
return Slice(_current, _slice.options);
return Slice(_current);
}
return _slice.at(_position);
}
@ -181,9 +181,9 @@ class ObjectIterator {
++_position;
if (_position <= _size && _current != nullptr) {
// skip over key
_current += Slice(_current, _slice.options).byteSize();
_current += Slice(_current).byteSize();
// skip over value
_current += Slice(_current, _slice.options).byteSize();
_current += Slice(_current).byteSize();
} else {
_current = nullptr;
}
@ -203,8 +203,8 @@ class ObjectIterator {
ObjectPair operator*() const {
if (_current != nullptr) {
Slice key = Slice(_current, _slice.options);
return ObjectPair(key, Slice(_current + key.byteSize(), _slice.options));
Slice key = Slice(_current);
return ObjectPair(key, Slice(_current + key.byteSize()));
}
return ObjectPair(_slice.keyAt(_position), _slice.valueAt(_position));
}
@ -232,7 +232,7 @@ class ObjectIterator {
throw Exception(Exception::IndexOutOfBounds);
}
if (_current != nullptr) {
return Slice(_current, _slice.options);
return Slice(_current);
}
return _slice.keyAt(_position);
}
@ -242,8 +242,8 @@ class ObjectIterator {
throw Exception(Exception::IndexOutOfBounds);
}
if (_current != nullptr) {
Slice key = Slice(_current, _slice.options);
return Slice(_current + key.byteSize(), _slice.options);
Slice key = Slice(_current);
return Slice(_current + key.byteSize());
}
return _slice.valueAt(_position);
}

View File

@ -49,7 +49,6 @@ struct CustomTypeHandler {
virtual void toJson(Slice const& value, Dumper* dumper,
Slice const& base) = 0;
virtual ValueLength byteSize(Slice const& value) = 0;
};
struct Options {

View File

@ -47,6 +47,7 @@ namespace velocypack {
// forward for fasthash64 function declared elsewhere
uint64_t fasthash64(void const*, size_t, uint64_t);
class AttributeTranslator;
class SliceScope;
class Slice {
@ -59,43 +60,17 @@ class Slice {
uint8_t const* _start;
public:
Options const* options;
static AttributeTranslator* attributeTranslator;
// constructor for an empty Value of type None
Slice() : Slice("\x00", &Options::Defaults) {}
Slice() : Slice("\x00") {}
explicit Slice(uint8_t const* start,
Options const* options = &Options::Defaults)
: _start(start), options(options) {
VELOCYPACK_ASSERT(options != nullptr);
}
explicit Slice(uint8_t const* start)
: _start(start) {}
explicit Slice(char const* start, Options const* options = &Options::Defaults)
: _start(reinterpret_cast<uint8_t const*>(start)), options(options) {
VELOCYPACK_ASSERT(options != nullptr);
}
Slice(Slice const& other) : _start(other._start), options(other.options) {
VELOCYPACK_ASSERT(options != nullptr);
}
Slice(Slice&& other) : _start(other._start), options(other.options) {
VELOCYPACK_ASSERT(options != nullptr);
}
Slice& operator=(Slice const& other) {
_start = other._start;
options = other.options;
VELOCYPACK_ASSERT(options != nullptr);
return *this;
}
Slice& operator=(Slice&& other) {
_start = other._start;
options = other.options;
VELOCYPACK_ASSERT(options != nullptr);
return *this;
}
explicit Slice(char const* start)
: _start(reinterpret_cast<uint8_t const*>(start)) {}
// creates a Slice from Json and adds it to a scope
static Slice fromJson(SliceScope& scope, std::string const& json,
@ -281,7 +256,7 @@ class Slice {
// find number of items
if (h <= 0x05) { // No offset table or length, need to compute:
ValueLength firstSubOffset = findDataOffset(h);
Slice first(_start + firstSubOffset, options);
Slice first(_start + firstSubOffset);
return (end - firstSubOffset) / first.byteSize();
} else if (offsetSize < 8) {
return readInteger<ValueLength>(_start + offsetSize + 1, offsetSize);
@ -322,7 +297,7 @@ class Slice {
}
Slice key = getNthKey(index, false);
return Slice(key.start() + key.byteSize(), options);
return Slice(key.start() + key.byteSize());
}
// look for the specified attribute path inside an Object
@ -334,7 +309,7 @@ class Slice {
}
// use ourselves as the starting point
Slice last = Slice(start(), options);
Slice last = Slice(start());
for (size_t i = 0; i < attributes.size(); ++i) {
// fetch subattribute
last = last.get(attributes[i]);
@ -636,11 +611,41 @@ class Slice {
}
case ValueType::Custom: {
if (options->customTypeHandler == nullptr) {
throw Exception(Exception::NeedCustomTypeHandler);
}
auto const h = head();
switch (h) {
case 0xf0: return 1 + 1;
case 0xf1: return 1 + 2;
case 0xf2: return 1 + 4;
case 0xf3: return 1 + 8;
return options->customTypeHandler->byteSize(*this);
case 0xf4:
case 0xf5:
case 0xf6: {
return 1 + readInteger<ValueLength>(_start + 1, 1);
}
case 0xf7:
case 0xf8:
case 0xf9: {
return 1 + readInteger<ValueLength>(_start + 1, 2);
}
case 0xfa:
case 0xfb:
case 0xfc: {
return 1 + readInteger<ValueLength>(_start + 1, 4);
}
case 0xfd:
case 0xfe:
case 0xff: {
return 1 + readInteger<ValueLength>(_start + 1, 8);
}
default: {
// fallthrough intentional
}
}
}
}
@ -659,8 +664,8 @@ class Slice {
return Slice(left).equals(Slice(right));
}
std::string toJson() const;
std::string toString() const;
std::string toJson(Options const* options = &Options::Defaults) const;
std::string toString(Options const* options = &Options::Defaults) const;
std::string hexType() const;
private:
@ -743,8 +748,7 @@ class SliceScope {
SliceScope();
~SliceScope();
Slice add(uint8_t const* data, ValueLength size,
Options const* options = &Options::Defaults);
Slice add(uint8_t const* data, ValueLength size);
private:
std::vector<uint8_t*> _allocations;

View File

@ -118,7 +118,7 @@ class SliceContainer {
if (_data == nullptr) {
return Slice();
}
return Slice(_data, &Options::Defaults);
return Slice(_data);
}
inline uint8_t const* begin() const { return _data; }

View File

@ -67,8 +67,7 @@ void Builder::doActualSort(std::vector<SortEntry>& entries) {
});
};
uint8_t const* Builder::findAttrName(uint8_t const* base, uint64_t& len,
Options const* options) {
uint8_t const* Builder::findAttrName(uint8_t const* base, uint64_t& len) {
uint8_t const b = *base;
if (b >= 0x40 && b <= 0xbe) {
// short UTF-8 string
@ -86,13 +85,11 @@ uint8_t const* Builder::findAttrName(uint8_t const* base, uint64_t& len,
}
// translate attribute name
Slice s(base, options);
return findAttrName(s.makeKey().start(), len, options);
return findAttrName(Slice(base).makeKey().start(), len);
}
void Builder::sortObjectIndexShort(uint8_t* objBase,
std::vector<ValueLength>& offsets,
Options const* options) {
std::vector<ValueLength>& offsets) {
auto cmp = [&](ValueLength a, ValueLength b) -> bool {
uint8_t const* aa = objBase + a;
uint8_t const* bb = objBase + b;
@ -104,8 +101,8 @@ void Builder::sortObjectIndexShort(uint8_t* objBase,
} else {
uint64_t lena;
uint64_t lenb;
aa = findAttrName(aa, lena, options);
bb = findAttrName(bb, lenb, options);
aa = findAttrName(aa, lena);
bb = findAttrName(bb, lenb);
uint64_t m = (std::min)(lena, lenb);
int c = memcmp(aa, bb, checkOverflow(m));
return (c < 0 || (c == 0 && lena < lenb));
@ -115,8 +112,7 @@ void Builder::sortObjectIndexShort(uint8_t* objBase,
}
void Builder::sortObjectIndexLong(uint8_t* objBase,
std::vector<ValueLength>& offsets,
Options const* options) {
std::vector<ValueLength>& offsets) {
// on some platforms we can use a thread-local vector
#if __llvm__ == 1
// nono thread local
@ -134,7 +130,7 @@ void Builder::sortObjectIndexLong(uint8_t* objBase,
for (size_t i = 0; i < n; i++) {
SortEntry e;
e.offset = offsets[i];
e.nameStart = findAttrName(objBase + e.offset, e.nameSize, options);
e.nameStart = findAttrName(objBase + e.offset, e.nameSize);
entries.push_back(e);
}
VELOCYPACK_ASSERT(entries.size() == n);
@ -147,12 +143,11 @@ void Builder::sortObjectIndexLong(uint8_t* objBase,
}
void Builder::sortObjectIndex(uint8_t* objBase,
std::vector<ValueLength>& offsets,
Options const* options) {
std::vector<ValueLength>& offsets) {
if (offsets.size() > 32) {
sortObjectIndexLong(objBase, offsets, options);
sortObjectIndexLong(objBase, offsets);
} else {
sortObjectIndexShort(objBase, offsets, options);
sortObjectIndexShort(objBase, offsets);
}
}
@ -325,7 +320,7 @@ Builder& Builder::close() {
if (!options->sortAttributeNames) {
_start[tos] = 0x0f; // unsorted
} else if (index.size() >= 2 && options->sortAttributeNames) {
sortObjectIndex(_start + tos, index, options);
sortObjectIndex(_start + tos, index);
}
}
for (size_t i = 0; i < index.size(); i++) {
@ -373,7 +368,7 @@ Builder& Builder::close() {
if (options->checkAttributeUniqueness && index.size() > 1 &&
_start[tos] >= 0x0b) {
// check uniqueness of attribute names
checkAttributeUniqueness(Slice(_start + tos, options));
checkAttributeUniqueness(Slice(_start + tos));
}
// Now the array or object is complete, we pop a ValueLength
@ -397,7 +392,7 @@ bool Builder::hasKey(std::string const& key) const {
return false;
}
for (size_t i = 0; i < index.size(); ++i) {
Slice s(_start + tos + index[i], options);
Slice s(_start + tos + index[i]);
if (s.makeKey().isEqualString(key)) {
return true;
}
@ -419,9 +414,9 @@ Slice Builder::getKey(std::string const& key) const {
return Slice();
}
for (size_t i = 0; i < index.size(); ++i) {
Slice s(_start + tos + index[i], options);
Slice s(_start + tos + index[i]);
if (s.makeKey().isEqualString(key)) {
return Slice(s.start() + s.byteSize(), options);
return Slice(s.start() + s.byteSize());
}
}
return Slice();

View File

@ -391,7 +391,7 @@ void Dumper::dumpValue(Slice const* slice, Slice const* base) {
}
case ValueType::External: {
Slice const external(slice->getExternal(), slice->options);
Slice const external(slice->getExternal());
dumpValue(&external, base);
break;
}

View File

@ -478,14 +478,14 @@ void Parser::parseObject() {
} else {
parseString();
if (options->attributeExcludeHandler->shouldExclude(
Slice(_b->_start + lastPos, options), _nesting)) {
Slice(_b->_start + lastPos), _nesting)) {
excludeAttribute = true;
}
}
if (!excludeAttribute && options->attributeTranslator != nullptr) {
// check if a translation for the attribute name exists
Slice key(_b->_start + lastPos, options);
Slice key(_b->_start + lastPos);
if (key.isString()) {
ValueLength keyLength;
@ -498,7 +498,7 @@ void Parser::parseObject() {
// and simply overwrite the existing key with the numeric translation
// id
_b->_pos = lastPos;
_b->addUInt(Slice(translated, options).getUInt());
_b->addUInt(Slice(translated).getUInt());
}
}
}

View File

@ -38,6 +38,8 @@
using namespace arangodb::velocypack;
using VT = arangodb::velocypack::ValueType;
AttributeTranslator* Slice::attributeTranslator = nullptr;
VT const Slice::TypeMap[256] = {
/* 0x00 */ VT::None, /* 0x01 */ VT::Array,
@ -220,7 +222,7 @@ Slice Slice::fromJson(SliceScope& scope, std::string const& json,
parser.parse(json);
Builder const& b = parser.builder(); // don't copy Builder contents here
return scope.add(b.start(), b.size(), options);
return scope.add(b.start(), b.size());
}
// translates an integer key into a string
@ -230,12 +232,11 @@ Slice Slice::translate() const {
"Cannot translate key of this type");
}
uint64_t id = getUInt();
if (options->attributeTranslator == nullptr) {
if (attributeTranslator == nullptr) {
throw Exception(Exception::NeedAttributeTranslator);
}
return Slice(options->attributeTranslator->translate(id), options);
return Slice(attributeTranslator->translate(id));
}
// check if two Slices are equal on the binary level
@ -254,7 +255,7 @@ bool Slice::equals(Slice const& other) const {
arangodb::velocypack::checkOverflow(size)) == 0);
}
std::string Slice::toJson() const {
std::string Slice::toJson(Options const* options) const {
std::string buffer;
StringSink sink(&buffer);
Dumper dumper(&sink, options);
@ -262,7 +263,7 @@ std::string Slice::toJson() const {
return buffer;
}
std::string Slice::toString() const {
std::string Slice::toString(Options const* options) const {
// copy options and set prettyPrint in copy
Options prettyOptions = *options;
prettyOptions.prettyPrint = true;
@ -311,16 +312,16 @@ Slice Slice::get(std::string const& attribute) const {
dataOffset = findDataOffset(h);
}
Slice key = Slice(_start + dataOffset, options);
Slice key = Slice(_start + dataOffset);
if (key.isString() && key.isEqualString(attribute)) {
return Slice(key.start() + key.byteSize(), options);
return Slice(key.start() + key.byteSize());
}
if (key.isSmallInt() || key.isUInt()) {
// translate key
if (key.translate().isEqualString(attribute)) {
return Slice(key.start() + key.byteSize(), options);
return Slice(key.start() + key.byteSize());
}
}
@ -460,7 +461,7 @@ Slice Slice::getFromCompactObject(std::string const& attribute) const {
while (it.valid()) {
Slice key = it.key();
if (key.makeKey().isEqualString(attribute)) {
return Slice(key.start() + key.byteSize(), options);
return Slice(key.start() + key.byteSize());
}
it.next();
@ -493,7 +494,7 @@ ValueLength Slice::getNthOffset(ValueLength index) const {
// find the number of items
ValueLength n;
if (h <= 0x05) { // No offset table or length, need to compute:
Slice first(_start + dataOffset, options);
Slice first(_start + dataOffset);
n = (end - dataOffset) / first.byteSize();
} else if (offsetSize < 8) {
n = readInteger<ValueLength>(_start + 1 + offsetSize, offsetSize);
@ -514,8 +515,7 @@ ValueLength Slice::getNthOffset(ValueLength index) const {
if (dataOffset == 0) {
dataOffset = findDataOffset(h);
}
Slice firstItem(_start + dataOffset, options);
return dataOffset + index * firstItem.byteSize();
return dataOffset + index * Slice(_start + dataOffset).byteSize();
}
ValueLength const ieBase =
@ -527,14 +527,14 @@ ValueLength Slice::getNthOffset(ValueLength index) const {
Slice Slice::getNth(ValueLength index) const {
VELOCYPACK_ASSERT(type() == ValueType::Array);
return Slice(_start + getNthOffset(index), options);
return Slice(_start + getNthOffset(index));
}
// extract the nth member from an Object
Slice Slice::getNthKey(ValueLength index, bool translate) const {
VELOCYPACK_ASSERT(type() == ValueType::Object);
Slice s(_start + getNthOffset(index), options);
Slice s(_start + getNthOffset(index));
if (translate) {
return s.makeKey();
@ -568,10 +568,9 @@ ValueLength Slice::getNthOffsetFromCompact(ValueLength index) const {
ValueLength current = 0;
while (current != index) {
uint8_t const* s = _start + offset;
Slice key = Slice(s, options);
offset += key.byteSize();
offset += Slice(s).byteSize();
if (h == 0x14) {
Slice value = Slice(_start + offset, options);
Slice value = Slice(_start + offset);
offset += value.byteSize();
}
++current;
@ -585,8 +584,7 @@ Slice Slice::searchObjectKeyLinear(std::string const& attribute,
ValueLength n) const {
for (ValueLength index = 0; index < n; ++index) {
ValueLength offset = ieBase + index * offsetSize;
Slice key(_start + readInteger<ValueLength>(_start + offset, offsetSize),
options);
Slice key(_start + readInteger<ValueLength>(_start + offset, offsetSize));
if (key.isString()) {
if (!key.isEqualString(attribute)) {
@ -603,7 +601,7 @@ Slice Slice::searchObjectKeyLinear(std::string const& attribute,
}
// key is identical. now return value
return Slice(key.start() + key.byteSize(), options);
return Slice(key.start() + key.byteSize());
}
// nothing found
@ -624,8 +622,7 @@ Slice Slice::searchObjectKeyBinary(std::string const& attribute,
ValueLength index = l + ((r - l) / 2);
ValueLength offset = ieBase + index * offsetSize;
Slice key(_start + readInteger<ValueLength>(_start + offset, offsetSize),
options);
Slice key(_start + readInteger<ValueLength>(_start + offset, offsetSize));
int res;
if (key.isString()) {
@ -640,7 +637,7 @@ Slice Slice::searchObjectKeyBinary(std::string const& attribute,
if (res == 0) {
// found
return Slice(key.start() + key.byteSize(), options);
return Slice(key.start() + key.byteSize());
}
if (res > 0) {
@ -665,15 +662,12 @@ SliceScope::~SliceScope() {
}
}
Slice SliceScope::add(uint8_t const* data, ValueLength size,
Options const* options) {
Slice SliceScope::add(uint8_t const* data, ValueLength size) {
size_t const s = checkOverflow(size);
std::unique_ptr<uint8_t[]> copy(new uint8_t[s]);
memcpy(copy.get(), data, s);
_allocations.push_back(copy.get());
uint8_t const* start = copy.release();
return Slice(start, options);
return Slice(copy.release());
}
std::ostream& operator<<(std::ostream& stream, Slice const* slice) {
@ -687,5 +681,4 @@ std::ostream& operator<<(std::ostream& stream, Slice const& slice) {
}
static_assert(sizeof(arangodb::velocypack::Slice) ==
sizeof(void*) + sizeof(void*),
"Slice has an unexpected size");
sizeof(void*), "Slice has an unexpected size");

View File

@ -335,7 +335,7 @@ class MarkerAccessorDocument : public T {
uint8_t* vPackValue() const { return versionedVPackValue() + 1; }
VPackSlice slice() const { return VPackSlice(this->vpackValue(), StorageOptions::getOptions()); }
VPackSlice slice() const { return VPackSlice(this->vpackValue(), StorageOptions::getDefaultOptions()); }
static uint64_t staticLength() { return 8; }
};
@ -415,7 +415,7 @@ class MarkerAccessorStructural : public T {
uint8_t* vPackValue() const { return versionedVPackValue() + 1; }
VPackSlice slice() const { return VPackSlice(this->vpackValue(), StorageOptions::getOptions()); }
VPackSlice slice() const { return VPackSlice(this->vpackValue(), StorageOptions::getDefaultOptions()); }
static uint64_t staticLength() { return 0; }
};

View File

@ -23,12 +23,12 @@
#include "Options.h"
#include "Basics/Exceptions.h"
#include "Basics/Logger.h"
#include "Utils/CollectionNameResolver.h"
#include "VocBase/voc-types.h"
#include "VocBase/vocbase.h"
#include <velocypack/AttributeTranslator.h>
#include <velocypack/Dumper.h>
#include <velocypack/Options.h>
#include <velocypack/Slice.h>
#include <velocypack/Value.h>
#include <velocypack/velocypack-aliases.h>
@ -37,57 +37,26 @@ using namespace arangodb;
static std::unique_ptr<VPackAttributeTranslator> translator;
static std::unique_ptr<VPackAttributeExcludeHandler> excludeHandler;
static std::unique_ptr<VPackOptions> options;
static std::unique_ptr<VPackCustomTypeHandler> customLengthHandler;
static std::unique_ptr<VPackOptions> defaultOptions;
static std::unique_ptr<VPackOptions> insertOptions;
void StorageOptions::initialize() {
translator.reset(new VPackAttributeTranslator);
/*
// these attribute names will be translated into short integer values
translator->add(TRI_VOC_ATTRIBUTE_KEY, 1);
translator->add(TRI_VOC_ATTRIBUTE_REV, 2);
translator->add(TRI_VOC_ATTRIBUTE_ID, 3);
translator->add(TRI_VOC_ATTRIBUTE_FROM, 4);
translator->add(TRI_VOC_ATTRIBUTE_TO, 5);
*/
translator->seal();
options.reset(new VPackOptions);
// options->attributeTranslator = translator.get();
}
VPackAttributeTranslator* StorageOptions::getTranslator() {
return translator.get();
}
VPackOptions* StorageOptions::getOptions() {
return options.get();
}
/*
// global options used when converting JSON into a document
VPackOptions StorageOptions::JsonToDocumentTemplate;
// global options used when converting documents into JSON
VPackOptions StorageOptions::DocumentToJsonTemplate;
// global options used for other conversions
VPackOptions StorageOptions::NonDocumentTemplate;
struct ExcludeHandlerImpl : public VPackAttributeExcludeHandler {
// attribute exclude handler for skipping over system attributes
struct SystemAttributeExcludeHandler : public VPackAttributeExcludeHandler {
bool shouldExclude(VPackSlice const& key, int nesting) override final {
VPackValueLength keyLength;
char const* p = key.getString(keyLength);
if (p == nullptr || *p != '_' || keyLength < 3 || keyLength > 5) {
if (p == nullptr || *p != '_' || keyLength < 3 || keyLength > 5 || nesting > 0) {
// keep attribute
return true;
}
if ((keyLength == 3 && memcmp(p, "_id", keyLength) == 0) ||
(keyLength == 4 && memcmp(p, "_rev", keyLength) == 0) ||
(keyLength == 3 && memcmp(p, "_to", keyLength) == 0) ||
(keyLength == 5 && memcmp(p, "_from", keyLength) == 0)) {
// exclude these attribute
// exclude these attributes (but not _key!)
if ((keyLength == 3 && memcmp(p, TRI_VOC_ATTRIBUTE_ID, keyLength) == 0) ||
(keyLength == 4 && memcmp(p, TRI_VOC_ATTRIBUTE_REV, keyLength) == 0) ||
(keyLength == 3 && memcmp(p, TRI_VOC_ATTRIBUTE_TO, keyLength) == 0) ||
(keyLength == 5 && memcmp(p, TRI_VOC_ATTRIBUTE_FROM, keyLength) == 0)) {
return true;
}
@ -96,89 +65,139 @@ struct ExcludeHandlerImpl : public VPackAttributeExcludeHandler {
}
};
struct CustomTypeHandlerImpl : public VPackCustomTypeHandler {
explicit CustomTypeHandlerImpl(
arangodb::CollectionNameResolver const* resolver)
: resolver(resolver) {}
void toJson(VPackSlice const& value, VPackDumper* dumper,
VPackSlice const& base) {
if (value.head() == 0xf0) {
// _id
if (!base.isObject()) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"invalid value type");
}
uint64_t cid = arangodb::velocypack::readUInt64(value.start() + 1);
char buffer[512]; // This is enough for collection name + _key
size_t len = resolver->getCollectionName(&buffer[0], cid);
buffer[len] = '/';
VPackSlice key = base.get(TRI_VOC_ATTRIBUTE_KEY);
VPackValueLength keyLength;
char const* p = key.getString(keyLength);
if (p == nullptr) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"invalid _key value");
}
memcpy(&buffer[len + 1], p, keyLength);
dumper->appendString(&buffer[0], len + 1 + keyLength);
return;
}
if (value.head() == 0xf1) {
// _rev
dumper->sink()->push_back('"');
dumper->appendUInt(arangodb::velocypack::readUInt64(value.start() + 1));
dumper->sink()->push_back('"');
return;
}
if (value.head() == 0xf2) {
// _from, _to
// TODO
return;
}
throw "unknown type!";
// custom type value handler, used for determining the length of the _id attribute
struct CustomIdLengthHandler : public VPackCustomTypeHandler {
void toJson(VPackSlice const&, VPackDumper*,
VPackSlice const&) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
}
VPackValueLength byteSize(VPackSlice const& value) {
if (value.head() == 0xf0) {
// _id
return 1 + 8; // 0xf0 + 8 bytes for collection id
if (value.head() != 0xf0) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"invalid custom type");
}
if (value.head() == 0xf1) {
// _rev
return 1 + 8; // 0xf1 + 8 bytes for tick value
}
if (value.head() == 0xf2) {
// _from, _to
// TODO!!
return 1;
}
throw "unknown type!";
// _id
return 1 + 8; // 0xf0 + 8 bytes for collection id
}
arangodb::CollectionNameResolver const* resolver;
TRI_voc_cid_t cid;
};
StorageOptions::StorageOptions()
: _translator(new VPackAttributeTranslator),
_excludeHandler(new ExcludeHandlerImpl) {
// custom type value handler, used for deciphering the _id attribute
struct CustomIdTypeHandler : public VPackCustomTypeHandler {
explicit CustomIdTypeHandler(TRI_vocbase_t* vocbase)
: vocbase(vocbase), resolver(nullptr), ownsResolver(false) {}
CustomIdTypeHandler(TRI_vocbase_t* vocbase, CollectionNameResolver* resolver)
: vocbase(vocbase), resolver(resolver), ownsResolver(false) {}
~CustomIdTypeHandler() {
if (ownsResolver) {
delete resolver;
}
}
CollectionNameResolver* getResolver() {
if (resolver == nullptr) {
resolver = new CollectionNameResolver(vocbase);
ownsResolver = true;
}
return resolver;
}
void toJson(VPackSlice const& value, VPackDumper* dumper,
VPackSlice const& base) {
if (value.head() != 0xf0) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"invalid custom type");
}
// _id
if (!base.isObject()) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"invalid value type");
}
uint64_t cid = arangodb::velocypack::readUInt64(value.start() + 1);
char buffer[512]; // This is enough for collection name + _key
size_t len = getResolver()->getCollectionName(&buffer[0], cid);
buffer[len] = '/';
VPackSlice key = base.get(TRI_VOC_ATTRIBUTE_KEY);
VPackValueLength keyLength;
char const* p = key.getString(keyLength);
if (p == nullptr) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"invalid _key value");
}
memcpy(&buffer[len + 1], p, keyLength);
dumper->appendString(&buffer[0], len + 1 + keyLength);
}
VPackValueLength byteSize(VPackSlice const& value) {
if (value.head() != 0xf0) {
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
"invalid custom type");
}
// _id
return 1 + 8; // 0xf0 + 8 bytes for collection id
}
TRI_vocbase_t* vocbase;
CollectionNameResolver* resolver;
bool ownsResolver;
};
// initialize global vpack options
void StorageOptions::initialize() {
// initialize translator
translator.reset(new VPackAttributeTranslator);
// these attribute names will be translated into short integer values
_translator->add(TRI_VOC_ATTRIBUTE_KEY, 1);
_translator->add(TRI_VOC_ATTRIBUTE_REV, 2);
_translator->add(TRI_VOC_ATTRIBUTE_ID, 3);
_translator->add(TRI_VOC_ATTRIBUTE_FROM, 4);
_translator->add(TRI_VOC_ATTRIBUTE_TO, 5);
translator->add(TRI_VOC_ATTRIBUTE_KEY, 1);
translator->add(TRI_VOC_ATTRIBUTE_REV, 2);
translator->add(TRI_VOC_ATTRIBUTE_ID, 3);
translator->add(TRI_VOC_ATTRIBUTE_FROM, 4);
translator->add(TRI_VOC_ATTRIBUTE_TO, 5);
_translator->seal();
translator->seal();
// initialize system attribute exclude handler
excludeHandler.reset(new SystemAttributeExcludeHandler);
customLengthHandler.reset(new CustomIdLengthHandler);
// initialize default options
defaultOptions.reset(new VPackOptions);
defaultOptions->attributeTranslator = nullptr;
defaultOptions->customTypeHandler = nullptr;
// initialize options for inserting documents
insertOptions.reset(new VPackOptions);
insertOptions->buildUnindexedArrays = false;
insertOptions->buildUnindexedObjects = false;
insertOptions->checkAttributeUniqueness = true;
insertOptions->sortAttributeNames = true;
insertOptions->attributeTranslator = translator.get();
insertOptions->customTypeHandler = customLengthHandler.get();
insertOptions->attributeExcludeHandler = excludeHandler.get();
}
VPackAttributeTranslator const* StorageOptions::getTranslator() {
return translator.get();
}
VPackOptions const* StorageOptions::getDefaultOptions() {
return defaultOptions.get();
}
VPackOptions const* StorageOptions::getInsertOptions() {
return insertOptions.get();
}
/*
// set options for JSON to document conversion
JsonToDocumentTemplate.buildUnindexedArrays = false;
JsonToDocumentTemplate.buildUnindexedObjects = false;
@ -209,24 +228,4 @@ StorageOptions::StorageOptions()
NonDocumentTemplate.escapeForwardSlashes = true;
NonDocumentTemplate.unsupportedTypeBehavior =
VPackOptions::FailOnUnsupportedType;
}
StorageOptions::~StorageOptions() {}
VPackOptions StorageOptions::getDocumentToJsonTemplate() {
return DocumentToJsonTemplate;
}
VPackOptions StorageOptions::getJsonToDocumentTemplate() {
return JsonToDocumentTemplate;
}
VPackOptions StorageOptions::getNonDocumentTemplate() {
return NonDocumentTemplate;
}
VPackCustomTypeHandler* StorageOptions::createCustomHandler(
arangodb::CollectionNameResolver const* resolver) {
return new CustomTypeHandlerImpl(resolver);
}
*/

View File

@ -35,14 +35,9 @@ namespace arangodb {
namespace StorageOptions {
void initialize();
VPackAttributeTranslator* getTranslator();
VPackOptions* getOptions();
VPackOptions* getDocumentToJsonTemplate();
VPackOptions* getJsonToDocumentTemplate();
VPackOptions* getNonDocumentTemplate();
// VPackCustomTypeHandler* createCustomHandler(
// arangodb::CollectionNameResolver const*);
VPackAttributeTranslator const* getTranslator();
VPackOptions const* getDefaultOptions();
VPackOptions const* getInsertOptions();
}
}

View File

@ -185,26 +185,6 @@ class Transaction {
return r;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief return the vpack options
//////////////////////////////////////////////////////////////////////////////
VPackOptions const* vpackOptions() const {
VPackOptions const* o = this->_transactionContext->getVPackOptions();
TRI_ASSERT(o != nullptr);
return o;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief return a copy of the vpack options
//////////////////////////////////////////////////////////////////////////////
VPackOptions copyVPackOptions() const {
VPackOptions const* o = this->_transactionContext->getVPackOptions();
TRI_ASSERT(o != nullptr);
return *o;
}
//////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the transaction is embedded
//////////////////////////////////////////////////////////////////////////////

View File

@ -38,10 +38,3 @@ TransactionContext::TransactionContext() {}
TransactionContext::~TransactionContext() {}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the vpack options
////////////////////////////////////////////////////////////////////////////////
VPackOptions const* TransactionContext::getVPackOptions() const {
return StorageOptions::getOptions();
}

View File

@ -84,12 +84,6 @@ class TransactionContext {
virtual int unregisterTransaction() = 0;
//////////////////////////////////////////////////////////////////////////////
/// @brief return the vpack options
//////////////////////////////////////////////////////////////////////////////
VPackOptions const* getVPackOptions() const;
};
}

View File

@ -61,7 +61,8 @@ static int const SLOT_DITCH = 2;
////////////////////////////////////////////////////////////////////////////////
static inline VPackSlice VPackFromMarker(TRI_df_marker_t const* marker) {
return VPackSlice(reinterpret_cast<uint8_t const*>(marker) + sizeof(TRI_df_marker_t) + 24); // TODO: remove hard-coded value
uint8_t const* ptr = reinterpret_cast<uint8_t const*>(marker) + sizeof(TRI_df_marker_t) + 24; // TODO: remove hard-coded value
return VPackSlice(ptr);
}
////////////////////////////////////////////////////////////////////////////////
@ -108,7 +109,7 @@ static void CopyAttributes(v8::Isolate* isolate, v8::Handle<v8::Object> self,
TRI_df_marker_t const* marker,
char const* excludeAttribute = nullptr) {
VPackSlice slice(VPackFromMarker(marker));
auto slice = VPackFromMarker(marker);
VPackObjectIterator it(slice);
while (it.valid()) {
@ -143,7 +144,7 @@ static void KeysOfVPack(v8::PropertyCallbackInfo<v8::Array> const& args) {
TRI_V8_RETURN(v8::Array::New(isolate));
}
VPackSlice slice(VPackFromMarker(marker));
auto slice = VPackFromMarker(marker);
std::vector<std::string> keys(VPackCollection::keys(slice));
v8::Handle<v8::Array> result = v8::Array::New(isolate, static_cast<int>(keys.size()));
@ -190,7 +191,7 @@ static void MapGetNamedVPack(
TRI_V8_RETURN(v8::Handle<v8::Value>());
}
VPackSlice slice(VPackFromMarker(marker));
auto slice = VPackFromMarker(marker);
TRI_V8_RETURN(TRI_VPackToV8(isolate, slice.get(key)));
} catch (...) {
@ -322,7 +323,7 @@ static void PropertyQueryVPack(
TRI_V8_RETURN(v8::Handle<v8::Integer>());
}
VPackSlice slice(VPackFromMarker(marker));
auto slice = VPackFromMarker(marker);
if (!slice.hasKey(key)) {
// key not found

View File

@ -1069,11 +1069,11 @@ static int AddSystemAttributes(Transaction* trx, TRI_voc_cid_t cid,
TRI_document_collection_t* document,
VPackBuilder& builder) {
// generate a new tick value
uint64_t const tick = TRI_NewTickServer();
TRI_voc_tick_t const tick = TRI_NewTickServer();
if (!builder.hasKey(TRI_VOC_ATTRIBUTE_KEY)) {
// "_key" attribute not present in object
std::string const keyString = document->_keyGenerator->generate(tick);
std::string keyString = document->_keyGenerator->generate(tick);
builder.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(keyString));
} else {
// "_key" attribute is present in object
@ -1090,19 +1090,16 @@ static int AddSystemAttributes(Transaction* trx, TRI_voc_cid_t cid,
return res;
}
}
/*
// now add _id attribute
// add _id attribute
uint8_t* p = builder.add(TRI_VOC_ATTRIBUTE_ID,
VPackValuePair(9ULL, VPackValueType::Custom));
*p++ = 0xf0;
arangodb::velocypack::storeUInt64(p, cid);
// now add _rev attribute
p = builder.add(TRI_VOC_ATTRIBUTE_REV,
VPackValuePair(9ULL, VPackValueType::Custom));
*p++ = 0xf1;
arangodb::velocypack::storeUInt64(p, tick);
*/
// add _rev attribute
builder.add(TRI_VOC_ATTRIBUTE_REV, VPackValue(std::to_string(tick)));
return TRI_ERROR_NO_ERROR;
}
@ -1236,6 +1233,8 @@ static void InsertVocbaseVPack(
// invalid value type. must be a document
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_TYPE_INVALID);
}
VPackOptions const* vpackOptions = StorageOptions::getInsertOptions();
// load collection
SingleCollectionWriteTransaction<1> trx(new V8TransactionContext(true),
@ -1247,7 +1246,7 @@ static void InsertVocbaseVPack(
TRI_V8_THROW_EXCEPTION(res);
}
VPackBuilder builder(trx.vpackOptions());
VPackBuilder builder(vpackOptions);
res = TRI_V8ToVPack(isolate, builder, args[0]->ToObject(), true);
if (res != TRI_ERROR_NO_ERROR) {
@ -1257,8 +1256,7 @@ static void InsertVocbaseVPack(
TRI_document_collection_t* document = trx.documentCollection();
// the AddSystemAttributes() needs the collection already loaded because it
// references the
// collection's key generator
// references the collection's key generator
res = AddSystemAttributes(&trx, col->_cid, document, builder);
if (res != TRI_ERROR_NO_ERROR) {
@ -1298,18 +1296,13 @@ static void InsertVocbaseVPack(
TRI_V8_RETURN_TRUE();
}
VPackSlice vpack(mptr.vpack());
std::string key = VPackSlice(mptr.vpack()).get(TRI_VOC_ATTRIBUTE_KEY).copyString();
v8::Handle<v8::Object> result = v8::Object::New(isolate);
TRI_GET_GLOBAL_STRING(_IdKey);
TRI_GET_GLOBAL_STRING(_RevKey);
TRI_GET_GLOBAL_STRING(_KeyKey);
result->Set(
_IdKey,
V8DocumentId(isolate, trx.resolver()->getCollectionName(col->_cid), key));
// result->Set(_RevKey,
// V8RevisionId(isolate, TRI_EXTRACT_MARKER_RID(&trx, &mptr)));
result->Set(_KeyKey, TRI_V8_STD_STRING(key));
result->ForceSet(TRI_V8_STRING(TRI_VOC_ATTRIBUTE_ID), V8DocumentId(isolate, trx.resolver()->getCollectionName(col->_cid), key));
result->ForceSet(TRI_V8_STRING(TRI_VOC_ATTRIBUTE_REV), TRI_V8_STD_STRING(vpack.get(TRI_VOC_ATTRIBUTE_REV).copyString()));
result->ForceSet(TRI_V8_STRING(TRI_VOC_ATTRIBUTE_KEY), TRI_V8_STD_STRING(key));
TRI_V8_RETURN(result);
}
@ -1844,9 +1837,7 @@ static void RemoveVocbaseVPack(
TRI_V8_THROW_EXCEPTION(res);
}
VPackOptions vpackOptions = trx.copyVPackOptions();
vpackOptions.attributeExcludeHandler = nullptr;
VPackBuilder builder(&vpackOptions);
VPackBuilder builder(StorageOptions::getDefaultOptions());
builder.add(VPackValue(VPackValueType::Object));
builder.add(TRI_VOC_ATTRIBUTE_KEY,

View File

@ -914,8 +914,6 @@ static void JS_AllQuery(v8::FunctionCallbackInfo<v8::Value> const& args) {
for (uint64_t i = 0; i < n; ++i) {
v8::Handle<v8::Value> doc = V8VPackWrapper::wrap(isolate, &trx, cid, ditch, static_cast<TRI_df_marker_t const*>(docs[i].getDataPtr()));
// v8::Handle<v8::Value> doc = TRI_VPackToV8(isolate, VPackSlice(docs[i].vpack()));
// WRAP_SHAPED_JSON(trx, col->_cid, docs[i].getDataPtr());
if (doc.IsEmpty()) {
TRI_V8_THROW_EXCEPTION_MEMORY();

View File

@ -26,6 +26,7 @@
#include "Basics/Common.h"
#include "Basics/JsonHelper.h"
#include "Storage/Options.h"
#include "Utils/Transaction.h"
#include "VocBase/document-collection.h"
#include "VocBase/shape-accessor.h"
@ -102,7 +103,7 @@ static inline std::string TRI_EXTRACT_MARKER_KEY(
if (marker->_type == TRI_WAL_MARKER_VPACK_DOCUMENT) {
auto b = reinterpret_cast<char const*>(marker) +
sizeof(arangodb::wal::vpack_document_marker_t);
VPackSlice slice(reinterpret_cast<uint8_t const*>(b), trx->vpackOptions());
VPackSlice slice(reinterpret_cast<uint8_t const*>(b));
return slice.get(TRI_VOC_ATTRIBUTE_KEY).copyString();
}
@ -133,7 +134,7 @@ static inline TRI_voc_rid_t TRI_EXTRACT_MARKER_RID(
if (marker->_type == TRI_WAL_MARKER_VPACK_DOCUMENT) {
auto b = reinterpret_cast<char const*>(marker) +
sizeof(arangodb::wal::vpack_document_marker_t);
VPackSlice slice(reinterpret_cast<uint8_t const*>(b), trx->vpackOptions());
VPackSlice slice(reinterpret_cast<uint8_t const*>(b));
VPackSlice value = slice.get(TRI_VOC_ATTRIBUTE_REV);
return arangodb::velocypack::readUInt64(value.start() + 1);
}
@ -168,7 +169,7 @@ static inline bool TRI_MATCHES_MARKER_KEY(arangodb::Transaction* trx,
if (marker->_type == TRI_WAL_MARKER_VPACK_DOCUMENT) {
auto b = reinterpret_cast<char const*>(marker) +
sizeof(arangodb::wal::vpack_document_marker_t);
VPackSlice slice(reinterpret_cast<uint8_t const*>(b), trx->vpackOptions());
VPackSlice slice(reinterpret_cast<uint8_t const*>(b));
VPackValueLength len;
char const* p = slice.get(TRI_VOC_ATTRIBUTE_KEY).getString(len);
if (len != strlen(key)) {
@ -198,13 +199,13 @@ static inline bool TRI_MATCHES_MARKER_KEY(arangodb::Transaction* trx,
rm->_type == TRI_WAL_MARKER_VPACK_DOCUMENT) {
auto lb = reinterpret_cast<char const*>(lm) +
sizeof(arangodb::wal::vpack_document_marker_t);
VPackSlice ls(reinterpret_cast<uint8_t const*>(lb), trx->vpackOptions());
VPackSlice ls(reinterpret_cast<uint8_t const*>(lb));
VPackValueLength llen;
char const* p = ls.get(TRI_VOC_ATTRIBUTE_KEY).getString(llen);
auto rb = reinterpret_cast<char const*>(rm) +
sizeof(arangodb::wal::vpack_document_marker_t);
VPackSlice rs(reinterpret_cast<uint8_t const*>(rb), trx->vpackOptions());
VPackSlice rs(reinterpret_cast<uint8_t const*>(rb));
VPackValueLength rlen;
char const* q = rs.get(TRI_VOC_ATTRIBUTE_KEY).getString(rlen);