/** * Construct a media driver with the given context. * * @param context for the media driver parameters */ private MediaDriver(final Context context) { this.ctx = context; ensureDirectoryIsRecreated(context); validateSufficientSocketBufferLengths(context); context .toConductorFromReceiverCommandQueue(new OneToOneConcurrentArrayQueue<>(CMD_QUEUE_CAPACITY)) .toConductorFromSenderCommandQueue(new OneToOneConcurrentArrayQueue<>(CMD_QUEUE_CAPACITY)) .receiverCommandQueue(new OneToOneConcurrentArrayQueue<>(CMD_QUEUE_CAPACITY)) .senderCommandQueue(new OneToOneConcurrentArrayQueue<>(CMD_QUEUE_CAPACITY)) .conclude(); final Receiver receiver = new Receiver(context); final Sender sender = new Sender(context); final DriverConductor conductor = new DriverConductor(context); context.receiverProxy().receiver(receiver); context.senderProxy().sender(sender); context.fromReceiverDriverConductorProxy().driverConductor(conductor); context.fromSenderDriverConductorProxy().driverConductor(conductor); context.toDriverCommands().consumerHeartbeatTime(context.epochClock().time()); final AtomicCounter errorCounter = context.systemCounters().errors(); final ErrorHandler errorHandler = context.errorHandler(); switch (context.threadingMode) { case SHARED: runners = Collections.singletonList( new AgentRunner( context.sharedIdleStrategy, errorHandler, errorCounter, new CompositeAgent(sender, receiver, conductor))); break; case SHARED_NETWORK: runners = Arrays.asList( new AgentRunner( context.sharedNetworkIdleStrategy, errorHandler, errorCounter, new CompositeAgent(sender, receiver)), new AgentRunner( context.conductorIdleStrategy, errorHandler, errorCounter, conductor)); break; default: case DEDICATED: runners = Arrays.asList( new AgentRunner(context.senderIdleStrategy, errorHandler, errorCounter, sender), new AgentRunner(context.receiverIdleStrategy, errorHandler, errorCounter, receiver), new AgentRunner( context.conductorIdleStrategy, errorHandler, errorCounter, conductor)); } }
private void ensureDirectoryIsRecreated(final Context ctx) { final File aeronDir = new File(ctx.dirName()); Consumer<String> logProgress = (message) -> {}; if (aeronDir.exists()) { if (ctx.warnIfDirectoriesExist()) { System.err.println("WARNING: " + aeronDir + " already exists."); logProgress = System.err::println; } if (ctx.dirsDeleteOnStart()) { ctx.deleteAeronDirectory(); } else { final boolean driverActive = ctx.isDriverActive(ctx.driverTimeoutMs(), logProgress); if (driverActive) { throw new ActiveDriverException("active driver detected"); } ctx.deleteAeronDirectory(); } } final BiConsumer<String, String> callback = (path, name) -> { if (ctx.warnIfDirectoriesExist()) { System.err.println("WARNING: " + name + " directory already exists: " + path); } }; IoUtil.ensureDirectoryIsRecreated(aeronDir, "aeron", callback); }
/** Shutdown the media driver by stopping all threads and freeing resources. */ public void close() { try { runners.forEach(AgentRunner::close); freeSocketsForReuseOnWindows(); ctx.close(); } catch (final Exception ex) { LangUtil.rethrowUnchecked(ex); } }
private static void validateSufficientSocketBufferLengths(final Context ctx) { try (final 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 < Configuration.SOCKET_SNDBUF_LENGTH) { System.err.format( "WARNING: Could not get desired SO_SNDBUF: attempted=%d, actual=%d\n", Configuration.SOCKET_SNDBUF_LENGTH, maxSoSndBuf); } probe.setOption(StandardSocketOptions.SO_RCVBUF, Integer.MAX_VALUE); final int maxSoRcvBuf = probe.getOption(StandardSocketOptions.SO_RCVBUF); if (maxSoRcvBuf < Configuration.SOCKET_RCVBUF_LENGTH) { System.err.format( "WARNING: Could not get desired SO_RCVBUF: attempted=%d, actual=%d\n", Configuration.SOCKET_RCVBUF_LENGTH, maxSoRcvBuf); } final int soSndBuf = (0 == Configuration.SOCKET_SNDBUF_LENGTH) ? defaultSoSndBuf : Configuration.SOCKET_SNDBUF_LENGTH; if (ctx.mtuLength() > soSndBuf) { throw new ConfigurationException( String.format( "MTU greater than socket SO_SNDBUF: mtuLength=%d, SO_SNDBUF=%d", ctx.mtuLength(), soSndBuf)); } } catch (final IOException ex) { throw new RuntimeException(String.format("probe socket: %s", ex.toString()), ex); } }
private void freeSocketsForReuseOnWindows() { ctx.receiverTransportPoller().selectNowWithoutProcessing(); ctx.senderTransportPoller().selectNowWithoutProcessing(); }
/** * Used to access the configured dirName for this MediaDriver Context typically used after the * {@link #launchEmbedded()} method is used. * * @return the context dirName */ public String contextDirName() { return ctx.dirName(); }
/** * Launch an isolated MediaDriver embedded in the current process with a provided configuration * context and a generated dirName (overwrites configured dirName) that can be retrieved by * calling contextDirName. * * @param ctx containing the configuration options. * @return the newly started MediaDriver. */ public static MediaDriver launchEmbedded(final Context ctx) { ctx.dirName(CommonContext.generateRandomDirName()); return launch(ctx); }
/** * 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(); }
/** * Launch an isolated MediaDriver embedded in the current process with a provided configuration * context and a generated aeronDirectoryName (overwrites configured aeronDirectoryName) that can * be retrieved by calling aeronDirectoryName. * * @param context containing the configuration options. * @return the newly started MediaDriver. */ public static MediaDriver launchEmbedded(final Context context) { context.aeronDirectoryName(CommonContext.generateRandomDirName()); return launch(context); }