diff --git a/3rdParty/velocypack/include/velocypack/Options.h b/3rdParty/velocypack/include/velocypack/Options.h index a0b3088b38..796b2804fc 100644 --- a/3rdParty/velocypack/include/velocypack/Options.h +++ b/3rdParty/velocypack/include/velocypack/Options.h @@ -36,6 +36,7 @@ namespace arangodb { namespace velocypack { class AttributeTranslator; class Dumper; +class Options; class Slice; struct AttributeExcludeHandler { @@ -47,8 +48,12 @@ struct AttributeExcludeHandler { struct CustomTypeHandler { virtual ~CustomTypeHandler() {} - virtual void toJson(Slice const& value, Dumper* dumper, - Slice const& base) = 0; + virtual void dump(Slice const& value, Dumper* dumper, + Slice const& base) = 0; + + virtual std::string toString(Slice const& value, Options const* options, + Slice const& base) = 0; + }; struct Options { diff --git a/3rdParty/velocypack/include/velocypack/Slice.h b/3rdParty/velocypack/include/velocypack/Slice.h index b94f01961f..74f2d616c9 100644 --- a/3rdParty/velocypack/include/velocypack/Slice.h +++ b/3rdParty/velocypack/include/velocypack/Slice.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "velocypack/velocypack-common.h" diff --git a/3rdParty/velocypack/src/Dumper.cpp b/3rdParty/velocypack/src/Dumper.cpp index 7b7d38b92c..71e4e65ebf 100644 --- a/3rdParty/velocypack/src/Dumper.cpp +++ b/3rdParty/velocypack/src/Dumper.cpp @@ -433,7 +433,7 @@ void Dumper::dumpValue(Slice const* slice, Slice const* base) { if (options->customTypeHandler == nullptr) { handleUnsupportedType(slice); } else { - options->customTypeHandler->toJson(*slice, this, *base); + options->customTypeHandler->dump(*slice, this, *base); } break; } diff --git a/arangod/Storage/Options.cpp b/arangod/Storage/Options.cpp index 076321be60..90196fb0d5 100644 --- a/arangod/Storage/Options.cpp +++ b/arangod/Storage/Options.cpp @@ -23,6 +23,7 @@ #include "Options.h" #include "Basics/Exceptions.h" +#include "Storage/Marker.h" #include "Utils/CollectionNameResolver.h" #include "VocBase/vocbase.h" @@ -66,14 +67,14 @@ struct SystemAttributeExcludeHandler : public VPackAttributeExcludeHandler { // custom type value handler, used for deciphering the _id attribute -struct CustomIdTypeHandler : public VPackCustomTypeHandler { - explicit CustomIdTypeHandler(TRI_vocbase_t* vocbase) +struct CustomTypeHandler : public VPackCustomTypeHandler { + explicit CustomTypeHandler(TRI_vocbase_t* vocbase) : vocbase(vocbase), resolver(nullptr), ownsResolver(false) {} - CustomIdTypeHandler(TRI_vocbase_t* vocbase, CollectionNameResolver* resolver) + CustomTypeHandler(TRI_vocbase_t* vocbase, CollectionNameResolver* resolver) : vocbase(vocbase), resolver(resolver), ownsResolver(false) {} - ~CustomIdTypeHandler() { + ~CustomTypeHandler() { if (ownsResolver) { delete resolver; } @@ -87,9 +88,9 @@ struct CustomIdTypeHandler : public VPackCustomTypeHandler { return resolver; } - void toJson(VPackSlice const& value, VPackDumper* dumper, - VPackSlice const& base) override final { - if (value.head() != 0xf0) { + void dump(VPackSlice const& value, VPackDumper* dumper, + VPackSlice const& base) override final { + if (value.head() != 0xf3) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid custom type"); } @@ -99,7 +100,8 @@ struct CustomIdTypeHandler : public VPackCustomTypeHandler { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "invalid value type"); } - uint64_t cid = arangodb::velocypack::readUInt64(value.start() + 1); + + uint64_t cid = MarkerHelper::readNumber(value.begin() + 1, sizeof(uint64_t)); char buffer[512]; // This is enough for collection name + _key size_t len = getResolver()->getCollectionName(&buffer[0], cid); buffer[len] = '/'; @@ -114,6 +116,34 @@ struct CustomIdTypeHandler : public VPackCustomTypeHandler { memcpy(&buffer[len + 1], p, keyLength); dumper->appendString(&buffer[0], len + 1 + keyLength); } + + std::string toString(VPackSlice const& value, VPackOptions const* options, + VPackSlice const& base) override final { + if (value.head() != 0xf0) { + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, + "invalid custom type"); + } + + // _id + if (!base.isObject()) { + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, + "invalid value type"); + } + + uint64_t cid = MarkerHelper::readNumber(value.begin() + 1, sizeof(uint64_t)); + std::string result(getResolver()->getCollectionName(cid)); + result.push_back('/'); + VPackSlice key = base.get(TRI_VOC_ATTRIBUTE_KEY); + + VPackValueLength keyLength; + char const* p = key.getString(keyLength); + if (p == nullptr) { + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, + "invalid _key value"); + } + result.append(p, keyLength); + return result; + } TRI_vocbase_t* vocbase; CollectionNameResolver* resolver; @@ -156,6 +186,10 @@ void StorageOptions::initialize() { insertOptions->attributeExcludeHandler = excludeHandler.get(); } +VPackCustomTypeHandler* StorageOptions::getCustomTypeHandler(TRI_vocbase_t* vocbase) { + return new CustomTypeHandler(vocbase); +} + VPackAttributeTranslator const* StorageOptions::getTranslator() { return translator.get(); } diff --git a/arangod/Storage/Options.h b/arangod/Storage/Options.h index 79967b1e34..deeee83d7e 100644 --- a/arangod/Storage/Options.h +++ b/arangod/Storage/Options.h @@ -30,6 +30,8 @@ #include #include +struct TRI_vocbase_t; + namespace arangodb { namespace StorageOptions { @@ -38,6 +40,8 @@ namespace StorageOptions { VPackAttributeTranslator const* getTranslator(); VPackOptions const* getDefaultOptions(); VPackOptions const* getInsertOptions(); + + VPackCustomTypeHandler* getCustomTypeHandler(TRI_vocbase_t*); } } diff --git a/arangod/Utils/OperationResult.h b/arangod/Utils/OperationResult.h index 89965a0e32..55b5bb15ca 100644 --- a/arangod/Utils/OperationResult.h +++ b/arangod/Utils/OperationResult.h @@ -27,15 +27,23 @@ #include "Basics/Common.h" #include +#include #include #include namespace arangodb { struct OperationResult { - OperationResult() : buffer(), code(TRI_ERROR_NO_ERROR), wasSynchronous(false) {} - explicit OperationResult(int code) : buffer(), code(code), wasSynchronous(false) {} - OperationResult(int code, std::shared_ptr> buffer) : buffer(buffer), code(code), wasSynchronous(false) {} + OperationResult() : buffer(), customTypeHandler(nullptr), code(TRI_ERROR_NO_ERROR), wasSynchronous(false) {} + OperationResult(std::shared_ptr> buffer, VPackCustomTypeHandler* handler) : buffer(buffer), customTypeHandler(handler), code(TRI_ERROR_NO_ERROR), wasSynchronous(false) {} + OperationResult(int code, std::shared_ptr> buffer) : buffer(buffer), customTypeHandler(nullptr), code(code), wasSynchronous(false) {} + OperationResult(std::shared_ptr> buffer, bool wasSynchronous) : buffer(buffer), customTypeHandler(nullptr), code(TRI_ERROR_NO_ERROR), wasSynchronous(wasSynchronous) {} + explicit OperationResult(std::shared_ptr> buffer) : OperationResult(TRI_ERROR_NO_ERROR, buffer) {} + explicit OperationResult(int code) : OperationResult(code, nullptr) { } + + ~OperationResult() { + // TODO: handle destruction of customTypeHandler + } bool successful() const { return code == TRI_ERROR_NO_ERROR; @@ -51,6 +59,7 @@ struct OperationResult { } std::shared_ptr> buffer; + VPackCustomTypeHandler* customTypeHandler; int code; bool wasSynchronous; }; diff --git a/arangod/Utils/Transaction.cpp b/arangod/Utils/Transaction.cpp index cd042d02ee..dbef1675b0 100644 --- a/arangod/Utils/Transaction.cpp +++ b/arangod/Utils/Transaction.cpp @@ -514,7 +514,7 @@ OperationResult Transaction::documentLocal(std::string const& collectionName, resultBuilder.add(VPackValue(mptr.vpack())); } - return OperationResult(TRI_ERROR_NO_ERROR, resultBuilder.steal()); + return OperationResult(resultBuilder.steal(), StorageOptions::getCustomTypeHandler(_vocbase)); } ////////////////////////////////////////////////////////////////////////////// @@ -638,7 +638,7 @@ OperationResult Transaction::insertLocal(std::string const& collectionName, resultBuilder.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(resultKey)); resultBuilder.close(); - return OperationResult(TRI_ERROR_NO_ERROR, resultBuilder.steal()); + return OperationResult(resultBuilder.steal(), options.waitForSync); } OperationResult Transaction::replace(std::string const& collectionName, @@ -784,7 +784,7 @@ OperationResult Transaction::updateLocal(std::string const& collectionName, resultBuilder.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(resultKey)); resultBuilder.close(); - return OperationResult(TRI_ERROR_NO_ERROR, resultBuilder.steal()); + return OperationResult(resultBuilder.steal(), options.waitForSync); } ////////////////////////////////////////////////////////////////////////////// @@ -896,6 +896,6 @@ OperationResult Transaction::removeLocal(std::string const& collectionName, resultBuilder.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(key)); resultBuilder.close(); - return OperationResult(TRI_ERROR_NO_ERROR, resultBuilder.steal()); + return OperationResult(resultBuilder.steal(), options.waitForSync); }