Back to index

lightning-sunbird  0.9+nobinonly
nsHttpConnectionMgr.h
Go to the documentation of this file.
00001 /* vim:set ts=4 sw=4 sts=4 et cin: */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Darin Fisher <darin@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #ifndef nsHttpConnectionMgr_h__
00040 #define nsHttpConnectionMgr_h__
00041 
00042 #include "nsHttpConnectionInfo.h"
00043 #include "nsHttpConnection.h"
00044 #include "nsHttpTransaction.h"
00045 #include "nsHashtable.h"
00046 #include "prmon.h"
00047 
00048 #include "nsIEventTarget.h"
00049 
00050 class nsHttpPipeline;
00051 
00052 //-----------------------------------------------------------------------------
00053 
00054 class nsHttpConnectionMgr
00055 {
00056 public:
00057 
00058     // parameter names
00059     enum nsParamName {
00060         MAX_CONNECTIONS,
00061         MAX_CONNECTIONS_PER_HOST,
00062         MAX_CONNECTIONS_PER_PROXY,
00063         MAX_PERSISTENT_CONNECTIONS_PER_HOST,
00064         MAX_PERSISTENT_CONNECTIONS_PER_PROXY,
00065         MAX_REQUEST_DELAY,
00066         MAX_PIPELINED_REQUESTS
00067     };
00068 
00069     //-------------------------------------------------------------------------
00070     // NOTE: functions below may only be called on the main thread.
00071     //-------------------------------------------------------------------------
00072 
00073     nsHttpConnectionMgr();
00074 
00075     nsresult Init(PRUint16 maxConnections,
00076                   PRUint16 maxConnectionsPerHost,
00077                   PRUint16 maxConnectionsPerProxy,
00078                   PRUint16 maxPersistentConnectionsPerHost,
00079                   PRUint16 maxPersistentConnectionsPerProxy,
00080                   PRUint16 maxRequestDelay,
00081                   PRUint16 maxPipelinedRequests);
00082     nsresult Shutdown();
00083 
00084     //-------------------------------------------------------------------------
00085     // NOTE: functions below may be called on any thread.
00086     //-------------------------------------------------------------------------
00087 
00088     nsrefcnt AddRef()
00089     {
00090         return PR_AtomicIncrement(&mRef);
00091     }
00092 
00093     nsrefcnt Release()
00094     {
00095         nsrefcnt n = PR_AtomicDecrement(&mRef);
00096         if (n == 0)
00097             delete this;
00098         return n;
00099     }
00100 
00101     // adds a transaction to the list of managed transactions.
00102     nsresult AddTransaction(nsHttpTransaction *, PRInt32 priority);
00103 
00104     // called to reschedule the given transaction.  it must already have been
00105     // added to the connection manager via AddTransaction.
00106     nsresult RescheduleTransaction(nsHttpTransaction *, PRInt32 priority);
00107 
00108     // cancels a transaction w/ the given reason.
00109     nsresult CancelTransaction(nsHttpTransaction *, nsresult reason);
00110 
00111     // called to force the connection manager to prune its list of idle
00112     // connections.
00113     nsresult PruneDeadConnections();
00114 
00115     // called to get a reference to the socket transport service.  the socket
00116     // transport service is not available when the connection manager is down.
00117     nsresult GetSocketThreadEventTarget(nsIEventTarget **);
00118 
00119     // called when a connection is done processing a transaction.  if the 
00120     // connection can be reused then it will be added to the idle list, else
00121     // it will be closed.
00122     nsresult ReclaimConnection(nsHttpConnection *conn);
00123 
00124     // called to update a parameter after the connection manager has already
00125     // been initialized.
00126     nsresult UpdateParam(nsParamName name, PRUint16 value);
00127 
00128     //-------------------------------------------------------------------------
00129     // NOTE: functions below may be called only on the socket thread.
00130     //-------------------------------------------------------------------------
00131 
00132     // removes the next transaction for the specified connection from the
00133     // pending transaction queue.
00134     void AddTransactionToPipeline(nsHttpPipeline *);
00135 
00136     // called to force the transaction queue to be processed once more, giving
00137     // preference to the specified connection.
00138     nsresult ProcessPendingQ(nsHttpConnectionInfo *);
00139 
00140 private:
00141     virtual ~nsHttpConnectionMgr();
00142 
00143     // nsConnectionEntry
00144     //
00145     // mCT maps connection info hash key to nsConnectionEntry object, which
00146     // contains list of active and idle connections as well as the list of
00147     // pending transactions.
00148     //
00149     struct nsConnectionEntry
00150     {
00151         nsConnectionEntry(nsHttpConnectionInfo *ci)
00152             : mConnInfo(ci)
00153         {
00154             NS_ADDREF(mConnInfo);
00155         }
00156        ~nsConnectionEntry() { NS_RELEASE(mConnInfo); }
00157 
00158         nsHttpConnectionInfo *mConnInfo;
00159         nsVoidArray           mPendingQ;    // pending transaction queue
00160         nsVoidArray           mActiveConns; // active connections
00161         nsVoidArray           mIdleConns;   // idle persistent connections
00162     };
00163 
00164     // nsConnectionHandle
00165     //
00166     // thin wrapper around a real connection, used to keep track of references
00167     // to the connection to determine when the connection may be reused.  the
00168     // transaction (or pipeline) owns a reference to this handle.  this extra
00169     // layer of indirection greatly simplifies consumer code, avoiding the
00170     // need for consumer code to know when to give the connection back to the
00171     // connection manager.
00172     //
00173     class nsConnectionHandle : public nsAHttpConnection
00174     {
00175     public:
00176         NS_DECL_ISUPPORTS
00177         NS_DECL_NSAHTTPCONNECTION
00178 
00179         nsConnectionHandle(nsHttpConnection *conn) { NS_ADDREF(mConn = conn); }
00180         virtual ~nsConnectionHandle();
00181 
00182         nsHttpConnection *mConn;
00183     };
00184 
00185     //-------------------------------------------------------------------------
00186     // NOTE: these members may be accessed from any thread (use mMonitor)
00187     //-------------------------------------------------------------------------
00188 
00189     PRInt32                   mRef;
00190     PRMonitor                *mMonitor;
00191     nsCOMPtr<nsIEventTarget>  mSTEventTarget; // event target for socket thread
00192 
00193     // connection limits
00194     PRUint16 mMaxConns;
00195     PRUint16 mMaxConnsPerHost;
00196     PRUint16 mMaxConnsPerProxy;
00197     PRUint16 mMaxPersistConnsPerHost;
00198     PRUint16 mMaxPersistConnsPerProxy;
00199     PRUint16 mMaxRequestDelay; // in seconds
00200     PRUint16 mMaxPipelinedRequests;
00201 
00202     //-------------------------------------------------------------------------
00203     // NOTE: these members are only accessed on the socket transport thread
00204     //-------------------------------------------------------------------------
00205 
00206     static PRIntn PR_CALLBACK ProcessOneTransactionCB(nsHashKey *, void *, void *);
00207     static PRIntn PR_CALLBACK PurgeOneIdleConnectionCB(nsHashKey *, void *, void *);
00208     static PRIntn PR_CALLBACK PruneDeadConnectionsCB(nsHashKey *, void *, void *);
00209     static PRIntn PR_CALLBACK ShutdownPassCB(nsHashKey *, void *, void *);
00210 
00211     PRBool   ProcessPendingQForEntry(nsConnectionEntry *);
00212     PRBool   AtActiveConnectionLimit(nsConnectionEntry *, PRUint8 caps);
00213     void     GetConnection(nsConnectionEntry *, PRUint8 caps, nsHttpConnection **);
00214     nsresult DispatchTransaction(nsConnectionEntry *, nsAHttpTransaction *,
00215                                  PRUint8 caps, nsHttpConnection *);
00216     PRBool   BuildPipeline(nsConnectionEntry *, nsAHttpTransaction *, nsHttpPipeline **);
00217     nsresult ProcessNewTransaction(nsHttpTransaction *);
00218 
00219     // message handlers have this signature
00220     typedef void (nsHttpConnectionMgr:: *nsConnEventHandler)(PRInt32, void *);
00221 
00222     // nsConnEvent
00223     //
00224     // subclass of PLEvent used to marshall events to the socket transport
00225     // thread.  this class is used to implement PostEvent.
00226     //
00227     class nsConnEvent;
00228     friend class nsConnEvent;
00229     class nsConnEvent : public PLEvent
00230     {
00231     public:
00232         nsConnEvent(nsHttpConnectionMgr *mgr,
00233                     nsConnEventHandler handler,
00234                     PRInt32 iparam,
00235                     void *vparam)
00236             : mHandler(handler)
00237             , mIParam(iparam)
00238             , mVParam(vparam)
00239         {
00240             NS_ADDREF(mgr);
00241             PL_InitEvent(this, mgr, HandleEvent, DestroyEvent);
00242         }
00243 
00244         PR_STATIC_CALLBACK(void*) HandleEvent(PLEvent *event)
00245         {
00246             nsHttpConnectionMgr *mgr = (nsHttpConnectionMgr *) event->owner;
00247             nsConnEvent *self = (nsConnEvent *) event;
00248             nsConnEventHandler handler = self->mHandler;
00249             (mgr->*handler)(self->mIParam, self->mVParam);
00250             NS_RELEASE(mgr);
00251             return nsnull;
00252         }
00253         PR_STATIC_CALLBACK(void) DestroyEvent(PLEvent *event)
00254         {
00255             delete (nsConnEvent *) event;
00256         }
00257 
00258     private:
00259         nsConnEventHandler  mHandler;
00260         PRInt32             mIParam;
00261         void               *mVParam;
00262     };
00263 
00264     nsresult PostEvent(nsConnEventHandler  handler,
00265                        PRInt32             iparam = 0,
00266                        void               *vparam = nsnull);
00267 
00268     // message handlers
00269     void OnMsgShutdown             (PRInt32, void *);
00270     void OnMsgNewTransaction       (PRInt32, void *);
00271     void OnMsgReschedTransaction   (PRInt32, void *);
00272     void OnMsgCancelTransaction    (PRInt32, void *);
00273     void OnMsgProcessPendingQ      (PRInt32, void *);
00274     void OnMsgPruneDeadConnections (PRInt32, void *);
00275     void OnMsgReclaimConnection    (PRInt32, void *);
00276     void OnMsgUpdateParam          (PRInt32, void *);
00277 
00278     // counters
00279     PRUint16 mNumActiveConns;
00280     PRUint16 mNumIdleConns;
00281 
00282     //
00283     // the connection table
00284     //
00285     // this table is indexed by connection key.  each entry is a
00286     // ConnectionEntry object.
00287     //
00288     nsHashtable mCT;
00289 };
00290 
00291 #endif // !nsHttpConnectionMgr_h__