aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Brede Vekterli <vekterli@vespa.ai>2023-10-19 09:56:40 +0000
committerTor Brede Vekterli <vekterli@vespa.ai>2023-10-19 09:56:40 +0000
commit0c5f0c977e636e3aea62cac1c7808ecec6cbe08e (patch)
treec4d66c32965170d97e6127890c9fab4c3830a8ad
parent6bce6e100606a9d2bfa14df6ba86bd09700c2545 (diff)
Rewire Bouncer configuration flow
Removes own `ConfigFetcher` in favor of pushing reconfiguration responsibilities onto the components owning the Bouncer instance. The current "superclass calls into subclass" approach isn't ideal, but the longer term plan is to hoist all config subscriptions out of `StorageNode` and into the higher-level `Process` structure.
-rw-r--r--storage/src/tests/storageserver/bouncertest.cpp33
-rw-r--r--storage/src/vespa/storage/storageserver/bouncer.cpp28
-rw-r--r--storage/src/vespa/storage/storageserver/bouncer.h21
-rw-r--r--storage/src/vespa/storage/storageserver/distributornode.cpp12
-rw-r--r--storage/src/vespa/storage/storageserver/distributornode.h3
-rw-r--r--storage/src/vespa/storage/storageserver/servicelayernode.cpp10
-rw-r--r--storage/src/vespa/storage/storageserver/servicelayernode.h7
-rw-r--r--storage/src/vespa/storage/storageserver/storagenode.cpp13
-rw-r--r--storage/src/vespa/storage/storageserver/storagenode.h10
9 files changed, 82 insertions, 55 deletions
diff --git a/storage/src/tests/storageserver/bouncertest.cpp b/storage/src/tests/storageserver/bouncertest.cpp
index 5b7d279537e..225b3c94120 100644
--- a/storage/src/tests/storageserver/bouncertest.cpp
+++ b/storage/src/tests/storageserver/bouncertest.cpp
@@ -1,20 +1,22 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-#include <vespa/storageapi/message/bucket.h>
-#include <vespa/storageapi/message/state.h>
-#include <vespa/storageapi/message/stat.h>
-#include <vespa/storage/storageserver/bouncer.h>
-#include <vespa/storage/storageserver/bouncer_metrics.h>
-#include <tests/common/teststorageapp.h>
-#include <tests/common/testhelper.h>
#include <tests/common/dummystoragelink.h>
+#include <tests/common/testhelper.h>
+#include <tests/common/teststorageapp.h>
+#include <vespa/config/common/exceptions.h>
+#include <vespa/config/helper/configgetter.hpp>
#include <vespa/document/bucket/fixed_bucket_spaces.h>
-#include <vespa/document/test/make_document_bucket.h>
#include <vespa/document/fieldset/fieldsets.h>
-#include <vespa/storageapi/message/persistence.h>
+#include <vespa/document/test/make_document_bucket.h>
#include <vespa/persistence/spi/bucket_limits.h>
+#include <vespa/storage/config/config-stor-bouncer.h>
+#include <vespa/storage/storageserver/bouncer.h>
+#include <vespa/storage/storageserver/bouncer_metrics.h>
+#include <vespa/storageapi/message/bucket.h>
+#include <vespa/storageapi/message/persistence.h>
+#include <vespa/storageapi/message/stat.h>
+#include <vespa/storageapi/message/state.h>
#include <vespa/vdslib/state/clusterstate.h>
-#include <vespa/config/common/exceptions.h>
#include <vespa/vespalib/gtest/gtest.h>
using document::test::makeDocumentBucket;
@@ -73,7 +75,10 @@ void BouncerTest::setUpAsNode(const lib::NodeType& type) {
_node.reset(new TestDistributorApp(NodeIndex(2), config.getConfigId()));
}
_upper.reset(new DummyStorageLink());
- _manager = new Bouncer(_node->getComponentRegister(), config::ConfigUri(config.getConfigId()));
+ using StorBouncerConfig = vespa::config::content::core::StorBouncerConfig;
+ auto cfg_uri = config::ConfigUri(config.getConfigId());
+ auto cfg = config::ConfigGetter<StorBouncerConfig>::getConfig(cfg_uri.getConfigId(), cfg_uri.getContext());
+ _manager = new Bouncer(_node->getComponentRegister(), *cfg);
_lower = new DummyStorageLink();
_upper->push_back(std::unique_ptr<StorageLink>(_manager));
_upper->push_back(std::unique_ptr<StorageLink>(_lower));
@@ -225,9 +230,9 @@ void
BouncerTest::configureRejectionThreshold(int newThreshold)
{
using Builder = vespa::config::content::core::StorBouncerConfigBuilder;
- auto config = std::make_unique<Builder>();
- config->feedRejectionPriorityThreshold = newThreshold;
- _manager->configure(std::move(config));
+ Builder config;
+ config.feedRejectionPriorityThreshold = newThreshold;
+ _manager->on_configure(config);
}
TEST_F(BouncerTest, reject_lower_prioritized_feed_messages_when_configured) {
diff --git a/storage/src/vespa/storage/storageserver/bouncer.cpp b/storage/src/vespa/storage/storageserver/bouncer.cpp
index 78f248e2b90..7e3b21ef33a 100644
--- a/storage/src/vespa/storage/storageserver/bouncer.cpp
+++ b/storage/src/vespa/storage/storageserver/bouncer.cpp
@@ -21,34 +21,19 @@ LOG_SETUP(".bouncer");
namespace storage {
-Bouncer::Bouncer(StorageComponentRegister& compReg, const config::ConfigUri & configUri)
+Bouncer::Bouncer(StorageComponentRegister& compReg, const StorBouncerConfig& bootstrap_config)
: StorageLink("Bouncer", MsgDownOnFlush::Disallowed, MsgUpOnClosed::Allowed),
- _config(new vespa::config::content::core::StorBouncerConfig()),
+ _config(std::make_unique<vespa::config::content::core::StorBouncerConfig>(bootstrap_config)),
_component(compReg, "bouncer"),
_lock(),
_baselineNodeState("s:i"),
_derivedNodeStates(),
_clusterState(&lib::State::UP),
- _configFetcher(std::make_unique<config::ConfigFetcher>(configUri.getContext())),
_metrics(std::make_unique<BouncerMetrics>()),
_closed(false)
{
_component.getStateUpdater().addStateListener(*this);
_component.registerMetric(*_metrics);
- // Register for config. Normally not critical, so catching config
- // exception allowing program to continue if missing/faulty config.
- try {
- if (!configUri.empty()) {
- _configFetcher->subscribe<vespa::config::content::core::StorBouncerConfig>(configUri.getConfigId(), this);
- _configFetcher->start();
- } else {
- LOG(info, "No config id specified. Using defaults rather than config");
- }
- } catch (config::InvalidConfigException& e) {
- LOG(info, "Bouncer failed to load config '%s'. This "
- "is not critical since it has sensible defaults: %s",
- configUri.getConfigId().c_str(), e.what());
- }
}
Bouncer::~Bouncer()
@@ -68,19 +53,18 @@ Bouncer::print(std::ostream& out, bool verbose,
void
Bouncer::onClose()
{
- _configFetcher->close();
_component.getStateUpdater().removeStateListener(*this);
std::lock_guard guard(_lock);
_closed = true;
}
void
-Bouncer::configure(std::unique_ptr<vespa::config::content::core::StorBouncerConfig> config)
+Bouncer::on_configure(const vespa::config::content::core::StorBouncerConfig& config)
{
- log_config_received(*config);
- validateConfig(*config);
+ validateConfig(config);
+ auto new_config = std::make_unique<StorBouncerConfig>(config);
std::lock_guard lock(_lock);
- _config = std::move(config);
+ _config = std::move(new_config);
}
const BouncerMetrics& Bouncer::metrics() const noexcept {
diff --git a/storage/src/vespa/storage/storageserver/bouncer.h b/storage/src/vespa/storage/storageserver/bouncer.h
index 1038e94ee94..44c7a16f3dc 100644
--- a/storage/src/vespa/storage/storageserver/bouncer.h
+++ b/storage/src/vespa/storage/storageserver/bouncer.h
@@ -1,12 +1,7 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
/**
- * @class storage::Bouncer
- * @ingroup storageserver
- *
- * @brief Denies messages from entering if state is not good.
- *
- * If we are not in up state, but process is still running, only a few
- * messages should be allowed through. This link stops all messages not allowed.
+ * Component which rejects messages that can not be accepted by the node in
+ * its current state.
*/
#pragma once
@@ -29,28 +24,28 @@ namespace storage {
struct BouncerMetrics;
class Bouncer : public StorageLink,
- private StateListener,
- private config::IFetcherCallback<vespa::config::content::core::StorBouncerConfig>
+ private StateListener
{
- std::unique_ptr<vespa::config::content::core::StorBouncerConfig> _config;
+ using StorBouncerConfig = vespa::config::content::core::StorBouncerConfig;
+
+ std::unique_ptr<StorBouncerConfig> _config;
StorageComponent _component;
std::mutex _lock;
lib::NodeState _baselineNodeState;
using BucketSpaceNodeStateMapping = std::unordered_map<document::BucketSpace, lib::NodeState, document::BucketSpace::hash>;
BucketSpaceNodeStateMapping _derivedNodeStates;
const lib::State* _clusterState;
- std::unique_ptr<config::ConfigFetcher> _configFetcher;
std::unique_ptr<BouncerMetrics> _metrics;
bool _closed;
public:
- Bouncer(StorageComponentRegister& compReg, const config::ConfigUri & configUri);
+ Bouncer(StorageComponentRegister& compReg, const StorBouncerConfig& bootstrap_config);
~Bouncer() override;
void print(std::ostream& out, bool verbose,
const std::string& indent) const override;
- void configure(std::unique_ptr<vespa::config::content::core::StorBouncerConfig> config) override;
+ void on_configure(const StorBouncerConfig& config);
const BouncerMetrics& metrics() const noexcept;
private:
diff --git a/storage/src/vespa/storage/storageserver/distributornode.cpp b/storage/src/vespa/storage/storageserver/distributornode.cpp
index 31785e19681..0c7bee01715 100644
--- a/storage/src/vespa/storage/storageserver/distributornode.cpp
+++ b/storage/src/vespa/storage/storageserver/distributornode.cpp
@@ -32,7 +32,8 @@ DistributorNode::DistributorNode(
_timestamp_second_counter(0),
_intra_second_pseudo_usec_counter(0),
_num_distributor_stripes(num_distributor_stripes),
- _retrievedCommunicationManager(std::move(communicationManager)) // may be nullptr
+ _retrievedCommunicationManager(std::move(communicationManager)), // may be nullptr
+ _bouncer(nullptr)
{
if (storage_chain_builder) {
set_storage_chain_builder(std::move(storage_chain_builder));
@@ -94,7 +95,9 @@ DistributorNode::createChain(IStorageChainBuilder &builder)
}
std::unique_ptr<StateManager> stateManager(releaseStateManager());
- builder.add(std::make_unique<Bouncer>(dcr, _configUri));
+ auto bouncer = std::make_unique<Bouncer>(dcr, bouncer_config());
+ _bouncer = bouncer.get();
+ builder.add(std::move(bouncer));
// Distributor instance registers a host info reporter with the state
// manager, which is safe since the lifetime of said state manager
// extends to the end of the process.
@@ -140,4 +143,9 @@ DistributorNode::pause()
return {};
}
+void DistributorNode::on_bouncer_config_changed() {
+ assert(_bouncer);
+ _bouncer->on_configure(bouncer_config());
+}
+
} // storage
diff --git a/storage/src/vespa/storage/storageserver/distributornode.h b/storage/src/vespa/storage/storageserver/distributornode.h
index ac3cad30036..b725f320851 100644
--- a/storage/src/vespa/storage/storageserver/distributornode.h
+++ b/storage/src/vespa/storage/storageserver/distributornode.h
@@ -19,6 +19,7 @@ namespace storage {
namespace distributor { class DistributorStripePool; }
+class Bouncer;
class IStorageChainBuilder;
class DistributorNode
@@ -34,6 +35,7 @@ class DistributorNode
uint32_t _intra_second_pseudo_usec_counter;
uint32_t _num_distributor_stripes;
std::unique_ptr<StorageLink> _retrievedCommunicationManager;
+ Bouncer* _bouncer;
// If the current wall clock is more than the below number of seconds into the
// past when compared to the highest recorded wall clock second time stamp, abort
@@ -65,6 +67,7 @@ private:
void initializeNodeSpecific() override;
void createChain(IStorageChainBuilder &builder) override;
api::Timestamp generate_unique_timestamp() override;
+ void on_bouncer_config_changed() override;
/**
* Shut down necessary distributor-specific components before shutting
diff --git a/storage/src/vespa/storage/storageserver/servicelayernode.cpp b/storage/src/vespa/storage/storageserver/servicelayernode.cpp
index 0cd5ffeba68..e76625ccca7 100644
--- a/storage/src/vespa/storage/storageserver/servicelayernode.cpp
+++ b/storage/src/vespa/storage/storageserver/servicelayernode.cpp
@@ -32,6 +32,7 @@ ServiceLayerNode::ServiceLayerNode(const config::ConfigUri & configUri, ServiceL
_context(context),
_persistenceProvider(persistenceProvider),
_externalVisitors(externalVisitors),
+ _bouncer(nullptr),
_bucket_manager(nullptr),
_fileStorManager(nullptr),
_init_has_been_called(false)
@@ -166,7 +167,9 @@ ServiceLayerNode::createChain(IStorageChainBuilder &builder)
auto communication_manager = std::make_unique<CommunicationManager>(compReg, _configUri, communication_manager_config());
_communicationManager = communication_manager.get();
builder.add(std::move(communication_manager));
- builder.add(std::make_unique<Bouncer>(compReg, _configUri));
+ auto bouncer = std::make_unique<Bouncer>(compReg, bouncer_config());
+ _bouncer = bouncer.get();
+ builder.add(std::move(bouncer));
auto merge_throttler_up = std::make_unique<MergeThrottler>(_configUri, compReg);
auto merge_throttler = merge_throttler_up.get();
builder.add(std::move(merge_throttler_up));
@@ -215,4 +218,9 @@ void ServiceLayerNode::perform_post_chain_creation_init_steps() {
_fileStorManager->complete_internal_initialization();
}
+void ServiceLayerNode::on_bouncer_config_changed() {
+ assert(_bouncer);
+ _bouncer->on_configure(bouncer_config());
+}
+
} // storage
diff --git a/storage/src/vespa/storage/storageserver/servicelayernode.h b/storage/src/vespa/storage/storageserver/servicelayernode.h
index 91a799c1295..4a5c2e37bb3 100644
--- a/storage/src/vespa/storage/storageserver/servicelayernode.h
+++ b/storage/src/vespa/storage/storageserver/servicelayernode.h
@@ -20,6 +20,7 @@ namespace storage {
namespace spi { struct PersistenceProvider; }
+class Bouncer;
class BucketManager;
class FileStorManager;
@@ -35,8 +36,9 @@ class ServiceLayerNode
// FIXME: Should probably use the fetcher in StorageNode
std::unique_ptr<config::ConfigFetcher> _configFetcher;
- BucketManager * _bucket_manager;
- FileStorManager * _fileStorManager;
+ Bouncer* _bouncer;
+ BucketManager* _bucket_manager;
+ FileStorManager* _fileStorManager;
bool _init_has_been_called;
public:
@@ -67,6 +69,7 @@ private:
documentapi::Priority::Value toDocumentPriority(uint8_t storagePriority) const override;
void createChain(IStorageChainBuilder &builder) override;
void removeConfigSubscriptions() override;
+ void on_bouncer_config_changed() override;
};
} // storage
diff --git a/storage/src/vespa/storage/storageserver/storagenode.cpp b/storage/src/vespa/storage/storageserver/storagenode.cpp
index f835b286165..3b0f3d875cd 100644
--- a/storage/src/vespa/storage/storageserver/storagenode.cpp
+++ b/storage/src/vespa/storage/storageserver/storagenode.cpp
@@ -106,6 +106,7 @@ void
StorageNode::subscribeToConfigs()
{
_configFetcher = std::make_unique<config::ConfigFetcher>(_configUri.getContext());
+ _configFetcher->subscribe<StorBouncerConfig>(_configUri.getConfigId(), this);
_configFetcher->subscribe<BucketspacesConfig>(_configUri.getConfigId(), this);
_configFetcher->subscribe<CommunicationManagerConfig>(_configUri.getConfigId(), this);
_configFetcher->subscribe<StorDistributionConfig>(_configUri.getConfigId(), this);
@@ -115,6 +116,7 @@ StorageNode::subscribeToConfigs()
// All the below config instances were synchronously populated as part of start()ing the config fetcher
std::lock_guard configLockGuard(_configLock);
+ _bouncer_config.promote_staging_to_active();
_bucket_spaces_config.promote_staging_to_active();
_comm_mgr_config.promote_staging_to_active();
_distribution_config.promote_staging_to_active();
@@ -318,6 +320,10 @@ StorageNode::handleLiveConfigUpdate(const InitialGuard & initGuard)
_comm_mgr_config.promote_staging_to_active();
_communicationManager->on_configure(communication_manager_config());
}
+ if (_bouncer_config.staging) {
+ _bouncer_config.promote_staging_to_active();
+ on_bouncer_config_changed();
+ }
}
void
@@ -441,10 +447,15 @@ StorageNode::configure(std::unique_ptr<BucketspacesConfig> config) {
}
void
-StorageNode::configure(std::unique_ptr<CommunicationManagerConfig > config) {
+StorageNode::configure(std::unique_ptr<CommunicationManagerConfig> config) {
stage_config_change(_comm_mgr_config, std::move(config));
}
+void
+StorageNode::configure(std::unique_ptr<StorBouncerConfig> config) {
+ stage_config_change(_bouncer_config, std::move(config));
+}
+
template <typename ConfigT>
void
StorageNode::stage_config_change(ConfigWrapper<ConfigT>& cfg, std::unique_ptr<ConfigT> new_cfg) {
diff --git a/storage/src/vespa/storage/storageserver/storagenode.h b/storage/src/vespa/storage/storageserver/storagenode.h
index fb616eb2475..ef2879d8f8a 100644
--- a/storage/src/vespa/storage/storageserver/storagenode.h
+++ b/storage/src/vespa/storage/storageserver/storagenode.h
@@ -15,6 +15,7 @@
#include <vespa/config/subscription/configuri.h>
#include <vespa/document/config/config-documenttypes.h>
#include <vespa/storage/common/doneinitializehandler.h>
+#include <vespa/storage/config/config-stor-bouncer.h>
#include <vespa/storage/config/config-stor-communicationmanager.h>
#include <vespa/storage/config/config-stor-server.h>
#include <vespa/storage/storageutil/resumeguard.h>
@@ -52,6 +53,7 @@ class StorageNode : private config::IFetcherCallback<vespa::config::content::cor
private config::IFetcherCallback<vespa::config::content::StorDistributionConfig>,
private config::IFetcherCallback<vespa::config::content::core::BucketspacesConfig>,
private config::IFetcherCallback<vespa::config::content::core::StorCommunicationmanagerConfig>,
+ private config::IFetcherCallback<vespa::config::content::core::StorBouncerConfig>,
private framework::MetricUpdateHook,
private DoneInitializeHandler,
private framework::defaultimplementation::ShutdownListener
@@ -92,6 +94,7 @@ public:
protected:
using BucketspacesConfig = vespa::config::content::core::BucketspacesConfig;
using CommunicationManagerConfig = vespa::config::content::core::StorCommunicationmanagerConfig;
+ using StorBouncerConfig = vespa::config::content::core::StorBouncerConfig;
using StorDistributionConfig = vespa::config::content::StorDistributionConfig;
using StorServerConfig = vespa::config::content::core::StorServerConfig;
private:
@@ -142,6 +145,7 @@ private:
void configure(std::unique_ptr<StorDistributionConfig> config) override;
void configure(std::unique_ptr<BucketspacesConfig>) override;
void configure(std::unique_ptr<CommunicationManagerConfig> config) override;
+ void configure(std::unique_ptr<StorBouncerConfig> config) override;
protected:
// Lock taken while doing configuration of the server.
@@ -149,11 +153,15 @@ protected:
std::mutex _initial_config_mutex;
using InitialGuard = std::lock_guard<std::mutex>;
+ ConfigWrapper<StorBouncerConfig> _bouncer_config;
ConfigWrapper<BucketspacesConfig> _bucket_spaces_config;
ConfigWrapper<CommunicationManagerConfig> _comm_mgr_config;
ConfigWrapper<StorDistributionConfig> _distribution_config;
ConfigWrapper<StorServerConfig> _server_config;
+ [[nodiscard]] const StorBouncerConfig& bouncer_config() const noexcept {
+ return *_bouncer_config.active;
+ }
[[nodiscard]] const BucketspacesConfig& bucket_spaces_config() const noexcept {
return *_bucket_spaces_config.active;
}
@@ -192,6 +200,8 @@ protected:
virtual void handleLiveConfigUpdate(const InitialGuard & initGuard);
void shutdown();
virtual void removeConfigSubscriptions();
+
+ virtual void on_bouncer_config_changed() { /* no-op by default */ }
public:
void set_storage_chain_builder(std::unique_ptr<IStorageChainBuilder> builder);
};