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
|
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
/**
* @class vdslib::Group
*
* Defines a Group object that defines a group of groups/nodes.
*
* The "1|*" partitions representation is stored as an array of double,
* where the star (*) is represented by zero (0).
* The subgroups and storagenode/distributor indexes are stored in increasing order.
*
*/
#pragma once
#include "redundancygroupdistribution.h"
#include <vespa/vespalib/objects/floatingpointtype.h>
#include <vespa/vespalib/util/crc.h>
#include <map>
#include <vector>
#include <memory>
namespace vespalib { class asciistream; }
namespace storage::lib {
class Group : public document::Printable
{
public:
using UP = std::unique_ptr<Group>;
using Distribution = RedundancyGroupDistribution ;
private:
vespalib::string _name;
uint16_t _index;
uint32_t _distributionHash;
Distribution _distributionSpec;
std::vector<Distribution> _preCalculated;
vespalib::Double _capacity;
std::map<uint16_t, Group*> _subGroups; // Set if branch group
// Invariant: _nodes is ordered by ascending index value.
std::vector<uint16_t> _nodes; // Set if leaf group
// Same set of indices as _nodes, but in the order originally given as
// part of setNodes(), i.e. may not be ordered.
// TODO(vekterli): this can be removed once model code is guaranteed to
// output nodes in a well-defined order, i.e. _originalNodes == _nodes.
std::vector<uint16_t> _originalNodes;
void calculateDistributionHashValues(uint32_t parentHash);
void getConfigHash(vespalib::asciistream & out) const;
public:
// Create leaf node
Group(uint16_t index, vespalib::stringref name) noexcept;
// Create branch node
Group(uint16_t index, vespalib::stringref name,
const Distribution&, uint16_t redundancy);
virtual ~Group();
bool isLeafGroup() const noexcept { return ! _nodes.empty(); }
bool operator==(const Group& other) const noexcept;
void print(std::ostream& out, bool verbose, const std::string& indent) const override;
vespalib::Double getCapacity() const noexcept { return _capacity; }
const vespalib::string & getName() const noexcept { return _name; }
uint16_t getIndex() const noexcept { return _index; }
std::map<uint16_t, Group*>& getSubGroups() { return _subGroups; }
const std::map<uint16_t, Group*>& getSubGroups() const noexcept { return _subGroups; }
const std::vector<uint16_t>& getNodes() const noexcept { return _nodes; };
const Distribution& getDistributionSpec() const noexcept { return _distributionSpec; }
const Distribution& getDistribution(uint16_t redundancy) const noexcept { return _preCalculated[redundancy]; }
uint32_t getDistributionHash() const noexcept { return _distributionHash; }
void addSubGroup(Group::UP);
void setCapacity(vespalib::Double capacity);
void setNodes(const std::vector<uint16_t>& nodes);
/**
* Returns the hierarchical group the given node is in.
*/
const Group* getGroupForNode(uint16_t index) const;
/**
* Calculates distribution hashes, used to create unique values for each
* group to XOR their bucket seeds with. Calculated based on index of itself
* and parent groups. Call this on the root group to generate all hashes.
*/
void calculateDistributionHashValues() {
calculateDistributionHashValues(0x8badf00d);
}
/**
* Get a string uniquely describing the parts of the distribution config
* that is critical for distribution. Use to match up two different group
* instances in order to verify if they would generate the same distribution
*/
vespalib::string getDistributionConfigHash() const;
};
}
|