aboutsummaryrefslogtreecommitdiffstats
path: root/storage/src/vespa/storage/persistence/testandsethelper.h
blob: f586f720e23c601471916a553014549170ba35f1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
// @author Vegard Sjonfjell

#pragma once

#include <vespa/storageapi/message/persistence.h>
#include <vespa/persistence/spi/result.h>
#include <stdexcept>

namespace document::select { class Node; }
namespace document {
    class FieldSet;
    class BucketIdFactory;
}

namespace storage {

namespace spi {
    class Context;
    struct PersistenceProvider;
}
class PersistenceThread;
class ServiceLayerComponent;
class PersistenceUtil;

class TestAndSetException : public std::runtime_error {
    api::ReturnCode _code;
public:
    explicit TestAndSetException(api::ReturnCode code)
        : std::runtime_error(code.getMessage()),
        _code(std::move(code))
    {}

    const api::ReturnCode & getCode() const { return _code; }
};

class TestAndSetHelper {
    const PersistenceUtil&                  _env;
    const spi::PersistenceProvider&         _spi;
    const documentapi::TestAndSetCondition& _condition;
    const document::Bucket                  _bucket;
    const document::DocumentId              _docId;
    const document::DocumentType*           _docTypePtr;
    std::unique_ptr<document::select::Node> _docSelectionUp;
    bool                                    _missingDocumentImpliesMatch;

    void resolveDocumentType(const document::DocumentTypeRepo & documentTypeRepo);
    void parseDocumentSelection(const document::DocumentTypeRepo & documentTypeRepo,
                                const document::BucketIdFactory & bucketIdFactory);
    spi::GetResult retrieveDocument(const document::FieldSet & fieldSet, spi::Context & context);

public:
    struct Result {
        enum class ConditionOutcome {
            DocNotFound,
            IsMatch,
            IsNotMatch,
            IsTombstone
        };

        api::Timestamp timestamp = 0;
        ConditionOutcome condition_outcome = ConditionOutcome::IsNotMatch;

        [[nodiscard]] bool doc_not_found() const noexcept {
            return condition_outcome == ConditionOutcome::DocNotFound;
        }
        [[nodiscard]] bool is_match() const noexcept {
            return condition_outcome == ConditionOutcome::IsMatch;
        }
        [[nodiscard]] bool is_not_match() const noexcept {
            return condition_outcome == ConditionOutcome::IsNotMatch;
        }
        [[nodiscard]] bool is_tombstone() const noexcept {
            return condition_outcome == ConditionOutcome::IsTombstone;
        }
    };

    TestAndSetHelper(const PersistenceUtil& env,
                     const spi::PersistenceProvider& _spi,
                     const document::BucketIdFactory& bucket_id_factory,
                     const documentapi::TestAndSetCondition& condition,
                     document::Bucket bucket,
                     document::DocumentId doc_id,
                     const document::DocumentType* doc_type_ptr,
                     bool missingDocumentImpliesMatch = false);
    ~TestAndSetHelper();

    Result fetch_and_match_raw(spi::Context& context);
    api::ReturnCode to_api_return_code(const Result& result) const;

    api::ReturnCode retrieveAndMatch(spi::Context & context);
};

} // storage