fixes bug 83526 "http should use fewer connections per server per page"

r=bbaetz sr=dougt,blizzard


git-svn-id: svn://10.0.0.236/trunk@102220 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
darin%netscape.com
2001-09-04 23:02:26 +00:00
parent 2ede81a925
commit f90e1af576
9 changed files with 232 additions and 149 deletions

View File

@@ -288,11 +288,28 @@ pref("network.http.keep-alive", true); // set it to false in case of problems
pref("network.http.proxy.keep-alive", true );
pref("network.http.keep-alive.timeout", 300);
pref("network.http.max-connections", 16);
pref("network.http.max-connections-per-server", 8);
pref("network.http.keep-alive.max-connections", 20); // max connections to be kept alive
pref("network.http.keep-alive.max-connections-per-server", 8);
// limit the absolute number of http connections.
pref("network.http.max-connections", 24);
// limit the absolute number of http connections that can be established per
// host. if a http proxy server is enabled, then the "server" is the proxy
// server. Otherwise, "server" is the http origin server.
pref("network.http.max-connections-per-server", 8);
// if network.http.keep-alive is true, then a new connection will only be
// attempted if the number of active connections to a host is less then
// network.http.max-persistent-connections-per-server. if a http proxy server
// is enabled, then the "server" is the proxy server. Otherwise, "server" is
// the http origin server.
pref("network.http.max-persistent-connections-per-server", 2);
// amount of time (in seconds) to suspend pending requests, before spawning a
// new connection, once the limit on the number of persistent connections per
// host has been reached. however, a new connection will not be created if the
// limit on the number of connections per host has also been reached.
pref("network.http.request.max-start-delay", 10);
// http specific network timeouts (XXX currently unused)
pref("network.http.connect.timeout", 30); // in seconds
pref("network.http.request.timeout", 120); // in seconds

View File

@@ -31,6 +31,11 @@
#include "nsString.h"
#include "nsNetCID.h"
#ifdef DEBUG
// in debug builds this will be valid while the socket transport service is active.
PRThread *NS_SOCKET_THREAD = 0;
#endif
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
@@ -356,6 +361,10 @@ nsSocketTransportService::Run(void)
PRBool hadThreadEvent = mThreadEvent ? PR_TRUE : PR_FALSE;
#endif
#ifdef DEBUG
NS_SOCKET_THREAD = PR_GetCurrentThread();
#endif
if (mThreadEvent)
{
//
@@ -517,7 +526,10 @@ nsSocketTransportService::Run(void)
/* Process any pending operations on the mWorkQ... */
rv = ProcessWorkQ();
}
return NS_OK;
#ifdef DEBUG
NS_SOCKET_THREAD = 0;
#endif
return NS_OK;
}

View File

@@ -291,7 +291,7 @@ nsHttpChannel::SetupTransaction()
if (NS_FAILED(rv)) return rv;
// create the transaction object
mTransaction = new nsHttpTransaction(listenerProxy, this);
mTransaction = new nsHttpTransaction(listenerProxy, this, mCapabilities);
if (!mTransaction)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mTransaction);

View File

@@ -47,9 +47,11 @@ nsHttpConnection::nsHttpConnection()
: mTransaction(0)
, mConnectionInfo(0)
, mLock(nsnull)
, mReadStartTime(0)
, mLastActiveTime(0)
, mIdleTimeout(0)
, mKeepAlive(0)
, mKeepAlive(1) // assume to keep-alive by default
, mKeepAliveMask(1)
, mWriteDone(0)
, mReadDone(0)
{
@@ -72,7 +74,7 @@ nsHttpConnection::~nsHttpConnection()
}
nsresult
nsHttpConnection::Init(nsHttpConnectionInfo *info)
nsHttpConnection::Init(nsHttpConnectionInfo *info, PRUint16 maxHangTime)
{
LOG(("nsHttpConnection::Init [this=%x]\n", this));
@@ -86,6 +88,7 @@ nsHttpConnection::Init(nsHttpConnectionInfo *info)
mConnectionInfo = info;
NS_ADDREF(mConnectionInfo);
mMaxHangTime = maxHangTime;
return NS_OK;
}
@@ -103,6 +106,10 @@ nsHttpConnection::SetTransaction(nsHttpTransaction *transaction)
mTransaction = transaction;
NS_ADDREF(mTransaction);
// default mKeepAlive according to what will be requested
mKeepAliveMask = mKeepAlive =
mTransaction->Capabilities() & NS_HTTP_ALLOW_KEEPALIVE;
// build a proxy for the progress event sink
mProgressSink = 0;
if (mTransaction->Callbacks() && mTransaction->ConsumerEventQ()) {
@@ -160,6 +167,7 @@ nsHttpConnection::OnHeadersAvailable(nsHttpTransaction *trans, PRBool *reset)
else
mKeepAlive = PR_TRUE;
}
mKeepAliveMask = mKeepAlive;
// if this connection is persistent, then the server may send a "Keep-Alive"
// header specifying the maximum number of times the connection can be
@@ -290,8 +298,8 @@ nsHttpConnection::ProxyStepUp()
PRBool
nsHttpConnection::CanReuse()
{
return mKeepAlive && (NowInSeconds() - mLastActiveTime < mIdleTimeout)
&& IsAlive();
return IsKeepAlive() && (NowInSeconds() - mLastActiveTime < mIdleTimeout)
&& IsAlive();
}
PRBool
@@ -318,7 +326,7 @@ nsHttpConnection::DropTransaction()
mProgressSink = 0;
// if the transaction was dropped, then we cannot reuse this connection.
mKeepAlive = PR_FALSE;
mKeepAliveMask = mKeepAlive = PR_FALSE;
}
// called on the socket thread
@@ -574,8 +582,10 @@ nsHttpConnection::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
mTransaction->SetSecurityInfo(info);
}
}
else
else {
mReadRequest = request;
mReadStartTime = NowInSeconds();
}
return NS_OK;
}
@@ -630,6 +640,9 @@ nsHttpConnection::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
NS_RELEASE(trans);
}
// reset the keep-alive mask
mKeepAliveMask = mKeepAlive;
nsHttpHandler::get()->ReclaimConnection(this);
}
// no point in returning anything else but NS_OK
@@ -690,14 +703,23 @@ nsHttpConnection::OnDataAvailable(nsIRequest *request, nsISupports *context,
nsIInputStream *inputStream,
PRUint32 offset, PRUint32 count)
{
LOG(("nsHttpConnection::OnDataAvailable [this=%x]\n", this));
if (!mTransaction) {
LOG(("nsHttpConnection: no transaction! closing stream\n"));
LOG(("no transaction! closing stream\n"));
return NS_BASE_STREAM_CLOSED;
}
mLastActiveTime = NowInSeconds();
LOG(("nsHttpConnection::OnDataAvailable [this=%x]\n", this));
if (mKeepAliveMask &&
(mLastActiveTime - mReadStartTime >= PRUint32(mMaxHangTime))) {
LOG(("max hang time exceeded!\n"));
// give the handler a chance to create a new persistent connection to
// this host if we've been busy for too long.
mKeepAliveMask = PR_FALSE;
nsHttpHandler::get()->ProcessTransactionQ();
}
nsresult rv = mTransaction->OnDataReadable(inputStream);

View File

@@ -63,7 +63,12 @@ public:
nsHttpConnection();
virtual ~nsHttpConnection();
nsresult Init(nsHttpConnectionInfo *);
// Initialize the connection:
// info - specifies the connection parameters.
// maxHangTime - limits the amount of time this connection can spend on a
// single transaction before it should no longer be kept
// alive. a value of 0xffff indicates no limit.
nsresult Init(nsHttpConnectionInfo *info, PRUint16 maxHangTime);
// SetTransaction causes the given transaction to be processed on this
// connection. It fails if there is already an existing transaction.
@@ -83,13 +88,11 @@ public:
// called to cause the underlying socket to start speaking SSL
nsresult ProxyStepUp();
PRBool CanReuse(); // can this connection be reused?
PRBool IsAlive();
PRBool IsKeepAlive() { return mKeepAlive; }
PRUint16 IdleTimeout() { return mIdleTimeout; }
void DontReuse() { mKeepAlive = PR_FALSE;
mIdleTimeout = 0; }
PRBool IsKeepAlive() { return mKeepAliveMask && mKeepAlive; }
PRBool CanReuse(); // can this connection be reused?
void DontReuse() { mKeepAliveMask = PR_FALSE;
mKeepAlive = PR_FALSE;
mIdleTimeout = 0; }
void DropTransaction();
void ReportProgress(PRUint32 progress, PRInt32 progressMax);
@@ -107,6 +110,8 @@ private:
nsresult SetupSSLProxyConnect();
PRBool IsAlive();
private:
nsCOMPtr<nsISocketTransport> mSocketTransport;
nsCOMPtr<nsIRequest> mWriteRequest;
@@ -122,10 +127,13 @@ private:
PRLock *mLock;
PRUint32 mReadStartTime; // time of OnStartRequest
PRUint32 mLastActiveTime;
PRUint16 mIdleTimeout; // value of keep-alive: timeout=
PRUint16 mMaxHangTime; // max download time before dropping keep-alive status
PRUint16 mIdleTimeout; // value of keep-alive: timeout=
PRPackedBool mKeepAlive;
PRPackedBool mKeepAliveMask;
PRPackedBool mWriteDone;
PRPackedBool mReadDone;
};

View File

@@ -62,6 +62,11 @@
#include <Gestalt.h>
#endif
#ifdef DEBUG
// defined by the socket transport service while active
extern PRThread *NS_SOCKET_THREAD;
#endif
static const char NETWORK_PREFS[] = "network.";
static const char INTL_ACCEPT_LANGUAGES[] = "intl.accept_languages";
static const char INTL_ACCEPT_CHARSET[] = "intl.charset.default";
@@ -95,9 +100,10 @@ nsHttpHandler::nsHttpHandler()
, mProxyCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
, mIdleTimeout(10)
, mMaxRequestAttempts(10)
, mMaxConnections(16)
, mMaxRequestDelay(10)
, mMaxConnections(24)
, mMaxConnectionsPerServer(8)
, mMaxIdleConnectionsPerServer(4)
, mMaxPersistentConnectionsPerServer(2)
, mActiveConnections(0)
, mIdleConnections(0)
, mTransactionQ(0)
@@ -378,8 +384,7 @@ nsHttpHandler::GetCacheSession(nsCacheStoragePolicy storagePolicy,
// may be called from any thread
nsresult
nsHttpHandler::InitiateTransaction(nsHttpTransaction *trans,
nsHttpConnectionInfo *ci,
PRBool failIfBusy)
nsHttpConnectionInfo *ci)
{
LOG(("nsHttpHandler::InitiateTransaction\n"));
@@ -388,19 +393,22 @@ nsHttpHandler::InitiateTransaction(nsHttpTransaction *trans,
nsAutoLock lock(mConnectionLock);
return InitiateTransaction_Locked(trans, ci, failIfBusy);
return InitiateTransaction_Locked(trans, ci);
}
// may be called from any thread
// called from the socket thread
nsresult
nsHttpHandler::ReclaimConnection(nsHttpConnection *conn)
{
NS_ENSURE_ARG_POINTER(conn);
#ifdef DEBUG
NS_PRECONDITION(PR_GetCurrentThread() == NS_SOCKET_THREAD, "wrong thread");
#endif
PRBool reusable = conn->CanReuse();
LOG(("nsHttpHandler::ReclaimConnection [conn=%x keep-alive=%d]\n",
conn, reusable));
LOG(("nsHttpHandler::ReclaimConnection [conn=%x(%s:%d) keep-alive=%d]\n",
conn, conn->ConnectionInfo()->Host(), conn->ConnectionInfo()->Port(), reusable));
nsAutoLock lock(mConnectionLock);
@@ -408,21 +416,11 @@ nsHttpHandler::ReclaimConnection(nsHttpConnection *conn)
mActiveConnections.RemoveElement(conn);
if (reusable) {
// verify that we aren't already maxed out on the number of
// keep-alives we can have for this server.
PRUint32 count = CountIdleConnections(conn->ConnectionInfo());
if (count == PRUint32(mMaxIdleConnectionsPerServer)) {
LOG(("not caching keep-alive connection: "
"would exceed max allowed per server\n"));
NS_RELEASE(conn);
}
else {
LOG(("adding connection to idle list [conn=%x]\n", conn));
// hold onto this connection in the idle list. we push it
// to the end of the list so as to ensure that we'll visit
// older connections first before getting to this one.
mIdleConnections.AppendElement(conn);
}
LOG(("adding connection to idle list [conn=%x]\n", conn));
// hold onto this connection in the idle list. we push it
// to the end of the list so as to ensure that we'll visit
// older connections first before getting to this one.
mIdleConnections.AppendElement(conn);
}
else {
LOG(("closing connection: connection can't be reused\n"));
@@ -433,7 +431,26 @@ nsHttpHandler::ReclaimConnection(nsHttpConnection *conn)
// process the pending transaction queue...
if (mTransactionQ.Count() > 0)
ProcessTransactionQ();
ProcessTransactionQ_Locked();
return NS_OK;
}
// called from the socket thread (see nsHttpConnection::OnDataAvailable)
nsresult
nsHttpHandler::ProcessTransactionQ()
{
LOG(("nsHttpHandler::ProcessTransactionQ\n"));
#ifdef DEBUG
NS_PRECONDITION(PR_GetCurrentThread() == NS_SOCKET_THREAD, "wrong thread");
#endif
nsAutoLock lock(mConnectionLock);
// conn is no longer keep-alive, so we may be able to initiate
// a pending transaction to the same host.
if (mTransactionQ.Count() > 0)
ProcessTransactionQ_Locked();
return NS_OK;
}
@@ -632,9 +649,9 @@ nsHttpHandler::UserAgent()
// called with the connection lock held
void
nsHttpHandler::ProcessTransactionQ()
nsHttpHandler::ProcessTransactionQ_Locked()
{
LOG(("nsHttpHandler::ProcessTransactionQ\n"));
LOG(("nsHttpHandler::ProcessTransactionQ_Locked\n"));
nsPendingTransaction *pt = nsnull;
@@ -644,17 +661,30 @@ nsHttpHandler::ProcessTransactionQ()
pt = (nsPendingTransaction *) mTransactionQ[i];
// try to initiate this transaction... if it fails
// then we'll just skip over this pending transaction
// and try the next.
// skip over a busy pending transaction
if (pt->IsBusy())
continue;
// the connection lock is released during InitiateTransaction_Locked, so
// the transaction queue could get modified. mark this pending transaction
// as busy to cause it to be skipped if this function happens to recurse.
pt->SetBusy(PR_TRUE);
// try to initiate this transaction... if it fails then we'll just skip
// over this pending transaction and try the next.
nsresult rv = InitiateTransaction_Locked(pt->Transaction(),
pt->ConnectionInfo(),
PR_TRUE);
if (NS_SUCCEEDED(rv)) {
mTransactionQ.RemoveElementAt(i);
delete pt;
i--;
}
else {
LOG(("InitiateTransaction_Locked failed [rv=%x]\n", rv));
pt->SetBusy(PR_FALSE);
}
}
}
@@ -671,7 +701,7 @@ nsHttpHandler::EnqueueTransaction(nsHttpTransaction *trans,
mTransactionQ.AppendElement(pt);
LOG(("transaction queue contains %u elements\n", mTransactionQ.Count()));
LOG((">> transaction queue contains %u elements\n", mTransactionQ.Count()));
return NS_OK;
}
@@ -682,57 +712,59 @@ nsHttpHandler::InitiateTransaction_Locked(nsHttpTransaction *trans,
PRBool failIfBusy)
{
nsresult rv;
PRUint8 caps = trans->Capabilities();
LOG(("nsHttpHandler::InitiateTransaction_Locked [failIfBusy=%d]\n", failIfBusy));
if ((mActiveConnections.Count() == PRInt32(mMaxConnections)) ||
(CountActiveConnections(ci) == mMaxConnectionsPerServer)) {
LOG(("unable to perform the transaction at this time [trans=%x]\n", trans));
if (failIfBusy) return NS_ERROR_FAILURE;
return EnqueueTransaction(trans, ci);
if (AtActiveConnectionLimit(ci, caps)) {
LOG((">> unable to perform the transaction at this time [trans=%x]\n", trans));
return failIfBusy ? NS_ERROR_FAILURE : EnqueueTransaction(trans, ci);
}
nsHttpConnection *conn = nsnull;
// search the idle connection list
PRInt32 i;
for (i=0; i<mIdleConnections.Count(); ++i) {
conn = (nsHttpConnection *) mIdleConnections[i];
if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
// search the idle connection list
PRInt32 i;
for (i=0; i<mIdleConnections.Count(); ++i) {
conn = (nsHttpConnection *) mIdleConnections[i];
LOG(("comparing against idle connection [host=%s:%d]\n",
conn->ConnectionInfo()->Host(), conn->ConnectionInfo()->Port()));
LOG((">> comparing against idle connection [conn=%x host=%s:%d]\n",
conn, conn->ConnectionInfo()->Host(), conn->ConnectionInfo()->Port()));
// we check if the connection can be reused before even checking if it
// is a "matching" connection. this is how we keep the idle connection
// list fresh. we could alternatively use some sort of timer for this.
if (!conn->CanReuse()) {
LOG(("dropping stale connection: [conn=%x]\n", conn));
mIdleConnections.RemoveElementAt(i);
i--;
NS_RELEASE(conn);
// we check if the connection can be reused before even checking if it
// is a "matching" connection. this is how we keep the idle connection
// list fresh. we could alternatively use some sort of timer for this.
if (!conn->CanReuse()) {
LOG((" dropping stale connection: [conn=%x]\n", conn));
mIdleConnections.RemoveElementAt(i);
i--;
NS_RELEASE(conn);
}
else if (conn->ConnectionInfo()->Equals(ci)) {
LOG((" reusing connection [conn=%x]\n", conn));
mIdleConnections.RemoveElementAt(i);
i--;
break;
}
conn = nsnull;
}
else if (conn->ConnectionInfo()->Equals(ci)) {
LOG(("reusing connection [conn=%x]\n", conn));
mIdleConnections.RemoveElementAt(i);
i--;
break;
}
conn = nsnull;
}
if (!conn) {
LOG(("creating new connection...\n"));
LOG((">> creating new connection...\n"));
NS_NEWXPCOM(conn, nsHttpConnection);
if (!conn)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(conn);
rv = conn->Init(ci);
rv = conn->Init(ci, mMaxRequestDelay);
if (NS_FAILED(rv)) {
NS_RELEASE(conn);
return rv;
}
} else {
}
else {
// Update the connectionInfo (bug 94038)
conn->ConnectionInfo()->SetOriginServer(ci->Host(), ci->Port());
}
@@ -750,6 +782,7 @@ nsHttpHandler::InitiateTransaction_Locked(nsHttpTransaction *trans,
PR_Lock(mConnectionLock);
if (NS_FAILED(rv)) {
LOG(("nsHttpConnection::SetTransaction failed [rv=%x]\n", rv));
// the connection may already have been removed from the
// active connection list.
if (mActiveConnections.RemoveElement(conn))
@@ -783,57 +816,41 @@ nsHttpHandler::RemovePendingTransaction(nsHttpTransaction *trans)
return NS_ERROR_NOT_AVAILABLE;
}
PRUint8
nsHttpHandler::CountActiveConnections(nsHttpConnectionInfo *ci)
// we're at the active connection limit if any one of the following conditions is true:
// (1) at max-connections
// (2) keep-alive enabled and at max-persistent-connections-per-host
// (3) keep-alive disabled and at max-connections-per-host
PRBool
nsHttpHandler::AtActiveConnectionLimit(nsHttpConnectionInfo *ci, PRUint8 caps)
{
PRUint8 count = 0;
nsHttpConnection *conn = 0;
LOG(("nsHttpHandler::AtActiveConnectionLimit [host=%s:%d caps=%x]\n",
ci->Host(), ci->Port(), caps));
LOG(("nsHttpHandler::CountActiveConnections [host=%s:%d]\n",
ci->Host(), ci->Port()));
// use >= just to be safe
if (mActiveConnections.Count() >= mMaxConnections)
return PR_TRUE;
nsHttpConnection *conn;
PRUint8 totalCount = 0, persistentCount = 0;
PRInt32 i;
for (i=0; i<mActiveConnections.Count(); ++i) {
conn = NS_STATIC_CAST(nsHttpConnection *, mActiveConnections[i]);
// only include a matching connection in the count...
if (conn->ConnectionInfo()->Equals(ci))
count++;
}
LOG(("found count=%u\n", (PRUintn) count));
return count;
}
PRUint8
nsHttpHandler::CountIdleConnections(nsHttpConnectionInfo *ci)
{
PRUint8 count = 0;
nsHttpConnection *conn = 0;
if (!ci)
return 0;
LOG(("nsHttpHandler::CountIdleConnections [host=%s:%d]\n",
ci->Host(), ci->Port()));
PRInt32 i;
for (i=0; i<mIdleConnections.Count(); ++i) {
conn = NS_STATIC_CAST(nsHttpConnection *, mIdleConnections[i]);
// only include a matching connection in the count if it
// can still be reused.
LOG((">> comparing against active connection [conn=%x host=%s:%d]\n",
conn, conn->ConnectionInfo()->Host(), conn->ConnectionInfo()->Port()));
if (conn->ConnectionInfo()->Equals(ci)) {
if (conn->CanReuse())
count++;
else {
mIdleConnections.RemoveElementAt(i);
NS_RELEASE(conn);
i--;
}
totalCount++;
if (conn->IsKeepAlive())
persistentCount++;
}
}
LOG(("found count=%u\n", (PRUintn) count));
return count;
LOG((" total-count=%u, persistent-count=%u\n",
PRUint32(totalCount), PRUint32(persistentCount)));
// use >= just to be safe
return (totalCount >= mMaxConnectionsPerServer) ||
((caps & NS_HTTP_ALLOW_KEEPALIVE) &&
(persistentCount >= mMaxPersistentConnectionsPerServer));
}
void
@@ -1075,6 +1092,12 @@ nsHttpHandler::PrefsChanged(const char *pref)
mMaxRequestAttempts = (PRUint16) CLAMP(val, 1, 0xffff);
}
if (bChangedAll || PL_strcmp(pref, "network.http.request.max-start-delay") == 0) {
rv = mPrefs->GetIntPref("network.http.request.max-start-delay", &val);
if (NS_SUCCEEDED(rv))
mMaxRequestDelay = (PRUint16) CLAMP(val, 0, 0xffff);
}
if (bChangedAll || PL_strcmp(pref, "network.http.max-connections") == 0) {
rv = mPrefs->GetIntPref("network.http.max-connections", &val);
if (NS_SUCCEEDED(rv))
@@ -1087,18 +1110,10 @@ nsHttpHandler::PrefsChanged(const char *pref)
mMaxConnectionsPerServer = (PRUint8) CLAMP(val, 1, 0xff);
}
/*
if (bChangedAll || PL_strcmp(pref, "network.http.keep-alive.max-connections") == 0) {
rv = mPrefs->GetIntPref("network.http.keep-alive.max-connections", &val);
if (bChangedAll || PL_strcmp(pref, "network.http.max-persistent-connections-per-server") == 0) {
rv = mPrefs->GetIntPref("network.http.max-persistent-connections-per-server", &val);
if (NS_SUCCEEDED(rv))
mMaxIdleConnections = (PRUint16) CLAMP(val, 1, 0xffff);
}
*/
if (bChangedAll || PL_strcmp(pref, "network.http.keep-alive.max-connections-per-server") == 0) {
rv = mPrefs->GetIntPref("network.http.keep-alive.max-connections-per-server", &val);
if (NS_SUCCEEDED(rv))
mMaxIdleConnectionsPerServer = (PRUint8) CLAMP(val, 1, 0xff);
mMaxPersistentConnectionsPerServer = (PRUint8) CLAMP(val, 1, 0xff);
}
if (bChangedAll || PL_strcmp(pref, "network.http.sendRefererHeader") == 0) {
@@ -1787,6 +1802,7 @@ nsPendingTransaction::nsPendingTransaction(nsHttpTransaction *trans,
nsHttpConnectionInfo *ci)
: mTransaction(trans)
, mConnectionInfo(ci)
, mBusy(0)
{
LOG(("Creating nsPendingTransaction @%x\n", this));

View File

@@ -106,9 +106,7 @@ public:
// Called to kick-off a new transaction, by default the transaction
// will be put on the pending transaction queue if it cannot be
// initiated at this time. Callable from any thread.
nsresult InitiateTransaction(nsHttpTransaction *,
nsHttpConnectionInfo *,
PRBool failIfBusy = PR_FALSE);
nsresult InitiateTransaction(nsHttpTransaction *, nsHttpConnectionInfo *);
// Called to cancel a transaction, which may or may not be assigned to
// a connection. Callable from any thread.
@@ -118,6 +116,10 @@ public:
// from any thread.
nsresult ReclaimConnection(nsHttpConnection *);
// Called when a connection has been busy with a single transaction for
// longer than mMaxRequestDelay.
nsresult ProcessTransactionQ();
//
// The HTTP handler caches pointers to specific XPCOM services, and
// provides the following helper routines for accessing those services:
@@ -150,15 +152,19 @@ private:
nsHttpTransaction *Transaction() { return mTransaction; }
nsHttpConnectionInfo *ConnectionInfo() { return mConnectionInfo; }
PRBool IsBusy() { return mBusy; }
void SetBusy(PRBool value) { mBusy = value; }
private:
nsHttpTransaction *mTransaction;
nsHttpConnectionInfo *mConnectionInfo;
PRPackedBool mBusy;
};
//
// Transaction queue helper methods
//
void ProcessTransactionQ();
void ProcessTransactionQ_Locked();
nsresult EnqueueTransaction(nsHttpTransaction *, nsHttpConnectionInfo *);
// Called with mConnectionLock held
@@ -167,10 +173,7 @@ private:
PRBool failIfBusy = PR_FALSE);
nsresult RemovePendingTransaction(nsHttpTransaction *);
PRUint8 CountActiveConnections(nsHttpConnectionInfo *);
PRUint8 CountIdleConnections(nsHttpConnectionInfo *);
PRBool AtActiveConnectionLimit(nsHttpConnectionInfo *, PRUint8 caps);
void DropConnections(nsVoidArray &);
//
@@ -213,10 +216,11 @@ private:
PRUint16 mIdleTimeout;
PRUint16 mMaxRequestAttempts;
PRUint16 mMaxRequestDelay;
PRUint16 mMaxConnections;
PRUint8 mMaxConnectionsPerServer;
PRUint8 mMaxIdleConnectionsPerServer;
PRUint8 mMaxPersistentConnectionsPerServer;
nsCString mAccept;
nsCString mAcceptLanguages;
@@ -230,10 +234,10 @@ private:
PRUint32 mSessionStartTime;
// connection management
nsVoidArray mActiveConnections; // list of nsHttpConnection objects
nsVoidArray mIdleConnections; // list of nsHttpConnection objects
nsVoidArray mTransactionQ; // list of nsPendingTransaction objects
PRLock *mConnectionLock; // protect connection lists
nsVoidArray mActiveConnections; // list of nsHttpConnection objects
nsVoidArray mIdleConnections; // list of nsHttpConnection objects
nsVoidArray mTransactionQ; // list of nsPendingTransaction objects
PRLock *mConnectionLock; // protect connection lists
// useragent components
nsXPIDLCString mAppName;

View File

@@ -38,7 +38,8 @@
//-----------------------------------------------------------------------------
nsHttpTransaction::nsHttpTransaction(nsIStreamListener *listener,
nsIInterfaceRequestor *callbacks)
nsIInterfaceRequestor *callbacks,
PRUint8 caps)
: mListener(listener)
, mCallbacks(callbacks)
, mConnection(nsnull)
@@ -49,6 +50,7 @@ nsHttpTransaction::nsHttpTransaction(nsIStreamListener *listener,
, mTransactionDone(0)
, mStatus(NS_OK)
, mRestartCount(0)
, mCapabilities(caps)
, mHaveStatusLine(PR_FALSE)
, mHaveAllHeaders(PR_FALSE)
, mFiredOnStart(PR_FALSE)

View File

@@ -52,7 +52,7 @@ public:
NS_DECL_NSIINPUTSTREAM
// A transaction is constructed from request headers.
nsHttpTransaction(nsIStreamListener *, nsIInterfaceRequestor *);
nsHttpTransaction(nsIStreamListener *, nsIInterfaceRequestor *, PRUint8 caps);
virtual ~nsHttpTransaction();
nsrefcnt RefCnt() { return mRefCnt; }
@@ -75,6 +75,7 @@ public:
nsISupports *SecurityInfo() { return mSecurityInfo; }
PRBool IsDone() { return mTransactionDone; }
nsresult Status() { return mStatus; }
PRUint8 Capabilities() { return mCapabilities; }
// Called to take ownership of the response headers; the transaction
// will drop any reference to the response headers after this call.
@@ -127,6 +128,7 @@ private:
nsresult mStatus;
PRUint16 mRestartCount; // the number of times this transaction has been restarted
PRUint8 mCapabilities;
PRPackedBool mHaveStatusLine;
PRPackedBool mHaveAllHeaders;