mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/arangodb/arangodb into devel
# Conflicts: # arangod/Replication/InitialSyncer.cpp
This commit is contained in:
commit
d228a94462
|
@ -182,9 +182,12 @@ class ObjectIterator {
|
|||
|
||||
ObjectIterator() = delete;
|
||||
|
||||
explicit ObjectIterator(Slice const& slice, bool allowRandomIteration = false)
|
||||
// The useSequentialIteration flag indicates whether or not the iteration
|
||||
// simply jumps from key/value pair to key/value pair without using the
|
||||
// index. The default `false` is to use the index if it is there.
|
||||
explicit ObjectIterator(Slice const& slice, bool useSequentialIteration = false)
|
||||
: _slice(slice), _size(_slice.length()), _position(0), _current(nullptr),
|
||||
_allowRandomIteration(allowRandomIteration) {
|
||||
_useSequentialIteration(useSequentialIteration) {
|
||||
if (!slice.isObject()) {
|
||||
throw Exception(Exception::InvalidValueType, "Expecting Object slice");
|
||||
}
|
||||
|
@ -193,7 +196,7 @@ class ObjectIterator {
|
|||
auto h = slice.head();
|
||||
if (h == 0x14) {
|
||||
_current = slice.keyAt(0, false).start();
|
||||
} else if (allowRandomIteration) {
|
||||
} else if (useSequentialIteration) {
|
||||
_current = slice.begin() + slice.findDataOffset(h);
|
||||
}
|
||||
}
|
||||
|
@ -204,7 +207,7 @@ class ObjectIterator {
|
|||
_size(other._size),
|
||||
_position(other._position),
|
||||
_current(other._current),
|
||||
_allowRandomIteration(other._allowRandomIteration) {}
|
||||
_useSequentialIteration(other._useSequentialIteration) {}
|
||||
|
||||
ObjectIterator& operator=(ObjectIterator const& other) = delete;
|
||||
|
||||
|
@ -306,7 +309,7 @@ class ObjectIterator {
|
|||
ValueLength const _size;
|
||||
ValueLength _position;
|
||||
uint8_t const* _current;
|
||||
bool const _allowRandomIteration;
|
||||
bool const _useSequentialIteration;
|
||||
};
|
||||
|
||||
} // namespace arangodb::velocypack
|
||||
|
|
|
@ -113,7 +113,7 @@ devel
|
|||
when unused.
|
||||
|
||||
Waiting for an unused V8 context will now also abort if no V8 context can be
|
||||
acquired/created after 120 seconds.
|
||||
acquired/created after 60 seconds.
|
||||
|
||||
* improved diagnostic messages written to logfiles by supervisor process
|
||||
|
||||
|
|
|
@ -254,6 +254,7 @@ while [ $# -gt 0 ]; do
|
|||
MAKE="cmake --build . --config ${BUILD_CONFIG}"
|
||||
PACKAGE_MAKE="cmake --build . --config ${BUILD_CONFIG} --target"
|
||||
CONFIGURE_OPTIONS="${CONFIGURE_OPTIONS} -DV8_TARGET_ARCHS=Release"
|
||||
export _IsNativeEnvironment=true
|
||||
;;
|
||||
|
||||
--symsrv)
|
||||
|
|
|
@ -1223,7 +1223,7 @@ bool AgencyComm::lock(std::string const& key, double ttl, double timeout,
|
|||
return true;
|
||||
}
|
||||
|
||||
usleep(sleepTime);
|
||||
usleep((TRI_usleep_t) sleepTime);
|
||||
|
||||
if (sleepTime < MAX_SLEEP_TIME) {
|
||||
sleepTime += INITIAL_SLEEP_TIME;
|
||||
|
@ -1264,7 +1264,7 @@ bool AgencyComm::unlock(std::string const& key, VPackSlice const& slice,
|
|||
return true;
|
||||
}
|
||||
|
||||
usleep(sleepTime);
|
||||
usleep((TRI_usleep_t)sleepTime);
|
||||
|
||||
if (sleepTime < MAX_SLEEP_TIME) {
|
||||
sleepTime += INITIAL_SLEEP_TIME;
|
||||
|
|
|
@ -208,6 +208,13 @@ void AgencyFeature::start() {
|
|||
return;
|
||||
}
|
||||
|
||||
// Find the agency prefix:
|
||||
auto feature = ApplicationServer::getFeature<ClusterFeature>("Cluster");
|
||||
arangodb::consensus::Supervision::setAgencyPrefix(
|
||||
std::string("/") + feature->agencyPrefix());
|
||||
arangodb::consensus::Job::agencyPrefix
|
||||
= std::string("/") + feature->agencyPrefix();
|
||||
|
||||
// TODO: Port this to new options handling
|
||||
std::string endpoint;
|
||||
|
||||
|
|
|
@ -27,10 +27,14 @@
|
|||
#include "Aql/ExecutionPlan.h"
|
||||
#include "Aql/Query.h"
|
||||
#include "Cluster/ClusterComm.h"
|
||||
#include "Graph/AttributeWeightShortestPathFinder.h"
|
||||
#include "Graph/ConstantWeightShortestPathFinder.h"
|
||||
#include "Graph/ShortestPathFinder.h"
|
||||
#include "Graph/ShortestPathResult.h"
|
||||
#include "Graph/AttributeWeightShortestPathFinder.h"
|
||||
#include "Graph/ConstantWeightShortestPathFinder.h"
|
||||
#include "Transaction/Methods.h"
|
||||
#include "Utils/OperationCursor.h"
|
||||
#include "VocBase/EdgeCollectionInfo.h"
|
||||
#include "VocBase/LogicalCollection.h"
|
||||
#include "VocBase/ManagedDocumentResult.h"
|
||||
#include "VocBase/ticks.h"
|
||||
|
@ -48,7 +52,7 @@ ShortestPathBlock::ShortestPathBlock(ExecutionEngine* engine,
|
|||
_vertexReg(ExecutionNode::MaxRegisterId),
|
||||
_edgeVar(nullptr),
|
||||
_edgeReg(ExecutionNode::MaxRegisterId),
|
||||
_opts(nullptr),
|
||||
_opts(static_cast<ShortestPathOptions*>(ep->options())),
|
||||
_posInPath(0),
|
||||
_pathLength(0),
|
||||
_path(nullptr),
|
||||
|
@ -58,8 +62,7 @@ ShortestPathBlock::ShortestPathBlock(ExecutionEngine* engine,
|
|||
_useTargetRegister(false),
|
||||
_usedConstant(false),
|
||||
_engines(nullptr) {
|
||||
_opts = static_cast<ShortestPathOptions*>(ep->options());
|
||||
_mmdr.reset(new ManagedDocumentResult);
|
||||
TRI_ASSERT(_opts != nullptr);
|
||||
|
||||
if (!ep->usesStartInVariable()) {
|
||||
_startVertexId = ep->getStartVertex();
|
||||
|
@ -257,9 +260,7 @@ bool ShortestPathBlock::nextPath(AqlItemBlock const* items) {
|
|||
VPackSlice start = _opts->getStart();
|
||||
VPackSlice end = _opts->getEnd();
|
||||
TRI_ASSERT(_finder != nullptr);
|
||||
// We do not need this data anymore. Result has been processed.
|
||||
// Save some memory.
|
||||
_coordinatorCache.clear();
|
||||
|
||||
bool hasPath =
|
||||
_finder->shortestPath(start, end, *_path, [this]() { throwIfKilled(); });
|
||||
|
||||
|
|
|
@ -32,25 +32,15 @@ namespace arangodb {
|
|||
class ManagedDocumentResult;
|
||||
|
||||
namespace graph {
|
||||
class ConstantWeightShortestPathFinder;
|
||||
class ShortestPathFinder;
|
||||
class ShortestPathResult;
|
||||
}
|
||||
|
||||
namespace traverser {
|
||||
class EdgeCollectionInfo;
|
||||
}
|
||||
|
||||
namespace aql {
|
||||
|
||||
class ShortestPathNode;
|
||||
|
||||
class ShortestPathBlock : public ExecutionBlock {
|
||||
friend struct EdgeWeightExpanderLocal;
|
||||
friend struct EdgeWeightExpanderCluster;
|
||||
|
||||
// TODO ONLY TEMPORARY
|
||||
friend class graph::ConstantWeightShortestPathFinder;
|
||||
|
||||
public:
|
||||
ShortestPathBlock(ExecutionEngine* engine, ShortestPathNode const* ep);
|
||||
|
@ -100,8 +90,6 @@ class ShortestPathBlock : public ExecutionBlock {
|
|||
/// @brief Register for the edge output
|
||||
RegisterId _edgeReg;
|
||||
|
||||
std::unique_ptr<ManagedDocumentResult> _mmdr;
|
||||
|
||||
/// @brief options to compute the shortest path
|
||||
graph::ShortestPathOptions* _opts;
|
||||
|
||||
|
@ -146,9 +134,6 @@ class ShortestPathBlock : public ExecutionBlock {
|
|||
/// We use it to check if we are done with enumerating.
|
||||
bool _usedConstant;
|
||||
|
||||
/// @brief Cache for edges send over the network
|
||||
std::vector<std::shared_ptr<VPackBuffer<uint8_t>>> _coordinatorCache;
|
||||
|
||||
/// @brief Traverser Engines
|
||||
std::unordered_map<ServerID, traverser::TraverserEngineID> const* _engines;
|
||||
|
||||
|
|
|
@ -577,7 +577,7 @@ bool ClusterComm::match(ClientTransactionID const& clientTransactionID,
|
|||
/// from deleting `result` and `answer`.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ClusterCommResult const ClusterComm::enquire(Ticket const ticketId) {
|
||||
ClusterCommResult const ClusterComm::enquire(communicator::Ticket const ticketId) {
|
||||
ResponseIterator i;
|
||||
AsyncResponse response;
|
||||
|
||||
|
@ -614,7 +614,7 @@ ClusterCommResult const ClusterComm::enquire(Ticket const ticketId) {
|
|||
|
||||
ClusterCommResult const ClusterComm::wait(
|
||||
ClientTransactionID const& clientTransactionID,
|
||||
CoordTransactionID const coordTransactionID, Ticket const ticketId,
|
||||
CoordTransactionID const coordTransactionID, communicator::Ticket const ticketId,
|
||||
ShardID const& shardID, ClusterCommTimeout timeout) {
|
||||
|
||||
ResponseIterator i;
|
||||
|
@ -1123,6 +1123,19 @@ void ClusterComm::addAuthorization(std::unordered_map<std::string, std::string>*
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<communicator::Ticket> ClusterComm::activeServerTickets(std::vector<std::string> const& servers) {
|
||||
std::vector<communicator::Ticket> tickets;
|
||||
CONDITION_LOCKER(locker, somethingReceived);
|
||||
for (auto const& it: responses) {
|
||||
for (auto const& server: servers) {
|
||||
if (it.second.result && it.second.result->serverID == server) {
|
||||
tickets.push_back(it.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tickets;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ClusterComm main loop
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1130,18 +1143,10 @@ void ClusterComm::addAuthorization(std::unordered_map<std::string, std::string>*
|
|||
void ClusterCommThread::abortRequestsToFailedServers() {
|
||||
ClusterInfo* ci = ClusterInfo::instance();
|
||||
auto failedServers = ci->getFailedServers();
|
||||
std::vector<std::string> failedServerEndpoints;
|
||||
failedServerEndpoints.reserve(failedServers.size());
|
||||
|
||||
for (auto const& failedServer: failedServers) {
|
||||
failedServerEndpoints.push_back(_cc->createCommunicatorDestination(ci->getServerEndpoint(failedServer), "/").url());
|
||||
}
|
||||
|
||||
for (auto const& request: _cc->communicator()->requestsInProgress()) {
|
||||
for (auto const& failedServerEndpoint: failedServerEndpoints) {
|
||||
if (request->_destination.url().substr(0, failedServerEndpoint.length()) == failedServerEndpoint) {
|
||||
_cc->communicator()->abortRequest(request->_ticketId);
|
||||
}
|
||||
if (failedServers.size() > 0) {
|
||||
auto ticketIds = _cc->activeServerTickets(failedServers);
|
||||
for (auto const& ticketId: ticketIds) {
|
||||
_cc->communicator()->abortRequest(ticketId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -616,6 +616,12 @@ class ClusterComm {
|
|||
|
||||
void cleanupAllQueues();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief activeServerTickets for a list of servers
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<communicator::Ticket> activeServerTickets(std::vector<std::string> const& servers);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief our background communications thread
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -133,6 +133,10 @@ void ClusterFeature::collectOptions(std::shared_ptr<ProgramOptions> options) {
|
|||
options->addOption("--cluster.system-replication-factor",
|
||||
"replication factor for system collections",
|
||||
new UInt32Parameter(&_systemReplicationFactor));
|
||||
|
||||
options->addOption("--cluster.create-waits-for-sync-replication",
|
||||
"active coordinator will wait for all replicas to create collection",
|
||||
new BooleanParameter(&_createWaitsForSyncReplication));
|
||||
}
|
||||
|
||||
void ClusterFeature::validateOptions(std::shared_ptr<ProgramOptions> options) {
|
||||
|
|
|
@ -45,6 +45,10 @@ class ClusterFeature : public application_features::ApplicationFeature {
|
|||
void start() override final;
|
||||
void unprepare() override final;
|
||||
|
||||
std::string agencyPrefix() {
|
||||
return _agencyPrefix;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> _agencyEndpoints;
|
||||
std::string _agencyPrefix;
|
||||
|
@ -58,6 +62,7 @@ class ClusterFeature : public application_features::ApplicationFeature {
|
|||
std::string _dbserverConfig;
|
||||
std::string _coordinatorConfig;
|
||||
uint32_t _systemReplicationFactor = 2;
|
||||
bool _createWaitsForSyncReplication = false;
|
||||
|
||||
private:
|
||||
void reportRole(ServerState::RoleEnum);
|
||||
|
@ -72,6 +77,7 @@ class ClusterFeature : public application_features::ApplicationFeature {
|
|||
};
|
||||
|
||||
void setUnregisterOnShutdown(bool);
|
||||
bool createWaitsForSyncReplication() { return _createWaitsForSyncReplication; };
|
||||
|
||||
void stop() override final;
|
||||
|
||||
|
|
|
@ -1042,6 +1042,7 @@ int ClusterInfo::createCollectionCoordinator(std::string const& databaseName,
|
|||
std::string const& collectionID,
|
||||
uint64_t numberOfShards,
|
||||
uint64_t replicationFactor,
|
||||
bool waitForReplication,
|
||||
VPackSlice const& json,
|
||||
std::string& errorMsg,
|
||||
double timeout) {
|
||||
|
@ -1100,19 +1101,10 @@ int ClusterInfo::createCollectionCoordinator(std::string const& databaseName,
|
|||
[=](VPackSlice const& result) {
|
||||
if (result.isObject() && result.length() == (size_t)numberOfShards) {
|
||||
std::string tmpMsg = "";
|
||||
bool tmpHaveError = false;
|
||||
|
||||
for (auto const& p : VPackObjectIterator(result)) {
|
||||
if (replicationFactor == 0) {
|
||||
VPackSlice servers = p.value.get("servers");
|
||||
if (!servers.isArray() || servers.length() < dbServers.size()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (arangodb::basics::VelocyPackHelper::getBooleanValue(
|
||||
p.value, "error", false)) {
|
||||
tmpHaveError = true;
|
||||
tmpMsg += " shardID:" + p.key.copyString() + ":";
|
||||
tmpMsg += arangodb::basics::VelocyPackHelper::getStringValue(
|
||||
p.value, "errorMessage", "");
|
||||
|
@ -1125,13 +1117,24 @@ int ClusterInfo::createCollectionCoordinator(std::string const& databaseName,
|
|||
tmpMsg += ")";
|
||||
}
|
||||
}
|
||||
*errMsg = "Error in creation of collection:" + tmpMsg + " "
|
||||
+ __FILE__ + std::to_string(__LINE__);
|
||||
*dbServerResult = TRI_ERROR_CLUSTER_COULD_NOT_CREATE_COLLECTION;
|
||||
return true;
|
||||
}
|
||||
|
||||
// wait that all followers have created our new collection
|
||||
if (waitForReplication) {
|
||||
uint64_t mutableReplicationFactor = replicationFactor;
|
||||
if (mutableReplicationFactor == 0) {
|
||||
mutableReplicationFactor = dbServers.size();
|
||||
}
|
||||
|
||||
VPackSlice servers = p.value.get("servers");
|
||||
if (!servers.isArray() || servers.length() < mutableReplicationFactor) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tmpHaveError) {
|
||||
*errMsg = "Error in creation of collection:" + tmpMsg + " "
|
||||
+ __FILE__ + std::to_string(__LINE__);
|
||||
*dbServerResult = TRI_ERROR_CLUSTER_COULD_NOT_CREATE_COLLECTION;
|
||||
return true;
|
||||
}
|
||||
*dbServerResult = setErrormsg(TRI_ERROR_NO_ERROR, *errMsg);
|
||||
}
|
||||
|
|
|
@ -349,6 +349,7 @@ class ClusterInfo {
|
|||
std::string const& collectionID,
|
||||
uint64_t numberOfShards,
|
||||
uint64_t replicationFactor,
|
||||
bool waitForReplication,
|
||||
arangodb::velocypack::Slice const& json,
|
||||
std::string& errorMsg, double timeout);
|
||||
|
||||
|
|
|
@ -2264,12 +2264,13 @@ std::unique_ptr<LogicalCollection>
|
|||
ClusterMethods::createCollectionOnCoordinator(TRI_col_type_e collectionType,
|
||||
TRI_vocbase_t* vocbase,
|
||||
VPackSlice parameters,
|
||||
bool ignoreDistributeShardsLikeErrors) {
|
||||
bool ignoreDistributeShardsLikeErrors,
|
||||
bool waitForSyncReplication) {
|
||||
auto col = std::make_unique<LogicalCollection>(vocbase, parameters);
|
||||
// Collection is a temporary collection object that undergoes sanity checks etc.
|
||||
// It is not used anywhere and will be cleaned up after this call.
|
||||
// Persist collection will return the real object.
|
||||
return persistCollectionInAgency(col.get(), ignoreDistributeShardsLikeErrors);
|
||||
return persistCollectionInAgency(col.get(), ignoreDistributeShardsLikeErrors, waitForSyncReplication);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2279,7 +2280,7 @@ ClusterMethods::createCollectionOnCoordinator(TRI_col_type_e collectionType,
|
|||
|
||||
std::unique_ptr<LogicalCollection>
|
||||
ClusterMethods::persistCollectionInAgency(
|
||||
LogicalCollection* col, bool ignoreDistributeShardsLikeErrors) {
|
||||
LogicalCollection* col, bool ignoreDistributeShardsLikeErrors, bool waitForSyncReplication) {
|
||||
std::string distributeShardsLike = col->distributeShardsLike();
|
||||
std::vector<std::string> dbServers;
|
||||
std::vector<std::string> avoid = col->avoidServers();
|
||||
|
@ -2364,7 +2365,7 @@ ClusterMethods::persistCollectionInAgency(
|
|||
std::string errorMsg;
|
||||
int myerrno = ci->createCollectionCoordinator(
|
||||
col->dbName(), col->cid_as_string(),
|
||||
col->numberOfShards(), col->replicationFactor(), velocy.slice(), errorMsg, 240.0);
|
||||
col->numberOfShards(), col->replicationFactor(), waitForSyncReplication, velocy.slice(), errorMsg, 240.0);
|
||||
|
||||
if (myerrno != TRI_ERROR_NO_ERROR) {
|
||||
if (errorMsg.empty()) {
|
||||
|
|
|
@ -258,7 +258,8 @@ class ClusterMethods {
|
|||
static std::unique_ptr<LogicalCollection> createCollectionOnCoordinator(
|
||||
TRI_col_type_e collectionType, TRI_vocbase_t* vocbase,
|
||||
arangodb::velocypack::Slice parameters,
|
||||
bool ignoreDistributeShardsLikeErrors = false);
|
||||
bool ignoreDistributeShardsLikeErrors,
|
||||
bool waitForSyncReplication);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -267,7 +268,7 @@ class ClusterMethods {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::unique_ptr<LogicalCollection> persistCollectionInAgency(
|
||||
LogicalCollection* col, bool ignoreDistributeShardsLikeErrors = false);
|
||||
LogicalCollection* col, bool ignoreDistributeShardsLikeErrors, bool waitForSyncReplication);
|
||||
};
|
||||
|
||||
} // namespace arangodb
|
||||
|
|
|
@ -1134,7 +1134,7 @@ int MMFilesDatafile::truncateAndSeal(TRI_voc_size_t position) {
|
|||
}
|
||||
|
||||
char zero = 0;
|
||||
int res = TRI_WRITE(fd, &zero, 1);
|
||||
long res = TRI_WRITE(fd, &zero, 1);
|
||||
|
||||
if (res < 0) {
|
||||
TRI_SYSTEM_ERROR();
|
||||
|
@ -1155,7 +1155,7 @@ int MMFilesDatafile::truncateAndSeal(TRI_voc_size_t position) {
|
|||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_SYSTEM_ERROR();
|
||||
TRI_set_errno(res);
|
||||
TRI_set_errno((int)res);
|
||||
TRI_TRACKED_CLOSE_FILE(fd);
|
||||
|
||||
// remove empty file
|
||||
|
|
|
@ -152,7 +152,7 @@ MMFilesEngine::MMFilesEngine(application_features::ApplicationServer* server)
|
|||
MMFilesEngine::~MMFilesEngine() {}
|
||||
|
||||
// perform a physical deletion of the database
|
||||
Result MMFilesEngine::dropDatabase(Database* database) {
|
||||
Result MMFilesEngine::dropDatabase(TRI_vocbase_t* database) {
|
||||
// delete persistent indexes for this database
|
||||
MMFilesPersistentIndexFeature::dropDatabase(database->id());
|
||||
|
||||
|
|
|
@ -138,14 +138,14 @@ class MMFilesEngine final : public StorageEngine {
|
|||
void waitForSync(TRI_voc_tick_t tick) override;
|
||||
|
||||
virtual TRI_vocbase_t* openDatabase(arangodb::velocypack::Slice const& parameters, bool isUpgrade, int&) override;
|
||||
Database* createDatabase(TRI_voc_tick_t id, arangodb::velocypack::Slice const& args, int& status) override {
|
||||
TRI_vocbase_t* createDatabase(TRI_voc_tick_t id, arangodb::velocypack::Slice const& args, int& status) override {
|
||||
status = TRI_ERROR_NO_ERROR;
|
||||
return createDatabaseMMFiles(id, args);
|
||||
}
|
||||
int writeCreateDatabaseMarker(TRI_voc_tick_t id, VPackSlice const& slice) override;
|
||||
|
||||
void prepareDropDatabase(TRI_vocbase_t* vocbase, bool useWriteMarker, int& status) override;
|
||||
Result dropDatabase(Database* database) override;
|
||||
Result dropDatabase(TRI_vocbase_t* database) override;
|
||||
void waitUntilDeletion(TRI_voc_tick_t id, bool force, int& status) override;
|
||||
|
||||
// wal in recovery
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "Basics/conversions.h"
|
||||
#include "Basics/files.h"
|
||||
#include "Cluster/ClusterComm.h"
|
||||
#include "Cluster/ClusterFeature.h"
|
||||
#include "Cluster/ClusterMethods.h"
|
||||
#include "Cluster/FollowerInfo.h"
|
||||
#include "GeneralServer/GeneralServer.h"
|
||||
|
@ -1592,14 +1593,15 @@ int MMFilesRestReplicationHandler::processRestoreCollectionCoordinator(
|
|||
if (dropExisting) {
|
||||
int res = ci->dropCollectionCoordinator(dbName, col->cid_as_string(),
|
||||
errorMsg, 0.0);
|
||||
if (res == TRI_ERROR_FORBIDDEN) {
|
||||
if (res == TRI_ERROR_FORBIDDEN ||
|
||||
res == TRI_ERROR_CLUSTER_MUST_NOT_DROP_COLL_OTHER_DISTRIBUTESHARDSLIKE) {
|
||||
// some collections must not be dropped
|
||||
res = truncateCollectionOnCoordinator(dbName, name);
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
errorMsg =
|
||||
"unable to truncate collection (dropping is forbidden): " + name;
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -1679,8 +1681,9 @@ int MMFilesRestReplicationHandler::processRestoreCollectionCoordinator(
|
|||
VPackSlice const merged = mergedBuilder.slice();
|
||||
|
||||
try {
|
||||
bool createWaitsForSyncReplication = application_features::ApplicationServer::getFeature<ClusterFeature>("Cluster")->createWaitsForSyncReplication();
|
||||
auto col = ClusterMethods::createCollectionOnCoordinator(
|
||||
collectionType, _vocbase, merged, ignoreDistributeShardsLikeErrors);
|
||||
collectionType, _vocbase, merged, ignoreDistributeShardsLikeErrors, createWaitsForSyncReplication);
|
||||
TRI_ASSERT(col != nullptr);
|
||||
} catch (basics::Exception const& e) {
|
||||
// Error, report it.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,6 +23,7 @@
|
|||
/// @author Jan Christoph Uhde
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Basics/StringRef.h"
|
||||
#include "RocksDBEngine/RocksDBCommon.h"
|
||||
#include "RocksDBEngine/RocksDBComparator.h"
|
||||
#include "RocksDBEngine/RocksDBEngine.h"
|
||||
|
@ -128,28 +129,66 @@ void uint64ToPersistent(std::string& p, uint64_t value) {
|
|||
} while (++len < sizeof(uint64_t));
|
||||
}
|
||||
|
||||
void stripObjectIds(VPackBuilder& builder, VPackSlice const& slice) {
|
||||
if (slice.isObject()) {
|
||||
bool hasObjectIds(VPackSlice const& inputSlice) {
|
||||
bool rv = false;
|
||||
if (inputSlice.isObject()) {
|
||||
for (auto const& objectPair :
|
||||
arangodb::velocypack::ObjectIterator(inputSlice)) {
|
||||
if (arangodb::StringRef(objectPair.key) == "objectId") {
|
||||
return true;
|
||||
}
|
||||
rv = hasObjectIds(objectPair.value);
|
||||
if (rv) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
} else if (inputSlice.isArray()) {
|
||||
for (auto const& slice : arangodb::velocypack::ArrayIterator(inputSlice)) {
|
||||
if (rv) {
|
||||
return rv;
|
||||
}
|
||||
rv = hasObjectIds(slice);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
VPackBuilder& stripObjectIdsImpl(VPackBuilder& builder, VPackSlice const& inputSlice) {
|
||||
if (inputSlice.isObject()) {
|
||||
builder.openObject();
|
||||
for (auto it = arangodb::velocypack::ObjectIterator(slice); it.valid();
|
||||
it++) {
|
||||
if (it.key().copyString() == "objectId") {
|
||||
for (auto const& objectPair :
|
||||
arangodb::velocypack::ObjectIterator(inputSlice)) {
|
||||
if (arangodb::StringRef(objectPair.key) == "objectId") {
|
||||
continue;
|
||||
}
|
||||
builder.add(it.key());
|
||||
stripObjectIds(builder, it.value());
|
||||
builder.add(objectPair.key);
|
||||
stripObjectIdsImpl(builder, objectPair.value);
|
||||
}
|
||||
builder.close();
|
||||
} else if (slice.isArray()) {
|
||||
} else if (inputSlice.isArray()) {
|
||||
builder.openArray();
|
||||
for (auto it = arangodb::velocypack::ArrayIterator(slice); it.valid();
|
||||
it++) {
|
||||
stripObjectIds(builder, it.value());
|
||||
for (auto const& slice : arangodb::velocypack::ArrayIterator(inputSlice)) {
|
||||
stripObjectIdsImpl(builder, slice);
|
||||
}
|
||||
builder.close();
|
||||
} else {
|
||||
builder.add(slice);
|
||||
builder.add(inputSlice);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
std::pair<VPackSlice, std::unique_ptr<VPackBuffer<uint8_t>>> stripObjectIds(
|
||||
VPackSlice const& inputSlice, bool checkBeforeCopy) {
|
||||
std::unique_ptr<VPackBuffer<uint8_t>> buffer = nullptr;
|
||||
if (checkBeforeCopy) {
|
||||
if (!hasObjectIds(inputSlice)) {
|
||||
return {inputSlice, std::move(buffer)};
|
||||
}
|
||||
}
|
||||
buffer.reset(new VPackBuffer<uint8_t>);
|
||||
VPackBuilder builder(*buffer);
|
||||
stripObjectIdsImpl(builder, inputSlice);
|
||||
return {VPackSlice(buffer->data()), std::move(buffer)};
|
||||
}
|
||||
|
||||
RocksDBTransactionState* toRocksTransactionState(transaction::Methods* trx) {
|
||||
|
|
|
@ -89,7 +89,8 @@ uint64_t uint64FromPersistent(char const* p);
|
|||
void uint64ToPersistent(char* p, uint64_t value);
|
||||
void uint64ToPersistent(std::string& out, uint64_t value);
|
||||
|
||||
void stripObjectIds(VPackBuilder&, VPackSlice const&);
|
||||
std::pair<VPackSlice, std::unique_ptr<VPackBuffer<uint8_t>>> stripObjectIds(
|
||||
VPackSlice const& inputSlice, bool checkBeforeCopy = true);
|
||||
|
||||
RocksDBTransactionState* toRocksTransactionState(transaction::Methods* trx);
|
||||
rocksdb::TransactionDB* globalRocksDB();
|
||||
|
|
|
@ -230,7 +230,12 @@ void RocksDBEngine::start() {
|
|||
}
|
||||
}
|
||||
|
||||
void RocksDBEngine::stop() {}
|
||||
void RocksDBEngine::stop() {
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
}
|
||||
replicationManager()->dropAll();
|
||||
}
|
||||
|
||||
void RocksDBEngine::unprepare() {
|
||||
if (!isEnabled()) {
|
||||
|
@ -486,7 +491,7 @@ TRI_vocbase_t* RocksDBEngine::openDatabase(
|
|||
return openExistingDatabase(id, name, true, isUpgrade);
|
||||
}
|
||||
|
||||
RocksDBEngine::Database* RocksDBEngine::createDatabase(
|
||||
TRI_vocbase_t* RocksDBEngine::createDatabase(
|
||||
TRI_voc_tick_t id, arangodb::velocypack::Slice const& args, int& status) {
|
||||
status = TRI_ERROR_NO_ERROR;
|
||||
auto vocbase = std::make_unique<TRI_vocbase_t>(TRI_VOCBASE_TYPE_NORMAL, id,
|
||||
|
@ -519,10 +524,6 @@ int RocksDBEngine::writeCreateCollectionMarker(TRI_voc_tick_t databaseId,
|
|||
|
||||
void RocksDBEngine::prepareDropDatabase(TRI_vocbase_t* vocbase,
|
||||
bool useWriteMarker, int& status) {
|
||||
// probably not required
|
||||
// THROW_ARANGO_NOT_YET_IMPLEMENTED();
|
||||
|
||||
// status = saveDatabaseParameters(vocbase->id(), vocbase->name(), true);
|
||||
VPackBuilder builder;
|
||||
builder.openObject();
|
||||
builder.add("id", VPackValue(std::to_string(vocbase->id())));
|
||||
|
@ -533,7 +534,8 @@ void RocksDBEngine::prepareDropDatabase(TRI_vocbase_t* vocbase,
|
|||
status = writeCreateDatabaseMarker(vocbase->id(), builder.slice());
|
||||
}
|
||||
|
||||
Result RocksDBEngine::dropDatabase(Database* database) {
|
||||
Result RocksDBEngine::dropDatabase(TRI_vocbase_t* database) {
|
||||
replicationManager()->drop(database);
|
||||
return dropDatabase(database->id());
|
||||
}
|
||||
|
||||
|
|
|
@ -123,14 +123,14 @@ class RocksDBEngine final : public StorageEngine {
|
|||
virtual TRI_vocbase_t* openDatabase(
|
||||
arangodb::velocypack::Slice const& parameters, bool isUpgrade,
|
||||
int&) override;
|
||||
Database* createDatabase(TRI_voc_tick_t id,
|
||||
TRI_vocbase_t* createDatabase(TRI_voc_tick_t id,
|
||||
arangodb::velocypack::Slice const& args,
|
||||
int& status) override;
|
||||
int writeCreateDatabaseMarker(TRI_voc_tick_t id,
|
||||
VPackSlice const& slice) override;
|
||||
void prepareDropDatabase(TRI_vocbase_t* vocbase, bool useWriteMarker,
|
||||
int& status) override;
|
||||
Result dropDatabase(Database* database) override;
|
||||
Result dropDatabase(TRI_vocbase_t* database) override;
|
||||
void waitUntilDeletion(TRI_voc_tick_t id, bool force, int& status) override;
|
||||
|
||||
// wal in recovery
|
||||
|
|
|
@ -74,7 +74,7 @@ class RocksDBLogValue {
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Returns a reference to the underlying string buffer.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
std::string const& string() { return _buffer; } // to be used with put
|
||||
std::string const& string() const { return _buffer; } // to be used with put
|
||||
/*VPackSlice slice() const { return VPackSlice(
|
||||
reinterpret_cast<uint8_t const*>(_buffer.data())
|
||||
); }*/ // return a slice
|
||||
|
@ -82,6 +82,7 @@ class RocksDBLogValue {
|
|||
RocksDBLogType type() const {
|
||||
return static_cast<RocksDBLogType>(*(_buffer.data()));
|
||||
}
|
||||
rocksdb::Slice slice() const { return rocksdb::Slice(_buffer); }
|
||||
|
||||
private:
|
||||
RocksDBLogValue(RocksDBLogType type, uint64_t);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "Transaction/Helpers.h"
|
||||
#include "Transaction/StandaloneContext.h"
|
||||
#include "Transaction/UserTransaction.h"
|
||||
#include "Utils/DatabaseGuard.h"
|
||||
#include "VocBase/replication-common.h"
|
||||
#include "VocBase/ticks.h"
|
||||
|
||||
|
@ -55,6 +56,7 @@ RocksDBReplicationContext::RocksDBReplicationContext()
|
|||
_mdr(),
|
||||
_customTypeHandler(),
|
||||
_vpackOptions(Options::Defaults),
|
||||
_lastChunkOffset(0),
|
||||
_expires(TRI_microtime() + DefaultTTL),
|
||||
_isDeleted(false),
|
||||
_isUsed(true),
|
||||
|
@ -390,10 +392,13 @@ void RocksDBReplicationContext::releaseDumpingResources() {
|
|||
_iter.reset();
|
||||
}
|
||||
_collection = nullptr;
|
||||
_guard.reset();
|
||||
}
|
||||
|
||||
std::unique_ptr<transaction::Methods>
|
||||
RocksDBReplicationContext::createTransaction(TRI_vocbase_t* vocbase) {
|
||||
_guard.reset(new DatabaseGuard(vocbase));
|
||||
|
||||
double lockTimeout = transaction::Methods::DefaultLockTimeout;
|
||||
std::shared_ptr<transaction::StandaloneContext> ctx =
|
||||
transaction::StandaloneContext::Create(vocbase);
|
||||
|
@ -401,6 +406,7 @@ RocksDBReplicationContext::createTransaction(TRI_vocbase_t* vocbase) {
|
|||
ctx, {}, {}, {}, lockTimeout, false, true));
|
||||
Result res = trx->begin();
|
||||
if (!res.ok()) {
|
||||
_guard.reset();
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
_customTypeHandler = ctx->orderCustomTypeHandler();
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <velocypack/Slice.h>
|
||||
|
||||
namespace arangodb {
|
||||
class DatabaseGuard;
|
||||
|
||||
class RocksDBReplicationContext {
|
||||
public:
|
||||
|
@ -53,6 +54,13 @@ class RocksDBReplicationContext {
|
|||
TRI_voc_tick_t id() const;
|
||||
uint64_t lastTick() const;
|
||||
uint64_t count() const;
|
||||
|
||||
TRI_vocbase_t* vocbase() const {
|
||||
if (_trx == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return _trx->vocbase();
|
||||
}
|
||||
|
||||
// creates new transaction/snapshot
|
||||
void bind(TRI_vocbase_t*);
|
||||
|
@ -113,7 +121,8 @@ class RocksDBReplicationContext {
|
|||
ManagedDocumentResult _mdr;
|
||||
std::shared_ptr<arangodb::velocypack::CustomTypeHandler> _customTypeHandler;
|
||||
arangodb::velocypack::Options _vpackOptions;
|
||||
uint64_t _lastChunkOffset = 0;
|
||||
uint64_t _lastChunkOffset;
|
||||
std::unique_ptr<DatabaseGuard> _guard;
|
||||
|
||||
double _expires;
|
||||
bool _isDeleted;
|
||||
|
|
|
@ -238,6 +238,40 @@ bool RocksDBReplicationManager::containsUsedContext() {
|
|||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief drop contexts by database (at least mark them as deleted)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RocksDBReplicationManager::drop(TRI_vocbase_t* vocbase) {
|
||||
{
|
||||
MUTEX_LOCKER(mutexLocker, _lock);
|
||||
|
||||
for (auto& context : _contexts) {
|
||||
if (context.second->vocbase() == vocbase) {
|
||||
context.second->deleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
garbageCollect(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief drop all contexts (at least mark them as deleted)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RocksDBReplicationManager::dropAll() {
|
||||
{
|
||||
MUTEX_LOCKER(mutexLocker, _lock);
|
||||
|
||||
for (auto& context : _contexts) {
|
||||
context.second->deleted();
|
||||
}
|
||||
}
|
||||
|
||||
garbageCollect(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief run a garbage collection on the contexts
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -92,6 +92,18 @@ class RocksDBReplicationManager {
|
|||
|
||||
bool containsUsedContext();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief drop contexts by database (at least mark them as deleted)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void drop(TRI_vocbase_t*);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief drop all contexts (at least mark them as deleted)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dropAll();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief run a garbage collection on the contexts
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -43,7 +43,7 @@ class WBReader : public rocksdb::WriteBatch::Handler {
|
|||
explicit WBReader(TRI_vocbase_t* vocbase, uint64_t from, size_t& limit,
|
||||
bool includeSystem, VPackBuilder& builder)
|
||||
: _vocbase(vocbase),
|
||||
_from(from),
|
||||
/* _from(from), */
|
||||
_limit(limit),
|
||||
_includeSystem(includeSystem),
|
||||
_builder(builder) {}
|
||||
|
@ -170,7 +170,7 @@ class WBReader : public rocksdb::WriteBatch::Handler {
|
|||
|
||||
private:
|
||||
TRI_vocbase_t* _vocbase;
|
||||
uint64_t _from;
|
||||
/* uint64_t _from; */
|
||||
size_t& _limit;
|
||||
bool _includeSystem;
|
||||
VPackBuilder& _builder;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "Basics/conversions.h"
|
||||
#include "Basics/files.h"
|
||||
#include "Cluster/ClusterComm.h"
|
||||
#include "Cluster/ClusterFeature.h"
|
||||
#include "Cluster/ClusterMethods.h"
|
||||
#include "Cluster/FollowerInfo.h"
|
||||
#include "GeneralServer/GeneralServer.h"
|
||||
|
@ -826,9 +827,8 @@ void RocksDBRestReplicationHandler::handleCommandRestoreCollection() {
|
|||
"invalid JSON");
|
||||
return;
|
||||
}
|
||||
VPackBuilder builder;
|
||||
stripObjectIds(builder, parsedRequest->slice());
|
||||
VPackSlice const slice = builder.slice();
|
||||
auto pair = stripObjectIds(parsedRequest->slice());
|
||||
VPackSlice const slice = pair.first;
|
||||
|
||||
bool overwrite = false;
|
||||
|
||||
|
@ -1732,14 +1732,15 @@ int RocksDBRestReplicationHandler::processRestoreCollectionCoordinator(
|
|||
if (dropExisting) {
|
||||
int res = ci->dropCollectionCoordinator(dbName, col->cid_as_string(),
|
||||
errorMsg, 0.0);
|
||||
if (res == TRI_ERROR_FORBIDDEN) {
|
||||
if (res == TRI_ERROR_FORBIDDEN ||
|
||||
res == TRI_ERROR_CLUSTER_MUST_NOT_DROP_COLL_OTHER_DISTRIBUTESHARDSLIKE) {
|
||||
// some collections must not be dropped
|
||||
res = truncateCollectionOnCoordinator(dbName, name);
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
errorMsg =
|
||||
"unable to truncate collection (dropping is forbidden): " + name;
|
||||
return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -1819,8 +1820,9 @@ int RocksDBRestReplicationHandler::processRestoreCollectionCoordinator(
|
|||
VPackSlice const merged = mergedBuilder.slice();
|
||||
|
||||
try {
|
||||
bool createWaitsForSyncReplication = application_features::ApplicationServer::getFeature<ClusterFeature>("Cluster")->createWaitsForSyncReplication();
|
||||
auto col = ClusterMethods::createCollectionOnCoordinator(collectionType,
|
||||
_vocbase, merged);
|
||||
_vocbase, merged, true, createWaitsForSyncReplication);
|
||||
TRI_ASSERT(col != nullptr);
|
||||
} catch (basics::Exception const& e) {
|
||||
// Error, report it.
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "RocksDBEngine/RocksDBCommon.h"
|
||||
#include "RocksDBEngine/RocksDBCounterManager.h"
|
||||
#include "RocksDBEngine/RocksDBEngine.h"
|
||||
#include "RocksDBEngine/RocksDBLogValue.h"
|
||||
#include "RocksDBEngine/RocksDBTransactionCollection.h"
|
||||
#include "StorageEngine/EngineSelectorFeature.h"
|
||||
#include "StorageEngine/StorageEngine.h"
|
||||
|
@ -156,6 +157,11 @@ Result RocksDBTransactionState::beginTransaction(transaction::Hints hints) {
|
|||
_rocksWriteOptions, rocksdb::TransactionOptions()));
|
||||
_rocksTransaction->SetSnapshot();
|
||||
_rocksReadOptions.snapshot = _rocksTransaction->GetSnapshot();
|
||||
|
||||
RocksDBLogValue header = RocksDBLogValue::BeginTransaction(_vocbase->id(),
|
||||
_id);
|
||||
_rocksTransaction->PutLogData(header.slice());
|
||||
|
||||
} else {
|
||||
TRI_ASSERT(_status == transaction::Status::RUNNING);
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ class Socket {
|
|||
virtual void shutdownReceive() = 0;
|
||||
virtual void shutdownReceive(boost::system::error_code& ec) = 0;
|
||||
virtual void shutdownSend(boost::system::error_code& ec) = 0;
|
||||
virtual int available(boost::system::error_code& ec) = 0;
|
||||
virtual size_t available(boost::system::error_code& ec) = 0;
|
||||
virtual void asyncRead(boost::asio::mutable_buffers_1 const& buffer,
|
||||
AsyncHandler const& handler) = 0;
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ void SocketUnixDomain::shutdownReceive(boost::system::error_code& ec) {
|
|||
void SocketUnixDomain::shutdownSend(boost::system::error_code& ec) {
|
||||
_socket.shutdown(boost::asio::local::stream_protocol::socket::shutdown_send, ec);
|
||||
}
|
||||
int SocketUnixDomain::available(boost::system::error_code& ec) {
|
||||
size_t SocketUnixDomain::available(boost::system::error_code& ec) {
|
||||
return _socket.available(ec);
|
||||
}
|
||||
void SocketUnixDomain::asyncRead(boost::asio::mutable_buffers_1 const& buffer, AsyncHandler const& handler) {
|
||||
|
|
|
@ -65,8 +65,8 @@ class SocketUnixDomain final : public Socket {
|
|||
|
||||
void shutdownSend(boost::system::error_code& ec) override;
|
||||
|
||||
int available(boost::system::error_code& ec) override;
|
||||
|
||||
size_t available(boost::system::error_code& ec) override;
|
||||
|
||||
void asyncRead(boost::asio::mutable_buffers_1 const& buffer, AsyncHandler const& handler) override;
|
||||
|
||||
public:
|
||||
|
|
|
@ -65,7 +65,7 @@ class ConnectionStatistics {
|
|||
_error = false;
|
||||
}
|
||||
|
||||
static size_t const QUEUE_SIZE = 5000;
|
||||
static size_t const QUEUE_SIZE = 64 * 1024 - 2; // current (1.62) boost maximum
|
||||
|
||||
static Mutex _dataLock;
|
||||
|
||||
|
|
|
@ -152,7 +152,7 @@ class RequestStatistics {
|
|||
void trace_log();
|
||||
|
||||
private:
|
||||
static size_t const QUEUE_SIZE = 1000;
|
||||
static size_t const QUEUE_SIZE = 64 * 1024 - 2; // current (1.62) boost maximum
|
||||
|
||||
static arangodb::Mutex _dataLock;
|
||||
|
||||
|
|
|
@ -146,7 +146,6 @@ class StorageEngine : public application_features::ApplicationFeature {
|
|||
|
||||
// TODO add pre / post conditions for functions
|
||||
|
||||
using Database = TRI_vocbase_t;
|
||||
using CollectionView = LogicalCollection;
|
||||
|
||||
virtual void waitForSync(TRI_voc_tick_t tick) = 0;
|
||||
|
@ -154,10 +153,10 @@ class StorageEngine : public application_features::ApplicationFeature {
|
|||
//// operations on databasea
|
||||
|
||||
/// @brief opens a database
|
||||
virtual Database* openDatabase(arangodb::velocypack::Slice const& args, bool isUpgrade, int& status) = 0;
|
||||
Database* openDatabase(arangodb::velocypack::Slice const& args, bool isUpgrade){
|
||||
virtual TRI_vocbase_t* openDatabase(arangodb::velocypack::Slice const& args, bool isUpgrade, int& status) = 0;
|
||||
TRI_vocbase_t* openDatabase(arangodb::velocypack::Slice const& args, bool isUpgrade){
|
||||
int status;
|
||||
Database* rv = openDatabase(args, isUpgrade, status);
|
||||
TRI_vocbase_t* rv = openDatabase(args, isUpgrade, status);
|
||||
TRI_ASSERT(status == TRI_ERROR_NO_ERROR);
|
||||
TRI_ASSERT(rv != nullptr);
|
||||
return rv;
|
||||
|
@ -172,16 +171,16 @@ class StorageEngine : public application_features::ApplicationFeature {
|
|||
// the WAL entry for the database creation will be written *after* the call
|
||||
// to "createDatabase" returns
|
||||
// no way to acquire id within this function?!
|
||||
virtual Database* createDatabase(TRI_voc_tick_t id, arangodb::velocypack::Slice const& args, int& status) = 0;
|
||||
Database* createDatabase(TRI_voc_tick_t id, arangodb::velocypack::Slice const& args ){
|
||||
virtual TRI_vocbase_t* createDatabase(TRI_voc_tick_t id, arangodb::velocypack::Slice const& args, int& status) = 0;
|
||||
TRI_vocbase_t* createDatabase(TRI_voc_tick_t id, arangodb::velocypack::Slice const& args ){
|
||||
int status;
|
||||
Database* rv = createDatabase(id, args, status);
|
||||
TRI_vocbase_t* rv = createDatabase(id, args, status);
|
||||
TRI_ASSERT(status == TRI_ERROR_NO_ERROR);
|
||||
TRI_ASSERT(rv != nullptr);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// @brief wirte create marker for database
|
||||
// @brief write create marker for database
|
||||
virtual int writeCreateDatabaseMarker(TRI_voc_tick_t id, VPackSlice const& slice) = 0;
|
||||
|
||||
// asks the storage engine to drop the specified database and persist the
|
||||
|
@ -194,14 +193,14 @@ class StorageEngine : public application_features::ApplicationFeature {
|
|||
//
|
||||
// is done under a lock in database feature
|
||||
virtual void prepareDropDatabase(TRI_vocbase_t* vocbase, bool useWriteMarker, int& status) = 0;
|
||||
void prepareDropDatabase(Database* db, bool useWriteMarker){
|
||||
void prepareDropDatabase(TRI_vocbase_t* db, bool useWriteMarker){
|
||||
int status = 0;
|
||||
prepareDropDatabase(db, useWriteMarker, status);
|
||||
TRI_ASSERT(status == TRI_ERROR_NO_ERROR);
|
||||
};
|
||||
|
||||
// perform a physical deletion of the database
|
||||
virtual Result dropDatabase(Database*) = 0;
|
||||
virtual Result dropDatabase(TRI_vocbase_t*) = 0;
|
||||
|
||||
/// @brief wait until a database directory disappears - not under lock in databaseFreature
|
||||
virtual void waitUntilDeletion(TRI_voc_tick_t id, bool force, int& status) = 0;
|
||||
|
|
|
@ -40,7 +40,9 @@ class DatabaseGuard {
|
|||
explicit DatabaseGuard(TRI_vocbase_t* vocbase)
|
||||
: _vocbase(vocbase) {
|
||||
TRI_ASSERT(vocbase != nullptr);
|
||||
_vocbase->use();
|
||||
if (!_vocbase->use()) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief create the guard, using a database id
|
||||
|
|
|
@ -566,7 +566,7 @@ V8Context* V8DealerFeature::enterContext(TRI_vocbase_t* vocbase,
|
|||
|
||||
TimedAction exitWhenNoContext([](double waitTime) {
|
||||
LOG_TOPIC(WARN, arangodb::Logger::V8) << "giving up waiting for unused V8 context after " << Logger::FIXED(waitTime) << " s";
|
||||
}, 120);
|
||||
}, 60);
|
||||
|
||||
|
||||
V8Context* context = nullptr;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "Basics/conversions.h"
|
||||
#include "Basics/tri-strings.h"
|
||||
#include "Cluster/ClusterFeature.h"
|
||||
#include "Cluster/ClusterInfo.h"
|
||||
#include "Cluster/ClusterMethods.h"
|
||||
#include "Indexes/Index.h"
|
||||
|
@ -669,12 +670,8 @@ static void CreateVocBase(v8::FunctionCallbackInfo<v8::Value> const& args,
|
|||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// We require exactly 1 or exactly 2 arguments -- anything else is an error
|
||||
// ...........................................................................
|
||||
|
||||
if (args.Length() < 1 || args.Length() > 3) {
|
||||
TRI_V8_THROW_EXCEPTION_USAGE("_create(<name>, <properties>, <type>)");
|
||||
if (args.Length() < 1 || args.Length() > 4) {
|
||||
TRI_V8_THROW_EXCEPTION_USAGE("_create(<name>, <properties>, <type>, <options>)");
|
||||
}
|
||||
|
||||
if (TRI_GetOperationModeServer() == TRI_VOCBASE_MODE_NO_CREATE) {
|
||||
|
@ -682,7 +679,7 @@ static void CreateVocBase(v8::FunctionCallbackInfo<v8::Value> const& args,
|
|||
}
|
||||
|
||||
// optional, third parameter can override collection type
|
||||
if (args.Length() == 3 && args[2]->IsString()) {
|
||||
if (args.Length() >= 3 && args[2]->IsString()) {
|
||||
std::string typeString = TRI_ObjectToString(args[2]);
|
||||
if (typeString == "edge") {
|
||||
collectionType = TRI_COL_TYPE_EDGE;
|
||||
|
@ -691,6 +688,7 @@ static void CreateVocBase(v8::FunctionCallbackInfo<v8::Value> const& args,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
PREVENT_EMBEDDED_TRANSACTION();
|
||||
|
||||
// extract the name
|
||||
|
@ -725,9 +723,19 @@ static void CreateVocBase(v8::FunctionCallbackInfo<v8::Value> const& args,
|
|||
infoSlice = builder.slice();
|
||||
|
||||
if (ServerState::instance()->isCoordinator()) {
|
||||
bool createWaitsForSyncReplication = application_features::ApplicationServer::getFeature<ClusterFeature>("Cluster")->createWaitsForSyncReplication();
|
||||
|
||||
if (args.Length() >= 3 && args[args.Length()-1]->IsObject()) {
|
||||
v8::Handle<v8::Object> obj = args[args.Length()-1]->ToObject();
|
||||
auto v8WaitForSyncReplication = obj->Get(TRI_V8_ASCII_STRING("waitForSyncReplication"));
|
||||
if (!v8WaitForSyncReplication->IsUndefined()) {
|
||||
createWaitsForSyncReplication = TRI_ObjectToBoolean(v8WaitForSyncReplication);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<LogicalCollection> col =
|
||||
ClusterMethods::createCollectionOnCoordinator(collectionType, vocbase,
|
||||
infoSlice);
|
||||
infoSlice, true, createWaitsForSyncReplication);
|
||||
TRI_V8_RETURN(WrapCollection(isolate, col.release()));
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,8 @@ macro (install_readme input output)
|
|||
endif ()
|
||||
|
||||
install(
|
||||
CODE "configure_file(${PROJECT_SOURCE_DIR}/${input} \"${PROJECT_BINARY_DIR}/${output}\" NEWLINE_STYLE ${CRLFSTYLE})"
|
||||
CODE "configure_file(${PROJECT_SOURCE_DIR}/${input} \"${PROJECT_BINARY_DIR}/${output}\" NEWLINE_STYLE ${CRLFSTYLE})")
|
||||
install(
|
||||
FILES "${PROJECT_BINARY_DIR}/${output}"
|
||||
DESTINATION "${where}"
|
||||
)
|
||||
|
|
|
@ -65,7 +65,6 @@ function collectionRepresentation(collection, showProperties, showCount, showFig
|
|||
|
||||
if (cluster.isCoordinator()) {
|
||||
result.avoidServers = properties.avoidServers;
|
||||
result.distributeShardsLike = properties.distributeShardsLike;
|
||||
result.numberOfShards = properties.numberOfShards;
|
||||
result.replicationFactor = properties.replicationFactor;
|
||||
result.avoidServers = properties.avoidServers;
|
||||
|
@ -206,6 +205,15 @@ function post_api_collection (req, res) {
|
|||
}
|
||||
|
||||
try {
|
||||
var options = {};
|
||||
if (req.parameters.hasOwnProperty('waitForSyncReplication')) {
|
||||
var value = req.parameters.waitForSyncReplication.toLowerCase();
|
||||
if (value === 'true' || value === 'yes' || value === 'on' || value === 'y' || value === '1') {
|
||||
options.waitForSyncReplication = true;
|
||||
} else {
|
||||
options.waitForSyncReplication = false;
|
||||
}
|
||||
}
|
||||
var collection;
|
||||
if (typeof (r.type) === 'string') {
|
||||
if (r.type.toLowerCase() === 'edge' || r.type === '3') {
|
||||
|
@ -213,9 +221,9 @@ function post_api_collection (req, res) {
|
|||
}
|
||||
}
|
||||
if (r.type === arangodb.ArangoCollection.TYPE_EDGE) {
|
||||
collection = arangodb.db._createEdgeCollection(r.name, r.parameters);
|
||||
collection = arangodb.db._createEdgeCollection(r.name, r.parameters, options);
|
||||
} else {
|
||||
collection = arangodb.db._createDocumentCollection(r.name, r.parameters);
|
||||
collection = arangodb.db._createDocumentCollection(r.name, r.parameters, options);
|
||||
}
|
||||
|
||||
var result = {};
|
||||
|
|
|
@ -970,12 +970,25 @@ actions.defineHttp({
|
|||
"body must be an object with a string attribute 'server'");
|
||||
return;
|
||||
}
|
||||
|
||||
// First translate the server name from short name to long name:
|
||||
var server = body.server;
|
||||
var servers = global.ArangoClusterInfo.getDBServers();
|
||||
for (let i = 0; i < servers.length; i++) {
|
||||
if (servers[i].serverId !== server) {
|
||||
if (servers[i].serverName === server) {
|
||||
server = servers[i].serverId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var ok = true;
|
||||
var id;
|
||||
try {
|
||||
id = ArangoClusterInfo.uniqid();
|
||||
var todo = { 'type': 'cleanOutServer',
|
||||
'server': body.server,
|
||||
'server': server,
|
||||
'jobId': id,
|
||||
'timeCreated': (new Date()).toISOString(),
|
||||
'creator': ArangoServerState.id() };
|
||||
|
|
|
@ -345,7 +345,7 @@ ArangoCollection.prototype.properties = function (properties) {
|
|||
requestResult = this._database._connection.GET(this._baseurl('properties'));
|
||||
|
||||
arangosh.checkRequestResult(requestResult);
|
||||
}else {
|
||||
} else {
|
||||
var body = {};
|
||||
|
||||
for (a in attributes) {
|
||||
|
|
|
@ -339,7 +339,7 @@ ArangoDatabase.prototype._collection = function (id) {
|
|||
// / @brief creates a new collection
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ArangoDatabase.prototype._create = function (name, properties, type) {
|
||||
ArangoDatabase.prototype._create = function (name, properties, type, options) {
|
||||
var body = {
|
||||
'name': name,
|
||||
'type': ArangoCollection.TYPE_DOCUMENT
|
||||
|
@ -355,12 +355,23 @@ ArangoDatabase.prototype._create = function (name, properties, type) {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
let urlAddon = '';
|
||||
if (typeof options === "object" && options !== null) {
|
||||
if (options.hasOwnProperty('waitForSyncReplication')) {
|
||||
if (options.waitForSyncReplication) {
|
||||
urlAddon = '?waitForSyncReplication=1';
|
||||
} else {
|
||||
urlAddon = '?waitForSyncReplication=0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type !== undefined) {
|
||||
body.type = type;
|
||||
}
|
||||
|
||||
var requestResult = this._connection.POST(this._collectionurl(),
|
||||
var requestResult = this._connection.POST(this._collectionurl() + urlAddon,
|
||||
JSON.stringify(body));
|
||||
|
||||
arangosh.checkRequestResult(requestResult);
|
||||
|
|
|
@ -805,6 +805,58 @@ describe('Cluster sync', function() {
|
|||
db._useDatabase('test');
|
||||
expect(db._collection('s100001').isLeader()).to.equal(true);
|
||||
});
|
||||
it('should kill any unplanned server from current', function() {
|
||||
let collection = db._create('s100001');
|
||||
collection.assumeLeadership();
|
||||
collection.addFollower('test');
|
||||
collection.addFollower('test2');
|
||||
let plan = {
|
||||
test: {
|
||||
"100001": {
|
||||
"deleted": false,
|
||||
"doCompact": true,
|
||||
"id": "100001",
|
||||
"indexBuckets": 8,
|
||||
"indexes": [
|
||||
{
|
||||
"fields": [
|
||||
"_key"
|
||||
],
|
||||
"id": "0",
|
||||
"sparse": false,
|
||||
"type": "primary",
|
||||
"unique": true
|
||||
}
|
||||
],
|
||||
"isSystem": false,
|
||||
"isVolatile": false,
|
||||
"journalSize": 1048576,
|
||||
"keyOptions": {
|
||||
"allowUserKeys": true,
|
||||
"type": "traditional"
|
||||
},
|
||||
"name": "testi",
|
||||
"numberOfShards": 1,
|
||||
"replicationFactor": 2,
|
||||
"shardKeys": [
|
||||
"_key"
|
||||
],
|
||||
"shards": {
|
||||
"s100001": [
|
||||
"repltest",
|
||||
"test2",
|
||||
]
|
||||
},
|
||||
"status": 2,
|
||||
"type": 2,
|
||||
"waitForSync": false
|
||||
}
|
||||
}
|
||||
};
|
||||
cluster.executePlanForCollections(plan);
|
||||
db._useDatabase('test');
|
||||
expect(collection.getFollowers()).to.deep.equal(['test2']);
|
||||
});
|
||||
});
|
||||
describe('Update current database', function() {
|
||||
beforeEach(function() {
|
||||
|
@ -972,7 +1024,7 @@ describe('Cluster sync', function() {
|
|||
let collection = db._create('testi', props);
|
||||
let current = {
|
||||
};
|
||||
let result = cluster.updateCurrentForCollections({}, current);
|
||||
let result = cluster.updateCurrentForCollections({}, {}, current);
|
||||
expect(Object.keys(result)).to.have.lengthOf(0);
|
||||
});
|
||||
it('should not delete any collections for which we are not a leader locally', function() {
|
||||
|
@ -983,7 +1035,7 @@ describe('Cluster sync', function() {
|
|||
},
|
||||
}
|
||||
};
|
||||
let result = cluster.updateCurrentForCollections({}, current);
|
||||
let result = cluster.updateCurrentForCollections({}, {}, current);
|
||||
expect(Object.keys(result)).to.have.lengthOf(0);
|
||||
});
|
||||
it('should resign leadership for which we are no more leader locally', function() {
|
||||
|
@ -996,7 +1048,7 @@ describe('Cluster sync', function() {
|
|||
},
|
||||
}
|
||||
};
|
||||
let result = cluster.updateCurrentForCollections({}, current);
|
||||
let result = cluster.updateCurrentForCollections({}, {}, current);
|
||||
expect(result).to.be.an('object');
|
||||
expect(Object.keys(result)).to.have.lengthOf(1);
|
||||
expect(result).to.have.property('/arango/Current/Collections/testung/888111/testi/servers')
|
||||
|
@ -1016,7 +1068,7 @@ describe('Cluster sync', function() {
|
|||
},
|
||||
}
|
||||
};
|
||||
let result = cluster.updateCurrentForCollections({}, current);
|
||||
let result = cluster.updateCurrentForCollections({}, {}, current);
|
||||
expect(result).to.be.an('object');
|
||||
expect(Object.keys(result)).to.have.lengthOf(1);
|
||||
expect(result).to.have.property('/arango/Current/Collections/testung/888111/testi')
|
||||
|
@ -1033,7 +1085,7 @@ describe('Cluster sync', function() {
|
|||
},
|
||||
}
|
||||
};
|
||||
let result = cluster.updateCurrentForCollections({}, current);
|
||||
let result = cluster.updateCurrentForCollections({}, {}, current);
|
||||
expect(result).to.be.an('object');
|
||||
expect(Object.keys(result)).to.have.lengthOf(1);
|
||||
expect(result).to.have.property('/arango/Current/Collections/testung/888111/testi')
|
||||
|
@ -1051,7 +1103,7 @@ describe('Cluster sync', function() {
|
|||
},
|
||||
}
|
||||
};
|
||||
let result = cluster.updateCurrentForCollections({}, current);
|
||||
let result = cluster.updateCurrentForCollections({}, {}, current);
|
||||
expect(result).to.be.an('object');
|
||||
expect(Object.keys(result)).to.have.lengthOf(1);
|
||||
expect(result).to.have.property('/arango/Current/Collections/testung/888111/testi')
|
||||
|
|
|
@ -58,7 +58,7 @@ function dumpTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test the empty collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testEmpty : function () {
|
||||
var c = db._collection("UnitTestsDumpEmpty");
|
||||
var p = c.properties();
|
||||
|
@ -76,7 +76,7 @@ function dumpTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test the collection with many documents
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testMany : function () {
|
||||
var c = db._collection("UnitTestsDumpMany");
|
||||
var p = c.properties();
|
||||
|
@ -101,7 +101,7 @@ function dumpTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test the edges collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testEdges : function () {
|
||||
var c = db._collection("UnitTestsDumpEdges");
|
||||
var p = c.properties();
|
||||
|
@ -128,7 +128,7 @@ function dumpTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test the order of documents
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testOrder : function () {
|
||||
var c = db._collection("UnitTestsDumpOrder");
|
||||
var p = c.properties();
|
||||
|
@ -146,7 +146,7 @@ function dumpTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test document removal & update
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testRemoved : function () {
|
||||
var c = db._collection("UnitTestsDumpRemoved");
|
||||
var p = c.properties();
|
||||
|
@ -178,7 +178,7 @@ function dumpTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test indexes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testIndexes : function () {
|
||||
var c = db._collection("UnitTestsDumpIndexes");
|
||||
var p = c.properties();
|
||||
|
@ -200,32 +200,32 @@ function dumpTestSuite () {
|
|||
assertFalse(c.getIndexes()[2].unique);
|
||||
assertFalse(c.getIndexes()[2].sparse);
|
||||
assertEqual([ "a_s1", "a_s2" ], c.getIndexes()[2].fields);
|
||||
|
||||
|
||||
assertEqual("hash", c.getIndexes()[3].type);
|
||||
assertFalse(c.getIndexes()[3].unique);
|
||||
assertFalse(c.getIndexes()[3].sparse);
|
||||
assertEqual([ "a_h1", "a_h2" ], c.getIndexes()[3].fields);
|
||||
|
||||
|
||||
assertEqual("skiplist", c.getIndexes()[4].type);
|
||||
assertTrue(c.getIndexes()[4].unique);
|
||||
assertFalse(c.getIndexes()[4].sparse);
|
||||
assertEqual([ "a_su" ], c.getIndexes()[4].fields);
|
||||
|
||||
|
||||
assertEqual("hash", c.getIndexes()[5].type);
|
||||
assertFalse(c.getIndexes()[5].unique);
|
||||
assertTrue(c.getIndexes()[5].sparse);
|
||||
assertEqual([ "a_hs1", "a_hs2" ], c.getIndexes()[5].fields);
|
||||
|
||||
|
||||
assertEqual("skiplist", c.getIndexes()[6].type);
|
||||
assertFalse(c.getIndexes()[6].unique);
|
||||
assertTrue(c.getIndexes()[6].sparse);
|
||||
assertEqual([ "a_ss1", "a_ss2" ], c.getIndexes()[6].fields);
|
||||
|
||||
|
||||
if (db._engine().name !== "rocksdb") {
|
||||
assertFalse(c.getIndexes()[7].unique);
|
||||
assertEqual("fulltext", c.getIndexes()[7].type);
|
||||
assertEqual([ "a_f" ], c.getIndexes()[7].fields);
|
||||
|
||||
|
||||
assertEqual("geo2", c.getIndexes()[8].type);
|
||||
assertEqual([ "a_la", "a_lo" ], c.getIndexes()[8].fields);
|
||||
assertFalse(c.getIndexes()[8].unique);
|
||||
|
@ -237,7 +237,7 @@ function dumpTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test truncate
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testTruncated : function () {
|
||||
var c = db._collection("UnitTestsDumpTruncated");
|
||||
var p = c.properties();
|
||||
|
@ -254,7 +254,7 @@ function dumpTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test keygen
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testKeygen : function () {
|
||||
var c = db._collection("UnitTestsDumpKeygen");
|
||||
var p = c.properties();
|
||||
|
@ -270,7 +270,7 @@ function dumpTestSuite () {
|
|||
assertEqual(1, c.getIndexes().length); // just primary index
|
||||
assertEqual("primary", c.getIndexes()[0].type);
|
||||
assertEqual(1000, c.count());
|
||||
|
||||
|
||||
for (var i = 0; i < 1000; ++i) {
|
||||
var doc = c.document(String(7 + (i * 42)));
|
||||
|
||||
|
@ -283,7 +283,7 @@ function dumpTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test strings
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testStrings : function () {
|
||||
var c = db._collection("UnitTestsDumpStrings");
|
||||
var p = c.properties();
|
||||
|
@ -298,18 +298,18 @@ function dumpTestSuite () {
|
|||
|
||||
var texts = [
|
||||
"big. Really big. He moment. Magrathea! - insisted Arthur, - I do you can sense no further because it doesn't fit properly. In my the denies faith, and the atmosphere beneath You are not cheap He was was his satchel. He throughout Magrathea. - He pushed a tore the ecstatic crowd. Trillian sat down the time, the existence is it? And he said, - What they don't want this airtight hatchway. - it's we you shooting people would represent their Poet Master Grunthos is in his mind.",
|
||||
"Ultimo cadere chi sedete uso chiuso voluto ora. Scotendosi portartela meraviglia ore eguagliare incessante allegrezza per. Pensava maestro pungeva un le tornano ah perduta. Fianco bearmi storia soffio prende udi poteva una. Cammino fascino elisire orecchi pollici mio cui sai sul. Chi egli sino sei dita ben. Audace agonie groppa afa vai ultima dentro scossa sii. Alcuni mia blocco cerchi eterno andare pagine poi. Ed migliore di sommesso oh ai angoscia vorresti.",
|
||||
"Ultimo cadere chi sedete uso chiuso voluto ora. Scotendosi portartela meraviglia ore eguagliare incessante allegrezza per. Pensava maestro pungeva un le tornano ah perduta. Fianco bearmi storia soffio prende udi poteva una. Cammino fascino elisire orecchi pollici mio cui sai sul. Chi egli sino sei dita ben. Audace agonie groppa afa vai ultima dentro scossa sii. Alcuni mia blocco cerchi eterno andare pagine poi. Ed migliore di sommesso oh ai angoscia vorresti.",
|
||||
"Νέο βάθος όλα δομές της χάσει. Μέτωπο εγώ συνάμα τρόπος και ότι όσο εφόδιο κόσμου. Προτίμηση όλη διάφορους του όλο εύθραυστη συγγραφής. Στα άρα ένα μία οποία άλλων νόημα. Ένα αποβαίνει ρεαλισμού μελετητές θεόσταλτο την. Ποντιακών και rites κοριτσάκι παπούτσια παραμύθια πει κυρ.",
|
||||
"Mody laty mnie ludu pole rury Białopiotrowiczowi. Domy puer szczypię jemy pragnął zacność czytając ojca lasy Nowa wewnątrz klasztoru. Chce nóg mego wami. Zamku stał nogą imion ludzi ustaw Białopiotrowiczem. Kwiat Niesiołowskiemu nierostrzygniony Staje brał Nauka dachu dumę Zamku Kościuszkowskie zagon. Jakowaś zapytać dwie mój sama polu uszakach obyczaje Mój. Niesiołowski książkowéj zimny mały dotychczasowa Stryj przestraszone Stolnikównie wdał śmiertelnego. Stanisława charty kapeluszach mięty bratem każda brząknął rydwan.",
|
||||
"Мелких против летают хижину тмится. Чудесам возьмет звездна Взжигай. . Податель сельские мучитель сверкает очищаясь пламенем. Увы имя меч Мое сия. Устранюсь воздушных Им от До мысленные потушатся Ко Ея терпеньем.",
|
||||
"Мелких против летают хижину тмится. Чудесам возьмет звездна Взжигай. . Податель сельские мучитель сверкает очищаясь пламенем. Увы имя меч Мое сия. Устранюсь воздушных Им от До мысленные потушатся Ко Ея терпеньем.",
|
||||
"dotyku. Výdech spalin bude položen záplavový detekční kabely 1x UPS Newave Conceptpower DPA 5x 40kVA bude ukončen v samostatné strojovně. Samotné servery mají pouze lokalita Ústí nad zdvojenou podlahou budou zakončené GateWayí HiroLink - Monitoring rozvaděče RTN na jednotlivých záplavových zón na soustrojí resp. technologie jsou označeny SA-MKx.y. Jejich výstupem je zajištěn přestupem dat z jejich provoz. Na dveřích vylepené výstražné tabulky. Kabeláž z okruhů zálohovaných obvodů v R.MON-I. Monitoring EZS, EPS, ... možno zajistit funkčností FireWallů na strukturovanou kabeláží vedenou v měrných jímkách zapuštěných v každém racku budou zakončeny v R.MON-NrNN. Monitoring motorgenerátorů: řídící systém bude zakončena v modulu",
|
||||
"ramien mu zrejme vôbec niekto je už presne čo mám tendenciu prispôsobiť dych jej páčil, čo chce. Hmm... Včera sa mi pozdava, len dočkali, ale keďže som na uz boli u jej nezavrela. Hlava jej to ve městě nepotká, hodně mi to tí vedci pri hre, keď je tu pre Designiu. Pokiaľ viete o odbornejšie texty. Prvým z tmavých uličiek, každý to niekedy, zrovnávať krok s obrovským batohom na okraj vane a temné úmysly, tak rozmýšľam, aký som si hromady mailov, čo chcem a neraz sa pokúšal o filmovém klubu v budúcnosti rozhodne uniesť mladú maliarku (Linda Rybová), ktorú so",
|
||||
" 復讐者」. 復讐者」. 伯母さん 復讐者」. 復讐者」. 復讐者」. 復讐者」. 第九章 第五章 第六章 第七章 第八章. 復讐者」 伯母さん. 復讐者」 伯母さん. 第十一章 第十九章 第十四章 第十八章 第十三章 第十五章. 復讐者」 . 第十四章 第十一章 第十二章 第十五章 第十七章 手配書. 第十四章 手配書 第十八章 第十七章 第十六章 第十三章. 第十一章 第十三章 第十八章 第十四章 手配書. 復讐者」."
|
||||
];
|
||||
|
||||
texts.forEach(function (t, i) {
|
||||
texts.forEach(function (t, i) {
|
||||
var doc = c.document("text" + i);
|
||||
|
||||
|
||||
assertEqual(t, doc.value);
|
||||
});
|
||||
|
||||
|
@ -318,12 +318,12 @@ function dumpTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test committed trx
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testTransactionCommit : function () {
|
||||
var c = db._collection("UnitTestsDumpTransactionCommit");
|
||||
|
||||
assertEqual(1000, c.count());
|
||||
|
||||
|
||||
for (var i = 0; i < 1000; ++i) {
|
||||
var doc = c.document("test" + i);
|
||||
|
||||
|
@ -336,12 +336,12 @@ function dumpTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test committed trx
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testTransactionUpdate : function () {
|
||||
var c = db._collection("UnitTestsDumpTransactionUpdate");
|
||||
|
||||
assertEqual(1000, c.count());
|
||||
|
||||
|
||||
for (var i = 0; i < 1000; ++i) {
|
||||
var doc = c.document("test" + i);
|
||||
|
||||
|
@ -359,37 +359,37 @@ function dumpTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test aborted trx
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testTransactionAbort : function () {
|
||||
var c = db._collection("UnitTestsDumpTransactionAbort");
|
||||
|
||||
assertEqual(1, c.count());
|
||||
|
||||
|
||||
assertTrue(c.exists("foo"));
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test persistent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
testPersistent : function () {
|
||||
var c = db._collection("UnitTestsDumpPersistent");
|
||||
var p = c.properties();
|
||||
|
||||
assertEqual(2, c.getIndexes().length);
|
||||
assertEqual(2, c.getIndexes().length);
|
||||
assertEqual("primary", c.getIndexes()[0].type);
|
||||
assertEqual("persistent", c.getIndexes()[1].type);
|
||||
assertEqual(10000, c.count());
|
||||
|
||||
var res = db._query("FOR doc IN " + c.name() + " FILTER doc.value >= 0 RETURN doc").toArray();
|
||||
assertEqual(10000, res.length);
|
||||
|
||||
|
||||
res = db._query("FOR doc IN " + c.name() + " FILTER doc.value >= 5000 RETURN doc").toArray();
|
||||
assertEqual(5000, res.length);
|
||||
|
||||
|
||||
res = db._query("FOR doc IN " + c.name() + " FILTER doc.value >= 9000 RETURN doc").toArray();
|
||||
assertEqual(1000, res.length);
|
||||
|
||||
|
||||
res = db._query("FOR doc IN " + c.name() + " FILTER doc.value >= 10000 RETURN doc").toArray();
|
||||
assertEqual(0, res.length);
|
||||
}
|
||||
|
@ -404,4 +404,3 @@ function dumpTestSuite () {
|
|||
jsunity.run(dumpTestSuite);
|
||||
|
||||
return jsunity.done();
|
||||
|
||||
|
|
|
@ -0,0 +1,308 @@
|
|||
/*jshint globalstrict:false, strict:false, maxlen : 4000 */
|
||||
/*global assertEqual, assertTrue, assertFalse */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests for dump/reload
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2012 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 triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var internal = require("internal");
|
||||
var jsunity = require("jsunity");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function dumpTestSuite () {
|
||||
'use strict';
|
||||
var db = internal.db;
|
||||
|
||||
return {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set up
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
setUp : function () {
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tear down
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
tearDown : function () {
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test the empty collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testEmpty : function () {
|
||||
var c = db._collection("UnitTestsDumpEmpty");
|
||||
var p = c.properties();
|
||||
|
||||
assertEqual(2, c.type()); // document
|
||||
assertTrue(p.waitForSync);
|
||||
|
||||
assertEqual(1, c.getIndexes().length); // just primary index
|
||||
assertEqual("primary", c.getIndexes()[0].type);
|
||||
assertEqual(0, c.count());
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test the collection with many documents
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testMany : function () {
|
||||
var c = db._collection("UnitTestsDumpMany");
|
||||
var p = c.properties();
|
||||
|
||||
assertEqual(2, c.type()); // document
|
||||
assertFalse(p.waitForSync);
|
||||
|
||||
assertEqual(1, c.getIndexes().length); // just primary index
|
||||
assertEqual("primary", c.getIndexes()[0].type);
|
||||
assertEqual(100000, c.count());
|
||||
|
||||
// test all documents
|
||||
var r = db._query(`FOR d IN ${c.name()} RETURN d`).toArray();
|
||||
var rr = new Map();
|
||||
for (let i = 0; i < r.length; ++i) {
|
||||
rr.set(r[i]._key, r[i]);
|
||||
}
|
||||
for (let i = 0; i < 100000; ++i) {
|
||||
var doc = rr.get("test" + i);
|
||||
assertEqual(i, doc.value1);
|
||||
assertEqual("this is a test", doc.value2);
|
||||
assertEqual("test" + i, doc.value3);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test the edges collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testEdges : function () {
|
||||
var c = db._collection("UnitTestsDumpEdges");
|
||||
var p = c.properties();
|
||||
|
||||
assertEqual(3, c.type()); // edges
|
||||
assertFalse(p.waitForSync);
|
||||
|
||||
assertEqual(2, c.getIndexes().length); // primary index + edges index
|
||||
assertEqual("primary", c.getIndexes()[0].type);
|
||||
assertEqual("edge", c.getIndexes()[1].type);
|
||||
assertEqual(10, c.count());
|
||||
|
||||
// test all documents
|
||||
for (var i = 0; i < 10; ++i) {
|
||||
var doc = c.document("test" + i);
|
||||
assertEqual("test" + i, doc._key);
|
||||
assertEqual("UnitTestsDumpMany/test" + i, doc._from);
|
||||
assertEqual("UnitTestsDumpMany/test" + (i + 1), doc._to);
|
||||
assertEqual(i + "->" + (i + 1), doc.what);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test the order of documents
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testOrder : function () {
|
||||
var c = db._collection("UnitTestsDumpOrder");
|
||||
var p = c.properties();
|
||||
|
||||
assertEqual(2, c.type()); // document
|
||||
assertFalse(p.waitForSync);
|
||||
|
||||
assertEqual(1, c.getIndexes().length); // just primary index
|
||||
assertEqual("primary", c.getIndexes()[0].type);
|
||||
assertEqual(3, c.count());
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test document removal & update
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRemoved : function () {
|
||||
var c = db._collection("UnitTestsDumpRemoved");
|
||||
var p = c.properties();
|
||||
|
||||
assertEqual(2, c.type()); // document
|
||||
assertFalse(p.waitForSync);
|
||||
|
||||
assertEqual(1, c.getIndexes().length); // just primary index
|
||||
assertEqual("primary", c.getIndexes()[0].type);
|
||||
assertEqual(9000, c.count());
|
||||
|
||||
var i;
|
||||
for (i = 0; i < 10000; ++i) {
|
||||
if (i % 10 === 0) {
|
||||
assertFalse(c.exists("test" + i));
|
||||
}
|
||||
else {
|
||||
var doc = c.document("test" + i);
|
||||
assertEqual(i, doc.value1);
|
||||
|
||||
if (i < 1000) {
|
||||
assertEqual(i + 1, doc.value2);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test indexes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testIndexes : function () {
|
||||
var c = db._collection("UnitTestsDumpIndexes");
|
||||
var p = c.properties();
|
||||
|
||||
assertEqual(2, c.type()); // document
|
||||
assertFalse(p.waitForSync);
|
||||
|
||||
assertEqual(7, c.getIndexes().length);
|
||||
assertEqual("primary", c.getIndexes()[0].type);
|
||||
|
||||
assertEqual("hash", c.getIndexes()[1].type);
|
||||
assertTrue(c.getIndexes()[1].unique);
|
||||
assertFalse(c.getIndexes()[1].sparse);
|
||||
assertEqual([ "a_uc" ], c.getIndexes()[1].fields);
|
||||
|
||||
assertEqual("skiplist", c.getIndexes()[2].type);
|
||||
assertFalse(c.getIndexes()[2].unique);
|
||||
assertFalse(c.getIndexes()[2].sparse);
|
||||
assertEqual([ "a_s1", "a_s2" ], c.getIndexes()[2].fields);
|
||||
|
||||
assertEqual("hash", c.getIndexes()[3].type);
|
||||
assertFalse(c.getIndexes()[3].unique);
|
||||
assertFalse(c.getIndexes()[3].sparse);
|
||||
assertEqual([ "a_h1", "a_h2" ], c.getIndexes()[3].fields);
|
||||
|
||||
assertEqual("skiplist", c.getIndexes()[4].type);
|
||||
assertTrue(c.getIndexes()[4].unique);
|
||||
assertFalse(c.getIndexes()[4].sparse);
|
||||
assertEqual([ "a_su" ], c.getIndexes()[4].fields);
|
||||
|
||||
assertEqual("hash", c.getIndexes()[5].type);
|
||||
assertFalse(c.getIndexes()[5].unique);
|
||||
assertTrue(c.getIndexes()[5].sparse);
|
||||
assertEqual([ "a_hs1", "a_hs2" ], c.getIndexes()[5].fields);
|
||||
|
||||
assertEqual("skiplist", c.getIndexes()[6].type);
|
||||
assertFalse(c.getIndexes()[6].unique);
|
||||
assertTrue(c.getIndexes()[6].sparse);
|
||||
assertEqual([ "a_ss1", "a_ss2" ], c.getIndexes()[6].fields);
|
||||
|
||||
assertEqual(0, c.count());
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test truncate
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testTruncated : function () {
|
||||
var c = db._collection("UnitTestsDumpTruncated");
|
||||
var p = c.properties();
|
||||
|
||||
assertEqual(2, c.type()); // document
|
||||
assertFalse(p.waitForSync);
|
||||
|
||||
assertEqual(1, c.getIndexes().length); // just primary index
|
||||
assertEqual("primary", c.getIndexes()[0].type);
|
||||
assertEqual(0, c.count());
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test shards
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testShards : function () {
|
||||
var c = db._collection("UnitTestsDumpShards");
|
||||
var p = c.properties();
|
||||
|
||||
assertEqual(2, c.type()); // document
|
||||
assertFalse(p.waitForSync);
|
||||
assertEqual(9, p.numberOfShards);
|
||||
|
||||
assertEqual(1, c.getIndexes().length); // just primary index
|
||||
assertEqual("primary", c.getIndexes()[0].type);
|
||||
assertEqual(1000, c.count());
|
||||
|
||||
for (var i = 0; i < 1000; ++i) {
|
||||
var doc = c.document(String(7 + (i * 42)));
|
||||
|
||||
assertEqual(String(7 + (i * 42)), doc._key);
|
||||
assertEqual(i, doc.value);
|
||||
assertEqual({ value: [ i, i ] }, doc.more);
|
||||
}
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test strings
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testStrings : function () {
|
||||
var c = db._collection("UnitTestsDumpStrings");
|
||||
var p = c.properties();
|
||||
|
||||
assertEqual(2, c.type()); // document
|
||||
assertFalse(p.waitForSync);
|
||||
|
||||
assertEqual(1, c.getIndexes().length); // just primary index
|
||||
assertEqual("primary", c.getIndexes()[0].type);
|
||||
assertEqual(8, c.count());
|
||||
|
||||
var texts = [
|
||||
"big. Really big. He moment. Magrathea! - insisted Arthur, - I do you can sense no further because it doesn't fit properly. In my the denies faith, and the atmosphere beneath You are not cheap He was was his satchel. He throughout Magrathea. - He pushed a tore the ecstatic crowd. Trillian sat down the time, the existence is it? And he said, - What they don't want this airtight hatchway. - it's we you shooting people would represent their Poet Master Grunthos is in his mind.",
|
||||
"Ultimo cadere chi sedete uso chiuso voluto ora. Scotendosi portartela meraviglia ore eguagliare incessante allegrezza per. Pensava maestro pungeva un le tornano ah perduta. Fianco bearmi storia soffio prende udi poteva una. Cammino fascino elisire orecchi pollici mio cui sai sul. Chi egli sino sei dita ben. Audace agonie groppa afa vai ultima dentro scossa sii. Alcuni mia blocco cerchi eterno andare pagine poi. Ed migliore di sommesso oh ai angoscia vorresti.",
|
||||
"Νέο βάθος όλα δομές της χάσει. Μέτωπο εγώ συνάμα τρόπος και ότι όσο εφόδιο κόσμου. Προτίμηση όλη διάφορους του όλο εύθραυστη συγγραφής. Στα άρα ένα μία οποία άλλων νόημα. Ένα αποβαίνει ρεαλισμού μελετητές θεόσταλτο την. Ποντιακών και rites κοριτσάκι παπούτσια παραμύθια πει κυρ.",
|
||||
"Mody laty mnie ludu pole rury Białopiotrowiczowi. Domy puer szczypię jemy pragnął zacność czytając ojca lasy Nowa wewnątrz klasztoru. Chce nóg mego wami. Zamku stał nogą imion ludzi ustaw Białopiotrowiczem. Kwiat Niesiołowskiemu nierostrzygniony Staje brał Nauka dachu dumę Zamku Kościuszkowskie zagon. Jakowaś zapytać dwie mój sama polu uszakach obyczaje Mój. Niesiołowski książkowéj zimny mały dotychczasowa Stryj przestraszone Stolnikównie wdał śmiertelnego. Stanisława charty kapeluszach mięty bratem każda brząknął rydwan.",
|
||||
"Мелких против летают хижину тмится. Чудесам возьмет звездна Взжигай. . Податель сельские мучитель сверкает очищаясь пламенем. Увы имя меч Мое сия. Устранюсь воздушных Им от До мысленные потушатся Ко Ея терпеньем.",
|
||||
"dotyku. Výdech spalin bude položen záplavový detekční kabely 1x UPS Newave Conceptpower DPA 5x 40kVA bude ukončen v samostatné strojovně. Samotné servery mají pouze lokalita Ústí nad zdvojenou podlahou budou zakončené GateWayí HiroLink - Monitoring rozvaděče RTN na jednotlivých záplavových zón na soustrojí resp. technologie jsou označeny SA-MKx.y. Jejich výstupem je zajištěn přestupem dat z jejich provoz. Na dveřích vylepené výstražné tabulky. Kabeláž z okruhů zálohovaných obvodů v R.MON-I. Monitoring EZS, EPS, ... možno zajistit funkčností FireWallů na strukturovanou kabeláží vedenou v měrných jímkách zapuštěných v každém racku budou zakončeny v R.MON-NrNN. Monitoring motorgenerátorů: řídící systém bude zakončena v modulu",
|
||||
"ramien mu zrejme vôbec niekto je už presne čo mám tendenciu prispôsobiť dych jej páčil, čo chce. Hmm... Včera sa mi pozdava, len dočkali, ale keďže som na uz boli u jej nezavrela. Hlava jej to ve městě nepotká, hodně mi to tí vedci pri hre, keď je tu pre Designiu. Pokiaľ viete o odbornejšie texty. Prvým z tmavých uličiek, každý to niekedy, zrovnávať krok s obrovským batohom na okraj vane a temné úmysly, tak rozmýšľam, aký som si hromady mailov, čo chcem a neraz sa pokúšal o filmovém klubu v budúcnosti rozhodne uniesť mladú maliarku (Linda Rybová), ktorú so",
|
||||
" 復讐者」. 復讐者」. 伯母さん 復讐者」. 復讐者」. 復讐者」. 復讐者」. 第九章 第五章 第六章 第七章 第八章. 復讐者」 伯母さん. 復讐者」 伯母さん. 第十一章 第十九章 第十四章 第十八章 第十三章 第十五章. 復讐者」 . 第十四章 第十一章 第十二章 第十五章 第十七章 手配書. 第十四章 手配書 第十八章 第十七章 第十六章 第十三章. 第十一章 第十三章 第十八章 第十四章 手配書. 復讐者」."
|
||||
];
|
||||
|
||||
texts.forEach(function (t, i) {
|
||||
var doc = c.document("text" + i);
|
||||
|
||||
assertEqual(t, doc.value);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes the test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
jsunity.run(dumpTestSuite);
|
||||
|
||||
return jsunity.done();
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/*jshint globalstrict:false, strict:false */
|
||||
/*global fail, assertEqual */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2017 ArangoDB GmbH, Cologne, Germany
|
||||
/// Copyright 2010-2017 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 Max Neunhoeffer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var jsunity = require("jsunity");
|
||||
var arangodb = require("@arangodb");
|
||||
var errors = require("internal").errors;
|
||||
|
||||
var db = arangodb.db;
|
||||
|
||||
function DistributeShardsLikeSuite() {
|
||||
'use strict';
|
||||
var cn1 = "UnitTestsDistributeShardsLike1";
|
||||
var cn2 = "UnitTestsDistributeShardsLike2";
|
||||
var cn3 = "UnitTestsDistributeShardsLike3";
|
||||
|
||||
return {
|
||||
setUp: function() {
|
||||
db._drop(cn2);
|
||||
db._drop(cn3);
|
||||
db._drop(cn1);
|
||||
},
|
||||
|
||||
tearDown: function() {
|
||||
db._drop(cn2);
|
||||
db._drop(cn3);
|
||||
db._drop(cn1);
|
||||
},
|
||||
|
||||
testPointToEmpty: function() {
|
||||
try {
|
||||
db._create(cn1, {numberOfShards: 2, distributeShardsLike: cn2});
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
require("internal").print("FUXX:", JSON.stringify(err));
|
||||
assertEqual(errors.ERROR_CLUSTER_UNKNOWN_DISTRIBUTESHARDSLIKE.code,
|
||||
err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
testAvoidChain: function() {
|
||||
db._create(cn1, {numberOfShards: 2});
|
||||
db._create(cn2, {numberOfShards: 2, distributeShardsLike: cn1});
|
||||
try {
|
||||
db._create(cn3, {numberOfShards: 2, distributeShardsLike: cn2});
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(errors.ERROR_CLUSTER_CHAIN_OF_DISTRIBUTESHARDSLIKE.code,
|
||||
err.errorNum);
|
||||
}
|
||||
},
|
||||
|
||||
testPreventDrop: function() {
|
||||
db._create(cn1, {numberOfShards: 2});
|
||||
db._create(cn2, {numberOfShards: 2, distributeShardsLike: cn1});
|
||||
db._create(cn3, {numberOfShards: 2, distributeShardsLike: cn1});
|
||||
try {
|
||||
db._drop(cn1);
|
||||
fail();
|
||||
}
|
||||
catch (err) {
|
||||
assertEqual(errors.ERROR_CLUSTER_MUST_NOT_DROP_COLL_OTHER_DISTRIBUTESHARDSLIKE.code,
|
||||
err.errorNum);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
jsunity.run(DistributeShardsLikeSuite);
|
||||
return jsunity.done();
|
||||
|
|
@ -92,11 +92,11 @@ static inline TRI_socket_t TRI_accept(TRI_socket_t s, struct sockaddr* address,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline int TRI_bind(TRI_socket_t s, const struct sockaddr* address,
|
||||
int addr_len) {
|
||||
size_t addr_len) {
|
||||
#ifdef _WIN32
|
||||
return bind(s.fileHandle, address, addr_len);
|
||||
#else
|
||||
return bind(s.fileDescriptor, address, addr_len);
|
||||
return bind(s.fileDescriptor, address, (socklen_t)addr_len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ TRI_socket_t EndpointIp::connectSocket(const struct addrinfo* aip,
|
|||
#endif
|
||||
|
||||
// server needs to bind to socket
|
||||
int result = TRI_bind(listenSocket, aip->ai_addr, (int)aip->ai_addrlen);
|
||||
int result = TRI_bind(listenSocket, aip->ai_addr, aip->ai_addrlen);
|
||||
|
||||
if (result != 0) {
|
||||
pErr = STR_ERROR();
|
||||
|
|
|
@ -69,7 +69,7 @@ TRI_socket_t EndpointUnixDomain::connect(double connectTimeout,
|
|||
|
||||
if (_type == EndpointType::SERVER) {
|
||||
int result =
|
||||
TRI_bind(listenSocket, (struct sockaddr*)&address, SUN_LEN(&address));
|
||||
TRI_bind(listenSocket, (struct sockaddr*)&address, (int) SUN_LEN(&address));
|
||||
if (result != 0) {
|
||||
// bind error
|
||||
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "bind() failed with " << errno << " (" << strerror(errno)
|
||||
|
|
|
@ -543,7 +543,6 @@ bool SslClientConnection::writeClientConnection(void const* buffer,
|
|||
return false;
|
||||
}
|
||||
|
||||
int errorDetail;
|
||||
int written = SSL_write(_ssl, buffer, (int)length);
|
||||
int err = SSL_get_error(_ssl, written);
|
||||
switch (err) {
|
||||
|
@ -569,16 +568,16 @@ bool SslClientConnection::writeClientConnection(void const* buffer,
|
|||
break;
|
||||
}
|
||||
|
||||
case SSL_ERROR_SSL:
|
||||
case SSL_ERROR_SSL:{
|
||||
/* A failure in the SSL library occurred, usually a protocol error.
|
||||
The OpenSSL error queue contains more information on the error. */
|
||||
errorDetail = ERR_get_error();
|
||||
unsigned long errorDetail = ERR_get_error();
|
||||
char errorBuffer[256];
|
||||
ERR_error_string_n(errorDetail, errorBuffer, sizeof(errorBuffer));
|
||||
_errorDetails = std::string("SSL: while writing: ") + errorBuffer;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
/* a true error */
|
||||
_errorDetails =
|
||||
|
|
Loading…
Reference in New Issue