1
0
Fork 0

fixed shard ordering in Job::clones with consequences for unit tests

This commit is contained in:
Kaveh Vahedipour 2017-04-27 13:37:47 +02:00
parent 1109c7b54e
commit e7797d292e
14 changed files with 122 additions and 99 deletions

View File

@ -22,9 +22,10 @@
////////////////////////////////////////////////////////////////////////////////
#include "Job.h"
#include "Random/RandomGenerator.h"
#include <numeric>
static std::string const DBServer = "DBServer";
using namespace arangodb::consensus;
@ -236,6 +237,38 @@ std::vector<std::string> Job::availableServers(Node const& snapshot) {
}
template<typename T> std::vector<size_t> idxsort (const std::vector<T> &v) {
std::vector<size_t> idx(v.size());
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(),
[&v](size_t i, size_t j) {return v[i] < v[j];});
return idx;
}
std::vector<std::string> sortedShardList(Node const& shards) {
std::vector<size_t> sids;
auto const& shardMap = shards.children();
for (const auto& shard : shardMap) {
sids.push_back(std::stoul(shard.first.substr(1)));
}
std::vector<size_t> idx(idxsort(sids));
std::vector<std::string> sorted;
for (const auto& i : idx) {
auto x = shardMap.begin();
std::advance(x,i);
sorted.push_back(x->first);
}
return sorted;
}
std::vector<Job::shard_t> Job::clones(
Node const& snapshot, std::string const& database,
std::string const& collection, std::string const& shard) {
@ -244,34 +277,24 @@ std::vector<Job::shard_t> Job::clones(
ret.emplace_back(collection, shard); // add (collection, shard) as first item
//typedef std::unordered_map<std::string, std::shared_ptr<Node>> UChildren;
try {
std::string databasePath = planColPrefix + database,
planPath = databasePath + "/" + collection + "/shards";
auto myshards = snapshot(planPath).children();
auto steps = std::distance(myshards.begin(), myshards.find(shard));
for (const auto& colptr : snapshot(databasePath).children()) { // collections
auto const col = *colptr.second;
auto const otherCollection = colptr.first;
try {
std::string const& prototype =
col("distributeShardsLike").slice().copyString();
if (otherCollection != collection && prototype == collection) {
auto othershards = col("shards").children();
auto opos = othershards.begin();
std::advance(opos, steps);
auto const& otherShard = opos->first;
ret.emplace_back(otherCollection, otherShard);
}
} catch(...) {}
std::string databasePath = planColPrefix + database,
planPath = databasePath + "/" + collection + "/shards";
auto myshards = sortedShardList(snapshot(planPath));
auto steps = std::distance(
myshards.begin(), std::find(myshards.begin(), myshards.end(), shard));
for (const auto& colptr : snapshot(databasePath).children()) { // collections
auto const col = *colptr.second;
auto const otherCollection = colptr.first;
if (otherCollection != collection &&
col.has("distributeShardsLike") &&
col("distributeShardsLike").slice().copyString() == collection) {
ret.emplace_back(otherCollection, sortedShardList(col("shards"))[steps]);
}
} catch (...) {
ret.clear();
ret.emplace_back(collection, shard);
}
return ret;

View File

@ -51,7 +51,7 @@ namespace add_follower_test {
const std::string PREFIX = "arango";
const std::string DATABASE = "database";
const std::string COLLECTION = "collection";
const std::string SHARD = "shard";
const std::string SHARD = "s99";
const std::string SHARD_LEADER = "leader";
const std::string SHARD_FOLLOWER1 = "follower1";
const std::string SHARD_FOLLOWER2 = "follower2";

View File

@ -5,7 +5,7 @@ R"=(
"Collections": {
"database": {
"collection": {
"shard": {
"s99": {
"servers": [
"leader",
"follower1"
@ -21,7 +21,7 @@ R"=(
"collection": {
"replicationFactor" : 3,
"shards": {
"shard": [
"s99": [
"leader",
"follower1"
]

View File

@ -4,7 +4,7 @@ R"=(
"type" : "addFollower",
"database" : "database",
"collection" : "collection",
"shard" : "shard",
"shard" : "s99",
"jobId" : "1" ,
"timeCreated" : "2017-01-01 00:00:00"
}

View File

@ -67,7 +67,7 @@ VPackBuilder createMoveShardJob() {
builder.add("toServer", VPackValue("test2"));
builder.add("isLeader", VPackValue(true));
builder.add("collection", VPackValue("test"));
builder.add("shard", VPackValue("test"));
builder.add("shard", VPackValue("s99"));
builder.add("creator", VPackValue("unittest"));
builder.add("jobId", VPackValue(JOBID + "-0"));
builder.add("database", VPackValue("test"));
@ -377,7 +377,7 @@ SECTION("cleanout server should fail if the server is failed") {
if (path == "/arango/Target/ToDo") {
builder->add(JOBID, createJob(SERVER).slice());
} else if (path == "/arango/Target/FailedServers") {
builder->add(SERVER, VPackValue("shard"));
builder->add(SERVER, VPackValue("s99"));
}
builder->close();
} else {
@ -424,9 +424,9 @@ SECTION("cleanout server should fail if the replicationFactor is too big for any
if (path == "/arango/Target/ToDo") {
builder->add(JOBID, createJob(SERVER).slice());
} else if (path == "/arango/Target/FailedServers") {
builder->add("follower1", VPackValue("shard"));
builder->add("follower2", VPackValue("shard"));
builder->add("free", VPackValue("shard"));
builder->add("follower1", VPackValue("s99"));
builder->add("follower2", VPackValue("s99"));
builder->add("free", VPackValue("s99"));
}
builder->close();
} else {
@ -863,4 +863,4 @@ SECTION("when the cleanout server job is aborted all subjobs should be aborted t
}
}
}
}
}

View File

@ -52,7 +52,7 @@ namespace failed_follower_test {
const std::string PREFIX = "arango";
const std::string DATABASE = "database";
const std::string COLLECTION = "collection";
const std::string SHARD = "shard";
const std::string SHARD = "s99";
const std::string SHARD_LEADER = "leader";
const std::string SHARD_FOLLOWER1 = "follower1";
const std::string SHARD_FOLLOWER2 = "follower2";
@ -72,10 +72,10 @@ VPackBuilder createJob() {
{
builder.add("creator", VPackValue("1"));
builder.add("type", VPackValue("failedFollower"));
builder.add("database", VPackValue("database"));
builder.add("collection", VPackValue("collection"));
builder.add("shard", VPackValue("shard"));
builder.add("fromServer", VPackValue("follower1"));
builder.add("database", VPackValue(DATABASE));
builder.add("collection", VPackValue(COLLECTION));
builder.add("shard", VPackValue(SHARD));
builder.add("fromServer", VPackValue(SHARD_FOLLOWER1));
builder.add("jobId", VPackValue("1"));
builder.add("timeCreated", VPackValue(
timepointToString(std::chrono::system_clock::now())));
@ -555,7 +555,7 @@ SECTION("a successfully started job should finish immediately and set everything
REQUIRE(preconditions.get("/arango/Plan/Collections/" + DATABASE + "/" + COLLECTION + "/shards/" + SHARD).get("old")[1].copyString() == "follower1");
REQUIRE(preconditions.get("/arango/Plan/Collections/" + DATABASE + "/" + COLLECTION + "/shards/" + SHARD).get("old")[2].copyString() == "follower2");
REQUIRE(preconditions.get("/arango/Supervision/DBServers/free").get("oldEmpty").getBool() == true);
REQUIRE(preconditions.get("/arango/Supervision/Shards/shard").get("oldEmpty").getBool() == true);
REQUIRE(preconditions.get("/arango/Supervision/Shards/s99").get("oldEmpty").getBool() == true);
return fakeTransResult;
});
@ -586,18 +586,18 @@ SECTION("the job should handle distributeShardsLike") {
if (path == "/arango/Current/Collections/" + DATABASE) {
// we fake that follower2 is in sync
char const* json1 =
R"=({"linkedshard1":{"servers":["leader","follower2"]}})=";
R"=({"s100":{"servers":["leader","follower2"]}})=";
builder->add("linkedcollection1", createBuilder(json1).slice());
// for the other shard there is only follower1 in sync
char const* json2 =
R"=({"linkedshard2":{"servers":["leader","follower1"]}})=";
R"=({"s101":{"servers":["leader","follower1"]}})=";
builder->add("linkedcollection2", createBuilder(json2).slice());
} else if (path == "/arango/Plan/Collections/" + DATABASE) {
char const* json1 = R"=({"distributeShardsLike":"collection","shards":
{"linkedshard1":["leader","follower1","follower2"]}})=";
{"s100":["leader","follower1","follower2"]}})=";
builder->add("linkedcollection1", createBuilder(json1).slice());
char const* json2 = R"=({"distributeShardsLike":"collection","shards":
{"linkedshard2":["leader","follower1","follower2"]}})=";
{"s101":["leader","follower1","follower2"]}})=";
builder->add("linkedcollection2", createBuilder(json2).slice());
} else if (path == "/arango/Target/ToDo") {
builder->add("1", createJob().slice());
@ -631,16 +631,16 @@ SECTION("the job should handle distributeShardsLike") {
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/" + COLLECTION + "/shards/" + SHARD)[0].copyString() == "leader");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/" + COLLECTION + "/shards/" + SHARD)[1].copyString() == "free");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/" + COLLECTION + "/shards/" + SHARD)[2].copyString() == "follower2");
REQUIRE(std::string(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/linkedshard1").typeName()) == "array");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/linkedshard1").length() == 3);
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/linkedshard1")[0].copyString() == "leader");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/linkedshard1")[1].copyString() == "free");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/linkedshard1")[2].copyString() == "follower2");
REQUIRE(std::string(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/linkedshard2").typeName()) == "array");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/linkedshard2").length() == 3);
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/linkedshard2")[0].copyString() == "leader");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/linkedshard2")[1].copyString() == "free");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/linkedshard2")[2].copyString() == "follower2");
REQUIRE(std::string(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/s100").typeName()) == "array");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/s100").length() == 3);
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/s100")[0].copyString() == "leader");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/s100")[1].copyString() == "free");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/s100")[2].copyString() == "follower2");
REQUIRE(std::string(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/s101").typeName()) == "array");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/s101").length() == 3);
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/s101")[0].copyString() == "leader");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/s101")[1].copyString() == "free");
REQUIRE(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/s101")[2].copyString() == "follower2");
REQUIRE(writes.get("/arango/Plan/Version").get("op").copyString() == "increment");
REQUIRE(std::string(writes.get("/arango/Target/Finished/1").typeName()) == "object");
@ -653,7 +653,7 @@ SECTION("the job should handle distributeShardsLike") {
REQUIRE(preconditions.get("/arango/Plan/Collections/" + DATABASE + "/" + COLLECTION + "/shards/" + SHARD).get("old")[1].copyString() == "follower1");
REQUIRE(preconditions.get("/arango/Plan/Collections/" + DATABASE + "/" + COLLECTION + "/shards/" + SHARD).get("old")[2].copyString() == "follower2");
REQUIRE(preconditions.get("/arango/Supervision/DBServers/free").get("oldEmpty").getBool() == true);
REQUIRE(preconditions.get("/arango/Supervision/Shards/shard").get("oldEmpty").getBool() == true);
REQUIRE(preconditions.get("/arango/Supervision/Shards/s99").get("oldEmpty").getBool() == true);
return fakeTransResult;
});

View File

@ -5,7 +5,7 @@ R"=(
"Collections": {
"database": {
"collection": {
"shard": {
"s99": {
"servers": [
"leader",
"follower1",
@ -21,7 +21,7 @@ R"=(
"database": {
"collection": {
"shards": {
"shard": [
"s99": [
"leader",
"follower1",
"follower2"

View File

@ -52,7 +52,7 @@ namespace failed_leader_test {
const std::string PREFIX = "arango";
const std::string DATABASE = "database";
const std::string COLLECTION = "collection";
const std::string SHARD = "shard";
const std::string SHARD = "s99";
const std::string SHARD_LEADER = "leader";
const std::string SHARD_FOLLOWER1 = "follower1";
const std::string SHARD_FOLLOWER2 = "follower2";
@ -98,7 +98,7 @@ Node createRootNode() {
char const* todo = R"=({
"creator":"1", "type":"failedLeader", "database":"database",
"collection":"collection", "shard":"shard", "fromServer":"leader",
"collection":"collection", "shard":"s99", "fromServer":"leader",
"jobId":"1", "timeCreated":"2017-01-01 00:00:00"
})=";
@ -402,18 +402,18 @@ SECTION("the job must not be started if there if one of the linked shards (distr
if (path == "/arango/Current/Collections/" + DATABASE) {
// we fake that follower2 is in sync
char const* json1 =
R"=({"linkedshard1":{"servers":["leader","follower2"]}})=";
R"=({"s100":{"servers":["leader","follower2"]}})=";
builder->add("linkedcollection1", createBuilder(json1).slice());
// for the other shard there is only follower1 in sync
char const* json2 =
R"=({"linkedshard2":{"servers":["leader","follower1"]}})=";
R"=({"s101":{"servers":["leader","follower1"]}})=";
builder->add("linkedcollection2", createBuilder(json2).slice());
} else if (path == "/arango/Plan/Collections/" + DATABASE) {
char const* json1 = R"=({"distributeShardsLike":"collection","shards":
{"linkedshard1":["leader","follower1","follower2"]}})=";
{"s100":["leader","follower1","follower2"]}})=";
builder->add("linkedcollection1", createBuilder(json1).slice());
char const* json2 = R"=({"distributeShardsLike":"collection","shards":
{"linkedshard2":["leader","follower1","follower2"]}})=";
{"s101":["leader","follower1","follower2"]}})=";
builder->add("linkedcollection2", createBuilder(json2).slice());
} else if (path == "/arango/Target/ToDo") {
builder->add("1", createBuilder(todo).slice());

View File

@ -5,7 +5,7 @@ R"=(
"Collections": {
"database": {
"collection": {
"shard": {
"s99": {
"servers": [
"leader",
"follower1",
@ -21,7 +21,7 @@ R"=(
"database": {
"collection": {
"shards": {
"shard": [
"s99": [
"leader",
"follower1",
"follower2"

View File

@ -43,7 +43,7 @@ using namespace fakeit;
const std::string PREFIX = "arango";
const std::string DATABASE = "database";
const std::string COLLECTION = "collection";
const std::string SHARD = "shard";
const std::string SHARD = "s99";
const std::string SHARD_LEADER = "leader";
const std::string SHARD_FOLLOWER1 = "follower1";
const std::string FREE_SERVER = "free";
@ -751,7 +751,7 @@ SECTION("when moving a shard that is a distributeShardsLike leader move the rest
builder->add(VPackValue("linkedcollection1"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("linkedshard1"));
builder->add(VPackValue("s100"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("servers"));
@ -766,7 +766,7 @@ SECTION("when moving a shard that is a distributeShardsLike leader move the rest
builder->add(VPackValue("linkedcollection2"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("linkedshard2"));
builder->add(VPackValue("s101"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("servers"));
@ -785,7 +785,7 @@ SECTION("when moving a shard that is a distributeShardsLike leader move the rest
builder->add(VPackValue("shards"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("linkedshard1"));
builder->add(VPackValue("s100"));
{
VPackArrayBuilder g(builder.get());
builder->add(VPackValue(SHARD_LEADER));
@ -800,7 +800,7 @@ SECTION("when moving a shard that is a distributeShardsLike leader move the rest
builder->add(VPackValue("shards"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("linkedshard2"));
builder->add(VPackValue("s101"));
{
VPackArrayBuilder g(builder.get());
builder->add(VPackValue(SHARD_LEADER));
@ -837,8 +837,8 @@ SECTION("when moving a shard that is a distributeShardsLike leader move the rest
CHECK(writes.get("/arango/Plan/Collections/" + DATABASE + "/" + COLLECTION + "/shards/" + SHARD).length() == 3); // leader, oldFollower, newLeader
auto json = writes.get("/arango/Plan/Collections/" + DATABASE + "/" + COLLECTION + "/shards/" + SHARD).toJson();
CHECK(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/linkedshard1").toJson() == json);
CHECK(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/linkedshard2").toJson() == json);
CHECK(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/s100").toJson() == json);
CHECK(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/s101").toJson() == json);
CHECK(writes.get("/arango/Plan/Collections/" + DATABASE + "/unrelatedcollection/shards/unrelatedshard").isNone());
CHECK(writes.get("/arango/Supervision/Shards/" + SHARD).copyString() == "1");
CHECK(writes.get("/arango/Supervision/Shards/unrelatedshard").isNone());
@ -1226,7 +1226,7 @@ SECTION("the job should not finish itself when only parts of distributeShardsLik
builder->add(VPackValue("linkedcollection1"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("linkedshard1"));
builder->add(VPackValue("s100"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("servers"));
@ -1242,7 +1242,7 @@ SECTION("the job should not finish itself when only parts of distributeShardsLik
builder->add(VPackValue("linkedcollection2"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("linkedshard2"));
builder->add(VPackValue("s101"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("servers"));
@ -1261,7 +1261,7 @@ SECTION("the job should not finish itself when only parts of distributeShardsLik
builder->add(VPackValue("shards"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("linkedshard1"));
builder->add(VPackValue("s100"));
{
VPackArrayBuilder g(builder.get());
builder->add(VPackValue(SHARD_LEADER));
@ -1277,7 +1277,7 @@ SECTION("the job should not finish itself when only parts of distributeShardsLik
builder->add(VPackValue("shards"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("linkedshard2"));
builder->add(VPackValue("s101"));
{
VPackArrayBuilder g(builder.get());
builder->add(VPackValue(SHARD_LEADER));
@ -1365,7 +1365,7 @@ SECTION("the job should finish when all distributeShardsLike shards have adapted
builder->add(VPackValue("linkedcollection1"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("linkedshard1"));
builder->add(VPackValue("s100"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("servers"));
@ -1381,7 +1381,7 @@ SECTION("the job should finish when all distributeShardsLike shards have adapted
builder->add(VPackValue("linkedcollection2"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("linkedshard2"));
builder->add(VPackValue("s101"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("servers"));
@ -1416,7 +1416,7 @@ SECTION("the job should finish when all distributeShardsLike shards have adapted
builder->add(VPackValue("shards"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("linkedshard1"));
builder->add(VPackValue("s100"));
{
VPackArrayBuilder g(builder.get());
builder->add(VPackValue(SHARD_LEADER));
@ -1432,7 +1432,7 @@ SECTION("the job should finish when all distributeShardsLike shards have adapted
builder->add(VPackValue("shards"));
{
VPackObjectBuilder f(builder.get());
builder->add(VPackValue("linkedshard2"));
builder->add(VPackValue("s101"));
{
VPackArrayBuilder g(builder.get());
builder->add(VPackValue(SHARD_LEADER));
@ -1475,15 +1475,15 @@ SECTION("the job should finish when all distributeShardsLike shards have adapted
CHECK(writes.get("/arango/Target/Pending/1").get("op").copyString() == "delete");
CHECK(std::string(writes.get("/arango/Target/Finished/1").typeName()) == "object");
CHECK(writes.get("/arango/Plan/Collections/" + DATABASE + "/" + COLLECTION + "/shards/" + SHARD).toJson() == "[\"leader\",\"free\"]");
CHECK(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/linkedshard1").toJson() == "[\"leader\",\"free\"]");
CHECK(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/linkedshard2").toJson() == "[\"leader\",\"free\"]");
CHECK(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/s100").toJson() == "[\"leader\",\"free\"]");
CHECK(writes.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/s101").toJson() == "[\"leader\",\"free\"]");
CHECK(writes.get("/arango/Plan/Collections/" + DATABASE + "/unrelatedcollection/shards/unrelatedshard").isNone());
CHECK(writes.get("/arango/Supervision/Shards/linkedshard1").isNone());
CHECK(writes.get("/arango/Supervision/Shards/s100").isNone());
auto preconditions = q->slice()[0][1];
CHECK(preconditions.get("/arango/Plan/Collections/" + DATABASE + "/" + COLLECTION + "/shards/" + SHARD).get("old").length() == 3);
CHECK(preconditions.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/linkedshard1").get("old").length() == 3);
CHECK(preconditions.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/linkedshard2").get("old").length() == 3);
CHECK(preconditions.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection1/shards/s100").get("old").length() == 3);
CHECK(preconditions.get("/arango/Plan/Collections/" + DATABASE + "/linkedcollection2/shards/s101").get("old").length() == 3);
CHECK(preconditions.get("/arango/Plan/Collections/" + DATABASE + "/unrelatedcollection/shards/unrelatedshard").isNone());
return fakeWriteResult;

View File

@ -5,7 +5,7 @@ R"=(
"Collections": {
"database": {
"collection": {
"shard": {
"s99": {
"servers": [
"leader",
"follower1"
@ -20,7 +20,7 @@ R"=(
"database": {
"collection": {
"shards": {
"shard": [
"s99": [
"leader",
"follower1"
]

View File

@ -52,7 +52,7 @@ const std::string PREFIX = "arango";
const std::string DATABASE = "database";
const std::string COLLECTION = "collection1";
const std::string CLONE = "collection2";
const std::string SHARD = "shard1";
const std::string SHARD = "s1";
const std::string SHARD_LEADER = "leader";
const std::string SHARD_FOLLOWER1 = "follower1";
const std::string SHARD_FOLLOWER2 = "follower2";

View File

@ -5,17 +5,17 @@ R"=(
"Collections": {
"database": {
"collection1": {
"shard1": {
"s1": {
"servers": ["leader", "follower1", "follower2"]
}
},
"collection2": {
"shard2": {
"s2": {
"servers": ["leader"]
}
},
"collection3": {
"shard3": {
"s3": {
"servers": ["leader", "follower1"]
}
}
@ -28,19 +28,19 @@ R"=(
"collection1": {
"replicationFactor" : 2,
"shards": {
"shard1": ["leader", "follower1", "follower2"]
"s1": ["leader", "follower1", "follower2"]
}
},
"collection2": {
"replicationFactor" : 2,
"shards": {
"shard2": ["leader", "follower1", "follower2"]
"s2": ["leader", "follower1", "follower2"]
}
},
"collection3": {
"replicationFactor" : 2,
"shards": {
"shard3": ["leader", "follower1", "follower2"]
"s3": ["leader", "follower1", "follower2"]
}
}
}

View File

@ -4,7 +4,7 @@ R"=(
"type" : "removeFollower",
"database" : "database",
"collection" : "collection1",
"shard" : "shard1",
"shard" : "s1",
"jobId" : "1" ,
"timeCreated" : "2017-01-01 00:00:00"
}