public void ReportConnectionReady(NotHttpConnection connection) { lock (this) { MarkConnectionReady(connection, false); } }
// Called with lock(this) private void MarkConnectionReady(NotHttpConnection connection, bool sacrificeWaiter) { if (requestWaiters.Count == 0) { idleConnections.Push(connection); } else { RequestWaiter waiter = requestWaiters.First(); Exception exception = connection.AssignRequest(waiter.request); if (exception == null) { requestWaiters.RemoveFirst(); // Run this asynchronously outside the lock Task.Run(() => waiter.task.SetResult(connection)); } else { if (sacrificeWaiter) { // give the waiter the connection even if it's faulted. // we do this on a failed open so that the client will see // the error rather than just perpetually retrying the open requestWaiters.RemoveFirst(); // do this asynchronously outside the lock Task.Run(() => waiter.task.SetException(new ApplicationException("Stream open failure", exception))); } --openedConnections; logger.Log("Removing faulted connection, " + openedConnections + " remaining: " + exception.Message); ReOpenConnections(); } } }
protected override async Task <byte[]> GetPreamble() { if (url == null || method == null) { throw new ApplicationException("Must set URL before writing request data"); } connection = await client.GetRequestConnection(this); SetStream(connection.Stream); string requestString; sequenceNumber = connection.NextSequenceNumber(this); if (isOverlapped) { requestString = String.Format("{0} {1} NOTHTTP/1.1 {2}\r\n", method, url.PathAndQuery, sequenceNumber); } else { requestString = String.Format("{0} {1} HTTP/1.1\r\n", method, url.PathAndQuery); } if (method != "POST" && method != "PUT") { SuppressPayload(); } method = null; return(System.Text.Encoding.UTF8.GetBytes(requestString)); }
private async void OpenConnection() { logger.Log("Opening connection to " + hostName + ":" + port); NotHttpConnection connection = new NotHttpConnection(this); await connection.Open(hostName, port); lock (this) { MarkConnectionReady(connection, true); } }
public async Task <NotHttpConnection> WaitForRequestSlot(NHClientRequest caller) { Task <NotHttpConnection> blockTask = null; lock (this) { // this is where we garbage collection connections that are faulted, so // go through the idle connections throwing them away if they // aren't good until we match one while (blockTask == null && idleConnections.Count > 0) { NotHttpConnection connection = idleConnections.Pop(); Exception exception = connection.AssignRequest(caller); if (exception == null) { blockTask = Task.FromResult(connection); } else { --openedConnections; logger.Log("Removing faulted connection, " + openedConnections + " remaining: " + exception.Message); } } if (blockTask == null) { RequestWaiter waiter = new RequestWaiter(caller); requestWaiters.AddLast(waiter); blockTask = waiter.task.Task; } ReOpenConnections(); } return(await blockTask); }
internal NHClientResponse(NotHttpConnection c, int sn, ILogger logger) : base(logger) { connection = c; sequenceNumber = sn; }