diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2023-08-09 17:36:52 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2023-08-10 09:08:09 +0000 |
commit | aa9cfaf526fa4cd0859dfaf47e50d5e02268161b (patch) | |
tree | 2a049970c7b1075c044d89df624d947ef1a4d217 | |
parent | 16ade10496858b0046e45d44052170be381e503f (diff) |
Avoid copying the ideal state out from the ideal state bundle.
It is just used as a const reference.
5 files changed, 89 insertions, 185 deletions
diff --git a/storage/src/tests/distributor/statecheckerstest.cpp b/storage/src/tests/distributor/statecheckerstest.cpp index 16854cd63c6..cd64d81774e 100644 --- a/storage/src/tests/distributor/statecheckerstest.cpp +++ b/storage/src/tests/distributor/statecheckerstest.cpp @@ -1383,9 +1383,8 @@ std::string StateCheckersTest::testGarbageCollection( getBucketDatabase().update(e); NodeMaintenanceStatsTracker statsTracker; - StateChecker::Context c(node_context(), operation_context(), - getDistributorBucketSpace(), statsTracker, - makeDocumentBucket(e.getBucketId())); + StateChecker::Context c(node_context(), operation_context(), getDistributorBucketSpace(), + statsTracker, makeDocumentBucket(e.getBucketId())); getClock().setAbsoluteTimeInSeconds(nowTimestamp); return testStateChecker(checker, c, false, PendingMessage(), includePriority, includeSchedulingPri); } @@ -1394,38 +1393,29 @@ TEST_F(StateCheckersTest, garbage_collection) { // BucketId(17, 0) has id (and thus 'hash') 0x4400000000000000. With a // check interval modulo of 3600, this implies a start point of 848. - EXPECT_EQ("NO OPERATIONS GENERATED", - testGarbageCollection(900, 3600 + 847, 3600)); + EXPECT_EQ("NO OPERATIONS GENERATED", testGarbageCollection(900, 3600 + 847, 3600)); - EXPECT_EQ("[Needs garbage collection: Last check at 900, current time 4448, " - "configured interval 3600]", + EXPECT_EQ("[Needs garbage collection: Last check at 900, current time 4448, configured interval 3600]", testGarbageCollection(900, 3600 + 848, 3600)); - EXPECT_EQ("[Needs garbage collection: Last check at 3, current time 4000, " - "configured interval 3600]", + EXPECT_EQ("[Needs garbage collection: Last check at 3, current time 4000, configured interval 3600]", testGarbageCollection(3, 4000, 3600)); // GC start point 3648. - EXPECT_EQ("NO OPERATIONS GENERATED", - testGarbageCollection(3, 3647, 8000)); + EXPECT_EQ("NO OPERATIONS GENERATED", testGarbageCollection(3, 3647, 8000)); - EXPECT_EQ("[Needs garbage collection: Last check at 3, current time 4000, " - "configured interval 3600]", + EXPECT_EQ("[Needs garbage collection: Last check at 3, current time 4000, configured interval 3600]", testGarbageCollection(3, 4000, 3600)); // GC explicitly disabled. - EXPECT_EQ("NO OPERATIONS GENERATED", - testGarbageCollection(3, 4000, 0)); + EXPECT_EQ("NO OPERATIONS GENERATED", testGarbageCollection(3, 4000, 0)); - EXPECT_EQ("NO OPERATIONS GENERATED", - testGarbageCollection(3, 3, 1)); + EXPECT_EQ("NO OPERATIONS GENERATED", testGarbageCollection(3, 3, 1)); - EXPECT_EQ("[Needs garbage collection: Last check at 3, current time 4000, " - "configured interval 300] (pri 200)", + EXPECT_EQ("[Needs garbage collection: Last check at 3, current time 4000, configured interval 300] (pri 200)", testGarbageCollection(3, 4000, 300, 1, true)); - EXPECT_EQ("NO OPERATIONS GENERATED", - testGarbageCollection(3850, 4000, 300, 1)); + EXPECT_EQ("NO OPERATIONS GENERATED", testGarbageCollection(3850, 4000, 300, 1)); } TEST_F(StateCheckersTest, gc_ops_are_prioritized_with_low_priority_category) { @@ -1597,7 +1587,7 @@ TEST_F(StateCheckersTest, context_populates_ideal_state_containers) { StateChecker::Context c(node_context(), operation_context(), getDistributorBucketSpace(), statsTracker, makeDocumentBucket({17, 0})); - ASSERT_THAT(c.idealState, ElementsAre(1, 3)); + ASSERT_THAT(c.idealState(), ElementsAre(1, 3)); // TODO replace with UnorderedElementsAre once we can build gmock without issues std::vector<uint16_t> ideal_state(c.unorderedIdealState.begin(), c.unorderedIdealState.end()); std::sort(ideal_state.begin(), ideal_state.end()); diff --git a/storage/src/vespa/storage/distributor/ideal_service_layer_nodes_bundle.h b/storage/src/vespa/storage/distributor/ideal_service_layer_nodes_bundle.h index 8f9cb8e14ec..bb2e2c15996 100644 --- a/storage/src/vespa/storage/distributor/ideal_service_layer_nodes_bundle.h +++ b/storage/src/vespa/storage/distributor/ideal_service_layer_nodes_bundle.h @@ -27,9 +27,9 @@ public: void set_available_nonretired_or_maintenance_nodes(std::vector<uint16_t> available_nonretired_or_maintenance_nodes) { _available_nonretired_or_maintenance_nodes = std::move(available_nonretired_or_maintenance_nodes); } - const std::vector<uint16_t> & get_available_nodes() const { return _available_nodes; } - const std::vector<uint16_t> & get_available_nonretired_nodes() const { return _available_nonretired_nodes; } - const std::vector<uint16_t> & get_available_nonretired_or_maintenance_nodes() const { + const std::vector<uint16_t> & get_available_nodes() const noexcept { return _available_nodes; } + const std::vector<uint16_t> & get_available_nonretired_nodes() const noexcept { return _available_nonretired_nodes; } + const std::vector<uint16_t> & get_available_nonretired_or_maintenance_nodes() const noexcept { return _available_nonretired_or_maintenance_nodes; } }; diff --git a/storage/src/vespa/storage/distributor/statechecker.cpp b/storage/src/vespa/storage/distributor/statechecker.cpp index 27a60b73716..96ad3b46e5d 100644 --- a/storage/src/vespa/storage/distributor/statechecker.cpp +++ b/storage/src/vespa/storage/distributor/statechecker.cpp @@ -51,13 +51,11 @@ public: StateChecker::Result StateChecker::Result::noMaintenanceNeeded() { - return Result(std::unique_ptr<ResultImpl>()); + return Result({}); } StateChecker::Result -StateChecker::Result::createStoredResult( - IdealStateOperation::UP operation, - MaintenancePriority::Priority priority) +StateChecker::Result::createStoredResult(IdealStateOperation::UP operation, MaintenancePriority::Priority priority) { return Result(std::make_unique<StoredResultImpl>(std::move(operation), MaintenancePriority(priority))); } @@ -74,14 +72,14 @@ StateChecker::Context::Context(const DistributorNodeContext& node_ctx_in, distributorConfig(op_ctx_in.distributor_config()), distribution(distributorBucketSpace.getDistribution()), gcTimeCalculator(op_ctx_in.bucket_id_hasher(), distributorConfig.getGarbageCollectionInterval()), + idealStateBundle(distributorBucketSpace.get_ideal_service_layer_nodes_bundle(bucket.getBucketId())), node_ctx(node_ctx_in), op_ctx(op_ctx_in), db(distributorBucketSpace.getBucketDatabase()), stats(statsTracker), merges_inhibited_in_bucket_space(distributorBucketSpace.merges_inhibited()) { - idealState = distributorBucketSpace.get_ideal_service_layer_nodes_bundle(bucket.getBucketId()).get_available_nonretired_or_maintenance_nodes(); - unorderedIdealState.insert(idealState.begin(), idealState.end()); + unorderedIdealState.insert(idealState().begin(), idealState().end()); } StateChecker::Context::~Context() = default; diff --git a/storage/src/vespa/storage/distributor/statechecker.h b/storage/src/vespa/storage/distributor/statechecker.h index 830e05676be..ef50c78f068 100644 --- a/storage/src/vespa/storage/distributor/statechecker.h +++ b/storage/src/vespa/storage/distributor/statechecker.h @@ -2,6 +2,7 @@ #pragma once #include "bucketgctimecalculator.h" +#include "ideal_service_layer_nodes_bundle.h" #include <vespa/storage/distributor/maintenance/maintenancepriority.h> #include <vespa/storage/distributor/operations/idealstate/idealstateoperation.h> #include <vespa/storage/common/storagecomponent.h> @@ -73,7 +74,7 @@ public: // need to both know the actual order (activation prioritization etc) as // well as have the ability to quickly check if a node is in an ideal // location. - std::vector<uint16_t> idealState; + const IdealServiceLayerNodesBundle & idealStateBundle; vespalib::hash_set<uint16_t> unorderedIdealState; const DistributorNodeContext& node_ctx; @@ -82,9 +83,8 @@ public: NodeMaintenanceStatsTracker& stats; const bool merges_inhibited_in_bucket_space; - const BucketDatabase::Entry& getSiblingEntry() const noexcept { - return siblingEntry; - } + const BucketDatabase::Entry& getSiblingEntry() const noexcept { return siblingEntry; } + const std::vector<uint16_t> & idealState() const noexcept { return idealStateBundle.get_available_nonretired_or_maintenance_nodes(); } document::Bucket getBucket() const noexcept { return bucket; } document::BucketId getBucketId() const noexcept { return bucket.getBucketId(); } diff --git a/storage/src/vespa/storage/distributor/statecheckers.cpp b/storage/src/vespa/storage/distributor/statecheckers.cpp index fe1f4422c45..56247d744bf 100644 --- a/storage/src/vespa/storage/distributor/statecheckers.cpp +++ b/storage/src/vespa/storage/distributor/statecheckers.cpp @@ -27,9 +27,7 @@ SplitBucketStateChecker::validForSplit(Context& c) { // Can't split if we have no nodes. if (c.entry->getNodeCount() == 0) { - LOG(spam, - "Can't split bucket %s, since it has no copies", - c.bucket.toString().c_str()); + LOG(spam, "Can't split bucket %s, since it has no copies", c.bucket.toString().c_str()); return false; } @@ -83,33 +81,21 @@ SplitBucketStateChecker::getBucketSizeRelativeToMax(Context& c) } StateChecker::Result -SplitBucketStateChecker::generateMinimumBucketSplitOperation( - Context& c) +SplitBucketStateChecker::generateMinimumBucketSplitOperation(Context& c) { - auto so = std::make_unique<SplitOperation>( - c.node_ctx, - BucketAndNodes(c.getBucket(), c.entry->getNodes()), - c.distributorConfig.getMinimalBucketSplit(), - 0, - 0); + auto so = std::make_unique<SplitOperation>(c.node_ctx, BucketAndNodes(c.getBucket(), c.entry->getNodes()), + c.distributorConfig.getMinimalBucketSplit(), 0, 0); so->setPriority(c.distributorConfig.getMaintenancePriorities().splitDistributionBits); - so->setDetailedReason( - "[Splitting bucket because the current system size requires " - "a higher minimum split bit]"); + so->setDetailedReason("[Splitting bucket because the current system size requires a higher minimum split bit]"); return Result::createStoredResult(std::move(so), MaintenancePriority::MEDIUM); } StateChecker::Result -SplitBucketStateChecker::generateMaxSizeExceededSplitOperation( - Context& c) +SplitBucketStateChecker::generateMaxSizeExceededSplitOperation(Context& c) { - auto so = std::make_unique<SplitOperation>( - c.node_ctx, - BucketAndNodes(c.getBucket(), c.entry->getNodes()), - 58, - c.distributorConfig.getSplitCount(), - c.distributorConfig.getSplitSize()); + auto so = std::make_unique<SplitOperation>(c.node_ctx, BucketAndNodes(c.getBucket(), c.entry->getNodes()), 58, + c.distributorConfig.getSplitCount(), c.distributorConfig.getSplitSize()); so->setPriority(c.distributorConfig.getMaintenancePriorities().splitLargeBucket); @@ -160,8 +146,7 @@ JoinBucketsStateChecker::isFirstSibling(const document::BucketId& bucketId) namespace { bool -equalNodeSet(const std::vector<uint16_t>& idealState, - const BucketDatabase::Entry& dbEntry) +equalNodeSet(const std::vector<uint16_t>& idealState, const BucketDatabase::Entry& dbEntry) { if (idealState.size() != dbEntry->getNodeCount()) { return false; @@ -179,12 +164,10 @@ equalNodeSet(const std::vector<uint16_t>& idealState, bool bucketAndSiblingReplicaLocationsEqualIdealState(const StateChecker::Context& context) { - if (!equalNodeSet(context.idealState, context.entry)) { + if (!equalNodeSet(context.idealState(), context.entry)) { return false; } - std::vector<uint16_t> siblingIdealState( - context.distribution.getIdealStorageNodes( - context.systemState, context.siblingBucket)); + std::vector<uint16_t> siblingIdealState = context.distribution.getIdealStorageNodes(context.systemState, context.siblingBucket); if (!equalNodeSet(siblingIdealState, context.siblingEntry)) { return false; } @@ -213,41 +196,29 @@ JoinBucketsStateChecker::siblingsAreInSync(const Context& context) const auto& siblingEntry(context.siblingEntry); if (entry->getNodeCount() != siblingEntry->getNodeCount()) { - LOG(spam, - "Not joining bucket %s because sibling bucket %s had different " - "node count", - context.bucket.toString().c_str(), - context.siblingBucket.toString().c_str()); + LOG(spam, "Not joining bucket %s because sibling bucket %s had different node count", + context.bucket.toString().c_str(), context.siblingBucket.toString().c_str()); return false; } bool siblingsCoLocated = true; for (uint32_t i = 0; i < entry->getNodeCount(); ++i) { - if (entry->getNodeRef(i).getNode() - != siblingEntry->getNodeRef(i).getNode()) - { + if (entry->getNodeRef(i).getNode() != siblingEntry->getNodeRef(i).getNode()) { siblingsCoLocated = false; break; } } if (!siblingsCoLocated && !inconsistentJoinIsAllowed(context)) { - LOG(spam, - "Not joining bucket %s because sibling bucket %s " - "does not have the same node set, or inconsistent joins cannot be " - "performed either due to config or because replicas were not in " - "their ideal location", - context.bucket.toString().c_str(), - context.siblingBucket.toString().c_str()); + LOG(spam, "Not joining bucket %s because sibling bucket %s does not have the same node set, or inconsistent " + "joins cannot be performed either due to config or because replicas were not in their ideal location", + context.bucket.toString().c_str(), context.siblingBucket.toString().c_str()); return false; } if (!entry->validAndConsistent() || !siblingEntry->validAndConsistent()) { - LOG(spam, - "Not joining bucket %s because it or %s is out of sync " - "and syncing it may cause it to become too large", - context.bucket.toString().c_str(), - context.siblingBucket.toString().c_str()); + LOG(spam, "Not joining bucket %s because it or %s is out of sync and syncing it may cause it to become too large", + context.bucket.toString().c_str(), context.siblingBucket.toString().c_str()); return false; } @@ -291,9 +262,8 @@ contextBucketHasTooManyReplicas(const StateChecker::Context& c) bool bucketAtDistributionBitLimit(const document::BucketId& bucket, const StateChecker::Context& c) { - return (bucket.getUsedBits() <= std::max( - uint32_t(c.systemState.getDistributionBitCount()), - c.distributorConfig.getMinimalBucketSplit())); + return (bucket.getUsedBits() <= std::max(uint32_t(c.systemState.getDistributionBitCount()), + c.distributorConfig.getMinimalBucketSplit())); } } @@ -302,31 +272,23 @@ bool JoinBucketsStateChecker::shouldJoin(const Context& c) { if (c.entry->getNodeCount() == 0) { - LOG(spam, "Not joining bucket %s because it has no nodes", - c.bucket.toString().c_str()); + LOG(spam, "Not joining bucket %s because it has no nodes", c.bucket.toString().c_str()); return false; } if (contextBucketHasTooManyReplicas(c)) { - LOG(spam, "Not joining %s because it has too high replication level", - c.bucket.toString().c_str()); + LOG(spam, "Not joining %s because it has too high replication level", c.bucket.toString().c_str()); return false; } if (c.distributorConfig.getJoinSize() == 0 && c.distributorConfig.getJoinCount() == 0) { - LOG(spam, "Not joining bucket %s because join is disabled", - c.bucket.toString().c_str()); + LOG(spam, "Not joining bucket %s because join is disabled", c.bucket.toString().c_str()); return false; } if (bucketAtDistributionBitLimit(c.getBucketId(), c)) { - LOG(spam, - "Not joining bucket %s because it is below the min split " - "count (config: %u, cluster state: %u, bucket has: %u)", - c.bucket.toString().c_str(), - c.distributorConfig.getMinimalBucketSplit(), - c.systemState.getDistributionBitCount(), - c.getBucketId().getUsedBits()); + LOG(spam, "Not joining bucket %s because it is below the min split count (config: %u, cluster state: %u, bucket has: %u)", + c.bucket.toString().c_str(), c.distributorConfig.getMinimalBucketSplit(), c.systemState.getDistributionBitCount(), c.getBucketId().getUsedBits()); return false; } @@ -336,11 +298,8 @@ JoinBucketsStateChecker::shouldJoin(const Context& c) if (c.getSiblingEntry().valid()) { if (!isFirstSibling(c.getBucketId())) { - LOG(spam, - "Not joining bucket %s because it is the second sibling of " - "%s and not the first", - c.bucket.toString().c_str(), - c.siblingBucket.toString().c_str()); + LOG(spam, "Not joining bucket %s because it is the second sibling of %s and not the first", + c.bucket.toString().c_str(), c.siblingBucket.toString().c_str()); return false; } if (!siblingsAreInSync(c)) { @@ -463,24 +422,13 @@ JoinBucketsStateChecker::check(Context& c) const sourceBuckets.push_back(c.getBucketId()); } sourceBuckets.push_back(c.getBucketId()); - auto op = std::make_unique<JoinOperation>( - c.node_ctx, - BucketAndNodes(joinedBucket, c.entry->getNodes()), - sourceBuckets); + auto op = std::make_unique<JoinOperation>(c.node_ctx, BucketAndNodes(joinedBucket, c.entry->getNodes()), sourceBuckets); op->setPriority(c.distributorConfig.getMaintenancePriorities().joinBuckets); vespalib::asciistream ost; - ost << "[Joining buckets " - << sourceBuckets[1].toString() - << " and " << sourceBuckets[0].toString() - << " because their size (" - << getTotalUsedFileSize(c) - << " bytes, " - << getTotalMetaCount(c) - << " docs) is less than the configured limit of (" - << c.distributorConfig.getJoinSize() - << ", " - << c.distributorConfig.getJoinCount() - << ")"; + ost << "[Joining buckets " << sourceBuckets[1].toString() << " and " << sourceBuckets[0].toString() + << " because their size (" << getTotalUsedFileSize(c) << " bytes, " + << getTotalMetaCount(c) << " docs) is less than the configured limit of (" + << c.distributorConfig.getJoinSize() << ", " << c.distributorConfig.getJoinCount() << ")"; op->setDetailedReason(ost.str()); @@ -516,8 +464,7 @@ vespalib::string SplitInconsistentStateChecker::getReason(const document::BucketId& bucketId, const std::vector<BucketDatabase::Entry>& entries) { vespalib::asciistream reason; - reason << "[Bucket is inconsistently split (list includes " - << vespalib::hex << "0x" << bucketId.getId(); + reason << "[Bucket is inconsistently split (list includes " << vespalib::hex << "0x" << bucketId.getId(); for (uint32_t i = 0, found = 0; i < entries.size() && found < 3; i++) { if (!(entries[i].getBucketId() == bucketId)) { @@ -530,10 +477,7 @@ SplitInconsistentStateChecker::getReason(const document::BucketId& bucketId, con reason << " and " << vespalib::dec << entries.size() - 4 << " others"; } - reason << ") Splitting it to improve the problem (max used bits " - << vespalib::dec - << getHighestUsedBits(entries) - << ")]"; + reason << ") Splitting it to improve the problem (max used bits " << vespalib::dec << getHighestUsedBits(entries) << ")]"; return reason.str(); } @@ -559,12 +503,8 @@ SplitInconsistentStateChecker::check(Context& c) const return Result::noMaintenanceNeeded(); } - auto op = std::make_unique<SplitOperation>( - c.node_ctx, - BucketAndNodes(c.getBucket(), c.entry->getNodes()), - getHighestUsedBits(c.entries), - 0, - 0); + auto op = std::make_unique<SplitOperation>(c.node_ctx, BucketAndNodes(c.getBucket(), c.entry->getNodes()), + getHighestUsedBits(c.entries), 0, 0); op->setPriority(c.distributorConfig.getMaintenancePriorities().splitInconsistentBucket); op->setDetailedReason(getReason(c.getBucketId(), c.entries)); @@ -576,8 +516,7 @@ namespace { bool containsMaintenanceNode(const std::vector<uint16_t>& ideal, const StateChecker::Context& c) { for (uint16_t n : ideal) { - lib::Node node(lib::NodeType::STORAGE, n); - if (c.systemState.getNodeState(node).getState() == lib::State::MAINTENANCE) { + if (c.systemState.getNodeState(lib::Node(lib::NodeType::STORAGE, n)).getState() == lib::State::MAINTENANCE) { return true; } } @@ -588,9 +527,8 @@ bool ideal_node_is_unavailable_in_pending_state(const StateChecker::Context& c) if (!c.pending_cluster_state) { return false; } - for (uint16_t n : c.idealState) { - lib::Node node(lib::NodeType::STORAGE, n); - if (!c.pending_cluster_state->getNodeState(node).getState().oneOf("uir")){ + for (uint16_t n : c.idealState()) { + if (!c.pending_cluster_state->getNodeState(lib::Node(lib::NodeType::STORAGE, n)).getState().oneOf("uir")){ return true; } } @@ -598,9 +536,7 @@ bool ideal_node_is_unavailable_in_pending_state(const StateChecker::Context& c) } bool -consistentApartFromEmptyBucketsInNonIdealLocationAndInvalidEntries( - const std::vector<uint16_t>& idealNodes, - const BucketInfo& entry) +consistentApartFromEmptyBucketsInNonIdealLocationAndInvalidEntries(const std::vector<uint16_t>& idealNodes, const BucketInfo& entry) { api::BucketInfo info; for (uint32_t i=0, n=entry.getNodeCount(); i<n; ++i) { @@ -730,7 +666,7 @@ addStatisticsForNonIdealNodes(const StateChecker::Context& c, bool missingReplic { // Common case is that ideal state == actual state with no missing replicas. // If so, do nothing. - if (!missingReplica && (c.idealState.size() == c.entry->getNodeCount())) { + if (!missingReplica && (c.idealState().size() == c.entry->getNodeCount())) { return; } for (uint32_t j = 0; j < c.entry->getNodeCount(); ++j) { @@ -753,26 +689,23 @@ checkForNodesMissingFromIdealState(StateChecker::Context& c) // Check if we need to add copies to get to ideal state. if (!c.entry->emptyAndConsistent()) { bool hasMissingReplica = false; - for (uint32_t i = 0; i < c.idealState.size(); i++) { + for (uint16_t node : c.idealState()) { bool found = false; for (uint32_t j = 0; j < c.entry->getNodeCount(); j++) { - if (c.entry->getNodeRef(j).getNode() == c.idealState[i]) { + if (c.entry->getNodeRef(j).getNode() == node) { found = true; break; } } if (!found) { - const DistributorConfiguration::MaintenancePriorities& mp( - c.distributorConfig.getMaintenancePriorities()); - if (c.idealState.size() > c.entry->getNodeCount()) { - ret.markMissingReplica(c.idealState[i], - mp.mergeTooFewCopies); + const auto & mp = c.distributorConfig.getMaintenancePriorities(); + if (c.idealState().size() > c.entry->getNodeCount()) { + ret.markMissingReplica(node, mp.mergeTooFewCopies); } else { - ret.markMoveToIdealLocation(c.idealState[i], - mp.mergeMoveToIdealNode); + ret.markMoveToIdealLocation(node,mp.mergeMoveToIdealNode); } - c.stats.incCopyingIn(c.idealState[i], c.getBucketSpace()); + c.stats.incCopyingIn(node, c.getBucketSpace()); hasMissingReplica = true; } } @@ -795,12 +728,8 @@ MergeNodes checkIfBucketsAreOutOfSyncAndNeedMerging(StateChecker::Context& c) { MergeNodes ret; - if (!consistentApartFromEmptyBucketsInNonIdealLocationAndInvalidEntries( - c.idealState, - c.entry.getBucketInfo())) - { - auto pri(c.distributorConfig.getMaintenancePriorities() - .mergeOutOfSyncCopies); + if (!consistentApartFromEmptyBucketsInNonIdealLocationAndInvalidEntries(c.idealState(),c.entry.getBucketInfo())) { + auto pri(c.distributorConfig.getMaintenancePriorities().mergeOutOfSyncCopies); ret.markOutOfSync(c, pri); addStatisticsForOutOfSyncCopies(c); } @@ -839,7 +768,7 @@ SynchronizeAndMoveStateChecker::check(Context& c) const if (isInconsistentlySplit(c)) { return Result::noMaintenanceNeeded(); } - if (containsMaintenanceNode(c.idealState, c)) { + if (containsMaintenanceNode(c.idealState(), c)) { return Result::noMaintenanceNeeded(); } if (ideal_node_is_unavailable_in_pending_state(c)) { @@ -863,8 +792,7 @@ SynchronizeAndMoveStateChecker::check(Context& c) const if ((c.getBucketSpace() == document::FixedBucketSpaces::default_space()) || !c.distributorConfig.prioritize_global_bucket_merges()) { - schedPri = (result.needsMoveOnly() ? MaintenancePriority::LOW - : MaintenancePriority::MEDIUM); + schedPri = (result.needsMoveOnly() ? MaintenancePriority::LOW : MaintenancePriority::MEDIUM); op->setPriority(result.priority()); } else { // Since the default bucket space has a dependency on the global bucket space, @@ -876,10 +804,8 @@ SynchronizeAndMoveStateChecker::check(Context& c) const return Result::createStoredResult(std::move(op), schedPri); } else { - LOG(spam, "Bucket %s: No need for merge, as bucket is in consistent state " - "(or inconsistent buckets are empty) %s", - c.bucket.toString().c_str(), - c.entry->toString().c_str()); + LOG(spam, "Bucket %s: No need for merge, as bucket is in consistent state (or inconsistent buckets are empty) %s", + c.bucket.toString().c_str(), c.entry->toString().c_str()); return Result::noMaintenanceNeeded(); } } @@ -894,7 +820,7 @@ DeleteExtraCopiesStateChecker::bucketHasNoData(const Context& c) bool DeleteExtraCopiesStateChecker::copyIsInIdealState(const BucketCopy& cp, const Context& c) { - return hasItem(c.idealState, cp.getNode()); + return hasItem(c.idealState(), cp.getNode()); } bool @@ -910,9 +836,7 @@ DeleteExtraCopiesStateChecker::addToRemoveSet( std::vector<uint16_t>& removedCopies, vespalib::asciistream& reasons) { - reasons << "[Removing " << reasonForRemoval - << " from node " << copyToRemove.getNode() - << ']'; + reasons << "[Removing " << reasonForRemoval << " from node " << copyToRemove.getNode() << ']'; removedCopies.push_back(copyToRemove.getNode()); } @@ -980,7 +904,7 @@ DeleteExtraCopiesStateChecker::check(Context& c) const } // Maintain symmetry with merge; don't try to mess with nodes that have an // ideal copy on a node set in maintenance mode. - if (containsMaintenanceNode(c.idealState, c)) { + if (containsMaintenanceNode(c.idealState(), c)) { return Result::noMaintenanceNeeded(); } @@ -988,8 +912,7 @@ DeleteExtraCopiesStateChecker::check(Context& c) const std::vector<uint16_t> removedCopies; if (bucketHasNoData(c)) { - reasons << "[Removing all copies since bucket is empty:" - << c.entry->toString() << "]"; + reasons << "[Removing all copies since bucket is empty:" << c.entry->toString() << "]"; for (uint32_t j = 0, cnt = c.entry->getNodeCount(); j < cnt; ++j) { removedCopies.push_back(c.entry->getNodeRef(j).getNode()); @@ -1003,9 +926,7 @@ DeleteExtraCopiesStateChecker::check(Context& c) const } if (!removedCopies.empty()) { - auto ro = std::make_unique<RemoveBucketOperation>( - c.node_ctx, - BucketAndNodes(c.getBucket(), removedCopies)); + auto ro = std::make_unique<RemoveBucketOperation>(c.node_ctx, BucketAndNodes(c.getBucket(), removedCopies)); ro->setPriority(c.distributorConfig.getMaintenancePriorities().deleteBucketCopy); ro->setDetailedReason(reasons.str()); @@ -1029,7 +950,7 @@ BucketStateStateChecker::shouldSkipActivationDueToMaintenance(const ActiveList& // If copy is not ready, we don't want to activate it if a node // is set in maintenance. Doing so would imply that we want proton // to start background indexing. - return containsMaintenanceNode(c.idealState, c); + return containsMaintenanceNode(c.idealState(), c); } // else: activation does not imply indexing, so we can safely do it at any time. } } @@ -1057,9 +978,8 @@ BucketStateStateChecker::check(Context& c) const return Result::noMaintenanceNeeded(); } - ActiveList activeNodes( - ActiveCopy::calculate(c.idealState, c.distribution, c.entry, - c.distributorConfig.max_activation_inhibited_out_of_sync_groups())); + ActiveList activeNodes = ActiveCopy::calculate(c.idealState(), c.distribution, c.entry, + c.distributorConfig.max_activation_inhibited_out_of_sync_groups()); if (activeNodes.empty()) { return Result::noMaintenanceNeeded(); } @@ -1075,8 +995,7 @@ BucketStateStateChecker::check(Context& c) const continue; } operationNodes.push_back(activeNodes[i]._nodeIndex); - reason << "[Setting node " << activeNodes[i]._nodeIndex << " as active: " - << activeNodes[i].getReason() << "]"; + reason << "[Setting node " << activeNodes[i]._nodeIndex << " as active: " << activeNodes[i].getReason() << "]"; } // Deactivate all copies that are currently marked as active. @@ -1105,10 +1024,7 @@ BucketStateStateChecker::check(Context& c) const for (uint32_t i=0; i<activeNodes.size(); ++i) { activeNodeIndexes.push_back(activeNodes[i]._nodeIndex); } - auto op = std::make_unique<SetBucketStateOperation>( - c.node_ctx, - BucketAndNodes(c.getBucket(), operationNodes), - activeNodeIndexes); + auto op = std::make_unique<SetBucketStateOperation>(c.node_ctx, BucketAndNodes(c.getBucket(), operationNodes), activeNodeIndexes); // If activeNodes > 1, we're dealing with a active-per-leaf group case and // we currently always send high pri activations. @@ -1134,7 +1050,7 @@ GarbageCollectionStateChecker::needs_garbage_collection(const Context& c, vespal if (c.entry->getNodeCount() == 0) { return false; } - if (containsMaintenanceNode(c.idealState, c)) { + if (containsMaintenanceNode(c.idealState(), c)) { return false; } std::chrono::seconds lastRunAt(c.entry->getLastGarbageCollectionTime()); |