Skip to content

Commit

Permalink
add code for properties
Browse files Browse the repository at this point in the history
  • Loading branch information
ObiWahn committed Aug 24, 2017
1 parent 4933eb4 commit c529c24
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 28 deletions.
2 changes: 1 addition & 1 deletion arangod/Cluster/ClusterComm.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ struct ClusterCommOperation {
////////////////////////////////////////////////////////////////////////////////

struct ClusterCommRequest {
std::string destination;
std::string destination; // shard: <id> || server: <id> || tcp://<ip> || ssl://<ip>
rest::RequestType requestType;
std::string path;
std::shared_ptr<std::string const> body;
Expand Down
163 changes: 138 additions & 25 deletions arangod/RestHandler/RestQueryCacheHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,18 @@
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Jan Christoph Uhde
////////////////////////////////////////////////////////////////////////////////

#include "RestQueryCacheHandler.h"
#include "Aql/QueryCache.h"
#include "Cluster/ClusterInfo.h"
#include "Cluster/ClusterComm.h"
#include "Cluster/ServerState.h"
#include "Rest/HttpRequest.h"
#include "RestQueryCacheHandler.h"
#include "Basics/error.h"

#include <string>

using namespace arangodb;
using namespace arangodb::aql;
Expand Down Expand Up @@ -80,19 +87,70 @@ bool RestQueryCacheHandler::clearCache() {
/// @brief was docuBlock GetApiQueryCacheProperties
////////////////////////////////////////////////////////////////////////////////

bool RestQueryCacheHandler::readProperties() {
auto queryCache = arangodb::aql::QueryCache::instance();

VPackBuilder result = queryCache->properties();
generateResult(rest::ResponseCode::OK, result.slice());
return true;
Result RestQueryCacheHandler::readProperties() {
Result rv;
if(ServerState::instance()->isCoordinator()) {
ClusterInfo* ci = ClusterInfo::instance();
if (!ci){
rv.reset(TRI_ERROR_INTERNAL, "unable to get ClusterInfo instance");
}

auto cc = ClusterComm::instance();
if (!cc){
rv.reset(TRI_ERROR_INTERNAL, "unable to get ClusterComm instance");
}

if(rv.fail()){ generateError(rv); return rv; };

auto dbServerIdVec = ci->getCurrentDBServers();
std::vector<ClusterCommRequest> requests;
std::string const requestsUrl = "/_api/query-cache/properties";
auto jsonBody = std::make_shared<std::string>();

if(!dbServerIdVec.empty()) {
// we assume that all DBServers have the same
// configuration what might not be true
size_t nrDone = 0;
static double const CL_DEFAULT_TIMEOUT = 120.0;
requests.emplace_back("server:" + dbServerIdVec[0],
arangodb::rest::RequestType::GET,
requestsUrl, jsonBody);
cc->performRequests(requests, CL_DEFAULT_TIMEOUT, nrDone, Logger::QUERIES, true);
if (!requests.empty()) {
auto& res = requests[0].result;
if (res.status == CL_COMM_RECEIVED) {
if (res.answer_code == arangodb::rest::ResponseCode::OK) {
VPackSlice answer = res.answer->payload();
if (answer.isObject()) {
generateResult(rest::ResponseCode::OK, answer);
} else {
rv.reset(TRI_ERROR_INTERNAL);
}
} else {
generateError(res.answer_code, TRI_ERROR_CLUSTER_CONNECTION_LOST, "did not receive cluster comm result");
rv.reset(TRI_ERROR_CLUSTER_CONNECTION_LOST);
return rv;
}
} else {
rv.reset(TRI_ERROR_CLUSTER_BACKEND_UNAVAILABLE);
}
}
}
if (rv.fail()){ generateError(rv); return rv; }
} else {
auto queryCache = arangodb::aql::QueryCache::instance();
VPackBuilder result = queryCache->properties();
generateResult(rest::ResponseCode::OK, result.slice());
}
return rv;
}

////////////////////////////////////////////////////////////////////////////////
/// @brief was docuBlock PutApiQueryCacheProperties
////////////////////////////////////////////////////////////////////////////////

bool RestQueryCacheHandler::replaceProperties() {
Result RestQueryCacheHandler::replaceProperties() {
Result rv;
auto const& suffixes = _request->suffixes();

if (suffixes.size() != 1 || suffixes[0] != "properties") {
Expand All @@ -117,23 +175,78 @@ bool RestQueryCacheHandler::replaceProperties() {
return true;
}

auto queryCache = arangodb::aql::QueryCache::instance();

std::pair<std::string, size_t> cacheProperties;
queryCache->properties(cacheProperties);

VPackSlice attribute = body.get("mode");
if (attribute.isString()) {
cacheProperties.first = attribute.copyString();
}

attribute = body.get("maxResults");

if (attribute.isNumber()) {
cacheProperties.second = static_cast<size_t>(attribute.getUInt());
if(ServerState::instance()->isCoordinator()) {
// Ask DB Servers to enable cache

ClusterInfo* ci = ClusterInfo::instance();
if (!ci){
rv.reset(TRI_ERROR_INTERNAL, "unable to get ClusterInfo instance");
}

auto cc = ClusterComm::instance();
if (!cc){
rv.reset(TRI_ERROR_INTERNAL, "unable to get ClusterComm instance");
}

if(rv.fail()){ generateError(rv); return rv; };

auto dbServerIdVec = ci->getCurrentDBServers();
std::vector<ClusterCommRequest> requests;
std::string const requestsUrl = "/_api/query-cache/properties";

auto jsonBody = std::make_shared<std::string>(body.toJson());

for (auto const& id : dbServerIdVec) {
requests.emplace_back("server:" + id,
arangodb::rest::RequestType::PUT,
requestsUrl, jsonBody);
}

size_t nrDone = 0;
static double const CL_DEFAULT_TIMEOUT = 120.0;
cc->performRequests(requests, CL_DEFAULT_TIMEOUT, nrDone, Logger::QUERIES, true);

for (auto& req : requests) {
auto& res = req.result;
if (res.status == CL_COMM_RECEIVED) {
if (res.answer_code == arangodb::rest::ResponseCode::OK) {
VPackSlice answer = res.answer->payload();
if (answer.isObject()) {
// fine
} else {
rv.reset(TRI_ERROR_INTERNAL);
}
} else {
generateError(res.answer_code, TRI_ERROR_CLUSTER_CONNECTION_LOST, "did not receive cluster comm result");
rv.reset(TRI_ERROR_CLUSTER_CONNECTION_LOST);
return rv;
}
} else {
rv.reset(TRI_ERROR_CLUSTER_BACKEND_UNAVAILABLE);
}
// communication to one of the dbservers failed
// so the overall operation failed
if (rv.fail()){ generateError(rv); return rv; }
}

} else {
auto queryCache = arangodb::aql::QueryCache::instance();

std::pair<std::string, size_t> cacheProperties;
queryCache->properties(cacheProperties);

VPackSlice attribute = body.get("mode");
if (attribute.isString()) {
cacheProperties.first = attribute.copyString();
}

attribute = body.get("maxResults");

if (attribute.isNumber()) {
cacheProperties.second = static_cast<size_t>(attribute.getUInt());
}

queryCache->setProperties(cacheProperties);
}

queryCache->setProperties(cacheProperties);

return readProperties();
}
4 changes: 2 additions & 2 deletions arangod/RestHandler/RestQueryCacheHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ class RestQueryCacheHandler : public RestVocbaseBaseHandler {
/// @brief returns the list of properties
//////////////////////////////////////////////////////////////////////////////

bool readProperties();
Result readProperties();

//////////////////////////////////////////////////////////////////////////////
/// @brief changes the properties
//////////////////////////////////////////////////////////////////////////////

bool replaceProperties();
Result replaceProperties();

//////////////////////////////////////////////////////////////////////////////
/// @brief clears the cache
Expand Down

0 comments on commit c529c24

Please sign in to comment.