/* * Copyright 2009 Red Hat, Inc. * * Red Hat licenses this file to you 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. */ package com.linkedin.databus.container.netty; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.nio.charset.Charset; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.avro.Schema; import org.apache.commons.cli.Option; import org.apache.commons.cli.OptionBuilder; import org.apache.log4j.Logger; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.ObjectMapper; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ServerChannel; import com.linkedin.databus.container.request.BufferInfoRequestProcessor; import com.linkedin.databus.container.request.GenerateDataEventsRequestProcessor; import com.linkedin.databus.container.request.LoadDataEventsRequestProcessor; import com.linkedin.databus.container.request.PhysicalBuffersRequestProcessor; import com.linkedin.databus.container.request.PhysicalSourcesRequestProcessor; import com.linkedin.databus.container.request.ReadEventsRequestProcessor; import com.linkedin.databus.container.request.RegisterRequestProcessor; import com.linkedin.databus.container.request.RelayCommandRequestProcessor; import com.linkedin.databus.container.request.RelayContainerStatsRequestProcessor; import com.linkedin.databus.container.request.RelayStatsRequestProcessor; import com.linkedin.databus.container.request.SourcesRequestProcessor; import com.linkedin.databus.core.DbusEventBuffer; import com.linkedin.databus.core.DbusEventBufferMetaInfo; import com.linkedin.databus.core.DbusEventBufferMult; import com.linkedin.databus.core.DbusEventBufferMult.PhysicalPartitionKey; import com.linkedin.databus.core.DbusEventFactory; import com.linkedin.databus.core.DbusEventV1Factory; import com.linkedin.databus.core.EventLogReader; import com.linkedin.databus.core.EventLogWriter; import com.linkedin.databus.core.UnsupportedKeyException; import com.linkedin.databus.core.data_model.PhysicalPartition; import com.linkedin.databus.core.monitoring.mbean.DbusEventStatsCollectorsPartitioner; import com.linkedin.databus.core.monitoring.mbean.DbusEventsStatisticsCollector; import com.linkedin.databus.core.util.ConfigApplier; import com.linkedin.databus.core.util.ConfigBuilder; import com.linkedin.databus.core.util.ConfigLoader; import com.linkedin.databus.core.util.ConfigManager; import com.linkedin.databus.core.util.DatabusEventProducer; import com.linkedin.databus.core.util.DatabusEventRandomProducer; import com.linkedin.databus.core.util.IdNamePair; import com.linkedin.databus.core.util.InvalidConfigException; import com.linkedin.databus.core.util.PhysicalSourceConfigBuilder; import com.linkedin.databus2.core.BufferNotFoundException; import com.linkedin.databus2.core.DatabusException; import com.linkedin.databus2.core.container.monitoring.mbean.DatabusComponentAdmin; import com.linkedin.databus2.core.container.monitoring.mbean.HttpStatisticsCollector; import com.linkedin.databus2.core.container.netty.ServerContainer; import com.linkedin.databus2.core.container.request.ConfigRequestProcessor; import com.linkedin.databus2.core.container.request.ContainerStatsRequestProcessor; import com.linkedin.databus2.core.container.request.EchoRequestProcessor; import com.linkedin.databus2.core.container.request.RequestProcessorRegistry; import com.linkedin.databus2.core.container.request.SleepRequestProcessor; import com.linkedin.databus2.producers.EventCreationException; import com.linkedin.databus2.relay.AddRemovePartitionInterface; import com.linkedin.databus2.relay.config.DataSourcesStaticConfig; import com.linkedin.databus2.relay.config.DataSourcesStaticConfigBuilder; import com.linkedin.databus2.relay.config.LogicalSourceConfig; import com.linkedin.databus2.relay.config.PhysicalSourceConfig; import com.linkedin.databus2.relay.config.PhysicalSourceStaticConfig; import com.linkedin.databus2.schemas.FileSystemSchemaRegistryService; import com.linkedin.databus2.schemas.SchemaRegistryConfigBuilder; import com.linkedin.databus2.schemas.SchemaRegistryService; import com.linkedin.databus2.schemas.SchemaRegistryStaticConfig; import com.linkedin.databus2.schemas.SourceIdNameRegistry; import com.linkedin.databus2.schemas.StandardSchemaRegistryFactory; import com.linkedin.databus2.schemas.utils.SchemaHelper; /** * The HTTP container for the databus relay */ public class HttpRelay extends ServerContainer implements AddRemovePartitionInterface { private static final String MODULE = HttpRelay.class.getName(); private static final Logger LOG = Logger.getLogger(MODULE); private DbusEventBufferMult _eventBufferMult; private final DbusEventFactory _eventFactory; private final SchemaRegistryService _schemaRegistryService; protected final StaticConfig _relayStaticConfig; private final ConfigManager<RuntimeConfig> _relayConfigManager; private final HttpStatisticsCollector _httpStatisticsCollector; private final SourceIdNameRegistry _sourcesIdNameRegistry; protected List<PhysicalSourceStaticConfig> _pConfigs; // The map maintains the highest last known schemaVersion for each source parsed // from the events from RPL-dbus. If there is a version change, we can detect by checking // with the version info stored in the map. final Map<String, Short> _sourceSchemaVersionMap = new ConcurrentHashMap<String, Short>(); // DB level inbound stats aggregate protected DbusEventStatsCollectorsPartitioner _dbInboundStatsCollectors; // DB level outbound stats aggregate protected DbusEventStatsCollectorsPartitioner _dbOutboundStatsCollectors; public HttpRelay(Config config, PhysicalSourceStaticConfig [] pConfigs) throws IOException, InvalidConfigException, DatabusException { this(config.build(), pConfigs); } public HttpRelay(StaticConfig config, PhysicalSourceStaticConfig[] pConfigs) throws IOException, InvalidConfigException, DatabusException { this(config, pConfigs, SourceIdNameRegistry.createFromIdNamePairs(config.getSourceIds()), (new StandardSchemaRegistryFactory(config.getSchemaRegistry())).createSchemaRegistry(), new DbusEventV1Factory()); } public HttpRelay(StaticConfig config, PhysicalSourceStaticConfig [] pConfigs, SourceIdNameRegistry sourcesIdNameRegistry, SchemaRegistryService schemaRegistry) throws IOException, InvalidConfigException, DatabusException { this(config, pConfigs, sourcesIdNameRegistry, schemaRegistry, new DbusEventV1Factory()); } public HttpRelay(StaticConfig config, PhysicalSourceStaticConfig [] pConfigs, SourceIdNameRegistry sourcesIdNameRegistry, SchemaRegistryService schemaRegistry, DbusEventFactory eventFactory) throws IOException, InvalidConfigException, DatabusException { super(config.getContainer(), eventFactory.getByteOrder()); _relayStaticConfig = config; _sourcesIdNameRegistry = sourcesIdNameRegistry; _eventFactory = eventFactory; //3 possible scenarios: // 1. _pConfigs is initialized by this moment // 2. _pConfigs is null - create a fake one for backward compatiblity // 3. _pConfigs is not null but empty - we are trying to create an empty relay if(pConfigs == null) { // nothing provided - create a fake ones initPConfigs(config); } else if(pConfigs.length == 0) { //nothing available yet, probably CM case _pConfigs = new ArrayList<PhysicalSourceStaticConfig>(); } else { _pConfigs = new ArrayList<PhysicalSourceStaticConfig>(); for(PhysicalSourceStaticConfig pC : pConfigs) _pConfigs.add(pC); } if(_eventBufferMult == null) { PhysicalSourceStaticConfig[] psscArr = new PhysicalSourceStaticConfig[_pConfigs.size()]; _pConfigs.toArray(psscArr); _eventBufferMult = new DbusEventBufferMult(psscArr, config.getEventBuffer(), _eventFactory); } _eventBufferMult.setDropOldEvents(true); _dbInboundStatsCollectors = new DbusEventStatsCollectorsPartitioner(getContainerStaticConfig().getId(), ".inbound", getMbeanServer()); _dbOutboundStatsCollectors = new DbusEventStatsCollectorsPartitioner(getContainerStaticConfig().getId(), ".outbound", getMbeanServer()); if (null != _eventBufferMult.getAllPhysicalPartitionKeys()) { for (PhysicalPartitionKey pkey: _eventBufferMult.getAllPhysicalPartitionKeys()) { addPhysicalPartitionCollectors(pkey.getPhysicalPartition()); } } _sourcesIdNameRegistry.getAllSources(); _schemaRegistryService = schemaRegistry; if (null == _schemaRegistryService) { throw new InvalidConfigException("Unable to initialize schema registry"); } HttpStatisticsCollector httpStatsColl = _relayStaticConfig.getHttpStatsCollector() .getExistingStatsCollector(); if (null == httpStatsColl) { httpStatsColl = new HttpStatisticsCollector(getContainerStaticConfig().getId(), "httpOutbound", _relayStaticConfig.getRuntime().getHttpStatsCollector().isEnabled(), true, getMbeanServer()); } _httpStatisticsCollector = httpStatsColl; _relayStaticConfig.getRuntime().setManagedInstance(this); _relayConfigManager = new ConfigManager<RuntimeConfig>("databus.relay.runtime.", _relayStaticConfig.getRuntime()); initializeRelayNetworking(); initializeRelayCommandProcessors(); } @Override protected DatabusComponentAdmin createComponentAdmin() { return new DatabusComponentAdmin(this, getMbeanServer(), HttpRelay.class.getSimpleName()); } public Map<String, Short> getSourceSchemaVersionMap() { return _sourceSchemaVersionMap; } public StaticConfig getRelayStaticConfig() { return _relayStaticConfig; } protected void initializeRelayNetworking() throws IOException, DatabusException { _httpBootstrap.setPipelineFactory(new HttpRelayPipelineFactory(this, _httpBootstrap.getPipelineFactory())); } protected void initializeRelayCommandProcessors() throws DatabusException { /** * Re-register containerStats to expose DB level aggregate inbound/event stats. * The ContainerStatsRequestProcessor is registered in ServiceContainer. Since, * we are overriding the behavior of ContainerStatsRequestProcessor, we are * re-registering the subclass (RelayContainerStatsRequestProcessor) in place * of ContainerStatsRequestProcessor. */ _processorRegistry.reregister(ContainerStatsRequestProcessor.COMMAND_NAME, new RelayContainerStatsRequestProcessor(null, this)); _processorRegistry.register(ConfigRequestProcessor.COMMAND_NAME, new ConfigRequestProcessor(null, this)); _processorRegistry.register(RelayStatsRequestProcessor.COMMAND_NAME, new RelayStatsRequestProcessor(null, this)); _processorRegistry.register(SourcesRequestProcessor.COMMAND_NAME, new SourcesRequestProcessor(null, this)); _processorRegistry.register(RegisterRequestProcessor.COMMAND_NAME, new RegisterRequestProcessor(null, this)); _processorRegistry.register(ReadEventsRequestProcessor.COMMAND_NAME, new ReadEventsRequestProcessor(null, this)); _processorRegistry.register(PhysicalSourcesRequestProcessor.COMMAND_NAME, new PhysicalSourcesRequestProcessor(null, this)); _processorRegistry.register(PhysicalBuffersRequestProcessor.COMMAND_NAME, new PhysicalBuffersRequestProcessor(null, this)); _processorRegistry.register(BufferInfoRequestProcessor.COMMAND_NAME, new BufferInfoRequestProcessor(null,_eventBufferMult)); _processorRegistry.register(RelayCommandRequestProcessor.COMMAND_NAME, new RelayCommandRequestProcessor(null, this)); } @Override protected void doStart() { super.doStart(); } public void disconnectDBusClients() { disconnectDBusClients(null); } synchronized public void disconnectDBusClients(Channel exceptThis) { LOG.info("disconnectDBusClients"); if(_httpChannelGroup != null) { LOG.info("Total " + _httpChannelGroup.size() + " channels"); for(Channel channel : _httpChannelGroup) { // Keep the server channel and REST channel if((channel instanceof ServerChannel) || (exceptThis != null && channel.getId().equals(exceptThis.getId()))) { LOG.info("Skipping closing channel" + channel.getId()); } else { LOG.info("closing channel" + channel.getId()); channel.close(); } } } } @Override protected void doShutdown() { super.doShutdown(); getHttpStatisticsCollector().unregisterMBeans(); if (null != _schemaRegistryService && _schemaRegistryService instanceof FileSystemSchemaRegistryService) { LOG.info("stopping file-system schema registry refresh thread"); ((FileSystemSchemaRegistryService)_schemaRegistryService).stopSchemasRefreshThread(); LOG.info("file-system schema registry refresh thread stopped."); } // unregister PhysicalSrcBased inbound collector _dbInboundStatsCollectors.removeAllStatsCollector(); // unregister PhysicalSrcBased inbound collector _dbOutboundStatsCollectors.removeAllStatsCollector(); } /** * add a new buffer - usually invoked by Helix * @param pConfig * @param config * @throws DatabusException * @throws Exception */ public DbusEventBuffer addNewBuffer(PhysicalSourceStaticConfig pConfig, HttpRelay.StaticConfig config) throws DatabusException { DbusEventBufferMult eventMult = getEventBuffer(); DbusEventBuffer buf = eventMult.addNewBuffer(pConfig, config.getEventBuffer()); return buf; } public void addOneProducer(PhysicalSourceStaticConfig pConfig) throws DatabusException, EventCreationException, UnsupportedKeyException, SQLException, InvalidConfigException { // do nothing by default. } public void removeOneProducer(PhysicalSourceStaticConfig pConfig) { // do nothing by default } /** remove a new buffer - usually invoked by Helix */ public void removeBuffer(PhysicalSourceStaticConfig pConfig) { DbusEventBufferMult eventMult = getEventBuffer(); eventMult.removeBuffer(pConfig); } @Override public void dropDatabase(String dbName) throws DatabusException { _schemaRegistryService.dropDatabase(dbName); DbusEventBufferMult eventMult = getEventBuffer(); /* * Close the buffers */ for (DbusEventBuffer dBuf : eventMult.bufIterable()) { PhysicalPartition pp = dBuf.getPhysicalPartition(); if (pp.getName().equals(dbName)) { dBuf.closeBuffer(false); dBuf.removeMMapFiles(); PhysicalPartitionKey pKey = new PhysicalPartitionKey(pp); eventMult.removeBuffer(pKey, null); } } eventMult.deallocateRemovedBuffers(true); return; } public void resetBuffer(PhysicalPartition p, long prevScn, long binlogOffset) throws BufferNotFoundException { DbusEventBufferMult eventMult = getEventBuffer(); eventMult.resetBuffer(p, prevScn); // TODO Set binlogOffset of the server } public int[] getBinlogOffset(int serverId) throws DatabusException { throw new DatabusException("Unimplemented method"); } public Map<String, String> printInfo() throws DatabusException { throw new DatabusException("Unimplemented method"); } public static void main(String[] args) throws Exception { Cli cli = new Cli(); cli.processCommandLineArgs(args); cli.parseRelayConfig(); StaticConfig staticConfig = cli.getRelayConfigBuilder().build(); HttpRelay relay = new HttpRelay(staticConfig, cli.getPhysicalSourceStaticConfigs()); RequestProcessorRegistry processorRegistry = relay.getProcessorRegistry(); //Changes to add schemaId to event; DDSDBUS-3421 //The long term fix is to remove DatabusEventRandomProducer in favour of RelayEventGenerator //The medium term fix is to send SchemaRegistry to DatabusEventRandomProducer, but move RandomProducer to databus-relay-impl (from databus-core-impl) //Reason: SchemaHelper classes required to parse/generate schemaId from schemaRegistry requires databus-schemas-core which depends on databus-core-impl SchemaRegistryService sr=relay.getSchemaRegistryService(); HashMap<Long,byte[]> schemaIds = new HashMap<Long,byte[]>(staticConfig.getSourceIds().size()); for (IdNamePair pair: staticConfig.getSourceIds()) { LOG.info("Http Relay Schema Reg:" + pair.getName() + " id=" + pair.getId()); String schemaStr = sr.fetchLatestSchemaBySourceName(pair.getName()); if (schemaStr != null) { Schema s= Schema.parse(schemaStr); byte[] sid=SchemaHelper.getSchemaId(s.toString()); LOG.info("Found schema! Adding schemaId for sourceName="+pair.getName() + " id=" + pair.getId() + " schemaId=" + sid); schemaIds.put(pair.getId(),sid); } else { byte[] defaultSid="abcde".getBytes(Charset.defaultCharset()); LOG.info("Didn't find schema! Adding default schemaId for sourceName="+pair.getName() + "id=" + pair.getId()+ " schemaId=" + defaultSid); schemaIds.put(pair.getId(),defaultSid); } } DatabusEventProducer randomEventProducer = new DatabusEventRandomProducer(relay.getEventBuffer(), 10, 100, 1000, staticConfig.getSourceIds(),schemaIds); // specify stats collector for this producer ((DatabusEventRandomProducer)randomEventProducer).setStatsCollector(relay.getInboundEventStatisticsCollector()); processorRegistry.register(EchoRequestProcessor.COMMAND_NAME, new EchoRequestProcessor(null)); processorRegistry.register(SleepRequestProcessor.COMMAND_NAME, new SleepRequestProcessor(null)); processorRegistry.register( GenerateDataEventsRequestProcessor.COMMAND_NAME, new GenerateDataEventsRequestProcessor(null, relay, randomEventProducer)); processorRegistry.register(LoadDataEventsRequestProcessor.COMMAND_NAME, new LoadDataEventsRequestProcessor(relay.getDefaultExecutorService(), relay)); LOG.info("source = " + relay.getSourcesIdNameRegistry().getAllSources()); try { relay.registerShutdownHook(); relay.startAndBlock(); } catch (Exception e) { LOG.error("Error starting the relay", e); } LOG.info("Exiting relay"); } public static class Cli extends ServerContainer.Cli { public static final char DB_RELAY_CONFIG_FILE_OPT_CHAR = 'Y'; public static final String DB_RELAY_CONFIG_FILE_OPT_NAME = "db_relay_config"; protected String []_physicalSrcConfigFiles; protected PhysicalSourceStaticConfig[] _pStaticConfigs; protected Config _relayConfigBuilder; public Cli() { this("java " + HttpRelay.class.getName() + " [options]"); } public Cli(String usage) { super(usage); } public String[] getPhysicalSrcConfigFiles() { if (null == _physicalSrcConfigFiles) return null; return Arrays.copyOf(_physicalSrcConfigFiles, _physicalSrcConfigFiles.length); } @Override public void processCommandLineArgs(String[] cliArgs) throws IOException, DatabusException { super.processCommandLineArgs(cliArgs); if (_cmd.hasOption(DB_RELAY_CONFIG_FILE_OPT_NAME)) { String opt = _cmd.getOptionValue(DB_RELAY_CONFIG_FILE_OPT_NAME); _physicalSrcConfigFiles = opt.split(","); for (int i = 0; i < _physicalSrcConfigFiles.length; ++i) _physicalSrcConfigFiles[i] = _physicalSrcConfigFiles[i].trim(); LOG.info("Physical Sources Config files = " + Arrays.toString(_physicalSrcConfigFiles)); } } /** * Parse the relay configuration from the properties */ public void parseRelayConfig() throws IOException, InvalidConfigException { _relayConfigBuilder = new Config(); ConfigLoader<StaticConfig> staticConfigLoader = new ConfigLoader<StaticConfig>( "databus.relay.", _relayConfigBuilder); staticConfigLoader.loadConfig(getConfigProps()); if (null != _physicalSrcConfigFiles && 0 < _physicalSrcConfigFiles.length) { parsePhysicalSourceConfigs(); } } private void parsePhysicalSourceConfigs() throws JsonParseException, JsonMappingException, IOException, InvalidConfigException { _pStaticConfigs = new PhysicalSourceStaticConfig[_physicalSrcConfigFiles.length]; ObjectMapper mapper = new ObjectMapper(); int i = 0; for (String file : _physicalSrcConfigFiles) { LOG.info("processing file: " + file); File sourcesJson = new File(file); PhysicalSourceConfig pConfig = mapper.readValue(sourcesJson, PhysicalSourceConfig.class); pConfig.checkForNulls(); _pStaticConfigs[i] = pConfig.build(); // Register all sources with the static config //TODO why do we need this? for (LogicalSourceConfig lsc : pConfig.getSources()) { _relayConfigBuilder.setSourceName(Short.toString(lsc.getId()), lsc.getName()); } i++; } } @SuppressWarnings("static-access") @Override protected void constructCommandLineOptions() { super.constructCommandLineOptions(); Option physConfigOption = OptionBuilder.withLongOpt(DB_RELAY_CONFIG_FILE_OPT_NAME) .hasArg() .hasArg() .withArgName("physical sources config File") .create(DB_RELAY_CONFIG_FILE_OPT_CHAR); _cliOptions.addOption(physConfigOption); } /** * return the physical sources configs */ public PhysicalSourceStaticConfig[] getPhysicalSourceStaticConfigs() { return null == _pStaticConfigs ? null : _pStaticConfigs.clone(); } /** * return a relay config builder (so settings can be further overriden) */ public Config getRelayConfigBuilder() { return _relayConfigBuilder; } /** * Set the default physical sources configuration files. * * Note: Once command-line options have been processed, changing this option has no effect. */ public void setDefaultPhysicalSrcConfigFiles(String... physicalSrcConfigFiles) { _physicalSrcConfigFiles = null == physicalSrcConfigFiles ? null : physicalSrcConfigFiles.clone(); } } public class RuntimeConfig implements ConfigApplier<RuntimeConfig> { private final ServerContainer.RuntimeConfig _container; private final HttpStatisticsCollector.RuntimeConfig _httpStatsCollector; public RuntimeConfig(ServerContainer.RuntimeConfig container, HttpStatisticsCollector.RuntimeConfig httpStatsCollector) { super(); _container = container; _httpStatsCollector = httpStatsCollector; } @Override public void applyNewConfig(RuntimeConfig oldConfig) { LOG.debug("Applying new relay config"); if (null == oldConfig || ! getContainer().equals(oldConfig.getContainer())) { _container.applyNewConfig(null != oldConfig ? oldConfig.getContainer() : null); } if (null == oldConfig || ! getHttpStatsCollector().equals(oldConfig.getHttpStatsCollector())) { getHttpStatsCollector().applyNewConfig(null != oldConfig ? oldConfig.getHttpStatsCollector() : null); } } @Override public boolean equals(Object other) { if (null == other || !(other instanceof RuntimeConfig)) return false; if(this == other) return true; return equalsConfig((RuntimeConfig)other); } @Override public boolean equalsConfig(RuntimeConfig otherConfig) { if (null == otherConfig) return false; return getContainer().equals(otherConfig.getContainer()) && getHttpStatsCollector().equals(otherConfig.getHttpStatsCollector()); } @Override public int hashCode() { return _container.hashCode() ^ _httpStatisticsCollector.hashCode(); } /** Runtime configuration options for the Netty container */ public ServerContainer.RuntimeConfig getContainer() { return _container; } /** Runtime configuration options for the HTTP calls statistics collect*/ public HttpStatisticsCollector.RuntimeConfig getHttpStatsCollector() { return _httpStatsCollector; } } public static class RuntimeConfigBuilder implements ConfigBuilder<RuntimeConfig> { private final ServerContainer.RuntimeConfigBuilder _container; private HttpRelay _managedInstance = null; private HttpStatisticsCollector.RuntimeConfigBuilder _httpStatsCollector; public RuntimeConfigBuilder(ServerContainer.RuntimeConfigBuilder container) { _container = container; _httpStatsCollector = new HttpStatisticsCollector.RuntimeConfigBuilder(); } public HttpRelay getManagedInstance() { return _managedInstance; } public void setManagedInstance(HttpRelay managedInstance) { _managedInstance = managedInstance; _container.setManagedInstance(managedInstance); _httpStatsCollector.setManagedInstance(_managedInstance.getHttpStatisticsCollector()); } public ServerContainer.RuntimeConfigBuilder getContainer() { return _container; } @Override public RuntimeConfig build() throws InvalidConfigException { if (null == _managedInstance) throw new InvalidConfigException("Missing relay"); return _managedInstance.new RuntimeConfig(_container.build(), _httpStatsCollector.build()); } public HttpStatisticsCollector.RuntimeConfigBuilder getHttpStatsCollector() { return _httpStatsCollector; } public void setHttpStatsCollector(HttpStatisticsCollector.RuntimeConfigBuilder httpStatsCollector) { _httpStatsCollector = httpStatsCollector; } } public static class StaticConfig { private final ServerContainer.StaticConfig _containerConfig; private final DbusEventBuffer.StaticConfig _eventBufferConfig; private final SchemaRegistryStaticConfig _schemaRegistryConfig; private final List<IdNamePair> _sourceIds; private final RuntimeConfigBuilder _runtime; private final HttpStatisticsCollector.StaticConfig _httpStatsCollector; private final DatabusEventRandomProducer.StaticConfig _randomProducer; private final EventLogWriter.StaticConfig _eventLogWriterConfig; private final EventLogReader.StaticConfig _eventLogReaderConfig; private final boolean _startDbPuller; private final DataSourcesStaticConfig _dataSources; private final PhysicalSourceStaticConfig[] _physicalSourcesConfigs; public StaticConfig(DbusEventBuffer.StaticConfig eventBufferConfig, ServerContainer.StaticConfig containerConfig, SchemaRegistryStaticConfig schemaRegistryConfig, List<IdNamePair> sourceIds, RuntimeConfigBuilder runtime, HttpStatisticsCollector.StaticConfig httpStatsCollector, DbusEventsStatisticsCollector.StaticConfig inboundEventsStatsCollector, DbusEventsStatisticsCollector.StaticConfig outboundEventsStatsCollector, DatabusEventRandomProducer.StaticConfig randomProducer, EventLogWriter.StaticConfig eventLogWriterConfig, EventLogReader.StaticConfig eventLogReaderConfig, boolean startDbPuller, DataSourcesStaticConfig dataSources, PhysicalSourceStaticConfig[] physicalSourcesConfigs) { super(); _eventBufferConfig = eventBufferConfig; _containerConfig = containerConfig; _schemaRegistryConfig = schemaRegistryConfig; _sourceIds = sourceIds; _runtime = runtime; _httpStatsCollector = httpStatsCollector; _randomProducer = randomProducer; _eventLogWriterConfig = eventLogWriterConfig; _eventLogReaderConfig = eventLogReaderConfig; _startDbPuller = startDbPuller; _dataSources = dataSources; _physicalSourcesConfigs = physicalSourcesConfigs.clone(); } /** Configuration options for the relay event buffer */ public DbusEventBuffer.StaticConfig getEventBuffer() { return _eventBufferConfig; } /** Configuration options for the relay random events producer (testing) */ public DatabusEventRandomProducer.StaticConfig getRandomProducer() { return _randomProducer; } /** Configuration options for the relay netty container */ public ServerContainer.StaticConfig getContainer() { return _containerConfig; } /** Configuration options for the schema registry */ public SchemaRegistryStaticConfig getSchemaRegistry() { return _schemaRegistryConfig; } /** Databus sources registered in the relay */ public List<IdNamePair> getSourceIds() { return _sourceIds; } /** Relay runtime configuration options */ public RuntimeConfigBuilder getRuntime() { return _runtime; } /** Configuration options for the HTTP calls statistics collector */ public HttpStatisticsCollector.StaticConfig getHttpStatsCollector() { return _httpStatsCollector; } /** Configuration options for the event log writer. */ public EventLogWriter.StaticConfig getEventLogWriterConfig() { return _eventLogWriterConfig; } /** Configuration options for the event log reader. */ public EventLogReader.StaticConfig getEventLogReaderConfig() { return _eventLogReaderConfig; } /**Configuration option for starting db puller thread on startup */ public boolean getStartDbPuller() { return _startDbPuller; } /** * Configuration for all physical data sources used by the relay. * * NOTE: WIP*/ public DataSourcesStaticConfig getDataSources() { return _dataSources; } /** Physical sources config */ public PhysicalSourceStaticConfig[] getPhysicalSourcesConfigs() { if (null == _physicalSourcesConfigs) return null; return Arrays.copyOf(_physicalSourcesConfigs, _physicalSourcesConfigs.length); } } public static class StaticConfigBuilderBase { protected DbusEventBuffer.Config _eventBuffer; protected ServerContainer.Config _container; protected SchemaRegistryConfigBuilder _schemaRegistry; protected final HashMap<String, String> _sourceName; protected RuntimeConfigBuilder _runtime; protected HttpStatisticsCollector.Config _httpStatsCollector; protected DbusEventsStatisticsCollector.Config _outboundEventsStatsCollector; protected DbusEventsStatisticsCollector.Config _inboundEventsStatsCollector; protected DatabusEventRandomProducer.Config _randomProducer; protected EventLogWriter.Config _eventLogWriter; protected EventLogReader.Config _eventLogReader; protected String _startDbPuller; protected DataSourcesStaticConfigBuilder _dataSources; protected ArrayList<PhysicalSourceConfig> _physicalSourcesConfigs; protected String _physicalSourcesConfigsPattern; public StaticConfigBuilderBase() throws IOException { _eventBuffer = new DbusEventBuffer.Config(); _schemaRegistry = new SchemaRegistryConfigBuilder(); setContainer(new ServerContainer.Config()); _sourceName = new HashMap<String, String>(100); _runtime = new RuntimeConfigBuilder(_container.getRuntime()); _httpStatsCollector = new HttpStatisticsCollector.Config(); _outboundEventsStatsCollector = new DbusEventsStatisticsCollector.Config(); _inboundEventsStatsCollector = new DbusEventsStatisticsCollector.Config(); _randomProducer = new DatabusEventRandomProducer.Config(); _eventLogWriter = new EventLogWriter.Config(); _eventLogReader = new EventLogReader.Config(); _dataSources = new DataSourcesStaticConfigBuilder(); _physicalSourcesConfigs = new ArrayList<PhysicalSourceConfig>(); setStartDbPuller("false"); } public ServerContainer.Config getContainer() { return _container; } public DbusEventBuffer.Config getEventBuffer() { return _eventBuffer; } public void setEventBuffer(DbusEventBuffer.Config eventBufferConfig) { System.out.println("DEBUG: setEventBuffer Called"); _eventBuffer = eventBufferConfig; } public DatabusEventRandomProducer.Config getRandomProducer() { return _randomProducer; } public void setRandomProducer(DatabusEventRandomProducer.Config randomProducer) { _randomProducer = randomProducer; } public void setContainer(ServerContainer.Config container) { _container = container; _container.setRuntimeConfigPropertyPrefix("com.linkedin.databus.relay"); } public SchemaRegistryConfigBuilder getSchemaRegistry() { return _schemaRegistry; } public void setSourceName(String idStr, String name) { _sourceName.put(idStr, name); } public String getSourceName(String idStr) { return _sourceName.get(idStr); } public RuntimeConfigBuilder getRuntime() { return _runtime; } public void setRuntime(RuntimeConfigBuilder runtime) { _runtime = runtime; } public HttpStatisticsCollector.Config getHttpStatsCollector() { return _httpStatsCollector; } public void setHttpStatsCollector(HttpStatisticsCollector.Config httpStatsCollector) { _httpStatsCollector = httpStatsCollector; } public DbusEventsStatisticsCollector.Config getOutboundEventsStatsCollector() { return _outboundEventsStatsCollector; } public void setOutboundEventsStatsCollector(DbusEventsStatisticsCollector.Config eventsStatsCollector) { _outboundEventsStatsCollector = eventsStatsCollector; } public DbusEventsStatisticsCollector.Config getInboundEventsStatsCollector() { return _inboundEventsStatsCollector; } public void setInboundEventsStatsCollector(DbusEventsStatisticsCollector.Config inboundEventsStatsCollector) { _inboundEventsStatsCollector = inboundEventsStatsCollector; } public EventLogWriter.Config getEventLogWriter() { return _eventLogWriter; } public void setEventLogWriter(EventLogWriter.Config eventLogWriterConfig) { _eventLogWriter = eventLogWriterConfig; } public EventLogReader.Config getEventLogReader() { return _eventLogReader; } public void setEventLogReader(EventLogReader.Config eventLogReader) { _eventLogReader = eventLogReader; } public void setStartDbPuller(String startDbPuller) { _startDbPuller = startDbPuller; } public String getStartDbPuller() { return _startDbPuller; } public DataSourcesStaticConfigBuilder getDataSources() { return _dataSources; } public PhysicalSourceConfig getPhysicalSourcesConfigs(int index) { while (_physicalSourcesConfigs.size() <= index) _physicalSourcesConfigs.add(new PhysicalSourceConfig()); return _physicalSourcesConfigs.get(index); } public void setPhysicalSourcesConfigs(int index, PhysicalSourceConfig conf) { while (_physicalSourcesConfigs.size() <= index) _physicalSourcesConfigs.add(new PhysicalSourceConfig()); _physicalSourcesConfigs.set(index, conf); } public String getPhysicalSourcesConfigsPattern() { return _physicalSourcesConfigsPattern; } public void setPhysicalSourcesConfigsPattern(String physicalSourcesConfigsPattern) { _physicalSourcesConfigsPattern = physicalSourcesConfigsPattern; } protected PhysicalSourceStaticConfig[] buildInitPhysicalSourcesConfigs() throws InvalidConfigException { String[] sourcesConfigFiles = null; String physConfDirName = null; if (null != _physicalSourcesConfigsPattern && _physicalSourcesConfigsPattern.trim().length() >0) { File patternFile = new File(_physicalSourcesConfigsPattern); physConfDirName = patternFile.getParent(); final String globPattern = patternFile.getName().replace(".", "\\.").replace("*", ".*") .replace("?", "."); sourcesConfigFiles = patternFile.getParentFile().list(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.matches(globPattern); } }); LOG.info("loading physical sources configs from: " + Arrays.toString(sourcesConfigFiles)); } int physConfigsSize = _physicalSourcesConfigs.size(); if (null != sourcesConfigFiles) physConfigsSize += sourcesConfigFiles.length; PhysicalSourceStaticConfig[] physConfigs = new PhysicalSourceStaticConfig[physConfigsSize]; int physConfIdx = 0; for (PhysicalSourceConfig confBuilder: _physicalSourcesConfigs) { physConfigs[physConfIdx++] = confBuilder.build(); } if (null != sourcesConfigFiles) { PhysicalSourceConfigBuilder fileConfBuilder = new PhysicalSourceConfigBuilder(physConfDirName, sourcesConfigFiles); PhysicalSourceStaticConfig[] confsFromFiles = fileConfBuilder.build(); System.arraycopy(confsFromFiles, 0, physConfigs, physConfIdx, confsFromFiles.length); } return physConfigs; } } public static class Config extends StaticConfigBuilderBase implements ConfigBuilder<StaticConfig> { public Config() throws IOException { super(); } @Override public StaticConfig build() throws InvalidConfigException { ArrayList<IdNamePair> sourceIds = new ArrayList<IdNamePair>(_sourceName.size()); for (String srcIdStr: _sourceName.keySet()) { try { long srcId = Long.parseLong(srcIdStr); sourceIds.add(new IdNamePair(srcId, _sourceName.get(srcIdStr))); } catch (NumberFormatException nfe) { throw new InvalidConfigException("Invalid source id: " + srcIdStr); } } PhysicalSourceStaticConfig[] physConfigs = buildInitPhysicalSourcesConfigs(); // TODO (DDSDBUS-77) Add config verification return new StaticConfig(_eventBuffer.build(), _container.build(), _schemaRegistry.build(), sourceIds, getRuntime(), _httpStatsCollector.build(), _inboundEventsStatsCollector.build(), _outboundEventsStatsCollector.build(), _randomProducer.build(), _eventLogWriter.build(), _eventLogReader.build(), Boolean.parseBoolean(_startDbPuller), _dataSources.build(), physConfigs); } } /** * The relay's event factory is the source of truth for its endianness. * * @return the event factory for this relay */ public DbusEventFactory getEventFactory() { return _eventFactory; } public DbusEventBufferMult getEventBuffer() { return _eventBufferMult; } public SchemaRegistryService getSchemaRegistryService() { return _schemaRegistryService; } public ConfigManager<RuntimeConfig> getRelayConfigManager() { return _relayConfigManager; } public HttpStatisticsCollector getHttpStatisticsCollector() { return _httpStatisticsCollector; } @Override public void pause() { //TODO: for jmx admin mbean, to be implemented by sub-classes } @Override public void resume() { //TODO: for jmx admin mbean, to be implemented by sub-classes } @Override public void suspendOnError(Throwable cause) { //TODO: implement me } // create a "fake" configuration for backward compatiblity - in case a new configuration is not available private void initPConfigs(HttpRelay.StaticConfig config) throws InvalidConfigException { if(_pConfigs != null) return; StringBuilder logListIds = new StringBuilder("Creating default physical source config. Sources are: "); // default ph config PhysicalSourceConfig pConfig = PhysicalSourceConfig.createFromLogicalSources(_sourcesIdNameRegistry.getAllSources()); // for(LogicalSourceConfig ls : pConfig.getSources()) logListIds.append(ls.getId() + ":" + ls.getName() + ","); LOG.info(logListIds); // set the memeber _pConfigs = new ArrayList<PhysicalSourceStaticConfig>(1); _pConfigs.add(pConfig.build()); } public List<PhysicalSourceStaticConfig> getPhysicalSources() { return _pConfigs; } public SourceIdNameRegistry getSourcesIdNameRegistry() { return _sourcesIdNameRegistry; } @Override public void addPartition(PhysicalSourceStaticConfig pConfig) throws DatabusException { addNewBuffer(pConfig, _relayStaticConfig); } @Override public void removePartition(PhysicalSourceStaticConfig pConfig) { removeBuffer(pConfig); } public void saveBufferMetaInfo(boolean infoOnly) throws IOException { getEventBuffer().saveBufferMetaInfo(infoOnly); } public void validateRelayBuffers() throws DbusEventBufferMetaInfo.DbusEventBufferMetaInfoException { getEventBuffer().validateRelayBuffers(); } @Override public void shutdown() { super.shutdown(); // shuts down all the connections getEventBuffer().rollbackAllBuffers(); getEventBuffer().close(); // will save the state of MMapped Buffers } public void addPhysicalPartitionCollectors(PhysicalPartition pPartition) { String statsCollectorName = pPartition.toSimpleString(); if (null != _inBoundStatsCollectors) { synchronized (_inBoundStatsCollectors) { if (null == _inBoundStatsCollectors.getStatsCollector(statsCollectorName)) { DbusEventsStatisticsCollector collector = new DbusEventsStatisticsCollector(getContainerStaticConfig().getId(), statsCollectorName+".inbound", true, false, getMbeanServer()); _inBoundStatsCollectors.addStatsCollector(statsCollectorName, collector); _dbInboundStatsCollectors.addStatsCollector(pPartition, collector); } } } if (null != _outBoundStatsCollectors) { synchronized (_outBoundStatsCollectors) { if (null == _outBoundStatsCollectors.getStatsCollector(statsCollectorName)) { DbusEventsStatisticsCollector collector = new DbusEventsStatisticsCollector(getContainerStaticConfig().getId(), statsCollectorName+".outbound", true, false, getMbeanServer()); _outBoundStatsCollectors.addStatsCollector(statsCollectorName, collector); _dbOutboundStatsCollectors.addStatsCollector(pPartition, collector); } } } } public DbusEventStatsCollectorsPartitioner getDbInboundStatsCollectors() { return _dbInboundStatsCollectors; } public DbusEventStatsCollectorsPartitioner getDbOutboundStatsCollectors() { return _dbOutboundStatsCollectors; } }