mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of ssh://github.com/ArangoDB/ArangoDB into devel
This commit is contained in:
commit
16769c59b4
|
@ -133,10 +133,13 @@ class Dumper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleUnsupportedType(Slice const*) {
|
void handleUnsupportedType(Slice const* slice) {
|
||||||
if (options->unsupportedTypeBehavior == Options::NullifyUnsupportedType) {
|
if (options->unsupportedTypeBehavior == Options::NullifyUnsupportedType) {
|
||||||
_sink->append("null", 4);
|
_sink->append("null", 4);
|
||||||
return;
|
return;
|
||||||
|
} else if (options->unsupportedTypeBehavior == Options::ConvertUnsupportedType) {
|
||||||
|
_sink->append(std::string("\"(non-representable type ") + slice->typeName() + ")\"");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw Exception(Exception::NoJsonEquivalent);
|
throw Exception(Exception::NoJsonEquivalent);
|
||||||
|
|
|
@ -62,6 +62,7 @@ struct CustomTypeHandler {
|
||||||
struct Options {
|
struct Options {
|
||||||
enum UnsupportedTypeBehavior {
|
enum UnsupportedTypeBehavior {
|
||||||
NullifyUnsupportedType,
|
NullifyUnsupportedType,
|
||||||
|
ConvertUnsupportedType,
|
||||||
FailOnUnsupportedType
|
FailOnUnsupportedType
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,9 @@ class Slice {
|
||||||
|
|
||||||
// creates a slice of type None
|
// creates a slice of type None
|
||||||
static Slice noneSlice() { return Slice("\x00"); }
|
static Slice noneSlice() { return Slice("\x00"); }
|
||||||
|
|
||||||
|
// creates a slice of type Illegal
|
||||||
|
static Slice illegalSlice() { return Slice("\x17"); }
|
||||||
|
|
||||||
// creates a slice of type Null
|
// creates a slice of type Null
|
||||||
static Slice nullSlice() { return Slice("\x18"); }
|
static Slice nullSlice() { return Slice("\x18"); }
|
||||||
|
@ -114,12 +117,12 @@ class Slice {
|
||||||
// No destructor, does not take part in memory management,
|
// No destructor, does not take part in memory management,
|
||||||
|
|
||||||
// get the type for the slice
|
// get the type for the slice
|
||||||
inline ValueType type() const { return TypeMap[head()]; }
|
inline ValueType type() const throw() { return TypeMap[head()]; }
|
||||||
|
|
||||||
char const* typeName() const { return valueTypeName(type()); }
|
char const* typeName() const { return valueTypeName(type()); }
|
||||||
|
|
||||||
// pointer to the head byte
|
// pointer to the head byte
|
||||||
uint8_t const* start() const { return _start; }
|
uint8_t const* start() const throw() { return _start; }
|
||||||
|
|
||||||
// Set new memory position
|
// Set new memory position
|
||||||
void set(uint8_t const* s) { _start = s; }
|
void set(uint8_t const* s) { _start = s; }
|
||||||
|
@ -131,7 +134,7 @@ class Slice {
|
||||||
}
|
}
|
||||||
|
|
||||||
// value of the head byte
|
// value of the head byte
|
||||||
inline uint8_t head() const { return *_start; }
|
inline uint8_t head() const throw() { return *_start; }
|
||||||
|
|
||||||
// hashes the binary representation of a value
|
// hashes the binary representation of a value
|
||||||
inline uint64_t hash(uint64_t seed = 0xdeadbeef) const {
|
inline uint64_t hash(uint64_t seed = 0xdeadbeef) const {
|
||||||
|
@ -144,76 +147,79 @@ class Slice {
|
||||||
uint64_t normalizedHash(uint64_t seed = 0xdeadbeef) const;
|
uint64_t normalizedHash(uint64_t seed = 0xdeadbeef) const;
|
||||||
|
|
||||||
// check if slice is of the specified type
|
// check if slice is of the specified type
|
||||||
inline bool isType(ValueType t) const { return type() == t; }
|
inline bool isType(ValueType t) const throw() { return TypeMap[*_start] == t; }
|
||||||
|
|
||||||
// check if slice is a None object
|
// check if slice is a None object
|
||||||
bool isNone() const { return isType(ValueType::None); }
|
bool isNone() const throw() { return isType(ValueType::None); }
|
||||||
|
|
||||||
|
// check if slice is an Illegal object
|
||||||
|
bool isIllegal() const throw() { return isType(ValueType::Illegal); }
|
||||||
|
|
||||||
// check if slice is a Null object
|
// check if slice is a Null object
|
||||||
bool isNull() const { return isType(ValueType::Null); }
|
bool isNull() const throw() { return isType(ValueType::Null); }
|
||||||
|
|
||||||
// check if slice is a Bool object
|
// check if slice is a Bool object
|
||||||
bool isBool() const { return isType(ValueType::Bool); }
|
bool isBool() const throw() { return isType(ValueType::Bool); }
|
||||||
|
|
||||||
// check if slice is a Bool object - this is an alias for isBool()
|
// check if slice is a Bool object - this is an alias for isBool()
|
||||||
bool isBoolean() const { return isBool(); }
|
bool isBoolean() const throw() { return isBool(); }
|
||||||
|
|
||||||
// check if slice is the Boolean value true
|
// check if slice is the Boolean value true
|
||||||
bool isTrue() const { return head() == 0x1a; }
|
bool isTrue() const throw() { return head() == 0x1a; }
|
||||||
|
|
||||||
// check if slice is the Boolean value false
|
// check if slice is the Boolean value false
|
||||||
bool isFalse() const { return head() == 0x19; }
|
bool isFalse() const throw() { return head() == 0x19; }
|
||||||
|
|
||||||
// check if slice is an Array object
|
// check if slice is an Array object
|
||||||
bool isArray() const { return isType(ValueType::Array); }
|
bool isArray() const throw() { return isType(ValueType::Array); }
|
||||||
|
|
||||||
// check if slice is an Object object
|
// check if slice is an Object object
|
||||||
bool isObject() const { return isType(ValueType::Object); }
|
bool isObject() const throw() { return isType(ValueType::Object); }
|
||||||
|
|
||||||
// check if slice is a Double object
|
// check if slice is a Double object
|
||||||
bool isDouble() const { return isType(ValueType::Double); }
|
bool isDouble() const throw() { return isType(ValueType::Double); }
|
||||||
|
|
||||||
// check if slice is a UTCDate object
|
// check if slice is a UTCDate object
|
||||||
bool isUTCDate() const { return isType(ValueType::UTCDate); }
|
bool isUTCDate() const throw() { return isType(ValueType::UTCDate); }
|
||||||
|
|
||||||
// check if slice is an External object
|
// check if slice is an External object
|
||||||
bool isExternal() const { return isType(ValueType::External); }
|
bool isExternal() const throw() { return isType(ValueType::External); }
|
||||||
|
|
||||||
// check if slice is a MinKey object
|
// check if slice is a MinKey object
|
||||||
bool isMinKey() const { return isType(ValueType::MinKey); }
|
bool isMinKey() const throw() { return isType(ValueType::MinKey); }
|
||||||
|
|
||||||
// check if slice is a MaxKey object
|
// check if slice is a MaxKey object
|
||||||
bool isMaxKey() const { return isType(ValueType::MaxKey); }
|
bool isMaxKey() const throw() { return isType(ValueType::MaxKey); }
|
||||||
|
|
||||||
// check if slice is an Int object
|
// check if slice is an Int object
|
||||||
bool isInt() const { return isType(ValueType::Int); }
|
bool isInt() const throw() { return isType(ValueType::Int); }
|
||||||
|
|
||||||
// check if slice is a UInt object
|
// check if slice is a UInt object
|
||||||
bool isUInt() const { return isType(ValueType::UInt); }
|
bool isUInt() const throw() { return isType(ValueType::UInt); }
|
||||||
|
|
||||||
// check if slice is a SmallInt object
|
// check if slice is a SmallInt object
|
||||||
bool isSmallInt() const { return isType(ValueType::SmallInt); }
|
bool isSmallInt() const throw() { return isType(ValueType::SmallInt); }
|
||||||
|
|
||||||
// check if slice is a String object
|
// check if slice is a String object
|
||||||
bool isString() const { return isType(ValueType::String); }
|
bool isString() const throw() { return isType(ValueType::String); }
|
||||||
|
|
||||||
// check if slice is a Binary object
|
// check if slice is a Binary object
|
||||||
bool isBinary() const { return isType(ValueType::Binary); }
|
bool isBinary() const throw() { return isType(ValueType::Binary); }
|
||||||
|
|
||||||
// check if slice is a BCD
|
// check if slice is a BCD
|
||||||
bool isBCD() const { return isType(ValueType::BCD); }
|
bool isBCD() const throw() { return isType(ValueType::BCD); }
|
||||||
|
|
||||||
// check if slice is a Custom type
|
// check if slice is a Custom type
|
||||||
bool isCustom() const { return isType(ValueType::Custom); }
|
bool isCustom() const throw() { return isType(ValueType::Custom); }
|
||||||
|
|
||||||
// check if a slice is any number type
|
// check if a slice is any number type
|
||||||
bool isInteger() const {
|
bool isInteger() const throw() {
|
||||||
return isType(ValueType::Int) || isType(ValueType::UInt) ||
|
return isType(ValueType::Int) || isType(ValueType::UInt) ||
|
||||||
isType(ValueType::SmallInt);
|
isType(ValueType::SmallInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if slice is any Number-type object
|
// check if slice is any Number-type object
|
||||||
bool isNumber() const { return isInteger() || isDouble(); }
|
bool isNumber() const throw() { return isInteger() || isDouble(); }
|
||||||
|
|
||||||
bool isSorted() const {
|
bool isSorted() const {
|
||||||
auto const h = head();
|
auto const h = head();
|
||||||
|
@ -599,6 +605,7 @@ class Slice {
|
||||||
ValueLength byteSize() const {
|
ValueLength byteSize() const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case ValueType::None:
|
case ValueType::None:
|
||||||
|
case ValueType::Illegal:
|
||||||
case ValueType::Null:
|
case ValueType::Null:
|
||||||
case ValueType::Bool:
|
case ValueType::Bool:
|
||||||
case ValueType::MinKey:
|
case ValueType::MinKey:
|
||||||
|
@ -736,6 +743,9 @@ class Slice {
|
||||||
std::string hexType() const;
|
std::string hexType() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// translates an integer key into a string, without checks
|
||||||
|
Slice translateUnchecked() const;
|
||||||
|
|
||||||
Slice getFromCompactObject(std::string const& attribute) const;
|
Slice getFromCompactObject(std::string const& attribute) const;
|
||||||
|
|
||||||
ValueLength findDataOffset(uint8_t head) const {
|
ValueLength findDataOffset(uint8_t head) const {
|
||||||
|
|
|
@ -35,8 +35,9 @@ namespace arangodb {
|
||||||
namespace velocypack {
|
namespace velocypack {
|
||||||
|
|
||||||
enum class ValueType {
|
enum class ValueType {
|
||||||
None, // not yet initialized
|
None, // not yet initialized
|
||||||
Null, // JSON null
|
Illegal, // illegal value
|
||||||
|
Null, // JSON null
|
||||||
Bool,
|
Bool,
|
||||||
Array,
|
Array,
|
||||||
Object,
|
Object,
|
||||||
|
|
|
@ -650,6 +650,11 @@ uint8_t* Builder::set(Value const& item) {
|
||||||
_pos += v;
|
_pos += v;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ValueType::Illegal: {
|
||||||
|
reserveSpace(1);
|
||||||
|
_start[_pos++] = 0x17;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ValueType::MinKey: {
|
case ValueType::MinKey: {
|
||||||
reserveSpace(1);
|
reserveSpace(1);
|
||||||
_start[_pos++] = 0x1e;
|
_start[_pos++] = 0x1e;
|
||||||
|
|
|
@ -396,6 +396,7 @@ void Dumper::dumpValue(Slice const* slice, Slice const* base) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ValueType::Illegal:
|
||||||
case ValueType::MinKey:
|
case ValueType::MinKey:
|
||||||
case ValueType::MaxKey: {
|
case ValueType::MaxKey: {
|
||||||
handleUnsupportedType(slice);
|
handleUnsupportedType(slice);
|
||||||
|
|
|
@ -53,7 +53,7 @@ VT const Slice::TypeMap[256] = {
|
||||||
/* 0x10 */ VT::Object, /* 0x11 */ VT::Object,
|
/* 0x10 */ VT::Object, /* 0x11 */ VT::Object,
|
||||||
/* 0x12 */ VT::Object, /* 0x13 */ VT::Array,
|
/* 0x12 */ VT::Object, /* 0x13 */ VT::Array,
|
||||||
/* 0x14 */ VT::Object, /* 0x15 */ VT::None,
|
/* 0x14 */ VT::Object, /* 0x15 */ VT::None,
|
||||||
/* 0x16 */ VT::None, /* 0x17 */ VT::None,
|
/* 0x16 */ VT::None, /* 0x17 */ VT::Illegal,
|
||||||
/* 0x18 */ VT::Null, /* 0x19 */ VT::Bool,
|
/* 0x18 */ VT::Null, /* 0x19 */ VT::Bool,
|
||||||
/* 0x1a */ VT::Bool, /* 0x1b */ VT::Double,
|
/* 0x1a */ VT::Bool, /* 0x1b */ VT::Double,
|
||||||
/* 0x1c */ VT::UTCDate, /* 0x1d */ VT::External,
|
/* 0x1c */ VT::UTCDate, /* 0x1d */ VT::External,
|
||||||
|
@ -231,12 +231,19 @@ Slice Slice::translate() const {
|
||||||
throw Exception(Exception::InvalidValueType,
|
throw Exception(Exception::InvalidValueType,
|
||||||
"Cannot translate key of this type");
|
"Cannot translate key of this type");
|
||||||
}
|
}
|
||||||
uint64_t id = getUInt();
|
|
||||||
if (attributeTranslator == nullptr) {
|
if (attributeTranslator == nullptr) {
|
||||||
throw Exception(Exception::NeedAttributeTranslator);
|
throw Exception(Exception::NeedAttributeTranslator);
|
||||||
}
|
}
|
||||||
|
return translateUnchecked();
|
||||||
|
}
|
||||||
|
|
||||||
return Slice(attributeTranslator->translate(id));
|
// translates an integer key into a string, without checks
|
||||||
|
Slice Slice::translateUnchecked() const {
|
||||||
|
uint8_t const* result = attributeTranslator->translate(getUInt());
|
||||||
|
if (result == nullptr) {
|
||||||
|
return Slice();
|
||||||
|
}
|
||||||
|
return Slice(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if two Slices are equal on the binary level
|
// check if two Slices are equal on the binary level
|
||||||
|
@ -581,7 +588,10 @@ Slice Slice::makeKey() const {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
if (isSmallInt() || isUInt()) {
|
if (isSmallInt() || isUInt()) {
|
||||||
return translate();
|
if (attributeTranslator == nullptr) {
|
||||||
|
throw Exception(Exception::NeedAttributeTranslator);
|
||||||
|
}
|
||||||
|
return translateUnchecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw Exception(Exception::InvalidValueType,
|
throw Exception(Exception::InvalidValueType,
|
||||||
|
@ -615,6 +625,8 @@ ValueLength Slice::getNthOffsetFromCompact(ValueLength index) const {
|
||||||
Slice Slice::searchObjectKeyLinear(std::string const& attribute,
|
Slice Slice::searchObjectKeyLinear(std::string const& attribute,
|
||||||
ValueLength ieBase, ValueLength offsetSize,
|
ValueLength ieBase, ValueLength offsetSize,
|
||||||
ValueLength n) const {
|
ValueLength n) const {
|
||||||
|
bool const useTranslator = (attributeTranslator != nullptr);
|
||||||
|
|
||||||
for (ValueLength index = 0; index < n; ++index) {
|
for (ValueLength index = 0; index < n; ++index) {
|
||||||
ValueLength offset = ieBase + index * offsetSize;
|
ValueLength offset = ieBase + index * offsetSize;
|
||||||
Slice key(_start + readInteger<ValueLength>(_start + offset, offsetSize));
|
Slice key(_start + readInteger<ValueLength>(_start + offset, offsetSize));
|
||||||
|
@ -625,7 +637,11 @@ Slice Slice::searchObjectKeyLinear(std::string const& attribute,
|
||||||
}
|
}
|
||||||
} else if (key.isSmallInt() || key.isUInt()) {
|
} else if (key.isSmallInt() || key.isUInt()) {
|
||||||
// translate key
|
// translate key
|
||||||
if (!key.translate().isEqualString(attribute)) {
|
if (!useTranslator) {
|
||||||
|
// no attribute translator
|
||||||
|
throw Exception(Exception::NeedAttributeTranslator);
|
||||||
|
}
|
||||||
|
if (!key.translateUnchecked().isEqualString(attribute)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -645,6 +661,7 @@ Slice Slice::searchObjectKeyLinear(std::string const& attribute,
|
||||||
Slice Slice::searchObjectKeyBinary(std::string const& attribute,
|
Slice Slice::searchObjectKeyBinary(std::string const& attribute,
|
||||||
ValueLength ieBase, ValueLength offsetSize,
|
ValueLength ieBase, ValueLength offsetSize,
|
||||||
ValueLength n) const {
|
ValueLength n) const {
|
||||||
|
bool const useTranslator = (attributeTranslator != nullptr);
|
||||||
VELOCYPACK_ASSERT(n > 0);
|
VELOCYPACK_ASSERT(n > 0);
|
||||||
|
|
||||||
ValueLength l = 0;
|
ValueLength l = 0;
|
||||||
|
@ -662,7 +679,11 @@ Slice Slice::searchObjectKeyBinary(std::string const& attribute,
|
||||||
res = key.compareString(attribute);
|
res = key.compareString(attribute);
|
||||||
} else if (key.isSmallInt() || key.isUInt()) {
|
} else if (key.isSmallInt() || key.isUInt()) {
|
||||||
// translate key
|
// translate key
|
||||||
res = key.translate().compareString(attribute);
|
if (!useTranslator) {
|
||||||
|
// no attribute translator
|
||||||
|
throw Exception(Exception::NeedAttributeTranslator);
|
||||||
|
}
|
||||||
|
res = key.translateUnchecked().compareString(attribute);
|
||||||
} else {
|
} else {
|
||||||
// invalid key
|
// invalid key
|
||||||
return Slice();
|
return Slice();
|
||||||
|
|
|
@ -34,6 +34,8 @@ char const* arangodb::velocypack::valueTypeName(ValueType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ValueType::None:
|
case ValueType::None:
|
||||||
return "none";
|
return "none";
|
||||||
|
case ValueType::Illegal:
|
||||||
|
return "illegal";
|
||||||
case ValueType::Null:
|
case ValueType::Null:
|
||||||
return "null";
|
return "null";
|
||||||
case ValueType::Bool:
|
case ValueType::Bool:
|
||||||
|
|
|
@ -170,6 +170,8 @@ the sort parameter.
|
||||||
v2.8.8 (????-??-??)
|
v2.8.8 (????-??-??)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* fixed issue #1805: Query: internal error (location: arangod/Aql/AqlValue.cpp:182). Please report this error to arangodb.com (while executing)
|
||||||
|
|
||||||
* allow specifying collection name prefixes for `_from` and `_to` in arangoimp:
|
* allow specifying collection name prefixes for `_from` and `_to` in arangoimp:
|
||||||
|
|
||||||
To avoid specifying complete document ids (consisting of collection names and document
|
To avoid specifying complete document ids (consisting of collection names and document
|
||||||
|
|
|
@ -220,6 +220,7 @@ bool Agent::recvAppendEntriesRPC (term_t term, id_t leaderId, index_t prevIndex,
|
||||||
<< " entries to state machine.";
|
<< " entries to state machine.";
|
||||||
/* bool success = */
|
/* bool success = */
|
||||||
_state.log (queries, term, leaderId, prevIndex, prevTerm);
|
_state.log (queries, term, leaderId, prevIndex, prevTerm);
|
||||||
|
// _constituent.vote();
|
||||||
} else {
|
} else {
|
||||||
// heart-beat
|
// heart-beat
|
||||||
}
|
}
|
||||||
|
@ -370,7 +371,7 @@ void Agent::run() {
|
||||||
while (!this->isStopping() && size() > 1) { // need only to run in multi-host
|
while (!this->isStopping() && size() > 1) { // need only to run in multi-host
|
||||||
|
|
||||||
if (leading())
|
if (leading())
|
||||||
_cv.wait(250000); // Only if leading
|
_cv.wait(500000); // Only if leading
|
||||||
else
|
else
|
||||||
_cv.wait(); // Just sit there doing nothing
|
_cv.wait(); // Just sit there doing nothing
|
||||||
|
|
||||||
|
|
|
@ -107,24 +107,31 @@ duration_t Constituent::sleepFor (double min_t, double max_t) {
|
||||||
|
|
||||||
// Get my term
|
// Get my term
|
||||||
term_t Constituent::term() const {
|
term_t Constituent::term() const {
|
||||||
|
MUTEX_LOCKER (guard, _castLock);
|
||||||
return _term;
|
return _term;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update my term
|
// Update my term
|
||||||
void Constituent::term(term_t t) {
|
void Constituent::term(term_t t) {
|
||||||
|
|
||||||
if (_term != t) {
|
term_t tmp;
|
||||||
|
|
||||||
|
{
|
||||||
|
MUTEX_LOCKER (guard, _castLock);
|
||||||
|
tmp = _term;
|
||||||
_term = t;
|
_term = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp != t) {
|
||||||
|
|
||||||
LOG_TOPIC(INFO, Logger::AGENCY) << "Updating term to " << t;
|
LOG_TOPIC(INFO, Logger::AGENCY) << "Updating term to " << t;
|
||||||
|
|
||||||
Builder body;
|
Builder body;
|
||||||
body.add(VPackValue(VPackValueType::Object));
|
body.add(VPackValue(VPackValueType::Object));
|
||||||
std::ostringstream i_str;
|
std::ostringstream i_str;
|
||||||
i_str << std::setw(20) << std::setfill('0') << _term;
|
i_str << std::setw(20) << std::setfill('0') << t;
|
||||||
body.add("_key", Value(i_str.str()));
|
body.add("_key", Value(i_str.str()));
|
||||||
body.add("term", Value(_term));
|
body.add("term", Value(t));
|
||||||
body.add("voted_for", Value((uint32_t)_voted_for));
|
body.add("voted_for", Value((uint32_t)_voted_for));
|
||||||
body.close();
|
body.close();
|
||||||
|
|
||||||
|
@ -153,21 +160,24 @@ void Constituent::term(term_t t) {
|
||||||
|
|
||||||
/// @brief My role
|
/// @brief My role
|
||||||
role_t Constituent::role () const {
|
role_t Constituent::role () const {
|
||||||
|
MUTEX_LOCKER (guard, _castLock);
|
||||||
return _role;
|
return _role;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Become follower in term
|
/// @brief Become follower in term
|
||||||
void Constituent::follow (term_t t) {
|
void Constituent::follow (term_t t) {
|
||||||
|
MUTEX_LOCKER(guard, _castLock);
|
||||||
if (_role != FOLLOWER) {
|
if (_role != FOLLOWER) {
|
||||||
LOG_TOPIC(INFO, Logger::AGENCY)
|
LOG_TOPIC(INFO, Logger::AGENCY)
|
||||||
<< "Role change: Converted to follower in term " << t;
|
<< "Role change: Converting to follower in term " << t;
|
||||||
}
|
}
|
||||||
this->term(t);
|
_term = t;
|
||||||
_role = FOLLOWER;
|
_role = FOLLOWER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Become leader
|
/// @brief Become leader
|
||||||
void Constituent::lead () {
|
void Constituent::lead () {
|
||||||
|
MUTEX_LOCKER(guard, _castLock);
|
||||||
if (_role != LEADER) {
|
if (_role != LEADER) {
|
||||||
LOG_TOPIC(INFO, Logger::AGENCY)
|
LOG_TOPIC(INFO, Logger::AGENCY)
|
||||||
<< "Role change: Converted to leader in term " << _term ;
|
<< "Role change: Converted to leader in term " << _term ;
|
||||||
|
@ -179,6 +189,7 @@ void Constituent::lead () {
|
||||||
|
|
||||||
/// @brief Become follower
|
/// @brief Become follower
|
||||||
void Constituent::candidate () {
|
void Constituent::candidate () {
|
||||||
|
MUTEX_LOCKER(guard, _castLock);
|
||||||
if (_role != CANDIDATE)
|
if (_role != CANDIDATE)
|
||||||
LOG_TOPIC(INFO, Logger::AGENCY)
|
LOG_TOPIC(INFO, Logger::AGENCY)
|
||||||
<< "Role change: Converted to candidate in term " << _term ;
|
<< "Role change: Converted to candidate in term " << _term ;
|
||||||
|
@ -187,16 +198,19 @@ void Constituent::candidate () {
|
||||||
|
|
||||||
/// @brief Leading?
|
/// @brief Leading?
|
||||||
bool Constituent::leading () const {
|
bool Constituent::leading () const {
|
||||||
|
MUTEX_LOCKER(guard, _castLock);
|
||||||
return _role == LEADER;
|
return _role == LEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Following?
|
/// @brief Following?
|
||||||
bool Constituent::following () const {
|
bool Constituent::following () const {
|
||||||
|
MUTEX_LOCKER(guard, _castLock);
|
||||||
return _role == FOLLOWER;
|
return _role == FOLLOWER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Runnig as candidate?
|
/// @brief Runnig as candidate?
|
||||||
bool Constituent::running () const {
|
bool Constituent::running () const {
|
||||||
|
MUTEX_LOCKER(guard, _castLock);
|
||||||
return _role == CANDIDATE;
|
return _role == CANDIDATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,14 +270,25 @@ size_t Constituent::notifyAll () {
|
||||||
/// @brief Vote
|
/// @brief Vote
|
||||||
bool Constituent::vote (
|
bool Constituent::vote (
|
||||||
term_t term, id_t id, index_t prevLogIndex, term_t prevLogTerm) {
|
term_t term, id_t id, index_t prevLogIndex, term_t prevLogTerm) {
|
||||||
if (term > _term || (_term==term&&_leader_id==id)) {
|
term_t t = 0;
|
||||||
|
id_t lid = 0;
|
||||||
|
{
|
||||||
|
MUTEX_LOCKER(guard,_castLock);
|
||||||
|
t = _term;
|
||||||
|
lid = _leader_id;
|
||||||
|
}
|
||||||
|
if (term > t || (t == term && lid == id)) {
|
||||||
this->term(term);
|
this->term(term);
|
||||||
_cast = true; // Note that I voted this time around.
|
{
|
||||||
_voted_for = id; // The guy I voted for I assume leader.
|
MUTEX_LOCKER(guard,_castLock);
|
||||||
_leader_id = id;
|
_cast = true; // Note that I voted this time around.
|
||||||
if (_role>FOLLOWER)
|
_voted_for = id; // The guy I voted for I assume leader.
|
||||||
|
_leader_id = id;
|
||||||
|
}
|
||||||
|
if (_role>FOLLOWER) {
|
||||||
follow (_term);
|
follow (_term);
|
||||||
_agent->persist(_term,_voted_for);
|
}
|
||||||
|
_agent->persist(term,id);
|
||||||
_cv.signal();
|
_cv.signal();
|
||||||
return true;
|
return true;
|
||||||
} else { // Myself running or leading
|
} else { // Myself running or leading
|
||||||
|
@ -271,17 +296,6 @@ bool Constituent::vote (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Implementation of a gossip protocol
|
|
||||||
void Constituent::gossip (const constituency_t& constituency) {
|
|
||||||
// TODO: Replace lame notification by gossip protocol
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Implementation of a gossip protocol
|
|
||||||
const constituency_t& Constituent::gossip () {
|
|
||||||
// TODO: Replace lame notification by gossip protocol
|
|
||||||
return _constituency;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Call to election
|
/// @brief Call to election
|
||||||
void Constituent::callElection() {
|
void Constituent::callElection() {
|
||||||
|
|
||||||
|
@ -417,8 +431,11 @@ void Constituent::run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always start off as follower
|
// Always start off as follower
|
||||||
while (!this->isStopping() && size() > 1) {
|
while (!this->isStopping() && size() > 1) {
|
||||||
|
|
||||||
if (_role == FOLLOWER) {
|
if (_role == FOLLOWER) {
|
||||||
|
bool cast = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
MUTEX_LOCKER(guard, _castLock);
|
MUTEX_LOCKER(guard, _castLock);
|
||||||
_cast = false; // New round set not cast vote
|
_cast = false; // New round set not cast vote
|
||||||
|
@ -426,13 +443,15 @@ void Constituent::run() {
|
||||||
|
|
||||||
dist_t dis(config().min_ping, config().max_ping);
|
dist_t dis(config().min_ping, config().max_ping);
|
||||||
long rand_wait = static_cast<long>(dis(_gen)*1000000.0);
|
long rand_wait = static_cast<long>(dis(_gen)*1000000.0);
|
||||||
bool timedout = _cv.wait(rand_wait);
|
/*bool timedout =*/ _cv.wait(rand_wait);
|
||||||
|
|
||||||
{
|
{
|
||||||
MUTEX_LOCKER(guard, _castLock);
|
MUTEX_LOCKER(guard, _castLock);
|
||||||
if (!_cast) {
|
cast = _cast;
|
||||||
candidate(); // Next round, we are running
|
}
|
||||||
}
|
|
||||||
|
if (!cast) {
|
||||||
|
candidate(); // Next round, we are running
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
callElection(); // Run for office
|
callElection(); // Run for office
|
||||||
|
|
|
@ -68,12 +68,6 @@ public:
|
||||||
/// @brief Get current role
|
/// @brief Get current role
|
||||||
role_t role() const;
|
role_t role() const;
|
||||||
|
|
||||||
/// @brief Gossip protocol: listen
|
|
||||||
void gossip(constituency_t const&);
|
|
||||||
|
|
||||||
/// @brief Gossip protocol: talk
|
|
||||||
const constituency_t& gossip();
|
|
||||||
|
|
||||||
/// @brief Are we leading?
|
/// @brief Are we leading?
|
||||||
bool leading() const;
|
bool leading() const;
|
||||||
|
|
||||||
|
@ -158,7 +152,7 @@ private:
|
||||||
id_t _voted_for;
|
id_t _voted_for;
|
||||||
|
|
||||||
arangodb::basics::ConditionVariable _cv; // agency callbacks
|
arangodb::basics::ConditionVariable _cv; // agency callbacks
|
||||||
arangodb::Mutex _castLock;
|
mutable arangodb::Mutex _castLock;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ void RestAgencyHandler::redirectRequest(id_t leaderId) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::string url = Endpoint::uriForm(
|
std::string url = Endpoint::uriForm(
|
||||||
_agent->config().end_points.at(leaderId));
|
_agent->config().end_points.at(leaderId)) + _request->requestPath();
|
||||||
createResponse(GeneralResponse::ResponseCode::TEMPORARY_REDIRECT);
|
createResponse(GeneralResponse::ResponseCode::TEMPORARY_REDIRECT);
|
||||||
static std::string const location = "location";
|
static std::string const location = "location";
|
||||||
_response->setHeaderNC(location, url);
|
_response->setHeaderNC(location, url);
|
|
@ -29,7 +29,7 @@ void SanityCheck::run() {
|
||||||
while (!this->isStopping()) {
|
while (!this->isStopping()) {
|
||||||
|
|
||||||
if (_agent->leading()) {
|
if (_agent->leading()) {
|
||||||
timedout = _cv.wait(1000000);
|
timedout = _cv.wait(250000);//quarter second
|
||||||
} else {
|
} else {
|
||||||
_cv.wait();
|
_cv.wait();
|
||||||
}
|
}
|
||||||
|
|
|
@ -909,6 +909,15 @@ void Store::dumpToBuilder (Builder& builder) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t Store::matchPath (std::vector<std::string> const& pv) const {
|
||||||
|
// Node* cur(this);
|
||||||
|
/* for (size_t i = 0; i < pv.size(); ++i) {
|
||||||
|
if (cur.find(pv.at(i))) {
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Start thread
|
// Start thread
|
||||||
bool Store::start () {
|
bool Store::start () {
|
||||||
Thread::start();
|
Thread::start();
|
||||||
|
|
|
@ -230,6 +230,9 @@ public:
|
||||||
/// @brief Notify observers
|
/// @brief Notify observers
|
||||||
void notifyObservers () const;
|
void notifyObservers () const;
|
||||||
|
|
||||||
|
/// @brief See how far the path matches anything in store
|
||||||
|
size_t matchPath (std::vector<std::string> const& pv) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// @brief Read individual entry specified in slice into builder
|
/// @brief Read individual entry specified in slice into builder
|
||||||
bool read (arangodb::velocypack::Slice const&,
|
bool read (arangodb::velocypack::Slice const&,
|
||||||
|
|
|
@ -96,7 +96,11 @@ QueryResult Parser::parse(bool withDetails) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// end main scope
|
// end main scope
|
||||||
scopes->endCurrent();
|
TRI_ASSERT(scopes->numActive() > 0);
|
||||||
|
|
||||||
|
while (scopes->numActive() > 0) {
|
||||||
|
scopes->endCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
TRI_ASSERT(scopes->numActive() == 0);
|
TRI_ASSERT(scopes->numActive() == 0);
|
||||||
|
|
||||||
|
|
|
@ -880,7 +880,6 @@ QueryResult Query::explain() {
|
||||||
enterState(FINALIZATION);
|
enterState(FINALIZATION);
|
||||||
|
|
||||||
QueryResult result(TRI_ERROR_NO_ERROR);
|
QueryResult result(TRI_ERROR_NO_ERROR);
|
||||||
QueryRegistry localRegistry;
|
|
||||||
|
|
||||||
if (allPlans()) {
|
if (allPlans()) {
|
||||||
result.result = std::make_shared<VPackBuilder>();
|
result.result = std::make_shared<VPackBuilder>();
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -58,6 +58,33 @@ void Aqlerror (YYLTYPE* locp,
|
||||||
parser->registerParseError(TRI_ERROR_QUERY_PARSE, message, locp->first_line, locp->first_column);
|
parser->registerParseError(TRI_ERROR_QUERY_PARSE, message, locp->first_line, locp->first_column);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief check if any of variables used into the INTO expression was
|
||||||
|
/// introduced by the COLLECT itself, in which case it would fail
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static Variable const* CheckIntoVariables(AstNode const* collectVars,
|
||||||
|
std::unordered_set<Variable const*> const& vars) {
|
||||||
|
if (collectVars == nullptr || collectVars->type != NODE_TYPE_ARRAY) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t const n = collectVars->numMembers();
|
||||||
|
for (size_t i = 0; i < n; ++i) {
|
||||||
|
auto member = collectVars->getMember(i);
|
||||||
|
|
||||||
|
if (member != nullptr) {
|
||||||
|
TRI_ASSERT(member->type == NODE_TYPE_ASSIGN);
|
||||||
|
auto v = static_cast<Variable*>(member->getMember(0)->getData());
|
||||||
|
if (vars.find(v) != vars.end()) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief register variables in the scope
|
/// @brief register variables in the scope
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -544,6 +571,17 @@ collect_statement:
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($3 != nullptr && $3->type == NODE_TYPE_ARRAY) {
|
||||||
|
std::unordered_set<Variable const*> vars;
|
||||||
|
Ast::getReferencedVariables($3->getMember(1), vars);
|
||||||
|
|
||||||
|
Variable const* used = CheckIntoVariables($2, vars);
|
||||||
|
if (used != nullptr) {
|
||||||
|
std::string msg("use of COLLECT variable '" + used->name + "' IN INTO expression");
|
||||||
|
parser->registerParseError(TRI_ERROR_QUERY_PARSE, msg.c_str(), yylloc.first_line, yylloc.first_column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AstNode const* into = GetIntoVariable(parser, $3);
|
AstNode const* into = GetIntoVariable(parser, $3);
|
||||||
AstNode const* intoExpression = GetIntoExpression($3);
|
AstNode const* intoExpression = GetIntoExpression($3);
|
||||||
|
|
||||||
|
@ -563,6 +601,22 @@ collect_statement:
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($3 != nullptr && $3->type == NODE_TYPE_ARRAY) {
|
||||||
|
std::unordered_set<Variable const*> vars;
|
||||||
|
Ast::getReferencedVariables($3->getMember(1), vars);
|
||||||
|
|
||||||
|
Variable const* used = CheckIntoVariables($1, vars);
|
||||||
|
if (used != nullptr) {
|
||||||
|
std::string msg("use of COLLECT variable '" + used->name + "' IN INTO expression");
|
||||||
|
parser->registerParseError(TRI_ERROR_QUERY_PARSE, msg.c_str(), yylloc.first_line, yylloc.first_column);
|
||||||
|
}
|
||||||
|
used = CheckIntoVariables($2, vars);
|
||||||
|
if (used != nullptr) {
|
||||||
|
std::string msg("use of COLLECT variable '" + used->name + "' IN INTO expression");
|
||||||
|
parser->registerParseError(TRI_ERROR_QUERY_PARSE, msg.c_str(), yylloc.first_line, yylloc.first_column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// note all group variables
|
// note all group variables
|
||||||
std::unordered_set<Variable const*> groupVars;
|
std::unordered_set<Variable const*> groupVars;
|
||||||
size_t n = $1->numMembers();
|
size_t n = $1->numMembers();
|
||||||
|
@ -609,6 +663,17 @@ collect_statement:
|
||||||
RegisterAssignVariables(scopes, $1);
|
RegisterAssignVariables(scopes, $1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($2 != nullptr && $2->type == NODE_TYPE_ARRAY) {
|
||||||
|
std::unordered_set<Variable const*> vars;
|
||||||
|
Ast::getReferencedVariables($2->getMember(1), vars);
|
||||||
|
|
||||||
|
Variable const* used = CheckIntoVariables($1, vars);
|
||||||
|
if (used != nullptr) {
|
||||||
|
std::string msg("use of COLLECT variable '" + used->name + "' IN INTO expression");
|
||||||
|
parser->registerParseError(TRI_ERROR_QUERY_PARSE, msg.c_str(), yylloc.first_line, yylloc.first_column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AstNode const* into = GetIntoVariable(parser, $2);
|
AstNode const* into = GetIntoVariable(parser, $2);
|
||||||
AstNode const* intoExpression = GetIntoExpression($2);
|
AstNode const* intoExpression = GetIntoExpression($2);
|
||||||
|
|
||||||
|
@ -627,6 +692,17 @@ collect_statement:
|
||||||
$3 != nullptr) {
|
$3 != nullptr) {
|
||||||
parser->registerParseError(TRI_ERROR_QUERY_PARSE, "use of 'KEEP' without 'INTO'", yylloc.first_line, yylloc.first_column);
|
parser->registerParseError(TRI_ERROR_QUERY_PARSE, "use of 'KEEP' without 'INTO'", yylloc.first_line, yylloc.first_column);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($2 != nullptr && $2->type == NODE_TYPE_ARRAY) {
|
||||||
|
std::unordered_set<Variable const*> vars;
|
||||||
|
Ast::getReferencedVariables($2->getMember(1), vars);
|
||||||
|
|
||||||
|
Variable const* used = CheckIntoVariables($1, vars);
|
||||||
|
if (used != nullptr) {
|
||||||
|
std::string msg("use of COLLECT variable '" + used->name + "' IN INTO expression");
|
||||||
|
parser->registerParseError(TRI_ERROR_QUERY_PARSE, msg.c_str(), yylloc.first_line, yylloc.first_column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AstNode const* into = GetIntoVariable(parser, $2);
|
AstNode const* into = GetIntoVariable(parser, $2);
|
||||||
AstNode const* intoExpression = GetIntoExpression($2);
|
AstNode const* intoExpression = GetIntoExpression($2);
|
||||||
|
|
|
@ -73,6 +73,8 @@ add_executable(${BIN_ARANGOD}
|
||||||
Agency/ApplicationAgency.cpp
|
Agency/ApplicationAgency.cpp
|
||||||
Agency/Constituent.cpp
|
Agency/Constituent.cpp
|
||||||
Agency/SanityCheck.cpp
|
Agency/SanityCheck.cpp
|
||||||
|
Agency/RestAgencyHandler.cpp
|
||||||
|
Agency/RestAgencyPrivHandler.cpp
|
||||||
Agency/State.cpp
|
Agency/State.cpp
|
||||||
Agency/Store.cpp
|
Agency/Store.cpp
|
||||||
Agency/StoreCallback.cpp
|
Agency/StoreCallback.cpp
|
||||||
|
@ -190,8 +192,6 @@ add_executable(${BIN_ARANGOD}
|
||||||
Replication/InitialSyncer.cpp
|
Replication/InitialSyncer.cpp
|
||||||
Replication/Syncer.cpp
|
Replication/Syncer.cpp
|
||||||
RestHandler/RestAdminLogHandler.cpp
|
RestHandler/RestAdminLogHandler.cpp
|
||||||
RestHandler/RestAgencyHandler.cpp
|
|
||||||
RestHandler/RestAgencyPrivHandler.cpp
|
|
||||||
RestHandler/RestBaseHandler.cpp
|
RestHandler/RestBaseHandler.cpp
|
||||||
RestHandler/RestBatchHandler.cpp
|
RestHandler/RestBatchHandler.cpp
|
||||||
RestHandler/RestCursorHandler.cpp
|
RestHandler/RestCursorHandler.cpp
|
||||||
|
|
|
@ -35,6 +35,8 @@
|
||||||
#include "Actions/actions.h"
|
#include "Actions/actions.h"
|
||||||
#include "Agency/Agent.h"
|
#include "Agency/Agent.h"
|
||||||
#include "Agency/ApplicationAgency.h"
|
#include "Agency/ApplicationAgency.h"
|
||||||
|
#include "Agency/RestAgencyHandler.h"
|
||||||
|
#include "Agency/RestAgencyPrivHandler.h"
|
||||||
#include "ApplicationServer/ApplicationServer.h"
|
#include "ApplicationServer/ApplicationServer.h"
|
||||||
#include "Aql/Query.h"
|
#include "Aql/Query.h"
|
||||||
#include "Aql/QueryCache.h"
|
#include "Aql/QueryCache.h"
|
||||||
|
@ -65,8 +67,6 @@
|
||||||
#include "Rest/OperationMode.h"
|
#include "Rest/OperationMode.h"
|
||||||
#include "Rest/Version.h"
|
#include "Rest/Version.h"
|
||||||
#include "RestHandler/RestAdminLogHandler.h"
|
#include "RestHandler/RestAdminLogHandler.h"
|
||||||
#include "RestHandler/RestAgencyHandler.h"
|
|
||||||
#include "RestHandler/RestAgencyPrivHandler.h"
|
|
||||||
#include "RestHandler/RestBatchHandler.h"
|
#include "RestHandler/RestBatchHandler.h"
|
||||||
#include "RestHandler/RestCursorHandler.h"
|
#include "RestHandler/RestCursorHandler.h"
|
||||||
#include "RestHandler/RestDebugHandler.h"
|
#include "RestHandler/RestDebugHandler.h"
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
|
|
||||||
rerenderValues: function(data) {
|
rerenderValues: function(data) {
|
||||||
|
|
||||||
// TODO cache value state like graph data
|
//TODO cache value state like graph data
|
||||||
|
|
||||||
//Connections
|
//Connections
|
||||||
this.renderValue('#clusterConnections', Math.round(data.clientConnectionsCurrent));
|
this.renderValue('#clusterConnections', Math.round(data.clientConnectionsCurrent));
|
||||||
|
@ -160,12 +160,9 @@
|
||||||
var totalMem = data.physicalMemory;
|
var totalMem = data.physicalMemory;
|
||||||
var usedMem = data.residentSizeCurrent;
|
var usedMem = data.residentSizeCurrent;
|
||||||
this.renderValue('#clusterRam', [usedMem, totalMem]);
|
this.renderValue('#clusterRam', [usedMem, totalMem]);
|
||||||
|
|
||||||
//NODES
|
|
||||||
this.renderValue('#clusterNodes', this.statCollectCoord.size());
|
|
||||||
},
|
},
|
||||||
|
|
||||||
renderValue: function(id, value) {
|
renderValue: function(id, value, error) {
|
||||||
if (typeof value === 'number') {
|
if (typeof value === 'number') {
|
||||||
$(id).html(value);
|
$(id).html(value);
|
||||||
}
|
}
|
||||||
|
@ -175,11 +172,60 @@
|
||||||
var percent = 1 / (b/a) * 100;
|
var percent = 1 / (b/a) * 100;
|
||||||
$(id).html(percent.toFixed(1) + ' %');
|
$(id).html(percent.toFixed(1) + ' %');
|
||||||
}
|
}
|
||||||
|
else if (typeof value === 'string') {
|
||||||
|
$(id).html(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
$(id).addClass('negative');
|
||||||
|
$(id).removeClass('positive');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$(id).addClass('positive');
|
||||||
|
$(id).removeClass('negative');
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
updateValues: function() {
|
updateValues: function() {
|
||||||
this.renderValue('#clusterNodes', this.statCollectCoord.size());
|
var self = this;
|
||||||
this.renderValue('#clusterRam', [1024, 4096]);
|
|
||||||
|
this.coordinators.fetch({
|
||||||
|
success: function() {
|
||||||
|
self.renderNode(true);
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
self.renderNode(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//this.renderValue('#clusterRam', [1024, 4096]);
|
||||||
|
},
|
||||||
|
|
||||||
|
renderNode: function(connection) {
|
||||||
|
var ok = 0, error = 0;
|
||||||
|
|
||||||
|
if (connection) {
|
||||||
|
this.coordinators.each(function(value) {
|
||||||
|
if (value.toJSON().status === 'ok') {
|
||||||
|
ok++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
error++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error > 0) {
|
||||||
|
var total = error + ok;
|
||||||
|
this.renderValue('#clusterNodes', ok + '/' + total, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.renderValue('#clusterNodes', ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.renderValue('#clusterNodes', 'OFFLINE', true);
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
initValues: function() {
|
initValues: function() {
|
||||||
|
@ -446,7 +492,6 @@
|
||||||
|
|
||||||
var mergeHistory = function(data) {
|
var mergeHistory = function(data) {
|
||||||
|
|
||||||
|
|
||||||
var onetime = ['times'];
|
var onetime = ['times'];
|
||||||
var values = [
|
var values = [
|
||||||
'physicalMemory',
|
'physicalMemory',
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
initialize: function () {
|
initialize: function () {
|
||||||
//also server online check
|
//also server online check
|
||||||
var self = this;
|
var self = this;
|
||||||
window.setInterval(function(){
|
window.setInterval(function() {
|
||||||
self.getVersion();
|
self.getVersion();
|
||||||
}, 15000);
|
}, 15000);
|
||||||
self.getVersion();
|
self.getVersion();
|
||||||
|
@ -51,45 +51,51 @@
|
||||||
else {
|
else {
|
||||||
self.collection.fetch({
|
self.collection.fetch({
|
||||||
success: function() {
|
success: function() {
|
||||||
self.renderClusterState();
|
self.renderClusterState(true);
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
self.renderClusterState(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
renderClusterState: function() {
|
renderClusterState: function(connection) {
|
||||||
var ok = 0, error = 0;
|
var ok = 0, error = 0;
|
||||||
|
|
||||||
this.collection.each(function(value) {
|
if (connection) {
|
||||||
if (value.toJSON().status === 'ok') {
|
this.collection.each(function(value) {
|
||||||
ok++;
|
if (value.toJSON().status === 'ok') {
|
||||||
}
|
ok++;
|
||||||
else {
|
}
|
||||||
error++;
|
else {
|
||||||
}
|
error++;
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (error > 0) {
|
if (error > 0) {
|
||||||
$('#healthStatus').removeClass('positive');
|
$('#healthStatus').removeClass('positive');
|
||||||
$('#healthStatus').addClass('negative');
|
$('#healthStatus').addClass('negative');
|
||||||
if (error === 1) {
|
if (error === 1) {
|
||||||
$('.health-state').html(error + ' NODE ERROR');
|
$('.health-state').html(error + ' NODE ERROR');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('.health-state').html(error + ' NODES ERROR');
|
||||||
|
}
|
||||||
|
$('.health-icon').html('<i class="fa fa-exclamation-circle"></i>');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$('.health-state').html(error + ' NODES ERROR');
|
$('#healthStatus').removeClass('negative');
|
||||||
|
$('#healthStatus').addClass('positive');
|
||||||
|
$('.health-state').html('NODES OK');
|
||||||
|
$('.health-icon').html('<i class="fa fa-check-circle"></i>');
|
||||||
}
|
}
|
||||||
$('.health-icon').html('<i class="fa fa-exclamation-circle"></i>');
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$('#healthStatus').removeClass('negative');
|
$('#healthStatus').removeClass('positive');
|
||||||
$('#healthStatus').addClass('positive');
|
$('#healthStatus').addClass('negative');
|
||||||
if (ok === 1) {
|
$('.health-state').html(window.location.host + ' OFFLINE');
|
||||||
$('.health-state').html(ok + ' NODE OK');
|
$('.health-icon').html('<i class="fa fa-exclamation-circle"></i>');
|
||||||
}
|
|
||||||
else {
|
|
||||||
$('.health-state').html(ok + ' NODES OK');
|
|
||||||
}
|
|
||||||
$('.health-icon').html('<i class="fa fa-check-circle"></i>');
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -34,17 +34,16 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
breadcrumb: function(name) {
|
breadcrumb: function(name) {
|
||||||
console.log("yes");
|
|
||||||
$('#subNavigationBar .breadcrumb').html("Node: " + name);
|
$('#subNavigationBar .breadcrumb').html("Node: " + name);
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
console.log(1);
|
|
||||||
this.$el.html(this.template.render({coords: []}));
|
this.$el.html(this.template.render({coords: []}));
|
||||||
|
|
||||||
var callback = function() {
|
var callback = function() {
|
||||||
this.continueRender();
|
this.continueRender();
|
||||||
this.breadcrumb(this.coordname);
|
this.breadcrumb(this.coordname);
|
||||||
|
$(window).trigger('resize');
|
||||||
}.bind(this);
|
}.bind(this);
|
||||||
|
|
||||||
if (!this.initDone) {
|
if (!this.initDone) {
|
||||||
|
@ -58,6 +57,8 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
continueRender: function() {
|
continueRender: function() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
this.dashboards[this.coordinator.get('name')] = new window.DashboardView({
|
this.dashboards[this.coordinator.get('name')] = new window.DashboardView({
|
||||||
dygraphConfig: window.dygraphConfig,
|
dygraphConfig: window.dygraphConfig,
|
||||||
database: window.App.arangoDatabase,
|
database: window.App.arangoDatabase,
|
||||||
|
@ -69,6 +70,9 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.dashboards[this.coordinator.get('name')].render();
|
this.dashboards[this.coordinator.get('name')].render();
|
||||||
|
window.setTimeout(function() {
|
||||||
|
self.dashboards[self.coordinator.get('name')].resize();
|
||||||
|
}, 100);
|
||||||
},
|
},
|
||||||
|
|
||||||
waitForCoordinators: function(callback) {
|
waitForCoordinators: function(callback) {
|
||||||
|
|
|
@ -58,7 +58,6 @@
|
||||||
|
|
||||||
continueRender: function() {
|
continueRender: function() {
|
||||||
var coords = this.coordinators.toJSON();
|
var coords = this.coordinators.toJSON();
|
||||||
console.log(coords);
|
|
||||||
this.$el.html(this.template.render({
|
this.$el.html(this.template.render({
|
||||||
coords: coords
|
coords: coords
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -17,11 +17,21 @@
|
||||||
border: 1px solid $c-content-border;
|
border: 1px solid $c-content-border;
|
||||||
margin-left: -1px;
|
margin-left: -1px;
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
|
padding: {
|
||||||
|
bottom: 10px;
|
||||||
|
left: 20px;
|
||||||
|
right: 20px;
|
||||||
|
top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.nv-controlsWrap {
|
.nv-controlsWrap {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nv-legendWrap {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
height: 250px;
|
height: 250px;
|
||||||
margin-left: -17px;
|
margin-left: -17px;
|
||||||
|
@ -42,10 +52,19 @@
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
color: $c-positive;
|
color: $c-black;
|
||||||
font-size: 24pt;
|
font-size: 24pt;
|
||||||
line-height: 150px;
|
line-height: 150px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
&.positive {
|
||||||
|
color: $c-positive;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.negative {
|
||||||
|
color: $c-negative;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div:first-child {
|
div:first-child {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*jshint globalstrict:false, strict:false, maxlen: 500 */
|
/*jshint globalstrict:false, strict:false, maxlen: 500 */
|
||||||
/*global assertEqual, assertTrue, AQL_EXECUTE */
|
/*global assertEqual, assertTrue, fail, AQL_EXECUTE */
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief tests for COLLECT w/ INTO var = expr
|
/// @brief tests for COLLECT w/ INTO var = expr
|
||||||
|
@ -30,12 +30,23 @@
|
||||||
|
|
||||||
var jsunity = require("jsunity");
|
var jsunity = require("jsunity");
|
||||||
var db = require("@arangodb").db;
|
var db = require("@arangodb").db;
|
||||||
|
var internal = require("internal");
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief test suite
|
/// @brief test suite
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
function optimizerCollectExpressionTestSuite () {
|
function optimizerCollectExpressionTestSuite () {
|
||||||
|
var assertFailingQuery = function (query) {
|
||||||
|
try {
|
||||||
|
AQL_EXECUTE(query);
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
assertEqual(internal.errors.ERROR_QUERY_PARSE.code, err.errorNum);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var c;
|
var c;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -202,6 +213,15 @@ function optimizerCollectExpressionTestSuite () {
|
||||||
for (i = 0; i < 500; ++i) {
|
for (i = 0; i < 500; ++i) {
|
||||||
assertTrue(typeof results.json[1].ages[i] === 'number');
|
assertTrue(typeof results.json[1].ages[i] === 'number');
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test expression
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testIntoWithOutVariableUsedInAssignment : function () {
|
||||||
|
assertFailingQuery("FOR doc IN [{ age: 1, value: 1 }, { age: 1, value: 2 }, { age: 2, value: 1 }, { age: 2, value: 2 }] COLLECT v1 = doc.age, v2 = doc.value INTO g = v1 RETURN [v1,v2,g]");
|
||||||
|
assertFailingQuery("FOR doc IN [{ age: 1, value: 1 }, { age: 1, value: 2 }, { age: 2, value: 1 }, { age: 2, value: 2 }] COLLECT v1 = doc.age AGGREGATE v2 = MAX(doc.value) INTO g = v2 RETURN [v1,v2,g]");
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -44,49 +44,6 @@ using VelocyPackHelper = arangodb::basics::VelocyPackHelper;
|
||||||
static std::unique_ptr<VPackAttributeTranslator> Translator;
|
static std::unique_ptr<VPackAttributeTranslator> Translator;
|
||||||
static std::unique_ptr<VPackAttributeExcludeHandler> ExcludeHandler;
|
static std::unique_ptr<VPackAttributeExcludeHandler> ExcludeHandler;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief "constant" global object for NULL which can be shared by all
|
|
||||||
/// expressions but must never be freed
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static VPackBuilder NullBuilder;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief "constant" global object for TRUE which can be shared by all
|
|
||||||
/// expressions but must never be freed
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static VPackBuilder TrueBuilder;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief "constant" global object for FALSE which can be shared by all
|
|
||||||
/// expressions but must never be freed
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static VPackBuilder FalseBuilder;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief "constant" global object for empty ARRAYs which can be shared by all
|
|
||||||
/// expressions but must never be freed
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static VPackBuilder EmptyArrayBuilder;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief "constant" global object for empty OBJECTs which can be shared by all
|
|
||||||
/// expressions but must never be freed
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static VPackBuilder EmptyObjectBuilder;
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
/// @brief "constant" global object for illegal slices
|
|
||||||
/// Are used in Array Indexes to distinguish NULL and not existent.
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static VPackBuilder IllegalBuilder;
|
|
||||||
|
|
||||||
|
|
||||||
// attribute exclude handler for skipping over system attributes
|
// attribute exclude handler for skipping over system attributes
|
||||||
struct SystemAttributeExcludeHandler : public VPackAttributeExcludeHandler {
|
struct SystemAttributeExcludeHandler : public VPackAttributeExcludeHandler {
|
||||||
bool shouldExclude(VPackSlice const& key, int nesting) override final {
|
bool shouldExclude(VPackSlice const& key, int nesting) override final {
|
||||||
|
@ -122,73 +79,27 @@ void VelocyPackHelper::initialize() {
|
||||||
Translator.reset(new VPackAttributeTranslator);
|
Translator.reset(new VPackAttributeTranslator);
|
||||||
|
|
||||||
// these attribute names will be translated into short integer values
|
// these attribute names will be translated into short integer values
|
||||||
Translator->add("_key", 1);
|
Translator->add("_key", 1); // TRI_VOC_ATTRIBUTE_KEY
|
||||||
Translator->add("_rev", 2);
|
Translator->add("_rev", 2); // TRI_VOC_ATTRIBUTE_REV
|
||||||
Translator->add("_id", 3);
|
Translator->add("_id", 3); // TRI_VOC_ATTRIBUTE_ID
|
||||||
Translator->add("_from", 4);
|
Translator->add("_from", 4); // TRI_VOC_ATTRIBUTE_FROM
|
||||||
Translator->add("_to", 5);
|
Translator->add("_to", 5); // TRI_VOC_ATTRIBUTE_TO
|
||||||
|
|
||||||
Translator->seal();
|
Translator->seal();
|
||||||
|
|
||||||
// set the attribute translator in the global options
|
// set the attribute translator in the global options
|
||||||
VPackOptions::Defaults.attributeTranslator = Translator.get();
|
VPackOptions::Defaults.attributeTranslator = Translator.get();
|
||||||
VPackSlice::attributeTranslator = Translator.get();
|
VPackSlice::attributeTranslator = Translator.get();
|
||||||
|
// VPackOptions::Defaults.unsupportedTypeBehavior = VPackOptions::ConvertUnsupportedType;
|
||||||
|
|
||||||
// initialize exclude handler for system attributes
|
// initialize exclude handler for system attributes
|
||||||
ExcludeHandler.reset(new SystemAttributeExcludeHandler);
|
ExcludeHandler.reset(new SystemAttributeExcludeHandler);
|
||||||
|
|
||||||
// Null value
|
|
||||||
NullBuilder.add(VPackValue(VPackValueType::Null));
|
|
||||||
// True value
|
|
||||||
TrueBuilder.add(VPackValue(true));
|
|
||||||
// False value
|
|
||||||
FalseBuilder.add(VPackValue(false));
|
|
||||||
// Array value (empty)
|
|
||||||
EmptyArrayBuilder.openArray();
|
|
||||||
EmptyArrayBuilder.close();
|
|
||||||
// Object value (empty)
|
|
||||||
EmptyObjectBuilder.openObject();
|
|
||||||
EmptyObjectBuilder.close();
|
|
||||||
|
|
||||||
// Illegal value
|
|
||||||
IllegalBuilder.add(VPackValue(VPackValueType::MinKey));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VelocyPackHelper::disableAssemblerFunctions() {
|
void VelocyPackHelper::disableAssemblerFunctions() {
|
||||||
arangodb::velocypack::disableAssemblerFunctions();
|
arangodb::velocypack::disableAssemblerFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
arangodb::velocypack::Slice VelocyPackHelper::NullValue() {
|
|
||||||
return NullBuilder.slice();
|
|
||||||
}
|
|
||||||
|
|
||||||
arangodb::velocypack::Slice VelocyPackHelper::TrueValue() {
|
|
||||||
return TrueBuilder.slice();
|
|
||||||
}
|
|
||||||
|
|
||||||
arangodb::velocypack::Slice VelocyPackHelper::FalseValue() {
|
|
||||||
return FalseBuilder.slice();
|
|
||||||
}
|
|
||||||
|
|
||||||
arangodb::velocypack::Slice VelocyPackHelper::BooleanValue(bool value) {
|
|
||||||
if (value) {
|
|
||||||
return TrueBuilder.slice();
|
|
||||||
}
|
|
||||||
return FalseBuilder.slice();
|
|
||||||
}
|
|
||||||
|
|
||||||
arangodb::velocypack::Slice VelocyPackHelper::EmptyArrayValue() {
|
|
||||||
return EmptyArrayBuilder.slice();
|
|
||||||
}
|
|
||||||
|
|
||||||
arangodb::velocypack::Slice VelocyPackHelper::EmptyObjectValue() {
|
|
||||||
return EmptyObjectBuilder.slice();
|
|
||||||
}
|
|
||||||
|
|
||||||
arangodb::velocypack::Slice VelocyPackHelper::IllegalValue() {
|
|
||||||
return IllegalBuilder.slice();
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief return the (global) attribute exclude handler instance
|
/// @brief return the (global) attribute exclude handler instance
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -222,7 +133,9 @@ bool VelocyPackHelper::VPackEqual::operator()(VPackSlice const& lhs, VPackSlice
|
||||||
static int TypeWeight(VPackSlice const& slice) {
|
static int TypeWeight(VPackSlice const& slice) {
|
||||||
switch (slice.type()) {
|
switch (slice.type()) {
|
||||||
case VPackValueType::MinKey:
|
case VPackValueType::MinKey:
|
||||||
return -1;
|
return -99; // must be lowest
|
||||||
|
case VPackValueType::Illegal:
|
||||||
|
return -1;
|
||||||
case VPackValueType::None:
|
case VPackValueType::None:
|
||||||
case VPackValueType::Null:
|
case VPackValueType::Null:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -232,14 +145,19 @@ static int TypeWeight(VPackSlice const& slice) {
|
||||||
case VPackValueType::Int:
|
case VPackValueType::Int:
|
||||||
case VPackValueType::UInt:
|
case VPackValueType::UInt:
|
||||||
case VPackValueType::SmallInt:
|
case VPackValueType::SmallInt:
|
||||||
|
case VPackValueType::UTCDate:
|
||||||
|
case VPackValueType::BCD:
|
||||||
return 2;
|
return 2;
|
||||||
case VPackValueType::String:
|
case VPackValueType::String:
|
||||||
|
case VPackValueType::Binary:
|
||||||
case VPackValueType::Custom:
|
case VPackValueType::Custom:
|
||||||
// custom type is used for id
|
// custom type is used for _id (which is a string)
|
||||||
return 3;
|
return 3;
|
||||||
case VPackValueType::Array:
|
case VPackValueType::Array:
|
||||||
return 4;
|
return 4;
|
||||||
case VPackValueType::Object:
|
case VPackValueType::Object:
|
||||||
|
case VPackValueType::External:
|
||||||
|
// External type is used for documents
|
||||||
return 5;
|
return 5;
|
||||||
default:
|
default:
|
||||||
// All other values have equal weight
|
// All other values have equal weight
|
||||||
|
@ -247,6 +165,41 @@ static int TypeWeight(VPackSlice const& slice) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int VelocyPackHelper::compareNumberValues(VPackSlice const& lhs, VPackSlice const& rhs) {
|
||||||
|
VPackValueType const lType = lhs.type();
|
||||||
|
|
||||||
|
if (lType == rhs.type()) {
|
||||||
|
// both types are equal
|
||||||
|
if (lType == VPackValueType::Int || lType == VPackValueType::SmallInt) {
|
||||||
|
// use exact comparisons. no need to cast to double
|
||||||
|
int64_t l = lhs.getInt();
|
||||||
|
int64_t r = rhs.getInt();
|
||||||
|
if (l == r) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (l < r ? -1 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lType == VPackValueType::UInt) {
|
||||||
|
// use exact comparisons. no need to cast to double
|
||||||
|
uint64_t l = lhs.getUInt();
|
||||||
|
uint64_t r = rhs.getUInt();
|
||||||
|
if (l == r) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (l < r ? -1 : 1);
|
||||||
|
}
|
||||||
|
// fallthrough to double comparison
|
||||||
|
}
|
||||||
|
|
||||||
|
double left = lhs.getNumericValue<double>();
|
||||||
|
double right = rhs.getNumericValue<double>();
|
||||||
|
if (left == right) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (left < right ? -1 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief returns a boolean sub-element, or a default if it is does not exist
|
/// @brief returns a boolean sub-element, or a default if it is does not exist
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -504,8 +457,10 @@ int VelocyPackHelper::compare(VPackSlice const& lhs, VPackSlice const& rhs,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (lhs.type()) {
|
switch (lhs.type()) {
|
||||||
|
case VPackValueType::Illegal:
|
||||||
case VPackValueType::MinKey:
|
case VPackValueType::MinKey:
|
||||||
return 0; // illegal is illegal
|
case VPackValueType::MaxKey:
|
||||||
|
return 0;
|
||||||
case VPackValueType::None:
|
case VPackValueType::None:
|
||||||
case VPackValueType::Null:
|
case VPackValueType::Null:
|
||||||
return 0; // null == null;
|
return 0; // null == null;
|
||||||
|
@ -524,15 +479,7 @@ int VelocyPackHelper::compare(VPackSlice const& lhs, VPackSlice const& rhs,
|
||||||
case VPackValueType::Int:
|
case VPackValueType::Int:
|
||||||
case VPackValueType::UInt:
|
case VPackValueType::UInt:
|
||||||
case VPackValueType::SmallInt: {
|
case VPackValueType::SmallInt: {
|
||||||
double left = lhs.getNumericValue<double>();
|
return compareNumberValues(lhs, rhs);
|
||||||
double right = rhs.getNumericValue<double>();
|
|
||||||
if (left == right) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (left < right) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
case VPackValueType::Custom:
|
case VPackValueType::Custom:
|
||||||
case VPackValueType::String: {
|
case VPackValueType::String: {
|
||||||
|
@ -683,6 +630,7 @@ double VelocyPackHelper::toDouble(VPackSlice const& slice, bool& failed) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VPackValueType::Illegal:
|
||||||
case VPackValueType::Object:
|
case VPackValueType::Object:
|
||||||
case VPackValueType::UTCDate:
|
case VPackValueType::UTCDate:
|
||||||
case VPackValueType::External:
|
case VPackValueType::External:
|
||||||
|
@ -717,7 +665,7 @@ uint64_t VelocyPackHelper::hashByAttributes(
|
||||||
error = TRI_ERROR_CLUSTER_NOT_ALL_SHARDING_ATTRIBUTES_GIVEN;
|
error = TRI_ERROR_CLUSTER_NOT_ALL_SHARDING_ATTRIBUTES_GIVEN;
|
||||||
}
|
}
|
||||||
// Null is equal to None/not present
|
// Null is equal to None/not present
|
||||||
sub = NullBuilder.slice();
|
sub = VPackSlice::nullSlice();
|
||||||
}
|
}
|
||||||
hash = sub.normalizedHash(hash);
|
hash = sub.normalizedHash(hash);
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,6 +199,13 @@ class VelocyPackHelper {
|
||||||
|
|
||||||
static bool velocyPackToFile(char const*, VPackSlice const&, bool);
|
static bool velocyPackToFile(char const*, VPackSlice const&, bool);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Compares two VelocyPack number values
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static int compareNumberValues(arangodb::velocypack::Slice const& lhs,
|
||||||
|
arangodb::velocypack::Slice const& rhs);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Compares two VelocyPack slices
|
/// @brief Compares two VelocyPack slices
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -227,13 +234,41 @@ class VelocyPackHelper {
|
||||||
static uint64_t hashByAttributes(VPackSlice, std::vector<std::string> const&,
|
static uint64_t hashByAttributes(VPackSlice, std::vector<std::string> const&,
|
||||||
bool, int&, std::string const& key = "");
|
bool, int&, std::string const& key = "");
|
||||||
|
|
||||||
static arangodb::velocypack::Slice NullValue();
|
static inline arangodb::velocypack::Slice NullValue() {
|
||||||
static arangodb::velocypack::Slice TrueValue();
|
return arangodb::velocypack::Slice::nullSlice();
|
||||||
static arangodb::velocypack::Slice FalseValue();
|
}
|
||||||
static arangodb::velocypack::Slice BooleanValue(bool);
|
|
||||||
static arangodb::velocypack::Slice EmptyArrayValue();
|
static inline arangodb::velocypack::Slice TrueValue() {
|
||||||
static arangodb::velocypack::Slice EmptyObjectValue();
|
return arangodb::velocypack::Slice::trueSlice();
|
||||||
static arangodb::velocypack::Slice IllegalValue();
|
}
|
||||||
|
|
||||||
|
static inline arangodb::velocypack::Slice FalseValue() {
|
||||||
|
return arangodb::velocypack::Slice::falseSlice();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline arangodb::velocypack::Slice BooleanValue(bool value) {
|
||||||
|
if (value) {
|
||||||
|
return arangodb::velocypack::Slice::trueSlice();
|
||||||
|
}
|
||||||
|
return arangodb::velocypack::Slice::falseSlice();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline arangodb::velocypack::Slice EmptyArrayValue() {
|
||||||
|
return arangodb::velocypack::Slice::emptyArraySlice();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline arangodb::velocypack::Slice EmptyObjectValue() {
|
||||||
|
return arangodb::velocypack::Slice::emptyObjectSlice();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief "constant" global object for illegal slices
|
||||||
|
/// Are used in Array Indexes to distinguish NULL and not existent.
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static inline arangodb::velocypack::Slice IllegalValue() {
|
||||||
|
return arangodb::velocypack::Slice::illegalSlice();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue