diff options
author | Tor Egge <Tor.Egge@broadpark.no> | 2020-11-03 15:15:20 +0100 |
---|---|---|
committer | Tor Egge <Tor.Egge@broadpark.no> | 2020-11-03 15:59:45 +0100 |
commit | 288daaf3cee2deac1a40fc996450856ac4322396 (patch) | |
tree | abc7d4de2f89cefd2ae143f25dd9003f1531f8b3 /vdslib | |
parent | b5cd73513c0a8c701829edc572de5095897c818b (diff) |
Remove diskstate from vdslib.
Diffstat (limited to 'vdslib')
-rw-r--r-- | vdslib/src/tests/distribution/distributiontest.cpp | 173 | ||||
-rw-r--r-- | vdslib/src/tests/state/clusterstatetest.cpp | 82 | ||||
-rw-r--r-- | vdslib/src/vespa/vdslib/distribution/distribution.cpp | 99 | ||||
-rw-r--r-- | vdslib/src/vespa/vdslib/distribution/distribution.h | 20 | ||||
-rw-r--r-- | vdslib/src/vespa/vdslib/state/CMakeLists.txt | 1 | ||||
-rw-r--r-- | vdslib/src/vespa/vdslib/state/clusterstate.cpp | 6 | ||||
-rw-r--r-- | vdslib/src/vespa/vdslib/state/diskstate.cpp | 163 | ||||
-rw-r--r-- | vdslib/src/vespa/vdslib/state/diskstate.h | 45 | ||||
-rw-r--r-- | vdslib/src/vespa/vdslib/state/nodestate.cpp | 197 | ||||
-rw-r--r-- | vdslib/src/vespa/vdslib/state/nodestate.h | 18 | ||||
-rw-r--r-- | vdslib/src/vespa/vdslib/state/state.cpp | 17 | ||||
-rw-r--r-- | vdslib/src/vespa/vdslib/state/state.h | 6 |
12 files changed, 20 insertions, 807 deletions
diff --git a/vdslib/src/tests/distribution/distributiontest.cpp b/vdslib/src/tests/distribution/distributiontest.cpp index 5a337433bdb..d9ebba39916 100644 --- a/vdslib/src/tests/distribution/distributiontest.cpp +++ b/vdslib/src/tests/distribution/distributiontest.cpp @@ -280,30 +280,6 @@ struct MyTest { } return result; } - std::vector<uint16_t> getDiskCounts(uint16_t node) const { - std::vector<uint16_t> result(3, 0); - for (uint32_t i=0; i<_bucketsToTest; ++i) { - document::BucketId bucket(16, i); - std::vector<uint16_t> nodes; - ClusterState clusterState(_state); - _distribution->getIdealNodes( - *_nodeType, clusterState, bucket, nodes, - _upStates, _redundancy); - for (uint32_t j=0; j<nodes.size(); ++j) { - if (nodes[j] == node) { - const NodeState& nodeState(clusterState.getNodeState( - Node(NodeType::STORAGE, node))); - // If disk was down, bucket should not map to this - // node at all - uint16_t disk = _distribution->getIdealDisk( - nodeState, node, bucket, - Distribution::IDEAL_DISK_EVEN_IF_DOWN); - ++result[disk]; - } - } - } - return result; - } }; MyTest::MyTest() @@ -350,13 +326,6 @@ std::vector<uint16_t> createNodeCountList(const std::string& source, EXPECT_EQ(exp123, cnt123); \ } -#define ASSERT_BUCKET_DISK_COUNTS(node, test, result) \ -{ \ - std::vector<uint16_t> cnt123(test.getDiskCounts(node)); \ - std::vector<uint16_t> exp123(createNodeCountList(result, cnt123)); \ - EXPECT_EQ(exp123, cnt123); \ -} - TEST(DistributionTest, test_down) { ASSERT_BUCKET_NODE_COUNTS( @@ -370,14 +339,6 @@ TEST(DistributionTest, test_down) "0:+ 1:+ 2:+ 3:+ 8:+ 9:+"); } -TEST(DistributionTest, testDiskDown) -{ - ASSERT_BUCKET_DISK_COUNTS( - 2, - MyTest().state("storage:10 .2.d:3 .2.d.0:d"), - "1:+ 2:+"); -} - TEST(DistributionTest, test_serialize_deserialize) { MyTest t1; @@ -386,14 +347,6 @@ TEST(DistributionTest, test_serialize_deserialize) EXPECT_EQ(t1.getNodeCounts(), t2.getNodeCounts()); } -TEST(DistributionTest, test_disk_down_maintenance) -{ - ASSERT_BUCKET_DISK_COUNTS( - 2, - MyTest().state("storage:10 .2.s:m .2.d:3 .2.d.0:d").upStates("um"), - "1:+ 2:+"); -} - TEST(DistributionTest, test_initializing) { ASSERT_BUCKET_NODE_COUNTS( @@ -448,132 +401,6 @@ TEST(DistributionTest, testHighSplitBit) EXPECT_EQ(ost1.str(), ost2.str()); } -TEST(DistributionTest, test_disk_capacity_weights) -{ - uint16_t num_disks = 10; - std::vector<double> capacities(num_disks); - - RandomGen rg(13); - std::ostringstream ost; - ost << "d:" << num_disks; - for (unsigned i = 0; i < num_disks; ++i) { - capacities[i] = rg.nextDouble(); - ost << " d." << i << ".c:" << capacities[i]; - } - - NodeState nodeState(ost.str(), &NodeType::STORAGE); - - Distribution distr(Distribution::getDefaultDistributionConfig(2, 3)); - - for(int j=0; j < 10; ++j) { - std::vector<float> diskDist(num_disks); - for(int i=0; i < 1000; ++i) { - document::BucketId id(16, i); - int index = distr.getPreferredAvailableDisk(nodeState, j, id); - diskDist[index]+=1; - } - - //normalization - for (unsigned i = 0; i < num_disks; ++i) { - diskDist[i] /= capacities[i]; - } - - std::sort(diskDist.begin(), diskDist.end()); - - double avg=0.0; - for (unsigned i = 0; i < num_disks; ++i) { - avg+=diskDist[i]; - } - avg /= num_disks; - - double skew = (diskDist[num_disks-1]-avg)/(diskDist[num_disks-1]); - - EXPECT_LT(skew, 0.3); - } -} - -TEST(DistributionTest, test_disk_skew_local) -{ - Distribution distr(Distribution::getDefaultDistributionConfig(2, 3, Distribution::MODULO_INDEX)); - std::vector<float> diskDist(100); - NodeState nodeState; - nodeState.setDiskCount(100); - for(int i=0; i < 65536; i++) { - document::BucketId id(16, i); - int index = distr.getPreferredAvailableDisk(nodeState, 7, id); - diskDist[index]+=1; - } - - std::sort(diskDist.begin(), diskDist.end()); - - EXPECT_LT((diskDist[99]-diskDist[0])/(diskDist[99]), 0.05); -} - -TEST(DistributionTest, test_disk_skew_global) -{ - uint16_t num_disks = 10; - uint16_t num_nodes = 10; - Distribution distr(Distribution::getDefaultDistributionConfig(2, num_nodes, Distribution::MODULO_INDEX)); - std::vector<std::vector<float> > diskDist(num_nodes, std::vector<float>(num_disks)); - NodeState nodeState; - nodeState.setDiskCount(num_disks); - for(uint16_t idx=0; idx < num_nodes; idx++) { - for(int i=0; i < 1000; i++) { - document::BucketId id(16, i); - int diskIndex = distr.getPreferredAvailableDisk(nodeState, idx, id); - diskDist[idx][diskIndex]+=1; - } - } - - std::vector<float> diskDist2; - for(uint16_t idx=0; idx < num_nodes; idx++) { - for(uint16_t d=0; d < num_disks; d++) { - diskDist2.push_back(diskDist[idx][d]); - } - } - - std::sort(diskDist2.begin(), diskDist2.end()); - - double skew = (diskDist2[num_nodes*num_disks-1]-diskDist2[0])/(diskDist2[num_nodes*num_disks-1]); - - EXPECT_LT(skew, 0.2); -} - -TEST(DistributionTest, test_disk_intersection) -{ - uint16_t num_disks = 8; - uint16_t num_nodes = 20; - float max = 0; - Distribution distr(Distribution::getDefaultDistributionConfig(2, num_nodes, Distribution::MODULO_INDEX)); - - NodeState nodeState; - nodeState.setDiskCount(num_disks); - - for(uint16_t i=0; i < num_nodes-1; i++) { - for(uint16_t j=i+1; j < num_nodes; j++) { - uint64_t count =0; -//std::cerr << "Comparing node " << i << " and node " << j << ":\n"; - for(int b=0; b < 1000; b++) { - document::BucketId id(16, b); - int idxI = distr.getPreferredAvailableDisk(nodeState, i, id); - int idxJ = distr.getPreferredAvailableDisk(nodeState, j, id); -//if (b < 50) std::cerr << " " << b << ": " << idxI << ", " << idxJ << "\n"; - if(idxI == idxJ){ - count++; - } - } - if(count > max){ - max = count; - } - } - } - if (max / 1000 > 0.5) { - std::ostringstream ost; - ost << "Value of " << max << " / " << 1000 << " is more than 0.5"; - FAIL() << ost.str(); - } -} - TEST(DistributionTest, test_distribution) { const int min_buckets = 1024*64; diff --git a/vdslib/src/tests/state/clusterstatetest.cpp b/vdslib/src/tests/state/clusterstatetest.cpp index 143f3aed0e9..1880683232d 100644 --- a/vdslib/src/tests/state/clusterstatetest.cpp +++ b/vdslib/src/tests/state/clusterstatetest.cpp @@ -78,13 +78,6 @@ TEST(ClusterStateTest, test_basic_functionality) VERIFYNEW("storage:10 .1.s:i .2.s:u .3.s:d .4.s:m .5.s:r", "storage:10 .1.s:i .1.i:0 .3.s:d .4.s:m .5.s:r"); - // Test legal disk states - VERIFYNEW("storage:10 .1.d:4 .1.d.0.s:u .1.d.1.s:d", - "storage:10 .1.d:4 .1.d.1.s:d"); - - // Test other disk properties - VERIFYSAMENEW("storage:10 .1.d:4 .1.d.0.c:1.4"); - // Test other distributor node propertise // (Messages is excluded from system states to not make them too long as // most nodes have no use for them) @@ -143,20 +136,10 @@ TEST(ClusterStateTest, test_error_behaviour) // VERIFY_FAIL("distributor:4 .2.s:r", // "Retired is not a legal distributor state"); - // Test illegal storage states - VERIFY_FAIL("storage:4 .2.d:2 .2.d.5.s:d", "Cannot index disk 5 of 2"); - // Test blatantly illegal values for known attributes: VERIFY_FAIL("distributor:4 .2.s:z", "Unknown state z given.*"); VERIFY_FAIL("distributor:4 .2.i:foobar", ".*Init progress must be a floating point number from .*"); - VERIFY_FAIL("storage:4 .2.d:foobar", "Invalid disk count 'foobar'. Need.*"); - VERIFY_FAIL("storage:4 .2.d:2 .2.d.1.s:foobar", - "Unknown state foobar given.*"); - VERIFY_FAIL("storage:4 .2.d:2 .2.d.1.c:foobar", - "Illegal disk capacity 'foobar'. Capacity must be a .*"); - VERIFY_FAIL("storage:4 .2.d:2 .2.d.a.s:d", - "Invalid disk index 'a'. Need a positive integer .*"); // Lacking absolute path first VERIFY_FAIL(".2.s:d distributor:4", "The first path in system state.*"); @@ -168,34 +151,7 @@ TEST(ClusterStateTest, test_error_behaviour) VERIFYNEW("distributor:4 .2:foo storage:5 .4:d", "distributor:4 storage:5"); VERIFYNEW("ballalaika:true distributor:4 .2.urk:oj .2.z:foo .2.s:s " ".2.j:foo storage:10 .3.d:4 .3.d.2.a:boo .3.s:s", - "distributor:4 .2.s:s storage:10 .3.s:s .3.d:4"); -} - -TEST(ClusterStateTest, test_backwards_compability) -{ - // 4.1 and older nodes do not support some features, and the java parser - // do not allow unknown elements as it was supposed to do, thus we should - // avoid using new features when talking to 4.1 nodes. - - // - 4.1 nodes should not see new cluster, version, initializing and - // description tags. - VERIFYOLD("version:4 cluster:i storage:2 .0.s:i .0.i:0.5 .1.m:foobar", - "distributor:0 storage:2 .0.s:i"); - - // - 4.1 nodes have only one disk property being state, so in 4.1, a - // disk state is typically set as .4.d.2:d while in new format it - // specifies that this is the state .4.d.2.s:d - VERIFYSAMEOLD("distributor:0 storage:3 .2.d:10 .2.d.4:d"); - VERIFYOLD("distributor:0 storage:3 .2.d:10 .2.d.4.s:d", - "distributor:0 storage:3 .2.d:10 .2.d.4:d"); - - // - 4.1 nodes should always have distributor and storage tags with counts. - VERIFYOLD("storage:4", "distributor:0 storage:4"); - VERIFYOLD("distributor:4", "distributor:4 storage:0"); - - // - 4.1 nodes should not see the state stopping - VERIFYOLD("storage:4 .2.s:s", "distributor:0 storage:4 .2.s:d"); - + "distributor:4 .2.s:s storage:10 .3.s:s"); } TEST(ClusterStateTest, test_detailed) @@ -249,41 +205,7 @@ TEST(ClusterStateTest, test_detailed) } else { EXPECT_EQ(State::UP, ns.getState()); } - // Test disk states - if (i == 2) { - EXPECT_EQ(uint16_t(16), ns.getDiskCount()); - } else if (i == 8) { - EXPECT_EQ(uint16_t(10), ns.getDiskCount()); - } else { - EXPECT_EQ(uint16_t(0), ns.getDiskCount()); - } - if (i == 2) { - for (uint16_t j = 0; j < 16; ++j) { - if (j == 3) { - EXPECT_EQ(State::DOWN, - ns.getDiskState(j).getState()); - } else { - EXPECT_EQ(State::UP, - ns.getDiskState(j).getState()); - } - } - } else if (i == 8) { - for (uint16_t j = 0; j < 10; ++j) { - if (j == 4) { - EXPECT_DOUBLE_EQ(0.6, ns.getDiskState(j).getCapacity().getValue()); - EXPECT_EQ( - string("small"), - ns.getDiskState(j).getDescription()); - } else { - EXPECT_DOUBLE_EQ( - 1.0, ns.getDiskState(j).getCapacity().getValue()); - EXPECT_EQ( - string(""), - ns.getDiskState(j).getDescription()); - } - } - } - // Test message + // Test message if (i == 6) { EXPECT_EQ(string("bar\tfoo"), ns.getDescription()); } else { diff --git a/vdslib/src/vespa/vdslib/distribution/distribution.cpp b/vdslib/src/vespa/vdslib/distribution/distribution.cpp index 474ed63e8c3..c9e1fd1bef6 100644 --- a/vdslib/src/vespa/vdslib/distribution/distribution.cpp +++ b/vdslib/src/vespa/vdslib/distribution/distribution.cpp @@ -237,48 +237,6 @@ Distribution::getStorageSeed( return seed; } -uint32_t -Distribution::getDiskSeed(const document::BucketId& bucket, uint16_t nodeIndex) const -{ - switch (_diskDistribution) { - case DiskDistribution::MODULO: - { - uint32_t seed(static_cast<uint32_t>(bucket.getRawId()) - & _distributionBitMasks[16]); - return 0xdeadbeef ^ seed; - } - case DiskDistribution::MODULO_INDEX: - { - uint32_t seed(static_cast<uint32_t>(bucket.getRawId()) - & _distributionBitMasks[16]); - return 0xdeadbeef ^ seed ^ nodeIndex; - } - case DiskDistribution::MODULO_KNUTH: - { - uint32_t seed(static_cast<uint32_t>(bucket.getRawId()) - & _distributionBitMasks[16]); - return 0xdeadbeef ^ seed ^ (1664525L * nodeIndex + 1013904223L); - } - case DiskDistribution::MODULO_BID: - { - uint64_t currentid = bucket.withoutCountBits(); - char ordered[8]; - ordered[0] = currentid >> (0*8); - ordered[1] = currentid >> (1*8); - ordered[2] = currentid >> (2*8); - ordered[3] = currentid >> (3*8); - ordered[4] = currentid >> (4*8); - ordered[5] = currentid >> (5*8); - ordered[6] = currentid >> (6*8); - ordered[7] = currentid >> (7*8); - uint32_t initval = (1664525 * nodeIndex + 0xdeadbeef); - return vespalib::BobHash::hash(ordered, 8, initval); - } - } - throw vespalib::IllegalStateException("Unknown disk distribution: " - + getDiskDistributionName(_diskDistribution), VESPA_STRLOC); -} - vespalib::string Distribution::getDiskDistributionName(DiskDistribution dist) { return DistributionConfig::getDiskDistributionName(toConfig(dist)); @@ -294,57 +252,6 @@ Distribution::print(std::ostream& out, bool, const std::string&) const { out << serialize(); } -// This function should only depend on disk distribution and node index. It is -// assumed that any other change, for instance in hierarchical grouping, does -// not change disk index on disk. -uint16_t -Distribution::getIdealDisk(const NodeState& nodeState, uint16_t nodeIndex, - const document::BucketId& bucket, - DISK_MODE flag) const -{ - // Catch special cases in a single if statement - if (nodeState.getDiskCount() < 2) { - if (nodeState.getDiskCount() == 1) return 0; - throw vespalib::IllegalArgumentException( - "Cannot pick ideal disk without knowing disk count.", - VESPA_STRLOC); - } - RandomGen randomizer(getDiskSeed(bucket, nodeIndex)); - switch (_diskDistribution) { - case DiskDistribution::MODULO_BID: - { - double maxScore = 0.0; - uint16_t idealDisk = 0xffff; - for (uint32_t i=0, n=nodeState.getDiskCount(); i<n; ++i) { - double score = randomizer.nextDouble(); - const DiskState& diskState(nodeState.getDiskState(i)); - if (flag == BEST_AVAILABLE_DISK - && !diskState.getState().oneOf("uis")) - { - continue; - } - if (diskState.getCapacity() != 1.0) { - score = std::pow(score, - 1.0 / diskState.getCapacity().getValue()); - } - if (score > maxScore) { - maxScore = score; - idealDisk = i; - } - } - if (idealDisk == 0xffff) { - throw vespalib::IllegalStateException( - "There are no available disks.", VESPA_STRLOC); - } - return idealDisk; - } - default: - { - return randomizer.nextUint32() % nodeState.getDiskCount(); - } - } -} - namespace { /** Used to record scored groups during ideal groups calculation. */ @@ -579,12 +486,6 @@ Distribution::getIdealNodes(const NodeType& nodeType, // seed if the node that is out of order is illegal anyways. const NodeState& nodeState(clusterState.getNodeState(Node(nodeType, nodes[j]))); if (!nodeState.getState().oneOf(upStates)) continue; - if (nodeState.isAnyDiskDown()) { - uint16_t idealDiskIndex(getIdealDisk(nodeState, nodes[j], bucket, IDEAL_DISK_EVEN_IF_DOWN)); - if (nodeState.getDiskState(idealDiskIndex).getState() != State::UP) { - continue; - } - } // Get the score from the random number generator. Make sure we // pick correct random number. Optimize for the case where we // pick in rising order. diff --git a/vdslib/src/vespa/vdslib/distribution/distribution.h b/vdslib/src/vespa/vdslib/distribution/distribution.h index 14146af918f..db68f123cbf 100644 --- a/vdslib/src/vespa/vdslib/distribution/distribution.h +++ b/vdslib/src/vespa/vdslib/distribution/distribution.h @@ -77,15 +77,6 @@ private: */ uint32_t getStorageSeed( const document::BucketId&, const ClusterState&) const; - /** - * Get seed to use for ideal state algorithm's random number generator - * to decide which disk on a storage node this bucket should be mapped to. - * Uses node index to ensure that copies of buckets goes to different disks - * on different nodes, such that 2 disks missing will have less overlapping - * data and all disks will add on some extra load if one disk goes missing. - */ - uint32_t getDiskSeed( - const document::BucketId&, uint16_t nodeIndex) const; void getIdealGroups(const document::BucketId& bucket, const ClusterState& clusterState, @@ -144,17 +135,6 @@ public: void print(std::ostream& out, bool, const std::string&) const override; - enum DISK_MODE { - IDEAL_DISK_EVEN_IF_DOWN, - BEST_AVAILABLE_DISK - }; - uint16_t getIdealDisk(const NodeState&, uint16_t nodeIndex, - const document::BucketId&, DISK_MODE flag) const; - - uint16_t getPreferredAvailableDisk(const NodeState& ns, uint16_t nodeIndex, - const document::BucketId& bucket) const - { return getIdealDisk(ns, nodeIndex, bucket, BEST_AVAILABLE_DISK); } - /** Simplified wrapper for getIdealNodes() */ std::vector<uint16_t> getIdealStorageNodes( const ClusterState&, const document::BucketId&, diff --git a/vdslib/src/vespa/vdslib/state/CMakeLists.txt b/vdslib/src/vespa/vdslib/state/CMakeLists.txt index 620e86c2677..f6bff6ce9a7 100644 --- a/vdslib/src/vespa/vdslib/state/CMakeLists.txt +++ b/vdslib/src/vespa/vdslib/state/CMakeLists.txt @@ -4,7 +4,6 @@ vespa_add_library(vdslib_state OBJECT nodetype.cpp node.cpp state.cpp - diskstate.cpp nodestate.cpp clusterstate.cpp cluster_state_bundle.cpp diff --git a/vdslib/src/vespa/vdslib/state/clusterstate.cpp b/vdslib/src/vespa/vdslib/state/clusterstate.cpp index b90e78104fc..ff792517bf9 100644 --- a/vdslib/src/vespa/vdslib/state/clusterstate.cpp +++ b/vdslib/src/vespa/vdslib/state/clusterstate.cpp @@ -217,8 +217,7 @@ ClusterState::serialize(vespalib::asciistream & out, bool ignoreNewFeatures) con vespalib::asciistream prefix; prefix << "." << it->first.getIndex() << "."; vespalib::asciistream ost; - it->second.serialize(ost, prefix.str(), false, false, - ignoreNewFeatures); + it->second.serialize(ost, prefix.str(), false); vespalib::stringref content = ost.str(); if (content.size() > 0) { out << " " << content; @@ -236,8 +235,7 @@ ClusterState::serialize(vespalib::asciistream & out, bool ignoreNewFeatures) con vespalib::asciistream prefix; prefix << "." << it->first.getIndex() << "."; vespalib::asciistream ost; - it->second.serialize(ost, prefix.str(), false, false, - ignoreNewFeatures); + it->second.serialize(ost, prefix.str(), false); vespalib::stringref content = ost.str(); if ( !content.empty()) { out << " " << content; diff --git a/vdslib/src/vespa/vdslib/state/diskstate.cpp b/vdslib/src/vespa/vdslib/state/diskstate.cpp deleted file mode 100644 index 0147b422a8e..00000000000 --- a/vdslib/src/vespa/vdslib/state/diskstate.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "diskstate.h" -#include <boost/lexical_cast.hpp> -#include <vespa/vespalib/text/stringtokenizer.h> -#include <vespa/document/util/stringutil.h> -#include <vespa/vespalib/util/exceptions.h> -#include <vespa/vespalib/stllike/asciistream.h> -#include <vespa/log/log.h> - -LOG_SETUP(".vdslib.diskstate"); - -namespace storage::lib { - -DiskState::DiskState() - : _state(0), - _description(""), - _capacity(1.0) -{ - setState(State::UP); -} - -DiskState::DiskState(const State& state, vespalib::stringref description, - double capacity) - : _state(0), - _description(description), - _capacity(1.0) -{ - setState(state); - setCapacity(capacity); -} - -DiskState::DiskState(vespalib::stringref serialized) - : _state(&State::UP), - _description(""), - _capacity(1.0) -{ - vespalib::StringTokenizer st(serialized, " \t\f\r\n"); - st.removeEmptyTokens(); - for (vespalib::StringTokenizer::Iterator it = st.begin(); - it != st.end(); ++it) - { - std::string::size_type index = it->find(':'); - if (index == std::string::npos) { - throw vespalib::IllegalArgumentException( - "Token " + *it + " does not contain ':': " + serialized, - VESPA_STRLOC); - } - std::string key = it->substr(0, index); - std::string value = it->substr(index + 1); - if (key.size() > 0) switch (key[0]) { - case 's': - if (key.size() > 1) break; - setState(State::get(value)); - continue; - case 'c': - if (key.size() > 1) break; - try{ - setCapacity(boost::lexical_cast<double>(value)); - } catch (...) { - throw vespalib::IllegalArgumentException( - "Illegal disk capacity '" + value + "'. Capacity " - "must be a positive floating point number", - VESPA_STRLOC); - } - continue; - case 'm': - if (key.size() > 1) break; - _description = document::StringUtil::unescape(value); - continue; - default: - break; - } - LOG(debug, "Unknown key %s in diskstate. Ignoring it, assuming it's a " - "new feature from a newer version than ourself: %s", - key.c_str(), vespalib::string(serialized).c_str()); - } - -} - -void -DiskState::serialize(vespalib::asciistream & out, vespalib::stringref prefix, - bool includeDescription, bool useOldFormat) const -{ - // Always give node state if not part of a system state - // to prevent empty serialization - bool empty = true; - if (*_state != State::UP || prefix.size() == 0) { - if (useOldFormat && prefix.size() > 0) { - out << prefix.substr(0, prefix.size() - 1) - << ":" << _state->serialize(); - } else { - out << prefix << "s:" << _state->serialize(); - } - empty = false; - } - if (_capacity != 1.0) { - if (empty) { empty = false; } else { out << ' '; } - out << prefix << "c:" << _capacity; - } - if (includeDescription && _description.size() > 0) { - if (empty) { empty = false; } else { out << ' '; } - out << prefix << "m:" - << document::StringUtil::escape(_description, ' '); - } -} - - -void -DiskState::setState(const State& state) -{ - if (!state.validDiskState()) { - throw vespalib::IllegalArgumentException( - "State " + state.toString() + " is not a valid disk state.", - VESPA_STRLOC); - } - _state = &state; -} - -void -DiskState::setCapacity(double capacity) -{ - if (capacity < 0) { - throw vespalib::IllegalArgumentException( - "Negative capacity makes no sense.", VESPA_STRLOC); - } - _capacity = capacity; -} - -void -DiskState::print(std::ostream& out, bool verbose, - const std::string& indent) const -{ - (void) indent; - if (verbose) { - out << "DiskState(" << *_state; - } else { - out << _state->serialize(); - } - if (_capacity != 1.0) { - out << (verbose ? ", capacity " : ", c ") << _capacity; - } - if (_description.size() > 0) { - out << ": " << _description; - } - if (verbose) { - out << ")"; - } -} - -bool -DiskState::operator==(const DiskState& other) const -{ - return (_state == other._state && _capacity == other._capacity); -} - -bool -DiskState::operator!=(const DiskState& other) const -{ - return (_state != other._state || _capacity != other._capacity); -} - -} diff --git a/vdslib/src/vespa/vdslib/state/diskstate.h b/vdslib/src/vespa/vdslib/state/diskstate.h deleted file mode 100644 index cb28e24daac..00000000000 --- a/vdslib/src/vespa/vdslib/state/diskstate.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -/** - * @class vdslib::DiskState - * - * Defines the state a given disk can have. - */ -#pragma once - -#include "state.h" -#include <vespa/document/util/printable.h> -#include <vespa/vespalib/objects/floatingpointtype.h> - -namespace storage::lib { - -class DiskState : public document::Printable { - const State* _state; - vespalib::string _description; - vespalib::Double _capacity; - -public: - typedef std::shared_ptr<const DiskState> CSP; - typedef std::shared_ptr<DiskState> SP; - - DiskState(); - DiskState(const State&, vespalib::stringref description = "", double capacity = 1.0); - explicit DiskState(vespalib::stringref serialized); - - void serialize(vespalib::asciistream & out, vespalib::stringref prefix = "", - bool includeReason = true, bool useOldFormat = false) const; - - const State& getState() const { return *_state; } - vespalib::Double getCapacity() const { return _capacity; } - const vespalib::string& getDescription() const { return _description; } - - void setState(const State& state); - void setCapacity(double capacity); - void setDescription(vespalib::stringref desc) { _description = desc; } - - void print(std::ostream& out, bool verbose, const std::string& indent) const override; - bool operator==(const DiskState& other) const; - bool operator!=(const DiskState& other) const; - -}; - -} diff --git a/vdslib/src/vespa/vdslib/state/nodestate.cpp b/vdslib/src/vespa/vdslib/state/nodestate.cpp index 41d42fd5c6f..fc4e18fa0cc 100644 --- a/vdslib/src/vespa/vdslib/state/nodestate.cpp +++ b/vdslib/src/vespa/vdslib/state/nodestate.cpp @@ -29,8 +29,6 @@ NodeState::NodeState() _reliability(1), _initProgress(0.0), _minUsedBits(16), - _diskStates(), - _anyDiskDown(false), _startTimestamp(0) { setState(State::UP); @@ -46,8 +44,6 @@ NodeState::NodeState(const NodeType& type, const State& state, _reliability(1), _initProgress(0.0), _minUsedBits(16), - _diskStates(), - _anyDiskDown(false), _startTimestamp(0) { setState(state); @@ -57,27 +53,6 @@ NodeState::NodeState(const NodeType& type, const State& state, } } -namespace { - struct DiskData { - bool empty; - uint16_t diskIndex; - std::ostringstream ost; - - DiskData() : empty(true), diskIndex(0), ost() {} - - void addTo(std::vector<DiskState>& diskStates) { - if (!empty) { - while (diskIndex >= diskStates.size()) { - diskStates.push_back(DiskState(State::UP)); - } - diskStates[diskIndex] = DiskState(ost.str()); - empty = true; - ost.str(""); - } - } - }; -} - NodeState::NodeState(vespalib::stringref serialized, const NodeType* type) : _type(type), _state(&State::UP), @@ -86,14 +61,11 @@ NodeState::NodeState(vespalib::stringref serialized, const NodeType* type) _reliability(1), _initProgress(0.0), _minUsedBits(16), - _diskStates(), - _anyDiskDown(false), _startTimestamp(0) { vespalib::StringTokenizer st(serialized, " \t\f\r\n"); st.removeEmptyTokens(); - DiskData diskData; for (vespalib::StringTokenizer::Iterator it = st.begin(); it != st.end(); ++it) { @@ -172,58 +144,6 @@ NodeState::NodeState(vespalib::stringref serialized, const NodeType* type) if (key.size() > 1) break; _description = document::StringUtil::unescape(value); continue; - case 'd': - { - if (_type != 0 && *type != NodeType::STORAGE) break; - if (key.size() == 1) { - uint16_t size(0); - try{ - size = boost::lexical_cast<uint16_t>(value); - } catch (...) { - throw vespalib::IllegalArgumentException( - "Invalid disk count '" + value + "'. Need a " - "positive integer value", VESPA_STRLOC); - } - while (_diskStates.size() < size) { - _diskStates.push_back(DiskState(State::UP)); - } - continue; - } - if (key[1] != '.') break; - uint16_t diskIndex; - std::string::size_type endp = key.find('.', 2); - std::string indexStr; - if (endp == std::string::npos) { - indexStr = key.substr(2); - } else { - indexStr = key.substr(2, endp - 2); - } - try{ - diskIndex = boost::lexical_cast<uint16_t>(indexStr); - } catch (...) { - throw vespalib::IllegalArgumentException( - "Invalid disk index '" + indexStr + "'. Need a " - "positive integer value", VESPA_STRLOC); - } - if (diskIndex >= _diskStates.size()) { - std::ostringstream ost; - ost << "Cannot index disk " << diskIndex << " of " - << _diskStates.size(); - throw vespalib::IllegalArgumentException( - ost.str(), VESPA_STRLOC); - } - if (diskData.diskIndex != diskIndex) { - diskData.addTo(_diskStates); - } - if (endp == std::string::npos) { - diskData.ost << " s:" << value; - } else { - diskData.ost << " " << key.substr(endp + 1) << ':' << value; - } - diskData.diskIndex = diskIndex; - diskData.empty = false; - continue; - } default: break; } @@ -231,19 +151,6 @@ NodeState::NodeState(vespalib::stringref serialized, const NodeType* type) "new feature from a newer version than ourself: %s", key.c_str(), vespalib::string(serialized).c_str()); } - diskData.addTo(_diskStates); - updateAnyDiskDownFlag(); -} - -void -NodeState::updateAnyDiskDownFlag() { - bool anyDown = false; - for (uint32_t i=0; i<_diskStates.size(); ++i) { - if (_diskStates[i].getState() != State::UP) { - anyDown = true; - } - } - _anyDiskDown = anyDown; } namespace { @@ -270,19 +177,14 @@ namespace { void NodeState::serialize(vespalib::asciistream & out, vespalib::stringref prefix, - bool includeDescription, bool includeDiskDescription, - bool useOldFormat) const + bool includeDescription) const { SeparatorPrinter sep; // Always give node state if not part of a system state // to prevent empty serialization if (*_state != State::UP || prefix.size() == 0) { out << sep << prefix << "s:"; - if (useOldFormat && *_state == State::STOPPING) { - out << State::DOWN.serialize(); - } else { - out << _state->serialize(); - } + out << _state->serialize(); } if (_capacity != 1.0) { out << sep << prefix << "c:" << _capacity; @@ -293,45 +195,18 @@ NodeState::serialize(vespalib::asciistream & out, vespalib::stringref prefix, if (_minUsedBits != 16) { out << sep << prefix << "b:" << _minUsedBits; } - if (*_state == State::INITIALIZING && !useOldFormat) { + if (*_state == State::INITIALIZING) { out << sep << prefix << "i:" << _initProgress; } if (_startTimestamp != 0) { out << sep << prefix << "t:" << _startTimestamp; } - if (_diskStates.size() > 0) { - out << sep << prefix << "d:" << _diskStates.size(); - for (uint16_t i = 0; i < _diskStates.size(); ++i) { - vespalib::asciistream diskPrefix; - diskPrefix << prefix << "d." << i << "."; - vespalib::asciistream disk; - _diskStates[i].serialize(disk, diskPrefix.str(), - includeDiskDescription, useOldFormat); - if ( ! disk.str().empty()) { - out << " " << disk.str(); - } - } - } if (includeDescription && ! _description.empty()) { out << sep << prefix << "m:" << document::StringUtil::escape(_description, ' '); } } -const DiskState& -NodeState::getDiskState(uint16_t index) const -{ - static const DiskState defaultState(State::UP); - if (_diskStates.size() == 0) return defaultState; - if (index >= _diskStates.size()) { - std::ostringstream ost; - ost << "Cannot get status of disk " << index << " of " - << _diskStates.size() << "."; - throw vespalib::IllegalArgumentException(ost.str(), VESPA_STRLOC); - } - return _diskStates[index]; -} - void NodeState::setState(const State& state) { @@ -412,32 +287,6 @@ NodeState::setStartTimestamp(uint64_t startTimestamp) } void -NodeState::setDiskCount(uint16_t count) -{ - while (_diskStates.size() > count) { - _diskStates.pop_back(); - } - _diskStates.reserve(count); - while (_diskStates.size() < count) { - _diskStates.push_back(DiskState(State::UP)); - } - updateAnyDiskDownFlag(); -} - -void -NodeState::setDiskState(uint16_t index, const DiskState& state) -{ - if (index >= _diskStates.size()) { - throw vespalib::IllegalArgumentException( - vespalib::make_string("Can't set state of disk %u of %u.", - index, (uint32_t) _diskStates.size()), - VESPA_STRLOC); - } - _diskStates[index] = state; - updateAnyDiskDownFlag(); -} - -void NodeState::print(std::ostream& out, bool verbose, const std::string& indent) const { @@ -463,20 +312,6 @@ NodeState::print(std::ostream& out, bool verbose, if (_startTimestamp != 0) { out << ", start timestamp " << _startTimestamp; } - if (_diskStates.size() > 0) { - bool printedHeader = false; - for (uint32_t i=0; i<_diskStates.size(); ++i) { - if (_diskStates[i] != DiskState(State::UP)) { - if (!printedHeader) { - out << ","; - printedHeader = true; - } - out << " Disk " << i << "("; - _diskStates[i].print(out, false, indent); - out << ")"; - } - } - } if (_description.size() > 0) { out << ": " << _description; } @@ -495,13 +330,6 @@ NodeState::operator==(const NodeState& other) const { return false; } - for (uint32_t i=0, n=std::max(_diskStates.size(), other._diskStates.size()); - i < n; ++i) - { - if (getDiskState(i) != other.getDiskState(i)) { - return false; - } - } return true; } @@ -524,13 +352,6 @@ NodeState::similarTo(const NodeState& other) const return false; } } - for (uint32_t i=0, n=std::max(_diskStates.size(), other._diskStates.size()); - i < n; ++i) - { - if (getDiskState(i) != other.getDiskState(i)) { - return false; - } - } return true; } @@ -589,18 +410,6 @@ NodeState::getTextualDifference(const NodeState& other) const { target << ", start timestamp " << other._startTimestamp; } - if (_diskStates.size() != other._diskStates.size()) { - source << ", " << _diskStates.size() << " disks"; - target << ", " << other._diskStates.size() << " disks"; - } else { - for (uint32_t i=0; i<_diskStates.size(); ++i) { - if (_diskStates[i] != other._diskStates[i]) { - source << ", disk " << i << _diskStates[i]; - target << ", disk " << i << other._diskStates[i]; - } - } - } - if (source.str().length() < 2 || target.str().length() < 2) { return "no change"; } diff --git a/vdslib/src/vespa/vdslib/state/nodestate.h b/vdslib/src/vespa/vdslib/state/nodestate.h index 6317cb3fa84..a313c35704d 100644 --- a/vdslib/src/vespa/vdslib/state/nodestate.h +++ b/vdslib/src/vespa/vdslib/state/nodestate.h @@ -10,8 +10,9 @@ */ #pragma once -#include "diskstate.h" +#include "state.h" #include <vespa/document/bucket/bucketidfactory.h> +#include <vespa/vespalib/objects/floatingpointtype.h> namespace storage::lib { @@ -24,12 +25,8 @@ class NodeState : public document::Printable uint16_t _reliability; vespalib::Double _initProgress; uint32_t _minUsedBits; - std::vector<DiskState> _diskStates; - bool _anyDiskDown; uint64_t _startTimestamp; - void updateAnyDiskDownFlag(); - public: typedef std::shared_ptr<const NodeState> CSP; typedef std::shared_ptr<NodeState> SP; @@ -55,9 +52,7 @@ public: * recreate the nodestate with NodeState(string) function. */ void serialize(vespalib::asciistream & out, vespalib::stringref prefix = "", - bool includeDescription = true, - bool includeDiskDescription = false, - bool useOldFormat = false) const; + bool includeDescription = true) const; const State& getState() const { return *_state; } vespalib::Double getCapacity() const { return _capacity; } @@ -67,10 +62,6 @@ public: const vespalib::string& getDescription() const { return _description; } uint64_t getStartTimestamp() const { return _startTimestamp; } - bool isAnyDiskDown() const { return _anyDiskDown; } - uint16_t getDiskCount() const { return _diskStates.size(); } - const DiskState& getDiskState(uint16_t index) const; - void setState(const State& state); void setCapacity(vespalib::Double capacity); void setMinUsedBits(uint32_t usedBits); @@ -79,9 +70,6 @@ public: void setStartTimestamp(uint64_t startTimestamp); void setDescription(vespalib::stringref desc) { _description = desc; } - void setDiskCount(uint16_t count); - void setDiskState(uint16_t index, const DiskState&); - void print(std::ostream& out, bool verbose, const std::string& indent) const override; bool operator==(const NodeState& other) const; diff --git a/vdslib/src/vespa/vdslib/state/state.cpp b/vdslib/src/vespa/vdslib/state/state.cpp index 5bf95b5530b..96829905c8a 100644 --- a/vdslib/src/vespa/vdslib/state/state.cpp +++ b/vdslib/src/vespa/vdslib/state/state.cpp @@ -8,19 +8,19 @@ namespace storage { namespace lib { const State State::UNKNOWN("Unknown", "-", 0, - false, true, true, false, false, false); + true, true, false, false, false); const State State::MAINTENANCE("Maintenance", "m", 1, - false, false, false, true, true, false); + false, false, true, true, false); const State State::DOWN("Down", "d", 2, - true, false, false, true, true, true); + false, false, true, true, true); const State State::STOPPING("Stopping", "s", 3, - false, true, true, false, false, true); + true, true, false, false, true); const State State::INITIALIZING("Initializing", "i", 4, - false, true, true, false, false, true); + true, true, false, false, true); const State State::RETIRED("Retired", "r", 5, - false, false, false, true, true, false); + false, false, true, true, false); const State State::UP("Up", "u", 6, - true, true, true, true, true, true); + true, true, true, true, true); const State& State::get(vespalib::stringref serialized) @@ -40,14 +40,13 @@ State::get(vespalib::stringref serialized) } State::State(vespalib::stringref name, vespalib::stringref serialized, - uint8_t rank, bool validDisk, + uint8_t rank, bool validDistributorReported, bool validStorageReported, bool validDistributorWanted, bool validStorageWanted, bool validCluster) : _name(name), _serialized(serialized), _rankValue(rank), - _validDiskState(validDisk), _validReportedNodeState(2), _validWantedNodeState(2), _validClusterState(validCluster) diff --git a/vdslib/src/vespa/vdslib/state/state.h b/vdslib/src/vespa/vdslib/state/state.h index bec500a082d..61747f5eed2 100644 --- a/vdslib/src/vespa/vdslib/state/state.h +++ b/vdslib/src/vespa/vdslib/state/state.h @@ -4,7 +4,7 @@ * * Defines legal states for various uses. Split this into its own class such * that we can easily see what states are legal to use in what situations. - * They double as disk states and node states nodes report they are in, and + * They double as node states nodes report they are in, and * wanted states set external sources. */ #pragma once @@ -20,14 +20,13 @@ class State : public vespalib::Printable { vespalib::string _name; vespalib::string _serialized; uint8_t _rankValue; - bool _validDiskState; std::vector<bool> _validReportedNodeState; std::vector<bool> _validWantedNodeState; bool _validClusterState; State(const State&); State(vespalib::stringref name, vespalib::stringref serialized, - uint8_t rank, bool validDisk, + uint8_t rank, bool validDistributorReported, bool validStorageReported, bool validDistributorWanted, bool validStorageWanted, bool validCluster); @@ -48,7 +47,6 @@ public: static const State& get(vespalib::stringref serialized); const vespalib::string& serialize() const { return _serialized; } - bool validDiskState() const { return _validDiskState; } bool validReportedNodeState(const NodeType& node) const { return _validReportedNodeState[node]; } bool validWantedNodeState(const NodeType& node) const |