diff --git a/arangod/Replication/Syncer.cpp b/arangod/Replication/Syncer.cpp index 2c8d2b165b..cd5bc9e3bb 100644 --- a/arangod/Replication/Syncer.cpp +++ b/arangod/Replication/Syncer.cpp @@ -351,6 +351,7 @@ int Syncer::applyCollectionDumpMarker( OperationOptions options; options.silent = true; options.ignoreRevs = true; + options.isRestore = true; try { // try insert first diff --git a/arangod/VocBase/document-collection.cpp b/arangod/VocBase/document-collection.cpp index 6883f95032..e82980cd85 100644 --- a/arangod/VocBase/document-collection.cpp +++ b/arangod/VocBase/document-collection.cpp @@ -3381,7 +3381,18 @@ int TRI_document_collection_t::update(Transaction* trx, mptr->setDataPtr(nullptr); prevRev = VPackSlice(); - TRI_voc_rid_t revisionId = TRI_NewTickServer(); + TRI_voc_rid_t revisionId = 0; + if (options.isRestore) { + VPackSlice oldRev = TRI_ExtractRevisionIdAsSlice(newSlice); + if (!oldRev.isString()) { + return TRI_ERROR_ARANGO_DOCUMENT_REV_BAD; + } + VPackValueLength length; + char const* p = oldRev.getString(length); + revisionId = arangodb::basics::StringUtils::uint64(p, length); + } else { + revisionId = TRI_NewTickServer(); + } TRI_voc_tick_t markerTick = 0; int res; @@ -3518,7 +3529,18 @@ int TRI_document_collection_t::replace(Transaction* trx, TRI_ASSERT(mptr != nullptr); mptr->setDataPtr(nullptr); - TRI_voc_rid_t revisionId = TRI_NewTickServer(); + TRI_voc_rid_t revisionId = 0; + if (options.isRestore) { + VPackSlice oldRev = TRI_ExtractRevisionIdAsSlice(newSlice); + if (!oldRev.isString()) { + return TRI_ERROR_ARANGO_DOCUMENT_REV_BAD; + } + VPackValueLength length; + char const* p = oldRev.getString(length); + revisionId = arangodb::basics::StringUtils::uint64(p, length); + } else { + revisionId = TRI_NewTickServer(); + } TRI_voc_tick_t markerTick = 0; int res; @@ -4107,8 +4129,20 @@ int TRI_document_collection_t::newObjectForInsert( DatafileHelper::StoreNumber(p, _info.id(), sizeof(uint64_t)); } VPackSlice s = value.get(TRI_VOC_ATTRIBUTE_KEY); - TRI_voc_tick_t const newRev = TRI_NewTickServer(); + TRI_voc_rid_t newRev = 0; + std::string newRevSt; + if (isRestore) { + VPackSlice oldRev = TRI_ExtractRevisionIdAsSlice(value); + if (!oldRev.isString()) { + return TRI_ERROR_ARANGO_DOCUMENT_REV_BAD; + } + newRevSt = oldRev.copyString(); + } else { + newRev = TRI_NewTickServer(); + newRevSt = std::to_string(newRev); + } if (s.isNone()) { + TRI_ASSERT(!isRestore); // need key in case of restore std::string keyString = _keyGenerator->generate(newRev); if (keyString.empty()) { return TRI_ERROR_ARANGO_OUT_OF_KEYS; @@ -4129,8 +4163,7 @@ int TRI_document_collection_t::newObjectForInsert( // we can get away with the fast hash function here, as key values are // restricted to strings hash = s.hash(); - std::string rev = std::to_string(newRev); - builder.add(TRI_VOC_ATTRIBUTE_REV, VPackValue(rev)); + builder.add(TRI_VOC_ATTRIBUTE_REV, VPackValue(newRevSt)); } return TRI_ERROR_NO_ERROR; } diff --git a/js/common/bootstrap/errors.js b/js/common/bootstrap/errors.js index f80872afd1..3b4c397a7b 100644 --- a/js/common/bootstrap/errors.js +++ b/js/common/bootstrap/errors.js @@ -103,6 +103,7 @@ "ERROR_ARANGO_WRITE_THROTTLE_TIMEOUT" : { "code" : 1236, "message" : "write-throttling timeout" }, "ERROR_ARANGO_COLLECTION_TYPE_MISMATCH" : { "code" : 1237, "message" : "collection type mismatch" }, "ERROR_ARANGO_COLLECTION_NOT_LOADED" : { "code" : 1238, "message" : "collection not loaded" }, + "ERROR_ARANGO_DOCUMENT_REV_BAD" : { "code" : 1239, "message" : "illegal document revision" }, "ERROR_ARANGO_DATAFILE_FULL" : { "code" : 1300, "message" : "datafile full" }, "ERROR_ARANGO_EMPTY_DATADIR" : { "code" : 1301, "message" : "server database directory is empty" }, "ERROR_REPLICATION_NO_RESPONSE" : { "code" : 1400, "message" : "no response" }, diff --git a/lib/Basics/errors.dat b/lib/Basics/errors.dat index 04983ef3ac..6ad720479a 100755 --- a/lib/Basics/errors.dat +++ b/lib/Basics/errors.dat @@ -123,6 +123,7 @@ ERROR_ARANGO_INDEX_CREATION_FAILED,1235,"index creation failed","Will be raised ERROR_ARANGO_WRITE_THROTTLE_TIMEOUT,1236,"write-throttling timeout","Will be raised when the server is write-throttled and a write operation has waited too long for the server to process queued operations." ERROR_ARANGO_COLLECTION_TYPE_MISMATCH,1237,"collection type mismatch","Will be raised when a collection has a different type from what has been expected." ERROR_ARANGO_COLLECTION_NOT_LOADED,1238,"collection not loaded","Will be raised when a collection is accessed that is not yet loaded." +ERROR_ARANGO_DOCUMENT_REV_BAD,1239,"illegal document revision","Will be raised when a document revision is corrupt or is missing where needed." ################################################################################ ## ArangoDB storage errors diff --git a/lib/Basics/voc-errors.cpp b/lib/Basics/voc-errors.cpp index cdc4abe254..557144058a 100644 --- a/lib/Basics/voc-errors.cpp +++ b/lib/Basics/voc-errors.cpp @@ -99,6 +99,7 @@ void TRI_InitializeErrorMessages () { REG_ERROR(ERROR_ARANGO_WRITE_THROTTLE_TIMEOUT, "write-throttling timeout"); REG_ERROR(ERROR_ARANGO_COLLECTION_TYPE_MISMATCH, "collection type mismatch"); REG_ERROR(ERROR_ARANGO_COLLECTION_NOT_LOADED, "collection not loaded"); + REG_ERROR(ERROR_ARANGO_DOCUMENT_REV_BAD, "illegal document revision"); REG_ERROR(ERROR_ARANGO_DATAFILE_FULL, "datafile full"); REG_ERROR(ERROR_ARANGO_EMPTY_DATADIR, "server database directory is empty"); REG_ERROR(ERROR_REPLICATION_NO_RESPONSE, "no response"); diff --git a/lib/Basics/voc-errors.h b/lib/Basics/voc-errors.h index 888da0d59b..3371082ebe 100644 --- a/lib/Basics/voc-errors.h +++ b/lib/Basics/voc-errors.h @@ -219,6 +219,9 @@ /// expected. /// - 1238: @LIT{collection not loaded} /// Will be raised when a collection is accessed that is not yet loaded. +/// - 1239: @LIT{illegal document revision} +/// Will be raised when a document revision is corrupt or is missing where +/// needed. /// - 1300: @LIT{datafile full} /// Will be raised when the datafile reaches its limit. /// - 1301: @LIT{server database directory is empty} @@ -1586,6 +1589,17 @@ void TRI_InitializeErrorMessages (); #define TRI_ERROR_ARANGO_COLLECTION_NOT_LOADED (1238) +//////////////////////////////////////////////////////////////////////////////// +/// @brief 1239: ERROR_ARANGO_DOCUMENT_REV_BAD +/// +/// illegal document revision +/// +/// Will be raised when a document revision is corrupt or is missing where +/// needed. +//////////////////////////////////////////////////////////////////////////////// + +#define TRI_ERROR_ARANGO_DOCUMENT_REV_BAD (1239) + //////////////////////////////////////////////////////////////////////////////// /// @brief 1300: ERROR_ARANGO_DATAFILE_FULL ///