1
0
Fork 0

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

This commit is contained in:
jsteemann 2016-06-07 17:26:46 +02:00
commit 9a83aaaca0
5 changed files with 408 additions and 1897 deletions

View File

@ -363,7 +363,7 @@ void Agent::run() {
while (!this->isStopping() && size() > 1) { // need only to run in multi-host
if (leading())
_appendCV.wait(500000); // Only if leading
_appendCV.wait(25000); // Only if leading
else
_appendCV.wait(); // Just sit there doing nothing

View File

@ -1106,3 +1106,196 @@ actions.defineHttp({
}
});
////////////////////////////////////////////////////////////////////////////////
/// @start Docu Block JSF_postCleanOutServer
/// (intentionally not in manual)
/// @brief triggers activities to clean out a DBServer
///
/// @ RESTHEADER{POST /_admin/cluster/cleanOutServer, Trigger activities to clean out a DBServers.}
///
/// @ RESTQUERYPARAMETERS
///
/// @ RESTDESCRIPTION Triggers activities to clean out a DBServer.
/// The body must be a JSON object with attribute "server" that is a string
/// with the ID of the server to be cleaned out.
///
/// @ RESTRETURNCODES
///
/// @ RESTRETURNCODE{202} is returned when everything went well and the
/// job is scheduled.
///
/// @ RESTRETURNCODE{400} body is not valid JSON.
///
/// @ RESTRETURNCODE{403} server is not a coordinator or method was not POST.
///
/// @ RESTRETURNCODE{503} the agency operation did not work.
///
/// @end Docu Block
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: "_admin/cluster/cleanOutServer",
allowUseDatabase: true,
prefix: false,
callback: function (req, res) {
if (!require("@arangodb/cluster").isCoordinator()) {
actions.resultError(req, res, actions.HTTP_FORBIDDEN, 0,
"only coordinators can serve this request");
return;
}
if (req.requestType !== actions.POST) {
actions.resultError(req, res, actions.HTTP_FORBIDDEN, 0,
"only the POST method is allowed");
return;
}
var timeout = 60.0;
// Now get to work:
var body = actions.getJsonBody(req, res);
if (body === undefined) {
return;
}
if (typeof body !== "object" ||
! body.hasOwnProperty("server") ||
typeof body.server !== "string") {
actions.resultError(req, res, actions.HTTP_BAD,
"body must be an object with a string attribute 'server'");
return;
}
var ok = true;
try {
var id = ArangoClusterInfo.uniqid();
var todo = { "type": "cleanOutServer",
"server": body.server,
"jobId": id,
"timeCreated": (new Date()).toISOString(),
"creator": ArangoServerState.id() };
ArangoAgency.set("Target/ToDo/" + id, todo);
}
catch (e1) {
ok = false;
}
if (!ok) {
actions.resultError(req, res, actions.HTTP_SERVICE_UNAVAILABLE,
"Cannot write to agency.");
return;
}
actions.resultOk(req, res, actions.HTTP_ACCEPTED, true);
}
});
////////////////////////////////////////////////////////////////////////////////
/// @start Docu Block JSF_postMoveShard
/// (intentionally not in manual)
/// @brief triggers activities to move a shard
///
/// @ RESTHEADER{POST /_admin/cluster/moveShard, Trigger activities to move a shard.}
///
/// @ RESTQUERYPARAMETERS
///
/// @ RESTDESCRIPTION Triggers activities to move a shard.
/// The body must be a JSON document with the following attributes:
/// - `"database"`: a string with the name of the database
/// - `"collection"`: a string with the name of the collection
/// - `"shard"`: a string with the name of the shard to move
/// - `"fromServer"`: a string with the ID of a server that is currently
/// the leader or a follower for this shard
/// - `"toServer"`: a string with the ID of a server that is currently
/// not the leader and not a follower for this shard
///
/// @ RESTRETURNCODES
///
/// @ RESTRETURNCODE{202} is returned when everything went well and the
/// job is scheduled.
///
/// @ RESTRETURNCODE{400} body is not valid JSON.
///
/// @ RESTRETURNCODE{403} server is not a coordinator or method was not POST.
///
/// @ RESTRETURNCODE{503} the agency operation did not work.
///
/// @end Docu Block
////////////////////////////////////////////////////////////////////////////////
actions.defineHttp({
url: "_admin/cluster/moveShard",
allowUseDatabase: true,
prefix: false,
callback: function (req, res) {
if (!require("@arangodb/cluster").isCoordinator()) {
actions.resultError(req, res, actions.HTTP_FORBIDDEN, 0,
"only coordinators can serve this request");
return;
}
if (req.requestType !== actions.POST) {
actions.resultError(req, res, actions.HTTP_FORBIDDEN, 0,
"only the POST method is allowed");
return;
}
var timeout = 60.0;
// Now get to work:
var body = actions.getJsonBody(req, res);
if (body === undefined) {
return;
}
if (typeof body !== "object" ||
! body.hasOwnProperty("database") ||
typeof body.database !== "string" ||
! body.hasOwnProperty("collection") ||
typeof body.collection !== "string" ||
! body.hasOwnProperty("shard") ||
typeof body.shard !== "string" ||
! body.hasOwnProperty("fromServer") ||
typeof body.fromServer !== "string" ||
! body.hasOwnProperty("toServer") ||
typeof body.toServer !== "string") {
actions.resultError(req, res, actions.HTTP_BAD,
"body must be an object with string attributes 'database', 'collection', 'shard', 'fromServer' and 'toServer'");
return;
}
var ok = true;
var isLeader;
try {
var coll = ArangoClusterInfo.getCollectionInfo(body.database,
body.collection);
var shards = coll.shards;
var shard = shards[body.shard];
var pos = shard.indexOf(body.fromServer);
if (pos === -1) {
throw "Banana";
} else if (pos === 0) {
isLeader = true;
} else {
isLeader = false;
}
} catch (e2) {
actions.resultError(req, res, actions.HTTP_BAD,
"Combination of database, collection, shard and fromServer does not make sense.");
return;
}
try {
var id = ArangoClusterInfo.uniqid();
var todo = { "type": "moveShard",
"database": body.database,
"collection": body.collection,
"shard": body.shard,
"fromServer": body.fromServer,
"toServer": body.toServer,
"jobId": id,
"timeCreated": (new Date()).toISOString(),
"creator": ArangoServerState.id() };
ArangoAgency.set("Target/ToDo/" + id, todo);
} catch (e1) {
actions.resultError(req, res, actions.HTTP_SERVICE_UNAVAILABLE,
"Cannot write to agency.");
return;
}
actions.resultOk(req, res, actions.HTTP_ACCEPTED, true);
}
});

View File

@ -42,8 +42,8 @@ function agencyTestSuite () {
/// @brief the agency servers
////////////////////////////////////////////////////////////////////////////////
var agencyServers = ARGUMENTS;
var whoseTurn = 0; // used to do round robin on agencyServers
var agencyServers = ARGUMENTS[0].split(" ");
var whoseTurn = 0;
var request = require("@arangodb/request");
@ -53,6 +53,7 @@ function agencyTestSuite () {
var res = request({url: agencyServers[whoseTurn] + "/_api/agency/read", method: "POST",
followRedirects: true, body: JSON.stringify(list),
headers: {"Content-Type": "application/json"}});
res.bodyParsed = JSON.parse(res.body);
return res;
}
@ -62,8 +63,10 @@ function agencyTestSuite () {
// response:
var res = request({url: agencyServers[whoseTurn] + "/_api/agency/write", method: "POST",
followRedirects: true, body: JSON.stringify(list),
headers: {"Content-Type": "application/json"}});
headers: {"Content-Type": "application/json",
"x-arangodb-agency-mode": "waitForCommitted"}});
res.bodyParsed = JSON.parse(res.body);
wait(.1);
return res;
}
@ -100,7 +103,7 @@ function agencyTestSuite () {
////////////////////////////////////////////////////////////////////////////////
testSingleTopLevel : function () {
wait(10);
wait(1);
assertEqual(readAndCheck([["/x"]]), [{}]);
writeAndCheck([[{x:12}]]);
assertEqual(readAndCheck([["/x"]]), [{x:12}]);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff