diff options
author | Tor Brede Vekterli <vekterli@oath.com> | 2018-11-26 13:51:12 +0000 |
---|---|---|
committer | Tor Brede Vekterli <vekterli@oath.com> | 2018-11-26 14:12:23 +0000 |
commit | b71cc013e878e4a12ee3ce6c7434424fcb7f204b (patch) | |
tree | 7986f84c321d3607b9f9389213fb9bd2c7a94dd5 /persistence | |
parent | 9871bb9e867198d767386d35a3842a2da8fc7dfb (diff) |
Support test-and-set for auto-create document updates
Has the obvious consistency caveats that if all your existing replicas are
down, the update will go through since the document from an weak consistency
perspective does not exist anywhere. But can be a useful feature if this
is an acceptable tradeoff.
Diffstat (limited to 'persistence')
-rw-r--r-- | persistence/src/vespa/persistence/conformancetest/conformancetest.cpp | 27 | ||||
-rw-r--r-- | persistence/src/vespa/persistence/spi/abstractpersistenceprovider.cpp | 20 |
2 files changed, 40 insertions, 7 deletions
diff --git a/persistence/src/vespa/persistence/conformancetest/conformancetest.cpp b/persistence/src/vespa/persistence/conformancetest/conformancetest.cpp index c1373a391f0..4d9d48c4926 100644 --- a/persistence/src/vespa/persistence/conformancetest/conformancetest.cpp +++ b/persistence/src/vespa/persistence/conformancetest/conformancetest.cpp @@ -948,7 +948,6 @@ void ConformanceTest::testUpdate() { CPPUNIT_ASSERT(!result.hasDocument()); } - { UpdateResult result = spi->update(bucket, Timestamp(6), update, context); @@ -957,6 +956,32 @@ void ConformanceTest::testUpdate() { CPPUNIT_ASSERT_EQUAL(Result::NONE, result.getErrorCode()); CPPUNIT_ASSERT_EQUAL(Timestamp(0), result.getExistingTimestamp()); } + + { + GetResult result = spi->get(bucket, document::AllFields(), doc1->getId(), context); + CPPUNIT_ASSERT_EQUAL(Result::NONE, result.getErrorCode()); + CPPUNIT_ASSERT_EQUAL(Timestamp(0), result.getTimestamp()); + CPPUNIT_ASSERT(!result.hasDocument()); + } + + update->setCreateIfNonExistent(true); + { + // Document does not exist (and therefore its condition cannot match by definition), + // but since CreateIfNonExistent is set it should be auto-created anyway. + UpdateResult result = spi->update(bucket, Timestamp(7), update, context); + spi->flush(bucket, context); + CPPUNIT_ASSERT_EQUAL(Result::NONE, result.getErrorCode()); + CPPUNIT_ASSERT_EQUAL(Timestamp(7), result.getExistingTimestamp()); + } + + { + GetResult result = spi->get(bucket, document::AllFields(), doc1->getId(), context); + CPPUNIT_ASSERT_EQUAL(Result::NONE, result.getErrorCode()); + CPPUNIT_ASSERT_EQUAL(Timestamp(7), result.getTimestamp()); + CPPUNIT_ASSERT_EQUAL(document::IntFieldValue(42), + reinterpret_cast<document::IntFieldValue&>( + *result.getDocument().getValue("headerval"))); + } } void ConformanceTest::testGet() { diff --git a/persistence/src/vespa/persistence/spi/abstractpersistenceprovider.cpp b/persistence/src/vespa/persistence/spi/abstractpersistenceprovider.cpp index 5e6e908e042..7f6bd835cd5 100644 --- a/persistence/src/vespa/persistence/spi/abstractpersistenceprovider.cpp +++ b/persistence/src/vespa/persistence/spi/abstractpersistenceprovider.cpp @@ -1,9 +1,10 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "abstractpersistenceprovider.h" +#include <vespa/document/datatype/documenttype.h> #include <vespa/document/update/documentupdate.h> #include <vespa/document/fieldset/fieldsets.h> - +#include <vespa/document/fieldvalue/document.h> namespace storage { @@ -19,20 +20,27 @@ AbstractPersistenceProvider::update(const Bucket& bucket, Timestamp ts, return UpdateResult(getResult.getErrorCode(), getResult.getErrorMessage()); } - if (!getResult.hasDocument()) { - return UpdateResult(); + auto docToUpdate = getResult.getDocumentPtr(); + Timestamp updatedTs = getResult.getTimestamp(); + if (!docToUpdate) { + if (!upd->getCreateIfNonExistent()) { + return UpdateResult(); + } else { + docToUpdate = std::make_shared<document::Document>(upd->getType(), upd->getId()); + updatedTs = ts; + } } - upd->applyTo(getResult.getDocument()); + upd->applyTo(*docToUpdate); - Result putResult = put(bucket, ts, getResult.getDocumentPtr(), context); + Result putResult = put(bucket, ts, docToUpdate, context); if (putResult.hasError()) { return UpdateResult(putResult.getErrorCode(), putResult.getErrorMessage()); } - return UpdateResult(getResult.getTimestamp()); + return UpdateResult(updatedTs); } RemoveResult |