public async Task FlushBlocks() { using (await _lockSem.GetDisposable().ConfigureAwait(false)) { if (Status != InMessageStatus.AllBlocksReceived) { throw new InvalidOperationException( "Status != InMessageStatus.AllBlocksReceived"); } int l = ReceivedData.Length; for (int i = 0; i < l; i++) { ReceivedData[i] = null; } } }
public async Task SendBlock(uint blockId) { if (blockId >= BlockCount) { throw new ArgumentOutOfRangeException("blockId"); } if (Status == OutMessageStatus.HandshakeOk) { Status = OutMessageStatus.FirstBlockSent; } using (await _blocksSentLockSem.GetDisposable().ConfigureAwait(false)) { if (!BlocksSent[blockId]) { BlocksSentCount++; BlocksSent[blockId] = true; if ( Status == OutMessageStatus.FirstBlockSent && BlocksSentCount == BlockCount ) { Status = OutMessageStatus.AllBlocksSent; } } } }
public async Task <T1> GetClientProxy() { using (_stateHelper.GetFuncWrapper()) { using (await _proxyLockSem.GetDisposable().ConfigureAwait(false)) { return(_proxy ?? (_proxy = (new ProxyFactory()).CreateProxy <T1>(this))); } } }
public async Task <uint> GetNextOutMessageId() { using ( await _nextOutMessageIdLockSem.GetDisposable().ConfigureAwait(false) ) { if (_nextOutMessageId == 0) { _nextOutMessageId++; } return(_nextOutMessageId++); } }
private async void IntervalCleanupAction(long i) { var curMethodName = this.MyNameOfMethod(e => e.IntervalCleanupAction(0)); try { using (_stateHelper.GetFuncWrapper()) { using (await _intervalCleanupActionLockSem.GetDisposable().ConfigureAwait(false)) { var nowTime = DateTime.UtcNow; using (await _destinationDbLockSem.GetDisposable().ConfigureAwait(false)) { foreach (KeyValuePair <string, DestinationInfo> destinationInfo in _destinationDb) { using (await destinationInfo.Value.InMessagesDbLockSem.GetDisposable().ConfigureAwait(false)) { var inMessageIdsToRemove = ( from inMessageInfo in destinationInfo.Value.InMessagesDb where nowTime > inMessageInfo.Value.CreatedTime + _settings.CleanInMessagesOlderThan select inMessageInfo.Key ).ToList(); foreach (uint messageId in inMessageIdsToRemove) { destinationInfo.Value.InMessagesDb.Remove(messageId); } } } } } } } catch (WrongDisposableObjectStateException) { } catch (Exception exc) { _log.Error("{0} unexpected error '{1}'", curMethodName, exc.ToString()); } }
public async Task ConfirmBlock(uint blockId) { if (blockId >= BlockCount) { throw new ArgumentOutOfRangeException("blockId"); } using (await _blockConfirmedLockSem.GetDisposable().ConfigureAwait(false)) { if (!BlockConfirmed[blockId]) { BlockConfirmed[blockId] = true; BlocksConfirmedCount++; if (BlocksConfirmedCount == BlockCount) { Status = OutMessageStatus.AllBlocksConfirmed; } } } }
private async Task WriteBuffer(byte[] writeBuffer) { using (await _writeBufferLockSem.GetDisposable().ConfigureAwait(false)) { try { await _samStream.WriteAsync( writeBuffer, 0, writeBuffer.Length ).ConfigureAwait(false); } catch (IOException) { IoExceptionThrown.OnNext(null); throw; } } }
private async Task ReadAndAccumulate( CancellationToken cancellationToken ) { int readBytes; using (await _streamReadLockSem.GetDisposable().ConfigureAwait(false)) { readBytes = await _samStream.ReadAsync( _buffer, 0, BufferSize, cancellationToken ).ThrowIfCancelled(cancellationToken).ConfigureAwait(false); } if (readBytes > 0) { _accumulateBuffer.AddRange(_buffer.Take(readBytes)); } }
public async Task <uint> SendReliableMessage( string destination, byte[] data, IProgress <OutMessageProgressInfo> progress = null, uint messageId = 0, uint replyToMessageId = 0, byte messageKind = 0, CancellationToken token = default(CancellationToken) ) { using (_stateHelper.GetFuncWrapper()) { try { Assert.True(SamHelper.IsDestinationStringValid(destination)); Assert.NotNull(data); Assert.InRange(data.Length, 1, _settings.MaxMesageLength); if (messageId == 0) { messageId = await GetNextOutMessageId().ConfigureAwait(false); } DestinationInfo destinationInfo; using (await _destinationDbLockSem.GetDisposable(token: token).ConfigureAwait(false)) { if (!_destinationDb.ContainsKey(destination)) { _destinationDb.Add(destination, new DestinationInfo()); } destinationInfo = _destinationDb[destination]; } OutMessageInfo outMessageInfo; using (await destinationInfo.OutMessagesDbLockSem.GetDisposable(token: token).ConfigureAwait(false)) { if ( destinationInfo.OutMessagesDb.ContainsKey(messageId) ) { throw new EnumException <SendReliableMessageExcs>( SendReliableMessageExcs.ExistMessageId ); } outMessageInfo = new OutMessageInfo( data, replyToMessageId, _settings.MaxBlockSize, progress ); destinationInfo.OutMessagesDb.Add(messageId, outMessageInfo); } try { uint blocksCount = outMessageInfo.BlockCount; /* * Handshake */ using ( var compositeTokenSource = CancellationTokenSource.CreateLinkedTokenSource( _cts.Token, token ) ) { try { var messageStatusTask = MessageStatusReceived .Where( x => x.Destination == destination && x.MessageId == messageId ) .FirstAsync() .ToTask(compositeTokenSource.Token); byte[] messageHash = GetMessageHash( messageId, replyToMessageId, messageKind, data ); for ( outMessageInfo.HandshakeAttemptNo = 0; outMessageInfo.HandshakeAttemptNo <= _settings.HandshakeAttemptCount; outMessageInfo.HandshakeAttemptNo++ ) { if ( outMessageInfo.HandshakeAttemptNo == _settings.HandshakeAttemptCount ) { throw new EnumException <SendReliableMessageExcs>( SendReliableMessageExcs.HandshakeTimeout ); } await SendHandshakeStart( destination, messageId, replyToMessageId, (uint)data.Length, outMessageInfo.BlockSize, messageHash, outMessageInfo.Data[0], messageKind ).ConfigureAwait(false); var waitTasks = await Task.WhenAny( messageStatusTask, Task.Delay( TimeSpan.FromSeconds( _settings.HandshakeTimeoutSeconds ), compositeTokenSource.Token ) ).ConfigureAwait(false); if (waitTasks == messageStatusTask) { var messageStatus = await messageStatusTask.ConfigureAwait(false); if ( !( messageStatus.StatusCode == MessageStatusArgs.MessageStatusCode.HandshakeOk || ( messageStatus.StatusCode == MessageStatusArgs.MessageStatusCode.AllBlocksReceived && outMessageInfo.BlockCount == 1 ) ) ) { throw new EnumException <SendReliableMessageExcs>( SendReliableMessageExcs.HandshakeError, messageStatus.WriteObjectToJson() ); } break; } } outMessageInfo.Status = OutMessageStatus.HandshakeOk; outMessageInfo.BlockConfirmed[0] = true; if (outMessageInfo.BlockCount > 1) { // Handshake established, start sending blocks DateTime lastBlockConfirmationTime = DateTime.UtcNow; var blocksInProgress = new SortedSet <uint>(); var blocksInProgressLockSem = new SemaphoreSlim(1); var blockSentTimes = new DateTime[blocksCount]; using ( BlockConfirmationReceived .Where(_ => _.Destination == destination && _.MessageId == messageId ) .ObserveOn(TaskPoolScheduler.Default) .Subscribe(async x => { if ( x.BlockId < blocksCount && !outMessageInfo.BlockConfirmed[x.BlockId] ) { await outMessageInfo.ConfirmBlock(x.BlockId).ConfigureAwait(false); lastBlockConfirmationTime = DateTime.UtcNow; using (await blocksInProgressLockSem.GetDisposable().ConfigureAwait(false)) { blocksInProgress.Remove(x.BlockId); } } } ) ) { while (true) { compositeTokenSource.Token.ThrowIfCancellationRequested(); IEnumerable <int> blocksToSend; using ( await blocksInProgressLockSem.GetDisposable(token: compositeTokenSource.Token) .ConfigureAwait(false)) { if ( blocksInProgress.Count == 0 && outMessageInfo.BlockConfirmed.All(x => x) ) { break; } blocksInProgress.RemoveWhere( i => DateTime.UtcNow > ( blockSentTimes[i] + TimeSpan.FromSeconds( _settings .ConfirmationOneBlockTimeoutSeconds ) ) ); blocksToSend = Enumerable.Range(0, (int)blocksCount) .Where( i => !blocksInProgress.Contains((uint)i) && !outMessageInfo.BlockConfirmed[i] ) .Take( Math.Max( 0, _settings.WindowSize - blocksInProgress.Count ) ); } foreach (int blockId in blocksToSend) { await SendBlock( destination, messageId, (uint)blockId ).ConfigureAwait(false); await outMessageInfo.SendBlock( (uint)blockId ).ConfigureAwait(false); using ( await blocksInProgressLockSem.GetDisposable(token: compositeTokenSource.Token) .ConfigureAwait(false)) { blocksInProgress.Add((uint)blockId); } blockSentTimes[blockId] = DateTime.UtcNow; } if ( DateTime.UtcNow > lastBlockConfirmationTime + TimeSpan.FromSeconds( _settings.ConfirmationTimeoutSeconds ) ) { throw new EnumException <SendReliableMessageExcs>( SendReliableMessageExcs.SendBlocksTimeout ); } await Task.Delay(50, compositeTokenSource.Token).ConfigureAwait(false); } } } outMessageInfo.Status = OutMessageStatus.AllBlocksSent; // all blocks sent and confirmed _log.Trace( "{4}, send reliable message of {0} bytes " + "to {1} id={2},rid={3},kind={5}", data.Length, destination.Substring(0, 20), messageId, replyToMessageId, _reliableSamHelperGuid.ToString().Substring(0, 5), messageKind ); return(messageId); } finally { compositeTokenSource.Cancel(); } } } finally { TryRemoveOutMessageInfo(destinationInfo, messageId); } } catch (EnumException <SendReliableMessageExcs> ) { throw; } catch (OperationCanceledException) { throw; } catch (TimeoutException) { throw; } catch (Exception exc) { throw new EnumException <SendReliableMessageExcs>( SendReliableMessageExcs.UnexpectedError, innerException: exc ); } } }
private async void ProcessNewChangedArgs() { try { using (_stateHelper.GetFuncWrapper()) { var lockSemCalledWrapper = _lockSem.GetCalledWrapper(); lockSemCalledWrapper.Called = true; using (await _lockSem.GetDisposable(true).ConfigureAwait(false)) { while (!_cts.IsCancellationRequested && lockSemCalledWrapper.Called) { lockSemCalledWrapper.Called = false; var currentChangesNumInDictToRemove = _changedArgsDict.Keys.Where(_ => _ <= _prevChangesCounter).ToList(); foreach (long key in currentChangesNumInDictToRemove) { MyNotifyCollectionChangedArgs <TItem> removedArgs; _changedArgsDict.TryRemove(key, out removedArgs); } MyNotifyCollectionChangedArgs <TItem> nextArgs; if ( _changedArgsDict.TryRemove( _prevChangesCounter + 1, out nextArgs ) ) { lockSemCalledWrapper.Called = true; if (nextArgs.ChangedAction == EMyCollectionChangedAction.Reset) { await ResetActionAsync().ConfigureAwait(false); } else if (nextArgs.ChangedAction == EMyCollectionChangedAction.NewItemsRangeInserted) { var insertIndex = nextArgs.NewItemsIndices[0]; var insertCount = nextArgs.NewItems.Count; if (insertCount > 0) { var insertArgs = new List <MutableTuple <int, TItem> >(); for (int i = 0; i < insertCount; i++) { insertArgs.Add( MutableTuple.Create( i + insertIndex, nextArgs.NewItems[i] ) ); } await _resultCollection.InsertRangeAtAsync( insertIndex, insertArgs ).ConfigureAwait(false); _originCollectionCopy.InsertRange( insertIndex, nextArgs.NewItems ); /**/ var currentResultCount = _originCollectionCopy.Count; var bulkUpdateArgs = new List <Tuple <int, MutableTuple <int, TItem> > >(); for (int i = insertIndex + insertCount; i < currentResultCount; i++) { bulkUpdateArgs.Add( Tuple.Create( i, MutableTuple.Create( i, _originCollectionCopy[i] ) ) ); } if (bulkUpdateArgs.Any()) { await _resultCollection.ReplaceBulkAsync( bulkUpdateArgs ).ConfigureAwait(false); } } _prevChangesCounter++; } else if (nextArgs.ChangedAction == EMyCollectionChangedAction.ItemsRangeRemoved) { var removeIndex = nextArgs.OldItemsIndices[0]; var removeCount = nextArgs.OldItems.Count; if (removeCount > 0) { await _resultCollection.RemoveRangeAsync( removeIndex, removeCount ).ConfigureAwait(false); _originCollectionCopy.RemoveRange( removeIndex, removeCount ); /**/ var currentResultCount = _originCollectionCopy.Count; var bulkUpdateArgs = new List <Tuple <int, MutableTuple <int, TItem> > >(); for (int i = removeIndex; i < currentResultCount; i++) { bulkUpdateArgs.Add( Tuple.Create( i, MutableTuple.Create( i, _originCollectionCopy[i] ) ) ); } if (bulkUpdateArgs.Any()) { await _resultCollection.ReplaceBulkAsync( bulkUpdateArgs ).ConfigureAwait(false); } } _prevChangesCounter++; } else if (nextArgs.ChangedAction == EMyCollectionChangedAction.ItemsChanged) { var count = nextArgs.NewItems.Count; var bulkUpdateArgs = new List <Tuple <int, MutableTuple <int, TItem> > >(); for (int i = 0; i < count; i++) { _originCollectionCopy[nextArgs.NewItemsIndices[i]] = nextArgs.NewItems[i]; bulkUpdateArgs.Add( Tuple.Create( nextArgs.NewItemsIndices[i], MutableTuple.Create( nextArgs.NewItemsIndices[i], nextArgs.NewItems[i] ) ) ); } if (bulkUpdateArgs.Any()) { await _resultCollection.ReplaceBulkAsync( bulkUpdateArgs ).ConfigureAwait(false); } _prevChangesCounter++; } else { throw new NotImplementedException(); } } } } } } catch (OperationCanceledException) { } catch (WrongDisposableObjectStateException) { } catch (Exception exc) { MiscFuncs.HandleUnexpectedError(exc, _log); } }
public async void TryToReconnect(DateTime callTime) { var curMethodName = this.MyNameOfMethod(e => e.TryToReconnect(DateTime.MinValue)); try { using (_stateHelper.GetFuncWrapper()) { if (callTime < _lastHelperRenewedTime) { _log.Trace("{0} callTime < _lastHelperRenewedTime", curMethodName); return; } using (await _tryToReconnectLockSem.GetDisposable(true).ConfigureAwait(false)) { LBL_RETRY: if (_cts.IsCancellationRequested) { return; } _log.Trace("{0} called", curMethodName); var curImpl = _currentImplementationHelper; if (curImpl != null) { _currentImplementationHelper = null; await curImpl.MyDisposeAsync().ConfigureAwait(false); foreach (var subscription in _currentImplSubscriptions) { subscription.Dispose(); } _currentImplSubscriptions.Clear(); } bool excThrown = false; try { await InitImpl(_cts.Token).ConfigureAwait(false); } catch (OperationCanceledException) { throw; } catch (Exception exc) { _log.Error( "{0} InitImpl err '{1}'", curMethodName, exc.Message ); excThrown = true; } if (excThrown) { await Task.Delay(_settings.DelayOnConnectFailed, _cts.Token).ConfigureAwait(false); goto LBL_RETRY; } } } } catch (WrongDisposableObjectStateException) { } catch (OperationCanceledException) { } catch (Exception exc) { _log.Error( "{0} unexpected error '{1}'", curMethodName, exc.ToString() ); } }