// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. /** * @class storage::StorageNode * @ingroup storageserver * * @brief Main storage server class. * * This class sets up the entire storage server. * * @author HÃ¥kon Humberset */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include namespace document { class DocumentTypeRepo; } namespace config { class ConfigFetcher; } namespace storage { class ApplicationGenerationFetcher; class CommunicationManager; class FileStorManager; class HostInfo; class IStorageChainBuilder; class NodeIdentity; class StateManager; class StateReporter; class StatusMetricConsumer; class StatusWebServer; class StorageComponent; class StorageLink; class NodeStateReporter; struct DeadLockDetector; struct StorageMetricSet; struct StorageNodeContext; namespace lib { class NodeType; } class StorageNode : private config::IFetcherCallback, private config::IFetcherCallback, private config::IFetcherCallback, private config::IFetcherCallback, private framework::MetricUpdateHook, private DoneInitializeHandler, private framework::defaultimplementation::ShutdownListener { public: enum RunMode { NORMAL, SINGLE_THREADED_TEST_MODE }; StorageNode(const StorageNode &) = delete; StorageNode & operator = (const StorageNode &) = delete; /** * @param excludeStorageChain With this option set, no chain will be set * up. This can be useful in unit testing if you need a storage server * instance, but you want to have full control over the components yourself. */ StorageNode(const config::ConfigUri & configUri, StorageNodeContext& context, ApplicationGenerationFetcher& generationFetcher, std::unique_ptr hostInfo, RunMode = NORMAL); ~StorageNode() override; virtual const lib::NodeType& getNodeType() const = 0; bool attemptedStopped() const; void notifyDoneInitializing() override; void waitUntilInitialized(vespalib::duration timeout = 15s); void updateMetrics(const MetricLockGuard & guard) override; /** Updates the document type repo. */ void setNewDocumentRepo(const std::shared_ptr& repo); /** * Pauses the persistence processing. While the returned ResumeGuard * is alive, no calls will be made towards the persistence provider. */ virtual ResumeGuard pause() = 0; void requestShutdown(vespalib::stringref reason) override; DoneInitializeHandler& getDoneInitializeHandler() { return *this; } // For testing StorageLink* getChain() { return _chain.get(); } virtual void initializeStatusWebServer(); protected: using StorServerConfig = vespa::config::content::core::StorServerConfig; using UpgradingConfig = vespa::config::content::UpgradingConfig; using StorDistributionConfig = vespa::config::content::StorDistributionConfig; using BucketspacesConfig = vespa::config::content::core::BucketspacesConfig; private: bool _singleThreadedDebugMode; // Subscriptions to config std::unique_ptr _configFetcher; std::unique_ptr _hostInfo; StorageNodeContext& _context; ApplicationGenerationFetcher& _generationFetcher; vespalib::string _rootFolder; std::atomic _attemptedStopped; vespalib::string _pidFile; // First components that doesn't depend on others std::unique_ptr _statusWebServer; std::shared_ptr _metrics; std::unique_ptr _metricManager; // Depends on bucket databases and stop() functionality std::unique_ptr _deadLockDetector; // Depends on metric manager std::unique_ptr _statusMetrics; // Depends on metric manager std::unique_ptr _stateReporter; std::unique_ptr _stateManager; // The storage chain can depend on anything. std::unique_ptr _chain; /** Implementation of config callbacks. */ void configure(std::unique_ptr config) override; void configure(std::unique_ptr config) override; void configure(std::unique_ptr config) override; virtual void configure(std::unique_ptr config, bool hasChanged, int64_t generation); void configure(std::unique_ptr) override; protected: // Lock taken while doing configuration of the server. std::mutex _configLock; std::mutex _initial_config_mutex; using InitialGuard = std::lock_guard; // Current running config. Kept, such that we can see what has been // changed in live config updates. std::unique_ptr _serverConfig; std::unique_ptr _clusterConfig; std::unique_ptr _distributionConfig; std::unique_ptr _doctypesConfig; std::unique_ptr _bucketSpacesConfig; // New configs gotten that has yet to have been handled std::unique_ptr _newServerConfig; std::unique_ptr _newClusterConfig; std::unique_ptr _newDistributionConfig; std::unique_ptr _newDoctypesConfig; std::unique_ptr _newBucketSpacesConfig; std::unique_ptr _component; std::unique_ptr _node_identity; config::ConfigUri _configUri; CommunicationManager* _communicationManager; private: std::unique_ptr _chain_builder; protected: /** * Node subclasses currently need to explicitly acquire ownership of state * manager so that they can add it to the end of their processing chains, * which this method allows for. * Any component releasing the state manager must ensure it lives for as * long as the node instance itself lives. */ std::unique_ptr releaseStateManager(); void initialize(const NodeStateReporter & reporter); virtual void subscribeToConfigs(); virtual void initializeNodeSpecific() = 0; virtual void perform_post_chain_creation_init_steps() = 0; virtual void createChain(IStorageChainBuilder &builder) = 0; virtual void handleLiveConfigUpdate(const InitialGuard & initGuard); void shutdown(); virtual void removeConfigSubscriptions(); public: void set_storage_chain_builder(std::unique_ptr builder); }; } // storage