diff options
21 files changed, 471 insertions, 74 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java index c07d6f66237..5698485b004 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV4Builder.java @@ -116,6 +116,7 @@ public class DomAdminV4Builder extends DomAdminBuilderBase { // Add base handlers and the log handler logServerCluster.addMetricStateHandler(); logServerCluster.addApplicationStatusHandler(); + logServerCluster.addStatisticsHandler(); logServerCluster.addDefaultRootHandler(); logServerCluster.addVipHandler(); addLogHandler(logServerCluster); diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java index d43defaeeb1..12613018ca7 100755 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/ContainerCluster.java @@ -232,6 +232,7 @@ public final class ContainerCluster addSimpleComponent("com.yahoo.container.jdisc.state.StateMonitor"); addSimpleComponent("com.yahoo.container.jdisc.ContainerThreadFactory"); addSimpleComponent("com.yahoo.container.protect.FreezeDetector"); + addSimpleComponent("com.yahoo.container.core.slobrok.SlobrokConfigurator"); addSimpleComponent("com.yahoo.container.handler.VipStatus"); addSimpleComponent(com.yahoo.container.handler.ClustersStatus.class.getName()); addJaxProviders(); @@ -288,6 +289,12 @@ public final class ContainerCluster addComponent(vipHandler); } + public void addStatisticsHandler() { + Handler<?> statsHandler = Handler.fromClassName(STATISTICS_HANDLER_CLASS); + statsHandler.addServerBindings("http://*/statistics/*", "https://*/statistics/*"); + addComponent(statsHandler); + } + @SuppressWarnings("deprecation") private void addJaxProviders() { addSimpleComponent(com.yahoo.container.xml.providers.DatatypeFactoryProvider.class); diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java index b5c1b1e1496..0be25808541 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java @@ -289,6 +289,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { cluster.addDefaultRootHandler(); cluster.addMetricStateHandler(); cluster.addApplicationStatusHandler(); + cluster.addStatisticsHandler(); } private void addClientProviders(DeployState deployState, Element spec, ContainerCluster cluster) { diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java index 49a989a9474..8158db51271 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerDocumentApiBuilderTest.java @@ -104,6 +104,7 @@ public class ContainerDocumentApiBuilderTest extends ContainerModelBuilderTestBa Map<String, Handler<?>> handlerMap = getHandlers("cluster1"); + assertThat(handlerMap.get("com.yahoo.container.config.StatisticsRequestHandler"), not(nullValue())); assertThat(handlerMap.get("com.yahoo.container.handler.VipStatusHandler"), not(nullValue())); assertThat(handlerMap.get("com.yahoo.container.handler.observability.ApplicationStatusHandler"), not(nullValue())); assertThat(handlerMap.get("com.yahoo.container.jdisc.state.StateHandler"), not(nullValue())); diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java index 0030392f318..aa1ac401014 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilderTest.java @@ -18,6 +18,7 @@ import com.yahoo.config.provision.SystemName; import com.yahoo.config.provision.Zone; import com.yahoo.container.ComponentsConfig; import com.yahoo.container.QrConfig; +import com.yahoo.container.config.StatisticsRequestHandler; import com.yahoo.container.core.ChainsConfig; import com.yahoo.container.core.VipStatusConfig; import com.yahoo.container.handler.VipStatusHandler; @@ -274,6 +275,10 @@ public class ContainerModelBuilderTest extends ContainerModelBuilderTestBase { assertThat(applicationStatusHandler.serverBindings(), contains("http://*/ApplicationStatus", "https://*/ApplicationStatus")); + JdiscBindingsConfig.Handlers statisticsRequestHandler = config.handlers(StatisticsRequestHandler.class.getName()); + assertTrue(statisticsRequestHandler.serverBindings(0).startsWith("http://*/statistics")); + assertTrue(statisticsRequestHandler.serverBindings(1).startsWith("https://*/statistics")); + JdiscBindingsConfig.Handlers fileRequestHandler = config.handlers(VipStatusHandler.class.getName()); assertThat(fileRequestHandler.serverBindings(), contains("http://*/status.html", "https://*/status.html")); diff --git a/container-core/src/main/java/com/yahoo/container/ConfigHack.java b/container-core/src/main/java/com/yahoo/container/ConfigHack.java new file mode 100644 index 00000000000..55cf208e163 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/ConfigHack.java @@ -0,0 +1,31 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container; + +import com.yahoo.container.config.StatisticsEmitter; + +/** + * Distribution point for QRS specific stuff in a more or less + * container agnostic way. This is only a stepping stone to moving these things + * to Container and other pertinent classes, or simply removing the problems. + * + * <p> + * This class should not reach a final release. + * + * @author Steinar Knutsen + */ +public final class ConfigHack { + + private volatile StatisticsEmitter statisticsEmitter = new StatisticsEmitter(); + public static final String TILED_TEMPLATE = "tiled"; + + public static final ConfigHack instance = new ConfigHack(); + + public StatisticsEmitter getStatisticsHandler() { + return statisticsEmitter; + } + + public void setStatisticsEmitter(StatisticsEmitter statisticsEmitter) { + this.statisticsEmitter = statisticsEmitter; + } + +} diff --git a/container-core/src/main/java/com/yahoo/container/Container.java b/container-core/src/main/java/com/yahoo/container/Container.java index c83dd2199ea..f378e7d51bd 100755 --- a/container-core/src/main/java/com/yahoo/container/Container.java +++ b/container-core/src/main/java/com/yahoo/container/Container.java @@ -4,6 +4,8 @@ package com.yahoo.container; import com.yahoo.component.AbstractComponent; import com.yahoo.component.provider.ComponentRegistry; import com.yahoo.container.core.config.BundleLoader; +import com.yahoo.container.osgi.AbstractRpcAdaptor; +import com.yahoo.container.osgi.ContainerRpcAdaptor; import com.yahoo.filedistribution.fileacquirer.FileAcquirer; import com.yahoo.filedistribution.fileacquirer.FileAcquirerFactory; import com.yahoo.jdisc.handler.RequestHandler; @@ -31,23 +33,35 @@ public class Container { private volatile ComponentRegistry<ServerProvider> serverProviderRegistry; private volatile ComponentRegistry<AbstractComponent> componentRegistry; private volatile FileAcquirer fileAcquirer; + private Osgi osgi; + + private final ContainerRpcAdaptor rpcAdaptor = new ContainerRpcAdaptor(osgi); private volatile BundleLoader bundleLoader; private static Logger logger = Logger.getLogger(Container.class.getName()); - // TODO: Make this final again. + //TODO: Make this final again. private static Container instance = new Container(); public static Container get() { return instance; } public void setOsgi(Osgi osgi) { + this.osgi = osgi; bundleLoader = new BundleLoader(osgi); } public void shutdown() { + com.yahoo.container.Server.get().shutdown(); if (fileAcquirer != null) fileAcquirer.shutdown(); + + rpcAdaptor.shutdown(); + } + + /** Returns the rpc adaptor owned by this */ + public ContainerRpcAdaptor getRpcAdaptor() { + return rpcAdaptor; } //Used to acquire files originating from the application package. @@ -61,13 +75,22 @@ public class Container { return bundleLoader; } - /** - * Hack. For internal use only, will be removed later + /** Hack. For internal use only, will be removed later * * Used by Application to be able to repeatedly set up containers. **/ public static void resetInstance() { instance = new Container(); + com.yahoo.container.Server.resetInstance(); + } + + /** + * Add an application specific RPC adaptor. + * + * @param adaptor the RPC adaptor to add to the Container + */ + public void addOptionalRpcAdaptor(AbstractRpcAdaptor adaptor) { + rpcAdaptor.bindRpcAdaptor(adaptor); } public ComponentRegistry<RequestHandler> getRequestHandlerRegistry() { @@ -142,5 +165,4 @@ public class Container { } }); } - } diff --git a/container-core/src/main/java/com/yahoo/container/Server.java b/container-core/src/main/java/com/yahoo/container/Server.java index a4dec6de5a2..293e8b4674e 100644 --- a/container-core/src/main/java/com/yahoo/container/Server.java +++ b/container-core/src/main/java/com/yahoo/container/Server.java @@ -3,43 +3,83 @@ package com.yahoo.container; import com.yahoo.config.subscription.ConfigSubscriber; import com.yahoo.container.QrConfig.Rpc; +import com.yahoo.container.osgi.ContainerRpcAdaptor; /** * The http server singleton managing listeners for various ports, * and the threads used to respond to requests on the ports * * @author bratseth - * @deprecated */ @SuppressWarnings("deprecation") -@Deprecated // TODO: Remove this when the last usage og getServerDiscriminator is removed public class Server { //TODO: Make this final again. - private static final Server instance = new Server(); + private static Server instance = new Server(); + private ConfigSubscriber subscriber = new ConfigSubscriber(); + + /** The OSGi container instance of this server */ + private Container container = Container.get(); /** A short string which is different for all the qrserver instances on a given node. */ private String localServerDiscriminator = "qrserver.0"; + /** Creates a new server instance. Not usually useful, use get() to get the current server */ private Server() { } + /** @deprecated returns 0 */ + @Deprecated + public int searchQueriesInFlight() { + return 0; + } + + /** + * An estimate of current number of connections. It is better to be + * inaccurate than to acquire a lock per query fsync. + * + * @return The current number of open search connections + */ + /** @deprecated returns 0 */ + @Deprecated + public int getCurrentConnections() { + return 0; + } + public static Server get() { return instance; } + private void initRpcServer(Rpc rpcConfig) { + if (rpcConfig.enabled()) { + ContainerRpcAdaptor rpcAdaptor = container.getRpcAdaptor(); + rpcAdaptor.listen(rpcConfig.port()); + rpcAdaptor.setSlobrokId(rpcConfig.slobrokId()); + } + } + + /** Ugly hack, see Container.resetInstance */ + static void resetInstance() { + instance = new Server(); + } + + // TODO: Make independent of config public void initialize(QrConfig config) { localServerDiscriminator = config.discriminator(); + container.setupFileAcquirer(config.filedistributor()); + initRpcServer(config.rpc()); } /** * A string unique for this QRS on this server. * * @return a server specific string - * @deprecated do not use */ - @Deprecated public String getServerDiscriminator() { return localServerDiscriminator; } + public void shutdown() { + if (subscriber!=null) subscriber.close(); + } + } diff --git a/container-core/src/main/java/com/yahoo/container/config/StatisticsEmitter.java b/container-core/src/main/java/com/yahoo/container/config/StatisticsEmitter.java new file mode 100644 index 00000000000..0e9d7ec9ce8 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/config/StatisticsEmitter.java @@ -0,0 +1,20 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.config; + + +import com.yahoo.container.jdisc.HttpRequest; + +/** + * An insulating layer between HTTP and whatever kind of HTTP statistics + * interface is made available. This is an intermediary step towards a + * generalized network layer. + * + * @author <a href="mailto:steinar@yahoo-inc.com">Steinar Knutsen</a> + */ +public class StatisticsEmitter { + + public StringBuilder respond(HttpRequest request) { + return new StringBuilder("No statistics available yet."); + } + +} diff --git a/container-core/src/main/java/com/yahoo/container/config/StatisticsRequestHandler.java b/container-core/src/main/java/com/yahoo/container/config/StatisticsRequestHandler.java new file mode 100644 index 00000000000..e0b6392b64a --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/config/StatisticsRequestHandler.java @@ -0,0 +1,55 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.config; + +import com.google.inject.Inject; +import com.yahoo.jdisc.Metric; +import com.yahoo.container.ConfigHack; +import com.yahoo.container.jdisc.HttpRequest; +import com.yahoo.container.jdisc.HttpResponse; +import com.yahoo.container.jdisc.ThreadedHttpRequestHandler; +import com.yahoo.container.logging.AccessLog; +import com.yahoo.text.Utf8; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.util.concurrent.Executor; + +/** + * Handler of statistics http requests. Temporary hack as a step towards a more + * general network interface. + * + * @author Steinar Knutsen + * @author Einar M R Rosenvinge + */ +public class StatisticsRequestHandler extends ThreadedHttpRequestHandler { + + @Inject + public StatisticsRequestHandler(Executor executor, Metric metric) { + super(executor, metric); + } + + @Override + public HttpResponse handle(HttpRequest request) { + return new StatisticsResponse(ConfigHack.instance.getStatisticsHandler().respond(request)); + } + + protected static class StatisticsResponse extends HttpResponse { + + private final StringBuilder string; + + private StatisticsResponse(StringBuilder stringBuilder) { + super(com.yahoo.jdisc.http.HttpResponse.Status.OK); + this.string = stringBuilder; + } + + @Override + public void render(OutputStream stream) throws IOException { + Writer osWriter = new OutputStreamWriter(stream, Utf8.getCharset()); + osWriter.write(string.toString()); + osWriter.flush(); + osWriter.close(); + } + } +} diff --git a/container-core/src/main/java/com/yahoo/container/config/package-info.java b/container-core/src/main/java/com/yahoo/container/config/package-info.java new file mode 100644 index 00000000000..b8e45b636dc --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/config/package-info.java @@ -0,0 +1,5 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +@ExportPackage +package com.yahoo.container.config; + +import com.yahoo.osgi.annotation.ExportPackage; diff --git a/container-core/src/main/java/com/yahoo/container/config/testutil/TestUtil.java b/container-core/src/main/java/com/yahoo/container/config/testutil/TestUtil.java new file mode 100644 index 00000000000..dbf8be8e1dc --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/config/testutil/TestUtil.java @@ -0,0 +1,85 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.config.testutil; + +import com.yahoo.container.core.config.HandlersConfigurerDi; + +import java.io.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author gjoranv + */ +public class TestUtil { + + public static void createComponentsConfig(String configFile, + String componentsFile, + String componentType) throws IOException { + createComponentsConfig(configFile, componentsFile, componentType, false); + } + + /** + * Copies the component ids from another config, e.g. 'handlers' to a 'components' array in a new components file, + * to avoid a manually written 'components' file for tests where the bundle spec is given by the component id. + * @param configFile Full path to the original config file, e.g. 'handlers' + * @param componentsFile Full path to the new 'components' file + * @param componentType The type of component, e.g. 'handler' + * @param append 'true' will append to an already existing 'componentsFile' + */ + public static void createComponentsConfig(String configFile, + String componentsFile, + String componentType, + boolean append) throws IOException { + StringBuilder buf = new StringBuilder(); + String line; + int i = 0; + if (append) { + final Pattern p = Pattern.compile("^[a-z]+" + "\\[\\d+\\]\\.id (.+)"); + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream(new File(componentsFile)), "UTF-8")); + while ((line = reader.readLine()) != null) { + Matcher m = p.matcher(line); + if (m.matches() && !m.group(1).equals(HandlersConfigurerDi.RegistriesHack.class.getName())) { + buf.append("components[").append(i).append("].id ").append(m.group(1)).append("\n"); + i++; + } + } + reader.close(); + } + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream(new File(configFile)), "UTF-8")); + final Pattern component = Pattern.compile("^" + componentType + "\\[\\d+\\]\\.id (.+)"); + while ((line = reader.readLine()) != null) { + Matcher m = component.matcher(line); + if (m.matches()) { + buf.append("components[").append(i).append("].id ").append(m.group(1)).append("\n"); + i++; + } + } + buf.append("components[").append(i).append("].id "). + append(HandlersConfigurerDi.RegistriesHack.class.getName()).append("\n"); + i++; + reader.close(); + buf.insert(0, "components["+i+"]\n"); + + Writer writer = new OutputStreamWriter(new FileOutputStream(new File(componentsFile)), "UTF-8"); + writer.write(buf.toString()); + writer.flush(); + writer.close(); + } + + /** + * Copies src file to dst file. If the dst file does not exist, it is created. + */ + public static void copyFile(String srcName, File dstFile) throws IOException { + InputStream src = new FileInputStream(new File(srcName)); + OutputStream dst = new FileOutputStream(dstFile); + byte[] buf = new byte[1024]; + int len; + while ((len = src.read(buf)) > 0) { + dst.write(buf, 0, len); + } + src.close(); + dst.close(); + } +} diff --git a/container-core/src/main/java/com/yahoo/container/core/slobrok/SlobrokConfigurator.java b/container-core/src/main/java/com/yahoo/container/core/slobrok/SlobrokConfigurator.java new file mode 100644 index 00000000000..9472fa07bb5 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/core/slobrok/SlobrokConfigurator.java @@ -0,0 +1,26 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.core.slobrok; + +import com.yahoo.cloud.config.SlobroksConfig; +import com.yahoo.cloud.config.SlobroksConfig.Slobrok; +import com.yahoo.container.Container; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Configures which slobrok nodes the container should register with. + * @author Tony Vaagenes + */ +public class SlobrokConfigurator { + public SlobrokConfigurator(SlobroksConfig config) { + Container.get().getRpcAdaptor().registerInSlobrok( + connectionSpecs(config.slobrok())); + } + + private static List<String> connectionSpecs(List<Slobrok> slobroks) { + return slobroks.stream(). + map(Slobrok::connectionspec). + collect(Collectors.toList()); + } +} diff --git a/container-core/src/main/java/com/yahoo/container/osgi/AbstractRpcAdaptor.java b/container-core/src/main/java/com/yahoo/container/osgi/AbstractRpcAdaptor.java new file mode 100644 index 00000000000..9486fe367f9 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/osgi/AbstractRpcAdaptor.java @@ -0,0 +1,15 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.osgi; + +import com.yahoo.jrt.Supervisor; + +/** + * Helper class for optional RPC adaptors in the Container. + * + * @author Steinar Knutsen + */ +public abstract class AbstractRpcAdaptor { + + public abstract void bindCommands(Supervisor supervisor); + +} diff --git a/container-core/src/main/java/com/yahoo/container/osgi/ContainerRpcAdaptor.java b/container-core/src/main/java/com/yahoo/container/osgi/ContainerRpcAdaptor.java new file mode 100644 index 00000000000..7db7d4032d5 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/osgi/ContainerRpcAdaptor.java @@ -0,0 +1,129 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.osgi; + +import com.yahoo.jrt.Acceptor; +import com.yahoo.jrt.ErrorCode; +import com.yahoo.jrt.ListenFailedException; +import com.yahoo.jrt.Method; +import com.yahoo.jrt.Request; +import com.yahoo.jrt.Spec; +import com.yahoo.jrt.StringValue; +import com.yahoo.jrt.Supervisor; +import com.yahoo.jrt.Transport; +import com.yahoo.jrt.slobrok.api.Register; +import com.yahoo.jrt.slobrok.api.SlobrokList; +import com.yahoo.net.HostName; +import com.yahoo.log.LogLevel; +import com.yahoo.osgi.Osgi; +import com.yahoo.yolean.Exceptions; +import org.osgi.framework.Bundle; + +import java.util.List; +import java.util.Optional; +import java.util.logging.Logger; + +/** + * An rpc adaptor to container Osgi commands. + * + * @author bratseth + */ +public class ContainerRpcAdaptor extends AbstractRpcAdaptor { + + private static final Logger log = Logger.getLogger(ContainerRpcAdaptor.class.getName()); + + private Acceptor acceptor; + private final Supervisor supervisor; + + private final Osgi osgi; + private final String hostname; + + private Optional<String> slobrokId = Optional.empty(); + private Optional<Register> slobrokRegistrator = Optional.empty(); + + public ContainerRpcAdaptor(Osgi osgi) { + this.osgi = osgi; + this.supervisor = new Supervisor(new Transport()); + this.hostname = HostName.getLocalhost(); + + bindCommands(supervisor); + } + + public void list(Request request) { + try { + StringBuilder buffer=new StringBuilder("Installed bundles:"); + for (Bundle bundle : osgi.getBundles()) { + if (bundle.getSymbolicName().equals("system.bundle")) continue; + buffer.append("\n"); + buffer.append(bundle.getSymbolicName()); + buffer.append(" ("); + buffer.append(bundle.getLocation()); + buffer.append(")"); + } + request.returnValues().add(new StringValue(buffer.toString())); + } + catch (Exception e) { + request.setError(ErrorCode.METHOD_FAILED,Exceptions.toMessageString(e)); + } + } + + public void bindCommands(Supervisor supervisor) { + supervisor.addMethod(new Method("list","","s",this,"list")); + } + + public synchronized void listen(int port) { + Spec spec = new Spec(port); + try { + acceptor = supervisor.listen(spec); + log.log(LogLevel.DEBUG, "Added new rpc server listening at" + " port '" + port + "'."); + } catch (ListenFailedException e) { + throw new RuntimeException("Could not create rpc server listening on " + spec, e); + } + } + + public synchronized void setSlobrokId(String slobrokId) { + this.slobrokId = Optional.of(slobrokId); + } + + public synchronized void registerInSlobrok(List<String> slobrokConnectionSpecs) { + shutdownSlobrokRegistrator(); + + if (slobrokConnectionSpecs.isEmpty()) { + return; + } + + if (!slobrokId.isPresent()) { + throw new AssertionError("Slobrok id must be set first"); + } + + SlobrokList slobrokList = new SlobrokList(); + slobrokList.setup(slobrokConnectionSpecs.stream().toArray(String[]::new)); + + Spec mySpec = new Spec(hostname, acceptor.port()); + + Register register = new Register(supervisor, slobrokList, mySpec); + register.registerName(slobrokId.get()); + slobrokRegistrator = Optional.of(register); + + log.log(LogLevel.INFO, "Registered name '" + slobrokId.get() + "' at " + mySpec + " with: " + slobrokList); + } + + private synchronized void shutdownSlobrokRegistrator() { + slobrokRegistrator.ifPresent(Register::shutdown); + slobrokRegistrator = Optional.empty(); + } + + public synchronized void shutdown() { + shutdownSlobrokRegistrator(); + + if (acceptor != null) { + acceptor.shutdown().join(); + } + supervisor.transport().shutdown().join(); + } + + + public synchronized void bindRpcAdaptor(AbstractRpcAdaptor adaptor) { + adaptor.bindCommands(supervisor); + } + +} diff --git a/container-core/src/main/java/com/yahoo/container/osgi/package-info.java b/container-core/src/main/java/com/yahoo/container/osgi/package-info.java new file mode 100644 index 00000000000..0768489a767 --- /dev/null +++ b/container-core/src/main/java/com/yahoo/container/osgi/package-info.java @@ -0,0 +1,5 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +@ExportPackage +package com.yahoo.container.osgi; + +import com.yahoo.osgi.annotation.ExportPackage; diff --git a/container-core/src/main/java/com/yahoo/osgi/OsgiImpl.java b/container-core/src/main/java/com/yahoo/osgi/OsgiImpl.java index 2e37a278387..d9ccd5c590f 100644 --- a/container-core/src/main/java/com/yahoo/osgi/OsgiImpl.java +++ b/container-core/src/main/java/com/yahoo/osgi/OsgiImpl.java @@ -16,6 +16,8 @@ import java.util.logging.Logger; */ public class OsgiImpl implements Osgi { + private static final Logger log = Logger.getLogger(OsgiImpl.class.getName()); + private final OsgiFramework jdiscOsgi; public OsgiImpl(OsgiFramework jdiscOsgi) { diff --git a/container-di/src/main/java/com/yahoo/container/di/Container.java b/container-di/src/main/java/com/yahoo/container/di/Container.java index 1b02961082f..d3d635eb522 100644 --- a/container-di/src/main/java/com/yahoo/container/di/Container.java +++ b/container-di/src/main/java/com/yahoo/container/di/Container.java @@ -35,7 +35,6 @@ import static com.yahoo.log.LogLevel.DEBUG; * @author ollivir */ public class Container { - private static final Logger log = Logger.getLogger(Container.class.getName()); private final SubscriberFactory subscriberFactory; @@ -264,5 +263,4 @@ public class Container { public static BundleInstantiationSpecification bundleInstatiationSpecification(ComponentsConfig.Components config) { return BundleInstantiationSpecification.getFromStrings(config.id(), config.classId(), config.bundle()); } - } diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java b/container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java index 27defe08fa8..69a525a2c54 100644 --- a/container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/ConfiguredApplication.java @@ -11,6 +11,7 @@ import com.yahoo.config.ConfigInstance; import com.yahoo.config.subscription.ConfigInterruptedException; import com.yahoo.container.Container; import com.yahoo.container.QrConfig; +import com.yahoo.container.Server; import com.yahoo.container.core.ChainsConfig; import com.yahoo.container.core.config.HandlersConfigurerDi; import com.yahoo.container.di.config.Subscriber; @@ -133,11 +134,10 @@ public final class ConfiguredApplication implements Application { portWatcher.start(); } - @SuppressWarnings("deprecation") + private static void hackToInitializeServer(QrConfig config) { try { - Container.get().setupFileAcquirer(config.filedistributor()); - com.yahoo.container.Server.get().initialize(config); + Server.get().initialize(config); } catch (Exception e) { log.log(LogLevel.ERROR, "Caught exception when initializing server. Exiting.", e); Runtime.getRuntime().halt(1); diff --git a/container-search/src/main/java/com/yahoo/prelude/templates/TiledTemplateSet.java b/container-search/src/main/java/com/yahoo/prelude/templates/TiledTemplateSet.java index 2fa6e14019e..115e9cd44a1 100644 --- a/container-search/src/main/java/com/yahoo/prelude/templates/TiledTemplateSet.java +++ b/container-search/src/main/java/com/yahoo/prelude/templates/TiledTemplateSet.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.prelude.templates; +import com.yahoo.container.ConfigHack; import com.yahoo.prelude.hitfield.HitField; import com.yahoo.prelude.hitfield.JSONString; import com.yahoo.prelude.hitfield.XMLString; @@ -80,7 +81,7 @@ public class TiledTemplateSet extends DefaultTemplateSet { private FormattingOptions hitOptions; public TiledTemplateSet() { - this("tiled"); + this(ConfigHack.TILED_TEMPLATE); } public TiledTemplateSet(String templateName) { diff --git a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java index 699e8619cd0..e9eb90378f4 100644 --- a/container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/searchchain/config/test/SearchChainConfigurerTestCase.java @@ -3,7 +3,7 @@ package com.yahoo.search.searchchain.config.test; import com.yahoo.config.search.IntConfig; import com.yahoo.config.search.StringConfig; -import com.yahoo.container.core.config.HandlersConfigurerDi; +import com.yahoo.container.config.testutil.TestUtil; import com.yahoo.container.core.config.testutil.HandlersConfigurerTestWrapper; import com.yahoo.search.Query; import com.yahoo.search.Result; @@ -19,8 +19,6 @@ import org.junit.Test; import java.io.*; import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; @@ -52,7 +50,7 @@ public class SearchChainConfigurerTestCase { } @AfterClass - public static void removeDefaultComponentsConfigs() { + public static void removeDefaultComponentsConfigs() throws IOException { new File(testDir + "components.cfg").delete(); } @@ -62,7 +60,7 @@ public class SearchChainConfigurerTestCase { } @Test - public synchronized void testConfiguration() { + public synchronized void testConfiguration() throws Exception { HandlersConfigurerTestWrapper configurer = new HandlersConfigurerTestWrapper("dir:" + testDir); SearchChain simple=getSearchChainRegistryFrom(configurer).getComponent("simple"); @@ -184,7 +182,7 @@ public class SearchChainConfigurerTestCase { * and that a searcher that has been removed from the configuration is not in the new registry. */ @Test - public void testChainsConfigUpdate() throws IOException { + public void testChainsConfigUpdate() throws IOException, InterruptedException { File cfgDir = getCfgDir(); copyFile(testDir + "handlers.cfg", cfgDir + "/handlers.cfg"); copyFile(testDir + "qr-search.cfg", cfgDir + "/qr-search.cfg"); @@ -268,7 +266,7 @@ public class SearchChainConfigurerTestCase { //// Helper methods - public static void printFile(File f, String content) throws IOException { + public static void printFile(File f, String content) throws IOException, InterruptedException { OutputStream out = new FileOutputStream(f); out.write(content.getBytes()); out.close(); @@ -302,58 +300,8 @@ public class SearchChainConfigurerTestCase { * Also adds the default SearchHandler. */ public static void createComponentsConfig(String chainsFile, String handlersFile, String componentsFile) throws IOException { - createComponentsConfig(handlersFile, componentsFile, "handler", false); - createComponentsConfig(chainsFile, componentsFile, "components", true); - } - - /** - * Copies the component ids from another config, e.g. 'handlers' to a 'components' array in a new components file, - * to avoid a manually written 'components' file for tests where the bundle spec is given by the component id. - * @param configFile Full path to the original config file, e.g. 'handlers' - * @param componentsFile Full path to the new 'components' file - * @param componentType The type of component, e.g. 'handler' - * @param append 'true' will append to an already existing 'componentsFile' - */ - public static void createComponentsConfig(String configFile, - String componentsFile, - String componentType, - boolean append) throws IOException { - StringBuilder buf = new StringBuilder(); - String line; - int i = 0; - if (append) { - Pattern p = Pattern.compile("^[a-z]+" + "\\[\\d+\\]\\.id (.+)"); - BufferedReader reader = new BufferedReader(new InputStreamReader( - new FileInputStream(new File(componentsFile)), "UTF-8")); - while ((line = reader.readLine()) != null) { - Matcher m = p.matcher(line); - if (m.matches() && !m.group(1).equals(HandlersConfigurerDi.RegistriesHack.class.getName())) { - buf.append("components[").append(i).append("].id ").append(m.group(1)).append("\n"); - i++; - } - } - reader.close(); - } - BufferedReader reader = new BufferedReader(new InputStreamReader( - new FileInputStream(new File(configFile)), "UTF-8")); - Pattern component = Pattern.compile("^" + componentType + "\\[\\d+\\]\\.id (.+)"); - while ((line = reader.readLine()) != null) { - Matcher m = component.matcher(line); - if (m.matches()) { - buf.append("components[").append(i).append("].id ").append(m.group(1)).append("\n"); - i++; - } - } - buf.append("components[").append(i).append("].id "). - append(HandlersConfigurerDi.RegistriesHack.class.getName()).append("\n"); - i++; - reader.close(); - buf.insert(0, "components["+i+"]\n"); - - Writer writer = new OutputStreamWriter(new FileOutputStream(new File(componentsFile)), "UTF-8"); - writer.write(buf.toString()); - writer.flush(); - writer.close(); + TestUtil.createComponentsConfig(handlersFile, componentsFile, "handler"); + TestUtil.createComponentsConfig(chainsFile, componentsFile, "components", true); } } |