/// <devdoc> /// <para> /// Used by the ServicePoint to find a free or new Connection /// for use in making Requests. /// </para> /// </devdoc> public Connection FindConnection(string connName) { Connection leastbusyConnection = null; Connection newConnection = null; bool freeConnectionsAvail = false; GlobalLog.Print("ConnectionGroup::FindConnection [" + connName + "] m_ConnectionList.Count:" + m_ConnectionList.Count.ToString()); lock (m_ConnectionList) { // // go through the list of open connections to this service point and pick // the first empty one or, if none is empty, pick the least busy one. // bool completed; do { int minBusyCount = Int32.MaxValue; completed = true; // by default, only once through the outer loop foreach (WeakReference currentConnectionReference in m_ConnectionList) { Connection currentConnection = null; if (currentConnectionReference != null) { currentConnection = currentConnectionReference.Target as Connection; } // // If the weak reference is alive, see if its not busy, // otherwise make sure to remove it from the list // if (currentConnection != null) { GlobalLog.Print("ConnectionGroup::FindConnection currentConnection.BusyCount:" + currentConnection.BusyCount.ToString()); if (currentConnection.BusyCount < minBusyCount) { leastbusyConnection = currentConnection; minBusyCount = currentConnection.BusyCount; if (minBusyCount == 0) { freeConnectionsAvail = true; break; } } } else { m_ConnectionList.Remove(currentConnectionReference); completed = false; // now start iterating again because we changed the ArrayList break; } } } while (!completed); // // If there is NOT a Connection free, then we allocate a new Connection // if (!freeConnectionsAvail && CurrentConnections < InternalConnectionLimit) { // // If we can create a new connection, then do it, // this may have complications in pipeling because // we may wish to optimize this case by actually // using existing connections, rather than creating new ones // // Note: this implicately results in a this.Associate being called. // GlobalLog.Print("ConnectionGroup::FindConnection [returning new Connection] freeConnectionsAvail:" + freeConnectionsAvail.ToString() + " CurrentConnections:" + CurrentConnections.ToString() + " InternalConnectionLimit:" + InternalConnectionLimit.ToString()); newConnection = new Connection( this, m_ServicePoint, m_IPAddress, m_ServicePoint.ProtocolVersion, m_ServicePoint.SupportsPipelining); } else { // // All connections are busy, use the least busy one // GlobalLog.Print("ConnectionGroup::FindConnection [returning leastbusyConnection] freeConnectionsAvail:" + freeConnectionsAvail.ToString() + " CurrentConnections:" + CurrentConnections.ToString() + " InternalConnectionLimit:" + InternalConnectionLimit.ToString()); GlobalLog.Assert(leastbusyConnection != null, "Connect.leastbusyConnection != null", "All connections have BusyCount equal to Int32.MaxValue"); newConnection = leastbusyConnection; } } return(newConnection); }
/// <devdoc> /// <para> /// Used by the ServicePoint to find a free or new Connection /// for use in making Requests. Under NTLM and Negotiate requests, /// this function depricates itself and switches the object over to /// using a new code path (see FindConnectionAuthenticationGroup). /// </para> /// </devdoc> internal Connection FindConnection(HttpWebRequest request, string connName, out bool forcedsubmit) { Connection leastbusyConnection = null; Connection newConnection = null; bool freeConnectionsAvail = false; forcedsubmit = false; if (m_AuthenticationGroup || request.LockConnection) { m_AuthenticationGroup = true; return(FindConnectionAuthenticationGroup(request, connName)); } GlobalLog.Print("ConnectionGroup::FindConnection [" + connName + "] m_ConnectionList.Count:" + m_ConnectionList.Count.ToString()); lock (m_ConnectionList) { // // go through the list of open connections to this service point and pick the connection as follows: // - free connection // - if there is no free connection and if we are under connection limit, create new connection // - pick the least busy connection which does not have non-keep alive request pipelined // - pick the least busy connection which may have non-keep alive request pipelined // If we pick the connection with non keep-alive request pipelined on it, we set forcedsubmit to true. // This will make sure that we don't start the request immediately and it gets queued on the connection. // int minBusyCount = Int32.MaxValue; bool foundLiveConnection = false; foreach (Connection currentConnection in m_ConnectionList) { GlobalLog.Print("ConnectionGroup::FindConnection currentConnection.BusyCount:" + currentConnection.BusyCount.ToString()); bool useThisConnection = false; if (foundLiveConnection) { useThisConnection = (!currentConnection.NonKeepAliveRequestPipelined && minBusyCount > currentConnection.BusyCount); } else { useThisConnection = (!currentConnection.NonKeepAliveRequestPipelined || minBusyCount > currentConnection.BusyCount); } if (useThisConnection) { leastbusyConnection = currentConnection; minBusyCount = currentConnection.BusyCount; if (!foundLiveConnection) { foundLiveConnection = !currentConnection.NonKeepAliveRequestPipelined; } else { GlobalLog.Assert(!currentConnection.NonKeepAliveRequestPipelined, "Connection.NonKeepAliveRequestPipelined == false|Non keep-alive request has been pipelined on this connection."); } if (foundLiveConnection && minBusyCount == 0) { freeConnectionsAvail = true; break; } } } // // If there is NOT a Connection free, then we allocate a new Connection // if (!freeConnectionsAvail && CurrentConnections < ConnectionLimit) { // // If we can create a new connection, then do it, // this may have complications in pipeling because // we may wish to optimize this case by actually // using existing connections, rather than creating new ones // // Note: this implicately results in a this.Associate being called. // GlobalLog.Print("ConnectionGroup::FindConnection [returning new Connection] freeConnectionsAvail:" + freeConnectionsAvail.ToString() + " CurrentConnections:" + CurrentConnections.ToString() + " ConnectionLimit:" + ConnectionLimit.ToString()); newConnection = new Connection(this); forcedsubmit = false; } else { // // All connections are busy, use the least busy one // GlobalLog.Print("ConnectionGroup::FindConnection [returning leastbusyConnection] freeConnectionsAvail:" + freeConnectionsAvail.ToString() + " CurrentConnections:" + CurrentConnections.ToString() + " ConnectionLimit:" + ConnectionLimit.ToString()); GlobalLog.Assert(leastbusyConnection != null, "Connect.leastbusyConnection != null|All connections have BusyCount equal to Int32.MaxValue."); newConnection = leastbusyConnection; forcedsubmit = !foundLiveConnection; } newConnection.MarkAsReserved(); } return(newConnection); }
/// <devdoc> /// <para> /// Attempts to match a request with a connection, if a connection is unassigned ie not locked with /// a request, then the least busy connections is returned in "leastbusyConnection." If the /// connection limit allows, and all connections are busy, a new one is allocated and returned. /// /// RETURNS: a Connection shown to match a previously locked Request/Connection (OTHERWISE) /// leasebusyConnection - will contain a newly allocated Connection or least Busy one /// suiteable for requests. /// /// NOTE: For Whidbey: try to integrate this code into FindConnection() /// </para> /// </devdoc> private Connection FindMatchingConnection(HttpWebRequest request, string connName, out Connection leastbusyConnection) { int minBusyCount = Int32.MaxValue; bool freeConnectionsAvail = false; leastbusyConnection = null; lock (m_ConnectionList) { // // go through the list of open connections to this service point and pick // the first empty one or, if none is empty, pick the least busy one. // bool completed; do { minBusyCount = Int32.MaxValue; completed = true; // by default, only once through the outer loop foreach (WeakReference currentConnectionReference in m_ConnectionList) { Connection currentConnection = null; if (currentConnectionReference != null) { currentConnection = currentConnectionReference.Target as Connection; } // // If the weak reference is alive, see if its not busy, // otherwise make sure to remove it from the list // if (currentConnection != null) { GlobalLog.Print("ConnectionGroup::FindConnection currentConnection.BusyCount:" + currentConnection.BusyCount.ToString()); if (currentConnection.LockedRequest == request) { leastbusyConnection = currentConnection; return(currentConnection); } GlobalLog.Print("ConnectionGroup::FindConnection: lockedRequest# " + ((currentConnection.LockedRequest == null) ? "null" : currentConnection.LockedRequest.GetHashCode().ToString())); if (currentConnection.BusyCount < minBusyCount && currentConnection.LockedRequest == null) { leastbusyConnection = currentConnection; minBusyCount = currentConnection.BusyCount; if (minBusyCount == 0) { freeConnectionsAvail = true; } } } else { m_ConnectionList.Remove(currentConnectionReference); completed = false; // now start iterating again because we changed the ArrayList break; } } } while (!completed); // // If there is NOT a Connection free, then we allocate a new Connection // if (!freeConnectionsAvail && CurrentConnections < InternalConnectionLimit) { // // If we can create a new connection, then do it, // this may have complications in pipeling because // we may wish to optimize this case by actually // using existing connections, rather than creating new ones // // Note: this implicately results in a this.Associate being called. // GlobalLog.Print("ConnectionGroup::FindConnection [returning new Connection] CurrentConnections:" + CurrentConnections.ToString() + " InternalConnectionLimit:" + InternalConnectionLimit.ToString()); leastbusyConnection = new Connection( this, m_ServicePoint, m_IPAddress, m_ServicePoint.ProtocolVersion, m_ServicePoint.SupportsPipelining ); } } return(null); // only if we have a locked Connection that matches can return non-null }
/// <devdoc> /// <para> /// Attempts to match a request with a connection, if a connection is unassigned ie not locked with /// a request, then the least busy connections is returned in "leastbusyConnection." If the /// connection limit allows, and all connections are busy, a new one is allocated and returned. /// /// RETURNS: a Connection shown to match a previously locked Request/Connection (OTHERWISE) /// leasebusyConnection - will contain a newly allocated Connection or least Busy one /// suiteable for requests. /// /// NOTE: For Whidbey: try to integrate this code into FindConnection() /// </para> /// </devdoc> private Connection FindMatchingConnection(HttpWebRequest request, string connName, out Connection leastbusyConnection) { int minBusyCount = Int32.MaxValue; bool freeConnectionsAvail = false; leastbusyConnection = null; lock (m_ConnectionList) { // // go through the list of open connections to this service point and pick the first free one or, // if none is free, pick the least busy one. Skip all connections with non keep-alive request pipelined. // minBusyCount = Int32.MaxValue; foreach (Connection currentConnection in m_ConnectionList) { GlobalLog.Print("ConnectionGroup::FindMatchingConnection currentConnection.BusyCount:" + currentConnection.BusyCount.ToString()); if (currentConnection.LockedRequest == request) { leastbusyConnection = currentConnection; return(currentConnection); } GlobalLog.Print("ConnectionGroup::FindMatchingConnection: lockedRequest# " + ((currentConnection.LockedRequest == null) ? "null" : currentConnection.LockedRequest.GetHashCode().ToString())); if (!currentConnection.NonKeepAliveRequestPipelined && currentConnection.BusyCount < minBusyCount && currentConnection.LockedRequest == null) { leastbusyConnection = currentConnection; minBusyCount = currentConnection.BusyCount; if (minBusyCount == 0) { freeConnectionsAvail = true; } } } // // If there is NOT a Connection free, then we allocate a new Connection // if (!freeConnectionsAvail && CurrentConnections < ConnectionLimit) { // // If we can create a new connection, then do it, // this may have complications in pipeling because // we may wish to optimize this case by actually // using existing connections, rather than creating new ones // // Note: this implicately results in a this.Associate being called. // GlobalLog.Print("ConnectionGroup::FindMatchingConnection [returning new Connection] CurrentConnections:" + CurrentConnections.ToString() + " ConnectionLimit:" + ConnectionLimit.ToString()); leastbusyConnection = new Connection(this); } } return(null); // only if we have a locked Connection that matches can return non-null }
/// <devdoc> /// <para> /// Used by the ServicePoint to find a free or new Connection /// for use in making Requests. Under NTLM and Negotiate requests, /// this function depricates itself and switches the object over to /// using a new code path (see FindConnectionAuthenticationGroup). /// </para> /// </devdoc> internal Connection FindConnection(HttpWebRequest request, string connName) { Connection leastbusyConnection = null; Connection newConnection = null; bool freeConnectionsAvail = false; if (m_AuthenticationGroup || request.LockConnection) { m_AuthenticationGroup = true; return(FindConnectionAuthenticationGroup(request, connName)); } GlobalLog.Print("ConnectionGroup::FindConnection [" + connName + "] m_ConnectionList.Count:" + m_ConnectionList.Count.ToString()); lock (m_ConnectionList) { // // go through the list of open connections to this service point and pick // the first empty one or, if none is empty, pick the least busy one. // int minBusyCount = Int32.MaxValue; foreach (Connection currentConnection in m_ConnectionList) { GlobalLog.Print("ConnectionGroup::FindConnection currentConnection.BusyCount:" + currentConnection.BusyCount.ToString()); if (currentConnection.BusyCount < minBusyCount) { leastbusyConnection = currentConnection; minBusyCount = currentConnection.BusyCount; if (minBusyCount == 0) { freeConnectionsAvail = true; break; } } } // // If there is NOT a Connection free, then we allocate a new Connection // if (!freeConnectionsAvail && CurrentConnections < ConnectionLimit) { // // If we can create a new connection, then do it, // this may have complications in pipeling because // we may wish to optimize this case by actually // using existing connections, rather than creating new ones // // Note: this implicately results in a this.Associate being called. // GlobalLog.Print("ConnectionGroup::FindConnection [returning new Connection] freeConnectionsAvail:" + freeConnectionsAvail.ToString() + " CurrentConnections:" + CurrentConnections.ToString() + " ConnectionLimit:" + ConnectionLimit.ToString()); newConnection = new Connection(this); } else { // // All connections are busy, use the least busy one // GlobalLog.Print("ConnectionGroup::FindConnection [returning leastbusyConnection] freeConnectionsAvail:" + freeConnectionsAvail.ToString() + " CurrentConnections:" + CurrentConnections.ToString() + " ConnectionLimit:" + ConnectionLimit.ToString()); GlobalLog.Assert(leastbusyConnection != null, "Connect.leastbusyConnection != null|All connections have BusyCount equal to Int32.MaxValue."); newConnection = leastbusyConnection; } } return(newConnection); }