mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'engine-vs-velocystream' of https://github.com/arangodb/arangodb into generic-col-types
This commit is contained in:
commit
df808cd665
|
@ -26,6 +26,7 @@ core.*
|
|||
Thumbs.db
|
||||
|
||||
compile_commands.json
|
||||
instanceinfo.json
|
||||
testresult.json
|
||||
botschaft.txt
|
||||
testsStarted
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
/// @author Kaveh Vahedipour
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "RestAgencyPrivHandler.h"
|
||||
#include "Rest/HttpRequest.h"
|
||||
#include "Rest/Version.h"
|
||||
#include "RestAgencyPrivHandler.h"
|
||||
|
||||
#include "Agency/Agent.h"
|
||||
|
||||
|
@ -58,13 +58,14 @@ inline RestHandler::status RestAgencyPrivHandler::reportErrorEmptyRequest() {
|
|||
}
|
||||
|
||||
inline RestHandler::status RestAgencyPrivHandler::reportTooManySuffices() {
|
||||
LOG_TOPIC(WARN, Logger::AGENCY) << "Agency handles a single suffix: vote, log or configure";
|
||||
LOG_TOPIC(WARN, Logger::AGENCY)
|
||||
<< "Agency handles a single suffix: vote, log or configure";
|
||||
generateError(rest::ResponseCode::NOT_FOUND, 404);
|
||||
return RestHandler::status::DONE;
|
||||
}
|
||||
|
||||
inline RestHandler::status RestAgencyPrivHandler::reportBadQuery(
|
||||
std::string const& message) {
|
||||
std::string const& message) {
|
||||
generateError(rest::ResponseCode::BAD, 400, message);
|
||||
return RestHandler::status::DONE;
|
||||
}
|
||||
|
@ -137,9 +138,9 @@ RestHandler::status RestAgencyPrivHandler::execute() {
|
|||
query_t query = _request->toVelocyPackBuilderPtr(&options);
|
||||
try {
|
||||
query_t ret = _agent->gossip(query);
|
||||
result.add("id",ret->slice().get("id"));
|
||||
result.add("endpoint",ret->slice().get("endpoint"));
|
||||
result.add("pool",ret->slice().get("pool"));
|
||||
result.add("id", ret->slice().get("id"));
|
||||
result.add("endpoint", ret->slice().get("endpoint"));
|
||||
result.add("pool", ret->slice().get("pool"));
|
||||
} catch (std::exception const& e) {
|
||||
return reportBadQuery(e.what());
|
||||
}
|
||||
|
@ -148,7 +149,8 @@ RestHandler::status RestAgencyPrivHandler::execute() {
|
|||
return reportMethodNotAllowed();
|
||||
}
|
||||
if (_agent->leaderID() != NO_LEADER) {
|
||||
result.add("active", _agent->config().activeAgentsToBuilder()->slice());
|
||||
result.add("active",
|
||||
_agent->config().activeAgentsToBuilder()->slice());
|
||||
}
|
||||
} else if (_request->suffix()[0] == "inform") {
|
||||
arangodb::velocypack::Options options;
|
||||
|
@ -159,8 +161,7 @@ RestHandler::status RestAgencyPrivHandler::execute() {
|
|||
return reportBadQuery(e.what());
|
||||
}
|
||||
} else {
|
||||
generateError(rest::ResponseCode::NOT_FOUND,
|
||||
404); // nothing else here
|
||||
generateError(rest::ResponseCode::NOT_FOUND, 404); // nothing else here
|
||||
return RestHandler::status::DONE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,6 +158,7 @@ class GeneralCommTask : public SocketTask {
|
|||
|
||||
void processResponse(GeneralResponse*);
|
||||
|
||||
public:
|
||||
virtual void handleSimpleError(rest::ResponseCode, uint64_t messagid) = 0;
|
||||
virtual void handleSimpleError(rest::ResponseCode, int code,
|
||||
std::string const& errorMessage,
|
||||
|
|
|
@ -192,6 +192,7 @@ bool GeneralServer::handleRequest(GeneralCommTask* task,
|
|||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
task->handleSimpleError(rest::ResponseCode::SERVICE_UNAVAILABLE, res, TRI_errno_string(res), messageId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,8 @@ HttpCommTask::HttpCommTask(GeneralServer* server, TRI_socket_t sock,
|
|||
_sinceCompactification(0),
|
||||
_originalBodyLength(0) { // TODO(fc) remove
|
||||
_protocol = "http";
|
||||
connectionStatisticsAgentSetHttp(); // old
|
||||
connectionStatisticsAgentSetHttp(); // this agent is inherited form
|
||||
// sockettask or task
|
||||
_agents.emplace(std::make_pair(1UL, RequestStatisticsAgent(true)));
|
||||
}
|
||||
|
||||
|
@ -588,6 +589,7 @@ void HttpCommTask::processRequest(std::unique_ptr<HttpRequest> request) {
|
|||
std::unique_ptr<GeneralResponse> response(
|
||||
new HttpResponse(rest::ResponseCode::SERVER_ERROR));
|
||||
response->setContentType(request->contentTypeResponse());
|
||||
response->setContentTypeRequested(request->contentTypeResponse());
|
||||
|
||||
executeRequest(std::move(request), std::move(response));
|
||||
}
|
||||
|
|
|
@ -176,7 +176,9 @@ void VppCommTask::addResponse(VppResponse* response) {
|
|||
|
||||
std::vector<VPackSlice> slices;
|
||||
slices.push_back(response_message._header);
|
||||
slices.push_back(response_message._payload);
|
||||
if (response->generateBody()) {
|
||||
slices.push_back(response_message._payload);
|
||||
}
|
||||
|
||||
LOG_TOPIC(DEBUG, Logger::COMMUNICATION) << "VppCommTask: "
|
||||
<< "created response:";
|
||||
|
@ -482,6 +484,7 @@ bool VppCommTask::processRead() {
|
|||
|
||||
std::unique_ptr<VppResponse> response(new VppResponse(
|
||||
rest::ResponseCode::SERVER_ERROR, chunkHeader._messageID));
|
||||
response->setContentTypeRequested(request->contentTypeResponse());
|
||||
executeRequest(std::move(request), std::move(response));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,31 +51,34 @@ void RestBaseHandler::handleError(Exception const& ex) {
|
|||
/// @brief generates a result from VelocyPack
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Payload>
|
||||
void RestBaseHandler::generateResult(rest::ResponseCode code,
|
||||
VPackSlice const& slice) {
|
||||
Payload&& payload) {
|
||||
resetResponse(code);
|
||||
VPackOptions options(VPackOptions::Defaults);
|
||||
options.escapeUnicode = true;
|
||||
writeResult(slice, options);
|
||||
writeResult(std::forward<Payload>(payload), options);
|
||||
}
|
||||
|
||||
template<typename Payload>
|
||||
void RestBaseHandler::generateResult(rest::ResponseCode code,
|
||||
VPackSlice const& slice,
|
||||
Payload&& payload,
|
||||
VPackOptions const* options) {
|
||||
resetResponse(code);
|
||||
VPackOptions tmpoptions(*options);
|
||||
tmpoptions.escapeUnicode = true;
|
||||
writeResult(slice, tmpoptions);
|
||||
writeResult(std::forward<Payload>(payload), tmpoptions);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates a result from VelocyPack
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename Payload>
|
||||
void RestBaseHandler::generateResult(
|
||||
rest::ResponseCode code, VPackSlice const& slice,
|
||||
rest::ResponseCode code, Payload&& payload,
|
||||
std::shared_ptr<TransactionContext> context) {
|
||||
resetResponse(code);
|
||||
writeResult(slice, *(context->getVPackOptionsForDump()));
|
||||
writeResult(std::forward<Payload>(payload), *(context->getVPackOptionsForDump()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -100,7 +103,8 @@ void RestBaseHandler::generateError(rest::ResponseCode code, int errorCode,
|
|||
std::string const& message) {
|
||||
resetResponse(code);
|
||||
|
||||
VPackBuilder builder;
|
||||
VPackBuffer<uint8_t> buffer;
|
||||
VPackBuilder builder(buffer);
|
||||
try {
|
||||
builder.add(VPackValue(VPackValueType::Object));
|
||||
builder.add("error", VPackValue(true));
|
||||
|
@ -116,7 +120,7 @@ void RestBaseHandler::generateError(rest::ResponseCode code, int errorCode,
|
|||
|
||||
VPackOptions options(VPackOptions::Defaults);
|
||||
options.escapeUnicode = true;
|
||||
writeResult(builder.slice(), options);
|
||||
writeResult(std::move(buffer), options);
|
||||
} catch (...) {
|
||||
// Building the error response failed
|
||||
}
|
||||
|
@ -142,14 +146,15 @@ void RestBaseHandler::generateCanceled() {
|
|||
/// @brief writes volocypack or json to response
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RestBaseHandler::writeResult(arangodb::velocypack::Slice const& slice,
|
||||
template<typename Payload>
|
||||
void RestBaseHandler::writeResult(Payload&& payload,
|
||||
VPackOptions const& options) {
|
||||
try {
|
||||
TRI_ASSERT(options.escapeUnicode);
|
||||
if (_request != nullptr) {
|
||||
_response->setContentType(_request->contentTypeResponse());
|
||||
}
|
||||
_response->setPayload(slice, true, options);
|
||||
_response->setPayload(std::forward<Payload>(payload), true, options);
|
||||
} catch (std::exception const& ex) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
||||
ex.what());
|
||||
|
@ -158,3 +163,21 @@ void RestBaseHandler::writeResult(arangodb::velocypack::Slice const& slice,
|
|||
"cannot generate output");
|
||||
}
|
||||
}
|
||||
|
||||
//TODO -- rather move code to header (slower linking) or remove templates
|
||||
template void RestBaseHandler::generateResult<VPackBuffer<uint8_t>>(rest::ResponseCode, VPackBuffer<uint8_t>&&);
|
||||
template void RestBaseHandler::generateResult<VPackSlice>(rest::ResponseCode, VPackSlice&&);
|
||||
template void RestBaseHandler::generateResult<VPackSlice&>(rest::ResponseCode, VPackSlice&);
|
||||
|
||||
template void RestBaseHandler::generateResult<VPackBuffer<uint8_t>>(rest::ResponseCode, VPackBuffer<uint8_t>&&, VPackOptions const*);
|
||||
template void RestBaseHandler::generateResult<VPackSlice>(rest::ResponseCode, VPackSlice&&, VPackOptions const*);
|
||||
template void RestBaseHandler::generateResult<VPackSlice&>(rest::ResponseCode, VPackSlice&, VPackOptions const*);
|
||||
|
||||
template void RestBaseHandler::generateResult<VPackBuffer<uint8_t>>(rest::ResponseCode, VPackBuffer<uint8_t>&&, std::shared_ptr<arangodb::TransactionContext>);
|
||||
template void RestBaseHandler::generateResult<VPackSlice>(rest::ResponseCode, VPackSlice&&, std::shared_ptr<arangodb::TransactionContext>);
|
||||
template void RestBaseHandler::generateResult<VPackSlice&>(rest::ResponseCode, VPackSlice&, std::shared_ptr<arangodb::TransactionContext>);
|
||||
|
||||
template void RestBaseHandler::writeResult<VPackBuffer<uint8_t>>(VPackBuffer<uint8_t>&& payload, VPackOptions const&);
|
||||
template void RestBaseHandler::writeResult<VPackSlice>(VPackSlice&& payload, VPackOptions const&);
|
||||
template void RestBaseHandler::writeResult<VPackSlice&>(VPackSlice& payload, VPackOptions const&);
|
||||
template void RestBaseHandler::writeResult<VPackSlice const&>(VPackSlice const& payload, VPackOptions const&);
|
||||
|
|
|
@ -44,17 +44,16 @@ class RestBaseHandler : public rest::RestHandler {
|
|||
|
||||
public:
|
||||
// generates a result from VelocyPack
|
||||
void generateResult(rest::ResponseCode,
|
||||
arangodb::velocypack::Slice const& slice);
|
||||
template <typename Payload>
|
||||
void generateResult(rest::ResponseCode, Payload&&);
|
||||
|
||||
// generates a result from VelocyPack
|
||||
void generateResult(rest::ResponseCode,
|
||||
arangodb::velocypack::Slice const& slice,
|
||||
VPackOptions const*);
|
||||
template <typename Payload>
|
||||
void generateResult(rest::ResponseCode, Payload&&, VPackOptions const*);
|
||||
|
||||
// generates a result from VelocyPack
|
||||
void generateResult(rest::ResponseCode,
|
||||
arangodb::velocypack::Slice const& slice,
|
||||
template <typename Payload>
|
||||
void generateResult(rest::ResponseCode, Payload&&,
|
||||
std::shared_ptr<arangodb::TransactionContext> context);
|
||||
|
||||
// generates an error
|
||||
|
@ -70,9 +69,8 @@ class RestBaseHandler : public rest::RestHandler {
|
|||
void generateCanceled();
|
||||
|
||||
protected:
|
||||
// write result back to client
|
||||
void writeResult(arangodb::velocypack::Slice const& slice,
|
||||
arangodb::velocypack::Options const& options);
|
||||
template <typename Payload>
|
||||
void writeResult(Payload&&, arangodb::velocypack::Options const& options);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,26 @@ RestBatchHandler::~RestBatchHandler() {}
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RestHandler::status RestBatchHandler::execute() {
|
||||
switch (_response->transportType()) {
|
||||
case Endpoint::TransportType::HTTP: {
|
||||
return executeHttp();
|
||||
}
|
||||
case Endpoint::TransportType::VPP: {
|
||||
return executeVpp();
|
||||
}
|
||||
}
|
||||
// should never get here
|
||||
TRI_ASSERT(false);
|
||||
return RestHandler::status::FAILED;
|
||||
}
|
||||
|
||||
RestHandler::status RestBatchHandler::executeVpp() {
|
||||
generateError(rest::ResponseCode::METHOD_NOT_ALLOWED, TRI_ERROR_NO_ERROR,
|
||||
"The RestBatchHandler is not supported for this protocol!");
|
||||
return status::DONE;
|
||||
}
|
||||
|
||||
RestHandler::status RestBatchHandler::executeHttp() {
|
||||
HttpResponse* httpResponse = dynamic_cast<HttpResponse*>(_response.get());
|
||||
|
||||
if (httpResponse == nullptr) {
|
||||
|
@ -66,8 +86,7 @@ RestHandler::status RestBatchHandler::execute() {
|
|||
// extract the request type
|
||||
auto const type = _request->requestType();
|
||||
|
||||
if (type != rest::RequestType::POST &&
|
||||
type != rest::RequestType::PUT) {
|
||||
if (type != rest::RequestType::POST && type != rest::RequestType::PUT) {
|
||||
generateError(rest::ResponseCode::METHOD_NOT_ALLOWED,
|
||||
TRI_ERROR_HTTP_METHOD_NOT_ALLOWED);
|
||||
return status::DONE;
|
||||
|
@ -77,8 +96,7 @@ RestHandler::status RestBatchHandler::execute() {
|
|||
|
||||
// invalid content-type or boundary sent
|
||||
if (!getBoundary(&boundary)) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid content-type or boundary received");
|
||||
return status::FAILED;
|
||||
}
|
||||
|
@ -110,8 +128,7 @@ RestHandler::status RestBatchHandler::execute() {
|
|||
// get the next part from the multipart message
|
||||
if (!extractPart(&helper)) {
|
||||
// error
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid multipart message received");
|
||||
LOG(WARN) << "received a corrupted multipart message";
|
||||
|
||||
|
|
|
@ -64,6 +64,8 @@ class RestBatchHandler : public RestVocbaseBaseHandler {
|
|||
RestHandler::status execute() override;
|
||||
|
||||
private:
|
||||
RestHandler::status executeHttp();
|
||||
RestHandler::status executeVpp();
|
||||
// extract the boundary from the body of a multipart message
|
||||
bool getBoundaryBody(std::string*);
|
||||
|
||||
|
|
|
@ -92,15 +92,32 @@ RestHandler::status RestImportHandler::execute() {
|
|||
// extract the import type
|
||||
std::string const& documentType = _request->value("type", found);
|
||||
|
||||
if (found && (documentType == "documents" || documentType == "array" ||
|
||||
documentType == "list" || documentType == "auto")) {
|
||||
createFromJson(documentType);
|
||||
} else {
|
||||
// CSV
|
||||
createFromKeyValueList();
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
switch (_response->transportType()) {
|
||||
case Endpoint::TransportType::HTTP: {
|
||||
if (found &&
|
||||
(documentType == "documents" || documentType == "array" ||
|
||||
documentType == "list" || documentType == "auto")) {
|
||||
createFromJson(documentType);
|
||||
} else {
|
||||
// CSV
|
||||
createFromKeyValueList();
|
||||
}
|
||||
} break;
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
case Endpoint::TransportType::VPP: {
|
||||
if (found &&
|
||||
(documentType == "documents" || documentType == "array" ||
|
||||
documentType == "list" || documentType == "auto")) {
|
||||
createFromVPack(documentType);
|
||||
} else {
|
||||
generateNotImplemented("ILLEGAL " + IMPORT_PATH);
|
||||
createFromKeyValueListVPack();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
} break;
|
||||
|
||||
default:
|
||||
generateNotImplemented("ILLEGAL " + IMPORT_PATH);
|
||||
|
@ -122,7 +139,6 @@ std::string RestImportHandler::positionize(size_t i) const {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief register an error
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RestImportHandler::registerError(RestImportResult& result,
|
||||
std::string const& errorMsg) {
|
||||
++result._numErrors;
|
||||
|
@ -133,7 +149,6 @@ void RestImportHandler::registerError(RestImportResult& result,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief construct an error message
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string RestImportHandler::buildParseError(size_t i,
|
||||
char const* lineStart) {
|
||||
if (lineStart != nullptr) {
|
||||
|
@ -155,13 +170,11 @@ std::string RestImportHandler::buildParseError(size_t i,
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief process a single VelocyPack document
|
||||
/// @brief process a single VelocyPack document of Object Type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int RestImportHandler::handleSingleDocument(SingleCollectionTransaction& trx,
|
||||
RestImportResult& result,
|
||||
VPackBuilder& babies,
|
||||
char const* lineStart,
|
||||
VPackSlice slice,
|
||||
bool isEdgeCollection, size_t i) {
|
||||
if (!slice.isObject()) {
|
||||
|
@ -267,8 +280,7 @@ bool RestImportHandler::createFromJson(std::string const& type) {
|
|||
std::vector<std::string> const& suffix = _request->suffix();
|
||||
|
||||
if (suffix.size() != 0) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_SUPERFLUOUS_SUFFICES,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_SUPERFLUOUS_SUFFICES,
|
||||
"superfluous suffix, expecting " + IMPORT_PATH +
|
||||
"?collection=<identifier>");
|
||||
return false;
|
||||
|
@ -439,7 +451,7 @@ bool RestImportHandler::createFromJson(std::string const& type) {
|
|||
continue;
|
||||
}
|
||||
|
||||
res = handleSingleDocument(trx, result, babies, oldPtr, builder->slice(),
|
||||
res = handleSingleDocument(trx, result, babies, builder->slice(),
|
||||
isEdgeCollection, i);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -455,27 +467,21 @@ bool RestImportHandler::createFromJson(std::string const& type) {
|
|||
|
||||
else {
|
||||
// the entire request body is one JSON document
|
||||
std::shared_ptr<VPackBuilder> parsedDocuments;
|
||||
HttpRequest* req = dynamic_cast<HttpRequest*>(_request.get());
|
||||
|
||||
if (req == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
VPackSlice documents;
|
||||
try {
|
||||
parsedDocuments = VPackParser::fromJson(req->body());
|
||||
documents = _request->payload();
|
||||
} catch (VPackException const&) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"expecting a JSON array in the request");
|
||||
return false;
|
||||
}
|
||||
|
||||
VPackSlice const documents = parsedDocuments->slice();
|
||||
// VPackSlice const documents = _request->payload(); //yields different
|
||||
// error from what is expected in the server test
|
||||
|
||||
if (!documents.isArray()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"expecting a JSON array in the request");
|
||||
return false;
|
||||
}
|
||||
|
@ -485,8 +491,8 @@ bool RestImportHandler::createFromJson(std::string const& type) {
|
|||
for (VPackValueLength i = 0; i < n; ++i) {
|
||||
VPackSlice const slice = documents.at(i);
|
||||
|
||||
res = handleSingleDocument(trx, result, babies, nullptr, slice,
|
||||
isEdgeCollection, static_cast<size_t>(i + 1));
|
||||
res = handleSingleDocument(trx, result, babies, slice, isEdgeCollection,
|
||||
static_cast<size_t>(i + 1));
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
if (complete) {
|
||||
|
@ -517,6 +523,110 @@ bool RestImportHandler::createFromJson(std::string const& type) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RestImportHandler::createFromVPack(std::string const& type) {
|
||||
if (_request == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
RestImportResult result;
|
||||
|
||||
std::vector<std::string> const& suffix = _request->suffix();
|
||||
|
||||
if (suffix.size() != 0) {
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_SUPERFLUOUS_SUFFICES,
|
||||
"superfluous suffix, expecting " + IMPORT_PATH +
|
||||
"?collection=<identifier>");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool const complete = extractBooleanParameter("complete", false);
|
||||
bool const overwrite = extractBooleanParameter("overwrite", false);
|
||||
OperationOptions opOptions;
|
||||
opOptions.waitForSync = extractBooleanParameter("waitForSync", false);
|
||||
|
||||
// extract the collection name
|
||||
bool found;
|
||||
std::string const& collectionName = _request->value("collection", found);
|
||||
|
||||
if (!found || collectionName.empty()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_ARANGO_COLLECTION_PARAMETER_MISSING,
|
||||
"'collection' is missing, expecting " + IMPORT_PATH +
|
||||
"?collection=<identifier>");
|
||||
return false;
|
||||
}
|
||||
|
||||
// find and load collection given by name or identifier
|
||||
SingleCollectionTransaction trx(
|
||||
StandaloneTransactionContext::Create(_vocbase), collectionName,
|
||||
TRI_TRANSACTION_WRITE);
|
||||
|
||||
// .............................................................................
|
||||
// inside write transaction
|
||||
// .............................................................................
|
||||
|
||||
int res = trx.begin();
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
generateTransactionError(collectionName, res, "");
|
||||
return false;
|
||||
}
|
||||
bool const isEdgeCollection = trx.isEdgeCollection(collectionName);
|
||||
|
||||
if (overwrite) {
|
||||
OperationOptions truncateOpts;
|
||||
truncateOpts.waitForSync = false;
|
||||
// truncate collection first
|
||||
trx.truncate(collectionName, truncateOpts);
|
||||
// Ignore the result ...
|
||||
}
|
||||
|
||||
VPackBuilder babies;
|
||||
babies.openArray();
|
||||
|
||||
VPackSlice const documents = _request->payload();
|
||||
|
||||
if (!documents.isArray()) {
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"expecting a JSON array in the request");
|
||||
return false;
|
||||
}
|
||||
|
||||
VPackValueLength const n = documents.length();
|
||||
|
||||
for (VPackValueLength i = 0; i < n; ++i) {
|
||||
VPackSlice const slice = documents.at(i);
|
||||
|
||||
res = handleSingleDocument(trx, result, babies, slice, isEdgeCollection,
|
||||
static_cast<size_t>(i + 1));
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
if (complete) {
|
||||
// only perform a full import: abort
|
||||
break;
|
||||
}
|
||||
|
||||
res = TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
babies.close();
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
// no error so far. go on and perform the actual insert
|
||||
res =
|
||||
performImport(trx, result, collectionName, babies, complete, opOptions);
|
||||
}
|
||||
|
||||
res = trx.finish(res);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
generateTransactionError(collectionName, res, "");
|
||||
} else {
|
||||
generateDocumentsCreated(result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief was docuBlock JSF_import_document
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -531,8 +641,7 @@ bool RestImportHandler::createFromKeyValueList() {
|
|||
std::vector<std::string> const& suffix = _request->suffix();
|
||||
|
||||
if (suffix.size() != 0) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_SUPERFLUOUS_SUFFICES,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_SUPERFLUOUS_SUFFICES,
|
||||
"superfluous suffix, expecting " + IMPORT_PATH +
|
||||
"?collection=<identifier>");
|
||||
return false;
|
||||
|
@ -578,8 +687,7 @@ bool RestImportHandler::createFromKeyValueList() {
|
|||
static_cast<char const*>(memchr(current, '\n', bodyEnd - current));
|
||||
|
||||
if (next == nullptr) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"no JSON array found in second line");
|
||||
return false;
|
||||
}
|
||||
|
@ -608,16 +716,14 @@ bool RestImportHandler::createFromKeyValueList() {
|
|||
parsedKeys = parseVelocyPackLine(lineStart, lineEnd, success);
|
||||
} catch (...) {
|
||||
// This throws if the body is not parseable
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"no JSON string array found in first line");
|
||||
return false;
|
||||
}
|
||||
VPackSlice const keys = parsedKeys->slice();
|
||||
|
||||
if (!success || !checkKeys(keys)) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"no JSON string array found in first line");
|
||||
return false;
|
||||
}
|
||||
|
@ -707,8 +813,8 @@ bool RestImportHandler::createFromKeyValueList() {
|
|||
try {
|
||||
std::shared_ptr<VPackBuilder> objectBuilder =
|
||||
createVelocyPackObject(keys, values, errorMsg, i);
|
||||
res = handleSingleDocument(trx, result, babies, lineStart,
|
||||
objectBuilder->slice(), isEdgeCollection, i);
|
||||
res = handleSingleDocument(trx, result, babies, objectBuilder->slice(),
|
||||
isEdgeCollection, i);
|
||||
} catch (...) {
|
||||
// raise any error
|
||||
res = TRI_ERROR_INTERNAL;
|
||||
|
|
|
@ -68,7 +68,6 @@ class RestImportHandler : public RestVocbaseBaseHandler {
|
|||
status execute() override final;
|
||||
|
||||
private:
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a position string
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -91,10 +90,10 @@ class RestImportHandler : public RestVocbaseBaseHandler {
|
|||
/// @brief process a single VelocyPack document
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int handleSingleDocument(SingleCollectionTransaction& trx,
|
||||
int handleSingleDocument(SingleCollectionTransaction& trx,
|
||||
RestImportResult& result,
|
||||
arangodb::velocypack::Builder& babies,
|
||||
char const* lineStart, arangodb::velocypack::Slice slice,
|
||||
arangodb::velocypack::Builder& babies,
|
||||
arangodb::velocypack::Slice slice,
|
||||
bool isEdgeCollection, size_t);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -103,6 +102,7 @@ class RestImportHandler : public RestVocbaseBaseHandler {
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool createFromJson(std::string const&);
|
||||
bool createFromVPack(std::string const&);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates documents by JSON objects
|
||||
|
@ -116,16 +116,18 @@ class RestImportHandler : public RestVocbaseBaseHandler {
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool createFromKeyValueList();
|
||||
bool createFromKeyValueListVPack() {
|
||||
LOG(ERR) << " not implemened";
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief perform the actual import (insert/update/replace) operations
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int performImport(SingleCollectionTransaction& trx,
|
||||
RestImportResult& result,
|
||||
int performImport(SingleCollectionTransaction& trx, RestImportResult& result,
|
||||
std::string const& collectionName,
|
||||
VPackBuilder const& babies,
|
||||
bool complete,
|
||||
VPackBuilder const& babies, bool complete,
|
||||
OperationOptions const& opOptions);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -152,9 +154,8 @@ class RestImportHandler : public RestVocbaseBaseHandler {
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::shared_ptr<arangodb::velocypack::Builder> createVelocyPackObject(
|
||||
arangodb::velocypack::Slice const&,
|
||||
arangodb::velocypack::Slice const&,
|
||||
std::string&, size_t);
|
||||
arangodb::velocypack::Slice const&, arangodb::velocypack::Slice const&,
|
||||
std::string&, size_t);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks the keys, returns true if all values in the list are
|
||||
|
|
|
@ -106,8 +106,7 @@ RestHandler::status RestReplicationHandler::execute() {
|
|||
}
|
||||
handleCommandLoggerFirstTick();
|
||||
} else if (command == "logger-follow") {
|
||||
if (type != rest::RequestType::GET &&
|
||||
type != rest::RequestType::PUT) {
|
||||
if (type != rest::RequestType::GET && type != rest::RequestType::PUT) {
|
||||
goto BAD_CALL;
|
||||
}
|
||||
if (isCoordinatorError()) {
|
||||
|
@ -140,8 +139,7 @@ RestHandler::status RestReplicationHandler::execute() {
|
|||
handleCommandInventory();
|
||||
}
|
||||
} else if (command == "keys") {
|
||||
if (type != rest::RequestType::GET &&
|
||||
type != rest::RequestType::POST &&
|
||||
if (type != rest::RequestType::GET && type != rest::RequestType::POST &&
|
||||
type != rest::RequestType::PUT &&
|
||||
type != rest::RequestType::DELETE_REQ) {
|
||||
goto BAD_CALL;
|
||||
|
@ -303,8 +301,8 @@ RestHandler::status RestReplicationHandler::execute() {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid command");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid command");
|
||||
}
|
||||
|
||||
return status::DONE;
|
||||
|
@ -312,8 +310,7 @@ RestHandler::status RestReplicationHandler::execute() {
|
|||
|
||||
BAD_CALL:
|
||||
if (len != 1) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_SUPERFLUOUS_SUFFICES,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_SUPERFLUOUS_SUFFICES,
|
||||
"expecting URL /_api/replication/<command>");
|
||||
} else {
|
||||
generateError(rest::ResponseCode::METHOD_NOT_ALLOWED,
|
||||
|
@ -326,8 +323,9 @@ BAD_CALL:
|
|||
/// @brief comparator to sort collections
|
||||
/// sort order is by collection type first (vertices before edges, this is
|
||||
/// because edges depend on vertices being there), then name
|
||||
bool RestReplicationHandler::sortCollections(arangodb::LogicalCollection const* l,
|
||||
arangodb::LogicalCollection const* r) {
|
||||
bool RestReplicationHandler::sortCollections(
|
||||
arangodb::LogicalCollection const* l,
|
||||
arangodb::LogicalCollection const* r) {
|
||||
if (l->type() != r->type()) {
|
||||
return l->type() < r->type();
|
||||
}
|
||||
|
@ -338,8 +336,8 @@ bool RestReplicationHandler::sortCollections(arangodb::LogicalCollection const*
|
|||
}
|
||||
|
||||
/// @brief filter a collection based on collection attributes
|
||||
bool RestReplicationHandler::filterCollection(arangodb::LogicalCollection* collection,
|
||||
void* data) {
|
||||
bool RestReplicationHandler::filterCollection(
|
||||
arangodb::LogicalCollection* collection, void* data) {
|
||||
bool includeSystem = *((bool*)data);
|
||||
|
||||
std::string const collectionName(collection->name());
|
||||
|
@ -467,8 +465,7 @@ void RestReplicationHandler::handleCommandLoggerState() {
|
|||
|
||||
generateResult(rest::ResponseCode::OK, builder.slice());
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_OUT_OF_MEMORY);
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,8 +491,7 @@ void RestReplicationHandler::handleCommandLoggerTickRanges() {
|
|||
b.close();
|
||||
generateResult(rest::ResponseCode::OK, b.slice());
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_OUT_OF_MEMORY);
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -531,8 +527,7 @@ void RestReplicationHandler::handleCommandLoggerFirstTick() {
|
|||
b.close();
|
||||
generateResult(rest::ResponseCode::OK, b.slice());
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_OUT_OF_MEMORY);
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -554,8 +549,8 @@ void RestReplicationHandler::handleCommandBatch() {
|
|||
_request->toVelocyPackBuilderPtr(&VPackOptions::Defaults);
|
||||
|
||||
if (input == nullptr || !input->slice().isObject()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid JSON");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid JSON");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -579,8 +574,7 @@ void RestReplicationHandler::handleCommandBatch() {
|
|||
b.close();
|
||||
generateResult(rest::ResponseCode::OK, b.slice());
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_OUT_OF_MEMORY);
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -593,8 +587,8 @@ void RestReplicationHandler::handleCommandBatch() {
|
|||
auto input = _request->toVelocyPackBuilderPtr(&VPackOptions::Defaults);
|
||||
|
||||
if (input == nullptr || !input->slice().isObject()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid JSON");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid JSON");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -654,8 +648,8 @@ void RestReplicationHandler::handleCommandBarrier() {
|
|||
_request->toVelocyPackBuilderPtr(&VPackOptions::Defaults);
|
||||
|
||||
if (input == nullptr || !input->slice().isObject()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid JSON");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid JSON");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -673,8 +667,8 @@ void RestReplicationHandler::handleCommandBarrier() {
|
|||
}
|
||||
|
||||
if (minTick == 0) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid tick value");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid tick value");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -690,8 +684,7 @@ void RestReplicationHandler::handleCommandBarrier() {
|
|||
b.close();
|
||||
generateResult(rest::ResponseCode::OK, b.slice());
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_OUT_OF_MEMORY);
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -704,8 +697,8 @@ void RestReplicationHandler::handleCommandBarrier() {
|
|||
_request->toVelocyPackBuilderPtr(&VPackOptions::Defaults);
|
||||
|
||||
if (input == nullptr || !input->slice().isObject()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid JSON");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid JSON");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -758,8 +751,7 @@ void RestReplicationHandler::handleCommandBarrier() {
|
|||
b.close();
|
||||
generateResult(rest::ResponseCode::OK, b.slice());
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_OUT_OF_MEMORY);
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -782,8 +774,8 @@ void RestReplicationHandler::handleTrampolineCoordinator() {
|
|||
ServerID DBserver = _request->value("DBserver");
|
||||
|
||||
if (DBserver.empty()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "need \"DBserver\" parameter");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"need \"DBserver\" parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -831,8 +823,7 @@ void RestReplicationHandler::handleTrampolineCoordinator() {
|
|||
}
|
||||
if (res->status == CL_COMM_BACKEND_UNAVAILABLE) {
|
||||
// there is no result
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_CLUSTER_CONNECTION_LOST,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_CLUSTER_CONNECTION_LOST,
|
||||
"lost connection within cluster");
|
||||
return;
|
||||
}
|
||||
|
@ -845,8 +836,8 @@ void RestReplicationHandler::handleTrampolineCoordinator() {
|
|||
}
|
||||
|
||||
bool dummy;
|
||||
resetResponse(static_cast<rest::ResponseCode>(
|
||||
res->result->getHttpReturnCode()));
|
||||
resetResponse(
|
||||
static_cast<rest::ResponseCode>(res->result->getHttpReturnCode()));
|
||||
|
||||
HttpResponse* httpResponse = dynamic_cast<HttpResponse*>(_response.get());
|
||||
|
||||
|
@ -891,8 +882,8 @@ void RestReplicationHandler::handleCommandLoggerFollow() {
|
|||
}
|
||||
|
||||
if (found && (tickStart > tickEnd || tickEnd == 0)) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid from/to values");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid from/to values");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -925,26 +916,23 @@ void RestReplicationHandler::handleCommandLoggerFollow() {
|
|||
VPackOptions options = VPackOptions::Defaults;
|
||||
options.checkAttributeUniqueness = true;
|
||||
std::shared_ptr<VPackBuilder> parsedRequest;
|
||||
VPackSlice slice;
|
||||
try {
|
||||
parsedRequest = _request->toVelocyPackBuilderPtr(&options);
|
||||
slice = _request->payload(&options);
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid body value. expecting array");
|
||||
return;
|
||||
}
|
||||
VPackSlice const slice = parsedRequest->slice();
|
||||
if (!slice.isArray()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid body value. expecting array");
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto const& id : VPackArrayIterator(slice)) {
|
||||
if (!id.isString()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid body value. expecting array of ids");
|
||||
return;
|
||||
}
|
||||
|
@ -1075,8 +1063,8 @@ void RestReplicationHandler::handleCommandDetermineOpenTransactions() {
|
|||
}
|
||||
|
||||
if (found && (tickStart > tickEnd || tickEnd == 0)) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid from/to values");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid from/to values");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1188,8 +1176,7 @@ void RestReplicationHandler::handleCommandInventory() {
|
|||
|
||||
generateResult(rest::ResponseCode::OK, builder.slice());
|
||||
} catch (std::bad_alloc&) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_OUT_OF_MEMORY);
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1372,8 +1359,8 @@ void RestReplicationHandler::handleCommandRestoreCollection() {
|
|||
try {
|
||||
parsedRequest = _request->toVelocyPackBuilderPtr(&options);
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid JSON");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid JSON");
|
||||
return;
|
||||
}
|
||||
VPackSlice const slice = parsedRequest->slice();
|
||||
|
@ -1456,8 +1443,8 @@ void RestReplicationHandler::handleCommandRestoreIndexes() {
|
|||
try {
|
||||
parsedRequest = _request->toVelocyPackBuilderPtr(&options);
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid JSON");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid JSON");
|
||||
return;
|
||||
}
|
||||
VPackSlice const slice = parsedRequest->slice();
|
||||
|
@ -2413,8 +2400,7 @@ void RestReplicationHandler::handleCommandRestoreData() {
|
|||
std::string const& value1 = _request->value("collection");
|
||||
|
||||
if (value1.empty()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid collection parameter, not given");
|
||||
return;
|
||||
}
|
||||
|
@ -2427,8 +2413,7 @@ void RestReplicationHandler::handleCommandRestoreData() {
|
|||
std::string msg = "invalid collection parameter: '";
|
||||
msg += value1;
|
||||
msg += "', cid is 0";
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, msg);
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2478,8 +2463,8 @@ void RestReplicationHandler::handleCommandRestoreDataCoordinator() {
|
|||
std::string const& name = _request->value("collection");
|
||||
|
||||
if (name.empty()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid collection parameter");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid collection parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2669,8 +2654,7 @@ void RestReplicationHandler::handleCommandRestoreDataCoordinator() {
|
|||
} else {
|
||||
LOG(ERR) << "result body is no object";
|
||||
}
|
||||
} else if (result.answer_code ==
|
||||
rest::ResponseCode::SERVER_ERROR) {
|
||||
} else if (result.answer_code == rest::ResponseCode::SERVER_ERROR) {
|
||||
// copy default options
|
||||
VPackOptions options = VPackOptions::Defaults;
|
||||
options.checkAttributeUniqueness = true;
|
||||
|
@ -2746,8 +2730,8 @@ void RestReplicationHandler::handleCommandCreateKeys() {
|
|||
std::string const& collection = _request->value("collection");
|
||||
|
||||
if (collection.empty()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid collection parameter");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid collection parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2829,8 +2813,7 @@ void RestReplicationHandler::handleCommandGetKeys() {
|
|||
std::vector<std::string> const& suffix = _request->suffix();
|
||||
|
||||
if (suffix.size() != 2) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"expecting GET /_api/replication/keys/<keys-id>");
|
||||
return;
|
||||
}
|
||||
|
@ -2922,8 +2905,7 @@ void RestReplicationHandler::handleCommandFetchKeys() {
|
|||
std::vector<std::string> const& suffix = _request->suffix();
|
||||
|
||||
if (suffix.size() != 2) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"expecting PUT /_api/replication/keys/<keys-id>");
|
||||
return;
|
||||
}
|
||||
|
@ -2960,8 +2942,8 @@ void RestReplicationHandler::handleCommandFetchKeys() {
|
|||
} else if (value3 == "docs") {
|
||||
keys = false;
|
||||
} else {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid 'type' value");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid 'type' value");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3035,8 +3017,7 @@ void RestReplicationHandler::handleCommandRemoveKeys() {
|
|||
std::vector<std::string> const& suffix = _request->suffix();
|
||||
|
||||
if (suffix.size() != 2) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"expecting DELETE /_api/replication/keys/<keys-id>");
|
||||
return;
|
||||
}
|
||||
|
@ -3051,8 +3032,7 @@ void RestReplicationHandler::handleCommandRemoveKeys() {
|
|||
bool found = keys->remove(collectionKeysId);
|
||||
|
||||
if (!found) {
|
||||
generateError(rest::ResponseCode::NOT_FOUND,
|
||||
TRI_ERROR_CURSOR_NOT_FOUND);
|
||||
generateError(rest::ResponseCode::NOT_FOUND, TRI_ERROR_CURSOR_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3060,13 +3040,11 @@ void RestReplicationHandler::handleCommandRemoveKeys() {
|
|||
resultBuilder.openObject();
|
||||
resultBuilder.add("id", VPackValue(id)); // id as a string
|
||||
resultBuilder.add("error", VPackValue(false));
|
||||
resultBuilder.add(
|
||||
"code",
|
||||
VPackValue(static_cast<int>(rest::ResponseCode::ACCEPTED)));
|
||||
resultBuilder.add("code",
|
||||
VPackValue(static_cast<int>(rest::ResponseCode::ACCEPTED)));
|
||||
resultBuilder.close();
|
||||
|
||||
generateResult(rest::ResponseCode::ACCEPTED,
|
||||
resultBuilder.slice());
|
||||
generateResult(rest::ResponseCode::ACCEPTED, resultBuilder.slice());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3077,8 +3055,8 @@ void RestReplicationHandler::handleCommandDump() {
|
|||
std::string const& collection = _request->value("collection");
|
||||
|
||||
if (collection.empty()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid collection parameter");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid collection parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3122,8 +3100,8 @@ void RestReplicationHandler::handleCommandDump() {
|
|||
}
|
||||
|
||||
if (tickStart > tickEnd || tickEnd == 0) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "invalid from/to values");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid from/to values");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3215,8 +3193,8 @@ void RestReplicationHandler::handleCommandDump() {
|
|||
response->setContentType(rest::ContentType::DUMP);
|
||||
|
||||
// set headers
|
||||
_response->setHeaderNC(
|
||||
TRI_REPLICATION_HEADER_CHECKMORE, (dump._hasMore ? "true" : "false"));
|
||||
_response->setHeaderNC(TRI_REPLICATION_HEADER_CHECKMORE,
|
||||
(dump._hasMore ? "true" : "false"));
|
||||
|
||||
_response->setHeaderNC(TRI_REPLICATION_HEADER_LASTINCLUDED,
|
||||
StringUtils::itoa(dump._lastFoundTick));
|
||||
|
@ -3255,8 +3233,7 @@ void RestReplicationHandler::handleCommandMakeSlave() {
|
|||
VelocyPackHelper::getStringValue(body, "endpoint", "");
|
||||
|
||||
if (endpoint.empty()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"<endpoint> must be a valid endpoint");
|
||||
return;
|
||||
}
|
||||
|
@ -3353,8 +3330,7 @@ void RestReplicationHandler::handleCommandMakeSlave() {
|
|||
(!restrictType.empty() && config._restrictCollections.empty()) ||
|
||||
(!restrictType.empty() && restrictType != "include" &&
|
||||
restrictType != "exclude")) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid value for <restrictCollections> or <restrictType>");
|
||||
return;
|
||||
}
|
||||
|
@ -3415,8 +3391,7 @@ void RestReplicationHandler::handleCommandMakeSlave() {
|
|||
_vocbase->replicationApplier()->toVelocyPack();
|
||||
generateResult(rest::ResponseCode::OK, result->slice());
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_OUT_OF_MEMORY);
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -3440,8 +3415,7 @@ void RestReplicationHandler::handleCommandSync() {
|
|||
VelocyPackHelper::getStringValue(body, "endpoint", "");
|
||||
|
||||
if (endpoint.empty()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"<endpoint> must be a valid endpoint");
|
||||
return;
|
||||
}
|
||||
|
@ -3482,8 +3456,7 @@ void RestReplicationHandler::handleCommandSync() {
|
|||
(!restrictType.empty() && restrictCollections.empty()) ||
|
||||
(!restrictType.empty() && restrictType != "include" &&
|
||||
restrictType != "exclude")) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid value for <restrictCollections> or <restrictType>");
|
||||
return;
|
||||
}
|
||||
|
@ -3597,8 +3570,7 @@ void RestReplicationHandler::handleCommandApplierGetConfig() {
|
|||
std::shared_ptr<VPackBuilder> configBuilder = config.toVelocyPack(false);
|
||||
generateResult(rest::ResponseCode::OK, configBuilder->slice());
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_OUT_OF_MEMORY);
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3793,8 +3765,7 @@ void RestReplicationHandler::handleCommandApplierGetState() {
|
|||
_vocbase->replicationApplier()->toVelocyPack();
|
||||
generateResult(rest::ResponseCode::OK, result->slice());
|
||||
} catch (...) {
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_OUT_OF_MEMORY);
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -3838,8 +3809,7 @@ void RestReplicationHandler::handleCommandAddFollower() {
|
|||
VPackSlice const followerId = body.get("followerId");
|
||||
VPackSlice const shard = body.get("shard");
|
||||
if (!followerId.isString() || !shard.isString()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"'followerId' and 'shard' attributes must be strings");
|
||||
return;
|
||||
}
|
||||
|
@ -3886,8 +3856,7 @@ void RestReplicationHandler::handleCommandRemoveFollower() {
|
|||
VPackSlice const followerId = body.get("followerId");
|
||||
VPackSlice const shard = body.get("shard");
|
||||
if (!followerId.isString() || !shard.isString()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"'followerId' and 'shard' attributes must be strings");
|
||||
return;
|
||||
}
|
||||
|
@ -3926,8 +3895,7 @@ void RestReplicationHandler::handleCommandHoldReadLockCollection() {
|
|||
}
|
||||
VPackSlice const body = parsedBody->slice();
|
||||
if (!body.isObject()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"body needs to be an object with attributes 'collection', "
|
||||
"'ttl' and 'id'");
|
||||
return;
|
||||
|
@ -3936,8 +3904,7 @@ void RestReplicationHandler::handleCommandHoldReadLockCollection() {
|
|||
VPackSlice const ttlSlice = body.get("ttl");
|
||||
VPackSlice const idSlice = body.get("id");
|
||||
if (!collection.isString() || !ttlSlice.isNumber() || !idSlice.isString()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"'collection' must be a string and 'ttl' a number and "
|
||||
"'id' a string");
|
||||
return;
|
||||
|
@ -4032,15 +3999,14 @@ void RestReplicationHandler::handleCommandCheckHoldReadLockCollection() {
|
|||
}
|
||||
VPackSlice const body = parsedBody->slice();
|
||||
if (!body.isObject()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"body needs to be an object with attribute 'id'");
|
||||
return;
|
||||
}
|
||||
VPackSlice const idSlice = body.get("id");
|
||||
if (!idSlice.isString()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "'id' needs to be a string");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"'id' needs to be a string");
|
||||
return;
|
||||
}
|
||||
std::string id = idSlice.copyString();
|
||||
|
@ -4049,8 +4015,7 @@ void RestReplicationHandler::handleCommandCheckHoldReadLockCollection() {
|
|||
CONDITION_LOCKER(locker, _condVar);
|
||||
auto it = _holdReadLockJobs.find(id);
|
||||
if (it == _holdReadLockJobs.end()) {
|
||||
generateError(rest::ResponseCode::NOT_FOUND,
|
||||
TRI_ERROR_HTTP_NOT_FOUND,
|
||||
generateError(rest::ResponseCode::NOT_FOUND, TRI_ERROR_HTTP_NOT_FOUND,
|
||||
"no hold read lock job found for 'id'");
|
||||
return;
|
||||
}
|
||||
|
@ -4079,15 +4044,14 @@ void RestReplicationHandler::handleCommandCancelHoldReadLockCollection() {
|
|||
}
|
||||
VPackSlice const body = parsedBody->slice();
|
||||
if (!body.isObject()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"body needs to be an object with attribute 'id'");
|
||||
return;
|
||||
}
|
||||
VPackSlice const idSlice = body.get("id");
|
||||
if (!idSlice.isString()) {
|
||||
generateError(rest::ResponseCode::BAD,
|
||||
TRI_ERROR_HTTP_BAD_PARAMETER, "'id' needs to be a string");
|
||||
generateError(rest::ResponseCode::BAD, TRI_ERROR_HTTP_BAD_PARAMETER,
|
||||
"'id' needs to be a string");
|
||||
return;
|
||||
}
|
||||
std::string id = idSlice.copyString();
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
#include "Basics/MutexLocker.h"
|
||||
#include "Basics/ScopeGuard.h"
|
||||
#include "Basics/StaticStrings.h"
|
||||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "Basics/VPackStringBufferAdapter.h"
|
||||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "Utils/SingleCollectionTransaction.h"
|
||||
#include "VocBase/LogicalCollection.h"
|
||||
#include "VocBase/Traverser.h"
|
||||
|
@ -256,9 +256,7 @@ void RestSimpleHandler::removeByKeys(VPackSlice const& slice) {
|
|||
result.add("removed", VPackValue(removed));
|
||||
result.add("ignored", VPackValue(ignored));
|
||||
result.add("error", VPackValue(false));
|
||||
result.add(
|
||||
"code",
|
||||
VPackValue(static_cast<int>(rest::ResponseCode::OK)));
|
||||
result.add("code", VPackValue(static_cast<int>(rest::ResponseCode::OK)));
|
||||
if (!silent) {
|
||||
result.add("old", queryResult.result->slice());
|
||||
}
|
||||
|
@ -273,8 +271,7 @@ void RestSimpleHandler::removeByKeys(VPackSlice const& slice) {
|
|||
ex.what());
|
||||
} catch (...) {
|
||||
unregisterQuery();
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_INTERNAL);
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,7 +352,8 @@ void RestSimpleHandler::lookupByKeys(VPackSlice const& slice) {
|
|||
resultSize = static_cast<size_t>(qResult.length());
|
||||
}
|
||||
|
||||
VPackBuilder result;
|
||||
VPackBuffer<uint8_t> resultBuffer;
|
||||
VPackBuilder result(resultBuffer);
|
||||
{
|
||||
VPackObjectBuilder guard(&result);
|
||||
resetResponse(rest::ResponseCode::OK);
|
||||
|
@ -436,32 +434,26 @@ void RestSimpleHandler::lookupByKeys(VPackSlice const& slice) {
|
|||
VPackValue(static_cast<int>(_response->responseCode())));
|
||||
|
||||
// reserve a few bytes per result document by default
|
||||
int res = response->body().reserve(32 * resultSize);
|
||||
int res = response->reservePayload(32 * resultSize);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
}
|
||||
|
||||
auto customTypeHandler = queryResult.context->orderCustomTypeHandler();
|
||||
VPackOptions options = VPackOptions::Defaults; // copy defaults
|
||||
options.customTypeHandler = customTypeHandler.get();
|
||||
generateResult(rest::ResponseCode::OK, std::move(resultBuffer),
|
||||
queryResult.context);
|
||||
|
||||
arangodb::basics::VPackStringBufferAdapter buffer(
|
||||
response->body().stringBuffer());
|
||||
VPackDumper dumper(&buffer, &options);
|
||||
dumper.dump(result.slice());
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
unregisterQuery();
|
||||
generateError(GeneralResponse::responseCode(ex.code()), ex.code(),
|
||||
ex.what());
|
||||
} catch (std::exception const& ex) {
|
||||
unregisterQuery();
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_INTERNAL, ex.what());
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
||||
ex.what());
|
||||
} catch (...) {
|
||||
unregisterQuery();
|
||||
generateError(rest::ResponseCode::SERVER_ERROR,
|
||||
TRI_ERROR_INTERNAL);
|
||||
generateError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,8 +114,7 @@ class RequestStatisticsAgent
|
|||
RequestStatisticsAgentDesc> {
|
||||
public:
|
||||
RequestStatisticsAgent(bool standalone = false)
|
||||
: StatisticsAgent(standalone) {
|
||||
}
|
||||
: StatisticsAgent(standalone) {}
|
||||
|
||||
RequestStatisticsAgent(RequestStatisticsAgent const&) = delete;
|
||||
|
||||
|
|
|
@ -30,48 +30,61 @@
|
|||
using namespace arangodb;
|
||||
using namespace arangodb::basics;
|
||||
|
||||
void GeneralResponse::addPayload(VPackSlice const& slice,
|
||||
arangodb::velocypack::Options const* options,
|
||||
bool resolve_externals) {
|
||||
addPayloadPreconditions();
|
||||
addPayloadPreHook(false, resolve_externals);
|
||||
if (!options) {
|
||||
options = &arangodb::velocypack::Options::Defaults;
|
||||
namespace detail {
|
||||
VPackOptions const* getOptions(VPackOptions const* options) {
|
||||
if (options) {
|
||||
return options;
|
||||
}
|
||||
return &VPackOptions::Options::Defaults;
|
||||
}
|
||||
}
|
||||
|
||||
if (resolve_externals) {
|
||||
auto tmpBuffer =
|
||||
basics::VelocyPackHelper::sanitizeExternalsChecked(slice, options);
|
||||
_vpackPayloads.push_back(std::move(tmpBuffer));
|
||||
} else {
|
||||
// just copy
|
||||
_vpackPayloads.emplace_back(slice.byteSize());
|
||||
_vpackPayloads.back().append(slice.startAs<char const>(), slice.byteSize());
|
||||
void GeneralResponse::addPayload(VPackSlice const& slice,
|
||||
VPackOptions const* options,
|
||||
bool resolveExternals) {
|
||||
addPayloadPreconditions();
|
||||
_numPayloads++;
|
||||
options = detail::getOptions(options);
|
||||
|
||||
bool skipBody = false;
|
||||
addPayloadPreHook(true, resolveExternals, skipBody);
|
||||
|
||||
if (!skipBody) {
|
||||
if (resolveExternals) {
|
||||
auto tmpBuffer =
|
||||
basics::VelocyPackHelper::sanitizeExternalsChecked(slice, options);
|
||||
_vpackPayloads.push_back(std::move(tmpBuffer));
|
||||
} else {
|
||||
// just copy
|
||||
_vpackPayloads.emplace_back(slice.byteSize());
|
||||
_vpackPayloads.back().append(slice.startAs<char const>(),
|
||||
slice.byteSize());
|
||||
}
|
||||
}
|
||||
addPayloadPostHook(options);
|
||||
// we pass the original slice here the new one can be accessed
|
||||
addPayloadPostHook(slice, options, resolveExternals, skipBody);
|
||||
};
|
||||
|
||||
void GeneralResponse::addPayload(VPackBuffer<uint8_t>&& buffer,
|
||||
arangodb::velocypack::Options const* options,
|
||||
bool resolve_externals) {
|
||||
bool resolveExternals) {
|
||||
addPayloadPreconditions();
|
||||
// TODO
|
||||
// skip sanatizing here for http if conent type is json because it will
|
||||
// be dumped anyway -- check with jsteemann
|
||||
addPayloadPreHook(true, resolve_externals);
|
||||
_numPayloads++;
|
||||
options = detail::getOptions(options);
|
||||
|
||||
if (!options) {
|
||||
options = &arangodb::velocypack::Options::Defaults;
|
||||
bool skipBody = false;
|
||||
addPayloadPreHook(true, resolveExternals, skipBody);
|
||||
if (!skipBody) {
|
||||
if (resolveExternals) {
|
||||
auto tmpBuffer = basics::VelocyPackHelper::sanitizeExternalsChecked(
|
||||
VPackSlice(buffer.data()), options);
|
||||
_vpackPayloads.push_back(std::move(tmpBuffer));
|
||||
} else {
|
||||
_vpackPayloads.push_back(std::move(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
if (resolve_externals) {
|
||||
auto tmpBuffer = basics::VelocyPackHelper::sanitizeExternalsChecked(
|
||||
VPackSlice(buffer.data()), options);
|
||||
_vpackPayloads.push_back(std::move(tmpBuffer));
|
||||
} else {
|
||||
_vpackPayloads.push_back(std::move(buffer));
|
||||
}
|
||||
addPayloadPostHook(options);
|
||||
addPayloadPostHook(VPackSlice(buffer.data()), options, resolveExternals,
|
||||
skipBody);
|
||||
};
|
||||
|
||||
std::string GeneralResponse::responseString(ResponseCode code) {
|
||||
|
@ -460,4 +473,6 @@ GeneralResponse::GeneralResponse(ResponseCode responseCode)
|
|||
: _responseCode(responseCode),
|
||||
_contentType(ContentType::UNSET),
|
||||
_connectionType(ConnectionType::CONNECTION_NONE),
|
||||
_options(velocypack::Options::Defaults) {}
|
||||
_options(velocypack::Options::Defaults),
|
||||
_generateBody(false),
|
||||
_contentTypeRequested(ContentType::UNSET) {}
|
||||
|
|
|
@ -79,6 +79,9 @@ class GeneralResponse {
|
|||
}
|
||||
|
||||
void setConnectionType(ConnectionType type) { _connectionType = type; }
|
||||
void setContentTypeRequested(ContentType type) {
|
||||
_contentTypeRequested = type;
|
||||
}
|
||||
|
||||
virtual arangodb::Endpoint::TransportType transportType() = 0;
|
||||
|
||||
|
@ -122,25 +125,42 @@ class GeneralResponse {
|
|||
|
||||
// generates the response body, sets the content type; this might
|
||||
// throw an error
|
||||
virtual void setPayload(arangodb::velocypack::Slice const&,
|
||||
bool generateBody = true,
|
||||
arangodb::velocypack::Options const& =
|
||||
arangodb::velocypack::Options::Defaults) = 0;
|
||||
void setPayload(VPackSlice&& slice, bool generateBody,
|
||||
VPackOptions const& options = VPackOptions::Options::Defaults,
|
||||
bool resolveExternals = true) {
|
||||
_generateBody = generateBody;
|
||||
auto tmp = std::move(slice);
|
||||
addPayload(tmp, &options, resolveExternals);
|
||||
}
|
||||
// Payload needs to be of type: VPackSlice const&
|
||||
// or VPackBuffer<uint8_t>&&
|
||||
template <typename Payload>
|
||||
void setPayload(Payload&& payload, bool generateBody,
|
||||
VPackOptions const& options = VPackOptions::Options::Defaults,
|
||||
bool resolveExternals = true) {
|
||||
_generateBody = generateBody;
|
||||
addPayload(std::forward<Payload>(payload), &options, resolveExternals);
|
||||
}
|
||||
|
||||
void addPayloadPreconditions() { TRI_ASSERT(_vpackPayloads.size() == 0); }
|
||||
virtual void addPayloadPreHook(bool inputIsBuffer, bool& resolveExternals) {}
|
||||
virtual void addPayloadPostHook(
|
||||
arangodb::velocypack::Options const* options) {}
|
||||
void addPayload(VPackSlice const& slice,
|
||||
arangodb::velocypack::Options const* options = nullptr,
|
||||
virtual void addPayloadPreHook(bool inputIsBuffer, bool& resolveExternals,
|
||||
bool& skipBody) {}
|
||||
void addPayload(VPackSlice const&,
|
||||
arangodb::velocypack::Options const* = nullptr,
|
||||
bool resolve_externals = true);
|
||||
void addPayload(VPackBuffer<uint8_t>&& buffer,
|
||||
arangodb::velocypack::Options const* options = nullptr,
|
||||
void addPayload(VPackBuffer<uint8_t>&&,
|
||||
arangodb::velocypack::Options const* = nullptr,
|
||||
bool resolve_externals = true);
|
||||
virtual void addPayloadPostHook(VPackSlice const&,
|
||||
arangodb::velocypack::Options const*,
|
||||
bool resolveExternals, bool bodySkipped) {}
|
||||
|
||||
virtual int reservePayload(std::size_t size) { return size; }
|
||||
virtual bool setGenerateBody(bool) { return true; }; // used for head
|
||||
// resonses
|
||||
virtual int reservePayload(std::size_t size) { return TRI_ERROR_NO_ERROR; }
|
||||
bool generateBody() const { return _generateBody; }; // used for head
|
||||
virtual bool setGenerateBody(bool) {
|
||||
return _generateBody;
|
||||
}; // used for head
|
||||
// resonses
|
||||
void setOptions(VPackOptions options) { _options = std::move(options); };
|
||||
|
||||
protected:
|
||||
|
@ -149,9 +169,12 @@ class GeneralResponse {
|
|||
_headers; // headers/metadata map
|
||||
|
||||
std::vector<VPackBuffer<uint8_t>> _vpackPayloads;
|
||||
std::size_t _numPayloads;
|
||||
ContentType _contentType;
|
||||
ConnectionType _connectionType;
|
||||
velocypack::Options _options;
|
||||
bool _generateBody;
|
||||
ContentType _contentTypeRequested;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -47,8 +47,8 @@ HttpResponse::HttpResponse(ResponseCode code)
|
|||
: GeneralResponse(code),
|
||||
_isHeadResponse(false),
|
||||
_body(TRI_UNKNOWN_MEM_ZONE, false),
|
||||
_bodySize(0),
|
||||
_generateBody(false) {
|
||||
_bodySize(0) {
|
||||
_generateBody = false;
|
||||
_contentType = ContentType::TEXT;
|
||||
_connectionType = rest::CONNECTION_KEEP_ALIVE;
|
||||
if (_body.c_str() == nullptr) {
|
||||
|
@ -300,14 +300,25 @@ void HttpResponse::writeHeader(StringBuffer* output) {
|
|||
// end of header, body to follow
|
||||
}
|
||||
|
||||
void HttpResponse::addPayloadPostHook(VPackOptions const* options) {
|
||||
VPackSlice slice(_vpackPayloads.front().data());
|
||||
void HttpResponse::addPayloadPostHook(
|
||||
VPackSlice const& slice,
|
||||
VPackOptions const* options = &VPackOptions::Options::Defaults,
|
||||
bool resolveExternals = true, bool bodySkipped = false) {
|
||||
VPackSlice const* slicePtr;
|
||||
if (!bodySkipped) {
|
||||
// we have Probably resolved externals
|
||||
TRI_ASSERT(!_vpackPayloads.empty());
|
||||
VPackSlice tmpSlice = VPackSlice(_vpackPayloads.front().data());
|
||||
slicePtr = &tmpSlice;
|
||||
} else {
|
||||
slicePtr = &slice;
|
||||
}
|
||||
|
||||
switch (_contentType) {
|
||||
case rest::ContentType::VPACK: {
|
||||
size_t length = static_cast<size_t>(slice.byteSize());
|
||||
size_t length = static_cast<size_t>(slicePtr->byteSize());
|
||||
if (_generateBody) {
|
||||
_body.appendText(slice.startAs<const char>(), length);
|
||||
_body.appendText(slicePtr->startAs<const char>(), length);
|
||||
} else {
|
||||
headResponse(length);
|
||||
}
|
||||
|
@ -317,7 +328,7 @@ void HttpResponse::addPayloadPostHook(VPackOptions const* options) {
|
|||
setContentType(rest::ContentType::JSON);
|
||||
if (_generateBody) {
|
||||
arangodb::basics::VelocyPackDumper dumper(&_body, options);
|
||||
dumper.dumpValue(slice);
|
||||
dumper.dumpValue(*slicePtr);
|
||||
} else {
|
||||
// TODO can we optimize this?
|
||||
// Just dump some where else to find real length
|
||||
|
@ -328,17 +339,10 @@ void HttpResponse::addPayloadPostHook(VPackOptions const* options) {
|
|||
|
||||
// usual dumping - but not to the response body
|
||||
VPackDumper dumper(&buffer, options);
|
||||
dumper.dump(slice);
|
||||
dumper.dump(*slicePtr);
|
||||
|
||||
headResponse(tmp.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
//_vpackPayloads.clear();
|
||||
}
|
||||
|
||||
void HttpResponse::setPayload(arangodb::velocypack::Slice const& slice,
|
||||
bool generateBody, VPackOptions const& options) {
|
||||
_generateBody = generateBody;
|
||||
addPayload(slice, &options, true);
|
||||
};
|
||||
|
|
|
@ -74,11 +74,10 @@ class HttpResponse : public GeneralResponse {
|
|||
public:
|
||||
void reset(ResponseCode code) override final;
|
||||
|
||||
void addPayloadPreHook(bool inputIsBuffer, bool& resolveExternals) override {
|
||||
void addPayloadPreHook(bool inputIsBuffer, bool& resolveExternals,
|
||||
bool& skipBody) override {
|
||||
if (_contentType == ContentType::JSON) {
|
||||
// resolveExternals = false; // they get resolved during dump in post
|
||||
// hook
|
||||
// this optimization leads to bad bas crahses
|
||||
skipBody = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,9 +85,8 @@ class HttpResponse : public GeneralResponse {
|
|||
return _generateBody = generateBody;
|
||||
} // used for head-responses
|
||||
int reservePayload(std::size_t size) override { return _body.reserve(size); }
|
||||
void addPayloadPostHook(VPackOptions const* options) override;
|
||||
void setPayload(arangodb::velocypack::Slice const&, bool generateBody,
|
||||
arangodb::velocypack::Options const&) override final;
|
||||
void addPayloadPostHook(VPackSlice const&, VPackOptions const* options,
|
||||
bool resolveExternals, bool bodySkipped) override;
|
||||
|
||||
arangodb::Endpoint::TransportType transportType() override {
|
||||
return arangodb::Endpoint::TransportType::HTTP;
|
||||
|
@ -103,7 +101,6 @@ class HttpResponse : public GeneralResponse {
|
|||
std::vector<std::string> _cookies;
|
||||
basics::StringBuffer _body;
|
||||
size_t _bodySize;
|
||||
bool _generateBody;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -53,17 +53,10 @@ void VppResponse::reset(ResponseCode code) {
|
|||
_responseCode = code;
|
||||
_headers.clear();
|
||||
_connectionType = rest::CONNECTION_KEEP_ALIVE;
|
||||
_contentType = ContentType::TEXT;
|
||||
_contentType = ContentType::VPACK;
|
||||
_generateBody = false; // payload has to be set
|
||||
}
|
||||
|
||||
void VppResponse::setPayload(arangodb::velocypack::Slice const& slice,
|
||||
bool generateBody, VPackOptions const& options) {
|
||||
if (setGenerateBody(generateBody)) {
|
||||
addPayload(slice, &options);
|
||||
}
|
||||
};
|
||||
|
||||
VPackMessageNoOwnBuffer VppResponse::prepareForNetwork() {
|
||||
// initalize builder with vpackbuffer. then we do not need to
|
||||
// steal the header and can avoid the shared pointer
|
||||
|
@ -75,8 +68,18 @@ VPackMessageNoOwnBuffer VppResponse::prepareForNetwork() {
|
|||
VPackValue(static_cast<int>(meta::underlyingValue(_responseCode))));
|
||||
builder.close();
|
||||
_header = builder.steal();
|
||||
return VPackMessageNoOwnBuffer(VPackSlice(_header->data()),
|
||||
VPackSlice(_vpackPayloads.front().data()),
|
||||
_messageId, _generateBody);
|
||||
if (_vpackPayloads.empty()) {
|
||||
if (_generateBody) {
|
||||
LOG_TOPIC(INFO, Logger::REQUESTS)
|
||||
<< "Response should generate body but no Data available";
|
||||
_generateBody = false; // no body availalbe
|
||||
}
|
||||
return VPackMessageNoOwnBuffer(VPackSlice(_header->data()),
|
||||
VPackSlice::noneSlice(), _messageId,
|
||||
_generateBody);
|
||||
} else {
|
||||
return VPackMessageNoOwnBuffer(VPackSlice(_header->data()),
|
||||
VPackSlice(_vpackPayloads.front().data()),
|
||||
_messageId, _generateBody);
|
||||
}
|
||||
}
|
||||
// void VppResponse::writeHeader(basics::StringBuffer*) {}
|
||||
|
|
|
@ -51,8 +51,6 @@ class VppResponse : public GeneralResponse {
|
|||
// required by base
|
||||
virtual uint64_t messageId() const override { return _messageId; }
|
||||
void reset(ResponseCode code) final;
|
||||
void setPayload(arangodb::velocypack::Slice const&, bool generateBody,
|
||||
arangodb::velocypack::Options const&) final;
|
||||
virtual arangodb::Endpoint::TransportType transportType() override {
|
||||
return arangodb::Endpoint::TransportType::VPP;
|
||||
};
|
||||
|
@ -65,7 +63,6 @@ class VppResponse : public GeneralResponse {
|
|||
std::shared_ptr<VPackBuffer<uint8_t>>
|
||||
_header; // generated form _headers when prepared for network
|
||||
uint64_t _messageId;
|
||||
bool _generateBody; // this must be true if payload should be send
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue