1
0
Fork 0

Merge branch 'devel' into schmutz-ng

This commit is contained in:
Max Neunhoeffer 2017-01-19 14:53:46 +01:00
commit 427c8e4553
14 changed files with 315 additions and 167 deletions

View File

@ -142,6 +142,13 @@ class Buffer {
initWithNone();
}
void resetTo(ValueLength position) {
if (position >= _alloc) {
throw Exception(Exception::IndexOutOfBounds);
}
_pos = position;
}
void clear() {
reset();
if (_buffer != _local) {

View File

@ -51,19 +51,13 @@ class ArrayIterator {
reset();
}
ArrayIterator(ArrayIterator const& other)
ArrayIterator(ArrayIterator const& other) noexcept
: _slice(other._slice),
_size(other._size),
_position(other._position),
_current(other._current) {}
ArrayIterator& operator=(ArrayIterator const& other) {
_slice = other._slice;
_size = other._size;
_position = other._position;
_current = other._current;
return *this;
}
ArrayIterator& operator=(ArrayIterator const& other) = delete;
// prefix ++
ArrayIterator& operator++() {
@ -94,18 +88,26 @@ class ArrayIterator {
return _slice.at(_position);
}
ArrayIterator begin() { return ArrayIterator(_slice); }
ArrayIterator begin() {
auto it = ArrayIterator(*this);
it._position = 0;
return it;
}
ArrayIterator begin() const { return ArrayIterator(_slice); }
ArrayIterator begin() const {
auto it = ArrayIterator(*this);
it._position = 0;
return it;
}
ArrayIterator end() {
auto it = ArrayIterator(_slice);
auto it = ArrayIterator(*this);
it._position = it._size;
return it;
}
ArrayIterator end() const {
auto it = ArrayIterator(_slice);
auto it = ArrayIterator(*this);
it._position = it._size;
return it;
}
@ -165,7 +167,7 @@ class ArrayIterator {
private:
Slice _slice;
ValueLength _size;
ValueLength const _size;
ValueLength _position;
uint8_t const* _current;
};
@ -197,21 +199,14 @@ class ObjectIterator {
}
}
ObjectIterator(ObjectIterator const& other)
ObjectIterator(ObjectIterator const& other) noexcept
: _slice(other._slice),
_size(other._size),
_position(other._position),
_current(other._current),
_allowRandomIteration(other._allowRandomIteration) {}
ObjectIterator& operator=(ObjectIterator const& other) {
_slice = other._slice;
_size = other._size;
_position = other._position;
_current = other._current;
_allowRandomIteration = other._allowRandomIteration;
return *this;
}
ObjectIterator& operator=(ObjectIterator const& other) = delete;
// prefix ++
ObjectIterator& operator++() {
@ -246,18 +241,26 @@ class ObjectIterator {
return ObjectPair(_slice.getNthKey(_position, true), _slice.getNthValue(_position));
}
ObjectIterator begin() { return ObjectIterator(_slice, _allowRandomIteration); }
ObjectIterator begin() {
auto it = ObjectIterator(*this);
it._position = 0;
return it;
}
ObjectIterator begin() const { return ObjectIterator(_slice, _allowRandomIteration); }
ObjectIterator begin() const {
auto it = ObjectIterator(*this);
it._position = 0;
return it;
}
ObjectIterator end() {
auto it = ObjectIterator(_slice, _allowRandomIteration);
auto it = ObjectIterator(*this);
it._position = it._size;
return it;
}
ObjectIterator end() const {
auto it = ObjectIterator(_slice, _allowRandomIteration);
auto it = ObjectIterator(*this);
it._position = it._size;
return it;
}
@ -300,10 +303,10 @@ class ObjectIterator {
private:
Slice _slice;
ValueLength _size;
ValueLength const _size;
ValueLength _position;
uint8_t const* _current;
bool _allowRandomIteration;
bool const _allowRandomIteration;
};
} // namespace arangodb::velocypack

View File

@ -24,6 +24,11 @@
#include "AgencyComm.h"
#include <thread>
#ifdef DEBUG_SYNC_REPLICATION
#include <atomic>
#endif
#include <velocypack/Iterator.h>
#include <velocypack/Sink.h>
#include <velocypack/velocypack-aliases.h>
@ -45,11 +50,6 @@
#include "SimpleHttpClient/SimpleHttpClient.h"
#include "SimpleHttpClient/SimpleHttpResult.h"
#include <thread>
#ifdef DEBUG_SYNC_REPLICATION
#include <atomic>
#endif
using namespace arangodb;
using namespace arangodb::application_features;
using namespace arangodb::httpclient;
@ -209,17 +209,22 @@ std::string AgencyWriteTransaction::toJson() const {
void AgencyWriteTransaction::toVelocyPack(VPackBuilder& builder) const {
VPackArrayBuilder guard(&builder);
{
VPackObjectBuilder guard2(&builder);
VPackObjectBuilder guard2(&builder); // Writes
for (AgencyOperation const& operation : operations) {
operation.toVelocyPack(builder);
}
}
if (preconditions.size() > 0) {
VPackObjectBuilder guard3(&builder);
if (preconditions.size() > 0) {
VPackObjectBuilder guard3(&builder); // Preconditions
for (AgencyPrecondition const& precondition : preconditions) {
precondition.toVelocyPack(builder);
}
} else {
VPackObjectBuilder guard3(&builder);
}
builder.add(VPackValue(clientId)); // Transactions
}
bool AgencyWriteTransaction::validate(AgencyCommResult const& result) const {
@ -278,6 +283,7 @@ void AgencyGeneralTransaction::toVelocyPack(VPackBuilder& builder) const {
} else {
std::get<0>(operation).toGeneralBuilder(builder);
std::get<1>(operation).toGeneralBuilder(builder);
builder.add(VPackValue(clientId));
}
}
}
@ -322,18 +328,23 @@ AgencyCommResult::AgencyCommResult()
_body(),
_values(),
_statusCode(0),
_connected(false) {}
_connected(false),
_clientId("") {}
AgencyCommResult::AgencyCommResult(int code, std::string const& message)
AgencyCommResult::AgencyCommResult(
int code, std::string const& message, std::string const& clientId)
: _location(),
_message(message),
_body(),
_values(),
_statusCode(code),
_connected(false) {}
_connected(false),
_clientId(clientId) {}
bool AgencyCommResult::connected() const { return _connected; }
std::string AgencyCommResult::clientId() const { return _clientId; }
int AgencyCommResult::httpCode() const { return _statusCode; }
int AgencyCommResult::errorCode() const {
@ -1064,11 +1075,12 @@ AgencyCommResult AgencyComm::sendTransactionWithFailover(
AgencyCommResult result = sendWithFailover(
arangodb::rest::RequestType::POST,
(timeout == 0.0 ? AgencyCommManager::CONNECTION_OPTIONS._requestTimeout
: timeout),
url, builder.slice().toJson());
(timeout == 0.0) ?
AgencyCommManager::CONNECTION_OPTIONS._requestTimeout : timeout,
url, builder.slice().toJson(), transaction.getClientId());
if (!result.successful() && result.httpCode() != 412) {
if (!result.successful() && result.httpCode() !=
(int)arangodb::rest::ResponseCode::PRECONDITION_FAILED) {
return result;
}
@ -1278,13 +1290,13 @@ void AgencyComm::updateEndpoints(arangodb::velocypack::Slice const& current) {
AgencyCommResult AgencyComm::sendWithFailover(
arangodb::rest::RequestType method, double const timeout,
std::string const& initialUrl, std::string const& body) {
std::string const& initialUrl, std::string const& body,
std::string const& clientId) {
std::string endpoint;
std::unique_ptr<GeneralClientConnection> connection =
AgencyCommManager::MANAGER->acquire(endpoint);
AgencyCommResult result;
std::string url = initialUrl;
@ -1320,7 +1332,7 @@ AgencyCommResult AgencyComm::sendWithFailover(
++tries;
if (connection == nullptr) {
AgencyCommResult result(400, "No endpoints for agency found.");
AgencyCommResult result(400, "No endpoints for agency found.", clientId);
LOG_TOPIC(ERR, Logger::AGENCYCOMM) << result._message;
return result;
}
@ -1337,7 +1349,7 @@ AgencyCommResult AgencyComm::sendWithFailover(
// try to send; if we fail completely, do not retry
try {
result = send(connection.get(), method, conTimeout, url, body);
result = send(connection.get(), method, conTimeout, url, body, clientId);
} catch (...) {
AgencyCommManager::MANAGER->failed(std::move(connection), endpoint);
endpoint.clear();
@ -1397,7 +1409,7 @@ AgencyCommResult AgencyComm::sendWithFailover(
AgencyCommResult AgencyComm::send(
arangodb::httpclient::GeneralClientConnection* connection,
arangodb::rest::RequestType method, double timeout, std::string const& url,
std::string const& body) {
std::string const& body, std::string const& clientId) {
TRI_ASSERT(connection != nullptr);
if (method == arangodb::rest::RequestType::GET ||
@ -1411,6 +1423,9 @@ AgencyCommResult AgencyComm::send(
AgencyCommResult result;
result._connected = false;
result._statusCode = 0;
if (!clientId.empty()) {
result._clientId = clientId;
}
LOG_TOPIC(TRACE, Logger::AGENCYCOMM)
<< "sending " << arangodb::HttpRequest::translateMethod(method)

View File

@ -27,12 +27,16 @@
#include "Basics/Common.h"
#include <list>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <velocypack/Slice.h>
#include <velocypack/velocypack-aliases.h>
#include <type_traits>
#include <list>
#include "Basics/Mutex.h"
#include "Rest/HttpRequest.h"
#include "SimpleHttpClient/GeneralClientConnection.h"
@ -214,7 +218,9 @@ class AgencyOperation {
class AgencyCommResult {
public:
AgencyCommResult();
AgencyCommResult(int code, std::string const& message);
AgencyCommResult(int code, std::string const& message,
std::string const& transactionId = std::string());
~AgencyCommResult() = default;
public:
@ -226,6 +232,8 @@ class AgencyCommResult {
int errorCode() const;
std::string clientId() const;
std::string errorMessage() const;
std::string errorDetails() const;
@ -252,6 +260,9 @@ class AgencyCommResult {
private:
std::shared_ptr<velocypack::Builder> _vpack;
public:
std::string _clientId;
};
// -----------------------------------------------------------------------------
@ -268,7 +279,8 @@ public:
virtual std::string toJson() const = 0;
virtual void toVelocyPack(arangodb::velocypack::Builder&) const = 0;
virtual std::string const& path() const = 0;
virtual std::string getClientId() const = 0;
virtual bool validate(AgencyCommResult const& result) const = 0;
};
@ -280,13 +292,15 @@ public:
struct AgencyGeneralTransaction : public AgencyTransaction {
explicit AgencyGeneralTransaction(
std::pair<AgencyOperation,AgencyPrecondition> const& operation) {
std::pair<AgencyOperation,AgencyPrecondition> const& operation) :
clientId(to_string(boost::uuids::random_generator()())) {
operations.push_back(operation);
}
explicit AgencyGeneralTransaction(
std::vector<std::pair<AgencyOperation,AgencyPrecondition>> const& _operations)
: operations(_operations) {}
std::vector<std::pair<AgencyOperation,AgencyPrecondition>> const& _opers) :
operations(_opers),
clientId(to_string(boost::uuids::random_generator()())) {}
AgencyGeneralTransaction() = default;
@ -299,12 +313,16 @@ struct AgencyGeneralTransaction : public AgencyTransaction {
void push_back(std::pair<AgencyOperation,AgencyPrecondition> const&);
inline std::string const& path() const override final {
inline virtual std::string const& path() const override final {
return AgencyTransaction::TypeUrl[2];
}
virtual bool validate(AgencyCommResult const& result) const override final;
inline virtual std::string getClientId() const override final {
return clientId;
}
virtual bool validate(AgencyCommResult const& result) const override final;
std::string clientId;
};
@ -315,23 +333,26 @@ struct AgencyGeneralTransaction : public AgencyTransaction {
struct AgencyWriteTransaction : public AgencyTransaction {
public:
explicit AgencyWriteTransaction(AgencyOperation const& operation) {
explicit AgencyWriteTransaction(AgencyOperation const& operation) :
clientId(to_string(boost::uuids::random_generator()())) {
operations.push_back(operation);
}
explicit AgencyWriteTransaction(
std::vector<AgencyOperation> const& _operations)
: operations(_operations) {}
explicit AgencyWriteTransaction (std::vector<AgencyOperation> const& _opers) :
operations(_opers),
clientId(to_string(boost::uuids::random_generator()())) {}
AgencyWriteTransaction(AgencyOperation const& operation,
AgencyPrecondition const& precondition) {
AgencyPrecondition const& precondition) :
clientId(to_string(boost::uuids::random_generator()())) {
operations.push_back(operation);
preconditions.push_back(precondition);
}
AgencyWriteTransaction(std::vector<AgencyOperation> const& _operations,
AgencyPrecondition const& precondition) {
AgencyPrecondition const& precondition) :
clientId(to_string(boost::uuids::random_generator()())) {
for (auto const& op : _operations) {
operations.push_back(op);
}
@ -339,7 +360,8 @@ public:
}
AgencyWriteTransaction(std::vector<AgencyOperation> const& opers,
std::vector<AgencyPrecondition> const& precs) {
std::vector<AgencyPrecondition> const& precs) :
clientId(to_string(boost::uuids::random_generator()())) {
for (auto const& op : opers) {
operations.push_back(op);
}
@ -355,14 +377,19 @@ public:
std::string toJson() const override final;
inline std::string const& path() const override final {
inline virtual std::string const& path() const override final {
return AgencyTransaction::TypeUrl[1];
}
inline virtual std::string getClientId() const override final {
return clientId;
}
virtual bool validate(AgencyCommResult const& result) const override final;
std::vector<AgencyPrecondition> preconditions;
std::vector<AgencyOperation> operations;
std::string clientId;
};
// -----------------------------------------------------------------------------
@ -416,6 +443,10 @@ public:
return AgencyTransaction::TypeUrl[3];
}
inline virtual std::string getClientId() const override final {
return std::string();
}
virtual bool validate(AgencyCommResult const& result) const override final;
std::vector<AgencyPrecondition> preconditions;
@ -443,10 +474,14 @@ public:
std::string toJson() const override final;
inline std::string const& path() const override final {
inline virtual std::string const& path() const override final {
return AgencyTransaction::TypeUrl[0];
}
inline virtual std::string getClientId() const override final {
return std::string();
}
virtual bool validate(AgencyCommResult const& result) const override final;
std::vector<std::string> keys;
@ -603,7 +638,8 @@ class AgencyComm {
bool ensureStructureInitialized();
AgencyCommResult sendWithFailover(arangodb::rest::RequestType, double,
std::string const&, std::string const&);
std::string const&, std::string const&,
std::string const& clientId = std::string());
private:
bool lock(std::string const&, double, double,
@ -612,7 +648,8 @@ class AgencyComm {
bool unlock(std::string const&, arangodb::velocypack::Slice const&, double);
AgencyCommResult send(httpclient::GeneralClientConnection*, rest::RequestType,
double, std::string const&, std::string const&);
double, std::string const&, std::string const&,
std::string const& clientId = std::string());
bool tryInitializeStructure(std::string const& jwtSecret);

View File

@ -616,7 +616,9 @@ trans_ret_t Agent::transact(query_t const& queries) {
for (const auto& query : VPackArrayIterator(qs)) {
if (query[0].isObject()) {
if(_spearhead.apply(query)) {
maxind = _state.log(query[0], term());
maxind = (query.length() == 3 && query[2].isString()) ?
_state.log(query[0], term(), query[2].copyString()) :
_state.log(query[0], term());
ret->add(VPackValue(maxind));
} else {
ret->add(VPackValue(0));
@ -651,30 +653,38 @@ trans_ret_t Agent::transact(query_t const& queries) {
// Non-persistent write to non-persisted key-value store
write_ret_t Agent::transient(query_t const& query) {
std::vector<bool> applied;
std::vector<index_t> indices;
trans_ret_t Agent::transient(query_t const& queries) {
auto ret = std::make_shared<arangodb::velocypack::Builder>();
auto leader = _constituent.leaderID();
if (leader != id()) {
return write_ret_t(false, leader);
return trans_ret_t(false, leader);
}
// Apply to spearhead and get indices for log entries
{
VPackArrayBuilder b(ret.get());
MUTEX_LOCKER(mutexLocker, _ioLock);
// Only leader else redirect
if (challengeLeadership()) {
_constituent.candidate();
return write_ret_t(false, NO_LEADER);
return trans_ret_t(false, NO_LEADER);
}
applied = _transient.apply(query);
// Read and writes
for (const auto& query : VPackArrayIterator(queries->slice())) {
if (query[0].isObject()) {
_transient.apply(query);
} else if (query[0].isString()) {
_transient.read(query, *ret);
}
}
}
return write_ret_t(true, id());
return trans_ret_t(true, id(), 0, 0, ret);
}
@ -695,14 +705,17 @@ inquire_ret_t Agent::inquire(query_t const& query) {
{
VPackArrayBuilder b(builder.get());
for (auto const& i : si) {
VPackObjectBuilder bb(builder.get());
builder->add("index", VPackValue(i.index));
builder->add("term", VPackValue(i.term));
builder->add("query", VPackSlice(i.entry->data()));
builder->add("index", VPackValue(i.index));
VPackArrayBuilder bb(builder.get());
for (auto const& j : i) {
VPackObjectBuilder bbb(builder.get());
builder->add("index", VPackValue(j.index));
builder->add("term", VPackValue(j.term));
builder->add("query", VPackSlice(j.entry->data()));
builder->add("index", VPackValue(j.index));
}
}
}
ret = inquire_ret_t(true, id(), builder);
return ret;
}
@ -797,7 +810,6 @@ void Agent::run() {
} else {
_appendCV.wait(1000000);
updateConfiguration();
}
}
@ -897,9 +909,9 @@ void Agent::detectActiveAgentFailures() {
system_clock::now() - lastAcked.at(id)).count();
if (ds > 180.0) {
std::string repl = _config.nextAgentInLine();
LOG_TOPIC(DEBUG, Logger::AGENCY) << "Active agent " << id << " has failed. << "
<< repl << " will be promoted to active agency membership";
// Guarded in ::
LOG_TOPIC(DEBUG, Logger::AGENCY)
<< "Active agent " << id << " has failed. << " << repl
<< " will be promoted to active agency membership";
_activator = std::make_unique<AgentActivator>(this, id, repl);
_activator->start();
return;
@ -910,13 +922,6 @@ void Agent::detectActiveAgentFailures() {
}
void Agent::updateConfiguration() {
// First ask last know leader
}
/// Orderly shutdown
void Agent::beginShutdown() {
Thread::beginShutdown();

View File

@ -94,7 +94,7 @@ class Agent : public arangodb::Thread {
bool load();
/// @brief Unpersisted key-value-store
write_ret_t transient(query_t const&);
trans_ret_t transient(query_t const&);
/// @brief Attempt write
write_ret_t write(query_t const&);
@ -223,9 +223,6 @@ class Agent : public arangodb::Thread {
/// @brief persist agency configuration in RAFT
void persistConfiguration(term_t t);
/// @brief Update my configuration as passive agent
void updateConfiguration();
/// @brief Find out, if we've had acknowledged RPCs recent enough
bool challengeLeadership();

View File

@ -146,7 +146,7 @@ RestStatus RestAgencyHandler::handleTransient() {
std::this_thread::sleep_for(duration_t(100));
}
write_ret_t ret;
trans_ret_t ret;
try {
ret = _agent->transient(query);

View File

@ -154,9 +154,8 @@ std::vector<arangodb::consensus::index_t> State::log(
/// Log transaction (leader)
arangodb::consensus::index_t State::log(
velocypack::Slice const& slice, term_t term) {
velocypack::Slice const& slice, term_t term, std::string const& clientId) {
std::string clientId;
arangodb::consensus::index_t idx = 0;
auto buf = std::make_shared<Buffer<uint8_t>>();
@ -165,6 +164,8 @@ arangodb::consensus::index_t State::log(
TRI_ASSERT(!_log.empty()); // log must not ever be empty
idx = _log.back().index + 1;
_log.push_back(log_t(idx, term, buf, clientId)); // log to RAM
_clientIdLookupTable.emplace(
std::pair<std::string, arangodb::consensus::index_t>(clientId, idx));
persist(idx, term, slice, clientId); // log to disk
return _log.back().index;
@ -839,9 +840,9 @@ query_t State::allLogs() const {
}
std::vector<log_t> State::inquire(query_t const& query) const {
std::vector<std::vector<log_t>> State::inquire(query_t const& query) const {
std::vector<log_t> result;
std::vector<std::vector<log_t>> result;
MUTEX_LOCKER(mutexLocker, _logLock); // Cannot be read lock (Compaction)
if (!query->slice().isArray()) {
@ -861,13 +862,15 @@ std::vector<log_t> State::inquire(query_t const& query) const {
+ std::to_string(pos) + " we got " + i.toJson());
}
std::vector<log_t> transactions;
auto ret = _clientIdLookupTable.equal_range(i.copyString());
for (auto it = ret.first; it != ret.second; ++it) {
if (it->second < _log[0].index) {
continue;
}
result.push_back(_log.at(it->second-_cur));
transactions.push_back(_log.at(it->second-_cur));
}
result.push_back(transactions);
pos++;

View File

@ -65,7 +65,9 @@ class State {
std::vector<bool> const& indices, term_t term);
/// @brief Single log entry (leader)
arangodb::consensus::index_t log(velocypack::Slice const& slice, term_t term);
arangodb::consensus::index_t log(
velocypack::Slice const& slice, term_t term,
std::string const& clientId = std::string());
/// @brief Log entries (followers)
arangodb::consensus::index_t log(query_t const& queries, size_t ndups = 0);
@ -79,7 +81,7 @@ class State {
index_t = 0, index_t = (std::numeric_limits<uint64_t>::max)()) const;
/// @brief Get log entries by client Id
std::vector<log_t> inquire(query_t const&) const;
std::vector<std::vector<log_t>> inquire(query_t const&) const;
/// @brief Get complete logged commands by lower and upper bounds.
/// Default: [first, last]
@ -182,6 +184,10 @@ class State {
/// @brief Operation options
OperationOptions _options;
/// @brief Empty log entry;
static log_t emptyLog;
};
}
}

View File

@ -205,6 +205,7 @@ bool Store::apply(Slice const& query, bool verbose) {
success = applies(query[0]);
break;
case 2: // precondition
case 3: // precondition + clientId
if (check(query[1])) {
success = applies(query[0]);
} else { // precondition failed

View File

@ -903,10 +903,11 @@ int ClusterInfo::createDatabaseCoordinator(std::string const& name,
(int)arangodb::rest::ResponseCode::PRECONDITION_FAILED) {
return setErrormsg(TRI_ERROR_ARANGO_DUPLICATE_NAME, errorMsg);
}
errorMsg = std::string("Failed to create database in ") + __FILE__ + ":" + std::to_string(__LINE__);
errorMsg = std::string("Failed to create database with ") +
res._clientId + " at " + __FILE__ + ":" + std::to_string(__LINE__);
return setErrormsg(TRI_ERROR_CLUSTER_COULD_NOT_CREATE_DATABASE_IN_PLAN,
errorMsg);
}
}
// Now update our own cache of planned databases:
loadPlan();
@ -1171,6 +1172,7 @@ int ClusterInfo::createCollectionCoordinator(std::string const& databaseName,
LOG_TOPIC(ERR, Logger::CLUSTER) << "Could not get agency dump!";
}
} else {
errorMsg += std::string("\nClientId ") + res._clientId;
errorMsg += std::string("\n") + __FILE__ + std::to_string(__LINE__);
errorMsg += std::string("\n") + res.errorMessage();
errorMsg += std::string("\n") + res.errorDetails();
@ -1295,9 +1297,9 @@ int ClusterInfo::dropCollectionCoordinator(std::string const& databaseName,
res = ac.sendTransactionWithFailover(trans);
if (!res.successful()) {
LOG(ERR) << "###################### WAS ERLAUBE? ####################";
AgencyCommResult ag = ac.getValues("");
if (ag.successful()) {
LOG_TOPIC(ERR, Logger::CLUSTER) << "ClientId: " << res._clientId;
LOG_TOPIC(ERR, Logger::CLUSTER) << "Agency dump:\n"
<< ag.slice().toJson();
} else {
@ -1756,6 +1758,7 @@ int ClusterInfo::ensureIndexCoordinator(
AgencyCommResult result = ac.sendTransactionWithFailover(trx, 0.0);
if (!result.successful()) {
errorMsg += "ClientId: " + result._clientId;
errorMsg += std::string(" ") + __FILE__ + ":" + std::to_string(__LINE__);
resultBuilder = *resBuilder;
return TRI_ERROR_CLUSTER_COULD_NOT_CREATE_INDEX_IN_PLAN;
@ -1976,6 +1979,7 @@ int ClusterInfo::dropIndexCoordinator(std::string const& databaseName,
AgencyCommResult result = ac.sendTransactionWithFailover(trx, 0.0);
if (!result.successful()) {
errorMsg += "ClientId: " + result._clientId;
errorMsg += std::string(" ") + __FILE__ + ":" + std::to_string(__LINE__);
events::DropIndex(collectionID, idString,
TRI_ERROR_CLUSTER_COULD_NOT_DROP_INDEX_IN_PLAN);
@ -2045,20 +2049,20 @@ void ClusterInfo::loadServers() {
result.slice()[0].get(
std::vector<std::string>(
{AgencyCommManager::path(), "Current", "ServersRegistered"}));
velocypack::Slice serversAliases =
result.slice()[0].get(
std::vector<std::string>(
{AgencyCommManager::path(), "Target", "MapUniqueToShortID"}));
if (serversRegistered.isObject()) {
if (serversRegistered.isObject()) {
decltype(_servers) newServers;
decltype(_serverAliases) newAliases;
size_t i = 0;
for (auto const& res : VPackObjectIterator(serversRegistered)) {
velocypack::Slice slice = res.value;
if (slice.isObject() && slice.hasKey("endpoint")) {
std::string server =
arangodb::basics::VelocyPackHelper::getStringValue(
@ -2075,7 +2079,7 @@ void ClusterInfo::loadServers() {
newServers.emplace(std::make_pair(res.key.copyString(), server));
}
}
// Now set the new value:
{
WRITE_LOCKER(writeLocker, _serversProt.lock);
@ -2087,13 +2091,13 @@ void ClusterInfo::loadServers() {
return;
}
}
LOG_TOPIC(DEBUG, Logger::CLUSTER)
<< "Error while loading " << prefixServers
<< " httpCode: " << result.httpCode()
<< " errorCode: " << result.errorCode()
<< " errorMessage: " << result.errorMessage()
<< " body: " << result.body();
<< "Error while loading " << prefixServers
<< " httpCode: " << result.httpCode()
<< " errorCode: " << result.errorCode()
<< " errorMessage: " << result.errorMessage()
<< " body: " << result.body();
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -3593,7 +3593,7 @@ void LogicalCollection::mergeObjectsForUpdate(
std::unordered_map<std::string, VPackSlice> newValues;
{
VPackObjectIterator it(newValue, false);
VPackObjectIterator it(newValue, true);
while (it.valid()) {
std::string key = it.key().copyString();
if (!key.empty() && key[0] == '_' &&
@ -3647,7 +3647,7 @@ void LogicalCollection::mergeObjectsForUpdate(
// add other attributes after the system attributes
{
VPackObjectIterator it(oldValue, false);
VPackObjectIterator it(oldValue, true);
while (it.valid()) {
std::string key = it.key().copyString();
// exclude system attributes in old value now
@ -3690,15 +3690,15 @@ void LogicalCollection::mergeObjectsForUpdate(
}
// add remaining values that were only in new object
for (auto& it : newValues) {
auto& s = it.second;
for (auto const& it : newValues) {
VPackSlice const& s = it.second;
if (s.isNone()) {
continue;
}
if (!keepNull && s.isNull()) {
continue;
}
b.add(std::move(it.first), s);
b.add(it.first, s);
}
b.close();

View File

@ -1,4 +1,3 @@
/* jshint strict: false, sub: true */
/* global print, arango */
'use strict';

View File

@ -296,90 +296,161 @@ function agencyTestSuite () {
testClientIds : function () {
var res;
var id = [guid(),guid(),guid(),guid(),guid(),
guid(),guid(),guid(),guid(),guid()];
var id = [guid(),guid(),guid(),guid(),guid(),guid(),
guid(),guid(),guid(),guid(),guid(),guid(),
guid(),guid(),guid()];
var query = [{"a":12},{"a":13},{"a":13}];
var pre = [{},{"a":12},{"a":12}];
writeAndCheck([[query[0], pre[0], id[0]]]);
res = accessAgency("inquire",[id[0]]).bodyParsed;
assertEqual(res.length, 1);
assertEqual(res[0].query, query[0]);
assertEqual(res[0].length, 1);
assertEqual(res[0][0].query, query[0]);
writeAndCheck([[query[1], pre[1], id[0]]]);
res = accessAgency("inquire",[id[0]]).bodyParsed;
assertEqual(res.length, 2);
assertEqual(res[0].query, query[0]);
assertEqual(res[1].query, query[1]);
assertEqual(res.length, 1);
assertEqual(res[0].length, 2);
assertEqual(res[0][0].query, query[0]);
assertEqual(res[0][1].query, query[1]);
res = accessAgency("write",[[query[1], pre[1], id[2]]]);
assertEqual(res.statusCode,412);
res = accessAgency("inquire",[id[2]]).bodyParsed;
assertEqual(res.length, 0);
assertEqual(res[0].length, 0);
res = accessAgency("write",[[query[0], pre[0], id[3]],
[query[1], pre[1], id[3]]]);
assertEqual(res.statusCode,200);
res = accessAgency("inquire",[id[3]]).bodyParsed;
assertEqual(res.length, 2);
assertEqual(res[0].query, query[0]);
assertEqual(res[1].query, query[1]);
assertEqual(res.length, 1);
assertEqual(res[0][0].query, query[0]);
assertEqual(res[0][1].query, query[1]);
res = accessAgency("write",[[query[0], pre[0], id[4]],
[query[1], pre[1], id[4]],
[query[2], pre[2], id[4]]]);
assertEqual(res.statusCode,412);
res = accessAgency("inquire",[id[4]]).bodyParsed;
assertEqual(res.length, 2);
assertEqual(res[0].query, query[0]);
assertEqual(res[1].query, query[1]);
assertEqual(res.length, 1);
assertEqual(res[0].length, 2);
assertEqual(res[0][0].query, query[0]);
assertEqual(res[0][1].query, query[1]);
res = accessAgency("write",[[query[0], pre[0], id[5]],
[query[2], pre[2], id[5]],
[query[1], pre[1], id[5]]]);
assertEqual(res.statusCode,412);
res = accessAgency("inquire",[id[5]]).bodyParsed;
assertEqual(res.length, 2);
assertEqual(res[0].query, query[0]);
assertEqual(res[1].query, query[1]);
assertEqual(res.length, 1);
assertEqual(res[0].length, 2);
assertEqual(res[0][0].query, query[0]);
assertEqual(res[0][1].query, query[1]);
res = accessAgency("write",[[query[2], pre[2], id[6]],
[query[0], pre[0], id[6]],
[query[1], pre[1], id[6]]]);
assertEqual(res.statusCode,412);
res = accessAgency("inquire",[id[6]]).bodyParsed;
assertEqual(res.length, 2);
assertEqual(res[0].query, query[0]);
assertEqual(res[1].query, query[1]);
assertEqual(res.length, 1);
assertEqual(res[0].length, 2);
assertEqual(res[0][0].query, query[0]);
assertEqual(res[0][1].query, query[1]);
res = accessAgency("write",[[query[2], pre[2], id[7]],
[query[0], pre[0], id[8]],
[query[1], pre[1], id[9]]]);
assertEqual(res.statusCode,412);
res = accessAgency("inquire",[id[7],id[8],id[9]]).bodyParsed;
assertEqual(res.length, 2);
assertEqual(res[0].query, query[0]);
assertEqual(res[1].query, query[1]);
assertEqual(res.length, 3);
assertEqual(res[0].length, 0);
assertEqual(res[1].length, 1);
assertEqual(res[1][0].query, query[0]);
assertEqual(res[2].length, 1);
assertEqual(res[2][0].query, query[1]);
res = accessAgency("inquire",[id[9],id[7],id[8]]).bodyParsed;
assertEqual(res.length, 2);
assertEqual(res[0].query, query[1]);
assertEqual(res[1].query, query[0]);
assertEqual(res.length, 3);
assertEqual(res[0].length, 1);
assertEqual(res[0][0].query, query[1]);
assertEqual(res[1].length, 0);
assertEqual(res[2].length, 1);
assertEqual(res[2][0].query, query[0]);
res = accessAgency("inquire",[id[8],id[9],id[7]]).bodyParsed;
assertEqual(res.length, 2);
assertEqual(res[0].query, query[0]);
assertEqual(res[1].query, query[1]);
assertEqual(res.length, 3);
assertEqual(res[0].length, 1);
assertEqual(res[0][0].query, query[0]);
assertEqual(res[1].length, 1);
assertEqual(res[1][0].query, query[1]);
assertEqual(res[2].length, 0);
res = accessAgency("inquire",[id[7],id[9],id[8]]).bodyParsed;
assertEqual(res.length, 2);
assertEqual(res[0].query, query[1]);
assertEqual(res[1].query, query[0]);
assertEqual(res.length, 3);
assertEqual(res[0].length, 0);
assertEqual(res[1].length, 1);
assertEqual(res[1][0].query, query[1]);
assertEqual(res[2].length, 1);
assertEqual(res[2][0].query, query[0]);
res = accessAgency("inquire",[id[8],id[7],id[9]]).bodyParsed;
assertEqual(res.length, 2);
assertEqual(res[0].query, query[0]);
assertEqual(res[1].query, query[1]);
assertEqual(res.length, 3);
assertEqual(res[0].length, 1);
assertEqual(res[0][0].query, query[0]);
assertEqual(res[1].length, 0);
assertEqual(res[2].length, 1);
assertEqual(res[2][0].query, query[1]);
res = accessAgency("inquire",[id[7],id[8],id[9]]).bodyParsed;
assertEqual(res.length, 3);
assertEqual(res[0].length, 0);
assertEqual(res[1].length, 1);
assertEqual(res[1][0].query, query[0]);
assertEqual(res[2].length, 1);
assertEqual(res[2][0].query, query[1]);
res = accessAgency("inquire",[id[7],id[8],id[9]]).bodyParsed;
assertEqual(res.length, 3);
assertEqual(res[0].length, 0);
assertEqual(res[1].length, 1);
assertEqual(res[1][0].query, query[0]);
assertEqual(res[2].length, 1);
assertEqual(res[2][0].query, query[1]);
res = accessAgency("write",[[query[2], pre[2], id[10]],
[query[0], pre[0], id[11]],
[query[1], pre[1], id[12]],
[query[0], pre[0], id[12]]]);
res = accessAgency("inquire",[id[10],id[11],id[12]]).bodyParsed;
assertEqual(res.length, 3);
assertEqual(res[0].length, 0);
assertEqual(res[1].length, 1);
assertEqual(res[1][0].query, query[0]);
assertEqual(res[2].length, 2);
assertEqual(res[2][0].query, query[1]);
assertEqual(res[2][1].query, query[0]);
res = accessAgency("transact",[[query[0], pre[0], id[13]],
[query[2], pre[2], id[13]],
[query[1], pre[1], id[13]],
["a"]]);
assertEqual(res.statusCode,412);
assertEqual(res.bodyParsed.length, 4);
assertEqual(res.bodyParsed[0] > 0, true);
assertEqual(res.bodyParsed[1] > 0, true);
assertEqual(res.bodyParsed[2], 0);
assertEqual(res.bodyParsed[3], query[1]);
res = accessAgency("inquire",[id[13]]).bodyParsed;
assertEqual(res.length, 1);
assertEqual(res[0].length, 2);
assertEqual(res[0][0].query, query[0]);
assertEqual(res[0][1].query, query[2]);
},