1
0
Fork 0

Merge branch 'json_agency_comm' of https://github.com/arangodb/arangodb into json_agency_comm

This commit is contained in:
Kaveh Vahedipour 2016-05-04 15:00:41 +02:00
commit 7eed0ecc2f
62 changed files with 968 additions and 777 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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) {

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
};

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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());
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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()) {

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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).

View File

@ -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;

View File

@ -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;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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;

View File

@ -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();
}
}

View File

@ -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 {

View File

@ -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

View File

@ -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()));
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -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);
}

View File

@ -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)

View File

@ -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')

View File

@ -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);
}

File diff suppressed because one or more lines are too long

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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%; }

View File

@ -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(

View File

@ -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>

View File

@ -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);
}
});

View File

@ -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;

View File

@ -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%;
}

View File

@ -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 {

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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();

View File

@ -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);
}
};

View File

@ -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;
}
}
};
}

View File

@ -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);
}
}

View File

@ -67,8 +67,6 @@ class VelocyPackDumper {
void dumpInteger(velocypack::Slice const*);
void dumpString(char const*, velocypack::ValueLength);
public:
velocypack::Options const* options;

View File

@ -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