diff options
19 files changed, 260 insertions, 52 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/Slobrok.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/Slobrok.java index 093694f41b3..aa6192291d3 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/admin/Slobrok.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/Slobrok.java @@ -2,6 +2,7 @@ package com.yahoo.vespa.model.admin; import com.yahoo.config.model.producer.AbstractConfigProducer; +import com.yahoo.vespa.config.StateserverConfig; import com.yahoo.vespa.model.AbstractService; /** @@ -9,9 +10,14 @@ import com.yahoo.vespa.model.AbstractService; * * @author gjoranv */ -public class Slobrok extends AbstractService { +public class Slobrok extends AbstractService implements StateserverConfig.Producer { private static final long serialVersionUID = 1L; + @Override + public void getConfig(StateserverConfig.Builder builder) { + builder.httpport(getStatePort()); + } + /** * @param parent The parent ConfigProducer. * @param index unique index for all slobroks @@ -40,9 +46,7 @@ public class Slobrok extends AbstractService { } public String getStartupCommand() { - return "exec $ROOT/sbin/vespa-slobrok -p " + getPort() + - " -s " + getStatePort() + - " -c " + getConfigId(); + return "exec $ROOT/sbin/vespa-slobrok -p " + getPort() + " -c " + getConfigId(); } /** @@ -55,15 +59,15 @@ public class Slobrok extends AbstractService { /** * @return The port on which this slobrok should respond, as a String. */ - public String getPort() { + private String getPort() { return String.valueOf(getRelativePort(0)); } /** * @return The port on which the state server should respond */ - public String getStatePort() { - return String.valueOf(getRelativePort(1)); + public int getStatePort() { + return getRelativePort(1); } /** diff --git a/config-model/src/test/java/com/yahoo/vespa/model/admin/AdminTestCase.java b/config-model/src/test/java/com/yahoo/vespa/model/admin/AdminTestCase.java index 5e6241a7043..a88d3b388a9 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/admin/AdminTestCase.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/admin/AdminTestCase.java @@ -17,6 +17,7 @@ import com.yahoo.config.provision.Zone; import com.yahoo.container.StatisticsConfig; import com.yahoo.container.jdisc.config.HealthMonitorConfig; import com.yahoo.net.HostName; +import com.yahoo.vespa.config.StateserverConfig; import com.yahoo.vespa.model.VespaModel; import com.yahoo.vespa.model.container.ContainerCluster; import com.yahoo.vespa.model.container.component.Component; @@ -83,6 +84,13 @@ public class AdminTestCase { } assertTrue(localHostOK); + StateserverConfig.Builder ssb = new StateserverConfig.Builder(); + vespaModel.getConfig(ssb, "admin/slobrok.0"); + assertEquals(19100, new StateserverConfig(ssb).httpport()); + + vespaModel.getConfig(ssb, "admin/slobrok.1"); + assertEquals(19102, new StateserverConfig(ssb).httpport()); + LogdConfig.Builder lb = new LogdConfig.Builder(); vespaModel.getConfig(lb, "admin/slobrok.0"); LogdConfig lc = new LogdConfig(lb); diff --git a/config/src/vespa/config/helper/configfetcher.cpp b/config/src/vespa/config/helper/configfetcher.cpp index b7e15240255..5a3cdad814e 100644 --- a/config/src/vespa/config/helper/configfetcher.cpp +++ b/config/src/vespa/config/helper/configfetcher.cpp @@ -16,7 +16,7 @@ ConfigFetcher::ConfigFetcher(const IConfigContext::SP & context) } ConfigFetcher::ConfigFetcher(const SourceSpec & spec) - : _poller(IConfigContext::SP(new ConfigContext(spec))), + : _poller(std::make_shared<ConfigContext>(spec)), _thread(std::make_unique<vespalib::Thread>(_poller)), _closed(false), _started(false) diff --git a/configdefinitions/src/vespa/CMakeLists.txt b/configdefinitions/src/vespa/CMakeLists.txt index e1e7a5a0c18..d7023e19622 100644 --- a/configdefinitions/src/vespa/CMakeLists.txt +++ b/configdefinitions/src/vespa/CMakeLists.txt @@ -74,3 +74,5 @@ vespa_generate_config(configdefinitions zookeepers.def) install_config_definition(zookeepers.def cloud.config.zookeepers.def) vespa_generate_config(configdefinitions bucketspaces.def) install_config_definition(bucketspaces.def vespa.config.content.core.bucketspaces.def) +vespa_generate_config(configdefinitions stateserver.def) +install_config_definition(stateserver.def vespa.config.stateserver.def) diff --git a/configdefinitions/src/vespa/stateserver.def b/configdefinitions/src/vespa/stateserver.def new file mode 100644 index 00000000000..5be221efb49 --- /dev/null +++ b/configdefinitions/src/vespa/stateserver.def @@ -0,0 +1,5 @@ +# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +namespace=vespa.config + +# Port used for serving the state/vN api +httpport int default = 0 diff --git a/configserver/src/test/apps/app-jdisc-only-restart/hosts.xml b/configserver/src/test/apps/app-jdisc-only-restart/hosts.xml new file mode 100644 index 00000000000..f4256c9fc81 --- /dev/null +++ b/configserver/src/test/apps/app-jdisc-only-restart/hosts.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!-- Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> +<hosts> + <host name="mytesthost"> + <alias>node1</alias> + </host> +</hosts> diff --git a/configserver/src/test/apps/app-jdisc-only-restart/searchdefinitions/music.sd b/configserver/src/test/apps/app-jdisc-only-restart/searchdefinitions/music.sd new file mode 100644 index 00000000000..2e40523a6d9 --- /dev/null +++ b/configserver/src/test/apps/app-jdisc-only-restart/searchdefinitions/music.sd @@ -0,0 +1,57 @@ +# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +# A basic search definition - called music, should be saved to music.sd +search music { + + # It contains one document type only - called music as well + document music { + + field title type string { + indexing: summary | index # How this field should be indexed + # index-to: title, default # Create two indexes + weight: 75 # Ranking importancy of this field, used by the built in nativeRank feature + header + } + + field artist type string { + indexing: summary | attribute | index + # index-to: artist, default + + weight: 25 + header + } + + field year type int { + indexing: summary | attribute + header + } + + # Increase query + field popularity type int { + indexing: summary | attribute + body + } + + field url type uri { + indexing: summary | index + header + } + + } + + rank-profile default inherits default { + first-phase { + expression: nativeRank(title,artist) + attribute(popularity) + } + + } + + rank-profile textmatch inherits default { + first-phase { + expression: nativeRank(title,artist) + } + + } + + + +} diff --git a/configserver/src/test/apps/app-jdisc-only-restart/services.xml b/configserver/src/test/apps/app-jdisc-only-restart/services.xml new file mode 100644 index 00000000000..b864ea206ef --- /dev/null +++ b/configserver/src/test/apps/app-jdisc-only-restart/services.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!-- Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. --> +<services version="1.0"> + + <admin version="2.0"> + <adminserver hostalias="node1"/> + <slobroks> + <slobrok hostalias="node1" baseport="12345"/> + </slobroks> + </admin> + + <jdisc version="1.0"> + <document-processing compressdocuments="true"> + <chain id="ContainerWrapperTest"> + <documentprocessor id="com.yahoo.vespa.config.AppleDocProc"/> + </chain> + </document-processing> + + <config name="project.specific"> + <value>someval</value> + </config> + + <nodes> + <node hostalias="node1" /> + </nodes> + + </jdisc> + +</services> diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java index ecc3a8a0a54..0b7e9a78967 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/ApplicationRepositoryTest.java @@ -33,6 +33,8 @@ public class ApplicationRepositoryTest { private final static File testApp = new File("src/test/apps/app"); private final static File testAppJdiscOnly = new File("src/test/apps/app-jdisc-only"); + private final static File testAppJdiscOnlyRestart = new File("src/test/apps/app-jdisc-only-restart"); + private final static TenantName tenantName = TenantName.from("test"); private final static Clock clock = Clock.systemUTC(); @@ -63,7 +65,7 @@ public class ApplicationRepositoryTest { @Test public void prepareAndActivateWithRestart() throws IOException { prepareAndActivateApp(testAppJdiscOnly); - PrepareResult result = prepareAndActivateApp(testApp); + PrepareResult result = prepareAndActivateApp(testAppJdiscOnlyRestart); assertTrue(result.configChangeActions().getRefeedActions().isEmpty()); assertFalse(result.configChangeActions().getRestartActions().isEmpty()); } diff --git a/slobrok/src/apps/slobrok/slobrok.cpp b/slobrok/src/apps/slobrok/slobrok.cpp index 277cc2f3a87..e69f2df53f0 100644 --- a/slobrok/src/apps/slobrok/slobrok.cpp +++ b/slobrok/src/apps/slobrok/slobrok.cpp @@ -50,7 +50,6 @@ int App::Main() { uint32_t portnum = 2773; - uint32_t statePort = 0; vespalib::string cfgId; int argi = 1; @@ -61,9 +60,6 @@ App::Main() case 'c': cfgId = std::string(optArg); break; - case 's': - statePort = atoi(optArg); - break; case 'p': portnum = atoi(optArg); break; @@ -77,10 +73,11 @@ App::Main() if (cfgId.empty()) { LOG(debug, "no config id specified"); ConfigShim shim(portnum); - mainobj.reset(new SBEnv(shim)); + mainobj = std::make_unique<SBEnv>(shim); } else { - ConfigShim shim(portnum, statePort, cfgId); - mainobj.reset(new SBEnv(shim)); + ConfigShim shim(portnum, cfgId); + shim.enableStateServer(true); + mainobj = std::make_unique<SBEnv>(shim); } hook_sigterm(); res = mainobj->MainLoop(); diff --git a/slobrok/src/vespa/slobrok/cfg.cpp b/slobrok/src/vespa/slobrok/cfg.cpp index 720fb5df962..a1f165fa7ea 100644 --- a/slobrok/src/vespa/slobrok/cfg.cpp +++ b/slobrok/src/vespa/slobrok/cfg.cpp @@ -1,9 +1,6 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "cfg.h" -#include <vespa/log/log.h> -LOG_SETUP(".slobrok.configurator"); - namespace slobrok { namespace { diff --git a/slobrok/src/vespa/slobrok/server/CMakeLists.txt b/slobrok/src/vespa/slobrok/server/CMakeLists.txt index 5ca41967524..a6772404ead 100644 --- a/slobrok/src/vespa/slobrok/server/CMakeLists.txt +++ b/slobrok/src/vespa/slobrok/server/CMakeLists.txt @@ -22,6 +22,7 @@ vespa_add_library(slobrok_slobrokserver slobrokserver.cpp visible_map.cpp metrics_producer.cpp + reconfigurable_stateserver.cpp INSTALL lib64 DEPENDS slobrok diff --git a/slobrok/src/vespa/slobrok/server/configshim.cpp b/slobrok/src/vespa/slobrok/server/configshim.cpp index 83f91a29b30..15c39516ded 100644 --- a/slobrok/src/vespa/slobrok/server/configshim.cpp +++ b/slobrok/src/vespa/slobrok/server/configshim.cpp @@ -5,24 +5,26 @@ namespace slobrok { ConfigShim::ConfigShim(uint32_t port) - : _port(port), _statePort(0), _configId(""), + : _port(port), + _enableStateServer(false), + _configId(""), _factory(config::ConfigUri::createEmpty()) {} -ConfigShim::ConfigShim(uint32_t port, uint32_t statePort_in, const std::string& cfgId) +ConfigShim::ConfigShim(uint32_t port, const std::string& cfgId) : _port(port), - _statePort(statePort_in), + _enableStateServer(false), _configId(cfgId), _factory(config::ConfigUri(_configId)) {} ConfigShim::ConfigShim(uint32_t port, const std::string& cfgId, config::IConfigContext::SP cfgCtx) : _port(port), - _statePort(0), + _enableStateServer(false), _configId(cfgId), _factory(config::ConfigUri(cfgId, cfgCtx)) {} -ConfigShim::~ConfigShim() {} +ConfigShim::~ConfigShim() = default; } diff --git a/slobrok/src/vespa/slobrok/server/configshim.h b/slobrok/src/vespa/slobrok/server/configshim.h index ed3c04b6233..750f6a4c139 100644 --- a/slobrok/src/vespa/slobrok/server/configshim.h +++ b/slobrok/src/vespa/slobrok/server/configshim.h @@ -9,19 +9,20 @@ namespace slobrok { class ConfigShim { private: - uint32_t _port; - uint32_t _statePort; - std::string _configId; + uint32_t _port; + bool _enableStateServer; + std::string _configId; ConfiguratorFactory _factory; public: ConfigShim(uint32_t port); - ConfigShim(uint32_t port, uint32_t statePort_in, const std::string& cfgId); + ConfigShim(uint32_t port, const std::string& cfgId); ConfigShim(uint32_t port, const std::string& cfgId, config::IConfigContext::SP cfgCtx); ~ConfigShim(); + ConfigShim & enableStateServer(bool v) { _enableStateServer = v; return *this; } + bool enableStateServer() const { return _enableStateServer; } uint32_t portNumber() const { return _port; } - uint32_t statePort() const { return _statePort; } std::string configId() const { return _configId; } const char *id() const { return _configId.c_str(); } const ConfiguratorFactory & factory() const { return _factory; } diff --git a/slobrok/src/vespa/slobrok/server/reconfigurable_stateserver.cpp b/slobrok/src/vespa/slobrok/server/reconfigurable_stateserver.cpp new file mode 100644 index 00000000000..ca6dcad1932 --- /dev/null +++ b/slobrok/src/vespa/slobrok/server/reconfigurable_stateserver.cpp @@ -0,0 +1,61 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "reconfigurable_stateserver.h" +#include <vespa/vespalib/util/exceptions.h> +#include <vespa/vespalib/net/state_server.h> +#include <thread> + +#include <vespa/log/log.h> +#include <vespa/config/common/exceptions.h> + +LOG_SETUP(".reconfigurable_stateserver"); + +using namespace std::chrono_literals; + +namespace slobrok { + +ReconfigurableStateServer::ReconfigurableStateServer(const config::ConfigUri & configUri, + vespalib::HealthProducer & health, + vespalib::MetricsProducer & metrics, + vespalib::ComponentConfigProducer & components) + : _health(health), + _metrics(metrics), + _components(components), + _configFetcher(std::make_unique<config::ConfigFetcher>(configUri.getContext())), + _server() +{ + _configFetcher->subscribe<vespa::config::StateserverConfig>(configUri.getConfigId(), this); + _configFetcher->start(); +} + +ReconfigurableStateServer::~ReconfigurableStateServer() +{ + _configFetcher->close(); +} + +void +ReconfigurableStateServer::configure(std::unique_ptr<vespa::config::StateserverConfig> config) +{ + _server.reset(); + for (size_t retryTime(1); !_server && (retryTime < 10); retryTime++) { + try { + _server = std::make_unique<vespalib::StateServer>(config->httpport, _health, _metrics, _components); + } catch (vespalib::PortListenException & e) { + LOG(warning, "Failed listening to network port(%d) with protocol(%s): '%s', will retry for 60s", + e.get_port(), e.get_protocol().c_str(), e.what()); + std::this_thread::sleep_for(retryTime * 1s); + } + } + if (!_server) { + try { + _server = std::make_unique<vespalib::StateServer>(config->httpport, _health, _metrics, _components); + } catch (vespalib::PortListenException & e) { + LOG(error, "Failed listening to network port(%d) with protocol(%s): '%s', giving up and restarting.", + e.get_port(), e.get_protocol().c_str(), e.what()); + std::quick_exit(17); + } + } + +} + +} diff --git a/slobrok/src/vespa/slobrok/server/reconfigurable_stateserver.h b/slobrok/src/vespa/slobrok/server/reconfigurable_stateserver.h new file mode 100644 index 00000000000..a8747d09bfd --- /dev/null +++ b/slobrok/src/vespa/slobrok/server/reconfigurable_stateserver.h @@ -0,0 +1,31 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include <vespa/config/helper/configfetcher.h> +#include <vespa/config/subscription/configuri.h> +#include <vespa/config-stateserver.h> + +namespace vespalib { + class HealthProducer; + class MetricsProducer; + class ComponentConfigProducer; + class StateServer; +} +namespace slobrok { + +class ReconfigurableStateServer : private config::IFetcherCallback<vespa::config::StateserverConfig> { +public: + ReconfigurableStateServer(const config::ConfigUri & configUri, + vespalib::HealthProducer & healt, + vespalib::MetricsProducer & metrics, + vespalib::ComponentConfigProducer & component); + ~ReconfigurableStateServer(); +private: + void configure(std::unique_ptr<vespa::config::StateserverConfig> config) override; + vespalib::HealthProducer & _health; + vespalib::MetricsProducer & _metrics; + vespalib::ComponentConfigProducer & _components; + std::unique_ptr<config::ConfigFetcher> _configFetcher; + std::unique_ptr<vespalib::StateServer> _server; +}; + +} diff --git a/slobrok/src/vespa/slobrok/server/sbenv.cpp b/slobrok/src/vespa/slobrok/server/sbenv.cpp index 002dd2244ca..35af0daf24a 100644 --- a/slobrok/src/vespa/slobrok/server/sbenv.cpp +++ b/slobrok/src/vespa/slobrok/server/sbenv.cpp @@ -1,20 +1,25 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include "reconfigurable_stateserver.h" #include "sbenv.h" #include "selfcheck.h" #include "remote_check.h" -#include <sstream> -#include <vespa/vespalib/net/state_server.h> #include <vespa/vespalib/util/host_name.h> -#include <vespa/vespalib/util/exception.h> +#include <vespa/vespalib/util/exceptions.h> #include <vespa/vespalib/stllike/asciistream.h> #include <vespa/fnet/frt/supervisor.h> #include <vespa/fnet/transport.h> +#include <vespa/config/helper/configfetcher.h> +#include <thread> +#include <sstream> #include <vespa/log/log.h> LOG_SETUP(".sbenv"); +using namespace std::chrono_literals; + namespace slobrok { + namespace { void @@ -80,17 +85,16 @@ ConfigTask::PerformTask() } // namespace slobrok::<unnamed> SBEnv::SBEnv(const ConfigShim &shim) - : _transport(new FNET_Transport()), - _supervisor(new FRT_Supervisor(_transport.get(), NULL)), - _sbPort(shim.portNumber()), - _statePort(shim.statePort()), + : _transport(std::make_unique<FNET_Transport>()), + _supervisor(std::make_unique<FRT_Supervisor>(_transport.get(), nullptr)), + _configShim(shim), _configurator(shim.factory().create(*this)), _shuttingDown(false), _partnerList(), _me(), _rpcHooks(*this, _rpcsrvmap, _rpcsrvmanager), - _selfchecktask(new SelfCheck(getSupervisor()->GetScheduler(), _rpcsrvmap, _rpcsrvmanager)), - _remotechecktask(new RemoteCheck(getSupervisor()->GetScheduler(), _rpcsrvmap, _rpcsrvmanager, _exchanger)), + _selfchecktask(std::make_unique<SelfCheck>(getSupervisor()->GetScheduler(), _rpcsrvmap, _rpcsrvmanager)), + _remotechecktask(std::make_unique<RemoteCheck>(getSupervisor()->GetScheduler(), _rpcsrvmap, _rpcsrvmanager, _exchanger)), _health(), _metrics(_rpcHooks, *_transport), _components(), @@ -98,7 +102,7 @@ SBEnv::SBEnv(const ConfigShim &shim) _exchanger(*this, _rpcsrvmap), _rpcsrvmap() { - srandom(time(NULL) ^ getpid()); + srandom(time(nullptr) ^ getpid()); _rpcHooks.initRPC(getSupervisor()); } @@ -158,20 +162,22 @@ toString(const std::vector<std::string> & v) { int SBEnv::MainLoop() { - vespalib::StateServer stateServer(_statePort, _health, _metrics, _components); - - if (! getSupervisor()->Listen(_sbPort)) { - LOG(error, "unable to listen to port %d", _sbPort); + if (! getSupervisor()->Listen(_configShim.portNumber())) { + LOG(error, "unable to listen to port %d", _configShim.portNumber()); EV_STOPPING("slobrok", "could not listen"); return 1; } else { - LOG(config, "listening on port %d", _sbPort); + LOG(config, "listening on port %d", _configShim.portNumber()); } - std::string myspec = createSpec(_sbPort); + std::string myspec = createSpec(_configShim.portNumber()); + + _me = std::make_unique<ManagedRpcServer>(myspec.c_str(), myspec.c_str(), _rpcsrvmanager); - _me.reset(new ManagedRpcServer(myspec.c_str(), myspec.c_str(), - _rpcsrvmanager)); + std::unique_ptr<ReconfigurableStateServer> stateServer; + if (_configShim.enableStateServer()) { + stateServer = std::make_unique<ReconfigurableStateServer>(_configShim.configId(), _health, _metrics, _components); + } try { _configurator->poll(); diff --git a/slobrok/src/vespa/slobrok/server/sbenv.h b/slobrok/src/vespa/slobrok/server/sbenv.h index f96b7540b3a..8c897c9c999 100644 --- a/slobrok/src/vespa/slobrok/server/sbenv.h +++ b/slobrok/src/vespa/slobrok/server/sbenv.h @@ -8,10 +8,10 @@ #include "exchange_manager.h" #include "configshim.h" #include "ok_state.h" +#include "metrics_producer.h" #include <vespa/config-slobroks.h> #include <vespa/slobrok/cfg.h> #include <vespa/vespalib/net/simple_health_producer.h> -#include "metrics_producer.h" #include <vespa/vespalib/net/simple_component_config_producer.h> class FastOS_ThreadPool; @@ -23,7 +23,6 @@ namespace slobrok { class NamedService; class ManagedRpcServer; -class RemoteRpcServer; class RPCHooks; class SelfCheck; class RemoteCheck; @@ -40,8 +39,7 @@ private: std::unique_ptr<FNET_Transport> _transport; std::unique_ptr<FRT_Supervisor> _supervisor; - uint32_t _sbPort; - uint32_t _statePort; + ConfigShim _configShim; Configurator::UP _configurator; bool _shuttingDown; diff --git a/staging_vespalib/src/vespa/vespalib/net/state_server.cpp b/staging_vespalib/src/vespa/vespalib/net/state_server.cpp index 61c3e4e6f74..bb81a3aa535 100644 --- a/staging_vespalib/src/vespa/vespalib/net/state_server.cpp +++ b/staging_vespalib/src/vespa/vespalib/net/state_server.cpp @@ -17,6 +17,6 @@ StateServer::StateServer(int port, _server.start(); } -StateServer::~StateServer() {} +StateServer::~StateServer() = default; } // namespace vespalib |