aboutsummaryrefslogtreecommitdiffstats
path: root/storage/src/vespa/storage/distributor/distributor_bucket_space.h
blob: cb7a6bf99ae40935a3c9a482cace72f32a2e0c13 (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once

#include "bucketownership.h"
#include "bucket_ownership_flags.h"
#include "ideal_service_layer_nodes_bundle.h"
#include <vespa/document/bucket/bucketid.h>
#include <vespa/vespalib/stllike/hash_map.h>
#include <memory>
#include <vector>

namespace storage {
class BucketDatabase;
}

namespace storage::lib {
    class ClusterState;
    class Distribution;
}

namespace storage::distributor {

/**
 * A distributor bucket space holds specific state and information required for
 * keeping track of, and computing operations for, a single bucket space:
 *
 * Bucket database instance
 *   Each bucket space has its own entirely separate bucket database.
 * Distribution config
 *   Each bucket space _may_ operate with its own distribution config, in
 *   particular so that redundancy, ready copies etc can differ across
 *   bucket spaces.
 */
class DistributorBucketSpace {
    std::unique_ptr<BucketDatabase>          _bucketDatabase;
    std::shared_ptr<const lib::ClusterState> _clusterState;
    std::shared_ptr<const lib::Distribution> _distribution;
    uint16_t                                 _node_index;
    uint16_t                                 _distribution_bits;
    bool                                     _merges_inhibited;
    std::shared_ptr<const lib::ClusterState> _pending_cluster_state;
    std::vector<bool>                        _available_nodes;
    mutable vespalib::hash_map<document::BucketId, BucketOwnershipFlags, document::BucketId::hash>  _ownerships;
    mutable vespalib::hash_map<document::BucketId, std::unique_ptr<IdealServiceLayerNodesBundle>, document::BucketId::hash> _ideal_nodes;

    void clear();
    void enumerate_available_nodes();
    bool owns_bucket_in_state(const lib::Distribution& distribution, const lib::ClusterState& cluster_state, document::BucketId bucket) const;
public:
    explicit DistributorBucketSpace();
    explicit DistributorBucketSpace(uint16_t node_index);
    ~DistributorBucketSpace();

    DistributorBucketSpace(const DistributorBucketSpace&) = delete;
    DistributorBucketSpace& operator=(const DistributorBucketSpace&) = delete;
    DistributorBucketSpace(DistributorBucketSpace&&) = delete;
    DistributorBucketSpace& operator=(DistributorBucketSpace&&) = delete;

    BucketDatabase& getBucketDatabase() noexcept {
        assert(_bucketDatabase);
        return *_bucketDatabase;
    }
    const BucketDatabase& getBucketDatabase() const noexcept {
        assert(_bucketDatabase);
        return *_bucketDatabase;
    }

    void setClusterState(std::shared_ptr<const lib::ClusterState> clusterState);

    const lib::ClusterState &getClusterState() const noexcept { return *_clusterState; }
    const std::shared_ptr<const lib::ClusterState>& cluster_state_sp() const noexcept {
        return _clusterState;
    }

    void setDistribution(std::shared_ptr<const lib::Distribution> distribution);

    // Precondition: setDistribution has been called at least once prior.
    const lib::Distribution& getDistribution() const noexcept {
        return *_distribution;
    }
    const std::shared_ptr<const lib::Distribution>& distribution_sp() const noexcept {
        return _distribution;
    }

    void set_pending_cluster_state(std::shared_ptr<const lib::ClusterState> pending_cluster_state);
    bool has_pending_cluster_state() const noexcept { return static_cast<bool>(_pending_cluster_state); }
    const lib::ClusterState& get_pending_cluster_state() const noexcept { return *_pending_cluster_state; }

    void set_merges_inhibited(bool inhibited) noexcept {
        _merges_inhibited = inhibited;
    }
    [[nodiscard]] bool merges_inhibited() const noexcept {
        return _merges_inhibited;
    }

    /**
     * Returns true if this distributor owns the given bucket in the
     * given cluster and current distribution config.
     * Only used by unit tests.
     */
    bool owns_bucket_in_state(const lib::ClusterState& clusterState, document::BucketId bucket) const;

    const std::vector<bool>& get_available_nodes() const { return _available_nodes; }

    /**
     * Returns the ideal nodes bundle for the given bucket.
     */
    const IdealServiceLayerNodesBundle &get_ideal_service_layer_nodes_bundle(document::BucketId bucket) const;

    /*
     * Return bucket ownership flags for the given bucket. Bucket is always
     * considered owned in pending state if there is no pending state.
     */
    BucketOwnershipFlags get_bucket_ownership_flags(document::BucketId bucket) const;

    /**
     * Returns the ownership status of a bucket as decided with the current
     * distribution and cluster state -and- that of the pending cluster
     * state and distribution (if any pending exists).
     */
    BucketOwnership check_ownership_in_pending_and_current_state(document::BucketId bucket) const;
};

}