public TransactionSignalScope(AsyncResult result, Transaction transaction) { Fx.Assert(transaction != null, "Null Transaction provided to AsyncResult.TransactionSignalScope."); _parent = result; _transactionScope = Fx.CreateTransactionScope(transaction); }
public void DebugVerifyEmpty() { Fx.Assert(this.gate == 0, "Finalized with unfinished slot."); Fx.Assert(this.heldCallback == null, "Finalized with leaked callback."); Fx.Assert(this.heldState == null, "Finalized with leaked state."); }
protected bool TryComplete(bool didCompleteSynchronously, Exception exception) { lock (ThisLock) { if (IsCompleted) { return(false); } _exception = exception; IsCompleted = true; } #if DEBUG _marker.AsyncResult = null; _marker = null; #endif CompletedSynchronously = didCompleteSynchronously; if (OnCompleting != null) { // Allow exception replacement, like a catch/throw pattern. try { OnCompleting(this, _exception); } catch (Exception e) when(!Fx.IsFatal(e)) { _exception = e; } } if (didCompleteSynchronously) { // If we completedSynchronously, then there's no chance that the manualResetEvent was created so // we don't need to worry about a race Fx.Assert(_manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult."); } else { lock (ThisLock) { if (_manualResetEvent != null) { _manualResetEvent.Set(); } } } if (_callback != null) { try { if (VirtualCallback != null) { VirtualCallback(_callback, this); } else { _callback(this); } } #pragma warning disable 1634 #pragma warning suppress 56500 // transferring exception to another thread catch (Exception e) { if (Fx.IsFatal(e)) { throw; } throw Fx.Exception.AsError(new InvalidOperationException(CommonResources.AsyncCallbackThrewException, e)); } #pragma warning restore 1634 } return(true); }
public static void End(IAsyncResult result) { Fx.AssertAndThrowFatal(result.IsCompleted, "CompletedAsyncResult was not completed!"); AsyncResult.End <CompletedAsyncResult>(result); }
void CompletionCallback(out Action <object> callback, out object state) { int slot = this.headTail; int slotLowPri; while (true) { Fx.Assert(Bits.Count(slot) != -1, "CompletionCallback called on idle IOTS!"); bool wasEmpty = Bits.Count(slot) == 0; if (wasEmpty) { // We're about to set this to idle. First check the low-priority queue. This alone doesn't // guarantee we service all the low-pri items - there hasn't even been an Interlocked yet. But // we take care of that later. slotLowPri = this.headTailLowPri; while (Bits.CountNoIdle(slotLowPri) != 0) { if (slotLowPri == (slotLowPri = Interlocked.CompareExchange(ref this.headTailLowPri, Bits.IncrementLo(slotLowPri), slotLowPri))) { this.overlapped.Post(this); this.slotsLowPri[slotLowPri & SlotMaskLowPri].DequeueWorkItem(out callback, out state); return; } } } if (slot == (slot = Interlocked.CompareExchange(ref this.headTail, Bits.IncrementLo(slot), slot))) { if (!wasEmpty) { this.overlapped.Post(this); this.slots[slot & SlotMask].DequeueWorkItem(out callback, out state); return; } // We just set the IOThreadScheduler to idle. Check if a low-priority item got added in the // interim. // Interlocked calls create a thread barrier, so this read will give us the value of // headTailLowPri at the time of the interlocked that set us to idle, or later. The invariant // here is that either the low-priority queue was empty at some point after we set the IOTS to // idle (so that the next enqueue will notice, and issue a Post), or that the IOTS was unidle at // some point after we set it to idle (so that the next attempt to go idle will verify that the // low-priority queue is empty). slotLowPri = this.headTailLowPri; if (Bits.CountNoIdle(slotLowPri) != 0) { // Whoops, go back from being idle (unless someone else already did). If we go back, start // over. (We still owe a Post.) slot = Bits.IncrementLo(slot); if (slot == Interlocked.CompareExchange(ref this.headTail, slot + Bits.HiOne, slot)) { slot += Bits.HiOne; continue; } // We know that there's a low-priority work item. But we also know that the IOThreadScheduler // wasn't idle. It's best to let it take care of itself, since according to this method, we // just set the IOThreadScheduler to idle so shouldn't take on any tasks. } break; } } callback = null; state = null; return; }
void IdleTimerCallback() { Fx.Assert(this.referenceCount == 0, "Cached IotHubConnection's ref count should be zero when idle timeout occurs!"); this.cache.RemoveHubScopeConnectionPool(this.ConnectionString); this.Connection.CloseAsync().Fork(); }
/// <summary> /// Copies the properties from the amqp message to the Message instance. /// </summary> public static void UpdateMessageHeaderAndProperties(AmqpMessage amqpMessage, Message data) { Fx.AssertAndThrow(amqpMessage.DeliveryTag != null, "AmqpMessage should always contain delivery tag."); data.DeliveryTag = amqpMessage.DeliveryTag; SectionFlag sections = amqpMessage.Sections; if ((sections & SectionFlag.Properties) != 0) { // Extract only the Properties that we support data.MessageId = amqpMessage.Properties.MessageId != null?amqpMessage.Properties.MessageId.ToString() : null; data.To = amqpMessage.Properties.To != null?amqpMessage.Properties.To.ToString() : null; if (amqpMessage.Properties.AbsoluteExpiryTime.HasValue) { data.ExpiryTimeUtc = amqpMessage.Properties.AbsoluteExpiryTime.Value; } data.CorrelationId = amqpMessage.Properties.CorrelationId != null?amqpMessage.Properties.CorrelationId.ToString() : null; data.UserId = amqpMessage.Properties.UserId.Array != null?Encoding.UTF8.GetString(amqpMessage.Properties.UserId.Array, 0 /*index*/, amqpMessage.Properties.UserId.Array.Length) : null; if (!string.IsNullOrWhiteSpace(amqpMessage.Properties.ContentType.Value)) { data.ContentType = amqpMessage.Properties.ContentType.Value; } if (!string.IsNullOrWhiteSpace(amqpMessage.Properties.ContentEncoding.Value)) { data.ContentEncoding = amqpMessage.Properties.ContentEncoding.Value; } } if ((sections & SectionFlag.MessageAnnotations) != 0) { string lockToken; if (amqpMessage.MessageAnnotations.Map.TryGetValue(LockTokenName, out lockToken)) { data.LockToken = lockToken; } ulong sequenceNumber; if (amqpMessage.MessageAnnotations.Map.TryGetValue(SequenceNumberName, out sequenceNumber)) { data.SequenceNumber = sequenceNumber; } DateTime enqueuedTime; if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.EnqueuedTime, out enqueuedTime)) { data.EnqueuedTimeUtc = enqueuedTime; } byte deliveryCount; if (amqpMessage.MessageAnnotations.Map.TryGetValue(MessageSystemPropertyNames.DeliveryCount, out deliveryCount)) { data.DeliveryCount = deliveryCount; } } if ((sections & SectionFlag.ApplicationProperties) != 0) { foreach (KeyValuePair <MapKey, object> pair in amqpMessage.ApplicationProperties.Map) { object netObject = null; if (TryGetNetObjectFromAmqpObject(pair.Value, MappingType.ApplicationProperty, out netObject)) { var stringObject = netObject as string; if (stringObject != null) { switch (pair.Key.ToString()) { case MessageSystemPropertyNames.Operation: data.SystemProperties[pair.Key.ToString()] = stringObject; break; case MessageSystemPropertyNames.MessageSchema: data.MessageSchema = stringObject; break; case MessageSystemPropertyNames.CreationTimeUtc: data.CreationTimeUtc = DateTime.Parse(stringObject); break; default: data.Properties[pair.Key.ToString()] = stringObject; break; } } else { // TODO: RDBug 4093369 Handling of non-string property values in Amqp messages // Drop non-string properties and log an error Fx.Exception.TraceHandled(new InvalidDataException("IotHub does not accept non-string Amqp properties"), "MessageConverter.UpdateMessageHeaderAndProperties"); } } } } }
public static void Fork(this Task thisTask, string tracingInfo) { Fx.Assert(thisTask != null, "task is required!"); thisTask.ContinueWith(t => Fx.Exception.TraceHandled(t.Exception, tracingInfo), TaskContinuationOptions.OnlyOnFaulted); }
public async Task <int> ReceiveAsync(byte[] buffer, int offset, int size, TimeSpan timeout) { if (Logging.IsEnabled) { Logging.Enter(this, timeout, $"{nameof(IotHubClientWebSocket)}.{nameof(ReceiveAsync)}"); } byte[] header = new byte[2]; Fx.AssertAndThrow(this.State == WebSocketState.Open, ClientWebSocketNotInOpenStateDuringReceive); this.TcpClient.ReceiveTimeout = TimeoutHelper.ToMilliseconds(timeout); bool succeeded = false; try { byte payloadLength; bool pongFrame; // TODO: rewrite this section to handle all control frames (including ping) int totalBytesRead; int bytesRead; do { // Ignore pong frame and start over totalBytesRead = 0; do { bytesRead = await this.WebSocketStream.ReadAsync(header, totalBytesRead, header.Length - totalBytesRead).ConfigureAwait(false); if (bytesRead == 0) { throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes")); } totalBytesRead += bytesRead; }while (totalBytesRead < header.Length); if (!ParseWebSocketFrameHeader(header, out payloadLength, out pongFrame)) { // Encountered a close frame or error in parsing frame from server. Close connection var closeHeader = PrepareWebSocketHeader(0, WebSocketMessageType.Close); await this.WebSocketStream.WriteAsync(closeHeader, 0, closeHeader.Length).ConfigureAwait(false); this.State = WebSocketState.Closed; #if !NETSTANDARD1_3 this.WebSocketStream?.Close(); this.TcpClient?.Close(); #else this.WebSocketStream?.Dispose(); this.TcpClient?.Dispose(); #endif return(0); // TODO: throw exception? } if (pongFrame && payloadLength > 0) { totalBytesRead = 0; var tempBuffer = new byte[payloadLength]; while (totalBytesRead < payloadLength) { bytesRead = await this.WebSocketStream.ReadAsync(tempBuffer, totalBytesRead, payloadLength - totalBytesRead).ConfigureAwait(false); if (bytesRead == 0) { throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes")); } totalBytesRead += bytesRead; } } }while (pongFrame); totalBytesRead = 0; if (buffer.Length < payloadLength) { throw Fx.Exception.AsError(new InvalidOperationException(Resources.SizeExceedsRemainingBufferSpace)); } if (payloadLength < MediumSizeFrame) { while (totalBytesRead < payloadLength) { bytesRead = await this.WebSocketStream.ReadAsync(buffer, offset + totalBytesRead, payloadLength - totalBytesRead).ConfigureAwait(false); if (bytesRead == 0) { throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes")); } totalBytesRead += bytesRead; } } else { switch (payloadLength) { case MediumSizeFrame: // read payload length (< 64K) do { bytesRead = await this.WebSocketStream.ReadAsync(header, totalBytesRead, header.Length - totalBytesRead).ConfigureAwait(false); if (bytesRead == 0) { throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes")); } totalBytesRead += bytesRead; }while (totalBytesRead < header.Length); totalBytesRead = 0; ushort extendedPayloadLength = (ushort)((header[0] << 8) | header[1]); // read payload if (buffer.Length >= extendedPayloadLength) { while (totalBytesRead < extendedPayloadLength) { bytesRead = await this.WebSocketStream.ReadAsync(buffer, offset + totalBytesRead, extendedPayloadLength - totalBytesRead).ConfigureAwait(false); if (bytesRead == 0) { throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes")); } totalBytesRead += bytesRead; } } else { throw Fx.Exception.AsError(new InvalidOperationException(Resources.SizeExceedsRemainingBufferSpace)); } break; case LargeSizeFrame: // read payload length (>= 64K) var payloadLengthBuffer = new byte[8]; do { bytesRead = await this.WebSocketStream.ReadAsync(payloadLengthBuffer, totalBytesRead, payloadLengthBuffer.Length - totalBytesRead).ConfigureAwait(false); if (bytesRead == 0) { throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes")); } totalBytesRead += bytesRead; }while (totalBytesRead < payloadLengthBuffer.Length); totalBytesRead = 0; // ignore bytes 0-3 - length cannot be larger than a 32-bit number uint superExtendedPayloadLength = (uint)((payloadLengthBuffer[4] << 24) | (payloadLengthBuffer[5] << 16) | (payloadLengthBuffer[6] << 8) | payloadLengthBuffer[7]); // read payload if (buffer.Length >= superExtendedPayloadLength) { while (totalBytesRead < superExtendedPayloadLength) { bytesRead = await this.WebSocketStream.ReadAsync(buffer, offset + totalBytesRead, (int)(superExtendedPayloadLength - totalBytesRead)).ConfigureAwait(false); if (bytesRead == 0) { throw new IOException(FramingPrematureEOF, new InvalidDataException("IotHubClientWebSocket was expecting more bytes")); } totalBytesRead += bytesRead; } } else { throw Fx.Exception.AsError(new InvalidOperationException(Resources.SizeExceedsRemainingBufferSpace)); } break; } } succeeded = true; return(totalBytesRead); } finally { if (!succeeded) { this.Fault(); } if (Logging.IsEnabled) { Logging.Exit(this, timeout, $"{nameof(IotHubClientWebSocket)}.{nameof(ReceiveAsync)}"); } } }
void SetDeadline() { Fx.Assert(!deadlineSet, "TimeoutHelper deadline set twice."); this.deadline = DateTime.UtcNow + this.originalTimeout; this.deadlineSet = true; }
public static Exception AssertAndThrowFatal(string description) { Fx.Assert(description); throw Fx.Exception.AsError(new FatalException(description)); }
public static Exception AssertAndThrow(string description) { Fx.Assert(description); throw Fx.Exception.AsError(new AssertionFailedException(description)); }