mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'spdvpk' of https://github.com/arangodb/arangodb into spdvpk
This commit is contained in:
commit
5b3b7e673b
|
@ -253,8 +253,9 @@ class Builder {
|
|||
std::shared_ptr<Buffer<uint8_t>> const& buffer() const { return _buffer; }
|
||||
|
||||
std::shared_ptr<Buffer<uint8_t>> steal() {
|
||||
std::shared_ptr<Buffer<uint8_t>> res = std::move(_buffer);
|
||||
_buffer.reset(new Buffer<uint8_t>());
|
||||
// After a steal the Builder is broken!
|
||||
std::shared_ptr<Buffer<uint8_t>> res = _buffer;
|
||||
_buffer.reset();
|
||||
_pos = 0;
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -164,8 +164,9 @@ class Parser {
|
|||
// Not with this high-performance two-pass approach. :-(
|
||||
|
||||
std::shared_ptr<Builder> steal() {
|
||||
// Parser object is broken after a steal()
|
||||
std::shared_ptr<Builder> res(_b);
|
||||
_b.reset(new Builder());
|
||||
_b.reset();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -253,9 +253,15 @@ bool RestDocumentHandler::readSingleDocument(bool generateBody) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (ServerState::instance()->isCoordinator()) {
|
||||
return getDocumentCoordinator(collection, key, generateBody);
|
||||
VPackBuilder builder;
|
||||
{
|
||||
VPackObjectBuilder guard(&builder);
|
||||
builder.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(key));
|
||||
if (ifRid != 0) {
|
||||
builder.add(TRI_VOC_ATTRIBUTE_REV, VPackValue(ifRid));
|
||||
}
|
||||
}
|
||||
VPackSlice search = builder.slice();
|
||||
|
||||
// find and load collection given by name or identifier
|
||||
SingleCollectionReadOnlyTransaction trx(new StandaloneTransactionContext(),
|
||||
|
@ -266,67 +272,44 @@ bool RestDocumentHandler::readSingleDocument(bool generateBody) {
|
|||
// .............................................................................
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
generateTransactionError(collection, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
TRI_voc_cid_t const cid = trx.cid();
|
||||
// If we are a DBserver, we want to use the cluster-wide collection
|
||||
// name for error reporting:
|
||||
std::string collectionName = collection;
|
||||
if (ServerState::instance()->isDBServer()) {
|
||||
collectionName = trx.resolver()->getCollectionName(cid);
|
||||
OperationOptions options;
|
||||
OperationResult result = trx.document(collection, search, options);
|
||||
|
||||
res = trx.finish(result.code);
|
||||
|
||||
if(!result.successful()) {
|
||||
if (result.code == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) {
|
||||
generateDocumentNotFound(collection, (TRI_voc_key_t)key.c_str());
|
||||
return false;
|
||||
} else if (ifRid != 0 && result.code == TRI_ERROR_ARANGO_CONFLICT) {
|
||||
generatePreconditionFailed(result.slice());
|
||||
} else {
|
||||
generateTransactionError(collection, res, (TRI_voc_key_t)key.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
TRI_doc_mptr_copy_t mptr;
|
||||
|
||||
res = trx.document(trx.trxCollection(), &mptr, key);
|
||||
|
||||
TRI_document_collection_t* document = trx.documentCollection();
|
||||
TRI_ASSERT(document != nullptr);
|
||||
auto shaper = document->getShaper(); // PROTECTED by trx here
|
||||
|
||||
res = trx.finish(res);
|
||||
|
||||
// .............................................................................
|
||||
// outside read transaction
|
||||
// .............................................................................
|
||||
|
||||
TRI_ASSERT(trx.hasDitch());
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
generateTransactionError(collectionName, res, (TRI_voc_key_t)key.c_str());
|
||||
generateTransactionError(collection, res, (TRI_voc_key_t)key.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mptr.getDataPtr() == nullptr) { // PROTECTED by trx here
|
||||
generateDocumentNotFound(trx, cid, (TRI_voc_key_t)key.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// generate result
|
||||
TRI_voc_rid_t const rid = mptr._rid;
|
||||
|
||||
if (ifNoneRid == 0) {
|
||||
if (ifRid == 0 || ifRid == rid) {
|
||||
generateDocument(trx, cid, mptr, shaper, generateBody);
|
||||
} else {
|
||||
generatePreconditionFailed(trx, cid, mptr, rid);
|
||||
}
|
||||
} else if (ifNoneRid == rid) {
|
||||
if (ifRid == 0 || ifRid == rid) {
|
||||
generateNotModified(rid);
|
||||
} else {
|
||||
generatePreconditionFailed(trx, cid, mptr, rid);
|
||||
}
|
||||
TRI_voc_rid_t const rid =
|
||||
VelocyPackHelper::getNumericValue<TRI_voc_rid_t>(
|
||||
result.slice(), TRI_VOC_ATTRIBUTE_REV, 0);
|
||||
if (ifNoneRid != 0 && ifNoneRid == rid) {
|
||||
generateNotModified(rid);
|
||||
} else {
|
||||
if (ifRid == 0 || ifRid == rid) {
|
||||
generateDocument(trx, cid, mptr, shaper, generateBody);
|
||||
} else {
|
||||
generatePreconditionFailed(trx, cid, mptr, rid);
|
||||
}
|
||||
VPackOptions options = VPackOptions::Defaults;
|
||||
options.customTypeHandler = result.customTypeHandler;
|
||||
generateDocument(result.slice(), generateBody, &options);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -287,6 +287,48 @@ void RestVocbaseBaseHandler::generateForbidden() {
|
|||
"operation forbidden");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates precondition failed
|
||||
/// DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RestVocbaseBaseHandler::generatePreconditionFailed(
|
||||
VPackSlice const& slice) {
|
||||
TRI_ASSERT(slice.isObject());
|
||||
TRI_ASSERT(slice.hasKey(TRI_VOC_ATTRIBUTE_ID));
|
||||
TRI_ASSERT(slice.hasKey(TRI_VOC_ATTRIBUTE_REV));
|
||||
TRI_ASSERT(slice.hasKey(TRI_VOC_ATTRIBUTE_KEY));
|
||||
|
||||
createResponse(HttpResponse::PRECONDITION_FAILED);
|
||||
_response->setContentType("application/json; charset=utf-8");
|
||||
std::string rev = VelocyPackHelper::getStringValue(slice, TRI_VOC_ATTRIBUTE_REV, "");
|
||||
_response->setHeader("etag", 4, "\"" + rev + "\"");
|
||||
VPackBuilder builder;
|
||||
{
|
||||
VPackObjectBuilder guard(&builder);
|
||||
// _id and _key are safe and do not need to be JSON-encoded
|
||||
builder.add("error", VPackValue(true));
|
||||
builder.add(
|
||||
"code",
|
||||
VPackValue(static_cast<int32_t>(HttpResponse::PRECONDITION_FAILED)));
|
||||
builder.add("errorNum", VPackValue(TRI_ERROR_ARANGO_CONFLICT));
|
||||
builder.add("errorMessage", VPackValue("precondition failed"));
|
||||
builder.add(TRI_VOC_ATTRIBUTE_ID, slice.get(TRI_VOC_ATTRIBUTE_ID));
|
||||
builder.add(TRI_VOC_ATTRIBUTE_KEY, slice.get(TRI_VOC_ATTRIBUTE_KEY));
|
||||
builder.add(TRI_VOC_ATTRIBUTE_REV, slice.get(TRI_VOC_ATTRIBUTE_REV));
|
||||
}
|
||||
|
||||
VPackStringBufferAdapter buffer(_response->body().stringBuffer());
|
||||
VPackDumper dumper(&buffer);
|
||||
|
||||
try {
|
||||
dumper.dump(builder.slice());
|
||||
} catch (...) {
|
||||
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
||||
"cannot generate output");
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates precondition failed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -315,6 +357,8 @@ void RestVocbaseBaseHandler::generatePreconditionFailed(
|
|||
.appendText("\"}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates not modified
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -328,6 +372,7 @@ void RestVocbaseBaseHandler::generateNotModified(TRI_voc_rid_t rid) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates next entry from a result set
|
||||
/// DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RestVocbaseBaseHandler::generateDocument(
|
||||
|
@ -421,6 +466,53 @@ void RestVocbaseBaseHandler::generateDocument(
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates next entry from a result set
|
||||
/// DEPRECATED
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RestVocbaseBaseHandler::generateDocument(VPackSlice const& document,
|
||||
bool generateBody,
|
||||
VPackOptions const* options) {
|
||||
TRI_ASSERT(document.isObject());
|
||||
TRI_ASSERT(document.hasKey(TRI_VOC_ATTRIBUTE_REV));
|
||||
|
||||
std::string rev = VelocyPackHelper::getStringValue(document, TRI_VOC_ATTRIBUTE_REV, "");
|
||||
|
||||
// and generate a response
|
||||
createResponse(HttpResponse::OK);
|
||||
_response->setContentType("application/json; charset=utf-8");
|
||||
_response->setHeader("etag", 4, "\"" + rev + "\"");
|
||||
|
||||
if (generateBody) {
|
||||
VPackStringBufferAdapter buffer(_response->body().stringBuffer());
|
||||
VPackDumper dumper(&buffer, options);
|
||||
try {
|
||||
dumper.dump(document);
|
||||
} catch (...) {
|
||||
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
||||
"cannot generate output");
|
||||
}
|
||||
} else {
|
||||
// TODO can we optimize this?
|
||||
// Just dump some where else to find real length
|
||||
TRI_string_buffer_t tmpBuffer;
|
||||
// convert object to string
|
||||
TRI_InitStringBuffer(&tmpBuffer, TRI_UNKNOWN_MEM_ZONE);
|
||||
|
||||
VPackStringBufferAdapter buffer(&tmpBuffer);
|
||||
VPackDumper dumper(&buffer, options);
|
||||
try {
|
||||
dumper.dump(document);
|
||||
} catch (...) {
|
||||
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
||||
"cannot generate output");
|
||||
}
|
||||
_response->headResponse(TRI_LengthStringBuffer(&tmpBuffer));
|
||||
TRI_DestroyStringBuffer(&tmpBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate an error message for a transaction error
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -282,11 +282,18 @@ class RestVocbaseBaseHandler : public RestBaseHandler {
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates precondition failed, without transaction info
|
||||
/// DEPRECATED
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void generatePreconditionFailed(std::string const&, TRI_voc_key_t key,
|
||||
TRI_voc_rid_t rid);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates precondition failed, without transaction info
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void generatePreconditionFailed(arangodb::velocypack::Slice const& slice);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates not modified
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -295,11 +302,19 @@ class RestVocbaseBaseHandler : public RestBaseHandler {
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates first entry from a result set
|
||||
/// DEPRECATED
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void generateDocument(SingleCollectionReadOnlyTransaction& trx, TRI_voc_cid_t,
|
||||
TRI_doc_mptr_copy_t const&, VocShaper*, bool);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates first entry from a result set
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void generateDocument(arangodb::velocypack::Slice const&, bool,
|
||||
arangodb::velocypack::Options const* options = nullptr);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate an error message for a transaction error
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -34,12 +34,28 @@
|
|||
namespace arangodb {
|
||||
|
||||
struct OperationResult {
|
||||
OperationResult() : buffer(), customTypeHandler(nullptr), code(TRI_ERROR_NO_ERROR), wasSynchronous(false) {}
|
||||
OperationResult(std::shared_ptr<VPackBuffer<uint8_t>> buffer, VPackCustomTypeHandler* handler) : buffer(buffer), customTypeHandler(handler), code(TRI_ERROR_NO_ERROR), wasSynchronous(false) {}
|
||||
OperationResult(int code, std::shared_ptr<VPackBuffer<uint8_t>> buffer) : buffer(buffer), customTypeHandler(nullptr), code(code), wasSynchronous(false) {}
|
||||
OperationResult(std::shared_ptr<VPackBuffer<uint8_t>> buffer, bool wasSynchronous) : buffer(buffer), customTypeHandler(nullptr), code(TRI_ERROR_NO_ERROR), wasSynchronous(wasSynchronous) {}
|
||||
explicit OperationResult(std::shared_ptr<VPackBuffer<uint8_t>> buffer) : OperationResult(TRI_ERROR_NO_ERROR, buffer) {}
|
||||
explicit OperationResult(int code) : OperationResult(code, nullptr) { }
|
||||
|
||||
explicit OperationResult(int code)
|
||||
: customTypeHandler(nullptr), code(code), wasSynchronous(false) {
|
||||
if (code != TRI_ERROR_NO_ERROR) {
|
||||
errorMessage = TRI_errno_string(code);
|
||||
}
|
||||
}
|
||||
|
||||
OperationResult(int code, std::string const& message)
|
||||
: customTypeHandler(nullptr), errorMessage(message), code(code),
|
||||
wasSynchronous(false) {
|
||||
TRI_ASSERT(code != TRI_ERROR_NO_ERROR);
|
||||
}
|
||||
|
||||
OperationResult(std::shared_ptr<VPackBuffer<uint8_t>> buffer,
|
||||
VPackCustomTypeHandler* handler,
|
||||
std::string const& message,
|
||||
int code,
|
||||
bool wasSynchronous)
|
||||
: buffer(buffer), customTypeHandler(handler), errorMessage(message),
|
||||
code(code), wasSynchronous(wasSynchronous) {
|
||||
}
|
||||
|
||||
~OperationResult() {
|
||||
// TODO: handle destruction of customTypeHandler
|
||||
|
@ -60,6 +76,7 @@ struct OperationResult {
|
|||
|
||||
std::shared_ptr<VPackBuffer<uint8_t>> buffer;
|
||||
VPackCustomTypeHandler* customTypeHandler;
|
||||
std::string errorMessage;
|
||||
int code;
|
||||
bool wasSynchronous;
|
||||
};
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "Indexes/PrimaryIndex.h"
|
||||
#include "Storage/Marker.h"
|
||||
#include "VocBase/KeyGenerator.h"
|
||||
#include "Cluster/ClusterMethods.h"
|
||||
|
||||
#include <velocypack/Builder.h>
|
||||
#include <velocypack/Collection.h>
|
||||
|
@ -522,7 +523,9 @@ OperationResult Transaction::documentLocal(std::string const& collectionName,
|
|||
resultBuilder.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(key));
|
||||
resultBuilder.close();
|
||||
|
||||
return OperationResult(TRI_ERROR_ARANGO_CONFLICT, resultBuilder.steal());
|
||||
return OperationResult(resultBuilder.steal(), nullptr, "",
|
||||
TRI_ERROR_ARANGO_CONFLICT,
|
||||
options.waitForSync || document->_info.waitForSync());
|
||||
}
|
||||
|
||||
VPackBuilder resultBuilder;
|
||||
|
@ -530,7 +533,7 @@ OperationResult Transaction::documentLocal(std::string const& collectionName,
|
|||
resultBuilder.add(VPackSlice(mptr.vpack()));
|
||||
}
|
||||
|
||||
return OperationResult(resultBuilder.steal(), StorageOptions::getCustomTypeHandler(_vocbase));
|
||||
return OperationResult(resultBuilder.steal(), StorageOptions::getCustomTypeHandler(_vocbase), "", TRI_ERROR_NO_ERROR, false);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -572,8 +575,31 @@ OperationResult Transaction::insert(std::string const& collectionName,
|
|||
OperationResult Transaction::insertCoordinator(std::string const& collectionName,
|
||||
VPackSlice const& value,
|
||||
OperationOptions& options) {
|
||||
// TODO
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
std::map<std::string, std::string> headers;
|
||||
arangodb::rest::HttpResponse::HttpResponseCode responseCode;
|
||||
std::map<std::string, std::string> resultHeaders;
|
||||
std::string resultBody;
|
||||
|
||||
int res = arangodb::createDocumentOnCoordinator(
|
||||
_vocbase->_name, collectionName, options.waitForSync,
|
||||
value, headers, responseCode, resultHeaders, resultBody);
|
||||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
VPackParser parser;
|
||||
try {
|
||||
parser.parse(resultBody);
|
||||
auto bui = parser.steal();
|
||||
auto buf = bui->steal();
|
||||
return OperationResult(buf, nullptr, "", TRI_ERROR_NO_ERROR,
|
||||
responseCode == arangodb::rest::HttpResponse::CREATED);
|
||||
}
|
||||
catch (VPackException& e) {
|
||||
std::string message = "JSON from DBserver not parseable: "
|
||||
+ resultBody + ":" + e.what();
|
||||
return OperationResult(TRI_ERROR_INTERNAL, message);
|
||||
}
|
||||
}
|
||||
return OperationResult(res);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -654,7 +680,8 @@ OperationResult Transaction::insertLocal(std::string const& collectionName,
|
|||
resultBuilder.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(resultKey));
|
||||
resultBuilder.close();
|
||||
|
||||
return OperationResult(resultBuilder.steal(), options.waitForSync);
|
||||
return OperationResult(resultBuilder.steal(), nullptr, "", TRI_ERROR_NO_ERROR,
|
||||
options.waitForSync || document->_info.waitForSync());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -790,7 +817,8 @@ OperationResult Transaction::updateLocal(std::string const& collectionName,
|
|||
resultBuilder.add("_oldRev", VPackValue(idString));
|
||||
resultBuilder.close();
|
||||
|
||||
return OperationResult(resultBuilder.steal(), options.waitForSync);
|
||||
return OperationResult(resultBuilder.steal(), nullptr, "", TRI_ERROR_NO_ERROR,
|
||||
options.waitForSync || document->_info.waitForSync());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1052,6 +1080,7 @@ OperationResult Transaction::removeLocal(std::string const& collectionName,
|
|||
resultBuilder.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(key));
|
||||
resultBuilder.close();
|
||||
|
||||
return OperationResult(resultBuilder.steal(), options.waitForSync);
|
||||
return OperationResult(resultBuilder.steal(), nullptr, "", TRI_ERROR_NO_ERROR,
|
||||
options.waitForSync || document->_info.waitForSync());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue