com.linkedin.databus.client.generic.SimpleFileLoggingConsumer.java Source code

Java tutorial

Introduction

Here is the source code for com.linkedin.databus.client.generic.SimpleFileLoggingConsumer.java

Source

package com.linkedin.databus.client.generic;
/*
 *
 * Copyright 2013 LinkedIn Corp. All rights reserved
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.log4j.Logger;

import com.linkedin.databus.client.DatabusHttpClientImpl;
import com.linkedin.databus.client.pub.DatabusRegistration;
import com.linkedin.databus.client.pub.ServerInfo.ServerInfoBuilder;
import com.linkedin.databus.client.registration.DatabusV2RegistrationImpl;
import com.linkedin.databus.core.util.ConfigLoader;
import com.linkedin.databus.core.util.InvalidConfigException;
import com.linkedin.databus2.core.container.netty.ServerContainer;
import com.linkedin.databus2.core.container.request.ContainerOperationProcessor;
import com.linkedin.databus2.core.container.request.ProcessorRegistrationConflictException;
import com.linkedin.databus2.core.filter.DbusKeyCompositeFilterConfig;

/**
 * Base class for setting up consumer, process arguments
 * @author dzhang
 *
 */
public class SimpleFileLoggingConsumer {

    public static final String MODULE = SimpleFileLoggingConsumer.class.getName();
    public static final Logger LOG = Logger.getLogger(MODULE);

    public static final String RELAY_HOST_OPT_NAME = "relay_host";
    public static final String RELAY_PORT_OPT_NAME = "relay_port";
    public static final String EVENT_DUMP_FILE_OPT_NAME = "f";
    public static final String VALUE_DUMP_FILE_OPT_NAME = "value_file";
    public static final String HTTP_PORT_OPT_NAME = "http_port";
    public static final String JMX_SERVICE_PORT_OPT_NAME = "jmx_service_port";
    public static final String CHECKPOINT_DIR = "checkpoint_dir";
    public static final String BOOTSTRAP_HOST_OPT_NAME = "bootstrap_host";
    public static final String BOOTSTRAP_PORT_OPT_NAME = "bootstrap_port";
    public static final String EVENT_PATTERN_OPT_NAME = "event_pattern";
    public static final String FILTER_CONF_FILE_OPT_NAME = "filter_conf_file";
    public static final String SERVER_SIDE_FILTER_PREFIX = "serversidefilter.";
    public static final String SOURCES_OPT_NAME = "sources";

    private static String _eventDumpFile = null;
    private static String _valueDumpFile = null;
    private static String _relayHost = null;
    private static String _relayPort = null;
    private static String _bootstrapHost = null;
    private static String _bootstrapPort = null;
    private static String _httpPort = null;
    private static String _jmxServicePort = null;
    private static String _checkpointFileRootDir = null;
    private static String _eventPattern = null;
    private static boolean _enableBootStrap = false;
    private static String _filterConfFile = null;
    private static String[] _sources = null;

    protected static Options constructCommandLineOptions() {
        Options options = new Options();
        options.addOption(RELAY_HOST_OPT_NAME, true, "Relay Host Name");
        options.addOption(RELAY_PORT_OPT_NAME, true, "Relay Port");
        options.addOption(EVENT_DUMP_FILE_OPT_NAME, true, "File to dump event");
        options.addOption(VALUE_DUMP_FILE_OPT_NAME, true, "File to dump deserilized values");
        options.addOption(HTTP_PORT_OPT_NAME, true, "Consumer http port");
        options.addOption(JMX_SERVICE_PORT_OPT_NAME, true, "Consumer jmx service port");
        options.addOption(CHECKPOINT_DIR, true, "Checkpoint dir");
        options.addOption(BOOTSTRAP_HOST_OPT_NAME, true, "Bootstrap server Name");
        options.addOption(BOOTSTRAP_PORT_OPT_NAME, true, "Bootstrap server Port");
        options.addOption(EVENT_PATTERN_OPT_NAME, true, "Event Pattern Name to Check");
        options.addOption(FILTER_CONF_FILE_OPT_NAME, true, "Server Side Filter Config");
        options.addOption(SOURCES_OPT_NAME, true, "Comma seperated source names");
        return options;
    }

    protected static String[] processLocalArgs(String[] cliArgs) throws IOException, ParseException {
        CommandLineParser cliParser = new GnuParser();
        Options cliOptions = constructCommandLineOptions();

        CommandLine cmd = cliParser.parse(cliOptions, cliArgs, true);
        // Options here has to be up front
        if (cmd.hasOption(RELAY_HOST_OPT_NAME)) {
            _relayHost = cmd.getOptionValue(RELAY_HOST_OPT_NAME);
            LOG.info("Relay Host = " + _relayHost);
        }
        if (cmd.hasOption(RELAY_PORT_OPT_NAME)) {
            _relayPort = cmd.getOptionValue(RELAY_PORT_OPT_NAME);
            LOG.info("Relay Port = " + _relayPort);
        }
        if (cmd.hasOption(EVENT_DUMP_FILE_OPT_NAME)) {
            _eventDumpFile = cmd.getOptionValue(EVENT_DUMP_FILE_OPT_NAME);
            LOG.info("Saving event dump to file: " + _eventDumpFile);
        }
        if (cmd.hasOption(VALUE_DUMP_FILE_OPT_NAME)) {
            _valueDumpFile = cmd.getOptionValue(VALUE_DUMP_FILE_OPT_NAME);
            LOG.info("Saving event value dump to file: " + _valueDumpFile);
        }
        if (cmd.hasOption(HTTP_PORT_OPT_NAME)) {
            _httpPort = cmd.getOptionValue(HTTP_PORT_OPT_NAME);
            LOG.info("Consumer http port =  " + _httpPort);
        }
        if (cmd.hasOption(JMX_SERVICE_PORT_OPT_NAME)) {
            _jmxServicePort = cmd.getOptionValue(JMX_SERVICE_PORT_OPT_NAME);
            LOG.info("Consumer JMX Service port =  " + _jmxServicePort);
        }
        if (cmd.hasOption(CHECKPOINT_DIR)) {
            _checkpointFileRootDir = cmd.getOptionValue(CHECKPOINT_DIR);
            LOG.info("Checkpoint dir =  " + _checkpointFileRootDir);
        }
        if (cmd.hasOption(BOOTSTRAP_HOST_OPT_NAME)) {
            _bootstrapHost = cmd.getOptionValue(BOOTSTRAP_HOST_OPT_NAME);
            LOG.info("Bootstrap Server = " + _bootstrapHost);
        }
        if (cmd.hasOption(BOOTSTRAP_PORT_OPT_NAME)) {
            _bootstrapPort = cmd.getOptionValue(BOOTSTRAP_PORT_OPT_NAME);
            LOG.info("Bootstrap Server Port = " + _bootstrapPort);
        }
        if (cmd.hasOption(EVENT_PATTERN_OPT_NAME)) {
            _eventPattern = cmd.getOptionValue(EVENT_PATTERN_OPT_NAME);
            LOG.info("Event pattern = " + _eventPattern);
        }
        if (_bootstrapHost != null || _bootstrapPort != null) {
            _enableBootStrap = true;
        }

        if (cmd.hasOption(FILTER_CONF_FILE_OPT_NAME)) {
            _filterConfFile = cmd.getOptionValue(FILTER_CONF_FILE_OPT_NAME);
            LOG.info("Server Side Filtering Config File =" + _filterConfFile);
        }

        if (cmd.hasOption(SOURCES_OPT_NAME)) {
            _sources = cmd.getOptionValue(SOURCES_OPT_NAME).split(",");
            LOG.info("Sources to be subscribed are =" + Arrays.toString(_sources));
        }

        // return what left over args
        return cmd.getArgs();
    }

    /**
     * @return the sources to be consumed by the consumer.  All the sources should be co-located in the same Relay EVB.
     */
    protected String[] addSources() {
        return _sources;
    }

    protected DatabusFileLoggingConsumer createTypedConsumer(String valueDumpFile) throws IOException {
        return createTypedConsumer(valueDumpFile, null);
    }

    protected DatabusFileLoggingConsumer createTypedConsumer(String valueDumpFile, String eventDumpFile)
            throws IOException {
        return new DatabusFileLoggingConsumer(valueDumpFile, null, eventDumpFile, false);
    }

    public void mainFunction(String args[]) throws Exception {
        String[] leftOverArgs = processLocalArgs(args);
        Properties startupProps = DatabusHttpClientImpl.processCommandLineArgs(leftOverArgs);
        DatabusHttpClientImpl.Config clientConfigBuilder = new DatabusHttpClientImpl.Config();

        clientConfigBuilder.getContainer().setIdFromName(MODULE + ".localhost");

        if (_enableBootStrap) {
            clientConfigBuilder.getRuntime().getBootstrap().setEnabled(true);
        }
        ConfigLoader<DatabusHttpClientImpl.StaticConfig> configLoader = new ConfigLoader<DatabusHttpClientImpl.StaticConfig>(
                "databus.client.", clientConfigBuilder);

        String[] sources = addSources();

        StringBuilder sourcesString = new StringBuilder();
        boolean firstSrc = true;
        for (String source : sources) {
            if (!firstSrc)
                sourcesString.append(",");
            firstSrc = false;
            sourcesString.append(source);
        }

        if (_httpPort != null) {
            startupProps.put("databus.client.container.httpPort", _httpPort);
        }
        if (_jmxServicePort != null) {
            startupProps.put("databus.client.container.jmx.jmxServicePort", _jmxServicePort);
        }
        if (_checkpointFileRootDir != null) {
            startupProps.put("databus.client.checkpointPersistence.fileSystem.rootDirectory",
                    _checkpointFileRootDir);
        }

        DatabusHttpClientImpl.StaticConfig clientConfig = configLoader.loadConfig(startupProps);

        // set up relay
        ServerInfoBuilder relayBuilder = clientConfig.getRuntime().getRelay("1");
        relayBuilder.setName("DefaultRelay");
        if (_relayHost != null) {
            relayBuilder.setHost(_relayHost);
        }
        if (_relayPort != null) {
            relayBuilder.setPort(Integer.parseInt(_relayPort));
        }
        relayBuilder.setSources(sourcesString.toString());

        // set up bootstrap
        if (_enableBootStrap) {
            ServerInfoBuilder bootstrapBuilder = clientConfig.getRuntime().getBootstrap().getService("2");
            bootstrapBuilder.setName("DefaultBootstrapServices");
            if (_bootstrapHost != null) {
                bootstrapBuilder.setHost(_bootstrapHost);
            }
            if (_bootstrapPort != null) {
                bootstrapBuilder.setPort(Integer.parseInt(_bootstrapPort));
            }
            bootstrapBuilder.setSources(sourcesString.toString());
        }

        // handler server side filtering, can either pass a config file or set from command line
        DbusKeyCompositeFilterConfig filterConfig = createServerSideFilterConfig(_filterConfFile, startupProps);

        // set up listeners
        DatabusHttpClientImpl client = new DatabusHttpClientImpl(clientConfig);

        // dump decoded payload values and raw (undecoded) events
        DatabusFileLoggingConsumer consumer = createTypedConsumer(_valueDumpFile, _eventDumpFile);

        if (_eventPattern != null) {
            consumer.setEventPattern(_eventPattern);
        }
        DatabusRegistration reg = client.register(consumer, sources);

        if (!(reg instanceof DatabusV2RegistrationImpl)) {
            throw new RuntimeException("Unexpected type for registration Object !!");
        }

        if (null != filterConfig)
            reg.withServerSideFilter(filterConfig);

        // add pause processor
        try {
            client.getProcessorRegistry().register(ConsumerPauseRequestProcessor.COMMAND_NAME,
                    new ConsumerPauseRequestProcessor(null, consumer));
            client.getProcessorRegistry().register(ContainerOperationProcessor.COMMAND_NAME,
                    new ContainerOperationProcessor(null, client));
        } catch (ProcessorRegistrationConflictException e) {
            LOG.error("Failed to register " + ConsumerPauseRequestProcessor.COMMAND_NAME);
        }

        DatabusClientShutdownThread shutdownThread = new DatabusClientShutdownThread(client);
        Runtime.getRuntime().addShutdownHook(shutdownThread);

        client.startAndBlock(); //this should automatically start the registration
    }

    private DbusKeyCompositeFilterConfig createServerSideFilterConfig(String filterConfFile,
            Properties startupProps) throws IOException, InvalidConfigException {
        Boolean cmdLineHasFilterConfig = hasServerSideFilterConfig(startupProps);
        if (filterConfFile != null || cmdLineHasFilterConfig) {
            Properties props;
            // cmdline override the config file
            if (cmdLineHasFilterConfig) {
                props = startupProps;
            } else {
                LOG.info("filterConfFile = " + filterConfFile);
                props = new Properties();

                FileInputStream filterConfStream = new FileInputStream(filterConfFile);
                try {
                    props.load(filterConfStream);
                } finally {
                    filterConfStream.close();
                }
            }

            DbusKeyCompositeFilterConfig.Config conf = new DbusKeyCompositeFilterConfig.Config();
            ConfigLoader<DbusKeyCompositeFilterConfig.StaticConfig> filterConfigLoader = new ConfigLoader<DbusKeyCompositeFilterConfig.StaticConfig>(
                    SERVER_SIDE_FILTER_PREFIX, conf);
            DbusKeyCompositeFilterConfig.StaticConfig sConf = filterConfigLoader.loadConfig(props);

            return new DbusKeyCompositeFilterConfig(sConf);
        } else {
            return null;
        }
    }

    private Boolean hasServerSideFilterConfig(Properties startupProps) {
        Enumeration<Object> propKeys = startupProps.keys();
        while (propKeys.hasMoreElements()) {
            String key = (String) propKeys.nextElement();
            if (key.contains(SERVER_SIDE_FILTER_PREFIX)) {
                return true;
            }
        }
        return false;
    }

    static class DatabusClientShutdownThread extends Thread {
        public static final String MODULE = DatabusClientShutdownThread.class.getName();
        public static final Logger LOG = Logger.getLogger(MODULE);

        private final ServerContainer _serverContainer;

        public DatabusClientShutdownThread(ServerContainer serverContainer) {
            super("ServerContainer Shutdown Thread");
            _serverContainer = serverContainer;
        }

        @Override
        public void run() {
            LOG.info("Starting shutdown procedure for server container...");
            try {
                if (null != _serverContainer && _serverContainer.isRunningStatus()) {
                    _serverContainer.shutdownUninteruptibly();
                }
                LOG.info("Server Container shutdown.");
            } catch (Exception e) {
                LOG.error("Error shutting down Server Container", e);
            }
        }
    }
}