mirror of https://gitee.com/bigwinds/arangodb
Feature/velocypack update (#6678)
This commit is contained in:
parent
883a2baace
commit
c06f2d77da
|
@ -229,6 +229,8 @@ class Buffer {
|
||||||
return append(value.data(), value.size());
|
return append(value.data(), value.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reserves len *extra* bytes of storage space
|
||||||
|
// this should probably be renamed to reserveExtra
|
||||||
inline void reserve(ValueLength len) {
|
inline void reserve(ValueLength len) {
|
||||||
VELOCYPACK_ASSERT(_size <= _capacity);
|
VELOCYPACK_ASSERT(_size <= _capacity);
|
||||||
|
|
||||||
|
@ -255,8 +257,8 @@ class Buffer {
|
||||||
|
|
||||||
// need reallocation
|
// need reallocation
|
||||||
ValueLength newLen = _size + len;
|
ValueLength newLen = _size + len;
|
||||||
static constexpr double growthFactor = 1.25;
|
constexpr double growthFactor = 1.25;
|
||||||
if (_size > 0 && newLen < growthFactor * _size) {
|
if (newLen < growthFactor * _size) {
|
||||||
// ensure the buffer grows sensibly and not by 1 byte only
|
// ensure the buffer grows sensibly and not by 1 byte only
|
||||||
newLen = static_cast<ValueLength>(growthFactor * _size);
|
newLen = static_cast<ValueLength>(growthFactor * _size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,15 +114,6 @@ class Builder {
|
||||||
bool _keyWritten; // indicates that in the current object the key
|
bool _keyWritten; // indicates that in the current object the key
|
||||||
// has been written but the value not yet
|
// has been written but the value not yet
|
||||||
|
|
||||||
// Sort the indices by attribute name:
|
|
||||||
static void doActualSort(std::vector<SortEntry>& entries);
|
|
||||||
|
|
||||||
// Find the actual bytes of the attribute name of the VPack value
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
void sortObjectIndexShort(uint8_t* objBase,
|
void sortObjectIndexShort(uint8_t* objBase,
|
||||||
std::vector<ValueLength>& offsets) const;
|
std::vector<ValueLength>& offsets) const;
|
||||||
|
|
||||||
|
@ -130,7 +121,13 @@ class Builder {
|
||||||
std::vector<ValueLength>& offsets);
|
std::vector<ValueLength>& offsets);
|
||||||
|
|
||||||
void sortObjectIndex(uint8_t* objBase,
|
void sortObjectIndex(uint8_t* objBase,
|
||||||
std::vector<ValueLength>& offsets);
|
std::vector<ValueLength>& offsets) {
|
||||||
|
if (offsets.size() > 32) {
|
||||||
|
sortObjectIndexLong(objBase, offsets);
|
||||||
|
} else {
|
||||||
|
sortObjectIndexShort(objBase, offsets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Options const* options;
|
Options const* options;
|
||||||
|
@ -573,7 +570,7 @@ class Builder {
|
||||||
private:
|
private:
|
||||||
inline void checkKeyIsString(bool isString) {
|
inline void checkKeyIsString(bool isString) {
|
||||||
if (!_stack.empty()) {
|
if (!_stack.empty()) {
|
||||||
ValueLength const tos = _stack.back();
|
ValueLength const& tos = _stack.back();
|
||||||
if (_start[tos] == 0x0b || _start[tos] == 0x14) {
|
if (_start[tos] == 0x0b || _start[tos] == 0x14) {
|
||||||
if (!_keyWritten && !isString) {
|
if (!_keyWritten && !isString) {
|
||||||
throw Exception(Exception::BuilderKeyMustBeString);
|
throw Exception(Exception::BuilderKeyMustBeString);
|
||||||
|
@ -615,7 +612,7 @@ class Builder {
|
||||||
uint8_t* addInternal(std::string const& attrName, T const& sub) {
|
uint8_t* addInternal(std::string const& attrName, T const& sub) {
|
||||||
bool haveReported = false;
|
bool haveReported = false;
|
||||||
if (!_stack.empty()) {
|
if (!_stack.empty()) {
|
||||||
ValueLength& tos = _stack.back();
|
ValueLength const& tos = _stack.back();
|
||||||
if (_start[tos] != 0x0b && _start[tos] != 0x14) {
|
if (_start[tos] != 0x0b && _start[tos] != 0x14) {
|
||||||
throw Exception(Exception::BuilderNeedOpenObject);
|
throw Exception(Exception::BuilderNeedOpenObject);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,29 +39,10 @@
|
||||||
#include "velocypack/velocypack-common.h"
|
#include "velocypack/velocypack-common.h"
|
||||||
#include "velocypack/Exception.h"
|
#include "velocypack/Exception.h"
|
||||||
#include "velocypack/Options.h"
|
#include "velocypack/Options.h"
|
||||||
|
#include "velocypack/StringRef.h"
|
||||||
#include "velocypack/Value.h"
|
#include "velocypack/Value.h"
|
||||||
#include "velocypack/ValueType.h"
|
#include "velocypack/ValueType.h"
|
||||||
|
|
||||||
#ifndef VELOCYPACK_XXHASH
|
|
||||||
#ifndef VELOCYPACK_FASTHASH
|
|
||||||
#define VELOCYPACK_XXHASH
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VELOCYPACK_XXHASH
|
|
||||||
// forward for XXH64 function declared elsewhere
|
|
||||||
extern "C" unsigned long long XXH64(void const*, size_t, unsigned long long);
|
|
||||||
|
|
||||||
#define VELOCYPACK_HASH(mem, size, seed) XXH64(mem, size, seed)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef VELOCYPACK_FASTHASH
|
|
||||||
// forward for fasthash64 function declared elsewhere
|
|
||||||
uint64_t fasthash64(void const*, size_t, uint64_t);
|
|
||||||
|
|
||||||
#define VELOCYPACK_HASH(mem, size, seed) fasthash64(mem, size, seed)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
namespace velocypack {
|
namespace velocypack {
|
||||||
|
|
||||||
|
@ -185,6 +166,13 @@ class Slice {
|
||||||
return VELOCYPACK_HASH(start(), size, seed);
|
return VELOCYPACK_HASH(start(), size, seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hashes the binary representation of a value, not using precalculated hash values
|
||||||
|
// this is mainly here for testing purposes
|
||||||
|
inline uint64_t hashSlow(uint64_t seed = defaultSeed) const {
|
||||||
|
size_t const size = checkOverflow(byteSize());
|
||||||
|
return VELOCYPACK_HASH(start(), size, seed);
|
||||||
|
}
|
||||||
|
|
||||||
// hashes the value, normalizing different representations of
|
// hashes the value, normalizing different representations of
|
||||||
// arrays, objects and numbers. this function may produce different
|
// arrays, objects and numbers. this function may produce different
|
||||||
// hash values than the binary hash() function
|
// hash values than the binary hash() function
|
||||||
|
@ -447,7 +435,8 @@ class Slice {
|
||||||
|
|
||||||
// look for the specified attribute path inside an Object
|
// look for the specified attribute path inside an Object
|
||||||
// returns a Slice(ValueType::None) if not found
|
// returns a Slice(ValueType::None) if not found
|
||||||
Slice get(std::vector<std::string> const& attributes,
|
template<typename T>
|
||||||
|
Slice get(std::vector<T> const& attributes,
|
||||||
bool resolveExternals = false) const {
|
bool resolveExternals = false) const {
|
||||||
size_t const n = attributes.size();
|
size_t const n = attributes.size();
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
|
@ -476,48 +465,47 @@ class Slice {
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
|
|
||||||
// look for the specified attribute path inside an Object
|
// look for the specified attribute inside an Object
|
||||||
// returns a Slice(ValueType::None) if not found
|
// returns a Slice(ValueType::None) if not found
|
||||||
Slice get(std::vector<char const*> const& attributes) const {
|
Slice get(StringRef const& attribute) const;
|
||||||
size_t const n = attributes.size();
|
|
||||||
if (n == 0) {
|
|
||||||
throw Exception(Exception::InvalidAttributePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// use ourselves as the starting point
|
Slice get(std::string const& attribute) const {
|
||||||
Slice last = Slice(start());
|
return get(StringRef(attribute.data(), attribute.size()));
|
||||||
for (size_t i = 0; i < attributes.size(); ++i) {
|
|
||||||
// fetch subattribute
|
|
||||||
last = last.get(attributes[i]);
|
|
||||||
|
|
||||||
// abort as early as possible
|
|
||||||
if (last.isNone() || (i + 1 < n && !last.isObject())) {
|
|
||||||
return Slice();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return last;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// look for the specified attribute inside an Object
|
|
||||||
// returns a Slice(ValueType::None) if not found
|
|
||||||
Slice get(std::string const& attribute) const;
|
|
||||||
|
|
||||||
// look for the specified attribute inside an Object
|
|
||||||
// returns a Slice(ValueType::None) if not found
|
|
||||||
Slice get(char const* attribute) const {
|
Slice get(char const* attribute) const {
|
||||||
return get(std::string(attribute));
|
return get(StringRef(attribute));
|
||||||
}
|
}
|
||||||
|
|
||||||
Slice operator[](std::string const& attribute) const {
|
Slice get(char const* attribute, size_t length) const {
|
||||||
|
return get(StringRef(attribute, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
Slice operator[](StringRef const& attribute) const {
|
||||||
return get(attribute);
|
return get(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Slice operator[](std::string const& attribute) const {
|
||||||
|
return get(attribute.data(), attribute.size());
|
||||||
|
}
|
||||||
|
|
||||||
// whether or not an Object has a specific key
|
// whether or not an Object has a specific key
|
||||||
bool hasKey(std::string const& attribute) const {
|
bool hasKey(StringRef const& attribute) const {
|
||||||
return !get(attribute).isNone();
|
return !get(attribute).isNone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasKey(std::string const& attribute) const {
|
||||||
|
return hasKey(StringRef(attribute));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasKey(char const* attribute) const {
|
||||||
|
return hasKey(StringRef(attribute));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasKey(char const* attribute, size_t length) const {
|
||||||
|
return hasKey(StringRef(attribute, length));
|
||||||
|
}
|
||||||
|
|
||||||
// whether or not an Object has a specific sub-key
|
// whether or not an Object has a specific sub-key
|
||||||
bool hasKey(std::vector<std::string> const& attributes) const {
|
bool hasKey(std::vector<std::string> const& attributes) const {
|
||||||
return !get(attributes).isNone();
|
return !get(attributes).isNone();
|
||||||
|
@ -705,6 +693,25 @@ class Slice {
|
||||||
|
|
||||||
throw Exception(Exception::InvalidValueType, "Expecting type String");
|
throw Exception(Exception::InvalidValueType, "Expecting type String");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return a copy of the value for a String object
|
||||||
|
StringRef stringRef() const {
|
||||||
|
uint8_t h = head();
|
||||||
|
if (h >= 0x40 && h <= 0xbe) {
|
||||||
|
// short UTF-8 String
|
||||||
|
ValueLength length = h - 0x40;
|
||||||
|
return StringRef(reinterpret_cast<char const*>(_start + 1),
|
||||||
|
static_cast<size_t>(length));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h == 0xbf) {
|
||||||
|
ValueLength length = readIntegerFixed<ValueLength, 8>(_start + 1);
|
||||||
|
return StringRef(reinterpret_cast<char const*>(_start + 1 + 8),
|
||||||
|
checkOverflow(length));
|
||||||
|
}
|
||||||
|
|
||||||
|
throw Exception(Exception::InvalidValueType, "Expecting type String");
|
||||||
|
}
|
||||||
|
|
||||||
// return the value for a Binary object
|
// return the value for a Binary object
|
||||||
uint8_t const* getBinary(ValueLength& length) const {
|
uint8_t const* getBinary(ValueLength& length) const {
|
||||||
|
@ -879,15 +886,37 @@ class Slice {
|
||||||
|
|
||||||
Slice makeKey() const;
|
Slice makeKey() const;
|
||||||
|
|
||||||
int compareString(char const* value, size_t length) const;
|
int compareString(StringRef const& value) const;
|
||||||
int compareStringUnchecked(char const* value, size_t length) const noexcept;
|
|
||||||
|
|
||||||
inline int compareString(std::string const& attribute) const {
|
inline int compareString(std::string const& value) const {
|
||||||
return compareString(attribute.data(), attribute.size());
|
return compareString(StringRef(value.data(), value.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
int compareString(char const* value, size_t length) const {
|
||||||
|
return compareString(StringRef(value, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
int compareStringUnchecked(StringRef const& value) const noexcept;
|
||||||
|
|
||||||
|
int compareStringUnchecked(std::string const& value) const noexcept {
|
||||||
|
return compareStringUnchecked(StringRef(value.data(), value.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isEqualString(std::string const& attribute) const;
|
int compareStringUnchecked(char const* value, size_t length) const noexcept {
|
||||||
bool isEqualStringUnchecked(std::string const& attribute) const noexcept;
|
return compareStringUnchecked(StringRef(value, length));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEqualString(StringRef const& attribute) const;
|
||||||
|
|
||||||
|
bool isEqualString(std::string const& attribute) const {
|
||||||
|
return isEqualString(StringRef(attribute.data(), attribute.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEqualStringUnchecked(StringRef const& attribute) const noexcept;
|
||||||
|
|
||||||
|
bool isEqualStringUnchecked(std::string const& attribute) const noexcept {
|
||||||
|
return isEqualStringUnchecked(StringRef(attribute.data(), attribute.size()));
|
||||||
|
}
|
||||||
|
|
||||||
// check if two Slices are equal on the binary level
|
// check if two Slices are equal on the binary level
|
||||||
bool equals(Slice const& other) const {
|
bool equals(Slice const& other) const {
|
||||||
|
@ -944,7 +973,7 @@ class Slice {
|
||||||
// translates an integer key into a string, without checks
|
// translates an integer key into a string, without checks
|
||||||
Slice translateUnchecked() const;
|
Slice translateUnchecked() const;
|
||||||
|
|
||||||
Slice getFromCompactObject(std::string const& attribute) const;
|
Slice getFromCompactObject(StringRef const& attribute) const;
|
||||||
|
|
||||||
// extract the nth member from an Array
|
// extract the nth member from an Array
|
||||||
Slice getNth(ValueLength index) const;
|
Slice getNth(ValueLength index) const;
|
||||||
|
@ -968,12 +997,12 @@ class Slice {
|
||||||
}
|
}
|
||||||
|
|
||||||
// perform a linear search for the specified attribute inside an Object
|
// perform a linear search for the specified attribute inside an Object
|
||||||
Slice searchObjectKeyLinear(std::string const& attribute, ValueLength ieBase,
|
Slice searchObjectKeyLinear(StringRef const& attribute, ValueLength ieBase,
|
||||||
ValueLength offsetSize, ValueLength n) const;
|
ValueLength offsetSize, ValueLength n) const;
|
||||||
|
|
||||||
// perform a binary search for the specified attribute inside an Object
|
// perform a binary search for the specified attribute inside an Object
|
||||||
template<ValueLength offsetSize>
|
template<ValueLength offsetSize>
|
||||||
Slice searchObjectKeyBinary(std::string const& attribute, ValueLength ieBase, ValueLength n) const;
|
Slice searchObjectKeyBinary(StringRef const& attribute, ValueLength ieBase, ValueLength n) const;
|
||||||
|
|
||||||
// assert that the slice is of a specific type
|
// assert that the slice is of a specific type
|
||||||
// can be used for debugging and removed in production
|
// can be used for debugging and removed in production
|
||||||
|
|
|
@ -29,12 +29,14 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "velocypack/velocypack-common.h"
|
#include "velocypack/velocypack-common.h"
|
||||||
#include "velocypack/Slice.h"
|
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
namespace velocypack {
|
namespace velocypack {
|
||||||
|
class Slice;
|
||||||
|
|
||||||
class StringRef {
|
class StringRef {
|
||||||
public:
|
public:
|
||||||
|
@ -44,19 +46,18 @@ class StringRef {
|
||||||
/// @brief create a StringRef from an std::string
|
/// @brief create a StringRef from an std::string
|
||||||
explicit StringRef(std::string const& str) noexcept : StringRef(str.data(), str.size()) {}
|
explicit StringRef(std::string const& str) noexcept : StringRef(str.data(), str.size()) {}
|
||||||
|
|
||||||
/// @brief create a StringRef from a null-terminated C string
|
|
||||||
explicit StringRef(char const* data) noexcept : StringRef(data, strlen(data)) {}
|
|
||||||
|
|
||||||
/// @brief create a StringRef from a VPack slice (must be of type String)
|
|
||||||
explicit StringRef(arangodb::velocypack::Slice const& slice) {
|
|
||||||
VELOCYPACK_ASSERT(slice.isString());
|
|
||||||
arangodb::velocypack::ValueLength l;
|
|
||||||
_data = slice.getString(l);
|
|
||||||
_length = l;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief create a StringRef from a C string plus length
|
/// @brief create a StringRef from a C string plus length
|
||||||
StringRef(char const* data, size_t length) noexcept : _data(data), _length(length) {}
|
constexpr StringRef(char const* data, size_t length) noexcept : _data(data), _length(length) {}
|
||||||
|
|
||||||
|
/// @brief create a StringRef from a null-terminated C string
|
||||||
|
#if __cplusplus >= 201703
|
||||||
|
constexpr explicit StringRef(char const* data) noexcept : StringRef(data, std::char_traits<char>::length(data)) {}
|
||||||
|
#else
|
||||||
|
explicit StringRef(char const* data) noexcept : StringRef(data, strlen(data)) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @brief create a StringRef from a VPack slice (must be of type String)
|
||||||
|
explicit StringRef(arangodb::velocypack::Slice const& slice);
|
||||||
|
|
||||||
/// @brief create a StringRef from another StringRef
|
/// @brief create a StringRef from another StringRef
|
||||||
StringRef(StringRef const& other) noexcept
|
StringRef(StringRef const& other) noexcept
|
||||||
|
@ -95,12 +96,7 @@ class StringRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a StringRef from a VPack slice of type String
|
/// @brief create a StringRef from a VPack slice of type String
|
||||||
StringRef& operator=(arangodb::velocypack::Slice const& slice) {
|
StringRef& operator=(arangodb::velocypack::Slice const& slice);
|
||||||
arangodb::velocypack::ValueLength l;
|
|
||||||
_data = slice.getString(l);
|
|
||||||
_length = l;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
int compare(std::string const& other) const noexcept {
|
int compare(std::string const& other) const noexcept {
|
||||||
int res = memcmp(_data, other.data(), (std::min)(_length, other.size()));
|
int res = memcmp(_data, other.data(), (std::min)(_length, other.size()));
|
||||||
|
@ -126,17 +122,17 @@ class StringRef {
|
||||||
return (_length == 0);
|
return (_length == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char const* begin() const {
|
inline char const* begin() const noexcept {
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char const* end() const {
|
inline char const* end() const noexcept {
|
||||||
return _data + _length;
|
return _data + _length;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char front() const { return _data[0]; }
|
inline char front() const noexcept { return _data[0]; }
|
||||||
|
|
||||||
inline char back() const { return _data[_length - 1]; }
|
inline char back() const noexcept { return _data[_length - 1]; }
|
||||||
|
|
||||||
inline char operator[](size_t index) const noexcept {
|
inline char operator[](size_t index) const noexcept {
|
||||||
return _data[index];
|
return _data[index];
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
// for size_t:
|
// for size_t:
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(__GNUG__)
|
#if defined(__GNUC__) || defined(__GNUG__)
|
||||||
#define VELOCYPACK_LIKELY(v) __builtin_expect(!!(v), 1)
|
#define VELOCYPACK_LIKELY(v) __builtin_expect(!!(v), 1)
|
||||||
|
@ -77,6 +78,26 @@
|
||||||
#define VELOCYPACK_UNUSED /* unused */
|
#define VELOCYPACK_UNUSED /* unused */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef VELOCYPACK_XXHASH
|
||||||
|
#ifndef VELOCYPACK_FASTHASH
|
||||||
|
#define VELOCYPACK_XXHASH
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VELOCYPACK_XXHASH
|
||||||
|
// forward for XXH64 function declared elsewhere
|
||||||
|
extern "C" unsigned long long XXH64(void const*, size_t, unsigned long long);
|
||||||
|
|
||||||
|
#define VELOCYPACK_HASH(mem, size, seed) XXH64(mem, size, seed)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VELOCYPACK_FASTHASH
|
||||||
|
// forward for fasthash64 function declared elsewhere
|
||||||
|
uint64_t fasthash64(void const*, size_t, uint64_t);
|
||||||
|
|
||||||
|
#define VELOCYPACK_HASH(mem, size, seed) fasthash64(mem, size, seed)
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
namespace velocypack {
|
namespace velocypack {
|
||||||
|
|
||||||
|
@ -177,10 +198,12 @@ static inline int64_t toInt64(uint64_t v) noexcept {
|
||||||
// specified length, starting at the specified byte offset
|
// specified length, starting at the specified byte offset
|
||||||
template <typename T, ValueLength length>
|
template <typename T, ValueLength length>
|
||||||
static inline T readIntegerFixed(uint8_t const* start) noexcept {
|
static inline T readIntegerFixed(uint8_t const* start) noexcept {
|
||||||
|
static_assert(std::is_unsigned<T>::value, "result type must be unsigned");
|
||||||
static_assert(length > 0, "length must be > 0");
|
static_assert(length > 0, "length must be > 0");
|
||||||
|
static_assert(length <= sizeof(T), "length must be <= sizeof(T)");
|
||||||
uint64_t x = 8;
|
uint64_t x = 8;
|
||||||
uint8_t const* end = start + length;
|
uint8_t const* end = start + length;
|
||||||
uint64_t value = static_cast<T>(*start++);
|
T value = static_cast<T>(*start++);
|
||||||
while (start < end) {
|
while (start < end) {
|
||||||
value += static_cast<T>(*start++) << x;
|
value += static_cast<T>(*start++) << x;
|
||||||
x += 8;
|
x += 8;
|
||||||
|
@ -189,13 +212,15 @@ static inline T readIntegerFixed(uint8_t const* start) noexcept {
|
||||||
}
|
}
|
||||||
|
|
||||||
// read an unsigned little endian integer value of the
|
// read an unsigned little endian integer value of the
|
||||||
// specified length, starting at the specified byte offset
|
// specified, non-0 length, starting at the specified byte offset
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static inline T readIntegerNonEmpty(uint8_t const* start, ValueLength length) noexcept {
|
static inline T readIntegerNonEmpty(uint8_t const* start, ValueLength length) noexcept {
|
||||||
|
static_assert(std::is_unsigned<T>::value, "result type must be unsigned");
|
||||||
VELOCYPACK_ASSERT(length > 0);
|
VELOCYPACK_ASSERT(length > 0);
|
||||||
|
VELOCYPACK_ASSERT(length <= sizeof(T));
|
||||||
uint64_t x = 8;
|
uint64_t x = 8;
|
||||||
uint8_t const* end = start + length;
|
uint8_t const* end = start + length;
|
||||||
uint64_t value = static_cast<T>(*start++);
|
T value = static_cast<T>(*start++);
|
||||||
while (start < end) {
|
while (start < end) {
|
||||||
value += static_cast<T>(*start++) << x;
|
value += static_cast<T>(*start++) << x;
|
||||||
x += 8;
|
x += 8;
|
||||||
|
|
|
@ -34,6 +34,76 @@
|
||||||
#include "velocypack/StringRef.h"
|
#include "velocypack/StringRef.h"
|
||||||
|
|
||||||
using namespace arangodb::velocypack;
|
using namespace arangodb::velocypack;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Find the actual bytes of the attribute name of the VPack value
|
||||||
|
// 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) {
|
||||||
|
uint8_t const b = *base;
|
||||||
|
if (b >= 0x40 && b <= 0xbe) {
|
||||||
|
// short UTF-8 string
|
||||||
|
len = b - 0x40;
|
||||||
|
return base + 1;
|
||||||
|
}
|
||||||
|
if (b == 0xbf) {
|
||||||
|
// long UTF-8 string
|
||||||
|
len = 0;
|
||||||
|
// read string length
|
||||||
|
for (size_t i = 8; i >= 1; i--) {
|
||||||
|
len = (len << 8) + base[i];
|
||||||
|
}
|
||||||
|
return base + 1 + 8; // string starts here
|
||||||
|
}
|
||||||
|
|
||||||
|
// translate attribute name
|
||||||
|
return findAttrName(arangodb::velocypack::Slice(base).makeKey().start(), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ObjectIndexSorterShort {
|
||||||
|
explicit ObjectIndexSorterShort(uint8_t const* objBase) : objBase(objBase) {}
|
||||||
|
|
||||||
|
bool operator()(arangodb::velocypack::ValueLength const& a,
|
||||||
|
arangodb::velocypack::ValueLength const& b) const noexcept {
|
||||||
|
uint8_t const* aa = objBase + a;
|
||||||
|
uint8_t const* bb = objBase + b;
|
||||||
|
if (*aa >= 0x40 && *aa <= 0xbe && *bb >= 0x40 && *bb <= 0xbe) {
|
||||||
|
// The fast path, short strings:
|
||||||
|
uint8_t m = (std::min)(*aa - 0x40, *bb - 0x40);
|
||||||
|
int c = memcmp(aa + 1, bb + 1, arangodb::velocypack::checkOverflow(m));
|
||||||
|
return (c < 0 || (c == 0 && *aa < *bb));
|
||||||
|
} else {
|
||||||
|
uint64_t lena;
|
||||||
|
uint64_t lenb;
|
||||||
|
aa = findAttrName(aa, lena);
|
||||||
|
bb = findAttrName(bb, lenb);
|
||||||
|
uint64_t m = (std::min)(lena, lenb);
|
||||||
|
int c = memcmp(aa, bb, arangodb::velocypack::checkOverflow(m));
|
||||||
|
return (c < 0 || (c == 0 && lena < lenb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t const* objBase;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ObjectIndexSorterLong {
|
||||||
|
bool operator()(arangodb::velocypack::Builder::SortEntry const& a,
|
||||||
|
arangodb::velocypack::Builder::SortEntry const& b) const noexcept {
|
||||||
|
// return true iff a < b:
|
||||||
|
uint8_t const* pa = a.nameStart;
|
||||||
|
uint64_t sizea = a.nameSize;
|
||||||
|
uint8_t const* pb = b.nameStart;
|
||||||
|
uint64_t sizeb = b.nameSize;
|
||||||
|
size_t const compareLength = arangodb::velocypack::checkOverflow((std::min)(sizea, sizeb));
|
||||||
|
int res = memcmp(pa, pb, compareLength);
|
||||||
|
|
||||||
|
return (res < 0 || (res == 0 && sizea < sizeb));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
std::string Builder::toString() const {
|
std::string Builder::toString() const {
|
||||||
Options options;
|
Options options;
|
||||||
|
@ -52,63 +122,9 @@ std::string Builder::toJson() const {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Builder::doActualSort(std::vector<SortEntry>& entries) {
|
|
||||||
VELOCYPACK_ASSERT(entries.size() > 1);
|
|
||||||
std::sort(entries.begin(), entries.end(),
|
|
||||||
[](SortEntry const& a, SortEntry const& b) {
|
|
||||||
// return true iff a < b:
|
|
||||||
uint8_t const* pa = a.nameStart;
|
|
||||||
uint64_t sizea = a.nameSize;
|
|
||||||
uint8_t const* pb = b.nameStart;
|
|
||||||
uint64_t sizeb = b.nameSize;
|
|
||||||
size_t const compareLength = checkOverflow((std::min)(sizea, sizeb));
|
|
||||||
int res = memcmp(pa, pb, compareLength);
|
|
||||||
|
|
||||||
return (res < 0 || (res == 0 && sizea < sizeb));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
|
||||||
len = b - 0x40;
|
|
||||||
return base + 1;
|
|
||||||
}
|
|
||||||
if (b == 0xbf) {
|
|
||||||
// long UTF-8 string
|
|
||||||
len = 0;
|
|
||||||
// read string length
|
|
||||||
for (size_t i = 8; i >= 1; i--) {
|
|
||||||
len = (len << 8) + base[i];
|
|
||||||
}
|
|
||||||
return base + 1 + 8; // string starts here
|
|
||||||
}
|
|
||||||
|
|
||||||
// translate attribute name
|
|
||||||
return findAttrName(Slice(base).makeKey().start(), len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Builder::sortObjectIndexShort(uint8_t* objBase,
|
void Builder::sortObjectIndexShort(uint8_t* objBase,
|
||||||
std::vector<ValueLength>& offsets) const {
|
std::vector<ValueLength>& offsets) const {
|
||||||
std::sort(offsets.begin(), offsets.end(), [&objBase](ValueLength a, ValueLength b) -> bool {
|
std::sort(offsets.begin(), offsets.end(), ::ObjectIndexSorterShort(objBase));
|
||||||
uint8_t const* aa = objBase + a;
|
|
||||||
uint8_t const* bb = objBase + b;
|
|
||||||
if (*aa >= 0x40 && *aa <= 0xbe && *bb >= 0x40 && *bb <= 0xbe) {
|
|
||||||
// The fast path, short strings:
|
|
||||||
uint8_t m = (std::min)(*aa - 0x40, *bb - 0x40);
|
|
||||||
int c = memcmp(aa + 1, bb + 1, checkOverflow(m));
|
|
||||||
return (c < 0 || (c == 0 && *aa < *bb));
|
|
||||||
} else {
|
|
||||||
uint64_t lena;
|
|
||||||
uint64_t lenb;
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Builder::sortObjectIndexLong(uint8_t* objBase,
|
void Builder::sortObjectIndexLong(uint8_t* objBase,
|
||||||
|
@ -116,15 +132,16 @@ void Builder::sortObjectIndexLong(uint8_t* objBase,
|
||||||
_sortEntries.clear();
|
_sortEntries.clear();
|
||||||
|
|
||||||
size_t const n = offsets.size();
|
size_t const n = offsets.size();
|
||||||
|
VELOCYPACK_ASSERT(n > 1);
|
||||||
_sortEntries.reserve(n);
|
_sortEntries.reserve(n);
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
SortEntry e;
|
SortEntry e;
|
||||||
e.offset = offsets[i];
|
e.offset = offsets[i];
|
||||||
e.nameStart = findAttrName(objBase + e.offset, e.nameSize);
|
e.nameStart = ::findAttrName(objBase + e.offset, e.nameSize);
|
||||||
_sortEntries.push_back(e);
|
_sortEntries.push_back(e);
|
||||||
}
|
}
|
||||||
VELOCYPACK_ASSERT(_sortEntries.size() == n);
|
VELOCYPACK_ASSERT(_sortEntries.size() == n);
|
||||||
doActualSort(_sortEntries);
|
std::sort(_sortEntries.begin(), _sortEntries.end(), ::ObjectIndexSorterLong());
|
||||||
|
|
||||||
// copy back the sorted offsets
|
// copy back the sorted offsets
|
||||||
for (size_t i = 0; i < n; i++) {
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
@ -133,15 +150,6 @@ void Builder::sortObjectIndexLong(uint8_t* objBase,
|
||||||
_sortEntries.clear();
|
_sortEntries.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Builder::sortObjectIndex(uint8_t* objBase,
|
|
||||||
std::vector<ValueLength>& offsets) {
|
|
||||||
if (offsets.size() > 32) {
|
|
||||||
sortObjectIndexLong(objBase, offsets);
|
|
||||||
} else {
|
|
||||||
sortObjectIndexShort(objBase, offsets);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Builder::removeLast() {
|
void Builder::removeLast() {
|
||||||
if (_stack.empty()) {
|
if (_stack.empty()) {
|
||||||
throw Exception(Exception::BuilderNeedOpenCompound);
|
throw Exception(Exception::BuilderNeedOpenCompound);
|
||||||
|
|
|
@ -746,7 +746,7 @@ uint64_t Slice::normalizedHash(uint64_t seed) const {
|
||||||
|
|
||||||
// look for the specified attribute inside an Object
|
// look for the specified attribute inside an Object
|
||||||
// returns a Slice(ValueType::None) if not found
|
// returns a Slice(ValueType::None) if not found
|
||||||
Slice Slice::get(std::string const& attribute) const {
|
Slice Slice::get(StringRef const& attribute) const {
|
||||||
if (VELOCYPACK_UNLIKELY(!isObject())) {
|
if (VELOCYPACK_UNLIKELY(!isObject())) {
|
||||||
throw Exception(Exception::InvalidValueType, "Expecting Object");
|
throw Exception(Exception::InvalidValueType, "Expecting Object");
|
||||||
}
|
}
|
||||||
|
@ -934,12 +934,13 @@ int64_t Slice::getSmallInt() const {
|
||||||
throw Exception(Exception::InvalidValueType, "Expecting type SmallInt");
|
throw Exception(Exception::InvalidValueType, "Expecting type SmallInt");
|
||||||
}
|
}
|
||||||
|
|
||||||
int Slice::compareString(char const* value, size_t length) const {
|
int Slice::compareString(StringRef const& value) const {
|
||||||
|
size_t const length = value.size();
|
||||||
ValueLength keyLength;
|
ValueLength keyLength;
|
||||||
char const* k = getString(keyLength);
|
char const* k = getString(keyLength);
|
||||||
size_t const compareLength =
|
size_t const compareLength =
|
||||||
(std::min)(static_cast<size_t>(keyLength), length);
|
(std::min)(static_cast<size_t>(keyLength), length);
|
||||||
int res = memcmp(k, value, compareLength);
|
int res = memcmp(k, value.data(), compareLength);
|
||||||
|
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
if (keyLength != length) {
|
if (keyLength != length) {
|
||||||
|
@ -949,12 +950,13 @@ int Slice::compareString(char const* value, size_t length) const {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Slice::compareStringUnchecked(char const* value, size_t length) const noexcept {
|
int Slice::compareStringUnchecked(StringRef const& value) const noexcept {
|
||||||
|
size_t const length = value.size();
|
||||||
ValueLength keyLength;
|
ValueLength keyLength;
|
||||||
char const* k = getStringUnchecked(keyLength);
|
char const* k = getStringUnchecked(keyLength);
|
||||||
size_t const compareLength =
|
size_t const compareLength =
|
||||||
(std::min)(static_cast<size_t>(keyLength), length);
|
(std::min)(static_cast<size_t>(keyLength), length);
|
||||||
int res = memcmp(k, value, compareLength);
|
int res = memcmp(k, value.data(), compareLength);
|
||||||
|
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
if (keyLength != length) {
|
if (keyLength != length) {
|
||||||
|
@ -964,7 +966,7 @@ int Slice::compareStringUnchecked(char const* value, size_t length) const noexce
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Slice::isEqualString(std::string const& attribute) const {
|
bool Slice::isEqualString(StringRef const& attribute) const {
|
||||||
ValueLength keyLength;
|
ValueLength keyLength;
|
||||||
char const* k = getString(keyLength);
|
char const* k = getString(keyLength);
|
||||||
if (static_cast<size_t>(keyLength) != attribute.size()) {
|
if (static_cast<size_t>(keyLength) != attribute.size()) {
|
||||||
|
@ -973,7 +975,7 @@ bool Slice::isEqualString(std::string const& attribute) const {
|
||||||
return (memcmp(k, attribute.data(), attribute.size()) == 0);
|
return (memcmp(k, attribute.data(), attribute.size()) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Slice::isEqualStringUnchecked(std::string const& attribute) const noexcept {
|
bool Slice::isEqualStringUnchecked(StringRef const& attribute) const noexcept {
|
||||||
ValueLength keyLength;
|
ValueLength keyLength;
|
||||||
char const* k = getStringUnchecked(keyLength);
|
char const* k = getStringUnchecked(keyLength);
|
||||||
if (static_cast<size_t>(keyLength) != attribute.size()) {
|
if (static_cast<size_t>(keyLength) != attribute.size()) {
|
||||||
|
@ -982,7 +984,7 @@ bool Slice::isEqualStringUnchecked(std::string const& attribute) const noexcept
|
||||||
return (memcmp(k, attribute.data(), attribute.size()) == 0);
|
return (memcmp(k, attribute.data(), attribute.size()) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Slice Slice::getFromCompactObject(std::string const& attribute) const {
|
Slice Slice::getFromCompactObject(StringRef const& attribute) const {
|
||||||
ObjectIterator it(*this);
|
ObjectIterator it(*this);
|
||||||
while (it.valid()) {
|
while (it.valid()) {
|
||||||
Slice key = it.key(false);
|
Slice key = it.key(false);
|
||||||
|
@ -1116,7 +1118,7 @@ ValueLength Slice::getNthOffsetFromCompact(ValueLength index) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
// perform a linear search for the specified attribute inside an Object
|
// perform a linear search for the specified attribute inside an Object
|
||||||
Slice Slice::searchObjectKeyLinear(std::string const& attribute,
|
Slice Slice::searchObjectKeyLinear(StringRef const& attribute,
|
||||||
ValueLength ieBase, ValueLength offsetSize,
|
ValueLength ieBase, ValueLength offsetSize,
|
||||||
ValueLength n) const {
|
ValueLength n) const {
|
||||||
bool const useTranslator = (Options::Defaults.attributeTranslator != nullptr);
|
bool const useTranslator = (Options::Defaults.attributeTranslator != nullptr);
|
||||||
|
@ -1128,7 +1130,7 @@ Slice Slice::searchObjectKeyLinear(std::string const& attribute,
|
||||||
if (key.isString()) {
|
if (key.isString()) {
|
||||||
if (!key.isEqualStringUnchecked(attribute)) {
|
if (!key.isEqualStringUnchecked(attribute)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (key.isSmallInt() || key.isUInt()) {
|
} else if (key.isSmallInt() || key.isUInt()) {
|
||||||
// translate key
|
// translate key
|
||||||
if (!useTranslator) {
|
if (!useTranslator) {
|
||||||
|
@ -1153,7 +1155,7 @@ Slice Slice::searchObjectKeyLinear(std::string const& attribute,
|
||||||
|
|
||||||
// perform a binary search for the specified attribute inside an Object
|
// perform a binary search for the specified attribute inside an Object
|
||||||
template<ValueLength offsetSize>
|
template<ValueLength offsetSize>
|
||||||
Slice Slice::searchObjectKeyBinary(std::string const& attribute,
|
Slice Slice::searchObjectKeyBinary(StringRef const& attribute,
|
||||||
ValueLength ieBase,
|
ValueLength ieBase,
|
||||||
ValueLength n) const {
|
ValueLength n) const {
|
||||||
bool const useTranslator = (Options::Defaults.attributeTranslator != nullptr);
|
bool const useTranslator = (Options::Defaults.attributeTranslator != nullptr);
|
||||||
|
@ -1205,10 +1207,10 @@ Slice Slice::searchObjectKeyBinary(std::string const& attribute,
|
||||||
}
|
}
|
||||||
|
|
||||||
// template instanciations for searchObjectKeyBinary
|
// template instanciations for searchObjectKeyBinary
|
||||||
template Slice Slice::searchObjectKeyBinary<1>(std::string const& attribute, ValueLength ieBase, ValueLength n) const;
|
template Slice Slice::searchObjectKeyBinary<1>(StringRef const& attribute, ValueLength ieBase, ValueLength n) const;
|
||||||
template Slice Slice::searchObjectKeyBinary<2>(std::string const& attribute, ValueLength ieBase, ValueLength n) const;
|
template Slice Slice::searchObjectKeyBinary<2>(StringRef const& attribute, ValueLength ieBase, ValueLength n) const;
|
||||||
template Slice Slice::searchObjectKeyBinary<4>(std::string const& attribute, ValueLength ieBase, ValueLength n) const;
|
template Slice Slice::searchObjectKeyBinary<4>(StringRef const& attribute, ValueLength ieBase, ValueLength n) const;
|
||||||
template Slice Slice::searchObjectKeyBinary<8>(std::string const& attribute, ValueLength ieBase, ValueLength n) const;
|
template Slice Slice::searchObjectKeyBinary<8>(StringRef const& attribute, ValueLength ieBase, ValueLength n) const;
|
||||||
|
|
||||||
SliceScope::SliceScope() : _allocations() {}
|
SliceScope::SliceScope() : _allocations() {}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Library to build up VPack documents.
|
||||||
|
///
|
||||||
|
/// DISCLAIMER
|
||||||
|
///
|
||||||
|
/// Copyright 2015 ArangoDB 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 Max Neunhoeffer
|
||||||
|
/// @author Jan Steemann
|
||||||
|
/// @author Copyright 2015, ArangoDB GmbH, Cologne, Germany
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "velocypack/StringRef.h"
|
||||||
|
#include "velocypack/Slice.h"
|
||||||
|
|
||||||
|
using namespace arangodb::velocypack;
|
||||||
|
|
||||||
|
StringRef::StringRef(arangodb::velocypack::Slice const& slice) {
|
||||||
|
VELOCYPACK_ASSERT(slice.isString());
|
||||||
|
arangodb::velocypack::ValueLength l;
|
||||||
|
_data = slice.getString(l);
|
||||||
|
_length = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief create a StringRef from a VPack slice of type String
|
||||||
|
StringRef& StringRef::operator=(arangodb::velocypack::Slice const& slice) {
|
||||||
|
arangodb::velocypack::ValueLength l;
|
||||||
|
_data = slice.getString(l);
|
||||||
|
_length = l;
|
||||||
|
return *this;
|
||||||
|
}
|
|
@ -274,7 +274,7 @@ std::string ActiveFailoverJob::findBestFollower() {
|
||||||
if (!resp.isArray() || resp.length() == 0) {
|
if (!resp.isArray() || resp.length() == 0) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
VPackSlice obj = resp.at(0).get({ Job::agencyPrefix, "AsyncReplication"});
|
VPackSlice obj = resp.at(0).get<std::string>({ Job::agencyPrefix, std::string("AsyncReplication") });
|
||||||
for (VPackObjectIterator::ObjectPair pair : VPackObjectIterator(obj)) {
|
for (VPackObjectIterator::ObjectPair pair : VPackObjectIterator(obj)) {
|
||||||
std::string srvUUID = pair.key.copyString();
|
std::string srvUUID = pair.key.copyString();
|
||||||
bool isAvailable = std::find(healthy.begin(), healthy.end(), srvUUID) != healthy.end();
|
bool isAvailable = std::find(healthy.begin(), healthy.end(), srvUUID) != healthy.end();
|
||||||
|
|
|
@ -124,6 +124,14 @@ struct AqlValueHintUInt {
|
||||||
uint64_t const value;
|
uint64_t const value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AqlValueHintEmptyArray {
|
||||||
|
constexpr AqlValueHintEmptyArray() noexcept {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AqlValueHintEmptyObject {
|
||||||
|
constexpr AqlValueHintEmptyObject() noexcept {}
|
||||||
|
};
|
||||||
|
|
||||||
struct AqlValue final {
|
struct AqlValue final {
|
||||||
friend struct std::hash<arangodb::aql::AqlValue>;
|
friend struct std::hash<arangodb::aql::AqlValue>;
|
||||||
friend struct std::equal_to<arangodb::aql::AqlValue>;
|
friend struct std::equal_to<arangodb::aql::AqlValue>;
|
||||||
|
@ -330,6 +338,16 @@ struct AqlValue final {
|
||||||
// construct from std::string
|
// construct from std::string
|
||||||
explicit AqlValue(std::string const& value) : AqlValue(value.c_str(), value.size()) {}
|
explicit AqlValue(std::string const& value) : AqlValue(value.c_str(), value.size()) {}
|
||||||
|
|
||||||
|
explicit AqlValue(AqlValueHintEmptyArray const&) noexcept {
|
||||||
|
_data.internal[0] = 0x01; // empty array in VPack
|
||||||
|
setType(AqlValueType::VPACK_INLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit AqlValue(AqlValueHintEmptyObject const&) noexcept {
|
||||||
|
_data.internal[0] = 0x0a; // empty object in VPack
|
||||||
|
setType(AqlValueType::VPACK_INLINE);
|
||||||
|
}
|
||||||
|
|
||||||
// construct from Buffer, potentially taking over its ownership
|
// construct from Buffer, potentially taking over its ownership
|
||||||
// (by adjusting the boolean passed)
|
// (by adjusting the boolean passed)
|
||||||
AqlValue(arangodb::velocypack::Buffer<uint8_t>* buffer, bool& shouldDelete) {
|
AqlValue(arangodb::velocypack::Buffer<uint8_t>* buffer, bool& shouldDelete) {
|
||||||
|
|
|
@ -588,7 +588,7 @@ AqlValue Expression::executeSimpleExpressionArray(
|
||||||
size_t const n = node->numMembers();
|
size_t const n = node->numMembers();
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction::BuilderLeaser builder(trx);
|
transaction::BuilderLeaser builder(trx);
|
||||||
|
@ -621,7 +621,7 @@ AqlValue Expression::executeSimpleExpressionObject(
|
||||||
size_t const n = node->numMembers();
|
size_t const n = node->numMembers();
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyObjectSlice());
|
return AqlValue(AqlValueHintEmptyObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
// unordered map to make object keys unique afterwards
|
// unordered map to make object keys unique afterwards
|
||||||
|
@ -1398,7 +1398,7 @@ AqlValue Expression::executeSimpleExpressionExpansion(
|
||||||
|
|
||||||
if (offset < 0 || count <= 0) {
|
if (offset < 0 || count <= 0) {
|
||||||
// no items to return... can already stop here
|
// no items to return... can already stop here
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILTER
|
// FILTER
|
||||||
|
@ -1412,7 +1412,7 @@ AqlValue Expression::executeSimpleExpressionExpansion(
|
||||||
filterNode = nullptr;
|
filterNode = nullptr;
|
||||||
} else {
|
} else {
|
||||||
// filter expression is always false
|
// filter expression is always false
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1431,7 +1431,7 @@ AqlValue Expression::executeSimpleExpressionExpansion(
|
||||||
|
|
||||||
if (!a.isArray()) {
|
if (!a.isArray()) {
|
||||||
TRI_ASSERT(!mustDestroy);
|
TRI_ASSERT(!mustDestroy);
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
VPackBuilder builder;
|
VPackBuilder builder;
|
||||||
|
@ -1473,7 +1473,7 @@ AqlValue Expression::executeSimpleExpressionExpansion(
|
||||||
|
|
||||||
if (!a.isArray()) {
|
if (!a.isArray()) {
|
||||||
TRI_ASSERT(!mustDestroy);
|
TRI_ASSERT(!mustDestroy);
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
mustDestroy = localMustDestroy; // maybe we need to destroy...
|
mustDestroy = localMustDestroy; // maybe we need to destroy...
|
||||||
|
|
|
@ -1207,7 +1207,7 @@ AqlValue mergeParameters(ExpressionContext* expressionContext,
|
||||||
size_t const n = parameters.size();
|
size_t const n = parameters.size();
|
||||||
|
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyObjectSlice());
|
return AqlValue(AqlValueHintEmptyObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
// use the first argument as the preliminary result
|
// use the first argument as the preliminary result
|
||||||
|
@ -1749,7 +1749,7 @@ AqlValue Functions::ToArray(ExpressionContext*,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.isNull(true)) {
|
if (value.isNull(true)) {
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction::BuilderLeaser builder(trx);
|
transaction::BuilderLeaser builder(trx);
|
||||||
|
@ -2915,7 +2915,7 @@ AqlValue Functions::Split(ExpressionContext* expressionContext,
|
||||||
return AqlValue(AqlValueHintNull());
|
return AqlValue(AqlValueHintNull());
|
||||||
}
|
}
|
||||||
if (limitNumber == 0) {
|
if (limitNumber == 0) {
|
||||||
return AqlValue(VPackSlice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3119,7 +3119,7 @@ AqlValue Functions::RegexSplit(ExpressionContext* expressionContext,
|
||||||
return AqlValue(AqlValueHintNull());
|
return AqlValue(AqlValueHintNull());
|
||||||
}
|
}
|
||||||
if (limitNumber == 0) {
|
if (limitNumber == 0) {
|
||||||
return AqlValue(VPackSlice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4109,7 +4109,7 @@ AqlValue Functions::Attributes(ExpressionContext* expressionContext,
|
||||||
|
|
||||||
TRI_ASSERT(value.isObject());
|
TRI_ASSERT(value.isObject());
|
||||||
if (value.length() == 0) {
|
if (value.length() == 0) {
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
AqlValueMaterializer materializer(trx);
|
AqlValueMaterializer materializer(trx);
|
||||||
|
@ -4173,7 +4173,7 @@ AqlValue Functions::Values(ExpressionContext* expressionContext,
|
||||||
|
|
||||||
TRI_ASSERT(value.isObject());
|
TRI_ASSERT(value.isObject());
|
||||||
if (value.length() == 0) {
|
if (value.length() == 0) {
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
AqlValueMaterializer materializer(trx);
|
AqlValueMaterializer materializer(trx);
|
||||||
|
@ -6426,7 +6426,7 @@ AqlValue Functions::RemoveValue(ExpressionContext* expressionContext,
|
||||||
AqlValue list = ExtractFunctionParameterValue(parameters, 0);
|
AqlValue list = ExtractFunctionParameterValue(parameters, 0);
|
||||||
|
|
||||||
if (list.isNull(true)) {
|
if (list.isNull(true)) {
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!list.isArray()) {
|
if (!list.isArray()) {
|
||||||
|
@ -6487,7 +6487,7 @@ AqlValue Functions::RemoveValues(ExpressionContext* expressionContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list.isNull(true)) {
|
if (list.isNull(true)) {
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!list.isArray() || !values.isArray()) {
|
if (!list.isArray() || !values.isArray()) {
|
||||||
|
@ -6522,7 +6522,7 @@ AqlValue Functions::RemoveNth(ExpressionContext* expressionContext,
|
||||||
AqlValue list = ExtractFunctionParameterValue(parameters, 0);
|
AqlValue list = ExtractFunctionParameterValue(parameters, 0);
|
||||||
|
|
||||||
if (list.isNull(true)) {
|
if (list.isNull(true)) {
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!list.isArray()) {
|
if (!list.isArray()) {
|
||||||
|
@ -7061,7 +7061,7 @@ AqlValue Functions::PregelResult(ExpressionContext* expressionContext,
|
||||||
pregel::PregelFeature* feature = pregel::PregelFeature::instance();
|
pregel::PregelFeature* feature = pregel::PregelFeature::instance();
|
||||||
if (!feature) {
|
if (!feature) {
|
||||||
::registerWarning(expressionContext, AFN, TRI_ERROR_FAILED);
|
::registerWarning(expressionContext, AFN, TRI_ERROR_FAILED);
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto buffer = std::make_unique<VPackBuffer<uint8_t>>();
|
auto buffer = std::make_unique<VPackBuffer<uint8_t>>();
|
||||||
|
@ -7070,7 +7070,7 @@ AqlValue Functions::PregelResult(ExpressionContext* expressionContext,
|
||||||
std::shared_ptr<pregel::Conductor> c = feature->conductor(execNr);
|
std::shared_ptr<pregel::Conductor> c = feature->conductor(execNr);
|
||||||
if (!c) {
|
if (!c) {
|
||||||
::registerWarning(expressionContext, AFN, TRI_ERROR_HTTP_NOT_FOUND);
|
::registerWarning(expressionContext, AFN, TRI_ERROR_HTTP_NOT_FOUND);
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
c->collectAQLResults(builder);
|
c->collectAQLResults(builder);
|
||||||
|
|
||||||
|
@ -7078,13 +7078,13 @@ AqlValue Functions::PregelResult(ExpressionContext* expressionContext,
|
||||||
std::shared_ptr<pregel::IWorker> worker = feature->worker(execNr);
|
std::shared_ptr<pregel::IWorker> worker = feature->worker(execNr);
|
||||||
if (!worker) {
|
if (!worker) {
|
||||||
::registerWarning(expressionContext, AFN, TRI_ERROR_HTTP_NOT_FOUND);
|
::registerWarning(expressionContext, AFN, TRI_ERROR_HTTP_NOT_FOUND);
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
worker->aqlResult(builder);
|
worker->aqlResult(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (builder.isEmpty()) {
|
if (builder.isEmpty()) {
|
||||||
return AqlValue(arangodb::velocypack::Slice::emptyArraySlice());
|
return AqlValue(AqlValueHintEmptyArray());
|
||||||
}
|
}
|
||||||
TRI_ASSERT(builder.slice().isArray());
|
TRI_ASSERT(builder.slice().isArray());
|
||||||
|
|
||||||
|
|
|
@ -2232,7 +2232,7 @@ Result ClusterInfo::setViewPropertiesCoordinator(
|
||||||
return { TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND };
|
return { TRI_ERROR_ARANGO_DATA_SOURCE_NOT_FOUND };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const view = res.slice()[0].get(
|
auto const view = res.slice()[0].get<std::string>(
|
||||||
{ AgencyCommManager::path(), "Plan", "Views", databaseName, viewID }
|
{ AgencyCommManager::path(), "Plan", "Views", databaseName, viewID }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -602,14 +602,14 @@ void HeartbeatThread::runSingleServer() {
|
||||||
VPackSlice agentPool = response.get(".agency");
|
VPackSlice agentPool = response.get(".agency");
|
||||||
updateAgentPool(agentPool);
|
updateAgentPool(agentPool);
|
||||||
|
|
||||||
VPackSlice shutdownSlice = response.get({AgencyCommManager::path(), "Shutdown"});
|
VPackSlice shutdownSlice = response.get<std::string>({AgencyCommManager::path(), "Shutdown"});
|
||||||
if (shutdownSlice.isBool() && shutdownSlice.getBool()) {
|
if (shutdownSlice.isBool() && shutdownSlice.getBool()) {
|
||||||
ApplicationServer::server->beginShutdown();
|
ApplicationServer::server->beginShutdown();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// performing failover checks
|
// performing failover checks
|
||||||
VPackSlice async = response.get({AgencyCommManager::path(), "Plan", "AsyncReplication"});
|
VPackSlice async = response.get<std::string>({AgencyCommManager::path(), "Plan", "AsyncReplication"});
|
||||||
if (!async.isObject()) {
|
if (!async.isObject()) {
|
||||||
LOG_TOPIC(WARN, Logger::HEARTBEAT)
|
LOG_TOPIC(WARN, Logger::HEARTBEAT)
|
||||||
<< "Heartbeat: Could not read async-replication metadata from agency!";
|
<< "Heartbeat: Could not read async-replication metadata from agency!";
|
||||||
|
|
|
@ -91,7 +91,7 @@ arangodb::Result Databases::info(TRI_vocbase_t* vocbase, VPackBuilder& result) {
|
||||||
return Result(commRes.errorCode(), commRes.errorMessage());
|
return Result(commRes.errorCode(), commRes.errorMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
VPackSlice value = commRes.slice()[0].get(
|
VPackSlice value = commRes.slice()[0].get<std::string>(
|
||||||
{AgencyCommManager::path(), "Plan", "Databases", vocbase->name()});
|
{AgencyCommManager::path(), "Plan", "Databases", vocbase->name()});
|
||||||
if (value.isObject() && value.hasKey("name")) {
|
if (value.isObject() && value.hasKey("name")) {
|
||||||
VPackValueLength l = 0;
|
VPackValueLength l = 0;
|
||||||
|
|
|
@ -102,7 +102,7 @@ void* LanguageFeature::prepareIcu(std::string const& binaryPath,
|
||||||
"'; please make sure it is available; "
|
"'; please make sure it is available; "
|
||||||
"the variable ICU_DATA='";
|
"the variable ICU_DATA='";
|
||||||
std::string icupath;
|
std::string icupath;
|
||||||
if ( TRI_GETENV("ICU_DATA", icupath)) {
|
if (TRI_GETENV("ICU_DATA", icupath)) {
|
||||||
msg += icupath;
|
msg += icupath;
|
||||||
}
|
}
|
||||||
msg += "' should point to the directory containing '" + fn + "'";
|
msg += "' should point to the directory containing '" + fn + "'";
|
||||||
|
|
|
@ -42,7 +42,7 @@ class StringRef {
|
||||||
constexpr StringRef() : _data(""), _length(0) {}
|
constexpr StringRef() : _data(""), _length(0) {}
|
||||||
|
|
||||||
/// @brief create a StringRef from an std::string
|
/// @brief create a StringRef from an std::string
|
||||||
explicit StringRef(std::string const& str) : _data(str.c_str()), _length(str.size()) {}
|
explicit StringRef(std::string const& str) noexcept : _data(str.data()), _length(str.size()) {}
|
||||||
|
|
||||||
/// @brief create a StringRef from a null-terminated C string
|
/// @brief create a StringRef from a null-terminated C string
|
||||||
explicit StringRef(char const* data) : _data(data), _length(strlen(data)) {}
|
explicit StringRef(char const* data) : _data(data), _length(strlen(data)) {}
|
||||||
|
|
|
@ -75,6 +75,7 @@ set(LIB_ARANGO_VPACK
|
||||||
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Options.cpp
|
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Options.cpp
|
||||||
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Parser.cpp
|
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Parser.cpp
|
||||||
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Slice.cpp
|
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Slice.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/StringRef.cpp
|
||||||
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Utf8Helper.cpp
|
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Utf8Helper.cpp
|
||||||
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/ValueType.cpp
|
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/ValueType.cpp
|
||||||
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Validator.cpp
|
${PROJECT_SOURCE_DIR}/3rdParty/velocypack/src/Validator.cpp
|
||||||
|
|
|
@ -261,7 +261,7 @@ std::unique_ptr<arangodb::aql::ExecutionPlan> planFromQuery(
|
||||||
|
|
||||||
uint64_t getCurrentPlanVersion() {
|
uint64_t getCurrentPlanVersion() {
|
||||||
auto const result = arangodb::AgencyComm().getValues("Plan");
|
auto const result = arangodb::AgencyComm().getValues("Plan");
|
||||||
auto const planVersionSlice = result.slice()[0].get(
|
auto const planVersionSlice = result.slice()[0].get<std::string>(
|
||||||
{ arangodb::AgencyCommManager::path(), "Plan", "Version" }
|
{ arangodb::AgencyCommManager::path(), "Plan", "Version" }
|
||||||
);
|
);
|
||||||
return planVersionSlice.getNumber<uint64_t>();
|
return planVersionSlice.getNumber<uint64_t>();
|
||||||
|
@ -574,4 +574,4 @@ void assertFilterParseFail(
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// --SECTION-- END-OF-FILE
|
// --SECTION-- END-OF-FILE
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
Loading…
Reference in New Issue