From ed6fba7d937cfe61aacfd8e6796886d08acd4eef Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Wed, 9 Aug 2023 09:17:35 +0000 Subject: Modernize code and prepare for changing map implementation. --- vdslib/src/vespa/vdslib/state/clusterstate.cpp | 237 ++++++++++++------------- vdslib/src/vespa/vdslib/state/clusterstate.h | 34 ++-- vdslib/src/vespa/vdslib/state/node.h | 12 +- 3 files changed, 132 insertions(+), 151 deletions(-) diff --git a/vdslib/src/vespa/vdslib/state/clusterstate.cpp b/vdslib/src/vespa/vdslib/state/clusterstate.cpp index 6a319af68ef..61a41086ef3 100644 --- a/vdslib/src/vespa/vdslib/state/clusterstate.cpp +++ b/vdslib/src/vespa/vdslib/state/clusterstate.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include LOG_SETUP(".vdslib.state.cluster"); @@ -24,9 +25,9 @@ namespace storage::lib { ClusterState::ClusterState() : Printable(), _version(0), + _nodeCount(), _clusterState(&State::DOWN), _nodeStates(), - _nodeCount(2), _description(), _distributionBits(16) { } @@ -41,14 +42,10 @@ struct NodeData { NodeData() : empty(true), node(NodeType::STORAGE, 0), ost() {} - void addTo(std::map& nodeStates, - std::vector& nodeCount) - { + void addTo(ClusterState::NodeMap & nodeStates, ClusterState::NodeCounts & nodeCount) { if (!empty) { NodeState state(ost.str(), &node.getType()); - if (state != NodeState(node.getType(), State::UP) - || state.getDescription().size() > 0) - { + if ((state != NodeState(node.getType(), State::UP)) || (state.getDescription().size() > 0)) { nodeStates.insert(std::make_pair(node, state)); } if (nodeCount[node.getType()] <= node.getIndex()) { @@ -63,9 +60,9 @@ struct NodeData { ClusterState::ClusterState(const vespalib::string& serialized) : Printable(), _version(0), + _nodeCount(), _clusterState(&State::UP), _nodeStates(), - _nodeCount(2), _description(), _distributionBits(16) { @@ -74,13 +71,13 @@ ClusterState::ClusterState(const vespalib::string& serialized) NodeData nodeData; vespalib::string lastAbsolutePath; - for (vespalib::StringTokenizer::Iterator it = st.begin(); it != st.end(); ++it) { - vespalib::string::size_type index = it->find(':'); + for (const auto & token : st) { + vespalib::string::size_type index = token.find(':'); if (index == vespalib::string::npos) { - throw IllegalArgumentException("Token " + *it + " does not contain ':': " + serialized, VESPA_STRLOC); + throw IllegalArgumentException("Token " + token + " does not contain ':': " + serialized, VESPA_STRLOC); } - vespalib::string key = it->substr(0, index); - vespalib::stringref value = it->substr(index + 1); + vespalib::string key = token.substr(0, index); + vespalib::stringref value = token.substr(index + 1); if (key.size() > 0 && key[0] == '.') { if (lastAbsolutePath == "") { throw IllegalArgumentException("The first path in system state string needs to be absolute", VESPA_STRLOC); @@ -111,7 +108,9 @@ ClusterState::parse(vespalib::stringref key, vespalib::stringref value, NodeData break; case 'b': if (key == "bits") { - _distributionBits = atoi(value.data()); + uint32_t numBits = atoi(value.data()); + assert(numBits <= 64); + _distributionBits = numBits; return true; } break; @@ -138,7 +137,7 @@ ClusterState::parse(vespalib::stringref key, vespalib::stringref value, NodeData bool ClusterState::parseSorD(vespalib::stringref key, vespalib::stringref value, NodeData & nodeData) { - const NodeType* nodeType(0); + const NodeType* nodeType = nullptr; vespalib::string::size_type dot = key.find('.'); vespalib::stringref type(dot == vespalib::string::npos ? key : key.substr(0, dot)); @@ -147,10 +146,9 @@ ClusterState::parseSorD(vespalib::stringref key, vespalib::stringref value, Node } else if (type == "distributor") { nodeType = &NodeType::DISTRIBUTOR; } - if (nodeType == 0) return false; + if (nodeType == nullptr) return false; if (dot == vespalib::string::npos) { // Entry that set node counts - uint16_t nodeCount = 0; - nodeCount = atoi(value.data()); + uint16_t nodeCount = atoi(value.data()); if (nodeCount > _nodeCount[*nodeType] ) { _nodeCount[*nodeType] = nodeCount; @@ -158,12 +156,9 @@ ClusterState::parseSorD(vespalib::stringref key, vespalib::stringref value, Node return true; } vespalib::string::size_type dot2 = key.find('.', dot + 1); - Node node; - if (dot2 == vespalib::string::npos) { - node = Node(*nodeType, atoi(key.substr(dot + 1).data())); - } else { - node = Node(*nodeType, atoi(key.substr(dot + 1, dot2 - dot - 1).data())); - } + Node node(*nodeType, (dot2 == vespalib::string::npos) + ? atoi(key.substr(dot + 1).data()) + : atoi(key.substr(dot + 1, dot2 - dot - 1).data())); if (node.getIndex() >= _nodeCount[*nodeType]) { vespalib::asciistream ost; @@ -184,17 +179,19 @@ ClusterState::parseSorD(vespalib::stringref key, vespalib::stringref value, Node } namespace { - struct SeparatorPrinter { - bool first; - SeparatorPrinter() : first(true) {} - const char * toString() { - if (first) { - first = false; - return ""; - } - return " "; + +struct SeparatorPrinter { + bool first; + SeparatorPrinter() : first(true) {} + const char * toString() { + if (first) { + first = false; + return ""; } - }; + return " "; + } +}; + } void @@ -214,15 +211,12 @@ ClusterState::serialize(vespalib::asciistream & out, bool ignoreNewFeatures) con uint16_t distCount = getNodeCount(NodeType::DISTRIBUTOR); if (ignoreNewFeatures || distCount > 0) { out << sep.toString() << "distributor:" << distCount; - for (std::map::const_iterator it = - _nodeStates.begin(); - it != _nodeStates.end(); ++it) - { - if (it->first.getType() != NodeType::DISTRIBUTOR) continue; + for (const auto & entry : _nodeStates) { + if (entry.first.getType() != NodeType::DISTRIBUTOR) continue; vespalib::asciistream prefix; - prefix << "." << it->first.getIndex() << "."; + prefix << "." << entry.first.getIndex() << "."; vespalib::asciistream ost; - it->second.serialize(ost, prefix.str(), false); + entry.second.serialize(ost, prefix.str(), false); vespalib::stringref content = ost.str(); if (content.size() > 0) { out << " " << content; @@ -232,15 +226,12 @@ ClusterState::serialize(vespalib::asciistream & out, bool ignoreNewFeatures) con uint16_t storCount = getNodeCount(NodeType::STORAGE); if (ignoreNewFeatures || storCount > 0) { out << sep.toString() << "storage:" << storCount; - for (std::map::const_iterator it = - _nodeStates.begin(); - it != _nodeStates.end(); ++it) - { - if (it->first.getType() != NodeType::STORAGE) continue; + for (const auto & entry : _nodeStates) { + if (entry.first.getType() != NodeType::STORAGE) continue; vespalib::asciistream prefix; - prefix << "." << it->first.getIndex() << "."; + prefix << "." << entry.first.getIndex() << "."; vespalib::asciistream ost; - it->second.serialize(ost, prefix.str(), false); + entry.second.serialize(ost, prefix.str(), false); vespalib::stringref content = ost.str(); if ( !content.empty()) { out << " " << content; @@ -265,12 +256,6 @@ ClusterState::operator!=(const ClusterState& other) const noexcept return !(*this == other); } -uint16_t -ClusterState::getNodeCount(const NodeType& type) const noexcept -{ - return _nodeCount[type]; -} - namespace { [[noreturn]] void throwUnknownType(const Node & node) __attribute__((noinline)); void throwUnknownType(const Node & node) { @@ -282,7 +267,7 @@ const NodeState& ClusterState::getNodeState(const Node& node) const { // If it actually has an entry in map, return that - auto it = _nodeStates.find(node); + const auto it = _nodeStates.find(node); if (it != _nodeStates.end()) return it->second; // If beyond node count, the node is down. @@ -307,9 +292,7 @@ void ClusterState::setClusterState(const State& state) { if (!state.validClusterState()) { - throw vespalib::IllegalStateException( - state.toString(true) + " is not a legal cluster state", - VESPA_STRLOC); + throw vespalib::IllegalStateException(state.toString(true) + " is not a legal cluster state", VESPA_STRLOC); } _clusterState = &state; } @@ -319,17 +302,12 @@ ClusterState::setNodeState(const Node& node, const NodeState& state) { state.verifySupportForNodeType(node.getType()); if (node.getIndex() >= _nodeCount[node.getType()]) { - for (uint32_t i = _nodeCount[node.getType()]; i < node.getIndex(); ++i) - { - _nodeStates.insert(std::make_pair( - Node(node.getType(), i), - NodeState(node.getType(), State::DOWN))); + for (uint32_t i = _nodeCount[node.getType()]; i < node.getIndex(); ++i) { + _nodeStates.insert(std::make_pair(Node(node.getType(), i), NodeState(node.getType(), State::DOWN))); } _nodeCount[node.getType()] = node.getIndex() + 1; } - if (state == NodeState(node.getType(), State::UP) - && state.getDescription().size() == 0) - { + if ((state == NodeState(node.getType(), State::UP)) && state.getDescription().empty()) { _nodeStates.erase(node); } else { _nodeStates.insert(std::make_pair(node, state)); @@ -339,8 +317,7 @@ ClusterState::setNodeState(const Node& node, const NodeState& state) } void -ClusterState::print(std::ostream& out, bool verbose, - const std::string&) const +ClusterState::print(std::ostream& out, bool verbose, const std::string&) const { (void) verbose; vespalib::asciistream tmp; @@ -350,21 +327,24 @@ ClusterState::print(std::ostream& out, bool verbose, void ClusterState::removeExtraElements() +{ + removeExtraElements(NodeType::STORAGE); + removeExtraElements(NodeType::DISTRIBUTOR); +} + +void +ClusterState::removeExtraElements(const NodeType & type) { // Simplify the system state by removing the last indexes if the nodes // are down. - for (uint32_t i=0; i<2; ++i) { - const NodeType& type(i == 0 ? NodeType::STORAGE - : NodeType::DISTRIBUTOR); - for (int32_t index = _nodeCount[type]; index >= 0; --index) { - Node node(type, index - 1); - std::map::iterator it(_nodeStates.find(node)); - if (it == _nodeStates.end()) break; - if (it->second.getState() != State::DOWN) break; - if (it->second.getDescription() != "") break; - _nodeStates.erase(it); - --_nodeCount[type]; - } + for (int32_t index = _nodeCount[type]; index >= 0; --index) { + Node node(type, index - 1); + const auto it = _nodeStates.find(node); + if (it == _nodeStates.end()) break; + if (it->second.getState() != State::DOWN) break; + if (it->second.getDescription() != "") break; + _nodeStates.erase(it); + --_nodeCount[type]; } } @@ -421,39 +401,58 @@ ClusterState::printStateGroupwise(std::ostream& out, const Distribution& dist, } namespace { - template - std::string getNumberSpec(const std::vector& numbers) { - std::ostringstream ost; - bool first = true; - uint32_t firstInRange = numbers.size() == 0 ? 0 : numbers[0];; - uint32_t lastInRange = firstInRange; - for (uint32_t i=1; i<=numbers.size(); ++i) { - if (i < numbers.size() && numbers[i] == lastInRange + 1) { - ++lastInRange; + +template +std::string getNumberSpec(const std::vector& numbers) { + std::ostringstream ost; + bool first = true; + uint32_t firstInRange = numbers.size() == 0 ? 0 : numbers[0];; + uint32_t lastInRange = firstInRange; + for (uint32_t i=1; i<=numbers.size(); ++i) { + if (i < numbers.size() && numbers[i] == lastInRange + 1) { + ++lastInRange; + } else { + if (first) { + first = false; } else { - if (first) { - first = false; - } else { - ost << ","; - } - if (firstInRange == lastInRange) { - ost << firstInRange; - } else { - ost << firstInRange << "-" << lastInRange; - } - if (i < numbers.size()) { - firstInRange = lastInRange = numbers[i]; - } + ost << ","; + } + if (firstInRange == lastInRange) { + ost << firstInRange; + } else { + ost << firstInRange << "-" << lastInRange; } + if (i < numbers.size()) { + firstInRange = lastInRange = numbers[i]; + } + } + } + return ost.str(); +} + +} + +bool +ClusterState::printStateGroupwise(std::ostream& out, const Group& group, bool verbose, + const std::string& indent, const NodeType& nodeType) const +{ + NodeState defState(nodeType, State::UP); + bool printedAny = false; + for (uint16_t nodeId : group.getNodes()) { + Node node(nodeType, nodeId); + const NodeState& state(getNodeState(node)); + if (state != defState) { + out << "\n" << indent << " " << node << ": "; + state.print(out, verbose, indent + " "); + printedAny = true; } - return ost.str(); } + return printedAny; } void -ClusterState::printStateGroupwise(std::ostream& out, const Group& group, - bool verbose, const std::string& indent, - bool rootGroup) const +ClusterState::printStateGroupwise(std::ostream& out, const Group& group, bool verbose, + const std::string& indent, bool rootGroup) const { if (rootGroup) { out << "\n" << indent << "Top group"; @@ -469,34 +468,18 @@ ClusterState::printStateGroupwise(std::ostream& out, const Group& group, out << " " << group.getNodes().size() << " node" << (group.getNodes().size() != 1 ? "s" : "") << " [" << getNumberSpec(group.getNodes()) << "] {"; - bool printedAny = false; - for (uint32_t j=0; j<2; ++j) { - const NodeType& nodeType( - j == 0 ? NodeType::DISTRIBUTOR : NodeType::STORAGE); - NodeState defState(nodeType, State::UP); - for (uint32_t i=0; i& children(group.getSubGroups()); + const auto & children(group.getSubGroups()); out << " " << children.size() << " branch" << (children.size() != 1 ? "es" : "") << " with distribution " << group.getDistributionSpec() << " {"; - for (std::map::const_iterator it = children.begin(); - it != children.end(); ++it) - { - printStateGroupwise(out, *it->second, verbose, - indent + " ", false); + for (const auto & child : children) { + printStateGroupwise(out, *child.second, verbose,indent + " ", false); } } out << "\n" << indent << "}"; diff --git a/vdslib/src/vespa/vdslib/state/clusterstate.h b/vdslib/src/vespa/vdslib/state/clusterstate.h index 44af81f52ce..47c7bbfd62f 100644 --- a/vdslib/src/vespa/vdslib/state/clusterstate.h +++ b/vdslib/src/vespa/vdslib/state/clusterstate.h @@ -11,6 +11,7 @@ #include "node.h" #include "nodestate.h" #include +#include namespace storage::lib { @@ -19,17 +20,9 @@ class Group; struct NodeData; class ClusterState : public document::Printable { - uint32_t _version; - const State* _clusterState; - std::map _nodeStates; - std::vector _nodeCount; - vespalib::string _description; - uint16_t _distributionBits; - - void getTextualDifference(std::ostringstream& builder, const NodeType& type, - const ClusterState& other) const; - public: + using NodeMap = std::map; + using NodeCounts = std::array; using CSP = std::shared_ptr; using SP = std::shared_ptr; using UP = std::unique_ptr; @@ -48,12 +41,12 @@ public: bool operator==(const ClusterState& other) const noexcept; bool operator!=(const ClusterState& other) const noexcept; - uint32_t getVersion() const { return _version; } + uint32_t getVersion() const noexcept { return _version; } /** * Returns the smallest number above the highest node index found of the * given type that is not down. */ - uint16_t getNodeCount(const NodeType& type) const noexcept; + uint16_t getNodeCount(const NodeType& type) const noexcept { return _nodeCount[type]; } uint16_t getDistributionBitCount() const noexcept { return _distributionBits; } const State& getClusterState() const noexcept { return *_clusterState; } const NodeState& getNodeState(const Node& node) const; @@ -65,9 +58,7 @@ public: void print(std::ostream& out, bool verbose, const std::string& indent) const override; - void printStateGroupwise(std::ostream& out, - const Distribution&, bool verbose = false, - const std::string& indent = "") const; + void printStateGroupwise(std::ostream& out, const Distribution&, bool verbose, const std::string& indent) const; private: // Preconditions: `key` and `value` MUST point into null-terminated strings. @@ -75,9 +66,16 @@ private: // Preconditions: `key` and `value` MUST point into null-terminated strings. bool parseSorD(vespalib::stringref key, vespalib::stringref value, NodeData & nodeData); void removeExtraElements(); - void printStateGroupwise(std::ostream& out, const Group&, bool verbose, - const std::string& indent, bool rootGroup) const; - + void removeExtraElements(const NodeType& type); + void printStateGroupwise(std::ostream& out, const Group&, bool verbose, const std::string& indent, bool rootGroup) const; + void getTextualDifference(std::ostringstream& builder, const NodeType& type, const ClusterState& other) const; + bool printStateGroupwise(std::ostream& out, const Group&, bool verbose, const std::string& indent, const NodeType& type) const; + uint32_t _version; + NodeCounts _nodeCount; + const State* _clusterState; + NodeMap _nodeStates; + vespalib::string _description; + uint16_t _distributionBits; }; } diff --git a/vdslib/src/vespa/vdslib/state/node.h b/vdslib/src/vespa/vdslib/state/node.h index 2e33e54c638..5dfd6a2ccf4 100644 --- a/vdslib/src/vespa/vdslib/state/node.h +++ b/vdslib/src/vespa/vdslib/state/node.h @@ -13,24 +13,24 @@ namespace storage::lib { class Node { const NodeType* _type; - uint16_t _index; + uint16_t _index; public: Node() noexcept : _type(&NodeType::STORAGE), _index(0) { } Node(const NodeType& type, uint16_t index) noexcept : _type(&type), _index(index) { } - const NodeType& getType() const { return *_type; } - uint16_t getIndex() const { return _index; } + const NodeType& getType() const noexcept { return *_type; } + uint16_t getIndex() const noexcept { return _index; } - bool operator==(const Node& other) const { + bool operator==(const Node& other) const noexcept { return (other._index == _index && *other._type == *_type); } - bool operator!=(const Node& other) const { + bool operator!=(const Node& other) const noexcept { return (other._index != _index || *other._type != *_type); } - bool operator<(const Node& n) const { + bool operator<(const Node& n) const noexcept { if (*_type != *n._type) return (*_type < *n._type); return (_index < n._index); } -- cgit v1.2.3 From 56d3b5290ba54231d46d08522db7ea55ab51fe49 Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Wed, 9 Aug 2023 10:49:25 +0000 Subject: Avoid short-circuit optimization trap... --- vdslib/src/vespa/vdslib/state/clusterstate.cpp | 14 +++++++------- vdslib/src/vespa/vdslib/state/clusterstate.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/vdslib/src/vespa/vdslib/state/clusterstate.cpp b/vdslib/src/vespa/vdslib/state/clusterstate.cpp index 61a41086ef3..e0fb16a5a4b 100644 --- a/vdslib/src/vespa/vdslib/state/clusterstate.cpp +++ b/vdslib/src/vespa/vdslib/state/clusterstate.cpp @@ -432,22 +432,22 @@ std::string getNumberSpec(const std::vector& numbers) { } -bool +size_t ClusterState::printStateGroupwise(std::ostream& out, const Group& group, bool verbose, const std::string& indent, const NodeType& nodeType) const { NodeState defState(nodeType, State::UP); - bool printedAny = false; + size_t printed = 0; for (uint16_t nodeId : group.getNodes()) { Node node(nodeType, nodeId); const NodeState& state(getNodeState(node)); if (state != defState) { out << "\n" << indent << " " << node << ": "; state.print(out, verbose, indent + " "); - printedAny = true; + printed++; } } - return printedAny; + return printed; } void @@ -468,9 +468,9 @@ ClusterState::printStateGroupwise(std::ostream& out, const Group& group, bool ve out << " " << group.getNodes().size() << " node" << (group.getNodes().size() != 1 ? "s" : "") << " [" << getNumberSpec(group.getNodes()) << "] {"; - bool printedAny = printStateGroupwise(out, group, verbose, indent, NodeType::DISTRIBUTOR); - printedAny = printedAny || printStateGroupwise(out, group, verbose, indent, NodeType::STORAGE); - if (!printedAny) { + size_t printed = printStateGroupwise(out, group, verbose, indent, NodeType::DISTRIBUTOR) + + printStateGroupwise(out, group, verbose, indent, NodeType::STORAGE); + if (printed > 0 ) { out << "\n" << indent << " All nodes in group up and available."; } } else { diff --git a/vdslib/src/vespa/vdslib/state/clusterstate.h b/vdslib/src/vespa/vdslib/state/clusterstate.h index 47c7bbfd62f..2630c4a2315 100644 --- a/vdslib/src/vespa/vdslib/state/clusterstate.h +++ b/vdslib/src/vespa/vdslib/state/clusterstate.h @@ -69,7 +69,7 @@ private: void removeExtraElements(const NodeType& type); void printStateGroupwise(std::ostream& out, const Group&, bool verbose, const std::string& indent, bool rootGroup) const; void getTextualDifference(std::ostringstream& builder, const NodeType& type, const ClusterState& other) const; - bool printStateGroupwise(std::ostream& out, const Group&, bool verbose, const std::string& indent, const NodeType& type) const; + size_t printStateGroupwise(std::ostream& out, const Group&, bool verbose, const std::string& indent, const NodeType& type) const; uint32_t _version; NodeCounts _nodeCount; const State* _clusterState; -- cgit v1.2.3 From 039deb6b169b76904ce13dd0d33ae588d27ccbee Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Wed, 9 Aug 2023 11:53:27 +0000 Subject: All are up if NONE are printed.... --- vdslib/src/vespa/vdslib/state/clusterstate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vdslib/src/vespa/vdslib/state/clusterstate.cpp b/vdslib/src/vespa/vdslib/state/clusterstate.cpp index e0fb16a5a4b..b72e0277b94 100644 --- a/vdslib/src/vespa/vdslib/state/clusterstate.cpp +++ b/vdslib/src/vespa/vdslib/state/clusterstate.cpp @@ -470,7 +470,7 @@ ClusterState::printStateGroupwise(std::ostream& out, const Group& group, bool ve << getNumberSpec(group.getNodes()) << "] {"; size_t printed = printStateGroupwise(out, group, verbose, indent, NodeType::DISTRIBUTOR) + printStateGroupwise(out, group, verbose, indent, NodeType::STORAGE); - if (printed > 0 ) { + if (printed == 0) { out << "\n" << indent << " All nodes in group up and available."; } } else { -- cgit v1.2.3 From 08a045383e2d4dffd93245b689aa555cd5422465 Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Wed, 9 Aug 2023 12:17:43 +0000 Subject: Common code for node serialization too. --- vdslib/src/vespa/vdslib/state/clusterstate.cpp | 81 ++++++++++++-------------- vdslib/src/vespa/vdslib/state/clusterstate.h | 2 + 2 files changed, 40 insertions(+), 43 deletions(-) diff --git a/vdslib/src/vespa/vdslib/state/clusterstate.cpp b/vdslib/src/vespa/vdslib/state/clusterstate.cpp index b72e0277b94..b796e357d24 100644 --- a/vdslib/src/vespa/vdslib/state/clusterstate.cpp +++ b/vdslib/src/vespa/vdslib/state/clusterstate.cpp @@ -178,8 +178,6 @@ ClusterState::parseSorD(vespalib::stringref key, vespalib::stringref value, Node return true; } -namespace { - struct SeparatorPrinter { bool first; SeparatorPrinter() : first(true) {} @@ -192,6 +190,35 @@ struct SeparatorPrinter { } }; +namespace { + +void +serialize_node(vespalib::asciistream & out, const std::pair & entry) { + vespalib::asciistream prefix; + prefix << "." << entry.first.getIndex() << "."; + vespalib::asciistream ost; + entry.second.serialize(ost, prefix.str(), false); + vespalib::stringref content = ost.str(); + if ( !content.empty()) { + out << " " << content; + } +} + +} + +void +ClusterState::serialize_nodes(vespalib::asciistream & out, bool ignoreNewFeatures, + SeparatorPrinter & sep, const NodeType & nodeType) const +{ + uint16_t nodeCount = getNodeCount(nodeType); + if (ignoreNewFeatures || nodeCount > 0) { + out << sep.toString() << nodeType.serialize() << ":" << nodeCount; + for (const auto & entry : _nodeStates) { + if (entry.first.getType() == nodeType) { + serialize_node(out, entry); + } + } + } } void @@ -208,36 +235,8 @@ ClusterState::serialize(vespalib::asciistream & out, bool ignoreNewFeatures) con out << sep.toString() << "bits:" << _distributionBits; } - uint16_t distCount = getNodeCount(NodeType::DISTRIBUTOR); - if (ignoreNewFeatures || distCount > 0) { - out << sep.toString() << "distributor:" << distCount; - for (const auto & entry : _nodeStates) { - if (entry.first.getType() != NodeType::DISTRIBUTOR) continue; - vespalib::asciistream prefix; - prefix << "." << entry.first.getIndex() << "."; - vespalib::asciistream ost; - entry.second.serialize(ost, prefix.str(), false); - vespalib::stringref content = ost.str(); - if (content.size() > 0) { - out << " " << content; - } - } - } - uint16_t storCount = getNodeCount(NodeType::STORAGE); - if (ignoreNewFeatures || storCount > 0) { - out << sep.toString() << "storage:" << storCount; - for (const auto & entry : _nodeStates) { - if (entry.first.getType() != NodeType::STORAGE) continue; - vespalib::asciistream prefix; - prefix << "." << entry.first.getIndex() << "."; - vespalib::asciistream ost; - entry.second.serialize(ost, prefix.str(), false); - vespalib::stringref content = ost.str(); - if ( !content.empty()) { - out << " " << content; - } - } - } + serialize_nodes(out, ignoreNewFeatures, sep, NodeType::DISTRIBUTOR); + serialize_nodes(out, ignoreNewFeatures, sep, NodeType::STORAGE); } bool @@ -393,9 +392,8 @@ void ClusterState::printStateGroupwise(std::ostream& out, const Distribution& dist, bool verbose, const std::string& indent) const { - out << "ClusterState(Version: " << _version << ", Cluster state: " - << _clusterState->toString(true) << ", Distribution bits: " - << _distributionBits << ") {"; + out << "ClusterState(Version: " << _version << ", Cluster state: " << _clusterState->toString(true) + << ", Distribution bits: " << _distributionBits << ") {"; printStateGroupwise(out, dist.getNodeGraph(), verbose, indent + " ", true); out << "\n" << indent << "}"; } @@ -457,17 +455,15 @@ ClusterState::printStateGroupwise(std::ostream& out, const Group& group, bool ve if (rootGroup) { out << "\n" << indent << "Top group"; } else { - out << "\n" << indent << "Group " << group.getIndex() << ": " - << group.getName(); + out << "\n" << indent << "Group " << group.getIndex() << ": " << group.getName(); if (group.getCapacity() != 1.0) { out << ", capacity " << group.getCapacity(); } } out << "."; if (group.isLeafGroup()) { - out << " " << group.getNodes().size() << " node" - << (group.getNodes().size() != 1 ? "s" : "") << " [" - << getNumberSpec(group.getNodes()) << "] {"; + out << " " << group.getNodes().size() << " node" << (group.getNodes().size() != 1 ? "s" : "") + << " [" << getNumberSpec(group.getNodes()) << "] {"; size_t printed = printStateGroupwise(out, group, verbose, indent, NodeType::DISTRIBUTOR) + printStateGroupwise(out, group, verbose, indent, NodeType::STORAGE); if (printed == 0) { @@ -475,9 +471,8 @@ ClusterState::printStateGroupwise(std::ostream& out, const Group& group, bool ve } } else { const auto & children(group.getSubGroups()); - out << " " << children.size() << " branch" - << (children.size() != 1 ? "es" : "") << " with distribution " - << group.getDistributionSpec() << " {"; + out << " " << children.size() << " branch" << (children.size() != 1 ? "es" : "") + << " with distribution " << group.getDistributionSpec() << " {"; for (const auto & child : children) { printStateGroupwise(out, *child.second, verbose,indent + " ", false); } diff --git a/vdslib/src/vespa/vdslib/state/clusterstate.h b/vdslib/src/vespa/vdslib/state/clusterstate.h index 2630c4a2315..70f4d59977a 100644 --- a/vdslib/src/vespa/vdslib/state/clusterstate.h +++ b/vdslib/src/vespa/vdslib/state/clusterstate.h @@ -18,6 +18,7 @@ namespace storage::lib { class Distribution; class Group; struct NodeData; +struct SeparatorPrinter; class ClusterState : public document::Printable { public: @@ -70,6 +71,7 @@ private: void printStateGroupwise(std::ostream& out, const Group&, bool verbose, const std::string& indent, bool rootGroup) const; void getTextualDifference(std::ostringstream& builder, const NodeType& type, const ClusterState& other) const; size_t printStateGroupwise(std::ostream& out, const Group&, bool verbose, const std::string& indent, const NodeType& type) const; + void serialize_nodes(vespalib::asciistream & out, bool ignoreNewFeatures, SeparatorPrinter & sep, const NodeType & nodeType) const; uint32_t _version; NodeCounts _nodeCount; const State* _clusterState; -- cgit v1.2.3