/* * Copyright 2014-2017 Real Logic Ltd. * * 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. */ package io.aeron.driver; import io.aeron.CncFileDescriptor; import io.aeron.CommonContext; import io.aeron.driver.buffer.RawLogFactory; import io.aeron.driver.cmd.DriverConductorCmd; import io.aeron.driver.cmd.ReceiverCmd; import io.aeron.driver.cmd.SenderCmd; import io.aeron.driver.exceptions.ActiveDriverException; import io.aeron.driver.exceptions.ConfigurationException; import io.aeron.driver.media.ControlTransportPoller; import io.aeron.driver.media.DataTransportPoller; import io.aeron.driver.media.ReceiveChannelEndpointThreadLocals; import io.aeron.driver.reports.LossReport; import io.aeron.driver.status.SystemCounters; import org.agrona.*; import org.agrona.concurrent.*; import org.agrona.concurrent.broadcast.BroadcastTransmitter; import org.agrona.concurrent.errors.DistinctErrorLog; import org.agrona.concurrent.ringbuffer.ManyToOneRingBuffer; import org.agrona.concurrent.ringbuffer.RingBuffer; import org.agrona.concurrent.status.*; import java.io.*; import java.net.StandardSocketOptions; import java.net.URL; import java.nio.MappedByteBuffer; import java.nio.channels.DatagramChannel; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.ThreadFactory; import java.util.function.Consumer; import static io.aeron.driver.reports.LossReportUtil.mapLossReport; import static java.lang.Boolean.getBoolean; import static org.agrona.IoUtil.mapNewFile; import static io.aeron.CncFileDescriptor.*; import static io.aeron.driver.Configuration.*; import static io.aeron.driver.status.SystemCounterDescriptor.*; /** * Main class for JVM-based media driver * * Usage: * <code> * $ java -jar aeron-driver.jar * $ java -Doption=value -jar aeron-driver.jar * </code> * * {@link Configuration} */ public final class MediaDriver implements AutoCloseable { /** * Attempt to delete directories on start if they exist */ public static final String DIRS_DELETE_ON_START_PROP_NAME = "aeron.dir.delete.on.start"; private final AgentRunner sharedRunner; private final AgentRunner sharedNetworkRunner; private final AgentRunner conductorRunner; private final AgentRunner receiverRunner; private final AgentRunner senderRunner; private final AgentInvoker sharedInvoker; private final Context ctx; /** * Load system properties from a given filename or url. * * File is first searched for in resources, then file system, then URL. All are loaded if multiples found. * * @param filenameOrUrl that holds properties */ public static void loadPropertiesFile(final String filenameOrUrl) { final Properties properties = new Properties(System.getProperties()); try (InputStream in = MediaDriver.class.getClassLoader().getResourceAsStream(filenameOrUrl)) { properties.load(in); } catch (final Exception ignore) { } try (FileInputStream in = new FileInputStream(filenameOrUrl)) { properties.load(in); } catch (final Exception ignore) { } try (InputStream in = new URL(filenameOrUrl).openStream()) { properties.load(in); } catch (final Exception ignore) { } System.setProperties(properties); } /** * Load system properties from a given set of filenames or URLs. * * @param filenamesOrUrls that holds properties * @see #loadPropertiesFile(String) */ public static void loadPropertiesFiles(final String[] filenamesOrUrls) { for (final String filenameOrUrl : filenamesOrUrls) { loadPropertiesFile(filenameOrUrl); } } /** * Start Media Driver as a stand-alone process. * * @param args command line arguments * @throws Exception if an error occurs */ public static void main(final String[] args) throws Exception { loadPropertiesFiles(args); try (MediaDriver ignored = MediaDriver.launch()) { new ShutdownSignalBarrier().await(); System.out.println("Shutdown Driver..."); } } /** * Construct a media driver with the given ctx. * * @param ctx for the media driver parameters */ private MediaDriver(final Context ctx) { this.ctx = ctx; ctx.concludeAeronDirectory(); ensureDirectoryIsRecreated(ctx); validateSufficientSocketBufferLengths(ctx); ctx .driverCommandQueue(new ManyToOneConcurrentArrayQueue<>(CMD_QUEUE_CAPACITY)) .receiverCommandQueue(new OneToOneConcurrentArrayQueue<>(CMD_QUEUE_CAPACITY)) .senderCommandQueue(new OneToOneConcurrentArrayQueue<>(CMD_QUEUE_CAPACITY)) .conclude(); final Receiver receiver = new Receiver(ctx); final Sender sender = new Sender(ctx); final DriverConductor conductor = new DriverConductor(ctx); ctx.receiverProxy().receiver(receiver); ctx.senderProxy().sender(sender); ctx.driverConductorProxy().driverConductor(conductor); final AtomicCounter errorCounter = ctx.systemCounters().get(ERRORS); final ErrorHandler errorHandler = ctx.errorHandler(); switch (ctx.threadingMode) { case INVOKER: this.sharedInvoker = new AgentInvoker( errorHandler, errorCounter, new CompositeAgent(sender, receiver, conductor)); this.sharedRunner = null; this.sharedNetworkRunner = null; this.conductorRunner = null; this.receiverRunner = null; this.senderRunner = null; ctx.driverAgentInvoker = this.sharedInvoker; break; case SHARED: this.sharedRunner = new AgentRunner( ctx.sharedIdleStrategy, errorHandler, errorCounter, new CompositeAgent(sender, receiver, conductor)); this.sharedNetworkRunner = null; this.conductorRunner = null; this.receiverRunner = null; this.senderRunner = null; this.sharedInvoker = null; break; case SHARED_NETWORK: this.sharedNetworkRunner = new AgentRunner( ctx.sharedNetworkIdleStrategy, errorHandler, errorCounter, new CompositeAgent(sender, receiver)); this.conductorRunner = new AgentRunner( ctx.conductorIdleStrategy, errorHandler, errorCounter, conductor); this.sharedRunner = null; this.receiverRunner = null; this.senderRunner = null; this.sharedInvoker = null; break; default: case DEDICATED: this.senderRunner = new AgentRunner(ctx.senderIdleStrategy, errorHandler, errorCounter, sender); this.receiverRunner = new AgentRunner(ctx.receiverIdleStrategy, errorHandler, errorCounter, receiver); this.conductorRunner = new AgentRunner( ctx.conductorIdleStrategy, errorHandler, errorCounter, conductor); this.sharedNetworkRunner = null; this.sharedRunner = null; this.sharedInvoker = null; break; } } /** * Launch an isolated MediaDriver embedded in the current process with a generated aeronDirectoryName that can be * retrieved by calling aeronDirectoryName. * * @return the newly started MediaDriver. */ public static MediaDriver launchEmbedded() { return launchEmbedded(new Context()); } /** * Launch an isolated MediaDriver embedded in the current process with a provided configuration ctx and a generated * aeronDirectoryName (overwrites configured {@link Context#aeronDirectoryName()}) that can be retrieved by calling * aeronDirectoryName. * * If the aeronDirectoryName is configured then it will be used. * * @param ctx containing the configuration options. * @return the newly started MediaDriver. */ public static MediaDriver launchEmbedded(final Context ctx) { if (CommonContext.AERON_DIR_PROP_DEFAULT.equals(ctx.aeronDirectoryName())) { ctx.aeronDirectoryName(CommonContext.generateRandomDirName()); } return launch(ctx); } /** * Launch a MediaDriver embedded in the current process with default configuration. * * @return the newly started MediaDriver. */ public static MediaDriver launch() { return launch(new Context()); } /** * Launch a MediaDriver embedded in the current process and provided a configuration ctx. * * @param ctx containing the configuration options. * @return the newly created MediaDriver. */ public static MediaDriver launch(final Context ctx) { return new MediaDriver(ctx).start(); } /** * Shutdown the media driver by stopping all threads and freeing resources. */ public void close() { CloseHelper.quietClose(sharedRunner); CloseHelper.quietClose(sharedNetworkRunner); CloseHelper.quietClose(receiverRunner); CloseHelper.quietClose(senderRunner); CloseHelper.quietClose(conductorRunner); CloseHelper.quietClose(sharedInvoker); ctx.close(); } /** * Used to access the configured aeronDirectoryName for this MediaDriver, typically used after the * {@link #launchEmbedded()} method is used. * * @return the context aeronDirectoryName */ public String aeronDirectoryName() { return ctx.aeronDirectoryName(); } private MediaDriver start() { if (SystemUtil.osName().startsWith("win") && !HighResolutionTimer.isEnabled()) { HighResolutionTimer.enable(); } if (null != conductorRunner) { AgentRunner.startOnThread(conductorRunner, ctx.conductorThreadFactory); } if (null != senderRunner) { AgentRunner.startOnThread(senderRunner, ctx.senderThreadFactory); } if (null != receiverRunner) { AgentRunner.startOnThread(receiverRunner, ctx.receiverThreadFactory); } if (null != sharedNetworkRunner) { AgentRunner.startOnThread(sharedNetworkRunner, ctx.sharedNetworkThreadFactory); } if (null != sharedRunner) { AgentRunner.startOnThread(sharedRunner, ctx.sharedThreadFactory); } return this; } private static void validateSufficientSocketBufferLengths(final Context ctx) { try (DatagramChannel probe = DatagramChannel.open()) { final int defaultSoSndBuf = probe.getOption(StandardSocketOptions.SO_SNDBUF); probe.setOption(StandardSocketOptions.SO_SNDBUF, Integer.MAX_VALUE); final int maxSoSndBuf = probe.getOption(StandardSocketOptions.SO_SNDBUF); if (maxSoSndBuf < SOCKET_SNDBUF_LENGTH) { System.err.format( "WARNING: Could not get desired SO_SNDBUF, adjust OS buffer to match %s: attempted=%d, actual=%d%n", SOCKET_SNDBUF_LENGTH_PROP_NAME, SOCKET_SNDBUF_LENGTH, maxSoSndBuf); } probe.setOption(StandardSocketOptions.SO_RCVBUF, Integer.MAX_VALUE); final int maxSoRcvBuf = probe.getOption(StandardSocketOptions.SO_RCVBUF); if (maxSoRcvBuf < SOCKET_RCVBUF_LENGTH) { System.err.format( "WARNING: Could not get desired SO_RCVBUF, adjust OS buffer to match %s: attempted=%d, actual=%d%n", SOCKET_RCVBUF_LENGTH_PROP_NAME, SOCKET_RCVBUF_LENGTH, maxSoRcvBuf); } final int soSndBuf = 0 == SOCKET_SNDBUF_LENGTH ? defaultSoSndBuf : SOCKET_SNDBUF_LENGTH; if (ctx.mtuLength() > soSndBuf) { throw new ConfigurationException(String.format( "MTU greater than socket SO_SNDBUF, adjust %s to match MTU: mtuLength=%d, SO_SNDBUF=%d", SOCKET_SNDBUF_LENGTH_PROP_NAME, ctx.mtuLength(), soSndBuf)); } } catch (final IOException ex) { throw new RuntimeException("probe socket: " + ex.toString(), ex); } } private static void ensureDirectoryIsRecreated(final Context ctx) { if (ctx.aeronDirectory().isDirectory()) { if (ctx.warnIfDirectoriesExist()) { System.err.println("WARNING: " + ctx.aeronDirectory() + " already exists."); } if (!ctx.dirsDeleteOnStart()) { final Consumer<String> logProgress = ctx.warnIfDirectoriesExist() ? System.err::println : (s) -> {}; final MappedByteBuffer cncByteBuffer = ctx.mapExistingCncFile(logProgress); try { if (CommonContext.isDriverActive(ctx.driverTimeoutMs(), logProgress, cncByteBuffer)) { throw new ActiveDriverException("Active driver detected"); } reportExistingErrors(ctx, cncByteBuffer); } finally { IoUtil.unmap(cncByteBuffer); } } ctx.deleteAeronDirectory(); } IoUtil.ensureDirectoryExists(ctx.aeronDirectory(), "aeron"); } private static void reportExistingErrors(final Context ctx, final MappedByteBuffer cncByteBuffer) { try { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final int observations = ctx.saveErrorLog(new PrintStream(baos, false, "UTF-8"), cncByteBuffer); if (observations > 0) { final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSSZ"); final String errorLogFilename = ctx.aeronDirectoryName() + '-' + dateFormat.format(new Date()) + "-error.log"; System.err.println("WARNING: Existing errors saved to: " + errorLogFilename); try (FileOutputStream out = new FileOutputStream(errorLogFilename)) { baos.writeTo(out); } } } catch (final Exception ex) { LangUtil.rethrowUnchecked(ex); } } public static class Context extends CommonContext { private RawLogFactory rawLogFactory; private DataTransportPoller dataTransportPoller; private ControlTransportPoller controlTransportPoller; private FlowControlSupplier unicastFlowControlSupplier; private FlowControlSupplier multicastFlowControlSupplier; private EpochClock epochClock; private NanoClock nanoClock; private ManyToOneConcurrentArrayQueue<DriverConductorCmd> driverCommandQueue; private OneToOneConcurrentArrayQueue<ReceiverCmd> receiverCommandQueue; private OneToOneConcurrentArrayQueue<SenderCmd> senderCommandQueue; private ReceiverProxy receiverProxy; private SenderProxy senderProxy; private DriverConductorProxy driverConductorProxy; private IdleStrategy conductorIdleStrategy; private IdleStrategy senderIdleStrategy; private IdleStrategy receiverIdleStrategy; private IdleStrategy sharedNetworkIdleStrategy; private IdleStrategy sharedIdleStrategy; private ClientProxy clientProxy; private RingBuffer toDriverCommands; private DistinctErrorLog errorLog; private ErrorHandler errorHandler; private MappedByteBuffer lossReportBuffer; private LossReport lossReport; private MappedByteBuffer cncByteBuffer; private UnsafeBuffer cncMetaDataBuffer; private CountersManager countersManager; private SystemCounters systemCounters; private long imageLivenessTimeoutNs = Configuration.IMAGE_LIVENESS_TIMEOUT_NS; private long clientLivenessTimeoutNs = Configuration.CLIENT_LIVENESS_TIMEOUT_NS; private long publicationUnblockTimeoutNs = Configuration.PUBLICATION_UNBLOCK_TIMEOUT_NS; private Boolean termBufferSparseFile; private int publicationTermBufferLength; private int ipcPublicationTermBufferLength; private int maxTermBufferLength; private int initialWindowLength; private long statusMessageTimeout; private int mtuLength; private boolean warnIfDirectoriesExist; private boolean dirsDeleteOnStart; private ThreadingMode threadingMode; private ThreadFactory conductorThreadFactory; private ThreadFactory senderThreadFactory; private ThreadFactory receiverThreadFactory; private ThreadFactory sharedThreadFactory; private ThreadFactory sharedNetworkThreadFactory; private SendChannelEndpointSupplier sendChannelEndpointSupplier; private ReceiveChannelEndpointSupplier receiveChannelEndpointSupplier; private ReceiveChannelEndpointThreadLocals receiveChannelEndpointThreadLocals; private byte[] applicationSpecificFeedback = Configuration.SM_APPLICATION_SPECIFIC_FEEDBACK; private CongestionControlSupplier congestionControlSupplier; private AgentInvoker driverAgentInvoker; public Context() { publicationTermBufferLength(Configuration.termBufferLength()); maxTermBufferLength(Configuration.maxTermBufferLength()); initialWindowLength(Configuration.initialWindowLength()); statusMessageTimeout(Configuration.statusMessageTimeout()); mtuLength(Configuration.MTU_LENGTH); warnIfDirectoriesExist = true; dirsDeleteOnStart(getBoolean(DIRS_DELETE_ON_START_PROP_NAME)); } public Context conclude() { super.conclude(); try { concludeNullProperties(); Configuration.validateTermBufferLength(maxTermBufferLength); Configuration.validateTermBufferLength(publicationTermBufferLength); Configuration.validateTermBufferLength(ipcPublicationTermBufferLength); if (publicationTermBufferLength > maxTermBufferLength) { throw new ConfigurationException(String.format( "publication term buffer length %d greater than max length %d", publicationTermBufferLength, maxTermBufferLength)); } if (ipcPublicationTermBufferLength > maxTermBufferLength) { throw new ConfigurationException(String.format( "IPC publication term buffer length %d greater than max length %d", ipcPublicationTermBufferLength, maxTermBufferLength)); } Configuration.validateInitialWindowLength(initialWindowLength(), mtuLength()); cncByteBuffer = mapNewFile( cncFile(), CncFileDescriptor.computeCncFileLength( CONDUCTOR_BUFFER_LENGTH + TO_CLIENTS_BUFFER_LENGTH + COUNTERS_METADATA_BUFFER_LENGTH + COUNTERS_VALUES_BUFFER_LENGTH + ERROR_BUFFER_LENGTH)); cncMetaDataBuffer = CncFileDescriptor.createMetaDataBuffer(cncByteBuffer); CncFileDescriptor.fillMetaData( cncMetaDataBuffer, CONDUCTOR_BUFFER_LENGTH, TO_CLIENTS_BUFFER_LENGTH, COUNTERS_METADATA_BUFFER_LENGTH, COUNTERS_VALUES_BUFFER_LENGTH, clientLivenessTimeoutNs, ERROR_BUFFER_LENGTH); final BroadcastTransmitter transmitter = new BroadcastTransmitter(createToClientsBuffer(cncByteBuffer, cncMetaDataBuffer)); clientProxy(new ClientProxy(transmitter)); toDriverCommands(new ManyToOneRingBuffer(createToDriverBuffer(cncByteBuffer, cncMetaDataBuffer))); if (null == errorLog) { errorLog = new DistinctErrorLog(createErrorLogBuffer(cncByteBuffer, cncMetaDataBuffer), epochClock); } if (null == errorHandler) { errorHandler = (throwable) -> { if (!errorLog.record(throwable)) { System.err.println( "Error Log is full, consider increasing " + ERROR_BUFFER_LENGTH_PROP_NAME); throwable.printStackTrace(System.err); } }; } concludeCounters(); receiverProxy(new ReceiverProxy( threadingMode, receiverCommandQueue(), systemCounters.get(RECEIVER_PROXY_FAILS))); senderProxy(new SenderProxy( threadingMode, senderCommandQueue(), systemCounters.get(SENDER_PROXY_FAILS))); driverConductorProxy(new DriverConductorProxy( threadingMode, driverCommandQueue, systemCounters.get(CONDUCTOR_PROXY_FAILS))); rawLogBuffersFactory(new RawLogFactory( aeronDirectoryName(), maxTermBufferLength, termBufferSparseFile, errorLog)); if (null == lossReport) { lossReportBuffer = mapLossReport(aeronDirectoryName(), Configuration.LOSS_REPORT_BUFFER_LENGTH); lossReport = new LossReport(new UnsafeBuffer(lossReportBuffer)); } concludeIdleStrategies(); } catch (final Exception ex) { LangUtil.rethrowUnchecked(ex); } return this; } private void concludeNullProperties() { if (null == epochClock) { epochClock = new SystemEpochClock(); } if (null == nanoClock) { nanoClock = new SystemNanoClock(); } if (null == threadingMode) { threadingMode = Configuration.THREADING_MODE_DEFAULT; } if (null == unicastFlowControlSupplier) { unicastFlowControlSupplier = Configuration.unicastFlowControlSupplier(); } if (null == multicastFlowControlSupplier) { multicastFlowControlSupplier = Configuration.multicastFlowControlSupplier(); } if (0 == ipcPublicationTermBufferLength) { ipcPublicationTermBufferLength = Configuration.ipcTermBufferLength(publicationTermBufferLength()); } if (null == sendChannelEndpointSupplier) { sendChannelEndpointSupplier = Configuration.sendChannelEndpointSupplier(); } if (null == receiveChannelEndpointSupplier) { receiveChannelEndpointSupplier = Configuration.receiveChannelEndpointSupplier(); } if (null == dataTransportPoller) { dataTransportPoller = new DataTransportPoller(); } if (null == controlTransportPoller) { controlTransportPoller = new ControlTransportPoller(); } if (null == termBufferSparseFile) { if (null != Configuration.TERM_BUFFER_SPARSE_FILE) { termBufferSparseFile = Boolean.valueOf(Configuration.TERM_BUFFER_SPARSE_FILE); } else { termBufferSparseFile = Boolean.FALSE; } } if (null == conductorThreadFactory) { conductorThreadFactory = Thread::new; } if (null == senderThreadFactory) { senderThreadFactory = Thread::new; } if (null == receiverThreadFactory) { receiverThreadFactory = Thread::new; } if (null == sharedThreadFactory) { sharedThreadFactory = Thread::new; } if (null == sharedNetworkThreadFactory) { sharedNetworkThreadFactory = Thread::new; } if (null == receiveChannelEndpointThreadLocals) { receiveChannelEndpointThreadLocals = new ReceiveChannelEndpointThreadLocals(this); } if (null == congestionControlSupplier) { congestionControlSupplier = Configuration.congestionControlSupplier(); } } public Context epochClock(final EpochClock clock) { this.epochClock = clock; return this; } public Context nanoClock(final NanoClock clock) { this.nanoClock = clock; return this; } public Context driverCommandQueue(final ManyToOneConcurrentArrayQueue<DriverConductorCmd> queue) { this.driverCommandQueue = queue; return this; } public Context rawLogBuffersFactory(final RawLogFactory rawLogFactory) { this.rawLogFactory = rawLogFactory; return this; } public Context dataTransportPoller(final DataTransportPoller transportPoller) { this.dataTransportPoller = transportPoller; return this; } public Context controlTransportPoller(final ControlTransportPoller transportPoller) { this.controlTransportPoller = transportPoller; return this; } public Context unicastFlowControlSupplier(final FlowControlSupplier senderFlowControl) { this.unicastFlowControlSupplier = senderFlowControl; return this; } public Context multicastFlowControlSupplier(final FlowControlSupplier senderFlowControl) { this.multicastFlowControlSupplier = senderFlowControl; return this; } public Context receiverCommandQueue(final OneToOneConcurrentArrayQueue<ReceiverCmd> receiverCommandQueue) { this.receiverCommandQueue = receiverCommandQueue; return this; } public Context senderCommandQueue(final OneToOneConcurrentArrayQueue<SenderCmd> senderCommandQueue) { this.senderCommandQueue = senderCommandQueue; return this; } public Context receiverProxy(final ReceiverProxy receiverProxy) { this.receiverProxy = receiverProxy; return this; } public Context senderProxy(final SenderProxy senderProxy) { this.senderProxy = senderProxy; return this; } public Context driverConductorProxy(final DriverConductorProxy driverConductorProxy) { this.driverConductorProxy = driverConductorProxy; return this; } public Context conductorIdleStrategy(final IdleStrategy strategy) { this.conductorIdleStrategy = strategy; return this; } public Context senderIdleStrategy(final IdleStrategy strategy) { this.senderIdleStrategy = strategy; return this; } public Context receiverIdleStrategy(final IdleStrategy strategy) { this.receiverIdleStrategy = strategy; return this; } public Context sharedNetworkIdleStrategy(final IdleStrategy strategy) { this.sharedNetworkIdleStrategy = strategy; return this; } public Context sharedIdleStrategy(final IdleStrategy strategy) { this.sharedIdleStrategy = strategy; return this; } public Context clientProxy(final ClientProxy clientProxy) { this.clientProxy = clientProxy; return this; } public Context toDriverCommands(final RingBuffer toDriverCommands) { this.toDriverCommands = toDriverCommands; return this; } public Context countersManager(final CountersManager countersManager) { this.countersManager = countersManager; return this; } public Context termBufferSparseFile(final Boolean termBufferSparseFile) { this.termBufferSparseFile = termBufferSparseFile; return this; } public Context publicationTermBufferLength(final int termBufferLength) { this.publicationTermBufferLength = termBufferLength; return this; } public Context maxTermBufferLength(final int maxTermBufferLength) { this.maxTermBufferLength = maxTermBufferLength; return this; } public Context ipcTermBufferLength(final int ipcTermBufferLength) { this.ipcPublicationTermBufferLength = ipcTermBufferLength; return this; } public Context initialWindowLength(final int initialWindowLength) { this.initialWindowLength = initialWindowLength; return this; } public Context statusMessageTimeout(final long statusMessageTimeout) { this.statusMessageTimeout = statusMessageTimeout; return this; } public Context warnIfDirectoriesExist(final boolean value) { this.warnIfDirectoriesExist = value; return this; } public Context errorLog(final DistinctErrorLog errorLog) { this.errorLog = errorLog; return this; } public Context lossReport(final LossReport lossReport) { this.lossReport = lossReport; return this; } public Context imageLivenessTimeoutNs(final long timeout) { this.imageLivenessTimeoutNs = timeout; return this; } public Context clientLivenessTimeoutNs(final long timeout) { this.clientLivenessTimeoutNs = timeout; return this; } public Context publicationUnblockTimeoutNs(final long timeout) { this.publicationUnblockTimeoutNs = timeout; return this; } public Context systemCounters(final SystemCounters systemCounters) { this.systemCounters = systemCounters; return this; } public Context threadingMode(final ThreadingMode threadingMode) { this.threadingMode = threadingMode; return this; } public Context senderThreadFactory(final ThreadFactory factory) { this.senderThreadFactory = factory; return this; } public Context receiverThreadFactory(final ThreadFactory factory) { this.receiverThreadFactory = factory; return this; } public Context conductorThreadFactory(final ThreadFactory factory) { this.conductorThreadFactory = factory; return this; } public Context sharedThreadFactory(final ThreadFactory factory) { this.sharedThreadFactory = factory; return this; } public Context sharedNetworkThreadFactory(final ThreadFactory factory) { this.sharedNetworkThreadFactory = factory; return this; } /** * Set whether or not the driver will immediately attempt to delete the Aeron directories when starting. * * @param dirsDeleteOnStart Attempt deletion. * @return this Object for method chaining. */ public Context dirsDeleteOnStart(final boolean dirsDeleteOnStart) { this.dirsDeleteOnStart = dirsDeleteOnStart; return this; } /** * @see CommonContext#aeronDirectoryName(String) */ public Context aeronDirectoryName(final String dirName) { super.aeronDirectoryName(dirName); return this; } public Context sendChannelEndpointSupplier(final SendChannelEndpointSupplier supplier) { this.sendChannelEndpointSupplier = supplier; return this; } public Context receiveChannelEndpointSupplier(final ReceiveChannelEndpointSupplier supplier) { this.receiveChannelEndpointSupplier = supplier; return this; } public Context receiveChannelEndpointThreadLocals(final ReceiveChannelEndpointThreadLocals threadLocals) { this.receiveChannelEndpointThreadLocals = threadLocals; return this; } public Context applicationSpecificFeedback(final byte[] bytes) { this.applicationSpecificFeedback = bytes; return this; } public Context congestControlSupplier(final CongestionControlSupplier supplier) { this.congestionControlSupplier = supplier; return this; } public AgentInvoker driverAgentInvoker() { return driverAgentInvoker; } public EpochClock epochClock() { return epochClock; } public NanoClock nanoClock() { return nanoClock; } public ManyToOneConcurrentArrayQueue<DriverConductorCmd> driverCommandQueue() { return driverCommandQueue; } public RawLogFactory rawLogBuffersFactory() { return rawLogFactory; } public DataTransportPoller dataTransportPoller() { return dataTransportPoller; } public ControlTransportPoller controlTransportPoller() { return controlTransportPoller; } public FlowControlSupplier unicastFlowControlSupplier() { return unicastFlowControlSupplier; } public FlowControlSupplier multicastFlowControlSupplier() { return multicastFlowControlSupplier; } public OneToOneConcurrentArrayQueue<ReceiverCmd> receiverCommandQueue() { return receiverCommandQueue; } public OneToOneConcurrentArrayQueue<SenderCmd> senderCommandQueue() { return senderCommandQueue; } public ReceiverProxy receiverProxy() { return receiverProxy; } public SenderProxy senderProxy() { return senderProxy; } public DriverConductorProxy driverConductorProxy() { return driverConductorProxy; } public IdleStrategy conductorIdleStrategy() { return conductorIdleStrategy; } public IdleStrategy senderIdleStrategy() { return senderIdleStrategy; } public IdleStrategy receiverIdleStrategy() { return receiverIdleStrategy; } public IdleStrategy sharedNetworkIdleStrategy() { return sharedNetworkIdleStrategy; } public IdleStrategy sharedIdleStrategy() { return sharedIdleStrategy; } public ThreadFactory senderThreadFactory() { return this.senderThreadFactory; } public ThreadFactory receiverThreadFactory() { return this.receiverThreadFactory; } public ThreadFactory conductorThreadFactory() { return this.conductorThreadFactory; } public ThreadFactory sharedThreadFactory() { return this.sharedThreadFactory; } public ThreadFactory sharedNetworkThreadFactory() { return this.sharedNetworkThreadFactory; } public ClientProxy clientProxy() { return clientProxy; } public RingBuffer toDriverCommands() { return toDriverCommands; } public CountersManager countersManager() { return countersManager; } public long imageLivenessTimeoutNs() { return imageLivenessTimeoutNs; } public long clientLivenessTimeoutNs() { return clientLivenessTimeoutNs; } public long publicationUnblockTimeoutNs() { return publicationUnblockTimeoutNs; } public int publicationTermBufferLength() { return publicationTermBufferLength; } public int maxTermBufferLength() { return maxTermBufferLength; } public int ipcTermBufferLength() { return ipcPublicationTermBufferLength; } public int initialWindowLength() { return initialWindowLength; } public long statusMessageTimeout() { return statusMessageTimeout; } public boolean warnIfDirectoriesExist() { return warnIfDirectoriesExist; } public ErrorHandler errorHandler() { return errorHandler; } public Context errorHandler(final ErrorHandler errorHandler) { this.errorHandler = errorHandler; return this; } public DistinctErrorLog errorLog() { return errorLog; } public LossReport lossReport() { return lossReport; } public int mtuLength() { return mtuLength; } public CommonContext mtuLength(final int mtuLength) { Configuration.validateMtuLength(mtuLength); this.mtuLength = mtuLength; return this; } public SystemCounters systemCounters() { return systemCounters; } /** * Get whether or not the driver will immediately attempt to delete the Aeron directories when starting. * * @return true when directories will be deleted, otherwise false. */ public boolean dirsDeleteOnStart() { return dirsDeleteOnStart; } public SendChannelEndpointSupplier sendChannelEndpointSupplier() { return sendChannelEndpointSupplier; } public ReceiveChannelEndpointSupplier receiveChannelEndpointSupplier() { return receiveChannelEndpointSupplier; } public ReceiveChannelEndpointThreadLocals receiveChannelEndpointThreadLocals() { return receiveChannelEndpointThreadLocals; } public byte[] applicationSpecificFeedback() { return applicationSpecificFeedback; } public CongestionControlSupplier congestionControlSupplier() { return congestionControlSupplier; } public void close() { // do not close the systemsCounters so that all counters are kept as is. IoUtil.unmap(cncByteBuffer); IoUtil.unmap(lossReportBuffer); super.close(); } private void concludeCounters() { if (countersManager() == null) { if (countersMetaDataBuffer() == null) { countersMetaDataBuffer(createCountersMetaDataBuffer(cncByteBuffer, cncMetaDataBuffer)); } if (countersValuesBuffer() == null) { countersValuesBuffer(createCountersValuesBuffer(cncByteBuffer, cncMetaDataBuffer)); } countersManager(new CountersManager(countersMetaDataBuffer(), countersValuesBuffer())); } if (null == systemCounters) { systemCounters = new SystemCounters(countersManager); } } private void concludeIdleStrategies() { final StatusIndicator controllableIdleStrategyStatus = new UnsafeBufferStatusIndicator(countersManager.valuesBuffer(), CONTROLLABLE_IDLE_STRATEGY.id()); if (null == conductorIdleStrategy) { conductorIdleStrategy(Configuration.conductorIdleStrategy(controllableIdleStrategyStatus)); } if (null == senderIdleStrategy) { senderIdleStrategy(Configuration.senderIdleStrategy(controllableIdleStrategyStatus)); } if (null == receiverIdleStrategy) { receiverIdleStrategy(Configuration.receiverIdleStrategy(controllableIdleStrategyStatus)); } if (null == sharedNetworkIdleStrategy) { sharedNetworkIdleStrategy(Configuration.sharedNetworkIdleStrategy(controllableIdleStrategyStatus)); } if (null == sharedIdleStrategy) { sharedIdleStrategy(Configuration.sharedIdleStrategy(controllableIdleStrategyStatus)); } } } }