router.get("/cluster", function (req, res) { if (!cluster.isCoordinator()) { throw new httperr.Forbidden("only allowed on coordinator"); } const DBserver = req.queryParams.DBserver; let type = req.queryParams.type; const options = { timeout: 10 }; if (type !== "short" && type !== "long") { type = "short"; } let url = "/_admin/statistics/" + type; let sep = "?"; if (req.queryParams.start) { url += sep + "start=" + encodeURIComponent(req.queryParams.start); sep = "&"; } if (req.queryParams.filter) { url += sep + "filter=" + encodeURIComponent(req.queryParams.filter); sep = "&"; } url += sep + "DBserver=" + encodeURIComponent(DBserver); const op = ArangoClusterComm.asyncRequest( "GET", "server:" + DBserver, "_system", url, "", {}, options ); const r = ArangoClusterComm.wait(op); if (r.status === "RECEIVED") { res.set("content-type", "application/json; charset=utf-8"); res.body = r.body; } else if (r.status === "TIMEOUT") { throw new httperr.BadRequest("operation timed out"); } else { let body; try { body = JSON.parse(r.body); } catch (e) { // noop } throw Object.assign( new httperr.BadRequest("error from DBserver, possibly DBserver unknown"), {extra: {body}} ); } })
var checkShards = function(req, collection) { if (collection === null) { throw "unexpected collection value"; } var cluster = require("@arangodb/cluster"); if (! cluster.isCoordinator()) { // no cluster return true; } // check number of shards var shards = cluster.shardList(req.database, collection.name()); if (shards.length <= 1) { return true; } return false; };
function collectionRepresentation(collection, showProperties, showCount, showFigures) { const result = { id: collection._id, name: collection.name(), isSystem: (result.name.charAt(0) === '_'), status: collection.status(), type: collection.type() }; if (showProperties) { const properties = collection.properties(); result.doCompact = properties.doCompact; result.isVolatile = properties.isVolatile; result.journalSize = properties.journalSize; result.keyOptions = properties.keyOptions; result.waitForSync = properties.waitForSync; if (cluster.isCoordinator()) { result.shardKeys = properties.shardKeys; result.numberOfShards = properties.numberOfShards; } } if (showCount) { result.count = collection.count(); } if (showFigures) { const figures = collection.figures(); if (figures) { result.figures = figures; } } return result; }
exports.databaseVersion = function() { if (cluster.isCoordinator()) { console.debug("skip on corrdinator"); return { result: exports.IS_CLUSTER }; } // path to the VERSION file var versionFile = db._path() + "/VERSION"; var lastVersion = null; // VERSION file exists, read its contents if (fs.exists(versionFile)) { var versionInfo = fs.read(versionFile); console.debug("found version file: " + versionInfo); if (versionInfo !== '') { var versionValues = JSON.parse(versionInfo); if (versionValues && versionValues.version && !isNaN(versionValues.version)) { lastVersion = parseFloat(versionValues.version); } else { logger.error("Cannot parse VERSION file '" + versionFile + "': '" + versionInfo + "'"); return { result: exports.CANNOT_PARSE_VERSION_FILE }; } } else { logger.error("Cannot read VERSION file: '" + versionFile + "'"); return { result: exports.CANNOT_READ_VERSION_FILE }; } } else { console.debug("version file (" + versionFile + ") not found"); return { result: exports.NO_VERSION_FILE }; } // extract server version var currentVersion = exports.CURRENT_VERSION; // version match! if (Math.floor(lastVersion / 100) === Math.floor(currentVersion / 100)) { console.debug("version match: last version " + lastVersion + ", current version " + currentVersion); return { result: exports.VERSION_MATCH, serverVersion: currentVersion, databaseVersion: lastVersion }; } // downgrade?? if (lastVersion > currentVersion) { console.debug("downgrade: last version " + lastVersion + ", current version " + currentVersion); return { result: exports.DOWNGRADE_NEEDED, serverVersion: currentVersion, databaseVersion: lastVersion }; } // upgrade if (lastVersion < currentVersion) { console.debug("upgrade: last version " + lastVersion + ", current version " + currentVersion); return { result: exports.UPGRADE_NEEDED, serverVersion: currentVersion, databaseVersion: lastVersion }; } console.error("should not happen: last version " + lastVersion + ", current version " + currentVersion); return { result: exports.NO_VERSION_FILE }; };
callback : function (req, res) { if (req.requestType !== actions.POST) { actions.resultError(req, res, actions.HTTP_FORBIDDEN, 0, "only POST requests are allowed"); return; } var body = actions.getJsonBody(req, res); if (body === undefined) { return; } var DBserver = req.parameters.DBserver; //build query var figures = body.figures; var filterString = " filter u.time > @startDate"; var bind = { startDate: (new Date().getTime() / 1000) - 20 * 60 }; if (cluster.isCoordinator() && !req.parameters.hasOwnProperty("DBserver")) { filterString += " filter u.clusterId == @serverId"; bind.serverId = cluster.coordinatorId(); } var returnValue = " return u"; if (figures) { returnValue = " return { time : u.time, server : {uptime : u.server.uptime} "; var groups = {}; figures.forEach(function(f) { var g = f.split(".")[0]; if (!groups[g]) { groups[g] = []; } groups[g].push(f.split(".")[1] + " : u." + f); }); Object.keys(groups).forEach(function(key) { returnValue += ", " + key + " : {" + groups[key] +"}"; }); returnValue += "}"; } // allow at most ((60 / 10) * 20) * 2 documents to prevent total chaos var myQueryVal = "FOR u in _statistics " + filterString + " LIMIT 240 SORT u.time" + returnValue; if (! req.parameters.hasOwnProperty("DBserver")) { // query the local statistics collection var cursor = AQL_EXECUTE(myQueryVal, bind); res.contentType = "application/json; charset=utf-8"; if (cursor instanceof Error) { res.responseCode = actions.HTTP_BAD; res.body = JSON.stringify( {"error":true, "errorMessage": "an error occurred"}); } res.responseCode = actions.HTTP_OK; res.body = JSON.stringify({result : cursor.docs}); } else { // query a remote statistics collection var options = { timeout:10 }; var op = ArangoClusterComm.asyncRequest("POST","server:"+DBserver,"_system", "/_api/cursor",JSON.stringify({query: myQueryVal, bindVars: bind}),{},options); var r = ArangoClusterComm.wait(op); res.contentType = "application/json; charset=utf-8"; if (r.status === "RECEIVED") { res.responseCode = actions.HTTP_OK; res.body = r.body; } else if (r.status === "TIMEOUT") { res.responseCode = actions.HTTP_BAD; res.body = JSON.stringify( {"error":true, "errorMessage": "operation timed out"}); } else { res.responseCode = actions.HTTP_BAD; var bodyobj; try { bodyobj = JSON.parse(r.body); } catch (err) { } res.body = JSON.stringify( {"error":true, "errorMessage": "error from DBserver, possibly DBserver unknown", "body": bodyobj} ); } } }
router.get('/amICoordinator', function(req, res) { res.json(cluster.isCoordinator()); })