diff --git a/js/server/modules/@arangodb/cluster.js b/js/server/modules/@arangodb/cluster.js index 8945553000..ce2c1bcb85 100644 --- a/js/server/modules/@arangodb/cluster.js +++ b/js/server/modules/@arangodb/cluster.js @@ -1,7 +1,7 @@ /* global ArangoServerState, ArangoClusterInfo */ 'use strict'; -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief JavaScript cluster functionality // / // / @file @@ -26,7 +26,7 @@ // / // / @author Jan Steemann // / @author Copyright 2012, triAGENS GmbH, Cologne, Germany -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// var console = require('console'); var arangodb = require('@arangodb'); @@ -133,9 +133,9 @@ function cancelReadLockOnLeader (endpoint, database, lockJobId) { return true; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief cancel barrier from sync -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function cancelBarrier (endpoint, database, barrierId) { if (barrierId <= 0) { @@ -152,9 +152,9 @@ function cancelBarrier (endpoint, database, barrierId) { return true; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief tell leader that we are in sync -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function addShardFollower (endpoint, database, shard) { console.debug('addShardFollower: tell the leader to put us into the follower list...'); @@ -169,9 +169,9 @@ function addShardFollower (endpoint, database, shard) { return true; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief tell leader that we are stop following -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function removeShardFollower (endpoint, database, shard) { console.debug('removeShardFollower: tell the leader to take us off the follower list...'); @@ -186,9 +186,9 @@ function removeShardFollower (endpoint, database, shard) { return true; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief lookup for 4-dimensional nested dictionary data -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function lookup4d (data, a, b, c) { if (!data.hasOwnProperty(a)) { @@ -203,9 +203,9 @@ function lookup4d (data, a, b, c) { return data[a][b][c]; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief return a shardId => server map -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function getShardMap (plannedCollections) { var shardMap = { }; @@ -235,9 +235,9 @@ function getShardMap (plannedCollections) { return shardMap; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief return the indexes of a collection as a map -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function getIndexMap (shard) { var indexes = { }, i; @@ -254,24 +254,28 @@ function getIndexMap (shard) { return indexes; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief return a hash with the local databases -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function getLocalDatabases () { - var result = { }; - var db = require('internal').db; - - db._databases().forEach(function (database) { - result[database] = { name: database }; - }); - + let result = { }; + let db = require('internal').db; + let curDb = db._name(); + try { + db._databases().forEach(function (database) { + db._useDatabase(database); + result[database] = { name: database, id: db._id() }; + }); + } finally { + db._useDatabase(curDb); + } return result; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief return a hash with the local collections -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function getLocalCollections () { var result = { }; @@ -305,9 +309,9 @@ function getLocalCollections () { return result; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief create databases if they exist in the plan but not locally -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function createLocalDatabases (plannedDatabases, currentDatabases) { var ourselves = global.ArangoServerState.id(); @@ -360,9 +364,9 @@ function createLocalDatabases (plannedDatabases, currentDatabases) { } } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief drop databases if they do exist locally but not in the plan -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function dropLocalDatabases (plannedDatabases) { var ourselves = global.ArangoServerState.id(); @@ -415,9 +419,9 @@ function dropLocalDatabases (plannedDatabases) { } } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief clean up what's in Current/Databases for ourselves -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function cleanupCurrentDatabases (currentDatabases) { var ourselves = global.ArangoServerState.id(); @@ -455,9 +459,9 @@ function cleanupCurrentDatabases (currentDatabases) { } } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief handle database changes -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function handleDatabaseChanges (plan, current) { var plannedDatabases = plan.Databases; @@ -468,9 +472,9 @@ function handleDatabaseChanges (plan, current) { cleanupCurrentDatabases(currentDatabases); } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief create collections if they exist in the plan but not locally -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function createLocalCollections (plannedCollections, planVersion, currentCollections, takeOverResponsibility) { @@ -785,9 +789,9 @@ function leaderResign (database, collId, shardName, ourselves) { } } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief drop collections if they exist locally but not in the plan -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function dropLocalCollections (plannedCollections, currentCollections) { var ourselves = global.ArangoServerState.id(); @@ -898,9 +902,9 @@ function dropLocalCollections (plannedCollections, currentCollections) { } } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief clean up what's in Current/Collections for ourselves -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function cleanupCurrentCollections (plannedCollections, currentCollections) { var dropCollectionAgency = function (database, collection, shardID) { @@ -955,9 +959,9 @@ function cleanupCurrentCollections (plannedCollections, currentCollections) { } } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief lock key space -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function lockSyncKeyspace () { while (!global.KEY_SET_CAS('shardSynchronization', 'lock', 1, null)) { @@ -965,17 +969,17 @@ function lockSyncKeyspace () { } } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief unlock key space -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function unlockSyncKeyspace () { global.KEY_SET('shardSynchronization', 'lock', null); } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief launch a scheduled job if needed -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function tryLaunchJob () { const registerTask = require('internal').registerTask; @@ -1033,9 +1037,9 @@ function tryLaunchJob () { } } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief synchronize one shard, this is run as a V8 task -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function synchronizeOneShard (database, shard, planId, leader) { // synchronize this shard from the leader @@ -1183,9 +1187,9 @@ function synchronizeOneShard (database, shard, planId, leader) { database, shard, database, planId); } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief schedule a shard synchronization -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function scheduleOneShardSynchronization (database, shard, planId, leader) { console.debug('scheduleOneShardSynchronization:', database, shard, planId, @@ -1222,10 +1226,10 @@ function scheduleOneShardSynchronization (database, shard, planId, leader) { return true; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief synchronize collections for which we are followers (synchronously // / replicated shards) -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function synchronizeLocalFollowerCollections (plannedCollections, currentCollections) { @@ -1299,9 +1303,9 @@ function synchronizeLocalFollowerCollections (plannedCollections, return true; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief handle collection changes -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function handleCollectionChanges (plan, current, takeOverResponsibility) { var plannedCollections = plan.Collections; @@ -1335,7 +1339,7 @@ function handleCollectionChanges (plan, current, takeOverResponsibility) { function migratePrimary(plan, current) { // will analyze local state and then issue db._create(), // db._drop() etc. to sync plan and local state for shards - let localErrors = executePlanForDatabases(plan); + let localErrors = executePlanForCollections(plan); // will do a diff between plan and current to find out // the shards for which this db server is a planned @@ -1350,9 +1354,139 @@ function migratePrimary(plan, current) { // diff current and local and prepare agency transactions or whatever // to update current. Will report the errors created locally to the agency - updateCurrentForDatabases(localErrors, current); + updateCurrentForCollections(localErrors, current); } +// ///////////////////////////////////////////////////////////////////////////// +// / @brief executePlanForDatabases +// ///////////////////////////////////////////////////////////////////////////// + +function executePlanForDatabases(plan) { + let plannedDatabases = plan.Databases; + let localErrors = {}; + + let db = require('internal').db; + db._useDatabase('_system'); + + let localDatabases = getLocalDatabases(); + let name; + + // check which databases need to be created locally: + for (name in plannedDatabases) { + if (plannedDatabases.hasOwnProperty(name)) { + if (!localDatabases.hasOwnProperty(name)) { + // must create database + + // TODO: handle options and user information + + console.debug("creating local database '%s'", name); + + try { + db._createDatabase(name); + } catch (err) { + localErrors[name] = { error: true, errorNum: err.errorNum, + errorMessage: err.errorMessage, name: name }; + } + } + } + } + + // check which databases need to be deleted locally + localDatabases = getLocalDatabases(); + for (name in localDatabases) { + if (localDatabases.hasOwnProperty(name)) { + if (!plannedDatabases.hasOwnProperty(name) && name.substr(0, 1) !== '_') { + // must drop database + + console.info("dropping local database '%s'", name); + + // Do we have to stop a replication applier first? + if (ArangoServerState.role() === 'SECONDARY') { + try { + db._useDatabase(name); + var rep = require('@arangodb/replication'); + var state = rep.applier.state(); + if (state.state.running === true) { + console.info('stopping replication applier first'); + rep.applier.stop(); + } + } + finally { + db._useDatabase('_system'); + } + } + db._dropDatabase(name); + } + } + } + + return localErrors; +} + +// ///////////////////////////////////////////////////////////////////////////// +// / @brief updateCurrentForDatabases +// ///////////////////////////////////////////////////////////////////////////// + +function updateCurrentForDatabases(localErrors, current) { + let ourselves = global.ArangoServerState.id(); + + function makeAddDatabaseAgencyOperation(payload, trx) { + trx[0][curDatabases + payload.name + '/' + ourselves] = + {op: 'set', new: payload}; + }; + + function makeDropDatabaseAgencyOperation(name, trx) { + trx[0][curDatabases + name + '/' + ourselves] = {'op':'delete'}; + }; + + let db = require('internal').db; + db._useDatabase('_system'); + + let localDatabases = getLocalDatabases(); + let currentDatabases = current.Databases; + let name; + let trx = [{}]; // Here we collect all write operations + + // Add entries that we have but that are not in Current: + for (name in localDatabases) { + if (localDatabases.hasOwnProperty(name) && name.substr(0, 1) !== '_') { + if (!currentDatabases.hasOwnProperty(name) || + !currentDatabases[name].hasOwnProperty(ourselves)) { + console.debug("adding entry in Current for database '%s'", name); + makeAddDatabaseAgencyOperation({error: false, errorNum: 0, name: name, + id: localDatabases[name].id, + errorMessage: ""}, trx); + } + } + } + + // Remove entries from current that no longer exist locally: + for (name in currentDatabases) { + if (currentDatabases.hasOwnProperty(name) && name.substr(0, 1) !== '_') { + if (!localDatabases.hasOwnProperty(name)) { + // we found a database we don't have locally + + if (currentDatabases[name].hasOwnProperty(ourselves)) { + // we are entered for a database that we don't have locally + console.debug("cleaning up entry for unknown database '%s'", name); + makeDropDatabaseAgencyOperation(name, trx); + } + } + } + } + + // Finally, report any errors that might have been produced earlier when + // we were trying to execute the Plan: + for (name in localErrors) { + if (localErrors.hasOwnProperty(name)) { + console.debug("reporting error to Current about database '%s'", name); + makeAddDatabaseAgencyOperation(localErrors[name], trx); + } + } + + return trx; +} + // ///////////////////////////////////////////////////////////////////////////// // / @brief take care of databases on any type of server according to Plan // ///////////////////////////////////////////////////////////////////////////// @@ -1360,10 +1494,22 @@ function migratePrimary(plan, current) { function migrateAnyServer(plan, current) { // will analyze local state and then issue db._createDatabase(), // db._dropDatabase() etc. to sync plan and local state for databases - let localErrors = executePlanForCollections(plan); + let localErrors = executePlanForDatabases(plan); // diff current and local and prepare agency transactions or whatever // to update current. will report the errors created locally to the agency - updateCurrentForCollections(localErrors, current); + let trx = updateCurrentForDatabases(localErrors, current); + if (Object.keys().length !== 0) { + trx[0][curVersion] = {op: 'increment'}; + // TODO: reduce timeout when we can: + try { + let res = global.ArangoAgency.write([trx]); + if (typeof res !== 'object' || res.length !== 1 || res[0] === 0) { + console.error('migrateAnyServer: could not send transaction for Current to agency, result:', res); + } + } catch (err) { + console.error('migrateAnyServer: caught exception when sending transaction for Current to agency:', err); + } + } } // ///////////////////////////////////////////////////////////////////////////// @@ -1408,9 +1554,9 @@ function setupReplication () { return ok; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief role change from secondary to primary -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function secondaryToPrimary () { console.info('Switching role from secondary to primary...'); @@ -1440,49 +1586,49 @@ function secondaryToPrimary () { } } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief role change from primary to secondary -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function primaryToSecondary () { console.info('Switching role from primary to secondary...'); } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief change handling trampoline function -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function handleChanges (plan, current) { + // Note: This is never called with role === 'COORDINATOR' or on a single + // server. var changed = false; var role = ArangoServerState.role(); - if (role === 'PRIMARY' || role === 'SECONDARY') { - // Need to check role change for automatic failover: - var myId = ArangoServerState.id(); - if (role === 'PRIMARY') { - if (!plan.DBServers[myId]) { - // Ooops! We do not seem to be a primary any more! - changed = ArangoServerState.redetermineRole(); + // Need to check role change for automatic failover: + var myId = ArangoServerState.id(); + if (role === 'PRIMARY') { + if (!plan.DBServers[myId]) { + // Ooops! We do not seem to be a primary any more! + changed = ArangoServerState.redetermineRole(); + } + } else { // role === "SECONDARY" + if (plan.DBServers[myId]) { + changed = ArangoServerState.redetermineRole(); + if (!changed) { + // mop: oops...changing role has failed. retry next time. + return false; } - } else { // role === "SECONDARY" - if (plan.DBServers[myId]) { + } else { + var found = null; + var p; + for (p in plan) { + if (plan.hasOwnProperty(p) && plan[p] === myId) { + found = p; + break; + } + } + if (found !== ArangoServerState.idOfPrimary()) { + // Note this includes the case that we are not found at all! changed = ArangoServerState.redetermineRole(); - if (!changed) { - // mop: oops...changing role has failed. retry next time. - return false; - } - } else { - var found = null; - var p; - for (p in plan) { - if (plan.hasOwnProperty(p) && plan[p] === myId) { - found = p; - break; - } - } - if (found !== ArangoServerState.idOfPrimary()) { - // Note this includes the case that we are not found at all! - changed = ArangoServerState.redetermineRole(); - } } } } @@ -1501,7 +1647,7 @@ function handleChanges (plan, current) { // migrateAnyServer(plan, current) // if (role === 'PRIMARY') { // migratePrimary(plan, current); - // } else if (role == 'SECONDARY') { + // } else { // if (role == 'SECONDARY') { // setupReplication(); // } @@ -1519,9 +1665,9 @@ function handleChanges (plan, current) { return success; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief throw an ArangoError -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// var raiseError = function (code, msg) { var err = new ArangoError(); @@ -1531,9 +1677,9 @@ var raiseError = function (code, msg) { throw err; }; -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief retrieve a list of shards for a collection -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// var shardList = function (dbName, collectionName) { let ci = global.ArangoClusterInfo.getCollectionInfo(dbName, collectionName); @@ -1561,9 +1707,9 @@ var shardList = function (dbName, collectionName) { return shards; }; -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief wait for a distributed response -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// var waitForDistributedResponse = function (data, numberOfRequests) { var received = []; @@ -1612,9 +1758,9 @@ var waitForDistributedResponse = function (data, numberOfRequests) { return received; }; -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief whether or not clustering is enabled -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// var isCluster = function () { var role = global.ArangoServerState.role(); @@ -1622,17 +1768,17 @@ var isCluster = function () { return (role !== undefined && role !== 'SINGLE' && role !== 'AGENT'); }; -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief whether or not we are a coordinator -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// var isCoordinator = function () { return global.ArangoServerState.isCoordinator(); }; -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief role -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// var role = function () { var role = global.ArangoServerState.role(); @@ -1643,9 +1789,9 @@ var role = function () { return undefined; }; -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief status -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// var status = function () { if (!isCluster() || !global.ArangoServerState.initialized()) { @@ -1655,9 +1801,9 @@ var status = function () { return global.ArangoServerState.status(); }; -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief isCoordinatorRequest -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// var isCoordinatorRequest = function (req) { if (!req || !req.hasOwnProperty('headers')) { @@ -1667,11 +1813,13 @@ var isCoordinatorRequest = function (req) { return req.headers.hasOwnProperty('x-arango-coordinator'); }; -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief handlePlanChange -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// var handlePlanChange = function (plan, current) { + // This is never called on a coordinator, we still make sure that it + // is not executed on a single server or coordinator, just to be sure: if (!isCluster() || isCoordinator() || !global.ArangoServerState.initialized()) { return true; } @@ -1681,43 +1829,8 @@ var handlePlanChange = function (plan, current) { current: current.Version }; - // //////////////////////////////////////////////////////////////////////////// - // / @brief execute an action under a write-lock - // //////////////////////////////////////////////////////////////////////////// - - function writeLocked (lockInfo, cb, args) { - var timeout = lockInfo.timeout; - if (timeout === undefined) { - timeout = 60; - } - - var ttl = lockInfo.ttl; - if (ttl === undefined) { - ttl = 120; - } - if (require('internal').coverage || require('internal').valgrind) { - ttl *= 10; - timeout *= 10; - } - - global.ArangoAgency.lockWrite(lockInfo.part, ttl, timeout); - - try { - cb.apply(null, args); - global.ArangoAgency.increaseVersion(lockInfo.part + '/Version'); - - let version = global.ArangoAgency.get(lockInfo.part + '/Version'); - versions[lockInfo.part.toLowerCase()] = version.arango[lockInfo.part].Version; - - global.ArangoAgency.unlockWrite(lockInfo.part, timeout); - } catch (err) { - global.ArangoAgency.unlockWrite(lockInfo.part, timeout); - throw err; - } - } - try { - versions.success = handleChanges(plan, current, writeLocked); + versions.success = handleChanges(plan, current); console.debug('plan change handling successful'); } catch (err) { @@ -1729,9 +1842,9 @@ var handlePlanChange = function (plan, current) { return versions; }; -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief coordinatorId -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// var coordinatorId = function () { if (!isCoordinator()) { @@ -1740,9 +1853,9 @@ var coordinatorId = function () { return global.ArangoServerState.id(); }; -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief bootstrap db servers -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// var bootstrapDbServers = function (isRelaunch) { global.ArangoClusterInfo.reloadDBServers(); @@ -1790,9 +1903,9 @@ var bootstrapDbServers = function (isRelaunch) { return result; }; -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief shard distribution -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function format (x) { var r = {}; @@ -1830,9 +1943,9 @@ function shardDistribution () { }; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief move shard -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function moveShard (info) { var isLeader; @@ -1874,9 +1987,9 @@ function moveShard (info) { return {error: false, id: id}; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief rebalance shards -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function rebalanceShards () { var dbServers = global.ArangoClusterInfo.getDBServers(); @@ -1982,9 +2095,9 @@ function rebalanceShards () { return true; } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief supervision state -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function supervisionState () { try { @@ -2000,9 +2113,9 @@ function supervisionState () { } } -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // / @brief wait for synchronous replication to settle -// ////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// function waitForSyncReplOneCollection (dbName, collName) { console.debug('waitForSyncRepl:', dbName, collName);