mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'json_agency_comm' of https://github.com/arangodb/arangodb into json_agency_comm
This commit is contained in:
commit
7eed0ecc2f
|
@ -346,6 +346,38 @@ class Builder {
|
|||
// Add a subvalue into an array from a Value:
|
||||
uint8_t* add(Value const& sub);
|
||||
|
||||
// Add an External slice to an array
|
||||
uint8_t* addExternal(uint8_t const* sub) {
|
||||
if (options->disallowExternals) {
|
||||
// External values explicitly disallowed as a security
|
||||
// precaution
|
||||
throw Exception(Exception::BuilderExternalsDisallowed);
|
||||
}
|
||||
|
||||
bool haveReported = false;
|
||||
if (!_stack.empty()) {
|
||||
if (! _keyWritten) {
|
||||
reportAdd();
|
||||
haveReported = true;
|
||||
}
|
||||
}
|
||||
try {
|
||||
auto oldPos = _pos;
|
||||
reserveSpace(1 + sizeof(void*));
|
||||
// store pointer. this doesn't need to be portable
|
||||
_start[_pos++] = 0x1d;
|
||||
memcpy(_start + _pos, &sub, sizeof(void*));
|
||||
_pos += sizeof(void*);
|
||||
return _start + oldPos;
|
||||
} catch (...) {
|
||||
// clean up in case of an exception
|
||||
if (haveReported) {
|
||||
cleanupAdd();
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a slice to an array
|
||||
uint8_t* add(Slice const& sub);
|
||||
|
||||
|
|
|
@ -48,14 +48,7 @@ class ArrayIterator {
|
|||
throw Exception(Exception::InvalidValueType, "Expecting Array slice");
|
||||
}
|
||||
|
||||
if (_size > 0) {
|
||||
auto h = slice.head();
|
||||
if (h == 0x13) {
|
||||
_current = slice.at(0).start();
|
||||
} else if (allowRandomIteration) {
|
||||
_current = slice.begin() + slice.findDataOffset(h);
|
||||
}
|
||||
}
|
||||
reset(allowRandomIteration);
|
||||
}
|
||||
|
||||
ArrayIterator(ArrayIterator const& other)
|
||||
|
@ -139,6 +132,25 @@ class ArrayIterator {
|
|||
|
||||
inline bool isLast() const throw() { return (_position + 1 >= _size); }
|
||||
|
||||
inline void forward(ValueLength count) {
|
||||
if (_position + count >= _size) {
|
||||
// beyond end of data
|
||||
_current = nullptr;
|
||||
_position = _size;
|
||||
} else {
|
||||
auto h = _slice.head();
|
||||
if (h == 0x13) {
|
||||
while (count-- > 0) {
|
||||
_current += Slice(_current).byteSize();
|
||||
++_position;
|
||||
}
|
||||
} else {
|
||||
_position += count;
|
||||
_current = _slice.at(_position).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void reset(bool allowRandomIteration) {
|
||||
_position = 0;
|
||||
_current = nullptr;
|
||||
|
|
|
@ -145,6 +145,14 @@ struct AqlValue final {
|
|||
setType(AqlValueType::RANGE);
|
||||
}
|
||||
|
||||
/// @brief AqlValues can be copied and moved as required
|
||||
/// memory management is not performed via AqlValue destructor but via
|
||||
/// explicit calls to destroy()
|
||||
AqlValue(AqlValue const&) noexcept = default;
|
||||
AqlValue& operator=(AqlValue const&) noexcept = default;
|
||||
AqlValue(AqlValue&&) noexcept = default;
|
||||
AqlValue& operator=(AqlValue&&) noexcept = default;
|
||||
|
||||
~AqlValue() = default;
|
||||
|
||||
/// @brief whether or not the value must be destroyed
|
||||
|
@ -162,12 +170,12 @@ struct AqlValue final {
|
|||
}
|
||||
|
||||
/// @brief whether or not the value is a range
|
||||
bool isRange() const {
|
||||
inline bool isRange() const {
|
||||
return type() == RANGE;
|
||||
}
|
||||
|
||||
/// @brief whether or not the value is a docvec
|
||||
bool isDocvec() const {
|
||||
inline bool isDocvec() const {
|
||||
return type() == DOCVEC;
|
||||
}
|
||||
|
||||
|
|
|
@ -299,7 +299,7 @@ bool FilterBlock::hasMore() {
|
|||
// trigger an expensive fetching operation, even if later on only
|
||||
// a single document is needed due to a LIMIT...
|
||||
// However, how should we know this here?
|
||||
if (!getBlock(DefaultBatchSize, DefaultBatchSize)) {
|
||||
if (!getBlock(DefaultBatchSize(), DefaultBatchSize())) {
|
||||
_done = true;
|
||||
return false;
|
||||
}
|
||||
|
@ -393,8 +393,8 @@ int LimitBlock::getOrSkipSome(size_t atLeast, size_t atMost, bool skipping,
|
|||
if (_fullCount) {
|
||||
// if fullCount is set, we must fetch all elements from the
|
||||
// dependency. we'll use the default batch size for this
|
||||
atLeast = DefaultBatchSize;
|
||||
atMost = DefaultBatchSize;
|
||||
atLeast = DefaultBatchSize();
|
||||
atMost = DefaultBatchSize();
|
||||
|
||||
// suck out all data from the dependencies
|
||||
while (true) {
|
||||
|
|
|
@ -85,7 +85,7 @@ VPackBuilder BindParameters::StripCollectionNames(VPackSlice const& keys,
|
|||
TRI_ASSERT(keys.isArray());
|
||||
VPackBuilder result;
|
||||
result.openArray();
|
||||
for (auto const& element : VPackArrayIterator(keys)) {
|
||||
for (auto const& element : VPackArrayIterator(keys, false)) {
|
||||
if (element.isString()) {
|
||||
VPackValueLength l;
|
||||
char const* s = element.getString(l);
|
||||
|
|
|
@ -220,7 +220,7 @@ bool GatherBlock::hasMore() {
|
|||
for (size_t i = 0; i < _gatherBlockBuffer.size(); i++) {
|
||||
if (!_gatherBlockBuffer.at(i).empty()) {
|
||||
return true;
|
||||
} else if (getBlock(i, DefaultBatchSize, DefaultBatchSize)) {
|
||||
} else if (getBlock(i, DefaultBatchSize(), DefaultBatchSize())) {
|
||||
_gatherBlockPos.at(i) = std::make_pair(i, 0);
|
||||
return true;
|
||||
}
|
||||
|
@ -620,7 +620,7 @@ bool ScatterBlock::hasMoreForShard(std::string const& shardId) {
|
|||
// _buffer.at(i) we are sending to <clientId>
|
||||
|
||||
if (pos.first > _buffer.size()) {
|
||||
if (!ExecutionBlock::getBlock(DefaultBatchSize, DefaultBatchSize)) {
|
||||
if (!ExecutionBlock::getBlock(DefaultBatchSize(), DefaultBatchSize())) {
|
||||
_doneForClient.at(clientId) = true;
|
||||
return false;
|
||||
}
|
||||
|
@ -802,7 +802,7 @@ bool DistributeBlock::hasMoreForShard(std::string const& shardId) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!getBlockForClient(DefaultBatchSize, DefaultBatchSize, clientId)) {
|
||||
if (!getBlockForClient(DefaultBatchSize(), DefaultBatchSize(), clientId)) {
|
||||
_doneForClient.at(clientId) = true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -31,18 +31,14 @@
|
|||
|
||||
using namespace arangodb::aql;
|
||||
|
||||
using Json = arangodb::basics::Json;
|
||||
|
||||
EnumerateCollectionBlock::EnumerateCollectionBlock(
|
||||
ExecutionEngine* engine, EnumerateCollectionNode const* ep)
|
||||
: ExecutionBlock(engine, ep),
|
||||
_collection(ep->_collection),
|
||||
_scanner(nullptr),
|
||||
_documentsSize(0),
|
||||
_posInDocuments(0),
|
||||
_random(ep->_random),
|
||||
_iterator(arangodb::basics::VelocyPackHelper::EmptyArrayValue()),
|
||||
_mustStoreResult(true) {
|
||||
_scanner = new CollectionScanner(_trx, _collection->getName(), _random);
|
||||
_scanner = new CollectionScanner(_trx, _collection->getName(), ep->_random);
|
||||
}
|
||||
|
||||
EnumerateCollectionBlock::~EnumerateCollectionBlock() { delete _scanner; }
|
||||
|
@ -51,8 +47,7 @@ EnumerateCollectionBlock::~EnumerateCollectionBlock() { delete _scanner; }
|
|||
void EnumerateCollectionBlock::initializeDocuments() {
|
||||
_scanner->reset();
|
||||
_documents = VPackSlice();
|
||||
_documentsSize = 0;
|
||||
_posInDocuments = 0;
|
||||
_iterator = VPackArrayIterator(arangodb::basics::VelocyPackHelper::EmptyArrayValue());
|
||||
}
|
||||
|
||||
/// @brief skip instead of fetching
|
||||
|
@ -70,7 +65,7 @@ bool EnumerateCollectionBlock::skipDocuments(size_t toSkip, size_t& skipped) {
|
|||
skipped += skippedHere;
|
||||
|
||||
_documents = VPackSlice();
|
||||
_posInDocuments = 0;
|
||||
_iterator = VPackArrayIterator(arangodb::basics::VelocyPackHelper::EmptyArrayValue());
|
||||
|
||||
_engine->_stats.scannedFull += static_cast<int64_t>(skippedHere);
|
||||
|
||||
|
@ -86,8 +81,8 @@ bool EnumerateCollectionBlock::skipDocuments(size_t toSkip, size_t& skipped) {
|
|||
/// @brief continue fetching of documents
|
||||
bool EnumerateCollectionBlock::moreDocuments(size_t hint) {
|
||||
DEBUG_BEGIN_BLOCK();
|
||||
if (hint < DefaultBatchSize) {
|
||||
hint = DefaultBatchSize;
|
||||
if (hint < DefaultBatchSize()) {
|
||||
hint = DefaultBatchSize();
|
||||
}
|
||||
|
||||
throwIfKilled(); // check if we were aborted
|
||||
|
@ -99,18 +94,18 @@ bool EnumerateCollectionBlock::moreDocuments(size_t hint) {
|
|||
_documents = _scanner->scan(hint);
|
||||
|
||||
TRI_ASSERT(_documents.isArray());
|
||||
VPackValueLength count = _documents.length();
|
||||
_documentsSize = static_cast<size_t>(count);
|
||||
_iterator = VPackArrayIterator(_documents, true);
|
||||
|
||||
VPackValueLength count = _iterator.size();
|
||||
|
||||
if (count == 0) {
|
||||
_documents = VPackSlice();
|
||||
_iterator = VPackArrayIterator(arangodb::basics::VelocyPackHelper::EmptyArrayValue());
|
||||
return false;
|
||||
}
|
||||
|
||||
_engine->_stats.scannedFull += static_cast<int64_t>(count);
|
||||
|
||||
_posInDocuments = 0;
|
||||
|
||||
return true;
|
||||
DEBUG_END_BLOCK();
|
||||
}
|
||||
|
@ -155,7 +150,7 @@ AqlItemBlock* EnumerateCollectionBlock::getSome(size_t, // atLeast,
|
|||
}
|
||||
|
||||
if (_buffer.empty()) {
|
||||
size_t toFetch = (std::min)(DefaultBatchSize, atMost);
|
||||
size_t toFetch = (std::min)(DefaultBatchSize(), atMost);
|
||||
if (!ExecutionBlock::getBlock(toFetch, toFetch)) {
|
||||
_done = true;
|
||||
return nullptr;
|
||||
|
@ -169,14 +164,14 @@ AqlItemBlock* EnumerateCollectionBlock::getSome(size_t, // atLeast,
|
|||
size_t const curRegs = cur->getNrRegs();
|
||||
|
||||
// Get more documents from collection if _documents is empty:
|
||||
if (_posInDocuments >= _documentsSize) {
|
||||
if (_iterator.index() >= _iterator.size()) {
|
||||
if (!moreDocuments(atMost)) {
|
||||
_done = true;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
size_t available = _documentsSize - _posInDocuments;
|
||||
size_t available = _iterator.size() - _iterator.index();
|
||||
size_t toSend = (std::min)(atMost, available);
|
||||
RegisterId nrRegs =
|
||||
getPlanNode()->getRegisterPlan()->nrRegs[getPlanNode()->getDepth()];
|
||||
|
@ -202,16 +197,15 @@ AqlItemBlock* EnumerateCollectionBlock::getSome(size_t, // atLeast,
|
|||
// The result is in the first variable of this depth,
|
||||
// we do not need to do a lookup in getPlanNode()->_registerPlan->varInfo,
|
||||
// but can just take cur->getNrRegs() as registerId:
|
||||
res->setValue(j, static_cast<arangodb::aql::RegisterId>(curRegs),
|
||||
AqlValue(_documents.at(_posInDocuments)));
|
||||
res->setValue(j, static_cast<arangodb::aql::RegisterId>(curRegs), AqlValue(_iterator.value()));
|
||||
// No harm done, if the setValue throws!
|
||||
}
|
||||
|
||||
++_posInDocuments;
|
||||
_iterator.next();
|
||||
}
|
||||
|
||||
// Advance read position:
|
||||
if (_posInDocuments >= _documentsSize) {
|
||||
if (_iterator.index() >= _iterator.size()) {
|
||||
// we have exhausted our local documents buffer
|
||||
// fetch more documents into our buffer
|
||||
if (!moreDocuments(atMost)) {
|
||||
|
@ -242,18 +236,20 @@ size_t EnumerateCollectionBlock::skipSome(size_t atLeast, size_t atMost) {
|
|||
}
|
||||
|
||||
if (!_documents.isNone()) {
|
||||
if (_posInDocuments < _documentsSize) {
|
||||
if (_iterator.index() < _iterator.size()) {
|
||||
// We still have unread documents in the _documents buffer
|
||||
// Just skip them
|
||||
size_t couldSkip = _documentsSize - _posInDocuments;
|
||||
size_t couldSkip = _iterator.size() - _iterator.index();
|
||||
if (atMost <= couldSkip) {
|
||||
// More in buffer then to skip.
|
||||
_posInDocuments += atMost;
|
||||
// More in buffer than to skip.
|
||||
|
||||
// move forward the iterator
|
||||
_iterator.forward(atMost);
|
||||
return atMost;
|
||||
}
|
||||
// Skip entire buffer
|
||||
_documents = VPackSlice();
|
||||
_posInDocuments = 0;
|
||||
_iterator = VPackArrayIterator(arangodb::basics::VelocyPackHelper::EmptyArrayValue());
|
||||
skipped += couldSkip;
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +260,7 @@ size_t EnumerateCollectionBlock::skipSome(size_t atLeast, size_t atMost) {
|
|||
|
||||
while (skipped < atLeast) {
|
||||
if (_buffer.empty()) {
|
||||
size_t toFetch = (std::min)(DefaultBatchSize, atMost);
|
||||
size_t toFetch = (std::min)(DefaultBatchSize(), atMost);
|
||||
if (!getBlock(toFetch, toFetch)) {
|
||||
_done = true;
|
||||
return skipped;
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include "Aql/ExecutionBlock.h"
|
||||
#include "Aql/ExecutionNode.h"
|
||||
|
||||
#include <velocypack/Iterator.h>
|
||||
#include <velocypack/Slice.h>
|
||||
|
||||
struct TRI_doc_mptr_t;
|
||||
|
||||
namespace arangodb {
|
||||
|
@ -73,18 +76,12 @@ class EnumerateCollectionBlock : public ExecutionBlock {
|
|||
/// @brief collection scanner
|
||||
CollectionScanner* _scanner;
|
||||
|
||||
/// @brief iterator over documents
|
||||
arangodb::velocypack::ArrayIterator _iterator;
|
||||
|
||||
/// @brief document buffer
|
||||
arangodb::velocypack::Slice _documents;
|
||||
|
||||
/// @brief length of documents
|
||||
size_t _documentsSize;
|
||||
|
||||
/// @brief current position in _documents
|
||||
size_t _posInDocuments;
|
||||
|
||||
/// @brief whether or not we're doing random iteration
|
||||
bool const _random;
|
||||
|
||||
/// @brief whether or not the enumerated documents need to be stored
|
||||
bool _mustStoreResult;
|
||||
};
|
||||
|
|
|
@ -85,7 +85,7 @@ AqlItemBlock* EnumerateListBlock::getSome(size_t, size_t atMost) {
|
|||
// try again!
|
||||
|
||||
if (_buffer.empty()) {
|
||||
size_t toFetch = (std::min)(DefaultBatchSize, atMost);
|
||||
size_t toFetch = (std::min)(DefaultBatchSize(), atMost);
|
||||
if (!ExecutionBlock::getBlock(toFetch, toFetch)) {
|
||||
_done = true;
|
||||
return nullptr;
|
||||
|
@ -182,7 +182,7 @@ size_t EnumerateListBlock::skipSome(size_t atLeast, size_t atMost) {
|
|||
|
||||
while (skipped < atLeast) {
|
||||
if (_buffer.empty()) {
|
||||
size_t toFetch = (std::min)(DefaultBatchSize, atMost);
|
||||
size_t toFetch = (std::min)(DefaultBatchSize(), atMost);
|
||||
if (!ExecutionBlock::getBlock(toFetch, toFetch)) {
|
||||
_done = true;
|
||||
return skipped;
|
||||
|
|
|
@ -27,9 +27,6 @@
|
|||
|
||||
using namespace arangodb::aql;
|
||||
|
||||
/// @brief batch size value
|
||||
size_t const ExecutionBlock::DefaultBatchSize = 1000;
|
||||
|
||||
ExecutionBlock::ExecutionBlock(ExecutionEngine* engine, ExecutionNode const* ep)
|
||||
: _engine(engine),
|
||||
_trx(engine->getQuery()->trx()),
|
||||
|
@ -309,7 +306,7 @@ bool ExecutionBlock::hasMore() {
|
|||
if (!_buffer.empty()) {
|
||||
return true;
|
||||
}
|
||||
if (getBlock(DefaultBatchSize, DefaultBatchSize)) {
|
||||
if (getBlock(DefaultBatchSize(), DefaultBatchSize())) {
|
||||
_pos = 0;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -46,19 +46,6 @@ class AqlTransaction;
|
|||
|
||||
namespace aql {
|
||||
|
||||
/// @brief struct to hold the member-indexes in the _condition node
|
||||
struct NonConstExpression {
|
||||
size_t const orMember;
|
||||
size_t const andMember;
|
||||
size_t const operatorMember;
|
||||
Expression* expression;
|
||||
|
||||
NonConstExpression(size_t orM, size_t andM, size_t opM, Expression* exp)
|
||||
: orMember(orM), andMember(andM), operatorMember(opM), expression(exp) {}
|
||||
|
||||
~NonConstExpression() { delete expression; }
|
||||
};
|
||||
|
||||
class ExecutionEngine;
|
||||
|
||||
class ExecutionBlock {
|
||||
|
@ -68,6 +55,9 @@ class ExecutionBlock {
|
|||
virtual ~ExecutionBlock();
|
||||
|
||||
public:
|
||||
/// @brief batch size value
|
||||
static constexpr inline size_t DefaultBatchSize() { return 1000; }
|
||||
|
||||
/// @brief determine the number of rows in a vector of blocks
|
||||
size_t countBlocksRows(std::vector<AqlItemBlock*> const&) const;
|
||||
|
||||
|
@ -209,10 +199,6 @@ class ExecutionBlock {
|
|||
|
||||
/// @brief if this is set, we are done, this is reset to false by execute()
|
||||
bool _done;
|
||||
|
||||
public:
|
||||
/// @brief batch size value
|
||||
static size_t const DefaultBatchSize;
|
||||
};
|
||||
|
||||
} // namespace arangodb::aql
|
||||
|
|
|
@ -462,7 +462,7 @@ static bool SortNumberList(arangodb::AqlTransaction* trx,
|
|||
return true;
|
||||
}
|
||||
|
||||
static void RequestEdges(VPackSlice const& vertexSlice,
|
||||
static void RequestEdges(VPackSlice vertexSlice,
|
||||
arangodb::AqlTransaction* trx,
|
||||
std::string const& collectionName,
|
||||
Transaction::IndexHandle const& indexId,
|
||||
|
@ -470,6 +470,8 @@ static void RequestEdges(VPackSlice const& vertexSlice,
|
|||
arangodb::ExampleMatcher const* matcher,
|
||||
bool includeVertices, VPackBuilder& result) {
|
||||
|
||||
vertexSlice = vertexSlice.resolveExternals();
|
||||
|
||||
std::string vertexId;
|
||||
if (vertexSlice.isString()) {
|
||||
vertexId = vertexSlice.copyString();
|
||||
|
@ -501,25 +503,26 @@ static void RequestEdges(VPackSlice const& vertexSlice,
|
|||
VPackSlice edges = opRes->slice();
|
||||
TRI_ASSERT(edges.isArray());
|
||||
if (includeVertices) {
|
||||
for (auto const& edge : VPackArrayIterator(edges)) {
|
||||
for (auto const& edge : VPackArrayIterator(edges, false)) {
|
||||
VPackObjectBuilder guard(&result);
|
||||
if (matcher == nullptr || matcher->matches(edge)) {
|
||||
result.add("edge", edge);
|
||||
|
||||
std::string target;
|
||||
TRI_ASSERT(edge.hasKey(StaticStrings::FromString));
|
||||
TRI_ASSERT(edge.hasKey(StaticStrings::ToString));
|
||||
VPackSlice e = edge.resolveExternals();
|
||||
TRI_ASSERT(e.hasKey(StaticStrings::FromString));
|
||||
TRI_ASSERT(e.hasKey(StaticStrings::ToString));
|
||||
switch (direction) {
|
||||
case TRI_EDGE_OUT:
|
||||
target = Transaction::extractToFromDocument(edge).copyString();
|
||||
target = Transaction::extractToFromDocument(e).copyString();
|
||||
break;
|
||||
case TRI_EDGE_IN:
|
||||
target = Transaction::extractFromFromDocument(edge).copyString();
|
||||
target = Transaction::extractFromFromDocument(e).copyString();
|
||||
break;
|
||||
case TRI_EDGE_ANY:
|
||||
target = Transaction::extractToFromDocument(edge).copyString();
|
||||
target = Transaction::extractToFromDocument(e).copyString();
|
||||
if (target == vertexId) {
|
||||
target = Transaction::extractFromFromDocument(edge).copyString();
|
||||
target = Transaction::extractFromFromDocument(e).copyString();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -535,14 +538,14 @@ static void RequestEdges(VPackSlice const& vertexSlice,
|
|||
|
||||
searchValueBuilder->clear();
|
||||
searchValueBuilder->openObject();
|
||||
searchValueBuilder->add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(key));
|
||||
searchValueBuilder->add(StaticStrings::KeyString, VPackValue(key));
|
||||
searchValueBuilder->close();
|
||||
result.add(VPackValue("vertex"));
|
||||
int res = trx->documentFastPath(collection, searchValueBuilder->slice(), result);
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
if (res == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) {
|
||||
// Not found is ok. Is equal to NULL
|
||||
result.add(VPackValue(VPackValueType::Null));
|
||||
result.add(arangodb::basics::VelocyPackHelper::NullValue());
|
||||
} else {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
|
@ -550,7 +553,7 @@ static void RequestEdges(VPackSlice const& vertexSlice,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for (auto const& edge : VPackArrayIterator(edges)) {
|
||||
for (auto const& edge : VPackArrayIterator(edges, false)) {
|
||||
if (matcher == nullptr || matcher->matches(edge)) {
|
||||
result.add(edge);
|
||||
}
|
||||
|
@ -2574,7 +2577,7 @@ AqlValue Functions::Edges(arangodb::aql::Query* query,
|
|||
builder->openArray();
|
||||
|
||||
if (vertexSlice.isArray()) {
|
||||
for (auto const& v : VPackArrayIterator(vertexSlice)) {
|
||||
for (auto const& v : VPackArrayIterator(vertexSlice, false)) {
|
||||
RequestEdges(v, trx, collectionName, indexId, direction,
|
||||
matcher.get(), includeVertices, *builder.get());
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "Basics/ScopeGuard.h"
|
||||
#include "Basics/json-utilities.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Basics/StaticStrings.h"
|
||||
#include "Utils/OperationCursor.h"
|
||||
#include "V8/v8-globals.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
@ -384,6 +385,8 @@ bool IndexBlock::readIndex(size_t atMost) {
|
|||
bool isReverse = (static_cast<IndexNode const*>(getPlanNode()))->_reverse;
|
||||
bool isLastIndex = (_currentIndex == lastIndexNr && !isReverse) ||
|
||||
(_currentIndex == 0 && isReverse);
|
||||
bool const hasMultipleIndexes = (_indexes.size() > 1);
|
||||
|
||||
while (_cursor != nullptr) {
|
||||
if (!_cursor->hasMore()) {
|
||||
startNextCursor();
|
||||
|
@ -407,18 +410,25 @@ bool IndexBlock::readIndex(size_t atMost) {
|
|||
TRI_IF_FAILURE("IndexBlock::readIndex") {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
|
||||
}
|
||||
for (auto const& doc : VPackArrayIterator(slice)) {
|
||||
std::string key =
|
||||
arangodb::basics::VelocyPackHelper::getStringValue(doc, TRI_VOC_ATTRIBUTE_KEY, "");
|
||||
if (_alreadyReturned.find(key) == _alreadyReturned.end()) {
|
||||
if (!isLastIndex) {
|
||||
_alreadyReturned.emplace(key);
|
||||
}
|
||||
|
||||
for (auto const& doc : VPackArrayIterator(slice, true)) {
|
||||
if (!hasMultipleIndexes) {
|
||||
_documents.emplace_back(doc);
|
||||
} else {
|
||||
VPackSlice keySlice = Transaction::extractKeyFromDocument(doc);
|
||||
std::string key = keySlice.copyString();
|
||||
if (_alreadyReturned.find(key) == _alreadyReturned.end()) {
|
||||
if (!isLastIndex) {
|
||||
_alreadyReturned.emplace(std::move(key));
|
||||
}
|
||||
_documents.emplace_back(doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Leave the loop here, we can only exhaust one cursor at a time, otherwise slices are lost
|
||||
break;
|
||||
if (!_documents.empty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_posInDocs = 0;
|
||||
return (!_documents.empty());
|
||||
|
@ -455,7 +465,7 @@ AqlItemBlock* IndexBlock::getSome(size_t atLeast, size_t atMost) {
|
|||
// try again!
|
||||
|
||||
if (_buffer.empty()) {
|
||||
size_t toFetch = (std::min)(DefaultBatchSize, atMost);
|
||||
size_t toFetch = (std::min)(DefaultBatchSize(), atMost);
|
||||
if (!ExecutionBlock::getBlock(toFetch, toFetch) || (!initIndexes())) {
|
||||
_done = true;
|
||||
return nullptr;
|
||||
|
@ -477,7 +487,7 @@ AqlItemBlock* IndexBlock::getSome(size_t atLeast, size_t atMost) {
|
|||
_pos = 0;
|
||||
}
|
||||
if (_buffer.empty()) {
|
||||
if (!ExecutionBlock::getBlock(DefaultBatchSize, DefaultBatchSize)) {
|
||||
if (!ExecutionBlock::getBlock(DefaultBatchSize(), DefaultBatchSize())) {
|
||||
_done = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -549,7 +559,7 @@ size_t IndexBlock::skipSome(size_t atLeast, size_t atMost) {
|
|||
|
||||
while (skipped < atLeast) {
|
||||
if (_buffer.empty()) {
|
||||
size_t toFetch = (std::min)(DefaultBatchSize, atMost);
|
||||
size_t toFetch = (std::min)(DefaultBatchSize(), atMost);
|
||||
if (!ExecutionBlock::getBlock(toFetch, toFetch) || (!initIndexes())) {
|
||||
_done = true;
|
||||
return skipped;
|
||||
|
|
|
@ -28,9 +28,6 @@
|
|||
#include "Aql/ExecutionBlock.h"
|
||||
#include "Aql/ExecutionNode.h"
|
||||
#include "Aql/IndexNode.h"
|
||||
#include "Utils/AqlTransaction.h"
|
||||
|
||||
struct TRI_doc_mptr_t;
|
||||
|
||||
namespace arangodb {
|
||||
struct OperationCursor;
|
||||
|
@ -46,6 +43,19 @@ struct AstNode;
|
|||
struct Collection;
|
||||
class ExecutionEngine;
|
||||
|
||||
/// @brief struct to hold the member-indexes in the _condition node
|
||||
struct NonConstExpression {
|
||||
size_t const orMember;
|
||||
size_t const andMember;
|
||||
size_t const operatorMember;
|
||||
Expression* expression;
|
||||
|
||||
NonConstExpression(size_t orM, size_t andM, size_t opM, Expression* exp)
|
||||
: orMember(orM), andMember(andM), operatorMember(opM), expression(exp) {}
|
||||
|
||||
~NonConstExpression() { delete expression; }
|
||||
};
|
||||
|
||||
class IndexBlock : public ExecutionBlock {
|
||||
public:
|
||||
IndexBlock(ExecutionEngine* engine, IndexNode const* ep);
|
||||
|
|
|
@ -580,7 +580,7 @@ QueryResult Query::execute(QueryRegistry* registry) {
|
|||
if (useQueryCache) {
|
||||
// iterate over result, return it and store it in query cache
|
||||
while (nullptr != (value = _engine->getSome(
|
||||
1, ExecutionBlock::DefaultBatchSize))) {
|
||||
1, ExecutionBlock::DefaultBatchSize()))) {
|
||||
size_t const n = value->size();
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
|
@ -611,7 +611,7 @@ QueryResult Query::execute(QueryRegistry* registry) {
|
|||
} else {
|
||||
// iterate over result and return it
|
||||
while (nullptr != (value = _engine->getSome(
|
||||
1, ExecutionBlock::DefaultBatchSize))) {
|
||||
1, ExecutionBlock::DefaultBatchSize()))) {
|
||||
|
||||
size_t const n = value->size();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
|
@ -742,7 +742,7 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
|
|||
|
||||
uint32_t j = 0;
|
||||
while (nullptr != (value = _engine->getSome(
|
||||
1, ExecutionBlock::DefaultBatchSize))) {
|
||||
1, ExecutionBlock::DefaultBatchSize()))) {
|
||||
size_t const n = value->size();
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
|
@ -766,16 +766,20 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
|
|||
}
|
||||
} else {
|
||||
// iterate over result and return it
|
||||
bool suppressResult = silent();
|
||||
|
||||
uint32_t j = 0;
|
||||
while (nullptr != (value = _engine->getSome(
|
||||
1, ExecutionBlock::DefaultBatchSize))) {
|
||||
size_t const n = value->size();
|
||||
1, ExecutionBlock::DefaultBatchSize()))) {
|
||||
if (!suppressResult) {
|
||||
size_t const n = value->size();
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
AqlValue const& val = value->getValueReference(i, resultRegister);
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
AqlValue const& val = value->getValueReference(i, resultRegister);
|
||||
|
||||
if (!val.isEmpty()) {
|
||||
result.result->Set(j++, val.toV8(isolate, _trx));
|
||||
if (!val.isEmpty()) {
|
||||
result.result->Set(j++, val.toV8(isolate, _trx));
|
||||
}
|
||||
}
|
||||
}
|
||||
delete value;
|
||||
|
|
|
@ -165,6 +165,9 @@ class Query {
|
|||
/// @brief should the execution be profiled?
|
||||
bool profiling() const { return getBooleanOption("profile", false); }
|
||||
|
||||
/// @brief should we suppress the query result (useful for performance testing only)?
|
||||
bool silent() const { return getBooleanOption("silent", false); }
|
||||
|
||||
/// @brief maximum number of plans to produce
|
||||
size_t maxNumberOfPlans() const {
|
||||
double value = getNumericOption("maxNumberOfPlans", 0.0);
|
||||
|
|
|
@ -713,7 +713,7 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
|
|||
auto atLeast =
|
||||
VelocyPackHelper::getNumericValue<size_t>(querySlice, "atLeast", 1);
|
||||
auto atMost = VelocyPackHelper::getNumericValue<size_t>(
|
||||
querySlice, "atMost", ExecutionBlock::DefaultBatchSize);
|
||||
querySlice, "atMost", ExecutionBlock::DefaultBatchSize());
|
||||
std::unique_ptr<AqlItemBlock> items;
|
||||
if (shardId.empty()) {
|
||||
items.reset(query->engine()->getSome(atLeast, atMost));
|
||||
|
@ -747,7 +747,7 @@ void RestAqlHandler::handleUseQuery(std::string const& operation, Query* query,
|
|||
auto atLeast =
|
||||
VelocyPackHelper::getNumericValue<size_t>(querySlice, "atLeast", 1);
|
||||
auto atMost = VelocyPackHelper::getNumericValue<size_t>(
|
||||
querySlice, "atMost", ExecutionBlock::DefaultBatchSize);
|
||||
querySlice, "atMost", ExecutionBlock::DefaultBatchSize());
|
||||
size_t skipped;
|
||||
try {
|
||||
if (shardId.empty()) {
|
||||
|
|
|
@ -53,7 +53,7 @@ int SortBlock::initializeCursor(AqlItemBlock* items, size_t pos) {
|
|||
return res;
|
||||
}
|
||||
// suck all blocks into _buffer
|
||||
while (getBlock(DefaultBatchSize, DefaultBatchSize)) {
|
||||
while (getBlock(DefaultBatchSize(), DefaultBatchSize())) {
|
||||
}
|
||||
|
||||
if (_buffer.empty()) {
|
||||
|
@ -117,7 +117,7 @@ void SortBlock::doSorting() {
|
|||
// install the rearranged values from _buffer into newbuffer
|
||||
|
||||
while (count < sum) {
|
||||
size_t sizeNext = (std::min)(sum - count, DefaultBatchSize);
|
||||
size_t sizeNext = (std::min)(sum - count, DefaultBatchSize());
|
||||
AqlItemBlock* next = new AqlItemBlock(sizeNext, nrregs);
|
||||
|
||||
try {
|
||||
|
|
|
@ -139,7 +139,7 @@ std::vector<AqlItemBlock*>* SubqueryBlock::executeSubquery() {
|
|||
try {
|
||||
do {
|
||||
std::unique_ptr<AqlItemBlock> tmp(
|
||||
_subquery->getSome(DefaultBatchSize, DefaultBatchSize));
|
||||
_subquery->getSome(DefaultBatchSize(), DefaultBatchSize()));
|
||||
|
||||
if (tmp.get() == nullptr) {
|
||||
break;
|
||||
|
|
|
@ -375,7 +375,7 @@ AqlItemBlock* TraversalBlock::getSome(size_t, // atLeast,
|
|||
}
|
||||
|
||||
if (_buffer.empty()) {
|
||||
size_t toFetch = (std::min)(DefaultBatchSize, atMost);
|
||||
size_t toFetch = (std::min)(DefaultBatchSize(), atMost);
|
||||
if (!ExecutionBlock::getBlock(toFetch, toFetch)) {
|
||||
_done = true;
|
||||
return nullptr;
|
||||
|
@ -476,7 +476,7 @@ size_t TraversalBlock::skipSome(size_t atLeast, size_t atMost) {
|
|||
}
|
||||
|
||||
if (_buffer.empty()) {
|
||||
size_t toFetch = (std::min)(DefaultBatchSize, atMost);
|
||||
size_t toFetch = (std::min)(DefaultBatchSize(), atMost);
|
||||
if (!ExecutionBlock::getBlock(toFetch, toFetch)) {
|
||||
_done = true;
|
||||
return skipped;
|
||||
|
|
|
@ -702,12 +702,10 @@ bool AgencyComm::tryInitializeStructure() {
|
|||
addEmptyVPackObject("_system", builder);
|
||||
}
|
||||
}
|
||||
addEmptyVPackObject("Launchers", builder);
|
||||
builder.add(VPackValue("Target"));
|
||||
{
|
||||
VPackObjectBuilder c(&builder);
|
||||
addEmptyVPackObject("Coordinators", builder);
|
||||
addEmptyVPackObject("MapIDToEndpoint", builder);
|
||||
builder.add(VPackValue("Collections"));
|
||||
{
|
||||
VPackObjectBuilder d(&builder);
|
||||
|
|
|
@ -2372,42 +2372,6 @@ std::vector<ServerID> ClusterInfo::getCurrentDBServers() {
|
|||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookup the server's endpoint by scanning Target/MapIDToEnpdoint for
|
||||
/// our id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::string const prefixTargetServerEndpoint = "Target/MapIDToEndpoint/";
|
||||
|
||||
std::string ClusterInfo::getTargetServerEndpoint(ServerID const& serverID) {
|
||||
AgencyCommResult result;
|
||||
|
||||
// fetch value at Target/MapIDToEndpoint
|
||||
{
|
||||
AgencyCommLocker locker("Target", "READ");
|
||||
|
||||
if (locker.successful()) {
|
||||
result = _agency.getValues2(prefixTargetServerEndpoint + serverID, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.successful()) {
|
||||
result.parse(prefixTargetServerEndpoint, false);
|
||||
|
||||
// check if we can find ourselves in the list returned by the agency
|
||||
std::map<std::string, AgencyCommResultEntry>::const_iterator it =
|
||||
result._values.find(serverID);
|
||||
|
||||
if (it != result._values.end()) {
|
||||
VPackSlice const slice = it->second._vpack->slice();
|
||||
return arangodb::basics::VelocyPackHelper::getStringValue(slice, "");
|
||||
}
|
||||
}
|
||||
|
||||
// not found
|
||||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief find the servers who are responsible for a shard (one leader
|
||||
/// and multiple followers)
|
||||
|
|
|
@ -773,13 +773,6 @@ class ClusterInfo {
|
|||
|
||||
std::vector<ServerID> getCurrentDBServers();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookup the server's endpoint by scanning Target/MapIDToEnpdoint for
|
||||
/// our id
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string getTargetServerEndpoint(ServerID const&);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief find the servers who are responsible for a shard (one leader
|
||||
/// and possibly multiple followers).
|
||||
|
|
|
@ -678,6 +678,10 @@ bool HeartbeatThread::syncDBServerStatusQuo() {
|
|||
std::unique_ptr<arangodb::rest::Job> job(new ServerJob(this));
|
||||
|
||||
auto dispatcher = DispatcherFeature::DISPATCHER;
|
||||
if (dispatcher == nullptr) {
|
||||
LOG(ERR) << "could not schedule dbserver sync - dispatcher gone.";
|
||||
return false;
|
||||
}
|
||||
if (dispatcher->addJob(job) == TRI_ERROR_NO_ERROR) {
|
||||
LOG(TRACE) << "scheduled dbserver sync";
|
||||
return true;
|
||||
|
|
|
@ -190,16 +190,6 @@ void ServerState::findAndSetRoleBlocking() {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ServerState::flush() {
|
||||
{
|
||||
WRITE_LOCKER(writeLocker, _lock);
|
||||
|
||||
if (_id.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_address = ClusterInfo::instance()->getTargetServerEndpoint(_id);
|
||||
}
|
||||
|
||||
findAndSetRoleBlocking();
|
||||
}
|
||||
|
||||
|
@ -484,32 +474,8 @@ void ServerState::setDescription(std::string const& description) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string ServerState::getAddress() {
|
||||
std::string id;
|
||||
|
||||
{
|
||||
READ_LOCKER(readLocker, _lock);
|
||||
if (!_address.empty()) {
|
||||
return _address;
|
||||
}
|
||||
|
||||
id = _id;
|
||||
}
|
||||
|
||||
// address not yet set
|
||||
if (id.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// fetch and set the address
|
||||
std::string const address =
|
||||
ClusterInfo::instance()->getTargetServerEndpoint(id);
|
||||
|
||||
{
|
||||
WRITE_LOCKER(writeLocker, _lock);
|
||||
_address = address;
|
||||
}
|
||||
|
||||
return address;
|
||||
READ_LOCKER(readLocker, _lock);
|
||||
return _address;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "Dispatcher/Dispatcher.h"
|
||||
#include "ProgramOptions/ProgramOptions.h"
|
||||
#include "ProgramOptions/Section.h"
|
||||
#include "Scheduler/Scheduler.h"
|
||||
#include "Scheduler/SchedulerFeature.h"
|
||||
#include "V8Server/V8DealerFeature.h"
|
||||
#include "V8Server/v8-dispatcher.h"
|
||||
|
@ -135,6 +136,25 @@ void DispatcherFeature::beginShutdown() {
|
|||
}
|
||||
|
||||
void DispatcherFeature::stop() {
|
||||
// signal the shutdown to the scheduler thread, so it does not
|
||||
// create any new tasks for us
|
||||
auto scheduler = SchedulerFeature::SCHEDULER;
|
||||
if (scheduler != nullptr) {
|
||||
scheduler->beginShutdown();
|
||||
}
|
||||
|
||||
// wait for scheduler threads to finish
|
||||
int counter = 0;
|
||||
while (scheduler != nullptr && scheduler->isRunning()) {
|
||||
usleep(10000);
|
||||
|
||||
// warn every 5 secs
|
||||
if (++counter == 50) {
|
||||
LOG(INFO) << "waiting for scheduler to shut down";
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_dispatcher->shutdown();
|
||||
|
||||
DISPATCHER = nullptr;
|
||||
|
|
|
@ -106,17 +106,17 @@ void HttpServer::startListening() {
|
|||
auto endpoints =
|
||||
_endpointList->matching(Endpoint::TransportType::HTTP, encryptionType());
|
||||
|
||||
for (auto&& i : endpoints) {
|
||||
LOG(TRACE) << "trying to bind to endpoint '" << i.first << "' for requests";
|
||||
for (auto& it : endpoints) {
|
||||
LOG(TRACE) << "trying to bind to endpoint '" << it.first << "' for requests";
|
||||
|
||||
bool ok = openEndpoint(i.second);
|
||||
bool ok = openEndpoint(it.second);
|
||||
|
||||
if (ok) {
|
||||
LOG(DEBUG) << "bound to endpoint '" << i.first << "'";
|
||||
LOG(DEBUG) << "bound to endpoint '" << it.first << "'";
|
||||
} else {
|
||||
LOG(FATAL) << "failed to bind to endpoint '" << i.first
|
||||
LOG(FATAL) << "failed to bind to endpoint '" << it.first
|
||||
<< "'. Please check whether another instance is already "
|
||||
"running or review your endpoints configuration.";
|
||||
"running using this endpint and review your endpoints configuration.";
|
||||
FATAL_ERROR_EXIT();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,8 +47,7 @@ class PrimaryIndexIterator final : public IndexIterator {
|
|||
: _trx(trx),
|
||||
_index(index),
|
||||
_keys(keys.get()),
|
||||
_iterator(_keys->slice(), true),
|
||||
_position(0) {
|
||||
_iterator(_keys->slice(), true) {
|
||||
|
||||
keys.release(); // now we have ownership for _keys
|
||||
TRI_ASSERT(_keys->slice().isArray());
|
||||
|
@ -65,7 +64,6 @@ class PrimaryIndexIterator final : public IndexIterator {
|
|||
PrimaryIndex const* _index;
|
||||
std::unique_ptr<VPackBuilder> _keys;
|
||||
arangodb::velocypack::ArrayIterator _iterator;
|
||||
size_t _position;
|
||||
};
|
||||
|
||||
class AllIndexIterator final : public IndexIterator {
|
||||
|
|
|
@ -122,6 +122,11 @@ void RestJobHandler::putJobMethod() {
|
|||
uint64_t jobId = StringUtils::uint64(value);
|
||||
|
||||
if (method == "cancel") {
|
||||
if (DispatcherFeature::DISPATCHER == nullptr) {
|
||||
generateError(GeneralResponse::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
bool status = DispatcherFeature::DISPATCHER->cancelJob(jobId);
|
||||
|
||||
// unknown or already fetched job
|
||||
|
|
|
@ -58,6 +58,7 @@ void OperationCursor::getMore(std::shared_ptr<OperationResult>& opRes,
|
|||
auto tmp = std::make_shared<OperationResult>(TRI_ERROR_NO_ERROR);
|
||||
opRes.swap(tmp);
|
||||
}
|
||||
|
||||
// This may throw out of memory
|
||||
if (!hasMore()) {
|
||||
TRI_ASSERT(false);
|
||||
|
@ -79,7 +80,7 @@ void OperationCursor::getMore(std::shared_ptr<OperationResult>& opRes,
|
|||
--batchSize;
|
||||
--_limit;
|
||||
if (useExternals) {
|
||||
builder.add(VPackValue(mptr->vpack(), VPackValueType::External));
|
||||
builder.addExternal(mptr->vpack());
|
||||
} else {
|
||||
builder.add(VPackSlice(mptr->vpack()));
|
||||
}
|
||||
|
|
|
@ -720,7 +720,10 @@ std::string Transaction::extractIdString(CollectionNameResolver const* resolver,
|
|||
/// be the first one
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VPackSlice Transaction::extractKeyFromDocument(VPackSlice const& slice) {
|
||||
VPackSlice Transaction::extractKeyFromDocument(VPackSlice slice) {
|
||||
if (slice.isExternal()) {
|
||||
slice = slice.resolveExternal();
|
||||
}
|
||||
TRI_ASSERT(slice.isObject());
|
||||
// a regular document must have at least the three attributes
|
||||
// _key, _id and _rev (in this order). _key must be the first attribute
|
||||
|
@ -747,7 +750,10 @@ VPackSlice Transaction::extractKeyFromDocument(VPackSlice const& slice) {
|
|||
/// and _rev (in this order)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VPackSlice Transaction::extractFromFromDocument(VPackSlice const& slice) {
|
||||
VPackSlice Transaction::extractFromFromDocument(VPackSlice slice) {
|
||||
if (slice.isExternal()) {
|
||||
slice = slice.resolveExternal();
|
||||
}
|
||||
TRI_ASSERT(slice.isObject());
|
||||
// this method must only be called on edges
|
||||
// this means we must have at least the attributes _key, _id, _from, _to and _rev
|
||||
|
@ -778,8 +784,10 @@ VPackSlice Transaction::extractFromFromDocument(VPackSlice const& slice) {
|
|||
/// and _rev (in this order)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VPackSlice Transaction::extractToFromDocument(VPackSlice const& slice) {
|
||||
TRI_ASSERT(slice.isObject());
|
||||
VPackSlice Transaction::extractToFromDocument(VPackSlice slice) {
|
||||
if (slice.isExternal()) {
|
||||
slice = slice.resolveExternal();
|
||||
}
|
||||
// this method must only be called on edges
|
||||
// this means we must have at least the attributes _key, _id, _from, _to and _rev
|
||||
TRI_ASSERT(slice.length() >= 5);
|
||||
|
@ -809,7 +817,10 @@ VPackSlice Transaction::extractToFromDocument(VPackSlice const& slice) {
|
|||
/// (possibly with _from and _to in between)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VPackSlice Transaction::extractRevFromDocument(VPackSlice const& slice) {
|
||||
VPackSlice Transaction::extractRevFromDocument(VPackSlice slice) {
|
||||
if (slice.isExternal()) {
|
||||
slice = slice.resolveExternal();
|
||||
}
|
||||
TRI_ASSERT(slice.isObject());
|
||||
TRI_ASSERT(slice.length() >= 2);
|
||||
|
||||
|
@ -838,9 +849,12 @@ VPackSlice Transaction::extractRevFromDocument(VPackSlice const& slice) {
|
|||
/// collection and compaction
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Transaction::extractKeyAndRevFromDocument(VPackSlice const& slice,
|
||||
void Transaction::extractKeyAndRevFromDocument(VPackSlice slice,
|
||||
VPackSlice& keySlice,
|
||||
TRI_voc_rid_t& revisionId) {
|
||||
if (slice.isExternal()) {
|
||||
slice = slice.resolveExternal();
|
||||
}
|
||||
TRI_ASSERT(slice.isObject());
|
||||
TRI_ASSERT(slice.length() >= 2);
|
||||
|
||||
|
|
|
@ -289,7 +289,7 @@ class Transaction {
|
|||
/// be the first one
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static VPackSlice extractKeyFromDocument(VPackSlice const&);
|
||||
static VPackSlice extractKeyFromDocument(VPackSlice);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief quick access to the _from attribute in a database document
|
||||
|
@ -297,7 +297,7 @@ class Transaction {
|
|||
/// and _rev (in this order)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static VPackSlice extractFromFromDocument(VPackSlice const&);
|
||||
static VPackSlice extractFromFromDocument(VPackSlice);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief quick access to the _to attribute in a database document
|
||||
|
@ -305,7 +305,7 @@ class Transaction {
|
|||
/// and _rev (in this order)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static VPackSlice extractToFromDocument(VPackSlice const&);
|
||||
static VPackSlice extractToFromDocument(VPackSlice);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief quick access to the _rev attribute in a database document
|
||||
|
@ -313,7 +313,7 @@ class Transaction {
|
|||
/// (possibly with _from and _to in between)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static VPackSlice extractRevFromDocument(VPackSlice const&);
|
||||
static VPackSlice extractRevFromDocument(VPackSlice);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract _key and _rev from a document, in one go
|
||||
|
@ -321,7 +321,7 @@ class Transaction {
|
|||
/// collection and compaction
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void extractKeyAndRevFromDocument(VPackSlice const& slice,
|
||||
static void extractKeyAndRevFromDocument(VPackSlice slice,
|
||||
VPackSlice& keySlice,
|
||||
TRI_voc_rid_t& revisionId);
|
||||
|
||||
|
|
|
@ -78,10 +78,17 @@ void V8PeriodicTask::getDescription(VPackBuilder& builder) const {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool V8PeriodicTask::handlePeriod() {
|
||||
TRI_ASSERT(DispatcherFeature::DISPATCHER != nullptr);
|
||||
|
||||
std::unique_ptr<Job> job(new V8Job(
|
||||
_vocbase, "(function (params) { " + _command + " } )(params);",
|
||||
_parameters, _allowUseDatabase));
|
||||
|
||||
if (DispatcherFeature::DISPATCHER == nullptr) {
|
||||
LOG(WARN) << "could not add task " << _command << " to non-existing queue";
|
||||
return false;
|
||||
}
|
||||
|
||||
DispatcherFeature::DISPATCHER->addJob(job);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -79,10 +79,17 @@ void V8TimerTask::getDescription(VPackBuilder& builder) const {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool V8TimerTask::handleTimeout() {
|
||||
TRI_ASSERT(DispatcherFeature::DISPATCHER != nullptr);
|
||||
|
||||
std::unique_ptr<Job> job(
|
||||
new V8Job(_vocbase, "(function (params) { " + _command + " } )(params);",
|
||||
_parameters, _allowUseDatabase));
|
||||
|
||||
if (DispatcherFeature::DISPATCHER == nullptr) {
|
||||
LOG(WARN) << "could not add task " << _command << " to non-existing queue";
|
||||
return false;
|
||||
}
|
||||
|
||||
int res = DispatcherFeature::DISPATCHER->addJob(job);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
|
|
@ -35,13 +35,13 @@ namespace DatafileHelper {
|
|||
/// a WAL file (bit set) or a datafile (bit not set)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
constexpr uint64_t WalFileBitmask() { return 0x8000000000000000ULL; }
|
||||
constexpr inline uint64_t WalFileBitmask() { return 0x8000000000000000ULL; }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief maximal size of a marker
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
constexpr TRI_voc_size_t MaximalMarkerSize() {
|
||||
constexpr inline TRI_voc_size_t MaximalMarkerSize() {
|
||||
static_assert(sizeof(TRI_voc_size_t) >= 4, "TRI_voc_size_t is too small");
|
||||
|
||||
return 2UL * 1024UL * 1024UL * 1024UL; // 2 GB
|
||||
|
@ -51,7 +51,7 @@ constexpr TRI_voc_size_t MaximalMarkerSize() {
|
|||
/// @brief journal overhead
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
constexpr TRI_voc_size_t JournalOverhead() {
|
||||
constexpr inline TRI_voc_size_t JournalOverhead() {
|
||||
return sizeof(TRI_df_header_marker_t) + sizeof(TRI_df_footer_marker_t);
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ constexpr TRI_voc_size_t JournalOverhead() {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename T>
|
||||
static constexpr T AlignedSize(T value) {
|
||||
static constexpr inline T AlignedSize(T value) {
|
||||
return (value + 7) - ((value + 7) & 7);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,14 +35,14 @@ using namespace arangodb::wal;
|
|||
|
||||
/// @brief returns the bitmask for the synchronous waiters
|
||||
/// for use in _waiters only
|
||||
static constexpr uint64_t syncWaitersMask() {
|
||||
static constexpr inline uint64_t syncWaitersMask() {
|
||||
return static_cast<uint64_t>(0xffffffffULL);
|
||||
}
|
||||
|
||||
/// @brief returns the numbers of bits to shift to get the
|
||||
/// number of asynchronous waiters
|
||||
/// for use in _waiters only
|
||||
static constexpr int asyncWaitersBits() { return 32; }
|
||||
static constexpr inline int asyncWaitersBits() { return 32; }
|
||||
|
||||
SynchronizerThread::SynchronizerThread(LogfileManager* logfileManager,
|
||||
uint64_t syncInterval)
|
||||
|
|
|
@ -68,6 +68,7 @@ router.post('/logout', function (req, res) {
|
|||
|
||||
router.post('/login', function (req, res) {
|
||||
const currentDb = db._name();
|
||||
/*
|
||||
const actualDb = req.body.database;
|
||||
if (actualDb !== currentDb) {
|
||||
res.redirect(307, joinPath(
|
||||
|
@ -78,7 +79,7 @@ router.post('/login', function (req, res) {
|
|||
));
|
||||
return;
|
||||
}
|
||||
|
||||
*/
|
||||
const user = req.body.username;
|
||||
const valid = users.isValid(user, req.body.password);
|
||||
|
||||
|
@ -93,8 +94,8 @@ router.post('/login', function (req, res) {
|
|||
})
|
||||
.body({
|
||||
username: joi.string().required(),
|
||||
password: joi.string().required().allow(''),
|
||||
database: joi.string().default(db._name())
|
||||
password: joi.string().required().allow('')
|
||||
//database: joi.string().default(db._name())
|
||||
}, 'Login credentials.')
|
||||
.error('unauthorized', 'Invalid credentials.')
|
||||
.summary('Log in')
|
||||
|
|
|
@ -19023,15 +19023,14 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
return a > b ? 1 : a < b ? -1 : 0;
|
||||
},
|
||||
|
||||
login: function (username, password, database, callback) {
|
||||
login: function (username, password, callback) {
|
||||
var self = this;
|
||||
|
||||
$.ajax("login", {
|
||||
method: "POST",
|
||||
data: JSON.stringify({
|
||||
username: username,
|
||||
password: password,
|
||||
database: database
|
||||
password: password
|
||||
}),
|
||||
dataType: "json"
|
||||
}).success(
|
||||
|
@ -22614,18 +22613,29 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
}
|
||||
});
|
||||
|
||||
//sort for library
|
||||
opts.file.sort(function(a,b){
|
||||
return new Date(b[0]) - new Date(a[0]);
|
||||
});
|
||||
if (opts.file === undefined) {
|
||||
$('#loadingScreen span').text('Statistics not ready yet. Waiting.');
|
||||
$('#loadingScreen').show();
|
||||
$('#content').hide();
|
||||
}
|
||||
else {
|
||||
$('#content').show();
|
||||
$('#loadingScreen').hide();
|
||||
|
||||
g.updateOptions(opts);
|
||||
//sort for library
|
||||
opts.file.sort(function(a,b){
|
||||
return new Date(b[0]) - new Date(a[0]);
|
||||
});
|
||||
|
||||
//clean up history
|
||||
if (this.history[this.server].hasOwnProperty(figure)) {
|
||||
this.cleanupHistory(figure);
|
||||
}
|
||||
g.updateOptions(opts);
|
||||
|
||||
//clean up history
|
||||
if (this.history[this.server].hasOwnProperty(figure)) {
|
||||
this.cleanupHistory(figure);
|
||||
}
|
||||
}
|
||||
$(window).trigger('resize');
|
||||
this.resize();
|
||||
},
|
||||
|
||||
mergeDygraphHistory: function (newData, i) {
|
||||
|
@ -25145,6 +25155,9 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
isOffline: true,
|
||||
isOfflineCounter: 0,
|
||||
firstLogin: true,
|
||||
timer: 15000,
|
||||
lap: 0,
|
||||
timerFunction: null,
|
||||
|
||||
events: {
|
||||
'click .footer-center p' : 'showShortcutModal'
|
||||
|
@ -25155,13 +25168,17 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
var self = this;
|
||||
window.setInterval(function() {
|
||||
self.getVersion();
|
||||
}, 15000);
|
||||
}, self.timer);
|
||||
self.getVersion();
|
||||
|
||||
window.VISIBLE = true;
|
||||
document.addEventListener('visibilitychange', function () {
|
||||
window.VISIBLE = !window.VISIBLE;
|
||||
});
|
||||
|
||||
$('#offlinePlaceholder button').on('click', function() {
|
||||
self.getVersion();
|
||||
});
|
||||
},
|
||||
|
||||
template: templateEngine.createTemplate("footerView.ejs"),
|
||||
|
@ -25175,12 +25192,17 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
$('#healthStatus').addClass('positive');
|
||||
$('.health-state').html('GOOD');
|
||||
$('.health-icon').html('<i class="fa fa-check-circle"></i>');
|
||||
$('#offlinePlaceholder').hide();
|
||||
}
|
||||
else {
|
||||
$('#healthStatus').removeClass('positive');
|
||||
$('#healthStatus').addClass('negative');
|
||||
$('.health-state').html('OFFLINE');
|
||||
$('.health-state').html('UNKNOWN');
|
||||
$('.health-icon').html('<i class="fa fa-exclamation-circle"></i>');
|
||||
|
||||
//show offline overlay
|
||||
$('#offlinePlaceholder').show();
|
||||
this.reconnectAnimation(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -25195,15 +25217,36 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
}
|
||||
},
|
||||
|
||||
reconnectAnimation: function(lap) {
|
||||
var self = this;
|
||||
|
||||
if (lap === 0) {
|
||||
self.lap = lap;
|
||||
$('#offlineSeconds').text(self.timer / 1000);
|
||||
clearTimeout(self.timerFunction);
|
||||
}
|
||||
|
||||
if (self.lap < this.timer / 1000) {
|
||||
self.lap++;
|
||||
$('#offlineSeconds').text(self.timer / 1000 - self.lap);
|
||||
|
||||
self.timerFunction = window.setTimeout(function() {
|
||||
if (self.timer / 1000 - self.lap === 0) {
|
||||
self.getVersion();
|
||||
}
|
||||
else {
|
||||
self.reconnectAnimation(self.lap);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
|
||||
renderClusterState: function(connection) {
|
||||
var ok = 0, error = 0;
|
||||
var error = 0;
|
||||
|
||||
if (connection) {
|
||||
this.collection.each(function(value) {
|
||||
if (value.toJSON().status === 'ok') {
|
||||
ok++;
|
||||
}
|
||||
else {
|
||||
if (value.toJSON().status !== 'ok') {
|
||||
error++;
|
||||
}
|
||||
});
|
||||
|
@ -27115,7 +27158,7 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
|
||||
/*jshint browser: true */
|
||||
/*jshint unused: false */
|
||||
/*global Backbone, EJS, arangoHelper, window, setTimeout, $, templateEngine*/
|
||||
/*global Backbone, document, EJS, _, arangoHelper, window, setTimeout, $, templateEngine*/
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
|
@ -27123,18 +27166,19 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
el: '#content',
|
||||
el2: '.header',
|
||||
el3: '.footer',
|
||||
loggedIn: false,
|
||||
|
||||
events: {
|
||||
"submit #loginForm" : "login",
|
||||
"keypress #loginForm input" : "clear",
|
||||
"change #loginForm input" : "clear"
|
||||
"submit #loginForm" : "goTo",
|
||||
"keyup #loginForm input" : "validate",
|
||||
"change #loginForm input" : "validate",
|
||||
"focusout #loginForm input" : "validate"
|
||||
},
|
||||
|
||||
template: templateEngine.createTemplate("loginView.ejs"),
|
||||
|
||||
render: function() {
|
||||
$(this.el).html(this.template.render({}));
|
||||
$('#loginDatabase').val('_system');
|
||||
$(this.el2).hide();
|
||||
$(this.el3).hide();
|
||||
|
||||
|
@ -27148,50 +27192,70 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
$('.wrong-credentials').hide();
|
||||
},
|
||||
|
||||
login: function (e) {
|
||||
e.preventDefault();
|
||||
validate: function(event) {
|
||||
this.clear();
|
||||
var self = this;
|
||||
|
||||
var username = $('#loginUsername').val();
|
||||
var password = $('#loginPassword').val();
|
||||
var database = $('#loginDatabase').val();
|
||||
|
||||
if (!username) {
|
||||
//Heiko: Form-Validator - please fill out all req. fields
|
||||
//do not send unneccessary requests if no user is given
|
||||
return;
|
||||
}
|
||||
|
||||
var callback = function(error, username) {
|
||||
var callback2 = function(error) {
|
||||
if (error) {
|
||||
arangoHelper.arangoError("User", "Could not fetch user settings");
|
||||
}
|
||||
};
|
||||
|
||||
console.log(event);
|
||||
var callback = function(error) {
|
||||
if (error) {
|
||||
$('#loginForm input').addClass("form-error");
|
||||
$('.wrong-credentials').show();
|
||||
if (event.type === 'focusout') {
|
||||
//$('#loginForm input').addClass("form-error");
|
||||
$('.wrong-credentials').show();
|
||||
}
|
||||
}
|
||||
else {
|
||||
var currentDB = window.location.pathname.split('/')[2];
|
||||
if (currentDB !== database) {
|
||||
var path = window.location.origin + window.location.pathname.replace(currentDB, database);
|
||||
window.location.href = path;
|
||||
$(this.el2).show();
|
||||
$(this.el3).show();
|
||||
$('#currentUser').text(username);
|
||||
this.collection.loadUserSettings(callback2);
|
||||
return;
|
||||
}
|
||||
$('.wrong-credentials').hide();
|
||||
|
||||
$(this.el2).show();
|
||||
$(this.el3).show();
|
||||
window.location.reload();
|
||||
$('#currentUser').text(username);
|
||||
this.collection.loadUserSettings(callback2);
|
||||
if (!self.loggedIn) {
|
||||
self.loggedIn = true;
|
||||
//get list of allowed dbs
|
||||
$.ajax("/_api/database/user").success(function(data) {
|
||||
//enable db select and login button
|
||||
$('#loginDatabase').prop('disabled', false);
|
||||
$('#submitLogin').prop('disabled', false);
|
||||
$('#loginDatabase').html('');
|
||||
//fill select with allowed dbs
|
||||
_.each(data.result, function(db) {
|
||||
$('#loginDatabase').append(
|
||||
'<option>' + db + '</option>'
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
this.collection.login(username, password, database, callback);
|
||||
this.collection.login(username, password, callback);
|
||||
|
||||
},
|
||||
|
||||
goTo: function (e) {
|
||||
e.preventDefault();
|
||||
var username = $('#loginUsername').val();
|
||||
var database = $('#loginDatabase').val();
|
||||
|
||||
var callback2 = function(error) {
|
||||
if (error) {
|
||||
arangoHelper.arangoError("User", "Could not fetch user settings");
|
||||
}
|
||||
};
|
||||
|
||||
var currentDB = window.location.pathname.split('/')[2];
|
||||
var path = window.location.origin + window.location.pathname.replace(currentDB, database);
|
||||
window.location.href = path;
|
||||
$(this.el2).show();
|
||||
$(this.el3).show();
|
||||
$('#currentUser').text(username);
|
||||
this.collection.loadUserSettings(callback2);
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -34880,6 +34944,7 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
execute: function(callback, args) {
|
||||
$('#subNavigationBar .breadcrumb').html('');
|
||||
$('#subNavigationBar .bottom').html('');
|
||||
$('#loadingScreen').hide();
|
||||
if (callback) {
|
||||
callback.apply(this, args);
|
||||
}
|
||||
|
|
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -1487,8 +1487,13 @@ if (list.length > 0) {
|
|||
<form id="loginForm">
|
||||
<input class="login-input" placeholder="username" id="loginUsername" type="text" name="username"><i class="fa fa-user"></i>
|
||||
<input class="login-input" placeholder="password" id="loginPassword" type="password" name="password"><i class="fa fa-lock"></i>
|
||||
<input class="login-input" placeholder="database" id="loginDatabase" type="text" name="database"><i class="fa fa-database"></i>
|
||||
<button id="submitLogin" class="button-success pull-right">Login</button>
|
||||
|
||||
<i class="fa fa-database"></i>
|
||||
<select id="loginDatabase" disabled>
|
||||
<option>database</option>
|
||||
</select>
|
||||
|
||||
<button id="submitLogin" class="button-success pull-right" disabled>Login</button>
|
||||
</form>
|
||||
</div>
|
||||
</div></script><script id="logsView.ejs" type="text/template"><div id="logContent" class="log-content-id innerContent">
|
||||
|
@ -3004,4 +3009,4 @@ var cutByResolution = function (str) {
|
|||
</div>
|
||||
|
||||
<div id="workMonitorContent" class="innerContent">
|
||||
</div></script></head><body><nav class="navbar"><div class="primary"><div class="navlogo"><a class="logo big" href="#"><img class="arangodbLogo" src="img/arangodb_logo_big.png"></a> <a class="logo small" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"></a> <a class="version"><span>VERSION:</span><span id="currentVersion"></span></a></div><div class="statmenu" id="statisticBar"></div><div class="navmenu" id="navigationBar"></div></div></nav><div class="bodyWrapper"><div class="centralRow"><div id="navbar2" class="navbarWrapper secondary"><div class="subnavmenu" id="subNavigationBar"></div></div><div class="resizecontainer contentWrapper"><div id="content" class="centralContent"></div><footer class="footer"><div id="footerBar"></div></footer></div></div></div><div id="modalPlaceholder"></div><div id="progressPlaceholder" style="display:none"></div><div id="spotlightPlaceholder" style="display:none"></div><div class="arangoFrame" style=""><div class="outerDiv"><div class="innerDiv"></div></div></div><script src="libs.js?version=1462192843595"></script><script src="app.js?version=1462192843595"></script></body></html>
|
||||
</div></script></head><body><nav class="navbar"><div class="primary"><div class="navlogo"><a class="logo big" href="#"><img class="arangodbLogo" src="img/arangodb_logo_big.png"></a> <a class="logo small" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"></a> <a class="version"><span>VERSION:</span><span id="currentVersion"></span></a></div><div class="statmenu" id="statisticBar"></div><div class="navmenu" id="navigationBar"></div></div></nav><div class="bodyWrapper"><div class="centralRow"><div id="navbar2" class="navbarWrapper secondary"><div class="subnavmenu" id="subNavigationBar"></div></div><div class="resizecontainer contentWrapper"><div id="loadingScreen" class="loadingScreen" style="display: none"><i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw margin-bottom"></i> <span class="sr-only">Loading...</span></div><div id="content" class="centralContent"></div><footer class="footer"><div id="footerBar"></div></footer></div></div></div><div id="modalPlaceholder"></div><div id="progressPlaceholder" style="display:none"></div><div id="spotlightPlaceholder" style="display:none"></div><div id="offlinePlaceholder" style="display:none"><div class="offline-div"><div class="pure-u"><div class="pure-u-1-4"></div><div class="pure-u-1-2 offline-window"><div class="offline-header"><h3>You have been disconnected from the server</h3></div><div class="offline-body"><p>The connection to the server has been lost. The server may be under heavy load.</p><p>Trying to reconnect in <span id="offlineSeconds">10</span> seconds.</p><p class="animation_state"><span><button class="button-success">Reconnect now</button></span></p></div></div><div class="pure-u-1-4"></div></div></div></div><div class="arangoFrame" style=""><div class="outerDiv"><div class="innerDiv"></div></div></div><script src="libs.js?version=1462290447850"></script><script src="app.js?version=1462290447850"></script></body></html>
|
Binary file not shown.
|
@ -1613,8 +1613,13 @@ if (list.length > 0) {
|
|||
<form id="loginForm">
|
||||
<input class="login-input" placeholder="username" id="loginUsername" type="text" name="username"><i class="fa fa-user"></i>
|
||||
<input class="login-input" placeholder="password" id="loginPassword" type="password" name="password"><i class="fa fa-lock"></i>
|
||||
<input class="login-input" placeholder="database" id="loginDatabase" type="text" name="database"><i class="fa fa-database"></i>
|
||||
<button id="submitLogin" class="button-success pull-right">Login</button>
|
||||
|
||||
<i class="fa fa-database"></i>
|
||||
<select id="loginDatabase" disabled>
|
||||
<option>database</option>
|
||||
</select>
|
||||
|
||||
<button id="submitLogin" class="button-success pull-right" disabled>Login</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3302,29 +3307,59 @@ var cutByResolution = function (str) {
|
|||
</div>
|
||||
|
||||
<div class="resizecontainer contentWrapper">
|
||||
|
||||
<div id="loadingScreen" class="loadingScreen" style="display: none">
|
||||
<i class="fa fa-circle-o-notch fa-spin fa-3x fa-fw margin-bottom"></i>
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
|
||||
<div id="content" class="centralContent"></div>
|
||||
|
||||
<footer class="footer">
|
||||
<div id="footerBar"></div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="modalPlaceholder">
|
||||
</div>
|
||||
<div id="modalPlaceholder">
|
||||
</div>
|
||||
|
||||
<div id="progressPlaceholder" style="display:none">
|
||||
</div>
|
||||
<div id="progressPlaceholder" style="display:none">
|
||||
</div>
|
||||
|
||||
<div id="spotlightPlaceholder" style="display:none">
|
||||
</div>
|
||||
<div id="spotlightPlaceholder" style="display:none">
|
||||
</div>
|
||||
|
||||
<div id="offlinePlaceholder" style="display:none">
|
||||
<div class="offline-div">
|
||||
|
||||
<div class="pure-u">
|
||||
|
||||
<div class="pure-u-1-4"></div>
|
||||
<div class="pure-u-1-2 offline-window">
|
||||
<div class="offline-header">
|
||||
<h3>You have been disconnected from the server</h3>
|
||||
</div>
|
||||
<div class="offline-body">
|
||||
<p>The connection to the server has been lost. The server may be under heavy load.</p>
|
||||
<p>Trying to reconnect in <span id="offlineSeconds">10</span> seconds.</p>
|
||||
<p class="animation_state">
|
||||
<span><button class="button-success">Reconnect now</button></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pure-u-1-4"></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="arangoFrame" style="">
|
||||
<div class="outerDiv">
|
||||
|
@ -3332,8 +3367,8 @@ var cutByResolution = function (str) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script src="libs.js?version=1462192843595"></script>
|
||||
<script src="app.js?version=1462192843595"></script>
|
||||
<script src="libs.js?version=1462290447850"></script>
|
||||
<script src="app.js?version=1462290447850"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
<script src="libs.js?version=1462192843595"></script>
|
||||
<script src="app.js?version=1462192843595"></script>
|
||||
<script src="libs.js?version=1462290447850"></script>
|
||||
<script src="app.js?version=1462290447850"></script>
|
||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -20,6 +20,60 @@ body {
|
|||
right: 0; }
|
||||
body .centralRow {
|
||||
position: relative; }
|
||||
body .loadingScreen {
|
||||
background-color: #fff;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding-top: 100px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 102px;
|
||||
z-index: 100; }
|
||||
body .loadingScreen span {
|
||||
display: inline-block;
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
width: 100%; }
|
||||
body .loadingScreen i {
|
||||
width: 100%; }
|
||||
body #offlinePlaceholder {
|
||||
background: rgba(64, 74, 83, 0.8);
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 9999; }
|
||||
body #offlinePlaceholder .offline-div {
|
||||
overflow: auto;
|
||||
position: fixed;
|
||||
top: 20%;
|
||||
width: 100%;
|
||||
z-index: 1050; }
|
||||
body #offlinePlaceholder .offline-div h3 {
|
||||
font-weight: 300; }
|
||||
body #offlinePlaceholder .offline-div p {
|
||||
font-weight: 300; }
|
||||
body #offlinePlaceholder .offline-div .pure-u {
|
||||
width: 100%; }
|
||||
body #offlinePlaceholder .offline-div .offline-window {
|
||||
background: #fff;
|
||||
border-radius: 3px; }
|
||||
body #offlinePlaceholder .offline-div .offline-window .offline-header {
|
||||
padding-top: 10px;
|
||||
text-align: center; }
|
||||
body #offlinePlaceholder .offline-div .offline-window .offline-body {
|
||||
padding-bottom: 20px;
|
||||
padding-top: 0; }
|
||||
body #offlinePlaceholder .offline-div .offline-window .offline-body .animation_state {
|
||||
padding-top: 20px; }
|
||||
body #offlinePlaceholder .offline-div .offline-window .offline-body > p {
|
||||
text-align: center;
|
||||
margin-bottom: 0; }
|
||||
body #offlinePlaceholder .offline-div .offline-window .offline-header,
|
||||
body #offlinePlaceholder .offline-div .offline-window .offline-body {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px; }
|
||||
|
||||
body,
|
||||
input,
|
||||
|
@ -2113,12 +2167,54 @@ textarea,
|
|||
.dropdownImport.headerDropdown input[type=checkbox].css-checkbox label.css-label, .search-submit-icon, .gv-search-submit-icon, .fixedDropdown .notificationItem i, .fullNotification:hover, .contentTables tr.contentRowInactive a, .arango-tab a, .arango-tab li, .pagination-line li a, .link > line, .node, .edit-index-table .icon_arangodb_roundminus {
|
||||
cursor: pointer; }
|
||||
|
||||
.arangoToolbar span.clickable:hover {
|
||||
.arangoToolbar span.clickable:hover, .login-window button {
|
||||
-moz-transition: all .2s ease-in;
|
||||
-o-transition: all .2s ease-in;
|
||||
-webkit-transition: all .2s ease-in;
|
||||
transition: all .2s ease-in; }
|
||||
|
||||
.login-window select {
|
||||
-webkit-appearance: none;
|
||||
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='50px' height='50px'><polyline points='46.139,15.518 25.166,36.49 4.193,15.519'/></svg>");
|
||||
background-color: #f2f2f2;
|
||||
background-position: right 10px top 12px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px 16px;
|
||||
border: 0;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
color: #000;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
height: 40px;
|
||||
line-height: initial;
|
||||
outline: 0;
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
-moz-transition: .3s ease all;
|
||||
-ms-transition: .3s ease all;
|
||||
-o-transition: .3s ease all;
|
||||
-webkit-transition: .3s ease all;
|
||||
transition: .3s ease all;
|
||||
width: 100%; }
|
||||
.login-window select.blue {
|
||||
background-color: #3498DB; }
|
||||
.login-window select.blue:hover {
|
||||
background-color: #2980B9; }
|
||||
.login-window select.green {
|
||||
background-color: #2ECC71; }
|
||||
.login-window select.green:hover {
|
||||
background-color: #27AE60; }
|
||||
.login-window select.red {
|
||||
background-color: #E74C3C; }
|
||||
.login-window select.red:hover {
|
||||
background-color: #C0392B; }
|
||||
.login-window select:disabled {
|
||||
opacity: .5; }
|
||||
.login-window select:focus, .login-window select:active {
|
||||
border: 0;
|
||||
outline: 0; }
|
||||
|
||||
.subnavmenu .infoEntry:hover .info {
|
||||
-webkit-touch-callout: none;
|
||||
-khtml-user-select: none;
|
||||
|
@ -6723,6 +6819,9 @@ div.headerBar {
|
|||
position: relative;
|
||||
top: 100px;
|
||||
width: 350px; }
|
||||
.login-window select {
|
||||
margin-bottom: 30px;
|
||||
padding-left: 35px; }
|
||||
.login-window .login-logo-round {
|
||||
margin-bottom: 25px;
|
||||
margin-top: 10px; }
|
||||
|
@ -6735,11 +6834,8 @@ div.headerBar {
|
|||
float: left;
|
||||
font-size: 14pt;
|
||||
left: 30px;
|
||||
margin-right: 44px;
|
||||
margin-top: 11px;
|
||||
position: absolute; }
|
||||
.login-window .fa.fa-lock {
|
||||
right: -9px; }
|
||||
.login-window .wrong-credentials {
|
||||
color: #e74c3c;
|
||||
margin-top: -30px;
|
||||
|
@ -6749,7 +6845,7 @@ div.headerBar {
|
|||
.login-window .login-input {
|
||||
background: #f2f2f2 !important;
|
||||
background-color: #f2f2f2 !important;
|
||||
border: 0;
|
||||
border: 2px #f2f2f2 !important;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
border-top-left-radius: 3px;
|
||||
|
@ -6763,7 +6859,7 @@ div.headerBar {
|
|||
padding-left: 35px;
|
||||
width: 100%; }
|
||||
.login-window .form-error {
|
||||
border: 1px solid #e74c3c !important; }
|
||||
border: 2px solid #e74c3c !important; }
|
||||
.login-window button {
|
||||
height: 40px;
|
||||
width: 100%; }
|
||||
|
|
Binary file not shown.
|
@ -31,15 +31,14 @@ window.ArangoUsers = Backbone.Collection.extend({
|
|||
return a > b ? 1 : a < b ? -1 : 0;
|
||||
},
|
||||
|
||||
login: function (username, password, database, callback) {
|
||||
login: function (username, password, callback) {
|
||||
var self = this;
|
||||
|
||||
$.ajax("login", {
|
||||
method: "POST",
|
||||
data: JSON.stringify({
|
||||
username: username,
|
||||
password: password,
|
||||
database: database
|
||||
password: password
|
||||
}),
|
||||
dataType: "json"
|
||||
}).success(
|
||||
|
|
|
@ -18,8 +18,13 @@
|
|||
<form id="loginForm">
|
||||
<input class="login-input" placeholder="username" id="loginUsername" type="text" name="username"><i class="fa fa-user"></i>
|
||||
<input class="login-input" placeholder="password" id="loginPassword" type="password" name="password"><i class="fa fa-lock"></i>
|
||||
<input class="login-input" placeholder="database" id="loginDatabase" type="text" name="database"><i class="fa fa-database"></i>
|
||||
<button id="submitLogin" class="button-success pull-right">Login</button>
|
||||
|
||||
<i class="fa fa-database"></i>
|
||||
<select id="loginDatabase" disabled>
|
||||
<option>database</option>
|
||||
</select>
|
||||
|
||||
<button id="submitLogin" class="button-success pull-right" disabled>Login</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*jshint browser: true */
|
||||
/*jshint unused: false */
|
||||
/*global Backbone, EJS, arangoHelper, window, setTimeout, $, templateEngine*/
|
||||
/*global Backbone, document, EJS, _, arangoHelper, window, setTimeout, $, templateEngine*/
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
|
@ -8,18 +8,19 @@
|
|||
el: '#content',
|
||||
el2: '.header',
|
||||
el3: '.footer',
|
||||
loggedIn: false,
|
||||
|
||||
events: {
|
||||
"submit #loginForm" : "login",
|
||||
"keypress #loginForm input" : "clear",
|
||||
"change #loginForm input" : "clear"
|
||||
"submit #loginForm" : "goTo",
|
||||
"keyup #loginForm input" : "validate",
|
||||
"change #loginForm input" : "validate",
|
||||
"focusout #loginForm input" : "validate"
|
||||
},
|
||||
|
||||
template: templateEngine.createTemplate("loginView.ejs"),
|
||||
|
||||
render: function() {
|
||||
$(this.el).html(this.template.render({}));
|
||||
$('#loginDatabase').val('_system');
|
||||
$(this.el2).hide();
|
||||
$(this.el3).hide();
|
||||
|
||||
|
@ -33,50 +34,70 @@
|
|||
$('.wrong-credentials').hide();
|
||||
},
|
||||
|
||||
login: function (e) {
|
||||
e.preventDefault();
|
||||
validate: function(event) {
|
||||
this.clear();
|
||||
var self = this;
|
||||
|
||||
var username = $('#loginUsername').val();
|
||||
var password = $('#loginPassword').val();
|
||||
var database = $('#loginDatabase').val();
|
||||
|
||||
if (!username) {
|
||||
//Heiko: Form-Validator - please fill out all req. fields
|
||||
//do not send unneccessary requests if no user is given
|
||||
return;
|
||||
}
|
||||
|
||||
var callback = function(error, username) {
|
||||
var callback2 = function(error) {
|
||||
if (error) {
|
||||
arangoHelper.arangoError("User", "Could not fetch user settings");
|
||||
}
|
||||
};
|
||||
|
||||
console.log(event);
|
||||
var callback = function(error) {
|
||||
if (error) {
|
||||
$('#loginForm input').addClass("form-error");
|
||||
$('.wrong-credentials').show();
|
||||
if (event.type === 'focusout') {
|
||||
//$('#loginForm input').addClass("form-error");
|
||||
$('.wrong-credentials').show();
|
||||
}
|
||||
}
|
||||
else {
|
||||
var currentDB = window.location.pathname.split('/')[2];
|
||||
if (currentDB !== database) {
|
||||
var path = window.location.origin + window.location.pathname.replace(currentDB, database);
|
||||
window.location.href = path;
|
||||
$(this.el2).show();
|
||||
$(this.el3).show();
|
||||
$('#currentUser').text(username);
|
||||
this.collection.loadUserSettings(callback2);
|
||||
return;
|
||||
}
|
||||
$('.wrong-credentials').hide();
|
||||
|
||||
$(this.el2).show();
|
||||
$(this.el3).show();
|
||||
window.location.reload();
|
||||
$('#currentUser').text(username);
|
||||
this.collection.loadUserSettings(callback2);
|
||||
if (!self.loggedIn) {
|
||||
self.loggedIn = true;
|
||||
//get list of allowed dbs
|
||||
$.ajax("/_api/database/user").success(function(data) {
|
||||
//enable db select and login button
|
||||
$('#loginDatabase').prop('disabled', false);
|
||||
$('#submitLogin').prop('disabled', false);
|
||||
$('#loginDatabase').html('');
|
||||
//fill select with allowed dbs
|
||||
_.each(data.result, function(db) {
|
||||
$('#loginDatabase').append(
|
||||
'<option>' + db + '</option>'
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
this.collection.login(username, password, database, callback);
|
||||
this.collection.login(username, password, callback);
|
||||
|
||||
},
|
||||
|
||||
goTo: function (e) {
|
||||
e.preventDefault();
|
||||
var username = $('#loginUsername').val();
|
||||
var database = $('#loginDatabase').val();
|
||||
|
||||
var callback2 = function(error) {
|
||||
if (error) {
|
||||
arangoHelper.arangoError("User", "Could not fetch user settings");
|
||||
}
|
||||
};
|
||||
|
||||
var currentDB = window.location.pathname.split('/')[2];
|
||||
var path = window.location.origin + window.location.pathname.replace(currentDB, database);
|
||||
window.location.href = path;
|
||||
$(this.el2).show();
|
||||
$(this.el3).show();
|
||||
$('#currentUser').text(username);
|
||||
this.collection.loadUserSettings(callback2);
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -32,6 +32,42 @@
|
|||
transition: all .2s ease-in;
|
||||
}
|
||||
|
||||
%flat-select {
|
||||
-webkit-appearance: none;
|
||||
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='50px' height='50px'><polyline points='46.139,15.518 25.166,36.49 4.193,15.519'/></svg>");
|
||||
background-color: $c-login-grey;
|
||||
background-position: right 10px top 12px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px 16px;
|
||||
border: 0;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
color: $c-black;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
height: 40px;
|
||||
line-height: initial;
|
||||
outline: 0;
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
-moz-transition: .3s ease all;
|
||||
-ms-transition: .3s ease all;
|
||||
-o-transition: .3s ease all;
|
||||
-webkit-transition: .3s ease all;
|
||||
transition: .3s ease all;
|
||||
width: 100%;
|
||||
|
||||
&:disabled {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
%noselect {
|
||||
-webkit-touch-callout: none;
|
||||
-khtml-user-select: none;
|
||||
|
|
|
@ -38,6 +38,12 @@
|
|||
top: 100px;
|
||||
width: 350px;
|
||||
|
||||
select {
|
||||
@extend %flat-select;
|
||||
margin-bottom: 30px;
|
||||
padding-left: 35px;
|
||||
}
|
||||
|
||||
.login-logo-round {
|
||||
margin-bottom: 25px;
|
||||
margin-top: 10px;
|
||||
|
@ -54,13 +60,8 @@
|
|||
float: left;
|
||||
font-size: 14pt;
|
||||
left: 30px;
|
||||
margin-right: 44px;
|
||||
margin-top: 11px;
|
||||
position: absolute;
|
||||
|
||||
&.fa-lock {
|
||||
right: -9px;
|
||||
}
|
||||
}
|
||||
|
||||
.wrong-credentials {
|
||||
|
@ -77,7 +78,7 @@
|
|||
@extend %inputs;
|
||||
background: $c-login-grey !important;
|
||||
background-color: $c-login-grey !important;
|
||||
border: 0;
|
||||
border: 2px $c-login-grey !important;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
border-top-left-radius: 3px;
|
||||
|
@ -93,10 +94,11 @@
|
|||
}
|
||||
|
||||
.form-error {
|
||||
border: 1px solid $c-negative !important;
|
||||
border: 2px solid $c-negative !important;
|
||||
}
|
||||
|
||||
button {
|
||||
@extend %animated;
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -85,6 +85,8 @@ const optionsDocumentation = [
|
|||
' - `skipTimeCritical`: if set to true, time critical tests will be skipped.',
|
||||
' - `skipNondeterministic`: if set, nondeterministic tests are skipped.',
|
||||
' - `skipShebang`: if set, the shebang tests are skipped.',
|
||||
' - `testBuckets`: split tests in to buckets and execute on, for example',
|
||||
' 10/2 will split into 10 buckets and execute the third bucket.',
|
||||
'',
|
||||
' - `onlyNightly`: execute only the nightly tests',
|
||||
' - `loopEternal`: to loop one test over and over.',
|
||||
|
@ -163,6 +165,7 @@ const optionsDefaults = {
|
|||
"skipSsl": false,
|
||||
"skipTimeCritical": false,
|
||||
"test": undefined,
|
||||
"testBuckets": undefined,
|
||||
"username": "root",
|
||||
"valgrind": false,
|
||||
"valgrindFileBase": "",
|
||||
|
@ -455,6 +458,44 @@ function analyzeCoreDumpWindows(instanceInfo) {
|
|||
executeExternalAndWait("cdb", args);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the bad has happened, tell it the user and try to gather more
|
||||
/// information about the incident.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
function analyzeServerCrash(arangod, options, checkStr)
|
||||
{
|
||||
serverCrashed = true;
|
||||
const storeArangodPath = "/var/tmp/arangod_" + arangod.pid;
|
||||
|
||||
print(RED +
|
||||
"during: " + checkStr + ": Core dump written; copying arangod to " +
|
||||
arangod.rootDir + " for later analysis.\n" +
|
||||
"Server shut down with :\n" +
|
||||
yaml.safeDump(arangod) +
|
||||
"marking build as crashy.");
|
||||
|
||||
let corePath = (options.coreDirectory === "") ?
|
||||
"core" :
|
||||
options.coreDirectory + "/core*" + arangod.pid + "*'";
|
||||
|
||||
arangod.exitStatus.gdbHint = "Run debugger with 'gdb " +
|
||||
storeArangodPath + " " + corePath;
|
||||
|
||||
if (platform.substr(0, 3) === 'win') {
|
||||
// Windows: wait for procdump to do its job...
|
||||
statusExternal(arangod.monitor, true);
|
||||
analyzeCoreDumpWindows(arangod);
|
||||
} else {
|
||||
fs.copyFile("bin/arangod", storeArangodPath);
|
||||
analyzeCoreDump(arangod, options, storeArangodPath, arangod.pid);
|
||||
}
|
||||
|
||||
print(RESET);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief periodic checks whether spawned arangod processes are still alive
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
function checkArangoAlive(arangod, options) {
|
||||
if (arangod.hasOwnProperty('exitStatus')) {
|
||||
return false;
|
||||
|
@ -468,40 +509,16 @@ function checkArangoAlive(arangod, options) {
|
|||
print(arangod);
|
||||
|
||||
if (res.hasOwnProperty('signal') &&
|
||||
((res.signal === 11) ||
|
||||
(res.signal === 6) ||
|
||||
// Windows sometimes has random numbers in signal...
|
||||
(platform.substr(0, 3) === 'win')
|
||||
)
|
||||
) {
|
||||
const storeArangodPath = "/var/tmp/arangod_" + arangod.pid;
|
||||
|
||||
print("Core dump written; copying arangod to " +
|
||||
arangod.rootDir + " for later analysis.");
|
||||
|
||||
let corePath = (options.coreDirectory === "") ?
|
||||
"core" :
|
||||
options.coreDirectory + "/core*" + arangod.pid + "*'";
|
||||
|
||||
res.gdbHint = "Run debugger with 'gdb " +
|
||||
storeArangodPath + " " + corePath;
|
||||
|
||||
if (platform.substr(0, 3) === 'win') {
|
||||
// Windows: wait for procdump to do its job...
|
||||
statusExternal(arangod.monitor, true);
|
||||
analyzeCoreDumpWindows(arangod);
|
||||
} else {
|
||||
fs.copyFile("bin/arangod", storeArangodPath);
|
||||
analyzeCoreDump(arangod, options, storeArangodPath, arangod.pid);
|
||||
}
|
||||
((res.signal === 11) ||
|
||||
(res.signal === 6) ||
|
||||
// Windows sometimes has random numbers in signal...
|
||||
(platform.substr(0, 3) === 'win')
|
||||
)
|
||||
) {
|
||||
arangod.exitStatus = res;
|
||||
analyzeServerCrash(arangod, options, "health Check");
|
||||
}
|
||||
|
||||
arangod.exitStatus = res;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
print("marking crashy");
|
||||
serverCrashed = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -891,10 +908,6 @@ function executeValgrind(cmd, args, options, valgrindTest) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function executeAndWait(cmd, args, options, valgrindTest) {
|
||||
if (options.extremeVerbosity) {
|
||||
print("executeAndWait: cmd =", cmd, "args =", args);
|
||||
}
|
||||
|
||||
if (valgrindTest && options.valgrind) {
|
||||
let valgrindOpts = {};
|
||||
|
||||
|
@ -920,7 +933,17 @@ function executeAndWait(cmd, args, options, valgrindTest) {
|
|||
cmd = options.valgrind;
|
||||
}
|
||||
|
||||
if (options.extremeVerbosity) {
|
||||
print("executeAndWait: cmd =", cmd, "args =", args);
|
||||
}
|
||||
|
||||
const startTime = time();
|
||||
if ((typeof(cmd) !== "string") || (cmd === 'true') || (cmd === 'false')) {
|
||||
return {
|
||||
status: false,
|
||||
message: "true or false as binary name for test cmd =" + cmd + "args =" + args
|
||||
};
|
||||
}
|
||||
const res = executeExternalAndWait(cmd, args);
|
||||
const deltaTime = time() - startTime;
|
||||
|
||||
|
@ -1187,16 +1210,7 @@ function shutdownInstance(instanceInfo, options) {
|
|||
}
|
||||
} else if (arangod.exitStatus.status !== "TERMINATED") {
|
||||
if (arangod.exitStatus.hasOwnProperty('signal')) {
|
||||
print("Server shut down with : " +
|
||||
yaml.safeDump(arangod.exitStatus) +
|
||||
" marking build as crashy.");
|
||||
|
||||
serverCrashed = true;
|
||||
return false;
|
||||
}
|
||||
if (platform.substr(0, 3) === 'win') {
|
||||
// Windows: wait for procdump to do its job...
|
||||
statusExternal(arangod.monitor, true);
|
||||
analyzeServerCrash(arangod, options, "instance Shutdown");
|
||||
}
|
||||
} else {
|
||||
print("Server shutdown: Success.");
|
||||
|
@ -1807,6 +1821,44 @@ function filterTestcaseByOptions(testname, options, whichFilter) {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief split into buckets
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function splitBuckets(options, cases) {
|
||||
if (!options.testBuckets || cases.length === 0) {
|
||||
return cases;
|
||||
}
|
||||
|
||||
let m = cases.length;
|
||||
let n = options.testBuckets.split("/");
|
||||
let r = parseInt(n[0]);
|
||||
let s = parseInt(n[1]);
|
||||
|
||||
if (r < 1) {
|
||||
r = 1;
|
||||
}
|
||||
|
||||
if (r === 1) {
|
||||
return cases;
|
||||
}
|
||||
|
||||
if (s < 0) {
|
||||
s = 0;
|
||||
}
|
||||
if (r <= s) {
|
||||
s = r - 1;
|
||||
}
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let i = s % m; i < cases.length; i = i + r) {
|
||||
result.push(cases[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test functions for all
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2358,7 +2410,7 @@ testFuncs.authentication_parameters = function(options) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function locateBoostTest(name) {
|
||||
var file = fs.join(UNITTESTS_DIR,name);
|
||||
var file = fs.join(UNITTESTS_DIR, name);
|
||||
if (platform.substr(0, 3) === 'win') {
|
||||
file += ".exe";
|
||||
}
|
||||
|
@ -2379,11 +2431,11 @@ testFuncs.boost = function(options) {
|
|||
|
||||
if (run !== "") {
|
||||
results.basics = executeAndWait(run, args, options, "basics");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
results.basics = {
|
||||
status: false,
|
||||
message: "binary 'basics_suite' not found"};
|
||||
message: "binary 'basics_suite' not found"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2392,11 +2444,11 @@ testFuncs.boost = function(options) {
|
|||
|
||||
if (run !== "") {
|
||||
results.geo_suite = executeAndWait(run, args, options, "geo_suite");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
results.geo_suite = {
|
||||
status: false,
|
||||
message: "binary 'geo_suite' not found"};
|
||||
message: "binary 'geo_suite' not found"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3322,15 +3374,21 @@ testFuncs.shell_server = function(options) {
|
|||
testFuncs.shell_server_aql = function(options) {
|
||||
findTests();
|
||||
|
||||
let cases;
|
||||
let name;
|
||||
|
||||
if (!options.skipAql) {
|
||||
if (options.skipRanges) {
|
||||
return performTests(options, testsCases.server_aql,
|
||||
'shell_server_aql_skipranges');
|
||||
cases = testsCases.server_aql;
|
||||
name = 'shell_server_aql_skipranges';
|
||||
} else {
|
||||
return performTests(options,
|
||||
testsCases.server_aql.concat(testsCases.server_aql_extended),
|
||||
'shell_server_aql');
|
||||
cases = testsCases.server_aql.concat(testsCases.server_aql_extended);
|
||||
name = 'shell_server_aql';
|
||||
}
|
||||
|
||||
cases = splitBuckets(options, cases);
|
||||
|
||||
return performTests(options, cases, name);
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -156,80 +156,6 @@ function addShardFollower(endpoint, shard) {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get values from Plan or Current by a prefix
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function getByPrefix (values, prefix) {
|
||||
var result = { };
|
||||
var a;
|
||||
var n = prefix.length;
|
||||
|
||||
for (a in values) {
|
||||
if (values.hasOwnProperty(a)) {
|
||||
if (a.substr(0, n) === prefix) {
|
||||
result[a.substr(n)] = values[a];
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get values from Plan or Current by a prefix
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function getByPrefix3d (values, prefix) {
|
||||
var result = { };
|
||||
var a;
|
||||
var n = prefix.length;
|
||||
|
||||
for (a in values) {
|
||||
if (values.hasOwnProperty(a)) {
|
||||
if (a.substr(0, n) === prefix) {
|
||||
var key = a.substr(n);
|
||||
var parts = key.split('/');
|
||||
if (parts.length >= 2) {
|
||||
if (! result.hasOwnProperty(parts[0])) {
|
||||
result[parts[0]] = { };
|
||||
}
|
||||
result[parts[0]][parts[1]] = values[a];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get values from Plan or Current by a prefix
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function getByPrefix4d (values, prefix) {
|
||||
var result = { };
|
||||
var a;
|
||||
var n = prefix.length;
|
||||
|
||||
for (a in values) {
|
||||
if (values.hasOwnProperty(a)) {
|
||||
if (a.substr(0, n) === prefix) {
|
||||
var key = a.substr(n);
|
||||
var parts = key.split('/');
|
||||
if (parts.length >= 3) {
|
||||
if (! result.hasOwnProperty(parts[0])) {
|
||||
result[parts[0]] = { };
|
||||
}
|
||||
if (! result[parts[0]].hasOwnProperty(parts[1])) {
|
||||
result[parts[0]][parts[1]] = { };
|
||||
}
|
||||
result[parts[0]][parts[1]][parts[2]] = values[a];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookup for 4-dimensional nested dictionary data
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*jshint globalstrict:false, strict:false, maxlen: 500 */
|
||||
/*global assertEqual, AQL_EXECUTE */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests for Ahuacatl, skiplist index queries
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2016 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 Michael Hackstein
|
||||
/// @author Copyright 2016, ArangoDB GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var internal = require("internal");
|
||||
var jsunity = require("jsunity");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function ahuacatlSkiplistOverlappingTestSuite () {
|
||||
const rulesDisabled = {optimizer: {rules: ["-all"]}};
|
||||
const rulesEnabled = {optimizer: {rules: [""]}};
|
||||
|
||||
let skiplist;
|
||||
|
||||
return {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set up
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
setUp : function () {
|
||||
internal.db._drop("UnitTestsAhuacatlSkiplist");
|
||||
skiplist = internal.db._create("UnitTestsAhuacatlSkiplist");
|
||||
skiplist.ensureSkiplist("a");
|
||||
|
||||
for (var i = 0; i < 10000; ++i) {
|
||||
skiplist.save({a: i});
|
||||
}
|
||||
},
|
||||
|
||||
tearDown : function () {
|
||||
internal.db._drop("UnitTestsAhuacatlSkiplist");
|
||||
},
|
||||
|
||||
testLargeOverlappingRanges : function () {
|
||||
let query = `FOR x IN @@cn FILTER (1000 <= x.a && x.a < 2500)
|
||||
|| (1500 <= x.a && x.a < 3000)
|
||||
RETURN x`;
|
||||
|
||||
let bindVars = {"@cn": skiplist.name()};
|
||||
assertEqual(2000, AQL_EXECUTE(query, bindVars, rulesDisabled).json.length);
|
||||
assertEqual(2000, AQL_EXECUTE(query, bindVars, rulesEnabled).json.length);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes the test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
jsunity.run(ahuacatlSkiplistOverlappingTestSuite);
|
||||
|
||||
return jsunity.done();
|
||||
|
|
@ -38,7 +38,6 @@ var jsunity = require("jsunity");
|
|||
function AgencySuite () {
|
||||
'use strict';
|
||||
var agency = ArangoAgency;
|
||||
var oldPrefix = agency.prefix(true);
|
||||
|
||||
var cleanupLocks = function () {
|
||||
agency.set("UnitTestsAgency/Target/Lock", "UNLOCKED");
|
||||
|
@ -49,8 +48,8 @@ function AgencySuite () {
|
|||
return {
|
||||
|
||||
setUp : function () {
|
||||
agency.setPrefix("UnitTestsAgency");
|
||||
assertEqual("UnitTestsAgency", agency.prefix(true));
|
||||
//agency.setPrefix("UnitTestsAgency");
|
||||
//assertEqual("UnitTestsAgency", agency.prefix(true));
|
||||
|
||||
try {
|
||||
agency.remove("UnitTestsAgency", true);
|
||||
|
@ -70,8 +69,8 @@ function AgencySuite () {
|
|||
catch (err) {
|
||||
}
|
||||
|
||||
agency.setPrefix(oldPrefix);
|
||||
assertEqual(oldPrefix, agency.prefix(true));
|
||||
//agency.setPrefix(oldPrefix);
|
||||
//assertEqual(oldPrefix, agency.prefix(true));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -321,39 +320,44 @@ function AgencySuite () {
|
|||
testSet : function () {
|
||||
// insert
|
||||
agency.set("UnitTestsAgency/foo", "test1");
|
||||
var values = agency.get("UnitTestsAgency/foo").arango.UnitTestsAgency.foo;
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/foo"));
|
||||
assertEqual(values["UnitTestsAgency/foo"], "test1");
|
||||
var values = agency.get("UnitTestsAgency/foo");
|
||||
assertTrue(values.hasOwnProperty("arango"));
|
||||
assertTrue(values.arango.hasOwnProperty("UnitTestsAgency"));
|
||||
assertTrue(values.arango.UnitTestsAgency.hasOwnProperty("foo"));
|
||||
assertEqual(values.arango.UnitTestsAgency.foo, "test1");
|
||||
|
||||
// overwrite
|
||||
agency.set("UnitTestsAgency/foo", "test2", 2);
|
||||
values = agency.get("UnitTestsAgency/foo").arango.UnitTestsAgency.foo;
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/foo"));
|
||||
assertEqual(values["UnitTestsAgency/foo"], "test2");
|
||||
values = agency.get("UnitTestsAgency/foo");
|
||||
assertTrue(values.hasOwnProperty("arango"));
|
||||
assertTrue(values.arango.hasOwnProperty("UnitTestsAgency"));
|
||||
assertTrue(values.arango.UnitTestsAgency.hasOwnProperty("foo"));
|
||||
assertEqual(values.arango.UnitTestsAgency.foo, "test2");
|
||||
|
||||
assertTrue(agency.remove("UnitTestsAgency/foo"));
|
||||
|
||||
// re-insert
|
||||
agency.set("UnitTestsAgency/foo", "test3");
|
||||
values = agency.get("UnitTestsAgency/foo").arango.UnitTestsAgency.foo;
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/foo"));
|
||||
assertEqual(values["UnitTestsAgency/foo"], "test3");
|
||||
values = agency.get("UnitTestsAgency/foo");
|
||||
assertTrue(values.hasOwnProperty("arango"));
|
||||
assertTrue(values.arango.hasOwnProperty("UnitTestsAgency"));
|
||||
assertTrue(values.arango.UnitTestsAgency.hasOwnProperty("foo"));
|
||||
assertEqual(values.arango.UnitTestsAgency.foo, "test3");
|
||||
|
||||
// update with ttl
|
||||
agency.set("UnitTestsAgency/foo", "test4", 2);
|
||||
values = agency.get("UnitTestsAgency/foo").arango.UnitTestsAgency.foo;
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/foo"));
|
||||
assertEqual(values["UnitTestsAgency/foo"], "test4");
|
||||
values = agency.get("UnitTestsAgency/foo");
|
||||
assertTrue(values.hasOwnProperty("arango"));
|
||||
assertTrue(values.arango.hasOwnProperty("UnitTestsAgency"));
|
||||
assertTrue(values.arango.UnitTestsAgency.hasOwnProperty("foo"));
|
||||
assertEqual(values.arango.UnitTestsAgency.foo, "test4");
|
||||
|
||||
require("internal").wait(3);
|
||||
|
||||
try {
|
||||
values = agency.get("UnitTestsAgency/foo").arango.UnitTestsAgency.foo;
|
||||
fail();
|
||||
}
|
||||
catch (e) {
|
||||
assertEqual(404, e.code);
|
||||
}
|
||||
values = agency.get("UnitTestsAgency/foo");
|
||||
assertTrue(values.hasOwnProperty("arango"));
|
||||
assertTrue(values.arango.hasOwnProperty("UnitTestsAgency"));
|
||||
assertFalse(values.arango.UnitTestsAgency.hasOwnProperty("foo"));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -470,16 +474,16 @@ function AgencySuite () {
|
|||
|
||||
assertTrue(agency.remove("UnitTestsAgency/1", true));
|
||||
|
||||
try {
|
||||
agency.get("UnitTestsAgency/1", true).arango.UnitTestsAgency["1"];
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
// key not found
|
||||
}
|
||||
var values = agency.get("UnitTestsAgency/1", true);
|
||||
assertTrue(values.hasOwnProperty("arango"));
|
||||
assertTrue(values.arango.hasOwnProperty("UnitTestsAgency"));
|
||||
assertFalse(values.arango.UnitTestsAgency.hasOwnProperty("1"));
|
||||
|
||||
var values = agency.get("UnitTestsAgency/2", true).arango.UnitTestsAgency.2;
|
||||
assertEqual({ "UnitTestsAgency/2/1/foo" : "baz" }, values);
|
||||
values = agency.get("UnitTestsAgency/2", true);
|
||||
assertTrue(values.hasOwnProperty("arango"));
|
||||
assertTrue(values.arango.hasOwnProperty("UnitTestsAgency"));
|
||||
assertTrue(values.arango.UnitTestsAgency.hasOwnProperty("2"));
|
||||
assertEqual(values.arango.UnitTestsAgency["2"], {"1":{"foo":"baz"}});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -499,13 +503,9 @@ function AgencySuite () {
|
|||
|
||||
assertTrue(agency.remove("UnitTestsAgency", true));
|
||||
|
||||
try {
|
||||
agency.get("UnitTestsAgency", true).arango.UnitTestsAgency;
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
// key not found
|
||||
}
|
||||
var value = agency.get("UnitTestsAgency", true);
|
||||
assertTrue(value.hasOwnProperty("arango"));
|
||||
assertEqual(value.arango, {});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -540,17 +540,15 @@ function AgencySuite () {
|
|||
var values;
|
||||
for (i = 0; i < 100; ++i) {
|
||||
if (i >= 10 && i < 90) {
|
||||
try {
|
||||
values = agency.get("UnitTestsAgency/" + i).arango.UnitTestsAgency[i];
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
}
|
||||
values = agency.get("UnitTestsAgency/" + i);
|
||||
assertEqual(values, {"arango":{"UnitTestsAgency":{}}});
|
||||
}
|
||||
else {
|
||||
values = agency.get("UnitTestsAgency/" + i).arango.UnitTestsAgency[i];
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/" + i));
|
||||
assertEqual(values["UnitTestsAgency/" + i], "value" + i);
|
||||
values = agency.get("UnitTestsAgency/" + i);
|
||||
assertTrue(values.hasOwnProperty("arango"));
|
||||
assertTrue(values.arango.hasOwnProperty("UnitTestsAgency"));
|
||||
assertTrue(values.arango.UnitTestsAgency.hasOwnProperty("" + i));
|
||||
assertEqual(values.arango.UnitTestsAgency[i], "value" + i);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -564,9 +562,8 @@ function AgencySuite () {
|
|||
|
||||
agency.set("UnitTestsAgency/someDir/foo", "bar");
|
||||
|
||||
var values = agency.get("UnitTestsAgency/someDir/foo").arango.UnitTestsAgency.someDir.foo;
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/foo"));
|
||||
assertEqual(values["UnitTestsAgency/someDir/foo"], "bar");
|
||||
var values = agency.get("UnitTestsAgency/someDir/foo");
|
||||
assertEqual(values, {"arango":{"UnitTestsAgency":{"someDir":{"foo":"bar"}}}});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -583,55 +580,25 @@ function AgencySuite () {
|
|||
agency.set("UnitTestsAgency/someDir/foo/2/1/1", "bar5");
|
||||
agency.set("UnitTestsAgency/someDir/foo/2/1/2", "bar6");
|
||||
|
||||
var values = agency.get("UnitTestsAgency/someDir").arango.UnitTestsAgency.someDir;
|
||||
assertEqual({ }, values);
|
||||
var values = agency.get("UnitTestsAgency/someDir").arango.UnitTestsAgency.someDir.foo;
|
||||
assertEqual({"1":{"1":{"1":"bar1","2":"bar2"},
|
||||
"2":{"1":"bar3","2":"bar4"}},
|
||||
"2":{"1":{"1":"bar5","2":"bar6"}}}, values);
|
||||
|
||||
values = agency.get("UnitTestsAgency/someDir/foo").arango.UnitTestsAgency.someDir.foo;
|
||||
assertEqual({ }, values);
|
||||
assertEqual({"1":{"1":{"1":"bar1","2":"bar2"},
|
||||
"2":{"1":"bar3","2":"bar4"}},
|
||||
"2":{"1":{"1":"bar5","2":"bar6"}}}, values);
|
||||
|
||||
values = agency.get("UnitTestsAgency/someDir", true).arango.UnitTestsAgency.someDir;
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/foo/1/1/1"));
|
||||
assertEqual("bar1", values["UnitTestsAgency/someDir/foo/1/1/1"]);
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/foo/1/1/2"));
|
||||
assertEqual("bar2", values["UnitTestsAgency/someDir/foo/1/1/2"]);
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/foo/1/2/1"));
|
||||
assertEqual("bar3", values["UnitTestsAgency/someDir/foo/1/2/1"]);
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/foo/1/2/2"));
|
||||
assertEqual("bar4", values["UnitTestsAgency/someDir/foo/1/2/2"]);
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/foo/2/1/1"));
|
||||
assertEqual("bar5", values["UnitTestsAgency/someDir/foo/2/1/1"]);
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/foo/2/1/2"));
|
||||
assertEqual("bar6", values["UnitTestsAgency/someDir/foo/2/1/2"]);
|
||||
},
|
||||
values = agency.get("UnitTestsAgency/someDir", true).arango.UnitTestsAgency.someDir.foo;
|
||||
assertEqual({"1":{"1":{"1":"bar1","2":"bar2"},
|
||||
"2":{"1":"bar3","2":"bar4"}},
|
||||
"2":{"1":{"1":"bar5","2":"bar6"}}}, values);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test get w/ indexes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testGetIndexes : function () {
|
||||
assertTrue(agency.createDirectory("UnitTestsAgency/someDir"));
|
||||
|
||||
agency.set("UnitTestsAgency/someDir/foo", "bar");
|
||||
agency.set("UnitTestsAgency/someDir/bar", "baz");
|
||||
|
||||
var values = agency.get("UnitTestsAgency/someDir", true, true).arango.UnitTestsAgency.someDir;
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/foo"));
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/bar"));
|
||||
assertEqual(values["UnitTestsAgency/someDir/foo"].value, "bar");
|
||||
assertEqual(values["UnitTestsAgency/someDir/bar"].value, "baz");
|
||||
assertTrue(values["UnitTestsAgency/someDir/foo"].hasOwnProperty("index"));
|
||||
assertTrue(values["UnitTestsAgency/someDir/bar"].hasOwnProperty("index"));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test set / get directory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testGetDirectory : function () {
|
||||
assertTrue(agency.createDirectory("UnitTestsAgency/someDir"));
|
||||
assertTrue(agency.set("UnitTestsAgency/someDir/foo", "bar"));
|
||||
|
||||
var values = agency.get("UnitTestsAgency", false).arango.UnitTestsAgency;
|
||||
assertEqual({ }, values);
|
||||
values = agency.get("UnitTestsAgency/someDir/foo", true).arango.UnitTestsAgency.someDir.foo;
|
||||
assertEqual({"1":{"1":{"1":"bar1","2":"bar2"},
|
||||
"2":{"1":"bar3","2":"bar4"}},
|
||||
"2":{"1":{"1":"bar5","2":"bar6"}}}, values);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -644,7 +611,7 @@ function AgencySuite () {
|
|||
assertTrue(agency.set("UnitTestsAgency/someDir/baz", "bart"));
|
||||
|
||||
var values = agency.get("UnitTestsAgency", true).arango.UnitTestsAgency;
|
||||
assertEqual({ "UnitTestsAgency/someDir/baz" : "bart", "UnitTestsAgency/someDir/foo" : "bar" }, values);
|
||||
assertEqual({ "someDir" : {"foo": "bar", "baz": "bart"}}, values);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -657,13 +624,11 @@ function AgencySuite () {
|
|||
agency.set("UnitTestsAgency/someDir/foo", "bar");
|
||||
|
||||
var values = agency.get("UnitTestsAgency/someDir/foo").arango.UnitTestsAgency.someDir.foo;
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/foo"));
|
||||
assertEqual(values["UnitTestsAgency/someDir/foo"], "bar");
|
||||
assertEqual(values, "bar");
|
||||
|
||||
agency.set("UnitTestsAgency/someDir/foo", "baz");
|
||||
values = agency.get("UnitTestsAgency/someDir/foo").arango.UnitTestsAgency.someDir.foo;
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/foo"));
|
||||
assertEqual(values["UnitTestsAgency/someDir/foo"], "baz");
|
||||
assertEqual(values, "baz");
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -676,18 +641,12 @@ function AgencySuite () {
|
|||
agency.set("UnitTestsAgency/someDir/foo", "bar");
|
||||
|
||||
var values = agency.get("UnitTestsAgency/someDir/foo").arango.UnitTestsAgency.someDir.foo;
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/foo"));
|
||||
assertEqual(values["UnitTestsAgency/someDir/foo"], "bar");
|
||||
assertEqual(values, "bar");
|
||||
|
||||
agency.remove("UnitTestsAgency/someDir/foo");
|
||||
|
||||
try {
|
||||
values = agency.get("UnitTestsAgency/someDir/foo").arango.UnitTestsAgency.someDir.foo;
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
// key not found
|
||||
}
|
||||
values = agency.get("UnitTestsAgency/someDir/foo").arango.UnitTestsAgency.someDir;
|
||||
assertEqual(values, {});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -697,13 +656,8 @@ function AgencySuite () {
|
|||
testGetNonExisting1 : function () {
|
||||
assertTrue(agency.createDirectory("UnitTestsAgency/someDir"));
|
||||
|
||||
try {
|
||||
agency.get("UnitTestsAgency/someDir/foo").arango.UnitTestsAgency.someDir.foo;
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
// key not found
|
||||
}
|
||||
var value = agency.get("UnitTestsAgency/someDir/foo");
|
||||
assertEqual(value, {"arango":{"UnitTestsAgency":{"someDir":{}}}});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -711,13 +665,8 @@ function AgencySuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testGetNonExisting2 : function () {
|
||||
try {
|
||||
agency.get("UnitTestsAgency/someOtherDir").arango.UnitTestsAgency.someOtherDir;
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
// key not found
|
||||
}
|
||||
var value = agency.get("UnitTestsAgency/someOtherDir");
|
||||
assertEqual(value, {"arango":{"UnitTestsAgency":{}}});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -731,8 +680,7 @@ function AgencySuite () {
|
|||
agency.set("UnitTestsAgency/someDir/foobar", value);
|
||||
|
||||
var values = agency.get("UnitTestsAgency/someDir/foobar").arango.UnitTestsAgency.someDir.foobar;
|
||||
assertTrue(values.hasOwnProperty("UnitTestsAgency/someDir/foobar"));
|
||||
assertEqual(values["UnitTestsAgency/someDir/foobar"], value);
|
||||
assertEqual(values, value);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -125,25 +125,6 @@ function ClusterEnabledSuite () {
|
|||
assertEqual("myself", ss.id());
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test address
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testAddress : function () {
|
||||
assertTrue(agency.set("Target/MapIDToEndpoint/myself", "tcp://127.0.0.1:8529"));
|
||||
assertTrue(agency.set("Plan/Coordinators/myself", "none"));
|
||||
assertTrue(agency.set("Plan/DBServers/myself", "other"));
|
||||
ss.setId("myself");
|
||||
ss.flush();
|
||||
|
||||
assertEqual("tcp://127.0.0.1:8529", ss.address());
|
||||
|
||||
assertTrue(agency.set("Target/MapIDToEndpoint/myself", "tcp://127.0.0.1:8530"));
|
||||
ss.flush();
|
||||
|
||||
assertEqual("tcp://127.0.0.1:8530", ss.address());
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test isCluster
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -399,6 +380,7 @@ function ClusterEnabledSuite () {
|
|||
last = id;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -233,119 +233,6 @@ void VelocyPackDumper::dumpInteger(VPackSlice const* slice) {
|
|||
}
|
||||
}
|
||||
|
||||
void VelocyPackDumper::dumpString(char const* src, VPackValueLength len) {
|
||||
static char const EscapeTable[256] = {
|
||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E
|
||||
// F
|
||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r',
|
||||
'u',
|
||||
'u', // 00
|
||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u',
|
||||
'u',
|
||||
'u', // 10
|
||||
0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
'/', // 20
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
0, // 30~4F
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
'\\', 0, 0, 0, // 50
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0,
|
||||
0, // 60~FF
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0};
|
||||
|
||||
TRI_string_buffer_t* buffer = _buffer->stringBuffer();
|
||||
|
||||
uint8_t const* p = reinterpret_cast<uint8_t const*>(src);
|
||||
uint8_t const* e = p + len;
|
||||
|
||||
static size_t const maxCount = 16;
|
||||
size_t count = maxCount;
|
||||
|
||||
while (p < e) {
|
||||
uint8_t c = *p;
|
||||
|
||||
// don't check for buffer reallocation on every single character
|
||||
if (count == maxCount) {
|
||||
// maximum value that we can append in one go is 6 bytes
|
||||
int res = TRI_ReserveStringBuffer(buffer, 6 * count);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
count = 0;
|
||||
} else {
|
||||
++count;
|
||||
}
|
||||
|
||||
|
||||
if ((c & 0x80) == 0) {
|
||||
// check for control characters
|
||||
char esc = EscapeTable[c];
|
||||
|
||||
if (esc) {
|
||||
if (c != '/' || options->escapeForwardSlashes) {
|
||||
// escape forward slashes only when requested
|
||||
TRI_AppendCharUnsafeStringBuffer(buffer, '\\');
|
||||
}
|
||||
TRI_AppendCharUnsafeStringBuffer(buffer, static_cast<char>(esc));
|
||||
|
||||
if (esc == 'u') {
|
||||
uint16_t i1 = (((uint16_t)c) & 0xf0) >> 4;
|
||||
uint16_t i2 = (((uint16_t)c) & 0x0f);
|
||||
|
||||
TRI_AppendStringUnsafeStringBuffer(buffer, "00", 2);
|
||||
TRI_AppendCharUnsafeStringBuffer(buffer,
|
||||
static_cast<char>((i1 < 10) ? ('0' + i1) : ('A' + i1 - 10)));
|
||||
TRI_AppendCharUnsafeStringBuffer(buffer,
|
||||
static_cast<char>((i2 < 10) ? ('0' + i2) : ('A' + i2 - 10)));
|
||||
}
|
||||
} else {
|
||||
TRI_AppendCharUnsafeStringBuffer(buffer, static_cast<char>(c));
|
||||
}
|
||||
} else if ((c & 0xe0) == 0xc0) {
|
||||
// two-byte sequence
|
||||
if (p + 1 >= e) {
|
||||
throw VPackException(VPackException::InvalidUtf8Sequence);
|
||||
}
|
||||
|
||||
TRI_AppendStringUnsafeStringBuffer(buffer, reinterpret_cast<char const*>(p), 2);
|
||||
++p;
|
||||
} else if ((c & 0xf0) == 0xe0) {
|
||||
// three-byte sequence
|
||||
if (p + 2 >= e) {
|
||||
throw VPackException(VPackException::InvalidUtf8Sequence);
|
||||
}
|
||||
|
||||
TRI_AppendStringUnsafeStringBuffer(buffer, reinterpret_cast<char const*>(p), 3);
|
||||
p += 2;
|
||||
} else if ((c & 0xf8) == 0xf0) {
|
||||
// four-byte sequence
|
||||
if (p + 3 >= e) {
|
||||
throw VPackException(VPackException::InvalidUtf8Sequence);
|
||||
}
|
||||
|
||||
TRI_AppendStringUnsafeStringBuffer(buffer, reinterpret_cast<char const*>(p), 4);
|
||||
p += 3;
|
||||
}
|
||||
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
void VelocyPackDumper::dumpValue(VPackSlice const* slice, VPackSlice const* base) {
|
||||
if (base == nullptr) {
|
||||
base = slice;
|
||||
|
@ -435,9 +322,15 @@ void VelocyPackDumper::dumpValue(VPackSlice const* slice, VPackSlice const* base
|
|||
case VPackValueType::String: {
|
||||
VPackValueLength len;
|
||||
char const* p = slice->getString(len);
|
||||
TRI_AppendCharUnsafeStringBuffer(buffer, '"');
|
||||
dumpString(p, len);
|
||||
if (TRI_AppendCharStringBuffer(buffer, '"') != TRI_ERROR_NO_ERROR) {
|
||||
int res;
|
||||
if (len == 0) {
|
||||
res = TRI_AppendString2StringBuffer(buffer, "\"\"", 2);
|
||||
} else {
|
||||
res = TRI_AppendCharStringBuffer(buffer, '"');
|
||||
res |= TRI_AppendJsonEncodedStringStringBuffer(buffer, p, len, options->escapeForwardSlashes);
|
||||
res |= TRI_AppendCharStringBuffer(buffer, '"');
|
||||
}
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
break;
|
||||
|
@ -453,10 +346,12 @@ void VelocyPackDumper::dumpValue(VPackSlice const* slice, VPackSlice const* base
|
|||
if (options->customTypeHandler == nullptr) {
|
||||
throw VPackException(VPackException::NeedCustomTypeHandler);
|
||||
} else {
|
||||
TRI_AppendCharUnsafeStringBuffer(buffer, '"');
|
||||
std::string v = options->customTypeHandler->toString(*slice, nullptr, *base);
|
||||
dumpString(v.c_str(), v.size());
|
||||
if (TRI_AppendCharStringBuffer(buffer, '"') != TRI_ERROR_NO_ERROR) {
|
||||
|
||||
int res = TRI_AppendCharStringBuffer(buffer, '"');
|
||||
res |= TRI_AppendJsonEncodedStringStringBuffer(buffer, v.c_str(), v.size(), options->escapeForwardSlashes);
|
||||
res |= TRI_AppendCharStringBuffer(buffer, '"');
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,8 +67,6 @@ class VelocyPackDumper {
|
|||
|
||||
void dumpInteger(velocypack::Slice const*);
|
||||
|
||||
void dumpString(char const*, velocypack::ValueLength);
|
||||
|
||||
public:
|
||||
velocypack::Options const* options;
|
||||
|
||||
|
|
|
@ -810,7 +810,7 @@ void SimpleHttpClient::processChunkedHeader() {
|
|||
|
||||
try {
|
||||
contentLength =
|
||||
static_cast<uint32_t>(std::stol(line, nullptr, 16)); // C++11
|
||||
static_cast<uint32_t>(std::stol(line, nullptr, 16));
|
||||
} catch (...) {
|
||||
setErrorMessage("found invalid content-length", true);
|
||||
// reset connection
|
||||
|
|
Loading…
Reference in New Issue