Fixes bug 82181 "bugzilla queries won't submit" r=gagan sr=blizzard a=asa

This commit is contained in:
darin%netscape.com 2001-05-25 23:18:50 +00:00
Родитель 4c871de289
Коммит 1d0e280b41
4 изменённых файлов: 129 добавлений и 16 удалений

Просмотреть файл

@ -45,7 +45,8 @@ static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
static void *PR_CALLBACK
TransactionReleaseEventHandler(PLEvent *ev)
{
nsHttpTransaction *trans = (nsHttpTransaction *) PL_GetEventOwner(ev);
nsHttpTransaction *trans =
NS_STATIC_CAST(nsHttpTransaction *, PL_GetEventOwner(ev));
LOG(("TransactionReleaseEventHandler [trans=%x refcnt=%u] calling release...\n",
trans, trans->RefCnt()));
@ -125,11 +126,11 @@ nsHttpConnection::SetTransaction(nsHttpTransaction *transaction)
NS_ADDREF(mTransaction);
// grab a reference to the calling thread's event queue.
mEventQ = 0;
mConsumerEventQ = 0;
nsCOMPtr<nsIEventQueueService> eqs;
nsHttpHandler::get()->GetEventQueueService(getter_AddRefs(eqs));
if (eqs)
eqs->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(mEventQ));
eqs->ResolveEventQueue(NS_CURRENT_EVENTQ, getter_AddRefs(mConsumerEventQ));
// build a proxy for the progress event sink
mProgressSink = 0;
@ -139,7 +140,7 @@ nsHttpConnection::SetTransaction(nsHttpTransaction *transaction)
nsCOMPtr<nsIProxyObjectManager> mgr;
nsHttpHandler::get()->GetProxyObjectManager(getter_AddRefs(mgr));
if (mgr)
mgr->GetProxyForObject(mEventQ,
mgr->GetProxyForObject(mConsumerEventQ,
NS_GET_IID(nsIProgressEventSink),
temp,
PROXY_ASYNC | PROXY_ALWAYS,
@ -301,7 +302,7 @@ nsHttpConnection::ProxyStepUp()
PRBool
nsHttpConnection::CanReuse()
{
return (mReuseCount < mMaxReuseCount) &&
return mKeepAlive && (mReuseCount < mMaxReuseCount) &&
(NowInSeconds() - mLastActiveTime < mIdleTimeout) && IsAlive();
}
@ -317,6 +318,20 @@ nsHttpConnection::IsAlive()
return isAlive;
}
void
nsHttpConnection::DropTransaction()
{
// the assertion here is that the transaction will not be destroyed
// by this release. we unfortunately don't have a threadsafe way of
// asserting this.
NS_IF_RELEASE(mTransaction);
mTransaction = 0;
mProgressSink = 0;
// if the transaction was dropped, then we cannot reuse this connection.
mKeepAlive = PR_FALSE;
}
void
nsHttpConnection::ReportProgress(PRUint32 progress, PRInt32 progressMax)
{
@ -420,7 +435,7 @@ nsHttpConnection::ProxyReleaseTransaction(nsHttpTransaction *trans)
LOG(("nsHttpConnection::ProxyReleaseTransaction [this=%x trans=%x refcnt=%u]\n",
this, trans, trans->RefCnt()));
NS_ENSURE_TRUE(mEventQ, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_TRUE(mConsumerEventQ, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_ARG_POINTER(trans);
PLEvent *event = new PLEvent;
@ -431,7 +446,7 @@ nsHttpConnection::ProxyReleaseTransaction(nsHttpTransaction *trans)
TransactionReleaseEventHandler,
TransactionReleaseDestroyHandler);
return mEventQ->PostEvent(event);
return mConsumerEventQ->PostEvent(event);
}
nsresult

Просмотреть файл

@ -89,10 +89,12 @@ public:
PRUint32 MaxReuseCount() { return mMaxReuseCount; }
PRUint32 IdleTimeout() { return mIdleTimeout; }
void DropTransaction();
void ReportProgress(PRUint32 progress, PRInt32 progressMax);
nsHttpTransaction *Transaction() { return mTransaction; }
nsHttpConnectionInfo *ConnectionInfo() { return mConnectionInfo; }
nsHttpTransaction *Transaction() { return mTransaction; }
nsHttpConnectionInfo *ConnectionInfo() { return mConnectionInfo; }
nsIEventQueue *ConsumerEventQ() { return mConsumerEventQ; }
private:
enum {
@ -117,7 +119,7 @@ private:
nsCOMPtr<nsIRequest> mReadRequest;
nsCOMPtr<nsIProgressEventSink> mProgressSink;
nsCOMPtr<nsIEventQueue> mEventQ;
nsCOMPtr<nsIEventQueue> mConsumerEventQ;
nsCOMPtr<nsIInputStream> mSSLProxyConnectStream;

Просмотреть файл

@ -30,6 +30,46 @@
#include "nsHttpChunkedDecoder.h"
#include "nsIStringStream.h"
#include "pratom.h"
#include "plevent.h"
//-----------------------------------------------------------------------------
// helpers...
//-----------------------------------------------------------------------------
static void *PR_CALLBACK
TransactionRestartEventHandler(PLEvent *ev)
{
nsHttpTransaction *trans =
NS_STATIC_CAST(nsHttpTransaction *, PL_GetEventOwner(ev));
LOG(("TransactionRestartEventHandler [trans=%x]\n", trans));
NS_PRECONDITION(trans->Connection() &&
trans->Connection()->ConnectionInfo(), "oops");
if (trans->Connection()) {
nsHttpConnectionInfo *ci = trans->Connection()->ConnectionInfo();
if (ci) {
NS_ADDREF(ci);
// clean up the old connection
nsHttpHandler::get()->ReclaimConnection(trans->Connection());
trans->SetConnection(nsnull);
// initiate the transaction again
nsHttpHandler::get()->InitiateTransaction(trans, ci);
NS_RELEASE(ci);
}
}
NS_RELEASE(trans);
return 0;
}
static void PR_CALLBACK
TransactionRestartDestroyHandler(PLEvent *ev)
{
delete ev;
}
//-----------------------------------------------------------------------------
// nsHttpTransaction
@ -50,6 +90,7 @@ nsHttpTransaction::nsHttpTransaction(nsIStreamListener *listener,
, mHaveAllHeaders(PR_FALSE)
, mFiredOnStart(PR_FALSE)
, mNoContent(PR_FALSE)
, mPrematureEOF(PR_FALSE)
{
LOG(("Creating nsHttpTransaction @%x\n", this));
@ -106,12 +147,8 @@ nsHttpTransaction::SetupRequest(nsHttpRequestHead *requestHead,
nsresult
nsHttpTransaction::SetConnection(nsHttpConnection *conn)
{
NS_ENSURE_ARG_POINTER(conn);
NS_ENSURE_TRUE(!mConnection, NS_ERROR_ALREADY_INITIALIZED);
mConnection = conn;
NS_ADDREF(mConnection);
NS_IF_ADDREF(mConnection);
return NS_OK;
}
@ -176,6 +213,28 @@ nsHttpTransaction::OnDataReadable(nsIInputStream *is)
LOG(("nsHttpTransaction: listener returned [rv=%x]\n", rv));
mSource = 0;
// check if this transaction needs to be restarted
if (mPrematureEOF) {
mPrematureEOF = PR_FALSE;
LOG(("restarting transaction @%x\n", this));
// just in case the connection is holding the last reference to us...
NS_ADDREF_THIS();
// we don't want the connection to send anymore notifications to us.
mConnection->DropTransaction();
// the transaction needs to be restarted from the thread on which
// it was created.
rv = ProxyRestartTransaction(mConnection->ConsumerEventQ());
NS_ASSERTION(NS_SUCCEEDED(rv), "ProxyRestartTransaction failed");
NS_RELEASE_THIS();
return NS_BINDING_ABORTED;
}
return rv;
}
@ -447,6 +506,27 @@ nsHttpTransaction::HandleContent(char *buf,
return (!mNoContent && !*countRead) ? NS_BASE_STREAM_WOULD_BLOCK : NS_OK;
}
nsresult
nsHttpTransaction::ProxyRestartTransaction(nsIEventQueue *eventQ)
{
LOG(("nsHttpTransaction::ProxyRestartTransaction [this=%x]\n", this));
NS_ENSURE_ARG_POINTER(eventQ);
NS_PRECONDITION(!mResponseHead, "already received a (partial) response!");
PLEvent *event = new PLEvent;
if (!event)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF_THIS();
PL_InitEvent(event, this,
TransactionRestartEventHandler,
TransactionRestartDestroyHandler);
return eventQ->PostEvent(event);
}
//-----------------------------------------------------------------------------
// nsHttpTransaction::nsISupports
//-----------------------------------------------------------------------------
@ -577,12 +657,25 @@ nsHttpTransaction::Read(char *buf, PRUint32 count, PRUint32 *bytesWritten)
if (mTransactionDone)
return NS_BASE_STREAM_CLOSED;
*bytesWritten = 0;
// read some data from our source and put it in the given buf
rv = mSource->Read(buf, count, bytesWritten);
if (NS_FAILED(rv) || (*bytesWritten == 0)) {
LOG(("mSource->Read [rv=%x count=%u countRead=%u]\n", rv, count, *bytesWritten));
if (NS_FAILED(rv)) {
LOG(("nsHttpTransaction: mSource->Read() returned [rv=%x]\n", rv));
return rv;
}
if (NS_SUCCEEDED(rv) && (*bytesWritten == 0)) {
LOG(("nsHttpTransaction: reached EOF\n"));
if (!mHaveStatusLine) {
// we've read nothing from the socket...
mPrematureEOF = PR_TRUE;
// return would block to prevent being called again.
return NS_BASE_STREAM_WOULD_BLOCK;
}
return rv;
}
// pretend that no bytes were written (since we're just borrowing the
// given buf anyways).

Просмотреть файл

@ -36,6 +36,7 @@ class nsHttpRequestHead;
class nsHttpResponseHead;
class nsHttpConnection;
class nsHttpChunkedDecoder;
class nsIEventQueue;
//-----------------------------------------------------------------------------
// nsHttpTransaction represents a single HTTP transaction. It is thread-safe,
@ -88,6 +89,7 @@ private:
void ParseLineSegment(char *seg, PRUint32 len);
nsresult ParseHead(char *, PRUint32 count, PRUint32 *countRead);
nsresult HandleContent(char *, PRUint32 count, PRUint32 *countRead);
nsresult ProxyRestartTransaction(nsIEventQueue *);
private:
nsCOMPtr<nsIStreamListener> mListener;
@ -116,6 +118,7 @@ private:
PRPackedBool mHaveAllHeaders;
PRPackedBool mFiredOnStart;
PRPackedBool mNoContent; // true if we're expecting an empty entity body
PRPackedBool mPrematureEOF;
};
#endif // nsHttpTransaction_h__