diff --git a/arangod/Utils/Transaction.cpp b/arangod/Utils/Transaction.cpp index 6567f50d68..b5edbfded9 100644 --- a/arangod/Utils/Transaction.cpp +++ b/arangod/Utils/Transaction.cpp @@ -457,8 +457,62 @@ OperationResult Transaction::documentCoordinator(std::string const& collectionNa OperationResult Transaction::documentLocal(std::string const& collectionName, VPackSlice const& value, OperationOptions const& options) { - // TODO - THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED); + TRI_voc_cid_t cid = resolver()->getCollectionId(collectionName); + + if (cid == 0) { + return OperationResult(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND); + } + + std::string key; + TRI_voc_rid_t expectedRevision = 0; + + // extract _key + if (value.isObject()) { + VPackSlice k = value.get(TRI_VOC_ATTRIBUTE_KEY); + if (!k.isString()) { + return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD); + } + key = k.copyString(); + + // extract _rev + VPackSlice r = value.get(TRI_VOC_ATTRIBUTE_REV); + if (!r.isNone()) { + if (r.isString()) { + expectedRevision = arangodb::basics::StringUtils::uint64(r.copyString()); + } + else if (r.isInteger()) { + expectedRevision = r.getNumber(); + } + } + } else if (value.isString()) { + key = value.copyString(); + } else { + return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD); + } + + // TODO: clean this up + TRI_document_collection_t* document = documentCollection(trxCollection(cid)); + + if (orderDitch(trxCollection(cid)) == nullptr) { + return OperationResult(TRI_ERROR_OUT_OF_MEMORY); + } + + TRI_doc_mptr_copy_t mptr; + int res = document->read(this, key, &mptr, !isLocked(document, TRI_TRANSACTION_READ)); + + if (res != TRI_ERROR_NO_ERROR) { + return OperationResult(res); + } + + TRI_ASSERT(mptr.getDataPtr() != nullptr); + if (expectedRevision != 0 && expectedRevision != mptr._rid) { + return OperationResult(TRI_ERROR_ARANGO_CONFLICT); + } + + VPackBuilder resultBuilder; + resultBuilder.add(VPackValue(mptr.vpack())); + + return OperationResult(TRI_ERROR_NO_ERROR, resultBuilder.steal()); } ////////////////////////////////////////////////////////////////////////////// @@ -558,6 +612,10 @@ OperationResult Transaction::insertLocal(std::string const& collectionName, VPackBuilder toInsert = VPackCollection::merge(value, merge.slice(), false, false); VPackSlice insertSlice = toInsert.slice(); + + if (orderDitch(trxCollection(cid)) == nullptr) { + return OperationResult(TRI_ERROR_OUT_OF_MEMORY); + } TRI_doc_mptr_copy_t mptr; int res = document->insert(this, &insertSlice, &mptr, !isLocked(document, TRI_TRANSACTION_WRITE), options.waitForSync); diff --git a/arangod/VocBase/document-collection.cpp b/arangod/VocBase/document-collection.cpp index 98ab1cd9f8..1dfb38df29 100644 --- a/arangod/VocBase/document-collection.cpp +++ b/arangod/VocBase/document-collection.cpp @@ -4733,8 +4733,7 @@ TRI_ASSERT(false); *mptr = *header; } - TRI_ASSERT(mptr->getDataPtr() != - nullptr); // PROTECTED by trx in trxCollection + TRI_ASSERT(mptr->getDataPtr() != nullptr); TRI_ASSERT(mptr->_rid > 0); return TRI_ERROR_NO_ERROR; @@ -5121,7 +5120,7 @@ int TRI_document_collection_t::read(Transaction* trx, std::string const& key, CollectionReadLocker collectionLocker(this, lock); TRI_doc_mptr_t* header; - int res = lookupDocument(trx, &slice, nullptr /* policy */, header); + int res = lookupDocument(trx, &slice, nullptr, header); if (res != TRI_ERROR_NO_ERROR) { return res; @@ -5131,9 +5130,8 @@ int TRI_document_collection_t::read(Transaction* trx, std::string const& key, *mptr = *header; } - TRI_ASSERT(mptr->getDataPtr() != - nullptr); // PROTECTED by trx in trxCollection - // TRI_ASSERT(mptr->_rid > 0); + TRI_ASSERT(mptr->getDataPtr() != nullptr); + TRI_ASSERT(mptr->_rid > 0); return TRI_ERROR_NO_ERROR; } @@ -5151,6 +5149,17 @@ int TRI_document_collection_t::insert(Transaction* trx, VPackSlice const* slice, VPackSlice const key(slice->get(TRI_VOC_ATTRIBUTE_KEY)); uint64_t const hash = key.hash(); + + TRI_voc_rid_t revision = 0; + { + VPackSlice r(slice->get(TRI_VOC_ATTRIBUTE_REV)); + if (r.isString()) { + revision = arangodb::basics::StringUtils::uint64(r.copyString()); + } + else if (r.isInteger()) { + revision = r.getNumber(); + } + } std::unique_ptr marker( createVPackInsertMarker(trx, slice)); @@ -5190,7 +5199,7 @@ int TRI_document_collection_t::insert(Transaction* trx, VPackSlice const* slice, // update the header we got void* mem = operation.marker->mem(); - // header->_rid = rid; // TODO + header->_rid = revision; header->_hash = hash; header->setDataPtr(mem); // PROTECTED by trx in trxCollection