protected virtual void Dispose(bool disposing) { if (disposed != null && !disposed.EnsureCalledOnce()) { if (disposing) { SafeLog(LogLevel.Trace, () => "Disposing {0} (disposing:{1})".Fmt(GetType(), disposing)); } if (IsConnected) { if (tcpClient != null) { tcpClient.Close(); tcpClient = null; SafeLog(LogLevel.Trace, () => "TcpClient closed"); } } var localCopy = Disposed; if (localCopy != null) { localCopy(this, EventArgs.Empty); } SafeLog(LogLevel.Debug, () => "{0} ({1}) Disposed".Fmt(GetType(), id)); } }
protected virtual void Dispose(bool disposing) { if (disposed != null && !disposed.EnsureCalledOnce()) { if (disposing) { SafeLog(LogLevel.Trace, "Disposing {0} (disposing:{1})".Fmt(GetType(), disposing)); } if (IsConnected) { readCancellationToken.Cancel(); if (tcpClient != null) { tcpClient.Close(); tcpClient = null; SafeLog(LogLevel.Trace, "TcpClient closed"); } } var localCopy = Disposed; localCopy?.Invoke(this, EventArgs.Empty); SafeLog(LogLevel.Debug, "{0} ({1}) Disposed".Fmt(GetType(), id)); } }
/// <summary> /// Starts observing commits and dispatching them.. /// </summary> /// <returns></returns> public async Task Start() { if (_isStarted.EnsureCalledOnce()) { return; } string checkpointToken = await _checkpointRepository.Get(); /* string checkpointToken = null; * await _retryPolicy.Retry(async () => checkpointToken = await _checkpointRepository.Get(), _disposed.Token); //TODO should have different retry policy? */ _subscription = _eventStoreClient.Subscribe(checkpointToken, async commit => { try { await _retryPolicy.Retry(() => _dispatchCommit(commit, _disposed.Token), _disposed.Token); await _retryPolicy.Retry(() => _checkpointRepository.Put(commit.CheckpointToken), _disposed.Token); } catch (Exception ex) { Logger.ErrorException( Messages.ExceptionHasOccuredWhenDispatchingACommit.FormatWith(commit.ToString()), ex); _projectedCommits.OnError(ex); throw; } _projectedCommits.OnNext(commit); }); }
protected virtual void Dispose(bool disposing) { if (disposed != null && !disposed.EnsureCalledOnce()) { if (disposing) { Console.WriteLine("Disposing {0} (disposing:{1})".Fmt(GetType(), disposing)); } if (IsConnected) { readCancellationToken.Cancel(); if (tcpClient != null) { tcpClient.Close(); tcpClient = null; Console.WriteLine("TcpClient closed"); } } var localCopy = Disposed; if (localCopy != null) { localCopy(this, EventArgs.Empty); } Console.WriteLine("{0} ({1}) Disposed".Fmt(GetType(), id)); } }
/// <summary> /// Starts observing commits and dispatching them.. /// </summary> /// <returns></returns> public async Task Start() { if (_isStarted.EnsureCalledOnce()) { return; } string checkpointToken = await _checkpointRepository.Get(); _subscription = _eventStoreClient.Subscribe(checkpointToken, async commit => { try { await _dispatchCommit(commit, _disposed.Token); await _checkpointRepository.Put(commit.CheckpointToken); } catch (Exception ex) { Logger.ErrorException( ExtensionMethods.FormatWith(Messages.ExceptionHasOccuredWhenDispatchingACommit, new[] { commit.ToString() }), ex); _projectedCommits.OnError(ex); throw; } _projectedCommits.OnNext(commit); }); }
protected virtual void Dispose(bool disposing) { if (disposed != null && !disposed.EnsureCalledOnce()) { if (disposing) { if (!Disposables.IsDisposed) { Disposables.Dispose(); } OtherLeg?.Dispose(); bridgedChannelsSubject.Dispose(); } if (eventSocket != null && eventSocket is OutboundSocket) { // todo: should we close the socket associated with the channel here? eventSocket.Dispose(); } eventSocket = null; Log.Debug(() => "Channel Disposed."); } base.Dispose(disposing); }
/// <summary> /// Releases unmanaged and - optionally - managed resources. /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (disposed != null && !disposed.EnsureCalledOnce()) { log.LogTrace("Disposing (disposing:{0})".Fmt(disposing)); if (disposing) { listenerTermination.OnNext(Unit.Default); listenerTermination.Dispose(); if (subscription != null) { subscription.Dispose(); subscription = null; } disposables.Dispose(); connections?.ToList().ForEach(connection => connection?.Dispose()); observable.OnCompleted(); observable.Dispose(); if (tcpListener != null) { tcpListener.Stop(); tcpListener = null; } } log.LogTrace("Disposed"); } }
public void Dispose() { if (_isDisposed.EnsureCalledOnce()) { return; } _durableCommitDispatcher.Dispose(); _storeEvents.Dispose(); }
protected virtual void Dispose(bool disposing) { if (disposed != null && !disposed.EnsureCalledOnce()) { if (buffer != null) { StringBuilderPool.Free(buffer); buffer = null; } } }
private static void PreventThreadPoolStarvationWhenRunningTestsInParallel() { if (Initialized.EnsureCalledOnce()) { return; } // doing this to avoid thread starvation when running tests in parallel eg. nCrunch, AppVeyor int maxThreads; int maxIoPorts; System.Threading.ThreadPool.GetMaxThreads(out maxThreads, out maxIoPorts); System.Threading.ThreadPool.SetMaxThreads(maxThreads * 2, maxIoPorts * 2); }
protected virtual void Dispose(bool disposing) { if (disposed != null && disposed.EnsureCalledOnce()) { if (disposing) { if (Disposables != null) { Disposables.Dispose(); } } Log.Debug(() => "BasicChannel Disposed."); } }
protected virtual void Dispose(bool disposing) { if (disposed != null && disposed.EnsureCalledOnce()) { if (disposing) { if (Disposables != null) { Disposables.Dispose(); } } Console.WriteLine("BasicChannel Disposed."); } }
private void UpdateTokens() { if (_updatingTokens.EnsureCalledOnce()) { return; } var currentTime = _getUtcNow().Ticks; if (currentTime >= _nextRefillTime) { Interlocked.Exchange(ref _tokens, _getBucketTokenCapacty()); _nextRefillTime = currentTime + _refillIntervalTicks; } _updatingTokens.Set(false); }
protected override void Dispose(bool disposing) { if (disposed != null && !disposed.EnsureCalledOnce()) { if (disposing) { // cancel any outgoing network sends if (cts != null) { cts.Cancel(); } } } base.Dispose(disposing); }
/// <summary> /// Initializes a new instance of the <see cref="ObservableSocket"/> class. /// </summary> /// <param name="tcpClient">The TCP client to wrap.</param> protected ObservableSocket(TcpClient tcpClient) { id = Interlocked.Increment(ref IdCounter); this.tcpClient = tcpClient; subject = new Subject <byte[]>(); receiver = Observable.Defer( () => { if (isStarted.EnsureCalledOnce()) { return(subject.AsObservable()); } Task.Run( async() => { Console.WriteLine("{0} Worker Thread {1} started".Fmt(GetType(), id)); int bytesRead = 1; var stream = tcpClient.GetStream(); byte[] buffer = SharedPools.ByteArray.Allocate(); try { while (bytesRead > 0) { bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, readCancellationToken.Token); if (bytesRead > 0) { if (bytesRead == buffer.Length) { subject.OnNext(buffer); } else { subject.OnNext(buffer.Take(bytesRead).ToArray()); } } else { subject.OnCompleted(); } } } catch (ObjectDisposedException) { //expected - normal shutdown subject.OnCompleted(); } catch (TaskCanceledException) { //expected - normal shutdown subject.OnCompleted(); } catch (IOException ex) { if (ex.InnerException is ObjectDisposedException) { //expected - normal shutdown subject.OnCompleted(); } else { //socket comms interrupted - propogate the error up the layers Console.WriteLine("IO Error reading from stream", ex); subject.OnError(ex); } } catch (SocketException ex) { //socket comms interrupted - propogate the error up the layers Console.WriteLine("Socket Error reading from stream", ex); subject.OnError(ex); } catch (Exception ex) { //unexpected error Console.WriteLine("Unexpected Error reading from stream", ex); subject.OnError(ex); } finally { SharedPools.ByteArray.Free(buffer); Console.WriteLine("{0} Worker Thread {1} completed".Fmt(GetType(), id)); Dispose(); } }); return(subject.AsObservable()); }); }
private void InitializeSubscriptions() { if (initialized.EnsureCalledOnce()) { Log.Warn(() => "Channel already initialized"); return; } Disposables.Add( eventSocket.ChannelEvents.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelBridge && x.OtherLegUUID != bridgedUUID) .Subscribe( async x => { Log.Info(() => "Channel [{0}] Bridged to [{1}] CHANNEL_BRIDGE".Fmt(UUID, x.GetHeader(HeaderNames.OtherLegUniqueId))); var apiResponse = await eventSocket.Api("uuid_dump", x.OtherLegUUID); if (apiResponse.Success && apiResponse.BodyText != "+OK") { var eventMessage = new ChannelEvent(apiResponse); bridgedChannelsSubject.OnNext(new BridgedChannel(eventMessage, eventSocket)); } else { Log.Error(() => "Unable to get CHANNEL_DATA info from 'api uuid_dump {0}' - received '{1}'.".Fmt(x.OtherLegUUID, apiResponse.BodyText)); } })); Disposables.Add( eventSocket.ChannelEvents.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelUnbridge && x.GetVariable("bridge_hangup_cause") != null) .Subscribe( x => { /* side effects: * the att_xfer application is evil * if after speaking to C, B presses '#' to cancel, * the A channel fires an unbridge event, even though it is still bridged to B * in this case, bridge_hangup_cause will be empty so we'll ignore those events * however, this may break if this channel has had any completed bridges before this. */ Log.Info( () => "Channel [{0}] Unbridged from [{1}] {2}".Fmt( UUID, x.GetVariable("last_bridge_to"), x.GetVariable("bridge_hangup_cause"))); bridgedChannelsSubject.OnNext(null); //clears out OtherLeg })); Disposables.Add(BridgedChannels.Subscribe( async b => { if (bridgedUUID != null && bridgedUUID != b.UUID) { await eventSocket.FilterDelete(HeaderNames.UniqueId, bridgedUUID).ConfigureAwait(false); await eventSocket.FilterDelete(HeaderNames.OtherLegUniqueId, bridgedUUID).ConfigureAwait(false); await eventSocket.FilterDelete(HeaderNames.ChannelCallUniqueId, bridgedUUID).ConfigureAwait(false); } bridgedUUID = b.UUID; await eventSocket.Filter(HeaderNames.UniqueId, bridgedUUID).ConfigureAwait(false); await eventSocket.Filter(HeaderNames.OtherLegUniqueId, bridgedUUID).ConfigureAwait(false); await eventSocket.Filter(HeaderNames.ChannelCallUniqueId, bridgedUUID).ConfigureAwait(false); Log.Trace(() => "Channel [{0}] setting OtherLeg to [{1}]".Fmt(UUID, b.UUID)); })); Disposables.Add( eventSocket.ChannelEvents.Where( x => x.EventName == EventName.ChannelBridge && x.UUID != UUID && x.GetHeader(HeaderNames.OtherLegUniqueId) == UUID && x.UUID != bridgedUUID) .Subscribe( x => { //there is another channel out there that has bridged to us but we didn't get the CHANNEL_BRIDGE event on this channel Log.Info(() => "Channel [{0}] bridged to [{1}]] on CHANNEL_BRIDGE received on other channel".Fmt(UUID, x.UUID)); bridgedChannelsSubject.OnNext(new BridgedChannel(x, eventSocket)); })); if (eventSocket is OutboundSocket) { Disposables.Add( eventSocket.ChannelEvents.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelHangupComplete) .Subscribe( async e => { if (ExitOnHangup) { //give event subscribers time to complete if (LingerTime > 0) { Log.Debug(() => "Channel[{0}] will exit in {1} seconds...".Fmt(UUID, LingerTime)); await Task.Delay(LingerTime * 1000); } if (eventSocket != null) { Log.Info(() => "Channel [{0}] exiting".Fmt(UUID)); await eventSocket.Exit().ConfigureAwait(false); } Dispose(); } })); } Log.Trace(() => "Channel [{0}] subscriptions initialized".Fmt(UUID)); }
private void InitializeSubscriptions() { if (initialized.EnsureCalledOnce()) { Log.Warn(() => "Channel already initialized"); return; } Disposables.Add( eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelBridge && x.OtherLegUUID != bridgedUUID) .Subscribe( async x => { Log.Info(() => "Channel [{0}] Bridged to [{1}] CHANNEL_BRIDGE".Fmt(UUID, x.GetHeader(HeaderNames.OtherLegUniqueId))); var apiResponse = await eventSocket.Api("uuid_dump", x.OtherLegUUID); if (apiResponse.Success && apiResponse.BodyText != "+OK") { var eventMessage = new EventMessage(apiResponse); bridgedChannels.OnNext(new BridgedChannel(eventMessage, eventSocket)); } else { Log.Error(() => "Unable to get CHANNEL_DATA info from 'api uuid_dump {0}' - received '{1}'.".Fmt(x.OtherLegUUID, apiResponse.BodyText)); } })); Disposables.Add( eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelUnbridge) .Subscribe(x => Log.Info(() => "Channel [{0}] Unbridged from [{1}] {2}".Fmt(UUID, x.GetVariable("last_bridge_to"), x.GetVariable("bridge_hangup_cause"))))); Disposables.Add(bridgedChannels.Subscribe( async b => { if (bridgedUUID != null && bridgedUUID != b.UUID) { await eventSocket.FilterDelete(HeaderNames.UniqueId, bridgedUUID).ConfigureAwait(false); await eventSocket.FilterDelete(HeaderNames.OtherLegUniqueId, bridgedUUID).ConfigureAwait(false); await eventSocket.FilterDelete(HeaderNames.ChannelCallUniqueId, bridgedUUID).ConfigureAwait(false); } bridgedUUID = b.UUID; await eventSocket.Filter(HeaderNames.UniqueId, bridgedUUID).ConfigureAwait(false); await eventSocket.Filter(HeaderNames.OtherLegUniqueId, bridgedUUID).ConfigureAwait(false); await eventSocket.Filter(HeaderNames.ChannelCallUniqueId, bridgedUUID).ConfigureAwait(false); this.OtherLeg = b; })); Disposables.Add( eventSocket.Events.Where( x => x.EventName == EventName.ChannelBridge && x.UUID != UUID && x.GetHeader(HeaderNames.OtherLegUniqueId) == UUID && x.UUID != bridgedUUID) .Subscribe( x => { //there is another channel out there that has bridged to us but we didn't get the CHANNEL_BRIDGE event on this channel Log.Info(() => "Channel [{0}] bridged to [{1}]] on CHANNEL_BRIDGE received on other channel".Fmt(UUID, x.UUID)); bridgedChannels.OnNext(new BridgedChannel(x, eventSocket)); })); if (eventSocket is OutboundSocket) { Disposables.Add( eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelHangup) .Subscribe( async e => { if (ExitOnHangup) { //give event subscribers time to complete if (LingerTime > 0) { await Task.Delay(LingerTime * 1000); } Log.Info(() => "Channel [{0}] exiting".Fmt(UUID)); await eventSocket.Exit().ConfigureAwait(false); } })); } Log.Trace(() => "Channel [{0}] subscriptions initialized".Fmt(UUID)); }
/// <summary> /// Starts the Listener /// </summary> public void Start() { if (disposed.Value) { throw new ObjectDisposedException(ToString()); } if (isStarted.EnsureCalledOnce()) { return; } tcpListener = new TcpListener(IPAddress.Any, port); tcpListener.Start(); log.LogTrace("Listener Started on Port {0}".Fmt(Port)); subscription = Observable.FromAsync(tcpListener.AcceptTcpClientAsync) .Repeat() .TakeUntil(listenerTermination) .Do(connection => log.LogTrace("New Connection from {0}".Fmt(connection.Client.RemoteEndPoint))) .Select( tcpClient => { try { return(observableSocketFactory(tcpClient)); } catch (Exception ex) { //race condition - socket might shut down before we can initialize log.LogError(ex, "Unable to create observableSocket"); return(null); } }) .Where(x => x != null) .Subscribe( connection => { if (connection != null) { connections.Add(connection); observable.OnNext(connection); disposables.Add( Observable.FromEventPattern(h => connection.Disposed += h, h => connection.Disposed -= h) .FirstAsync() .Subscribe( _ => { log.LogTrace("Connection Disposed"); connections.Remove(connection); })); } }, ex => { //ObjectDisposedException is thrown by TcpListener when Stop() is called before EndAcceptTcpClient() if (!(ex is ObjectDisposedException)) { log.LogError(ex, "Error handling inbound connection"); } }, () => isStarted.Set(false)); }
private void InitializeSubscriptions() { if (initialized.EnsureCalledOnce()) { Log.Warn(() => "Channel already initialized"); return; } Disposables.Add( eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelBridge).Subscribe( x => { Log.Trace( () => "Channel [{0}] Bridged to [{1}]".Fmt(UUID, x.GetHeader(HeaderNames.OtherLegUniqueId))); if (Bridge.Channel != null && x.GetHeader(HeaderNames.OtherLegUniqueId) != Bridge.Channel.UUID) { //possibly changed bridge partner as part of att_xfer Log.Warn( () => "Channel [{0}] was Bridged to [{1}] but now changed to [{2}]".Fmt( UUID, Bridge.Channel.UUID, x.UUID)); Bridge.Channel.Dispose(); Bridge = new BridgeStatus(true, "TRANSFERRED", new BridgedChannel(x, eventSocket)); } })); Disposables.Add( eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelUnbridge) .Subscribe( x => Log.Trace( () => "Channel [{0}] Unbridged from [{1}] {2}".Fmt( UUID, Bridge.Channel.UUID, x.GetVariable("bridge_hangup_cause"))))); Disposables.Add( eventSocket.Events.Where( x => x.EventName == EventName.ChannelBridge && x.UUID != UUID && x.GetHeader(HeaderNames.OtherLegUniqueId) == UUID && (Bridge.Channel != null && x.UUID != Bridge.Channel.UUID)).Subscribe( x => { //there is another channel out there that has bridged to us but we didn't get the CHANNEL_BRIDGE event on this channel //possibly an attended transfer. We'll swap our bridge partner so we can get its events Log.Warn( () => "Channel [{0}] was Bridged to [{1}] but now changed to [{2}]".Fmt( UUID, Bridge.Channel.UUID, x.UUID)); Bridge.Channel.Dispose(); Bridge = new BridgeStatus(true, "TRANSFERRED", new BridgedChannel(x, eventSocket)); })); if (this.eventSocket is OutboundSocket) { Disposables.Add( eventSocket.Events.Where(x => x.UUID == UUID && x.EventName == EventName.ChannelHangup) .Subscribe( e => { if (ExitOnHangup) { Log.Info(() => "Channel [{0}] exiting".Fmt(UUID)); eventSocket.Exit(); //don't care about the result, no need to wait } })); } Log.Trace(() => "Channel [{0}] subscriptions initialized".Fmt(UUID)); }