mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/arangodb/arangodb into vpack
This commit is contained in:
commit
59084c193d
|
@ -1,6 +1,8 @@
|
|||
v2.8.0 (XXXX-XX-XX)
|
||||
-------------------
|
||||
|
||||
* web interface: aql editor now supports bind parameters
|
||||
|
||||
* added startup option `--server.hide-product-header` to make the server not send
|
||||
the HTTP response header `"Server: ArangoDB"` in its HTTP responses. By default,
|
||||
the option is turned off so the header is still sent as usual.
|
||||
|
@ -101,6 +103,9 @@ v2.8.0 (XXXX-XX-XX)
|
|||
v2.7.2 (XXXX-XX-XX)
|
||||
-------------------
|
||||
|
||||
* fixed undefined behavior when accessing the top level of a document with the `[*]`
|
||||
operator
|
||||
|
||||
* fixed potentially invalid pointer access in shaper when the currently accessed
|
||||
document got re-located by the WAL collector at the very same time
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "Basics/AttributeNameParser.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Basics/json.h"
|
||||
#include "Basics/vector.h"
|
||||
#include "Basics/JsonHelper.h"
|
||||
|
||||
#include <functional>
|
||||
|
|
|
@ -529,7 +529,7 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
|
|||
case NODE_TYPE_EXPANSION:
|
||||
return executeSimpleExpressionExpansion(node, trx, argv, startPos, vars, regs);
|
||||
case NODE_TYPE_ITERATOR:
|
||||
return executeSimpleExpressionIterator(node, trx, argv, startPos, vars, regs);
|
||||
return executeSimpleExpressionIterator(node, collection, trx, argv, startPos, vars, regs);
|
||||
case NODE_TYPE_OPERATOR_BINARY_PLUS:
|
||||
case NODE_TYPE_OPERATOR_BINARY_MINUS:
|
||||
case NODE_TYPE_OPERATOR_BINARY_TIMES:
|
||||
|
@ -1290,6 +1290,7 @@ AqlValue Expression::executeSimpleExpressionExpansion (AstNode const* node,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue Expression::executeSimpleExpressionIterator (AstNode const* node,
|
||||
TRI_document_collection_t const** collection,
|
||||
triagens::arango::AqlTransaction* trx,
|
||||
AqlItemBlock const* argv,
|
||||
size_t startPos,
|
||||
|
@ -1298,9 +1299,8 @@ AqlValue Expression::executeSimpleExpressionIterator (AstNode const* node,
|
|||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 2);
|
||||
|
||||
// intentionally do not stringify node 0
|
||||
TRI_document_collection_t const* myCollection = nullptr;
|
||||
return executeSimpleExpression(node->getMember(1), &myCollection, trx, argv, startPos, vars, regs, true);
|
||||
*collection = nullptr;
|
||||
return executeSimpleExpression(node->getMember(1), collection, trx, argv, startPos, vars, regs, true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -485,6 +485,7 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AqlValue executeSimpleExpressionIterator (AstNode const*,
|
||||
TRI_document_collection_t const**,
|
||||
triagens::arango::AqlTransaction*,
|
||||
AqlItemBlock const*,
|
||||
size_t,
|
||||
|
|
|
@ -241,6 +241,7 @@ add_executable(
|
|||
VocBase/datafile.cpp
|
||||
VocBase/Ditch.cpp
|
||||
VocBase/document-collection.cpp
|
||||
VocBase/DocumentAccessor.cpp
|
||||
VocBase/ExampleMatcher.cpp
|
||||
VocBase/edge-collection.cpp
|
||||
VocBase/headers.cpp
|
||||
|
|
|
@ -383,10 +383,10 @@ std::list<AgencyEndpoint*> AgencyComm::_globalEndpoints;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AgencyConnectionOptions AgencyComm::_globalConnectionOptions = {
|
||||
15.0, // connectTimeout
|
||||
9.0, // requestTimeout
|
||||
5.0, // lockTimeout
|
||||
3 // numRetries
|
||||
15.0, // connectTimeout
|
||||
120.0, // requestTimeout
|
||||
120.0, // lockTimeout
|
||||
10 // numRetries
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "Basics/json.h"
|
||||
#include "Basics/logging.h"
|
||||
#include "Basics/tri-strings.h"
|
||||
#include "Basics/vector.h"
|
||||
#include "Basics/json-utilities.h"
|
||||
#include "Basics/JsonHelper.h"
|
||||
#include "Basics/MutexLocker.h"
|
||||
|
@ -403,8 +402,8 @@ bool ClusterInfo::doesDatabaseExist (DatabaseID const& databaseID,
|
|||
/// @brief get list of databases in the cluster
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
vector<DatabaseID> ClusterInfo::listDatabases (bool reload) {
|
||||
vector<DatabaseID> result;
|
||||
std::vector<DatabaseID> ClusterInfo::listDatabases (bool reload) {
|
||||
std::vector<DatabaseID> result;
|
||||
|
||||
if (reload ||
|
||||
! _plannedDatabasesProt.isValid ||
|
||||
|
@ -712,18 +711,18 @@ void ClusterInfo::loadPlannedCollections (bool acquireLock) {
|
|||
(*it).second._json = nullptr;
|
||||
|
||||
shared_ptr<CollectionInfo> collectionData (new CollectionInfo(json));
|
||||
vector<string>* shardKeys = new vector<string>;
|
||||
std::vector<std::string>* shardKeys = new std::vector<std::string>;
|
||||
*shardKeys = collectionData->shardKeys();
|
||||
newShardKeys.insert(
|
||||
make_pair(collection, shared_ptr<vector<string> > (shardKeys)));
|
||||
make_pair(collection, shared_ptr<std::vector<std::string> > (shardKeys)));
|
||||
map<ShardID, ServerID> shardIDs = collectionData->shardIds();
|
||||
vector<string>* shards = new vector<string>;
|
||||
std::vector<std::string>* shards = new std::vector<std::string>;
|
||||
map<ShardID, ServerID>::iterator it3;
|
||||
for (it3 = shardIDs.begin(); it3 != shardIDs.end(); ++it3) {
|
||||
shards->push_back(it3->first);
|
||||
}
|
||||
newShards.emplace(
|
||||
std::make_pair(collection, shared_ptr<vector<string> >(shards)));
|
||||
std::make_pair(collection, shared_ptr<std::vector<std::string> >(shards)));
|
||||
|
||||
// insert the collection into the existing map, insert it under its
|
||||
// ID as well as under its name, so that a lookup can be done with
|
||||
|
@ -2260,7 +2259,7 @@ std::vector<ServerID> ClusterInfo::getCurrentDBServers () {
|
|||
/// our id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const std::string prefixTargetServerEndoint = "Target/MapIDToEndpoint/";
|
||||
static const std::string prefixTargetServerEndpoint = "Target/MapIDToEndpoint/";
|
||||
|
||||
std::string ClusterInfo::getTargetServerEndpoint (ServerID const& serverID) {
|
||||
|
||||
|
@ -2271,12 +2270,12 @@ std::string ClusterInfo::getTargetServerEndpoint (ServerID const& serverID) {
|
|||
AgencyCommLocker locker("Target", "READ");
|
||||
|
||||
if (locker.successful()) {
|
||||
result = _agency.getValues(prefixTargetServerEndoint + serverID, false);
|
||||
result = _agency.getValues(prefixTargetServerEndpoint + serverID, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.successful()) {
|
||||
result.parse(prefixTargetServerEndoint, false);
|
||||
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);
|
||||
|
@ -2357,9 +2356,9 @@ int ClusterInfo::getResponsibleShard (CollectionID const& collectionID,
|
|||
}
|
||||
|
||||
int tries = 0;
|
||||
shared_ptr<vector<string> > shardKeysPtr;
|
||||
shared_ptr<std::vector<std::string> > shardKeysPtr;
|
||||
char const** shardKeys = nullptr;
|
||||
shared_ptr<vector<ShardID> > shards;
|
||||
shared_ptr<std::vector<ShardID> > shards;
|
||||
bool found = false;
|
||||
|
||||
while (true) {
|
||||
|
|
|
@ -199,6 +199,7 @@ arangod_libarangod_a_SOURCES = \
|
|||
arangod/VocBase/datafile.cpp \
|
||||
arangod/VocBase/Ditch.cpp \
|
||||
arangod/VocBase/document-collection.cpp \
|
||||
arangod/VocBase/DocumentAccessor.cpp \
|
||||
arangod/VocBase/ExampleMatcher.cpp \
|
||||
arangod/VocBase/edge-collection.cpp \
|
||||
arangod/VocBase/headers.cpp \
|
||||
|
|
|
@ -0,0 +1,301 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief read-accesses internals of a document
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS 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 Jan Steemann
|
||||
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
|
||||
/// @author Copyright 2006-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "DocumentAccessor.h"
|
||||
#include "Basics/conversions.h"
|
||||
#include "Basics/Exceptions.h"
|
||||
#include "Utils/CollectionNameResolver.h"
|
||||
#include "VocBase/VocShaper.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- DocumentAccessor
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
DocumentAccessor::DocumentAccessor (triagens::arango::CollectionNameResolver const* resolver,
|
||||
TRI_document_collection_t* document,
|
||||
TRI_doc_mptr_t const* mptr)
|
||||
: _resolver(resolver),
|
||||
_document(document),
|
||||
_mptr(mptr),
|
||||
_json(),
|
||||
_current(nullptr) {
|
||||
}
|
||||
|
||||
DocumentAccessor::~DocumentAccessor () {
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
bool DocumentAccessor::hasKey (std::string const& attribute) const {
|
||||
if (! isObject()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DocumentAccessor::isObject () const {
|
||||
if (_current != nullptr) {
|
||||
return TRI_IsObjectJson(_current);
|
||||
}
|
||||
|
||||
// ok, must be a document/edge
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DocumentAccessor::isArray () const {
|
||||
if (_current != nullptr) {
|
||||
return TRI_IsArrayJson(_current);
|
||||
}
|
||||
|
||||
// ok, must be a document/edge
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t DocumentAccessor::length () const {
|
||||
if (! isArray()) {
|
||||
return 0;
|
||||
}
|
||||
// ok, we have confirmed this is an array
|
||||
TRI_ASSERT(_current != nullptr);
|
||||
if (_current != nullptr) {
|
||||
return TRI_LengthArrayJson(_current);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DocumentAccessor& DocumentAccessor::get (std::string const& name) {
|
||||
return get(name.c_str(), name.size());
|
||||
}
|
||||
|
||||
DocumentAccessor& DocumentAccessor::get (char const* name, size_t nameLength) {
|
||||
if (_current == nullptr) {
|
||||
// a document, we need the access its attributes using special methods
|
||||
lookupDocumentAttribute(name, nameLength);
|
||||
}
|
||||
else {
|
||||
// already a JSON
|
||||
lookupJsonAttribute(name, nameLength);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
DocumentAccessor& DocumentAccessor::at (int64_t index) {
|
||||
if (isArray()) {
|
||||
size_t length = TRI_LengthArrayJson(_current);
|
||||
|
||||
if (index < 0) {
|
||||
// a negative position is allowed
|
||||
index = static_cast<int64_t>(length) + index;
|
||||
}
|
||||
|
||||
if (index >= 0 && index < static_cast<int64_t>(length)) {
|
||||
// only look up the value if it is within array bounds
|
||||
TRI_json_t* found = TRI_LookupArrayJson(_current, static_cast<size_t>(index));
|
||||
|
||||
if (found != nullptr) {
|
||||
_current = found;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
// fall-through intentional
|
||||
}
|
||||
|
||||
setToNull();
|
||||
return *this;
|
||||
}
|
||||
|
||||
triagens::basics::Json DocumentAccessor::toJson () {
|
||||
if (_current == nullptr) {
|
||||
return triagens::basics::Json(triagens::basics::Json::Null);
|
||||
}
|
||||
|
||||
// should always be true
|
||||
if (_current == _json.get()) {
|
||||
// _current points at the JSON that we own
|
||||
TRI_json_t* value = _json.release();
|
||||
setToNull();
|
||||
return triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, value);
|
||||
}
|
||||
|
||||
TRI_json_t* copy = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, _current);
|
||||
|
||||
if (copy != nullptr) {
|
||||
_json.release();
|
||||
return triagens::basics::Json(TRI_UNKNOWN_MEM_ZONE, copy);
|
||||
}
|
||||
// fall-through intentional
|
||||
|
||||
return triagens::basics::Json(triagens::basics::Json::Null);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void DocumentAccessor::setToNull () {
|
||||
// check if already null
|
||||
if (! TRI_IsNullJson(_current)) {
|
||||
_json.reset(TRI_CreateNullJson(TRI_UNKNOWN_MEM_ZONE));
|
||||
_current = _json.get();
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentAccessor::lookupJsonAttribute (char const* name, size_t nameLength) {
|
||||
TRI_ASSERT(_current != nullptr);
|
||||
|
||||
TRI_json_t* value = TRI_LookupObjectJson(_current, name);
|
||||
|
||||
if (value == nullptr) {
|
||||
// attribute not found
|
||||
setToNull();
|
||||
}
|
||||
else {
|
||||
// found
|
||||
_current = value;
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentAccessor::lookupDocumentAttribute (char const* name, size_t nameLength) {
|
||||
if (*name == '_' && name[1] != '\0') {
|
||||
if (name[1] == 'k' && nameLength == 4 && memcmp(name, TRI_VOC_ATTRIBUTE_KEY, nameLength) == 0) {
|
||||
// _key value is copied into JSON
|
||||
char const* key = TRI_EXTRACT_MARKER_KEY(_mptr);
|
||||
if (key == nullptr) {
|
||||
setToNull();
|
||||
return;
|
||||
}
|
||||
_json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, key, strlen(key)));
|
||||
_current = _json.get();
|
||||
return;
|
||||
}
|
||||
|
||||
if (name[1] == 'i' && nameLength == 3 && memcmp(name, TRI_VOC_ATTRIBUTE_ID, nameLength) == 0) {
|
||||
// _id
|
||||
char buffer[512]; // big enough for max key length + max collection name length
|
||||
size_t pos = _resolver->getCollectionName(&buffer[0], _document->_info._cid);
|
||||
buffer[pos++] = '/';
|
||||
char const* key = TRI_EXTRACT_MARKER_KEY(_mptr);
|
||||
if (key == nullptr) {
|
||||
setToNull();
|
||||
return;
|
||||
}
|
||||
size_t len = strlen(key);
|
||||
memcpy(&buffer[pos], key, len);
|
||||
buffer[pos + len] = '\0';
|
||||
_json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], pos + len));
|
||||
_current = _json.get();
|
||||
return;
|
||||
}
|
||||
|
||||
if (name[1] == 'r' && nameLength == 4 && memcmp(name, TRI_VOC_ATTRIBUTE_REV, nameLength) == 0) {
|
||||
// _rev
|
||||
char buffer[21];
|
||||
TRI_voc_rid_t rid = TRI_EXTRACT_MARKER_RID(_mptr);
|
||||
size_t len = TRI_StringUInt64InPlace(rid, &buffer[0]);
|
||||
_json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], len));
|
||||
_current = _json.get();
|
||||
return;
|
||||
}
|
||||
|
||||
if (name[1] == 'f' && nameLength == 5 && memcmp(name, TRI_VOC_ATTRIBUTE_FROM, nameLength) == 0) {
|
||||
// _from
|
||||
char buffer[512]; // big enough for max key length + max collection name length
|
||||
size_t pos = _resolver->getCollectionNameCluster(&buffer[0], TRI_EXTRACT_MARKER_FROM_CID(_mptr));
|
||||
buffer[pos++] = '/';
|
||||
char const* key = TRI_EXTRACT_MARKER_FROM_KEY(_mptr);
|
||||
if (key == nullptr) {
|
||||
setToNull();
|
||||
return;
|
||||
}
|
||||
size_t len = strlen(key);
|
||||
memcpy(&buffer[pos], key, len);
|
||||
buffer[pos + len] = '\0';
|
||||
_json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], pos + len));
|
||||
_current = _json.get();
|
||||
return;
|
||||
}
|
||||
|
||||
if (name[1] == 't' && nameLength == 3 && memcmp(name, TRI_VOC_ATTRIBUTE_TO, nameLength) == 0) {
|
||||
// to
|
||||
char buffer[512]; // big enough for max key length + max collection name length
|
||||
size_t pos = _resolver->getCollectionNameCluster(&buffer[0], TRI_EXTRACT_MARKER_TO_CID(_mptr));
|
||||
buffer[pos++] = '/';
|
||||
char const* key = TRI_EXTRACT_MARKER_TO_KEY(_mptr);
|
||||
if (key == nullptr) {
|
||||
setToNull();
|
||||
return;
|
||||
}
|
||||
size_t len = strlen(key);
|
||||
memcpy(&buffer[pos], key, len);
|
||||
buffer[pos + len] = '\0';
|
||||
_json.reset(TRI_CreateStringCopyJson(TRI_UNKNOWN_MEM_ZONE, &buffer[0], pos + len));
|
||||
_current = _json.get();
|
||||
return;
|
||||
}
|
||||
|
||||
// fall-through intentional
|
||||
}
|
||||
|
||||
auto shaper = _document->getShaper();
|
||||
|
||||
TRI_shape_pid_t pid = shaper->lookupAttributePathByName(name);
|
||||
|
||||
if (pid == 0) {
|
||||
// attribute does not exist
|
||||
setToNull();
|
||||
return;
|
||||
}
|
||||
|
||||
// attribute exists
|
||||
TRI_shaped_json_t document;
|
||||
TRI_EXTRACT_SHAPED_JSON_MARKER(document, _mptr->getDataPtr());
|
||||
|
||||
TRI_shaped_json_t json;
|
||||
TRI_shape_t const* shape;
|
||||
|
||||
bool ok = shaper->extractShapedJson(&document, 0, pid, &json, &shape);
|
||||
|
||||
if (ok && shape != nullptr) {
|
||||
_json.reset(TRI_JsonShapedJson(shaper, &json));
|
||||
_current = _json.get();
|
||||
return;
|
||||
}
|
||||
|
||||
// not found
|
||||
setToNull();
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief read-accesses internals of a document
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2004-2014 triAGENS 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 Jan Steemann
|
||||
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
|
||||
/// @author Copyright 2006-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGODB_VOC_BASE_DOCUMENT_ACCESSOR_H
|
||||
#define ARANGODB_VOC_BASE_DOCUMENT_ACCESSOR_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Basics/JsonHelper.h"
|
||||
#include "VocBase/document-collection.h"
|
||||
#include "VocBase/shape-accessor.h"
|
||||
#include "VocBase/shaped-json.h"
|
||||
#include "VocBase/Shaper.h"
|
||||
|
||||
struct TRI_doc_mptr_t;
|
||||
|
||||
namespace triagens {
|
||||
namespace arango {
|
||||
class CollectionNameResolver;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- DocumentAccessor
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
class DocumentAccessor {
|
||||
|
||||
public:
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
DocumentAccessor (DocumentAccessor const&);
|
||||
DocumentAccessor& operator= (DocumentAccessor const&);
|
||||
|
||||
DocumentAccessor (triagens::arango::CollectionNameResolver const* resolver,
|
||||
TRI_document_collection_t* document,
|
||||
TRI_doc_mptr_t const* mptr);
|
||||
|
||||
~DocumentAccessor ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
bool hasKey (std::string const& attribute) const;
|
||||
|
||||
bool isObject () const;
|
||||
|
||||
bool isArray () const;
|
||||
|
||||
size_t length () const;
|
||||
|
||||
DocumentAccessor& get (char const* name, size_t nameLength);
|
||||
|
||||
DocumentAccessor& get (std::string const& name);
|
||||
|
||||
DocumentAccessor& at (int64_t index);
|
||||
|
||||
triagens::basics::Json toJson ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
|
||||
void setToNull ();
|
||||
|
||||
void lookupJsonAttribute (char const* name, size_t nameLength);
|
||||
|
||||
void lookupDocumentAttribute (char const* name, size_t nameLength);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
|
||||
triagens::arango::CollectionNameResolver const* _resolver;
|
||||
|
||||
TRI_document_collection_t* _document;
|
||||
|
||||
TRI_doc_mptr_t const* _mptr;
|
||||
|
||||
std::unique_ptr<TRI_json_t> _json; // the JSON that we own
|
||||
|
||||
TRI_json_t* _current; // the JSON that we point to
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- END-OF-FILE
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
|
||||
// End:
|
|
@ -700,6 +700,15 @@ static inline TRI_voc_rid_t TRI_EXTRACT_MARKER_RID (TRI_df_marker_t const* marke
|
|||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extracts the revision id from a master pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline TRI_voc_rid_t TRI_EXTRACT_MARKER_RID (TRI_doc_mptr_t const* mptr) {
|
||||
TRI_df_marker_t const* marker = static_cast<TRI_df_marker_t const*>(mptr->getDataPtr());
|
||||
return TRI_EXTRACT_MARKER_RID(marker);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extracts the pointer to the key from a marker
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1,31 +1,36 @@
|
|||
[
|
||||
{
|
||||
"name" : "FOR .. FILTER .. RETURN template",
|
||||
"value": "/* Please insert some values for the @@collection and @value placeholders */\nFOR i IN @@collection\n FILTER i.`attribute` == @value\n RETURN i",
|
||||
"value": "/* Please insert some values for the @@collection and @value bind parameters */\nFOR doc IN @@collection\n FILTER doc.`attribute` == @value\n RETURN doc",
|
||||
"parameter": {"@collection": "my_collection", "value": "my_value"}
|
||||
},
|
||||
{
|
||||
"name" : "Limit",
|
||||
"value": "/* Please insert some values for the @@collection, @offset and @count placeholders */\nFOR i IN @@collection\n LIMIT @offset, @count\n RETURN i",
|
||||
"parameter": {"@collection": "my_collection", "offset": "my_offset", "count": "my_count"}
|
||||
"value": "/* Please insert some values for the @@collection, @offset and @count bind parameters */\nFOR doc IN @@collection\n LIMIT @offset, @count\n RETURN doc",
|
||||
"parameter": {"@collection": "my_collection", "offset": 0, "count": 10}
|
||||
},
|
||||
{
|
||||
"name" : "Inner join",
|
||||
"value": "/* Please insert some values for the @@collection1 and @@collection2 bind parameters */\nFOR doc1 IN @@collection1\n FOR doc2 IN @@collection2\n FILTER doc1.`attribute` == doc2.`attribute`\n RETURN { doc1, doc2 }",
|
||||
"parameter": {"@collection1": "collection1", "@collection2": "collection2"}
|
||||
},
|
||||
{
|
||||
"name" : "Random document",
|
||||
"value": "/* Please insert some value for the @@collection placeholder */\nFOR i IN @@collection\n SORT RAND()\n LIMIT 1\n RETURN i",
|
||||
"value": "/* Please insert some value for the @@collection bind parameter */\nFOR doc IN @@collection\n SORT RAND()\n LIMIT 1\n RETURN doc",
|
||||
"parameter": {"@collection": "my_collection"}
|
||||
},
|
||||
{
|
||||
"name" : "Subquery example",
|
||||
"value": "/* Please insert some values for the @@collection, @value and @count placeholders */\nFOR i IN @@collection\n LET values = (\n FOR s IN i.`attribute`\n FILTER s.`attribute` == @value\n RETURN s\n )\n FILTER LENGTH(values) > @count\n RETURN {\n i : i,\n values : values\n }",
|
||||
"parameter": {"@collection": "my_collection", "value": "my_value", "count": "my_count"}
|
||||
"value": "/* Please insert some values for the @@collection, @value and @count bind parameters */\nFOR doc IN @@collection\n LET values = (\n FOR s IN doc.`attribute`\n FILTER s.`attribute` == @value\n RETURN s\n )\n FILTER LENGTH(values) > @count\n RETURN {\n doc,\n values\n }",
|
||||
"parameter": {"@collection": "my_collection", "value": "my_value", "count": 10}
|
||||
},
|
||||
{
|
||||
"name" : "Sequences",
|
||||
"value": "/* Returns the sequence of integers between 2010 and 2013 (including) */\nFOR year IN 2010..2013\n RETURN year"
|
||||
"value": "/* Returns the sequence of integers between 2010 and 2015 (including) */\nFOR year IN 2010..2015\n RETURN year"
|
||||
},
|
||||
{
|
||||
"name" : "Bind parameters",
|
||||
"value": "/* There are two types of bind parameters:\n - bind parameter names starting with a single @ character, e.g. @count, @value, @test:\n These can be used to ship any JSON-encodable data to the server.\n - bind parameter names starting with two @ characters always refer to collections, e.g. @@collections, @@c:\n These can be used as placeholders for collection names.\n */\nFOR i IN @@collection\n FILTER i.value == @value\n RETURN i",
|
||||
"value": "/* There are two types of bind parameters:\n - bind parameter names starting with a single @ character, e.g. @count, @value, @test:\n These can be used to ship any JSON-encodable data to the server.\n - bind parameter names starting with two @ characters always refer to collections, e.g. @@collections, @@c:\n These can be used as placeholders for collection names.\n */\nFOR doc IN @@collection\n FILTER doc.value == @value\n RETURN doc",
|
||||
"parameter": {"@collection": "my_collection", "value": "my_value"}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -678,7 +678,7 @@ function processQuery (query, explain) {
|
|||
}
|
||||
|
||||
/* the exposed function */
|
||||
function explain (data, options, shouldPrint) {
|
||||
function explain (data, options, shouldPrint, bindVars) {
|
||||
'use strict';
|
||||
if (typeof data === "string") {
|
||||
data = { query: data };
|
||||
|
@ -687,10 +687,20 @@ function explain (data, options, shouldPrint) {
|
|||
throw "ArangoStatement needs initial data";
|
||||
}
|
||||
|
||||
if (options === undefined) {
|
||||
options = data.options;
|
||||
}
|
||||
options = options || { };
|
||||
setColors(options.colors === undefined ? true : options.colors);
|
||||
|
||||
var stmt = db._createStatement(data);
|
||||
|
||||
if (typeof bindVars === 'object') {
|
||||
Object.keys(bindVars).forEach(function(key) {
|
||||
stmt.bind(key, bindVars[key]);
|
||||
});
|
||||
}
|
||||
|
||||
var result = stmt.explain(options);
|
||||
|
||||
stringBuilder.clearOutput();
|
||||
|
|
|
@ -135,4 +135,86 @@
|
|||
<% mediumChart("pageFaultsChart", "Major Page Faults") %>
|
||||
<% mediumChart("systemUserTimeChart", "Used CPU Time per Second") %>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-headerbar headerBar">
|
||||
<a class="arangoHeader">Replication</a>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-row">
|
||||
<div class="dashboard-full-width-chart" id="replication-chart">
|
||||
<div class="dashboard-full-width-chart-inner">
|
||||
<div id="repl-numbers" class="dashboard-interior-chart">
|
||||
<div class="inner">
|
||||
<div class="top dashboard-subtitle-bar">Numbers</div>
|
||||
<div class="bottom">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Events</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Requests</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Failed</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="repl-ticks" class="dashboard-interior-chart">
|
||||
<div class="inner">
|
||||
<div class="top dashboard-subtitle-bar">Ticks</div>
|
||||
<div class="bottom">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Applied</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Processed</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Available</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="repl-progress" class="dashboard-interior-chart">
|
||||
<div class="inner">
|
||||
<div class="top dashboard-subtitle-bar">Progress</div>
|
||||
<div class="bottom">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Message</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Time</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Failed</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dashboard-sub-bar"">Replication</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</script>
|
||||
|
|
|
@ -415,6 +415,45 @@
|
|||
cuts[counter] : cuts[counter - 1] + " - " + cuts[counter];
|
||||
},
|
||||
|
||||
renderReplicationStatistics: function(object) {
|
||||
$('#repl-numbers table tr:nth-child(1) > td:nth-child(2)').html(object.state.totalEvents);
|
||||
$('#repl-numbers table tr:nth-child(2) > td:nth-child(2)').html(object.state.totalRequests);
|
||||
$('#repl-numbers table tr:nth-child(3) > td:nth-child(2)').html(object.state.totalFailedConnects);
|
||||
|
||||
$('#repl-ticks table tr:nth-child(1) > td:nth-child(2)').html(object.state.lastAppliedContinuousTick);
|
||||
$('#repl-ticks table tr:nth-child(2) > td:nth-child(2)').html(object.state.lastProcessedContinuousTick);
|
||||
$('#repl-ticks table tr:nth-child(3) > td:nth-child(2)').html(object.state.lastAvailableContinuousTick);
|
||||
|
||||
$('#repl-progress table tr:nth-child(1) > td:nth-child(2)').html(object.state.progress.message);
|
||||
$('#repl-progress table tr:nth-child(2) > td:nth-child(2)').html(object.state.progress.time);
|
||||
$('#repl-progress table tr:nth-child(3) > td:nth-child(2)').html(object.state.progress.failedConnects);
|
||||
},
|
||||
|
||||
getReplicationStatistics: function() {
|
||||
var self = this;
|
||||
|
||||
$.ajax(
|
||||
'/_api/replication/applier-state',
|
||||
{async: true}
|
||||
).done(
|
||||
function (d) {
|
||||
console.log(d);
|
||||
if (d.hasOwnProperty('state')) {
|
||||
var running;
|
||||
if (d.state.running) {
|
||||
running = "Enabled";
|
||||
}
|
||||
else {
|
||||
running = "Disabled";
|
||||
}
|
||||
running = '<span class="state">' + running + '</span>';
|
||||
$('#replication-chart .dashboard-sub-bar').html("Replication " + running);
|
||||
|
||||
self.renderReplicationStatistics(d);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getStatistics: function (callback) {
|
||||
var self = this;
|
||||
var url = "/_db/_system/_admin/aardvark/statistics/short";
|
||||
|
@ -453,6 +492,8 @@
|
|||
}
|
||||
self.updateCharts();
|
||||
});
|
||||
|
||||
this.getReplicationStatistics();
|
||||
},
|
||||
|
||||
getHistoryStatistics: function (figure) {
|
||||
|
|
|
@ -47,6 +47,74 @@
|
|||
}
|
||||
}
|
||||
|
||||
.dashboard-full-width-chart {
|
||||
@extend %dashboard-chart-basic;
|
||||
border: 1px solid rgba(104, 103, 102, .10);
|
||||
border-radius: 3px;
|
||||
margin-right: 12px;
|
||||
|
||||
.dashboard-full-width-chart-inner {
|
||||
@extend %dashboard-chart-box;
|
||||
@extend %pull-left;
|
||||
background-color: $c-white;
|
||||
border-left: $dashboard-borderwidth solid $c-white;
|
||||
border-right: $dashboard-borderwidth solid $c-white;
|
||||
border-top: $dashboard-borderwidth solid $c-white;
|
||||
padding-bottom: $dashboard-padding;
|
||||
padding-top: $dashboard-padding + 2px;
|
||||
|
||||
.dashboard-subtitle-bar {
|
||||
|
||||
&.top {
|
||||
border-bottom: 1px solid $c-e1grey;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.dashboard-interior-chart {
|
||||
@extend %pull-left;
|
||||
border-left: 1px solid $c-e1grey;
|
||||
|
||||
.inner {
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
|
||||
|
||||
table {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
|
||||
td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
td:first-child {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.dashboard-interior-chart:first-child {
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.state {
|
||||
background-color: $c-white;
|
||||
border-radius: 5px;
|
||||
color: $c-black;
|
||||
margin-left: 5px;
|
||||
padding-left: 3px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-large-chart {
|
||||
@extend %dashboard-chart-basic;
|
||||
|
|
|
@ -147,6 +147,26 @@
|
|||
width: $content-size;
|
||||
}
|
||||
|
||||
.dashboard-full-width-chart {
|
||||
$int-width: $content-size - 3px;
|
||||
width: $int-width;
|
||||
|
||||
.dashboard-full-width-chart-inner {
|
||||
width: $int-width - 10px;
|
||||
|
||||
.dashboard-interior-chart {
|
||||
float: left;
|
||||
$int-height: (($dashboard-height - 29px) / 2) - $tendency-height-corrector;
|
||||
height: $int-height;
|
||||
width: (($int-width - 11px) / 3) - 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-sub-bar {
|
||||
width: $int-width - 11px;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-large-chart {
|
||||
$int-width: ($content-size * 2 / 3) - 4px - 2px;
|
||||
width: $int-width;
|
||||
|
|
|
@ -88,14 +88,14 @@ var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
|
|||
var AqlHighlightRules = function() {
|
||||
|
||||
var keywords = (
|
||||
"for|return|filter|sort|limit|let|collect|asc|desc|if|in|into|insert|update|remove|replace|options|with|and|or|not|distinct"
|
||||
"for|return|filter|sort|limit|let|collect|asc|desc|in|into|insert|update|remove|replace|upsert|options|with|and|or|not|distinct"
|
||||
);
|
||||
|
||||
var builtinFunctions = (
|
||||
"(to_bool|to_number|to_string|to_list|is_null|is_bool|is_number|is_string|is_list|is_document|" +
|
||||
"concat|concat_separator|char_length|lower|upper|substring|left|right|trim|reverse|contains|" +
|
||||
"like|floor|ceil|round|abs|rand|sqrt|length|min|max|average|sum|median|variance_population|" +
|
||||
"variance_sample|first|last|unique|matches|merge|merge_recursive|has|attributes|values|unset|keep|" +
|
||||
"variance_sample|first|last|unique|matches|merge|merge_recursive|has|attributes|values|unset|unset_recursive|keep|" +
|
||||
"near|within|within_rectangle|is_in_polygon|fulltext|paths|traversal|traversal_tree|edges|stddev_sample|stddev_population|" +
|
||||
"slice|nth|position|translate|zip|call|apply|push|append|pop|shift|unshift|remove_value|remove_values|" +
|
||||
"remove_nth|graph_paths|shortest_path|graph_shortest_path|graph_distance_to|graph_traversal|graph_traversal_tree|graph_edges|" +
|
||||
|
@ -107,7 +107,7 @@ var AqlHighlightRules = function() {
|
|||
"date_add|date_subtract|date_diff|date_compare|date_format|fail|passthru|sleep|not_null|" +
|
||||
"first_list|first_document|parse_identifier|current_user|current_database|" +
|
||||
"collections|document|union|union_distinct|intersection|flatten|" +
|
||||
"ltrim|rtrim|find_first|find_last|split|substitute|assemble|md5|sha1|random_token|AQL_LAST_ENTRY)"
|
||||
"ltrim|rtrim|find_first|find_last|split|substitute|md5|sha1|random_token|AQL_LAST_ENTRY)"
|
||||
);
|
||||
|
||||
var keywordMapper = this.createKeywordMapper({
|
||||
|
@ -142,7 +142,7 @@ var AqlHighlightRules = function() {
|
|||
regex : "[a-zA-Z_][a-zA-Z0-9_]*\\b"
|
||||
}, {
|
||||
token : "keyword.operator",
|
||||
regex : "\\+|\\-|\\/|\\/\\/|%|@>|<@|&&|\\||!|<|>|<=|=>|==|!=|="
|
||||
regex : "\\+|\\-|\\/|\\/\\/|%|@>|<@|&&|\\|\\||!|<|>|<=|=>|==|!=|=|\\[\\*\\]"
|
||||
}, {
|
||||
token : "paren.lparen",
|
||||
regex : "[\\(\\{]"
|
||||
|
|
|
@ -686,6 +686,9 @@ function explain (data, options, shouldPrint, bindVars) {
|
|||
throw "ArangoStatement needs initial data";
|
||||
}
|
||||
|
||||
if (options === undefined) {
|
||||
options = data.options;
|
||||
}
|
||||
options = options || { };
|
||||
setColors(options.colors === undefined ? true : options.colors);
|
||||
|
||||
|
|
|
@ -168,12 +168,12 @@ function getIndexMap (shard) {
|
|||
function writeLocked (lockInfo, cb, args) {
|
||||
var timeout = lockInfo.timeout;
|
||||
if (timeout === undefined) {
|
||||
timeout = 5;
|
||||
timeout = 60;
|
||||
}
|
||||
|
||||
var ttl = lockInfo.ttl;
|
||||
if (ttl === undefined) {
|
||||
ttl = 10;
|
||||
ttl = 120;
|
||||
}
|
||||
if (require("internal").coverage || require("internal").valgrind) {
|
||||
ttl *= 10;
|
||||
|
|
|
@ -165,9 +165,9 @@ function ReplicationSuite () {
|
|||
break;
|
||||
}
|
||||
|
||||
if (compareTicks(slaveState.state.lastAppliedContinuousTick, syncResult.lastLogTick) > 0 ||
|
||||
compareTicks(slaveState.state.lastProcessedContinuousTick, syncResult.lastLogTick) > 0 ||
|
||||
compareTicks(slaveState.state.lastAvailableContinuousTick, syncResult.lastLogTick) > 0) {
|
||||
if (compareTicks(slaveState.state.lastAppliedContinuousTick, syncResult.lastLogTick) >= 0 ||
|
||||
compareTicks(slaveState.state.lastProcessedContinuousTick, syncResult.lastLogTick) >= 0) { // ||
|
||||
// compareTicks(slaveState.state.lastAvailableContinuousTick, syncResult.lastLogTick) > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -226,11 +226,11 @@ function ReplicationSuite () {
|
|||
function (state) {
|
||||
// flush the wal logs on the master so the start tick is not available
|
||||
// anymore when we start replicating
|
||||
for (var i = 0; i < 25; ++i) {
|
||||
for (var i = 0; i < 30; ++i) {
|
||||
db._collection(cn).save({ value: i });
|
||||
internal.wal.flush(); //true, true);
|
||||
}
|
||||
internal.wait(5, false);
|
||||
internal.wait(6, false);
|
||||
},
|
||||
|
||||
function (state) {
|
||||
|
@ -239,7 +239,7 @@ function ReplicationSuite () {
|
|||
|
||||
function (state) {
|
||||
// data loss on slave!
|
||||
assertTrue(db._collection(cn).count() < 20);
|
||||
assertTrue(db._collection(cn).count() < 25);
|
||||
},
|
||||
{
|
||||
requireFromPresent: false
|
||||
|
@ -262,16 +262,16 @@ function ReplicationSuite () {
|
|||
function (state) {
|
||||
// flush the wal logs on the master so the start tick is not available
|
||||
// anymore when we start replicating
|
||||
for (var i = 0; i < 25; ++i) {
|
||||
for (var i = 0; i < 30; ++i) {
|
||||
db._collection(cn).save({ value: i });
|
||||
internal.wal.flush(); //true, true);
|
||||
}
|
||||
internal.wait(5, false);
|
||||
internal.wait(6, false);
|
||||
},
|
||||
|
||||
function (state) {
|
||||
// wait for slave applier to have started and detect the mess
|
||||
internal.wait(2, false);
|
||||
internal.wait(3, false);
|
||||
|
||||
// slave should have stopped
|
||||
assertFalse(replication.applier.state().state.running);
|
||||
|
@ -282,7 +282,7 @@ function ReplicationSuite () {
|
|||
|
||||
function (state) {
|
||||
// data loss on slave!
|
||||
assertTrue(db._collection(cn).count() < 20);
|
||||
assertTrue(db._collection(cn).count() < 25);
|
||||
},
|
||||
{
|
||||
requireFromPresent: true
|
||||
|
|
|
@ -159,9 +159,9 @@ function ReplicationSuite () {
|
|||
break;
|
||||
}
|
||||
|
||||
if (compareTicks(slaveState.state.lastAppliedContinuousTick, syncResult.lastLogTick) > 0 ||
|
||||
compareTicks(slaveState.state.lastProcessedContinuousTick, syncResult.lastLogTick) > 0 ||
|
||||
compareTicks(slaveState.state.lastAvailableContinuousTick, syncResult.lastLogTick) > 0) {
|
||||
if (compareTicks(slaveState.state.lastAppliedContinuousTick, syncResult.lastLogTick) >= 0 ||
|
||||
compareTicks(slaveState.state.lastProcessedContinuousTick, syncResult.lastLogTick) >= 0) { //||
|
||||
// compareTicks(slaveState.state.lastAvailableContinuousTick, syncResult.lastLogTick) > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue