Bug 675873 - Switch nsHttpConnectionMgr from nsHashtable to nsClassHashtable, r=bz
authorMichael Wu <mwu@mozilla.com>
Wed, 03 Aug 2011 18:59:10 -0700
changeset 73815 bc72dc6b31ca1ff719b789e0833f13c624350055
parent 73814 a73864715b24a901f2ce8b5535ca791bce847a60
child 73816 81dd021d45bde24d943f7e1d437611bc5e4301f9
push id20917
push usermak77@bonardo.net
push dateThu, 04 Aug 2011 09:19:44 +0000
treeherdermozilla-central@5d742d2e4304 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs675873
milestone8.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 675873 - Switch nsHttpConnectionMgr from nsHashtable to nsClassHashtable, r=bz
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/protocol/http/nsHttpConnectionMgr.h
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -88,16 +88,17 @@ nsHttpConnectionMgr::nsHttpConnectionMgr
     , mMaxPersistConnsPerHost(0)
     , mMaxPersistConnsPerProxy(0)
     , mIsShuttingDown(PR_FALSE)
     , mNumActiveConns(0)
     , mNumIdleConns(0)
     , mTimeOfNextWakeUp(LL_MAXUINT)
 {
     LOG(("Creating nsHttpConnectionMgr @%x\n", this));
+    mCT.Init();
 }
 
 nsHttpConnectionMgr::~nsHttpConnectionMgr()
 {
     LOG(("Destroying nsHttpConnectionMgr @%x\n", this));
 }
 
 nsresult
@@ -333,18 +334,17 @@ nsHttpConnectionMgr::AddTransactionToPip
 {
     LOG(("nsHttpConnectionMgr::AddTransactionToPipeline [pipeline=%x]\n", pipeline));
 
     NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
 
     nsRefPtr<nsHttpConnectionInfo> ci;
     pipeline->GetConnectionInfo(getter_AddRefs(ci));
     if (ci) {
-        nsCStringKey key(ci->HashKey());
-        nsConnectionEntry *ent = (nsConnectionEntry *) mCT.Get(&key);
+        nsConnectionEntry *ent = mCT.Get(ci->HashKey());
         if (ent) {
             // search for another request to pipeline...
             PRInt32 i, count = ent->mPendingQ.Length();
             for (i=0; i<count; ++i) {
                 nsHttpTransaction *trans = ent->mPendingQ[i];
                 if (trans->Caps() & NS_HTTP_ALLOW_PIPELINING) {
                     pipeline->AddTransaction(trans);
 
@@ -395,76 +395,77 @@ nsHttpConnectionMgr::CloseIdleConnection
     NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
     LOG(("nsHttpConnectionMgr::CloseIdleConnection %p conn=%p",
          this, conn));
 
     nsHttpConnectionInfo *ci = conn->ConnectionInfo();
     if (!ci)
         return NS_ERROR_UNEXPECTED;
 
-    nsCStringKey key(ci->HashKey());
-    nsConnectionEntry *ent = (nsConnectionEntry *) mCT.Get(&key);
+    nsConnectionEntry *ent = mCT.Get(ci->HashKey());
 
     if (!ent || !ent->mIdleConns.RemoveElement(conn))
         return NS_ERROR_UNEXPECTED;
 
     conn->Close(NS_ERROR_ABORT);
     NS_RELEASE(conn);
     mNumIdleConns--;
     if (0 == mNumIdleConns)
         StopPruneDeadConnectionsTimer();
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 // enumeration callbacks
 
-PRIntn
-nsHttpConnectionMgr::ProcessOneTransactionCB(nsHashKey *key, void *data, void *closure)
+PLDHashOperator
+nsHttpConnectionMgr::ProcessOneTransactionCB(const nsACString &key,
+                                             nsAutoPtr<nsConnectionEntry> &ent,
+                                             void *closure)
 {
     nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure;
-    nsConnectionEntry *ent = (nsConnectionEntry *) data;
 
     if (self->ProcessPendingQForEntry(ent))
-        return kHashEnumerateStop;
+        return PL_DHASH_STOP;
 
-    return kHashEnumerateNext;
+    return PL_DHASH_NEXT;
 }
 
 // If the global number of idle connections is preventing the opening of
 // new connections to a host without idle connections, then
 // close them regardless of their TTL
-PRIntn
-nsHttpConnectionMgr::PurgeExcessIdleConnectionsCB(nsHashKey *key,
-                                                  void *data, void *closure)
+PLDHashOperator
+nsHttpConnectionMgr::PurgeExcessIdleConnectionsCB(const nsACString &key,
+                                                  nsAutoPtr<nsConnectionEntry> &ent,
+                                                  void *closure)
 {
     nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure;
-    nsConnectionEntry *ent = (nsConnectionEntry *) data;
 
     while (self->mNumIdleConns + self->mNumActiveConns + 1 >= self->mMaxConns) {
         if (!ent->mIdleConns.Length()) {
             // There are no idle conns left in this connection entry
-            return kHashEnumerateNext;
+            return PL_DHASH_NEXT;
         }
         nsHttpConnection *conn = ent->mIdleConns[0];
         ent->mIdleConns.RemoveElementAt(0);
         conn->Close(NS_ERROR_ABORT);
         NS_RELEASE(conn);
         self->mNumIdleConns--;
         if (0 == self->mNumIdleConns)
             self->StopPruneDeadConnectionsTimer();
     }
-    return kHashEnumerateStop;
+    return PL_DHASH_STOP;
 }
 
-PRIntn
-nsHttpConnectionMgr::PruneDeadConnectionsCB(nsHashKey *key, void *data, void *closure)
+PLDHashOperator
+nsHttpConnectionMgr::PruneDeadConnectionsCB(const nsACString &key,
+                                            nsAutoPtr<nsConnectionEntry> &ent,
+                                            void *closure)
 {
     nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure;
-    nsConnectionEntry *ent = (nsConnectionEntry *) data;
 
     LOG(("  pruning [ci=%s]\n", ent->mConnInfo->HashKey().get()));
 
     // Find out how long it will take for next idle connection to not be reusable
     // anymore.
     PRUint32 timeToNextExpire = PR_UINT32_MAX;
     PRInt32 count = ent->mIdleConns.Length();
     if (count > 0) {
@@ -507,33 +508,33 @@ nsHttpConnectionMgr::PruneDeadConnection
 #endif
 
     // if this entry is empty, then we can remove it.
     if (ent->mIdleConns.Length()   == 0 &&
         ent->mActiveConns.Length() == 0 &&
         ent->mHalfOpens.Length()   == 0 &&
         ent->mPendingQ.Length()    == 0) {
         LOG(("    removing empty connection entry\n"));
-        delete ent;
-        return kHashEnumerateRemove;
+        return PL_DHASH_REMOVE;
     }
 
     // else, use this opportunity to compact our arrays...
     ent->mIdleConns.Compact();
     ent->mActiveConns.Compact();
     ent->mPendingQ.Compact();
 
-    return kHashEnumerateNext;
+    return PL_DHASH_NEXT;
 }
 
-PRIntn
-nsHttpConnectionMgr::ShutdownPassCB(nsHashKey *key, void *data, void *closure)
+PLDHashOperator
+nsHttpConnectionMgr::ShutdownPassCB(const nsACString &key,
+                                    nsAutoPtr<nsConnectionEntry> &ent,
+                                    void *closure)
 {
     nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure;
-    nsConnectionEntry *ent = (nsConnectionEntry *) data;
 
     nsHttpTransaction *trans;
     nsHttpConnection *conn;
 
     // close all active connections
     while (ent->mActiveConns.Length()) {
         conn = ent->mActiveConns[0];
 
@@ -568,18 +569,17 @@ nsHttpConnectionMgr::ShutdownPassCB(nsHa
         trans->Close(NS_ERROR_ABORT);
         NS_RELEASE(trans);
     }
 
     // close all half open tcp connections
     for (PRInt32 i = ((PRInt32) ent->mHalfOpens.Length()) - 1; i >= 0; i--)
         ent->mHalfOpens[i]->Abandon();
 
-    delete ent;
-    return kHashEnumerateRemove;
+    return PL_DHASH_REMOVE;
 }
 
 //-----------------------------------------------------------------------------
 
 PRBool
 nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent)
 {
     LOG(("nsHttpConnectionMgr::ProcessPendingQForEntry [ci=%s]\n",
@@ -702,24 +702,24 @@ nsHttpConnectionMgr::ClosePersistentConn
         NS_RELEASE(conn);
     }
     
     PRInt32 activeCount = ent->mActiveConns.Length();
     for (PRInt32 i=0; i < activeCount; i++)
         ent->mActiveConns[i]->DontReuse();
 }
 
-PRIntn
-nsHttpConnectionMgr::ClosePersistentConnectionsCB(nsHashKey *key,
-                                                  void *data, void *closure)
+PLDHashOperator
+nsHttpConnectionMgr::ClosePersistentConnectionsCB(const nsACString &key,
+                                                  nsAutoPtr<nsConnectionEntry> &ent,
+                                                  void *closure)
 {
     nsHttpConnectionMgr *self = static_cast<nsHttpConnectionMgr *>(closure);
-    nsConnectionEntry *ent = static_cast<nsConnectionEntry *>(data);
     self->ClosePersistentConnections(ent);
-    return kHashEnumerateNext;
+    return PL_DHASH_NEXT;
 }
 
 void
 nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent,
                                    nsHttpTransaction *trans,
                                    PRBool onlyReusedConnection,
                                    nsHttpConnection **result)
 {
@@ -942,26 +942,25 @@ nsHttpConnectionMgr::ProcessNewTransacti
         LOG(("  transaction was canceled... dropping event!\n"));
         return NS_OK;
     }
 
     PRUint8 caps = trans->Caps();
     nsHttpConnectionInfo *ci = trans->ConnectionInfo();
     NS_ASSERTION(ci, "no connection info");
 
-    nsCStringKey key(ci->HashKey());
-    nsConnectionEntry *ent = (nsConnectionEntry *) mCT.Get(&key);
+    nsConnectionEntry *ent = mCT.Get(ci->HashKey());
     if (!ent) {
         nsHttpConnectionInfo *clone = ci->Clone();
         if (!clone)
             return NS_ERROR_OUT_OF_MEMORY;
         ent = new nsConnectionEntry(clone);
         if (!ent)
             return NS_ERROR_OUT_OF_MEMORY;
-        mCT.Put(&key, ent);
+        mCT.Put(ci->HashKey(), ent);
     }
 
     // If we are doing a force reload then close out any existing conns
     // to this host so that changes in DNS, LBs, etc.. are reflected
     if (caps & NS_HTTP_CLEAR_KEEPALIVES)
         ClosePersistentConnections(ent);
 
     // Check if the transaction already has a sticky reference to a connection.
@@ -1000,17 +999,17 @@ nsHttpConnectionMgr::ProcessNewTransacti
 
 //-----------------------------------------------------------------------------
 
 void
 nsHttpConnectionMgr::OnMsgShutdown(PRInt32, void *)
 {
     LOG(("nsHttpConnectionMgr::OnMsgShutdown\n"));
 
-    mCT.Reset(ShutdownPassCB, this);
+    mCT.Enumerate(ShutdownPassCB, this);
 
     // signal shutdown complete
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     mon.Notify();
 }
 
 void
 nsHttpConnectionMgr::OnMsgNewTransaction(PRInt32 priority, void *param)
@@ -1029,18 +1028,17 @@ void
 nsHttpConnectionMgr::OnMsgReschedTransaction(PRInt32 priority, void *param)
 {
     LOG(("nsHttpConnectionMgr::OnMsgNewTransaction [trans=%p]\n", param));
 
     nsHttpTransaction *trans = (nsHttpTransaction *) param;
     trans->SetPriority(priority);
 
     nsHttpConnectionInfo *ci = trans->ConnectionInfo();
-    nsCStringKey key(ci->HashKey());
-    nsConnectionEntry *ent = (nsConnectionEntry *) mCT.Get(&key);
+    nsConnectionEntry *ent = mCT.Get(ci->HashKey());
     if (ent) {
         PRInt32 index = ent->mPendingQ.IndexOf(trans);
         if (index >= 0) {
             ent->mPendingQ.RemoveElementAt(index);
             InsertTransactionSorted(ent->mPendingQ, trans);
         }
     }
 
@@ -1058,18 +1056,17 @@ nsHttpConnectionMgr::OnMsgCancelTransact
     // then ask the connection to close the transaction.  otherwise, close the
     // transaction directly (removing it from the pending queue first).
     //
     nsAHttpConnection *conn = trans->Connection();
     if (conn && !trans->IsDone())
         conn->CloseTransaction(trans, reason);
     else {
         nsHttpConnectionInfo *ci = trans->ConnectionInfo();
-        nsCStringKey key(ci->HashKey());
-        nsConnectionEntry *ent = (nsConnectionEntry *) mCT.Get(&key);
+        nsConnectionEntry *ent = mCT.Get(ci->HashKey());
         if (ent) {
             PRInt32 index = ent->mPendingQ.IndexOf(trans);
             if (index >= 0) {
                 ent->mPendingQ.RemoveElementAt(index);
                 nsHttpTransaction *temp = trans;
                 NS_RELEASE(temp); // b/c NS_RELEASE nulls its argument!
             }
         }
@@ -1081,18 +1078,17 @@ nsHttpConnectionMgr::OnMsgCancelTransact
 void
 nsHttpConnectionMgr::OnMsgProcessPendingQ(PRInt32, void *param)
 {
     nsHttpConnectionInfo *ci = (nsHttpConnectionInfo *) param;
 
     LOG(("nsHttpConnectionMgr::OnMsgProcessPendingQ [ci=%s]\n", ci->HashKey().get()));
 
     // start by processing the queue identified by the given connection info.
-    nsCStringKey key(ci->HashKey());
-    nsConnectionEntry *ent = (nsConnectionEntry *) mCT.Get(&key);
+    nsConnectionEntry *ent = mCT.Get(ci->HashKey());
     if (!(ent && ProcessPendingQForEntry(ent))) {
         // if we reach here, it means that we couldn't dispatch a transaction
         // for the specified connection info.  walk the connection table...
         mCT.Enumerate(ProcessOneTransactionCB, this);
     }
 
     NS_RELEASE(ci);
 }
@@ -1127,18 +1123,17 @@ nsHttpConnectionMgr::OnMsgReclaimConnect
     // 1) remove the connection from the active list
     // 2) if keep-alive, add connection to idle list
     // 3) post event to process the pending transaction queue
     //
 
     nsHttpConnectionInfo *ci = conn->ConnectionInfo();
     NS_ADDREF(ci);
 
-    nsCStringKey key(ci->HashKey());
-    nsConnectionEntry *ent = (nsConnectionEntry *) mCT.Get(&key);
+    nsConnectionEntry *ent = mCT.Get(ci->HashKey());
 
     NS_ASSERTION(ent, "no connection entry");
     if (ent) {
         // If the connection is in the active list, remove that entry
         // and the reference held by the mActiveConns list.
         // This is never the final reference on conn as the event context
         // is also holding one that is released at the end of this function.
         if (ent->mActiveConns.RemoveElement(conn)) {
--- a/netwerk/protocol/http/nsHttpConnectionMgr.h
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.h
@@ -39,17 +39,17 @@
 #ifndef nsHttpConnectionMgr_h__
 #define nsHttpConnectionMgr_h__
 
 #include "nsHttpConnectionInfo.h"
 #include "nsHttpConnection.h"
 #include "nsHttpTransaction.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
-#include "nsHashtable.h"
+#include "nsClassHashtable.h"
 #include "nsAutoPtr.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "nsISocketTransportService.h"
 
 #include "nsIObserver.h"
 #include "nsITimer.h"
 
 class nsHttpPipeline;
@@ -257,22 +257,22 @@ private:
     PRUint16 mMaxPipelinedRequests;
 
     PRPackedBool mIsShuttingDown;
 
     //-------------------------------------------------------------------------
     // NOTE: these members are only accessed on the socket transport thread
     //-------------------------------------------------------------------------
 
-    static PRIntn ProcessOneTransactionCB(nsHashKey *, void *, void *);
+    static PLDHashOperator ProcessOneTransactionCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
 
-    static PRIntn PruneDeadConnectionsCB(nsHashKey *, void *, void *);
-    static PRIntn ShutdownPassCB(nsHashKey *, void *, void *);
-    static PRIntn PurgeExcessIdleConnectionsCB(nsHashKey *, void *, void *);
-    static PRIntn ClosePersistentConnectionsCB(nsHashKey *, void *, void *);
+    static PLDHashOperator PruneDeadConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
+    static PLDHashOperator ShutdownPassCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
+    static PLDHashOperator PurgeExcessIdleConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
+    static PLDHashOperator ClosePersistentConnectionsCB(const nsACString &, nsAutoPtr<nsConnectionEntry> &, void *);
     PRBool   ProcessPendingQForEntry(nsConnectionEntry *);
     PRBool   AtActiveConnectionLimit(nsConnectionEntry *, PRUint8 caps);
     void     GetConnection(nsConnectionEntry *, nsHttpTransaction *,
                            PRBool, nsHttpConnection **);
     nsresult DispatchTransaction(nsConnectionEntry *, nsAHttpTransaction *,
                                  PRUint8 caps, nsHttpConnection *);
     PRBool   BuildPipeline(nsConnectionEntry *, nsAHttpTransaction *, nsHttpPipeline **);
     nsresult ProcessNewTransaction(nsHttpTransaction *);
@@ -352,14 +352,14 @@ private:
     PRUint64 mTimeOfNextWakeUp;
     // Timer for next pruning of dead connections.
     nsCOMPtr<nsITimer> mTimer;
 
     //
     // the connection table
     //
     // this table is indexed by connection key.  each entry is a
-    // ConnectionEntry object.
+    // nsConnectionEntry object.
     //
-    nsHashtable mCT;
+    nsClassHashtable<nsCStringHashKey, nsConnectionEntry> mCT;
 };
 
 #endif // !nsHttpConnectionMgr_h__