internal ClientConductor( IEpochClock epochClock, INanoClock nanoClock, CopyBroadcastReceiver broadcastReceiver, ILogBuffersFactory logBuffersFactory, UnsafeBuffer counterValuesBuffer, DriverProxy driverProxy, ErrorHandler errorHandler, AvailableImageHandler availableImageHandler, UnavailableImageHandler unavailableImageHandler, long keepAliveIntervalNs, long driverTimeoutMs, long interServiceTimeoutNs, long publicationConnectionTimeoutMs) { _epochClock = epochClock; _nanoClock = nanoClock; _timeOfLastKeepalive = nanoClock.NanoTime(); _timeOfLastCheckResources = nanoClock.NanoTime(); _timeOfLastWork = nanoClock.NanoTime(); _errorHandler = errorHandler; _counterValuesBuffer = counterValuesBuffer; _driverProxy = driverProxy; _logBuffersFactory = logBuffersFactory; _availableImageHandler = availableImageHandler; _unavailableImageHandler = unavailableImageHandler; _keepAliveIntervalNs = keepAliveIntervalNs; _driverTimeoutMs = driverTimeoutMs; _driverTimeoutNs = NanoUtil.FromMilliseconds(driverTimeoutMs); _interServiceTimeoutNs = interServiceTimeoutNs; _publicationConnectionTimeoutMs = publicationConnectionTimeoutMs; _driverListener = new DriverListenerAdapter(broadcastReceiver, this); }
internal ClientConductor(Aeron.Context ctx) { _ctx = ctx; _clientLock = ctx.ClientLock(); _epochClock = ctx.EpochClock(); _nanoClock = ctx.NanoClock(); _errorHandler = ctx.ErrorHandler(); _counterValuesBuffer = ctx.CountersValuesBuffer(); _driverProxy = ctx.DriverProxy(); _logBuffersFactory = ctx.LogBuffersFactory(); _imageMapMode = ctx.ImageMapMode(); _keepAliveIntervalNs = ctx.KeepAliveInterval(); _driverTimeoutMs = ctx.DriverTimeoutMs(); _driverTimeoutNs = _driverTimeoutMs * 1000000; _interServiceTimeoutNs = ctx.InterServiceTimeout(); _publicationConnectionTimeoutMs = ctx.PublicationConnectionTimeout(); _driverListener = new DriverListenerAdapter(ctx.ToClientBuffer(), this); _driverAgentInvoker = ctx.DriverAgentInvoker(); long nowNs = _nanoClock.NanoTime(); _timeOfLastKeepaliveNs = nowNs; _timeOfLastCheckResourcesNs = nowNs; _timeOfLastWorkNs = nowNs; }
internal ClusteredServiceAgent(ClusteredServiceContainer.Context ctx) { this.ctx = ctx; archiveCtx = ctx.ArchiveContext(); aeron = ctx.Aeron(); service = ctx.ClusteredService(); idleStrategy = ctx.IdleStrategy(); serviceId = ctx.ServiceId(); epochClock = ctx.EpochClock(); markFile = ctx.MarkFile(); var channel = ctx.ServiceControlChannel(); _consensusModuleProxy = new ConsensusModuleProxy(aeron.AddPublication(channel, ctx.ConsensusModuleStreamId())); _serviceAdapter = new ServiceAdapter(aeron.AddSubscription(channel, ctx.ServiceStreamId()), this); UnsafeBuffer headerBuffer = new UnsafeBuffer(new byte[SESSION_HEADER_LENGTH]); _egressMessageHeaderEncoder.WrapAndApplyHeader(headerBuffer, 0, new MessageHeaderEncoder()); _vectors[0] = new DirectBufferVector(headerBuffer, 0, SESSION_HEADER_LENGTH); _vectors[1] = _messageVector; }
internal ClientConductor(Aeron.Context ctx) { _ctx = ctx; _clientLock = ctx.ClientLock(); _epochClock = ctx.EpochClock(); _nanoClock = ctx.NanoClock(); _driverProxy = ctx.DriverProxy(); _logBuffersFactory = ctx.LogBuffersFactory(); _keepAliveIntervalNs = ctx.KeepAliveInterval(); _driverTimeoutMs = ctx.DriverTimeoutMs(); _driverTimeoutNs = _driverTimeoutMs * 1000000; _interServiceTimeoutNs = ctx.InterServiceTimeout(); _defaultAvailableImageHandler = ctx.AvailableImageHandler(); _defaultUnavailableImageHandler = ctx.UnavailableImageHandler(); _availableCounterHandler = ctx.AvailableCounterHandler(); _unavailableCounterHandler = ctx.UnavailableCounterHandler(); _driverEventsAdapter = new DriverEventsAdapter(ctx.ToClientBuffer(), this); _counterValuesBuffer = ctx.CountersValuesBuffer(); _countersReader = new CountersReader(ctx.CountersMetaDataBuffer(), ctx.CountersValuesBuffer(), Encoding.ASCII); long nowNs = _nanoClock.NanoTime(); _timeOfLastKeepAliveNs = nowNs; _timeOfLastResourcesCheckNs = nowNs; _timeOfLastServiceNs = nowNs; }
internal ClientConductor(Aeron.Context ctx) { _clientLock = ctx.ClientLock(); _epochClock = ctx.EpochClock(); _nanoClock = ctx.NanoClock(); _errorHandler = ctx.ErrorHandler(); _counterValuesBuffer = ctx.CountersValuesBuffer(); _driverProxy = ctx.DriverProxy(); _logBuffersFactory = ctx.LogBuffersFactory(); _imageMapMode = ctx.ImageMapMode(); _keepAliveIntervalNs = ctx.KeepAliveInterval(); _driverTimeoutMs = ctx.DriverTimeoutMs(); _driverTimeoutNs = _driverTimeoutMs * 1000000; _interServiceTimeoutNs = ctx.InterServiceTimeout(); _publicationConnectionTimeoutMs = ctx.PublicationConnectionTimeout(); _defaultAvailableImageHandler = ctx.AvailableImageHandler(); _defaultUnavailableImageHandler = ctx.UnavailableImageHandler(); _driverEventsAdapter = new DriverEventsAdapter(ctx.ToClientBuffer(), this); long nowNs = _nanoClock.NanoTime(); _timeOfLastKeepAliveNs = nowNs; _timeOfLastResourcesCheckNs = nowNs; _timeOfLastServiceNs = nowNs; }
public ClusterMarkFile( FileInfo file, ClusterComponentType type, int errorBufferLength, IEpochClock epochClock, long timeoutMs) { var markFileExists = file.Exists; markFile = new MarkFile( file, markFileExists, MarkFileHeaderDecoder.VersionEncodingOffset(), MarkFileHeaderDecoder.ActivityTimestampEncodingOffset(), HEADER_LENGTH + errorBufferLength, timeoutMs, epochClock, (version) => { if (version != MarkFileHeaderDecoder.SCHEMA_VERSION) { throw new ClusterException("mark file version " + version + " does not match software:" + MarkFileHeaderDecoder.SCHEMA_VERSION); } }, null); buffer = markFile.Buffer(); errorBuffer = new UnsafeBuffer(buffer, HEADER_LENGTH, errorBufferLength); headerEncoder.Wrap(buffer, 0); headerDecoder.Wrap(buffer, 0, MarkFileHeaderDecoder.BLOCK_LENGTH, MarkFileHeaderDecoder.SCHEMA_VERSION); if (markFileExists) { var existingErrorBuffer = new UnsafeBuffer( buffer, headerDecoder.HeaderLength(), headerDecoder.ErrorBufferLength()); SaveExistingErrors(file, existingErrorBuffer, Console.Error); errorBuffer.SetMemory(0, errorBufferLength, 0); } else { headerEncoder.CandidateTermId(Aeron.Aeron.NULL_VALUE); } var existingType = headerDecoder.ComponentType(); if (existingType != ClusterComponentType.NULL && existingType != type) { throw new InvalidOperationException("existing Mark file type " + existingType + " not same as required type " + type); } headerEncoder.ComponentType(type); headerEncoder.HeaderLength(HEADER_LENGTH); headerEncoder.ErrorBufferLength(errorBufferLength); headerEncoder.Pid(Process.GetCurrentProcess().Id); headerEncoder.StartTimestamp(epochClock.Time()); }
internal ClusteredServiceAgent(ClusteredServiceContainer.Context ctx) { this.ctx = ctx; headerVector = new DirectBufferVector(headerBuffer, 0, headerBuffer.Capacity); abortHandler = Abort; archiveCtx = ctx.ArchiveContext(); aeron = ctx.Aeron(); aeronAgentInvoker = ctx.Aeron().ConductorAgentInvoker; service = ctx.ClusteredService(); idleStrategy = ctx.IdleStrategy(); serviceId = ctx.ServiceId(); epochClock = ctx.EpochClock(); markFile = ctx.MarkFile(); var channel = ctx.ServiceControlChannel(); _consensusModuleProxy = new ConsensusModuleProxy(aeron.AddPublication(channel, ctx.ConsensusModuleStreamId())); _serviceAdapter = new ServiceAdapter(aeron.AddSubscription(channel, ctx.ServiceStreamId()), this); _sessionMessageHeaderEncoder.WrapAndApplyHeader(headerBuffer, 0, new MessageHeaderEncoder()); aeron.AddCloseHandler(abortHandler); }
/// <summary> /// Create a new counter buffer manager over two buffers. /// </summary> /// <param name="metaDataBuffer"> containing the types, keys, and labels for the counters. </param> /// <param name="valuesBuffer"> containing the values of the counters themselves. </param> public CountersManager(IAtomicBuffer metaDataBuffer, IAtomicBuffer valuesBuffer) : base(metaDataBuffer, valuesBuffer) { valuesBuffer.VerifyAlignment(); _epochClock = new NullEpochClock(); if (metaDataBuffer.Capacity < valuesBuffer.Capacity * 2) { throw new ArgumentException("Meta data buffer not sufficiently large"); } }
/// <summary> /// Create a new counter buffer manager over two buffers. /// </summary> /// <param name="metaDataBuffer"> containing the types, keys, and labels for the counters. </param> /// <param name="valuesBuffer"> containing the values of the counters themselves. </param> /// <param name="labelCharset"> for the label encoding. </param> /// <param name="epochClock"> to use for determining time for keep counter from being reused after being freed. </param> /// <param name="freeToReuseTimeoutMs"> timeout (in milliseconds) to keep counter from being reused after being freed. </param> public CountersManager(IAtomicBuffer metaDataBuffer, IAtomicBuffer valuesBuffer, Encoding labelCharset, IEpochClock epochClock, long freeToReuseTimeoutMs) : base(metaDataBuffer, valuesBuffer, labelCharset) { valuesBuffer.VerifyAlignment(); _epochClock = epochClock; _freeToReuseTimeoutMs = freeToReuseTimeoutMs; if (metaDataBuffer.Capacity < (valuesBuffer.Capacity * 2)) { throw new ArgumentException("Meta data buffer not sufficiently large"); } }
/// <summary> /// Map a pre-existing CnC file if one present and is active. /// /// Total length of CnC file will be mapped until <seealso cref="#close()"/> is called. /// </summary> /// <param name="directory"> for the CnC file </param> /// <param name="filename"> of the CnC file </param> /// <param name="versionFieldOffset"> to use for version field access </param> /// <param name="timestampFieldOffset"> to use for timestamp field access </param> /// <param name="timeoutMs"> for the activity check (in milliseconds) and for how long to wait for file to exist </param> /// <param name="epochClock"> to use for time checks </param> /// <param name="versionCheck"> to use for existing CnC file and version field </param> /// <param name="logger"> to use to signal progress or null </param> public MarkFile(DirectoryInfo directory, string filename, int versionFieldOffset, int timestampFieldOffset, long timeoutMs, IEpochClock epochClock, Action <int> versionCheck, Action <string> logger) { ValidateOffsets(versionFieldOffset, timestampFieldOffset); this.parentDir = directory; this.markFile = new FileInfo(Path.Combine(directory.FullName, filename)); this.mappedBuffer = MapExistingCncFile(markFile, versionFieldOffset, timestampFieldOffset, timeoutMs, epochClock, versionCheck, logger); this.buffer = new UnsafeBuffer(mappedBuffer); this.versionFieldOffset = versionFieldOffset; this.timestampFieldOffset = timestampFieldOffset; }
public ClusterMarkFile(DirectoryInfo directory, string filename, IEpochClock epochClock, long timeoutMs, Action <string> logger) { markFile = new MarkFile(directory, filename, MarkFileHeaderDecoder.VersionEncodingOffset(), MarkFileHeaderDecoder.ActivityTimestampEncodingOffset(), timeoutMs, epochClock, (version) => { if (version != MarkFileHeaderDecoder.SCHEMA_VERSION) { throw new ArgumentException("Mark file version " + version + " does not match software:" + MarkFileHeaderDecoder.SCHEMA_VERSION); } }, logger); buffer = markFile.Buffer(); headerDecoder.Wrap(buffer, 0, MarkFileHeaderDecoder.BLOCK_LENGTH, MarkFileHeaderDecoder.SCHEMA_VERSION); }
public static MappedByteBuffer MapNewOrExistingCncFile(FileInfo cncFile, bool shouldPreExist, int versionFieldOffset, int timestampFieldOffset, long totalFileLength, long timeoutMs, IEpochClock epochClock, Action <int> versionCheck, Action <string> logger) { MappedByteBuffer cncByteBuffer = null; try { cncByteBuffer = IoUtil.MapNewOrExixtingFile(cncFile, totalFileLength); UnsafeBuffer cncBuffer = new UnsafeBuffer(cncByteBuffer); if (shouldPreExist) { int cncVersion = cncBuffer.GetIntVolatile(versionFieldOffset); if (null != logger) { logger("INFO: CnC file exists: " + cncFile); } versionCheck(cncVersion); long timestamp = cncBuffer.GetLongVolatile(timestampFieldOffset); long now = epochClock.Time(); long timestampAge = now - timestamp; if (null != logger) { logger("INFO: heartbeat is (ms): " + timestampAge); } if (timestampAge < timeoutMs) { throw new System.InvalidOperationException("Active CnC file detected"); } } } catch (Exception) { if (null != cncByteBuffer) { IoUtil.Unmap(cncByteBuffer); } throw; } return(cncByteBuffer); }
/// <summary> /// Create a CnC file if none present. Checking if an active CnC file exists and is active. Existing CnC file /// is used if not active. /// /// Total length of CnC file will be mapped until <seealso cref="#close()"/> is called. /// </summary> /// <param name="markFile"> to use </param> /// <param name="shouldPreExist"> or not </param> /// <param name="versionFieldOffset"> to use for version field access </param> /// <param name="timestampFieldOffset"> to use for timestamp field access </param> /// <param name="totalFileLength"> to allocate when creating new CnC file </param> /// <param name="timeoutMs"> for the activity check (in milliseconds) </param> /// <param name="epochClock"> to use for time checks </param> /// <param name="versionCheck"> to use for existing CnC file and version field </param> /// <param name="logger"> to use to signal progress or null </param> public MarkFile(FileInfo markFile, bool shouldPreExist, int versionFieldOffset, int timestampFieldOffset, int totalFileLength, long timeoutMs, IEpochClock epochClock, Action <int> versionCheck, Action <string> logger) { ValidateOffsets(versionFieldOffset, timestampFieldOffset); this.parentDir = markFile.Directory; this.markFile = markFile; this.mappedBuffer = MapNewOrExistingCncFile(markFile, shouldPreExist, versionFieldOffset, timestampFieldOffset, totalFileLength, timeoutMs, epochClock, versionCheck, logger); this.buffer = new UnsafeBuffer(mappedBuffer.Pointer, totalFileLength); this.versionFieldOffset = versionFieldOffset; this.timestampFieldOffset = timestampFieldOffset; }
/// <summary> /// Create a CnC directory and file if none present. Checking if an active CnC file exists and is active. Old CnC /// file is deleted and recreated if not active. /// /// Total length of CnC file will be mapped until <seealso cref="#close()"/> is called. /// </summary> /// <param name="directory"> for the CnC file </param> /// <param name="filename"> of the CnC file </param> /// <param name="warnIfDirectoryExists"> for logging purposes </param> /// <param name="dirDeleteOnStart"> if desired </param> /// <param name="versionFieldOffset"> to use for version field access </param> /// <param name="timestampFieldOffset"> to use for timestamp field access </param> /// <param name="totalFileLength"> to allocate when creating new CnC file </param> /// <param name="timeoutMs"> for the activity check (in milliseconds) </param> /// <param name="epochClock"> to use for time checks </param> /// <param name="versionCheck"> to use for existing CnC file and version field </param> /// <param name="logger"> to use to signal progress or null </param> public MarkFile(DirectoryInfo directory, string filename, bool warnIfDirectoryExists, bool dirDeleteOnStart, int versionFieldOffset, int timestampFieldOffset, int totalFileLength, long timeoutMs, IEpochClock epochClock, Action <int> versionCheck, Action <string> logger) { ValidateOffsets(versionFieldOffset, timestampFieldOffset); EnsureDirectoryExists(directory, filename, warnIfDirectoryExists, dirDeleteOnStart, versionFieldOffset, timestampFieldOffset, timeoutMs, epochClock, versionCheck, logger); this.parentDir = directory; this.markFile = new FileInfo(Path.Combine(directory.Name, filename)); this.mappedBuffer = MapNewFile(markFile, totalFileLength); this.buffer = new UnsafeBuffer(mappedBuffer.Pointer, totalFileLength); this.versionFieldOffset = versionFieldOffset; this.timestampFieldOffset = timestampFieldOffset; }
internal ClusteredServiceAgent(ClusteredServiceContainer.Context ctx) { this.ctx = ctx; archiveCtx = ctx.ArchiveContext(); aeron = ctx.Aeron(); service = ctx.ClusteredService(); idleStrategy = ctx.IdleStrategy(); serviceId = ctx.ServiceId(); epochClock = ctx.EpochClock(); markFile = ctx.MarkFile(); var channel = ctx.ServiceControlChannel(); _consensusModuleProxy = new ConsensusModuleProxy(aeron.AddPublication(channel, ctx.ConsensusModuleStreamId())); _serviceAdapter = new ServiceAdapter(aeron.AddSubscription(channel, ctx.ServiceStreamId()), this); }
internal ClientConductor(Aeron.Context ctx, Aeron aeron) { _ctx = ctx; _aeron = aeron; _clientLock = ctx.ClientLock(); _epochClock = ctx.EpochClock(); _nanoClock = ctx.NanoClock(); _awaitingIdleStrategy = ctx.AwaitingIdleStrategy(); _driverProxy = ctx.DriverProxy(); _logBuffersFactory = ctx.LogBuffersFactory(); _keepAliveIntervalNs = ctx.KeepAliveIntervalNs(); _driverTimeoutMs = ctx.DriverTimeoutMs(); _driverTimeoutNs = _driverTimeoutMs * 1000000; _interServiceTimeoutNs = ctx.InterServiceTimeoutNs(); _defaultAvailableImageHandler = ctx.AvailableImageHandler(); _defaultUnavailableImageHandler = ctx.UnavailableImageHandler(); _driverEventsAdapter = new DriverEventsAdapter(ctx.ToClientBuffer(), ctx.ClientId(), this, _asyncCommandIdSet); _driverAgentInvoker = ctx.DriverAgentInvoker(); _counterValuesBuffer = ctx.CountersValuesBuffer(); _countersReader = new CountersReader(ctx.CountersMetaDataBuffer(), ctx.CountersValuesBuffer(), Encoding.ASCII); if (null != ctx.AvailableCounterHandler()) { _availableCounterHandlers.Add(ctx.AvailableCounterHandler()); } if (null != ctx.UnavailableCounterHandler()) { _unavailableCounterHandlers.Add(ctx.UnavailableCounterHandler()); } if (null != ctx.CloseHandler()) { _closeHandlers.Add(ctx.CloseHandler()); } long nowNs = _nanoClock.NanoTime(); _timeOfLastKeepAliveNs = nowNs; _timeOfLastServiceNs = nowNs; }
internal ClusteredServiceAgent(ClusteredServiceContainer.Context ctx) { this.ctx = ctx; archiveCtx = ctx.ArchiveContext(); aeron = ctx.Aeron(); shouldCloseResources = ctx.OwnsAeronClient(); service = ctx.ClusteredService(); recordingLog = ctx.RecordingLog(); idleStrategy = ctx.IdleStrategy(); serviceId = ctx.ServiceId(); epochClock = ctx.EpochClock(); markFile = ctx.MarkFile(); var channel = ctx.ServiceControlChannel(); var streamId = ctx.ServiceControlStreamId(); serviceControlPublisher = new ServiceControlPublisher(aeron.AddPublication(channel, streamId)); serviceControlAdapter = new ServiceControlAdapter(aeron.AddSubscription(channel, streamId), this); }
public static void EnsureDirectoryExists(DirectoryInfo directory, string filename, bool warnIfDirectoryExists, bool dirDeleteOnStart, int versionFieldOffset, int timestampFieldOffset, long timeoutMs, IEpochClock epochClock, Action <int> versionCheck, Action <string> logger) { FileInfo cncFile = new FileInfo(Path.Combine(directory.FullName, filename)); if (directory.Exists) { if (warnIfDirectoryExists && null != logger) { logger("WARNING: " + directory + " already exists."); } if (!dirDeleteOnStart) { int offset = Math.Min(versionFieldOffset, timestampFieldOffset); int length = Math.Max(versionFieldOffset, timestampFieldOffset) + BitUtil.SIZE_OF_LONG - offset; MappedByteBuffer cncByteBuffer = MapExistingFile(cncFile, logger, offset, length); try { if (IsActive(cncByteBuffer, epochClock, timeoutMs, versionFieldOffset, timestampFieldOffset, versionCheck, logger)) { throw new System.InvalidOperationException("Active CnC file detected"); } } finally { IoUtil.Unmap(cncByteBuffer); } } IoUtil.Delete(directory, false); } IoUtil.EnsureDirectoryExists(directory, directory.ToString()); }
public ClusterMarkFile(DirectoryInfo directory, string filename, IEpochClock epochClock, long timeoutMs, Action <string> logger) { markFile = new MarkFile( directory, filename, MarkFileHeaderDecoder.VersionEncodingOffset(), MarkFileHeaderDecoder.ActivityTimestampEncodingOffset(), timeoutMs, epochClock, (version) => { if (SemanticVersion.Major(version) != AeronCluster.Configuration.MAJOR_VERSION) { throw new ArgumentException("mark file major version " + SemanticVersion.Major(version) + " does not match software:" + AeronCluster.Configuration.MAJOR_VERSION); } }, logger); buffer = markFile.Buffer(); headerDecoder.Wrap(buffer, 0, MarkFileHeaderDecoder.BLOCK_LENGTH, MarkFileHeaderDecoder.SCHEMA_VERSION); errorBuffer = new UnsafeBuffer(buffer, headerDecoder.HeaderLength(), headerDecoder.ErrorBufferLength()); }
public static bool IsActive(MappedByteBuffer cncByteBuffer, IEpochClock epochClock, long timeoutMs, int versionFieldOffset, int timestampFieldOffset, Action <int> versionCheck, Action <string> logger) { if (null == cncByteBuffer) { return(false); } UnsafeBuffer cncBuffer = new UnsafeBuffer(cncByteBuffer); long startTimeMs = epochClock.Time(); int cncVersion; while (0 == (cncVersion = cncBuffer.GetIntVolatile(versionFieldOffset))) { if (epochClock.Time() > (startTimeMs + timeoutMs)) { throw new System.InvalidOperationException("CnC file is created but not initialised."); } Sleep(1); } versionCheck(cncVersion); long timestamp = cncBuffer.GetLongVolatile(timestampFieldOffset); long now = epochClock.Time(); long timestampAge = now - timestamp; if (null != logger) { logger("INFO: heartbeat is (ms): " + timestampAge); } return(timestampAge <= timeoutMs); }
/// <summary> /// Create a <seealso cref="ReplayMerge"/> to manage the merging of a replayed stream and switching over to live stream as /// appropriate. /// </summary> /// <param name="subscription"> to use for the replay and live stream. Must be a multi-destination subscription. </param> /// <param name="archive"> to use for the replay. </param> /// <param name="replayChannel"> to use for the replay. </param> /// <param name="replayDestination"> to send the replay to and the destination added by the <seealso cref="Subscription"/>. </param> /// <param name="liveDestination"> for the live stream and the destination added by the <seealso cref="Subscription"/>. </param> /// <param name="recordingId"> for the replay. </param> /// <param name="startPosition"> for the replay. </param> /// <param name="epochClock"> to use for progress checks. </param> /// <param name="mergeProgressTimeoutMs"> to use for progress checks. </param> public ReplayMerge(Subscription subscription, AeronArchive archive, string replayChannel, string replayDestination, string liveDestination, long recordingId, long startPosition, IEpochClock epochClock, long mergeProgressTimeoutMs) { if (subscription.Channel.StartsWith(IPC_CHANNEL) || replayChannel.StartsWith(IPC_CHANNEL) || replayDestination.StartsWith(IPC_CHANNEL) || liveDestination.StartsWith(IPC_CHANNEL)) { throw new System.ArgumentException("IPC merging is not supported"); } ChannelUri subscriptionChannelUri = ChannelUri.Parse(subscription.Channel); if (!MDC_CONTROL_MODE_MANUAL.Equals(subscriptionChannelUri.Get(MDC_CONTROL_MODE_PARAM_NAME))) { throw new ArgumentException("Subscription must have manual control-mode: control-mode=" + subscriptionChannelUri.Get(MDC_CONTROL_MODE_PARAM_NAME)); } ChannelUri replayChannelUri = ChannelUri.Parse(replayChannel); replayChannelUri.Put(LINGER_PARAM_NAME, "0"); replayChannelUri.Put(EOS_PARAM_NAME, "false"); this.archive = archive; this.subscription = subscription; this.epochClock = epochClock; this.replayDestination = replayDestination; this.replayChannel = replayChannelUri.ToString(); this.liveDestination = liveDestination; this.recordingId = recordingId; this.startPosition = startPosition; this.timeOfLastProgressMs = epochClock.Time(); this.mergeProgressTimeoutMs = mergeProgressTimeoutMs; subscription.AsyncAddDestination(replayDestination); }
/// <summary> /// This is called automatically by <seealso cref="Connect()"/> and its overloads. /// There is no need to call it from a client application. It is responsible for providing default /// values for options that are not individually changed through field setters. /// </summary> /// <returns> this Aeron.Context for method chaining. </returns> public Context Conclude() { try { _cncFile = new FileInfo(Path.Combine(_aeronDirectoryName, CncFileDescriptor.CNC_FILE)); if (_epochClock == null) { _epochClock = new SystemEpochClock(); } if (_nanoClock == null) { _nanoClock = new SystemNanoClock(); } if (_idleStrategy == null) { _idleStrategy = new SleepingIdleStrategy(IdleSleepMs); } if (CncFile() != null) { _cncByteBuffer = IoUtil.MapExistingFile(CncFile().FullName); _cncMetaDataBuffer = CncFileDescriptor.CreateMetaDataBuffer(_cncByteBuffer); var cncVersion = _cncMetaDataBuffer.GetInt(CncFileDescriptor.CncVersionOffset(0)); if (CncFileDescriptor.CNC_VERSION != cncVersion) { throw new InvalidOperationException( "aeron cnc file version not understood: version=" + cncVersion); } } if (_toClientBuffer == null) { var receiver = new BroadcastReceiver(CncFileDescriptor.CreateToClientsBuffer(_cncByteBuffer, _cncMetaDataBuffer)); _toClientBuffer = new CopyBroadcastReceiver(receiver); } if (_toDriverBuffer == null) { _toDriverBuffer = new ManyToOneRingBuffer(CncFileDescriptor.CreateToDriverBuffer(_cncByteBuffer, _cncMetaDataBuffer)); } if (CountersMetaDataBuffer() == null) { CountersMetaDataBuffer(CncFileDescriptor.CreateCountersMetaDataBuffer(_cncByteBuffer, _cncMetaDataBuffer)); } if (CountersValuesBuffer() == null) { CountersValuesBuffer(CncFileDescriptor.CreateCountersValuesBuffer(_cncByteBuffer, _cncMetaDataBuffer)); } _interServiceTimeout = CncFileDescriptor.ClientLivenessTimeout(_cncMetaDataBuffer); if (_logBuffersFactory == null) { _logBuffersFactory = new MappedLogBuffersFactory(); } if (_errorHandler == null) { _errorHandler = DEFAULT_ERROR_HANDLER; } if (_availableImageHandler == null) { _availableImageHandler = image => { }; } if (_unavailableImageHandler == null) { _unavailableImageHandler = image => { }; } } catch ( Exception ex) { Console.WriteLine("***"); Console.WriteLine("***"); Console.WriteLine("Failed to connect to the Media Driver - is it currently running?"); Console.WriteLine("***"); Console.WriteLine("***"); throw new InvalidOperationException("Could not initialise communication buffers", ex); } return(this); }
public ClusterMarkFile( FileInfo file, ClusterComponentType type, int errorBufferLength, IEpochClock epochClock, long timeoutMs) { var markFileExists = file.Exists; markFile = new MarkFile( file, markFileExists, MarkFileHeaderDecoder.VersionEncodingOffset(), MarkFileHeaderDecoder.ActivityTimestampEncodingOffset(), HEADER_LENGTH + errorBufferLength, timeoutMs, epochClock, (version) => { if (VERSION_FAILED == version && markFileExists) { Console.WriteLine("mark file version -1 indicates error on previous startup."); } else if (SemanticVersion.Major(version) != AeronCluster.Configuration.MAJOR_VERSION) { throw new ArgumentException("mark file major version " + SemanticVersion.Major(version) + " does not match software:" + AeronCluster.Configuration.MAJOR_VERSION); } }, null); buffer = markFile.Buffer(); errorBuffer = new UnsafeBuffer(buffer, HEADER_LENGTH, errorBufferLength); headerEncoder.Wrap(buffer, 0); headerDecoder.Wrap(buffer, 0, MarkFileHeaderDecoder.BLOCK_LENGTH, MarkFileHeaderDecoder.SCHEMA_VERSION); if (markFileExists) { var existingErrorBuffer = new UnsafeBuffer( buffer, headerDecoder.HeaderLength(), headerDecoder.ErrorBufferLength()); SaveExistingErrors(file, existingErrorBuffer, Console.Error); errorBuffer.SetMemory(0, errorBufferLength, 0); } else { headerEncoder.CandidateTermId(Aeron.Aeron.NULL_VALUE); } var existingType = headerDecoder.ComponentType(); if (existingType != ClusterComponentType.NULL && existingType != type) { if (existingType != ClusterComponentType.BACKUP || ClusterComponentType.CONSENSUS_MODULE != type) { throw new InvalidOperationException( "existing Mark file type " + existingType + " not same as required type " + type); } } headerEncoder.ComponentType(type); headerEncoder.HeaderLength(HEADER_LENGTH); headerEncoder.ErrorBufferLength(errorBufferLength); headerEncoder.Pid(Process.GetCurrentProcess().Id); headerEncoder.StartTimestamp(epochClock.Time()); }
/// <summary> /// Create a new error log that will be written to a provided <seealso cref="IAtomicBuffer"/>. /// </summary> /// <param name="buffer"> into which the observation records are recorded. </param> /// <param name="clock"> to be used for time stamping records. </param> public DistinctErrorLog(IAtomicBuffer buffer, IEpochClock clock) { buffer.VerifyAlignment(); _clock = clock; _buffer = buffer; }
public void Conclude() { if (null == threadFactory) { threadFactory = new DefaultThreadFactory(); } if (null == idleStrategySupplier) { idleStrategySupplier = Configuration.IdleStrategySupplier(null); } if (null == epochClock) { epochClock = new SystemEpochClock(); } if (null == errorHandler) { throw new InvalidOperationException("Error handler must be supplied"); } if (null == aeron) { aeron = Adaptive.Aeron.Aeron.Connect( new Aeron.Aeron.Context() .AeronDirectoryName(aeronDirectoryName) .ErrorHandler(countedErrorHandler.OnError) .EpochClock(epochClock)); if (null == errorCounter) { errorCounter = aeron.AddCounter(SYSTEM_COUNTER_TYPE_ID, "Cluster errors - service " + serviceId); } ownsAeronClient = true; } if (null == errorCounter) { throw new InvalidOperationException("Error counter must be supplied"); } if (null == countedErrorHandler) { countedErrorHandler = new CountedErrorHandler(errorHandler, errorCounter); if (ownsAeronClient) { aeron.Ctx().ErrorHandler(countedErrorHandler.OnError); } } if (null == archiveContext) { archiveContext = new AeronArchive.Context() .ControlRequestChannel(AeronArchive.Configuration.LocalControlChannel()) .ControlResponseChannel(AeronArchive.Configuration.LocalControlChannel()) .ControlRequestStreamId(AeronArchive.Configuration.LocalControlStreamId()); } archiveContext .AeronClient(aeron) .OwnsAeronClient(false) .Lock(new NoOpLock()); if (deleteDirOnStart) { if (null != clusteredServiceDir) { IoUtil.Delete(clusteredServiceDir, true); } else { IoUtil.Delete(new DirectoryInfo(Configuration.ClusteredServiceDirName()), true); } } if (null == clusteredServiceDir) { clusteredServiceDir = new DirectoryInfo(clusteredServiceDirectoryName); } if (!clusteredServiceDir.Exists) { Directory.CreateDirectory(clusteredServiceDir.FullName); } if (null == recordingLog) { recordingLog = new RecordingLog(clusteredServiceDir); } if (null == shutdownSignalBarrier) { shutdownSignalBarrier = new ShutdownSignalBarrier(); } if (null == terminationHook) { terminationHook = () => shutdownSignalBarrier.Signal(); } if (null == clusteredService) { string className = Config.GetProperty(Configuration.SERVICE_CLASS_NAME_PROP_NAME); if (null == className) { throw new InvalidOperationException("Either a ClusteredService instance or class name for the service must be provided"); } clusteredService = (IClusteredService)Activator.CreateInstance(Type.GetType(className)); } ConcludeMarkFile(); }
/// <summary> /// Set the <seealso cref="EpochClock"/> to be used for tracking wall clock time when interacting with the archive. /// </summary> /// <param name="clock"> <seealso cref="EpochClock"/> to be used for tracking wall clock time when interacting with the archive. </param> /// <returns> this for a fluent API. </returns> public Context EpochClock(IEpochClock clock) { this.epochClock = clock; return(this); }
public void Conclude() { if (serviceId < 0) { throw new ConfigurationException("service id must be not be negative: " + serviceId); } if (null == threadFactory) { threadFactory = new DefaultThreadFactory(); } if (null == idleStrategySupplier) { idleStrategySupplier = Configuration.IdleStrategySupplier(null); } if (null == epochClock) { epochClock = new SystemEpochClock(); } if (null == clusterDir) { clusterDir = new DirectoryInfo(clusteredServiceDirectoryName); } if (!clusterDir.Exists) { Directory.CreateDirectory(clusterDir.FullName); } if (null == markFile) { markFile = new ClusterMarkFile( new FileInfo(Path.Combine(clusterDir.FullName, ClusterMarkFile.MarkFilenameForService(serviceId))), ClusterComponentType.CONTAINER, errorBufferLength, epochClock, 0); } if (null == errorLog) { errorLog = new DistinctErrorLog(markFile.ErrorBuffer, epochClock); } if (null == errorHandler) { errorHandler = new LoggingErrorHandler(errorLog).OnError; // TODO Use interface } if (null == aeron) { aeron = Adaptive.Aeron.Aeron.Connect( new Aeron.Aeron.Context() .AeronDirectoryName(aeronDirectoryName) .ErrorHandler(errorHandler) .EpochClock(epochClock)); ownsAeronClient = true; } if (null == errorCounter) { errorCounter = aeron.AddCounter(SYSTEM_COUNTER_TYPE_ID, "Cluster errors - service " + serviceId); } if (null == countedErrorHandler) { countedErrorHandler = new CountedErrorHandler(errorHandler, errorCounter); if (ownsAeronClient) { aeron.Ctx().ErrorHandler(countedErrorHandler.OnError); } } if (null == archiveContext) { archiveContext = new AeronArchive.Context() .ControlRequestChannel(AeronArchive.Configuration.LocalControlChannel()) .ControlResponseChannel(AeronArchive.Configuration.LocalControlChannel()) .ControlRequestStreamId(AeronArchive.Configuration.LocalControlStreamId()); } archiveContext .AeronClient(aeron) .OwnsAeronClient(false) .Lock(new NoOpLock()); if (null == shutdownSignalBarrier) { shutdownSignalBarrier = new ShutdownSignalBarrier(); } if (null == terminationHook) { terminationHook = () => shutdownSignalBarrier.Signal(); } if (null == clusteredService) { string className = Config.GetProperty(Configuration.SERVICE_CLASS_NAME_PROP_NAME); if (null == className) { throw new ClusterException("either a ClusteredService instance or class name for the service must be provided"); } clusteredService = (IClusteredService)Activator.CreateInstance(Type.GetType(className)); } ConcludeMarkFile(); }
/// <summary> /// Set the <seealso cref="EpochClock"/> to be used for tracking wall clock time when interacting with the driver. /// </summary> /// <param name="clock"> <seealso cref="EpochClock"/> to be used for tracking wall clock time when interacting with the driver. </param> /// <returns> this Aeron.Context for method chaining </returns> public Context EpochClock(IEpochClock clock) { _epochClock = clock; return this; }
public static MappedByteBuffer MapExistingCncFile(FileInfo cncFile, int versionFieldOffset, int timestampFieldOffset, long timeoutMs, IEpochClock epochClock, Action <int> versionCheck, Action <string> logger) { long startTimeMs = epochClock.Time(); while (true) { while (!cncFile.Exists) { if (epochClock.Time() > (startTimeMs + timeoutMs)) { throw new InvalidOperationException("CnC file not found: " + cncFile.FullName); } Sleep(16); } MappedByteBuffer cncByteBuffer = MapExistingFile(cncFile, logger); UnsafeBuffer cncBuffer = new UnsafeBuffer(cncByteBuffer); int cncVersion; while (0 == (cncVersion = cncBuffer.GetIntVolatile(versionFieldOffset))) { if (epochClock.Time() > (startTimeMs + timeoutMs)) { throw new InvalidOperationException("CnC file is created but not initialised."); } Sleep(1); } versionCheck(cncVersion); while (0 == cncBuffer.GetLongVolatile(timestampFieldOffset)) { if (epochClock.Time() > (startTimeMs + timeoutMs)) { throw new InvalidOperationException("No non-0 timestamp detected."); } Sleep(1); } return(cncByteBuffer); } }
public ClusterMarkFile(FileInfo file, ClusterComponentType type, int totalFileLength, IEpochClock epochClock, long timeoutMs) { markFile = new MarkFile(file, file.Exists, MarkFileHeaderDecoder.VersionEncodingOffset(), MarkFileHeaderDecoder.ActivityTimestampEncodingOffset(), totalFileLength, timeoutMs, epochClock, (version) => { if (version != MarkFileHeaderDecoder.SCHEMA_VERSION) { throw new ArgumentException("Mark file version " + version + " does not match software:" + MarkFileHeaderDecoder.SCHEMA_VERSION); } }, null); buffer = markFile.Buffer(); headerEncoder.Wrap(buffer, 0); headerDecoder.Wrap(buffer, 0, MarkFileHeaderDecoder.BLOCK_LENGTH, MarkFileHeaderDecoder.SCHEMA_VERSION); var existingType = headerDecoder.ComponentType(); if (existingType != ClusterComponentType.NULL && existingType != type) { throw new InvalidOperationException("existing Mark file type " + existingType + " not same as required type " + type); } headerEncoder.ComponentType(type); headerEncoder.Pid(Process.GetCurrentProcess().Id); }
/// <summary> /// This is called automatically by <seealso cref="Connect()"/> and its overloads. /// There is no need to call it from a client application. It is responsible for providing default /// values for options that are not individually changed through field setters. /// </summary> /// <returns> this Aeron.Context for method chaining. </returns> public Context Conclude() { try { _cncFile = new FileInfo(Path.Combine(_aeronDirectoryName, CncFileDescriptor.CNC_FILE)); if (_epochClock == null) { _epochClock = new SystemEpochClock(); } if (_nanoClock == null) { _nanoClock = new SystemNanoClock(); } if (_idleStrategy == null) { _idleStrategy = new SleepingIdleStrategy(IdleSleepMs); } if (CncFile() != null) { _cncByteBuffer = IoUtil.MapExistingFile(CncFile().FullName); _cncMetaDataBuffer = CncFileDescriptor.CreateMetaDataBuffer(_cncByteBuffer); var cncVersion = _cncMetaDataBuffer.GetInt(CncFileDescriptor.CncVersionOffset(0)); if (CncFileDescriptor.CNC_VERSION != cncVersion) { throw new InvalidOperationException( "aeron cnc file version not understood: version=" + cncVersion); } } if (_toClientBuffer == null) { var receiver = new BroadcastReceiver(CncFileDescriptor.CreateToClientsBuffer(_cncByteBuffer, _cncMetaDataBuffer)); _toClientBuffer = new CopyBroadcastReceiver(receiver); } if (_toDriverBuffer == null) { _toDriverBuffer = new ManyToOneRingBuffer(CncFileDescriptor.CreateToDriverBuffer(_cncByteBuffer, _cncMetaDataBuffer)); } if (CountersMetaDataBuffer() == null) { CountersMetaDataBuffer(CncFileDescriptor.CreateCountersMetaDataBuffer(_cncByteBuffer, _cncMetaDataBuffer)); } if (CountersValuesBuffer() == null) { CountersValuesBuffer(CncFileDescriptor.CreateCountersValuesBuffer(_cncByteBuffer, _cncMetaDataBuffer)); } _interServiceTimeout = CncFileDescriptor.ClientLivenessTimeout(_cncMetaDataBuffer); if (_logBuffersFactory == null) { _logBuffersFactory = new MappedLogBuffersFactory(); } if (_errorHandler == null) { _errorHandler = DEFAULT_ERROR_HANDLER; } if (_availableImageHandler == null) { _availableImageHandler = image => { }; } if (_unavailableImageHandler == null) { _unavailableImageHandler = image => { }; } } catch ( Exception ex) { Console.WriteLine("***"); Console.WriteLine("***"); Console.WriteLine("Failed to connect to the Media Driver - is it currently running?"); Console.WriteLine("***"); Console.WriteLine("***"); throw new InvalidOperationException("Could not initialise communication buffers", ex); } return this; }
/// <summary> /// This is called automatically by <seealso cref="Connect()"/> and its overloads. /// There is no need to call it from a client application. It is responsible for providing default /// values for options that are not individually changed through field setters. /// </summary> /// <returns> this Aeron.Context for method chaining. </returns> public Context Conclude() { _cncFile = new FileInfo(Path.Combine(_aeronDirectoryName, CncFileDescriptor.CNC_FILE)); if (_epochClock == null) { _epochClock = new SystemEpochClock(); } if (_nanoClock == null) { _nanoClock = new SystemNanoClock(); } if (_idleStrategy == null) { _idleStrategy = new SleepingIdleStrategy(IdleSleepMs); } if (CncFile() != null) { ConnectToDriver(); } if (_toClientBuffer == null) { var receiver = new BroadcastReceiver(CncFileDescriptor.CreateToClientsBuffer(_cncByteBuffer, _cncMetaDataBuffer)); _toClientBuffer = new CopyBroadcastReceiver(receiver); } if (_toDriverBuffer == null) { _toDriverBuffer = new ManyToOneRingBuffer(CncFileDescriptor.CreateToDriverBuffer(_cncByteBuffer, _cncMetaDataBuffer)); } if (CountersMetaDataBuffer() == null) { CountersMetaDataBuffer(CncFileDescriptor.CreateCountersMetaDataBuffer(_cncByteBuffer, _cncMetaDataBuffer)); } if (CountersValuesBuffer() == null) { CountersValuesBuffer(CncFileDescriptor.CreateCountersValuesBuffer(_cncByteBuffer, _cncMetaDataBuffer)); } _interServiceTimeout = CncFileDescriptor.ClientLivenessTimeout(_cncMetaDataBuffer); if (_logBuffersFactory == null) { _logBuffersFactory = new MappedLogBuffersFactory(); } if (_errorHandler == null) { _errorHandler = DEFAULT_ERROR_HANDLER; } if (_availableImageHandler == null) { _availableImageHandler = image => { }; } if (_unavailableImageHandler == null) { _unavailableImageHandler = image => { }; } return(this); }