aboutsummaryrefslogtreecommitdiffstats
path: root/storage/src/vespa/storage/persistence/asynchandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/src/vespa/storage/persistence/asynchandler.cpp')
-rw-r--r--storage/src/vespa/storage/persistence/asynchandler.cpp66
1 files changed, 43 insertions, 23 deletions
diff --git a/storage/src/vespa/storage/persistence/asynchandler.cpp b/storage/src/vespa/storage/persistence/asynchandler.cpp
index e20c0475556..85a13f5f0db 100644
--- a/storage/src/vespa/storage/persistence/asynchandler.cpp
+++ b/storage/src/vespa/storage/persistence/asynchandler.cpp
@@ -115,7 +115,7 @@ bucketStatesAreSemanticallyEqual(const api::BucketInfo& a, const api::BucketInfo
class UnrevertableRemoveEntryProcessor : public BucketProcessor::EntryProcessor {
public:
using DocumentIdsAndTimeStamps = std::vector<spi::IdAndTimestamp>;
- UnrevertableRemoveEntryProcessor(DocumentIdsAndTimeStamps & to_remove)
+ explicit UnrevertableRemoveEntryProcessor(DocumentIdsAndTimeStamps& to_remove) noexcept
: _to_remove(to_remove)
{}
@@ -159,11 +159,15 @@ AsyncHandler::handlePut(api::PutCommand& cmd, MessageTracker::UP trackerUP) cons
tracker.setMetric(metrics);
metrics.request_size.addValue(cmd.getApproxByteSize());
- if (tasConditionExists(cmd) && !tasConditionMatches(cmd, tracker, tracker.context())) {
- // Will also count condition parse failures etc as TaS failures, but
- // those results _will_ increase the error metrics as well.
- metrics.test_and_set_failed.inc();
- return trackerUP;
+ if (tasConditionExists(cmd)) {
+ auto tas_res = tasConditionMatches(cmd, tracker, tracker.context(), DocNotFoundPolicy::ReturnTaSError);
+ if (tas_res == TasResult::FailedAndSetInTracker) {
+ // Will also count condition parse failures etc. as TaS failures, but
+ // those results _will_ increase the error metrics as well.
+ metrics.test_and_set_failed.inc();
+ return trackerUP;
+ }
+ assert(tas_res == TasResult::Matched); // NotFound treated as failure for Puts
}
spi::Bucket bucket = _env.getBucket(cmd.getDocumentId(), cmd.getBucket());
@@ -283,9 +287,19 @@ AsyncHandler::handleUpdate(api::UpdateCommand& cmd, MessageTracker::UP trackerUP
tracker.setMetric(metrics);
metrics.request_size.addValue(cmd.getApproxByteSize());
- if (tasConditionExists(cmd) && !tasConditionMatches(cmd, tracker, tracker.context(), cmd.getUpdate()->getCreateIfNonExistent())) {
- metrics.test_and_set_failed.inc();
- return trackerUP;
+ if (tasConditionExists(cmd)) {
+ const bool create_missing = cmd.getUpdate()->getCreateIfNonExistent();
+ const auto not_found_policy = (create_missing ? DocNotFoundPolicy::TreatAsMatch : DocNotFoundPolicy::ReturnNotFound);
+ auto tas_res = tasConditionMatches(cmd, tracker, tracker.context(), not_found_policy);
+ if (tas_res == TasResult::FailedAndSetInTracker) {
+ metrics.test_and_set_failed.inc();
+ return trackerUP;
+ } else if (tas_res == TasResult::NotFound) {
+ metrics.notFound.inc();
+ tracker.setReply(std::make_shared<api::UpdateReply>(cmd, 0)); // Zero-timestamp == not found
+ return trackerUP;
+ }
+ assert(tas_res == TasResult::Matched);
}
spi::Bucket bucket = _env.getBucket(cmd.getDocumentId(), cmd.getBucket());
@@ -313,9 +327,13 @@ AsyncHandler::handleRemove(api::RemoveCommand& cmd, MessageTracker::UP trackerUP
tracker.setMetric(metrics);
metrics.request_size.addValue(cmd.getApproxByteSize());
- if (tasConditionExists(cmd) && !tasConditionMatches(cmd, tracker, tracker.context())) {
- metrics.test_and_set_failed.inc();
- return trackerUP;
+ if (tasConditionExists(cmd)) {
+ auto tas_res = tasConditionMatches(cmd, tracker, tracker.context(), DocNotFoundPolicy::ReturnTaSError);
+ if (tas_res == TasResult::FailedAndSetInTracker) {
+ metrics.test_and_set_failed.inc();
+ return trackerUP;
+ }
+ assert(tas_res == TasResult::Matched); // NotFound treated as failure for Removes
}
spi::Bucket bucket = _env.getBucket(cmd.getDocumentId(), cmd.getBucket());
@@ -354,24 +372,26 @@ AsyncHandler::tasConditionExists(const api::TestAndSetCommand & cmd) {
return cmd.getCondition().isPresent();
}
-bool
-AsyncHandler::tasConditionMatches(const api::TestAndSetCommand & cmd, MessageTracker & tracker,
- spi::Context & context, bool missingDocumentImpliesMatch) const {
+AsyncHandler::TasResult
+AsyncHandler::tasConditionMatches(const api::TestAndSetCommand& cmd, MessageTracker& tracker,
+ spi::Context& context, DocNotFoundPolicy doc_not_found_policy) const {
try {
- TestAndSetHelper helper(_env, _spi, _bucketIdFactory, cmd, missingDocumentImpliesMatch);
-
- auto code = helper.retrieveAndMatch(context);
- if (code.failed()) {
- tracker.fail(code.getResult(), code.getMessage());
- return false;
+ TestAndSetHelper helper(_env, _spi, _bucketIdFactory, cmd, doc_not_found_policy);
+
+ auto maybe_code = helper.retrieveAndMatch(context);
+ if (maybe_code && maybe_code->failed()) {
+ tracker.fail(maybe_code->getResult(), maybe_code->getMessage());
+ return TasResult::FailedAndSetInTracker;
+ } else if (!maybe_code) {
+ return TasResult::NotFound;
}
} catch (const TestAndSetException & e) {
auto code = e.getCode();
tracker.fail(code.getResult(), code.getMessage());
- return false;
+ return TasResult::FailedAndSetInTracker;
}
- return true;
+ return TasResult::Matched;
}
bool