diff options
author | Bjørn Meland <bjormel@users.noreply.github.com> | 2017-10-05 11:59:57 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-05 11:59:57 +0200 |
commit | cf86d459aa9d3d136fd7b4d5de91429165b9a8c3 (patch) | |
tree | 0878f31d717e79465523ec138d60796683543e54 | |
parent | 7de6a28f74be7515a8fabe1a778b9c0728725b9e (diff) | |
parent | c206adf7dfde86c32653937a43e0ef08de67ed29 (diff) |
Merge pull request #3654 from vespa-engine/arnej/cpp-logforwarder-start-2
Arnej/cpp logforwarder start 2
23 files changed, 430 insertions, 8 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f7752d5915e..db6bbde423a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,6 +71,7 @@ add_subdirectory(jrt_test) add_subdirectory(juniper) add_subdirectory(logd) add_subdirectory(logserver) +add_subdirectory(logforwarder) add_subdirectory(lowercasing_test) add_subdirectory(memfilepersistence) add_subdirectory(messagebus) diff --git a/config-model/pom.xml b/config-model/pom.xml index c1c08e6e702..4e79da3279d 100644 --- a/config-model/pom.xml +++ b/config-model/pom.xml @@ -279,7 +279,7 @@ <artifactId>filedistribution</artifactId> <version>${project.version}</version> </dependency> - <dependency> + <dependency> <groupId>com.yahoo.vespa</groupId> <artifactId>searchsummary</artifactId> <version>${project.version}</version> diff --git a/config-model/src/main/java/com/yahoo/vespa/model/admin/LogForwarder.java b/config-model/src/main/java/com/yahoo/vespa/model/admin/LogForwarder.java new file mode 100644 index 00000000000..46f5807b350 --- /dev/null +++ b/config-model/src/main/java/com/yahoo/vespa/model/admin/LogForwarder.java @@ -0,0 +1,64 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.model.admin; + +import com.yahoo.cloud.config.LogforwarderConfig; +import com.yahoo.config.model.producer.AbstractConfigProducer; +import com.yahoo.vespa.model.AbstractService; + +import java.util.ArrayList; +import java.util.List; + +public class LogForwarder extends AbstractService implements LogforwarderConfig.Producer { + + public static class Config { + public final String deploymentServer; + public final String clientName; + + private Config(String ds, String cn) { + this.deploymentServer = ds; + this.clientName = cn; + } + public Config withDeploymentServer(String ds) { + return new Config(ds, clientName); + } + public Config withClientName(String cn) { + return new Config(deploymentServer, cn); + } + } + + private final Config config; + + /** + * Creates a new LogForwarder instance. + */ + // TODO: Use proper types? + public LogForwarder(AbstractConfigProducer parent, int index, Config config) { + super(parent, "logforwarder." + index); + this.config = config; + setProp("clustertype", "hosts"); + setProp("clustername", "admin"); + } + + public static Config cfg() { + return new Config(null, null); + } + + /** + * LogForwarder does not need any ports. + * + * @return The number of ports reserved by the LogForwarder + */ + public int getPortCount() { return 0; } + + /** + * @return The command used to start LogForwarder + */ + public String getStartupCommand() { return "exec $ROOT/bin/vespa-logforwarder-start -c " + getConfigId(); } + + @Override + public void getConfig(LogforwarderConfig.Builder builder) { + builder.deploymentServer(config.deploymentServer); + builder.clientName(config.clientName); + } + +} diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java index 908481aad63..3049112ac0a 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminBuilderBase.java @@ -111,4 +111,21 @@ public abstract class DomAdminBuilderBase extends VespaDomBuilder.DomConfigProdu return minutes; } + void addLogForwarders(ModelElement logForwardingElement, Admin admin) { + if (logForwardingElement == null) return; + + int i = 0; + for (ModelElement e : logForwardingElement.getChildren("splunk")) { + LogForwarder.Config cfg = LogForwarder.cfg() + .withDeploymentServer(e.getStringAttribute("deployment-server")) + .withClientName(e.getStringAttribute("client-name")); + for (HostResource host : admin.getHostSystem().getHosts()) { + LogForwarder logForwarder = new LogForwarder(admin, i, cfg); + logForwarder.setHostResource(host); + logForwarder.initService(); + i++; + } + } + } + } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java index 180cf4eadec..dd1d4e36255 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/DomAdminV2Builder.java @@ -49,6 +49,9 @@ public class DomAdminV2Builder extends DomAdminBuilderBase { admin.addSlobroks(getSlobroks(admin, XML.getChild(adminE, "slobroks"))); if ( ! admin.multitenant()) admin.setClusterControllers(addConfiguredClusterControllers(admin, adminE)); + + ModelElement adminElement = new ModelElement(adminE); + addLogForwarders(adminElement.getChild("logforwarding"), admin); } private List<Configserver> parseConfigservers(Admin admin, Element adminE) { 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 5e22ba3961f..cb8ec205395 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 @@ -51,6 +51,8 @@ public class DomAdminV4Builder extends DomAdminBuilderBase { assignSlobroks(requestedSlobroks.orElse(NodesSpecification.nonDedicated(3, version)), admin); assignLogserver(requestedLogservers.orElse(NodesSpecification.nonDedicated(1, version)), admin); + + addLogForwarders(adminElement.getChild("logforwarding"), admin); } private void assignSlobroks(NodesSpecification nodesSpecification, Admin admin) { diff --git a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/ModelElement.java b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/ModelElement.java index c5bc275a9e1..1fc70e343f3 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/ModelElement.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/builder/xml/dom/ModelElement.java @@ -11,7 +11,7 @@ import java.util.List; import java.util.StringTokenizer; /** - * A w3c Element wrapper whith a better API. + * A w3c Element wrapper with a better API. * * Author unknown. */ @@ -46,6 +46,18 @@ public class ModelElement { return null; } + /** + * If not found, return empty list + */ + public List<ModelElement> getChildren(String name) { + List<Element> e = XML.getChildren(xml, name); + + List<ModelElement> list = new ArrayList<>(); + e.forEach(element -> list.add(new ModelElement(element))); + + return list; + } + public ModelElement getChildByPath(String path) { StringTokenizer tokenizer = new StringTokenizer(path, "."); ModelElement curElem = this; diff --git a/config-model/src/main/resources/schema/admin.rnc b/config-model/src/main/resources/schema/admin.rnc index 26705784a34..3ab02af3efd 100644 --- a/config-model/src/main/resources/schema/admin.rnc +++ b/config-model/src/main/resources/schema/admin.rnc @@ -13,7 +13,8 @@ AdminV2 = AdminSlobroks? & (LegacyAdminMonitoring | AdminMonitoring)? & (LegacyMetricConsumers | Metrics)? & - ClusterControllers? + ClusterControllers? & + LogForwarding? } AdminV3 = @@ -32,7 +33,8 @@ AdminV4 = AdminV4LogServers? & GenericConfig* & (LegacyAdminMonitoring | AdminMonitoring)? & - (LegacyMetricConsumers | Metrics)? + (LegacyMetricConsumers | Metrics)? & + LogForwarding? } AdminV4Slobroks = @@ -112,3 +114,10 @@ ClusterControllers = element cluster-controllers { service.attlist }+ } + +LogForwarding = element logforwarding { + element splunk { + attribute deployment-server { xsd:string } & + attribute client-name { xsd:string } + } +} 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 2dfef135425..b5375ccbce4 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 @@ -8,6 +8,7 @@ import com.yahoo.cloud.config.SentinelConfig; import com.yahoo.config.model.ApplicationConfigProducerRoot; import com.yahoo.config.model.deploy.DeployProperties; import com.yahoo.config.model.deploy.DeployState; +import com.yahoo.config.model.test.MockApplicationPackage; import com.yahoo.config.model.test.TestDriver; import com.yahoo.config.model.test.TestRoot; import com.yahoo.config.provision.ApplicationId; @@ -22,9 +23,12 @@ import com.yahoo.vespa.model.container.ContainerCluster; import com.yahoo.vespa.model.container.component.Component; import com.yahoo.vespa.model.container.component.StatisticsComponent; import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithFilePkg; +import com.yahoo.vespa.model.test.utils.VespaModelCreatorWithMockPkg; +import org.junit.Ignore; import org.junit.Test; import java.util.Set; +import java.util.stream.IntStream; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; @@ -246,7 +250,29 @@ public class AdminTestCase { assertEquals(sc.values(0).operations(0).name(), StatisticsConfig.Values.Operations.Name.REGULAR); assertEquals(sc.values(0).operations(0).arguments(0).key(), "limits"); assertEquals(sc.values(0).operations(0).arguments(0).value(), "25,50,100,500"); - } + @Test + public void testLogForwarding() throws Exception { + String hosts = "<hosts>" + + " <host name=\"myhost0\">" + + " <alias>node0</alias>" + + " </host>" + + "</hosts>"; + + String services = "<services>" + + " <admin version='2.0'>" + + " <adminserver hostalias='node0' />" + + " <logforwarding>" + + " <splunk deployment-server='foo:123' client-name='foocli'/>" + + " </logforwarding>" + + " </admin>" + + "</services>"; + + VespaModel vespaModel = new VespaModelCreatorWithMockPkg(hosts, services).create(); + + Set<String> configIds = vespaModel.getConfigIds(); + // 1 logforwarder on each host + assertTrue(configIds.toString(), configIds.contains("admin/logforwarder.0")); + } } diff --git a/config-model/src/test/java/com/yahoo/vespa/model/admin/DedicatedAdminV4Test.java b/config-model/src/test/java/com/yahoo/vespa/model/admin/DedicatedAdminV4Test.java index 5b5094a9c43..e3f773a64c2 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/admin/DedicatedAdminV4Test.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/admin/DedicatedAdminV4Test.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.vespa.model.admin; +import com.yahoo.cloud.config.LogforwarderConfig; import com.yahoo.cloud.config.SentinelConfig; import com.yahoo.config.model.NullConfigModelRegistry; import com.yahoo.config.application.api.ApplicationPackage; @@ -16,13 +17,13 @@ import org.junit.Test; import org.xml.sax.SAXException; import java.io.IOException; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.IntStream; import static com.yahoo.vespa.model.admin.monitoring.DefaultMetricsConsumer.VESPA_CONSUMER_ID; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.*; /** * @author lulf @@ -141,6 +142,53 @@ public class DedicatedAdminV4Test { "slobrok", "logd", "filedistributorservice", "qrserver"); } + @Test + public void testLogForwarding() throws IOException, SAXException { + String services = "<services>" + + " <admin version='4.0'>" + + " <slobroks><nodes count='2' dedicated='true'/></slobroks>" + + " <logservers><nodes count='1' dedicated='true'/></logservers>" + + " <logforwarding>" + + " <splunk deployment-server='foo:123' client-name='foocli'/>" + + " </logforwarding>" + + " </admin>" + + "</services>"; + + VespaModel model = createModel(hosts, services); + assertEquals(3, model.getHosts().size()); + + assertHostContainsServices(model, "hosts/myhost0", + "filedistributorservice", "logd", "logforwarder", "slobrok"); + assertHostContainsServices(model, "hosts/myhost1", + "filedistributorservice", "logd", "logforwarder", "slobrok"); + assertHostContainsServices(model, "hosts/myhost2", + "filedistributorservice", "logd", "logforwarder", "logserver"); + + Set<String> configIds = model.getConfigIds(); + // 1 logforwarder on each host + IntStream.of(0, 1, 2).forEach(i -> assertTrue(configIds.toString(), configIds.contains("admin/logforwarder." + i))); + + // First forwarder + { + LogforwarderConfig.Builder builder = new LogforwarderConfig.Builder(); + model.getConfig(builder, "admin/logforwarder.0"); + LogforwarderConfig config = new LogforwarderConfig(builder); + + assertEquals("foo:123", config.deploymentServer()); + assertEquals("foocli", config.clientName()); + } + + // Other host's forwarder + { + LogforwarderConfig.Builder builder = new LogforwarderConfig.Builder(); + model.getConfig(builder, "admin/logforwarder.2"); + LogforwarderConfig config = new LogforwarderConfig(builder); + + assertEquals("foo:123", config.deploymentServer()); + assertEquals("foocli", config.clientName()); + } + } + private Set<String> serviceNames(VespaModel model, String hostname) { SentinelConfig config = model.getConfig(SentinelConfig.class, hostname); return config.service().stream().map(SentinelConfig.Service::name).collect(Collectors.toSet()); diff --git a/config-model/src/test/schema-test-files/services.xml b/config-model/src/test/schema-test-files/services.xml index 322f4ed8356..4b6eb12208c 100644 --- a/config-model/src/test/schema-test-files/services.xml +++ b/config-model/src/test/schema-test-files/services.xml @@ -26,6 +26,9 @@ <metric-set id="my-set2" /> </consumer> </metrics> + <logforwarding> + <splunk deployment-server="foo:8989" client-name="foobar"/> + </logforwarding> </admin> <config name="bar"> diff --git a/configdefinitions/src/vespa/CMakeLists.txt b/configdefinitions/src/vespa/CMakeLists.txt index 4ed4dc06d41..9297383c53f 100644 --- a/configdefinitions/src/vespa/CMakeLists.txt +++ b/configdefinitions/src/vespa/CMakeLists.txt @@ -28,6 +28,8 @@ vespa_generate_config(configdefinitions lb-services.def) install_config_definition(lb-services.def cloud.config.lb-services.def) vespa_generate_config(configdefinitions load-type.def) install_config_definition(load-type.def vespa.config.content.load-type.def) +vespa_generate_config(configdefinitions logforwarder.def) +install_config_definition(logforwarder.def cloud.config.logforwarder.def) vespa_generate_config(configdefinitions messagetyperouteselectorpolicy.def) install_config_definition(messagetyperouteselectorpolicy.def vespa.config.content.messagetyperouteselectorpolicy.def) vespa_generate_config(configdefinitions model.def) diff --git a/configdefinitions/src/vespa/logforwarder.def b/configdefinitions/src/vespa/logforwarder.def new file mode 100644 index 00000000000..205e8ad3b8c --- /dev/null +++ b/configdefinitions/src/vespa/logforwarder.def @@ -0,0 +1,6 @@ +namespace=cloud.config + +# only splunk type config for now + +deploymentServer string default="" +clientName string default="" diff --git a/logforwarder/CMakeLists.txt b/logforwarder/CMakeLists.txt new file mode 100644 index 00000000000..bd1e480a074 --- /dev/null +++ b/logforwarder/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_define_module( + DEPENDS + vespalog + vespalib + config_cloudconfig + + APPS + src/apps/vespa-logforwarder-start +) diff --git a/logforwarder/OWNERS b/logforwarder/OWNERS new file mode 100644 index 00000000000..67cd2820bb8 --- /dev/null +++ b/logforwarder/OWNERS @@ -0,0 +1 @@ +arnej27959 diff --git a/logforwarder/README b/logforwarder/README new file mode 100644 index 00000000000..30f5992157b --- /dev/null +++ b/logforwarder/README @@ -0,0 +1,5 @@ +Utility for log forwarding management + +currently this only supports "splunk", and +just saves splunk config in a file using the +appropriate format. diff --git a/logforwarder/src/apps/vespa-logforwarder-start/.gitignore b/logforwarder/src/apps/vespa-logforwarder-start/.gitignore new file mode 100644 index 00000000000..64d78991a4c --- /dev/null +++ b/logforwarder/src/apps/vespa-logforwarder-start/.gitignore @@ -0,0 +1,3 @@ +vespa-logforwarder-start +config-logforwarder.cpp +config-logforwarder.h diff --git a/logforwarder/src/apps/vespa-logforwarder-start/CMakeLists.txt b/logforwarder/src/apps/vespa-logforwarder-start/CMakeLists.txt new file mode 100644 index 00000000000..f26edd8eee8 --- /dev/null +++ b/logforwarder/src/apps/vespa-logforwarder-start/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(logforwarder-start_app + SOURCES + main.cpp + cf-handler.cpp + sig-catch.cpp + OUTPUT_NAME vespa-logforwarder-start + INSTALL bin + DEPENDS + config_cloudconfig + configdefinitions +) diff --git a/logforwarder/src/apps/vespa-logforwarder-start/cf-handler.cpp b/logforwarder/src/apps/vespa-logforwarder-start/cf-handler.cpp new file mode 100644 index 00000000000..e34a83030e8 --- /dev/null +++ b/logforwarder/src/apps/vespa-logforwarder-start/cf-handler.cpp @@ -0,0 +1,91 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "cf-handler.h" +#include <dirent.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <vespa/defaults.h> +#include <vespa/config/common/configsystem.h> +#include <vespa/config/common/exceptions.h> + +#include <vespa/log/log.h> +LOG_SETUP(".cf-handler"); + +CfHandler::CfHandler() : _subscriber() {} + +CfHandler::~CfHandler() +{ +} + +void +CfHandler::subscribe(const std::string & configId, uint64_t timeoutMS) +{ + _handle = _subscriber.subscribe<LogforwarderConfig>(configId, timeoutMS); +} + +namespace { +std::string +cfFilePath() { + std::string path = vespa::Defaults::underVespaHome("var/db/vespa/splunk"); + DIR *dp = opendir(path.c_str()); + if (dp == NULL) { + if (errno != ENOENT || mkdir(path.c_str(), 0755) != 0) { + perror(path.c_str()); + } + } else { + closedir(dp); + } + path += "/deploymentclient.conf"; + return path; +} +} + +void +CfHandler::doConfigure() +{ + std::unique_ptr<LogforwarderConfig> cfg(_handle->getConfig()); + const LogforwarderConfig& config(*cfg); + + std::string path = cfFilePath(); + std::string tmpPath = path + ".new"; + FILE *fp = fopen(tmpPath.c_str(), "w"); + if (fp == NULL) return; + + fprintf(fp, "[deployment-client]\n"); + fprintf(fp, "clientName = %s\n", config.clientName.c_str()); + fprintf(fp, "\n"); + fprintf(fp, "[target-broker:deploymentServer]\n"); + fprintf(fp, "targetUri = %s\n", config.deploymentServer.c_str()); + + fclose(fp); + rename(tmpPath.c_str(), path.c_str()); +} + +void +CfHandler::check() +{ + if (_subscriber.nextConfig(0)) { + doConfigure(); + } +} + +constexpr uint64_t CONFIG_TIMEOUT_MS = 30 * 1000; + +void +CfHandler::start(const char *configId) +{ + LOG(debug, "Reading configuration with id '%s'", configId); + try { + subscribe(configId, CONFIG_TIMEOUT_MS); + } catch (config::ConfigTimeoutException & ex) { + LOG(warning, "Timout getting config, please check your setup. Will exit and restart: %s", ex.getMessage().c_str()); + exit(EXIT_FAILURE); + } catch (config::InvalidConfigException& ex) { + LOG(error, "Fatal: Invalid configuration, please check your setup: %s", ex.getMessage().c_str()); + exit(EXIT_FAILURE); + } catch (config::ConfigRuntimeException& ex) { + LOG(error, "Fatal: Could not get config, please check your setup: %s", ex.getMessage().c_str()); + exit(EXIT_FAILURE); + } +} diff --git a/logforwarder/src/apps/vespa-logforwarder-start/cf-handler.h b/logforwarder/src/apps/vespa-logforwarder-start/cf-handler.h new file mode 100644 index 00000000000..99f0a6cd6d5 --- /dev/null +++ b/logforwarder/src/apps/vespa-logforwarder-start/cf-handler.h @@ -0,0 +1,20 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#pragma once + +#include <vespa/config/config.h> +#include <vespa/config-logforwarder.h> + +using cloud::config::LogforwarderConfig; + +class CfHandler { +private: + config::ConfigSubscriber _subscriber; + config::ConfigHandle<LogforwarderConfig>::UP _handle; + void subscribe(const std::string & configId, uint64_t timeoutMS); + void doConfigure(); +public: + CfHandler(); + virtual ~CfHandler(); + void start(const char *configId); + void check(); +}; diff --git a/logforwarder/src/apps/vespa-logforwarder-start/main.cpp b/logforwarder/src/apps/vespa-logforwarder-start/main.cpp new file mode 100644 index 00000000000..e06d3dd6d8d --- /dev/null +++ b/logforwarder/src/apps/vespa-logforwarder-start/main.cpp @@ -0,0 +1,38 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include <csignal> +#include <unistd.h> + +#include <vespa/log/log.h> +LOG_SETUP("vespa-logforwarder-start"); + +#include "cf-handler.h" +#include "sig-catch.h" + +class Wrapper { + const char *_configId; +public: + Wrapper(const char *cfid) : _configId(cfid) {} + void run() { + SigCatch catcher; + CfHandler handler; + handler.start(_configId); + while (! catcher.receivedStopSignal()) { + handler.check(); + usleep(12500); // Avoid busy looping; + } + } +}; + +int +main(int argc, char** argv) +{ + int c = getopt(argc, argv, "c:"); + if (c != 'c') { + LOG(error, "Usage: %s -c <config-id>", argv[0]); + exit(EXIT_FAILURE); + } + Wrapper wrapper(optarg); + wrapper.run(); + return 0; +} diff --git a/logforwarder/src/apps/vespa-logforwarder-start/sig-catch.cpp b/logforwarder/src/apps/vespa-logforwarder-start/sig-catch.cpp new file mode 100644 index 00000000000..b10275d515e --- /dev/null +++ b/logforwarder/src/apps/vespa-logforwarder-start/sig-catch.cpp @@ -0,0 +1,41 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "sig-catch.h" +#include <csignal> +#include <unistd.h> +#include <string.h> + +static int sigPermanent(int sig, void(*handler)(int)); +static void setStopFlag(int sig); +sig_atomic_t stop = 0; + +SigCatch::SigCatch() +{ + sigPermanent(SIGPIPE, SIG_IGN); + sigPermanent(SIGTERM, setStopFlag); + sigPermanent(SIGINT, setStopFlag); +} + +bool +SigCatch::receivedStopSignal() { + return stop != 0; +} + +static void +setStopFlag(int sig) +{ + (void)sig; + stop = 1; +} + +static int +sigPermanent(int sig, void(*handler)(int)) +{ + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; // no SA_RESTART! + sa.sa_handler = handler; + return sigaction(sig, &sa, nullptr); +} diff --git a/logforwarder/src/apps/vespa-logforwarder-start/sig-catch.h b/logforwarder/src/apps/vespa-logforwarder-start/sig-catch.h new file mode 100644 index 00000000000..905f37103ec --- /dev/null +++ b/logforwarder/src/apps/vespa-logforwarder-start/sig-catch.h @@ -0,0 +1,8 @@ +// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +class SigCatch +{ +public: + SigCatch(); + bool receivedStopSignal(); +}; |