Back to index

lightning-sunbird  0.9+nobinonly
tmQueue.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Transaction Manager.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corp.
00018  * Portions created by the Initial Developer are Copyright (C) 2003
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   John Gaunt <jgaunt@netscape.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "plstr.h"
00039 #include "tmQueue.h"
00040 #include "tmTransaction.h"
00041 #include "tmTransactionManager.h"
00042 #include "tmUtils.h"
00043 
00045 // Constructors & Destructor
00046 
00047 tmQueue::~tmQueue() {
00048 
00049   // empty the vectors
00050   PRUint32 index = 0;
00051   PRUint32 size = mTransactions.Size();
00052   for ( ; index < size ; index++) {
00053     if (mTransactions[index])
00054       delete (tmTransaction *)mTransactions[index];
00055   }
00056 
00057   // don't need to delete the mListeners because 
00058   // we just insert PRUint32s, no allocation
00059 
00060   mTM = nsnull;
00061   mID = 0;
00062   if (mName)
00063     PL_strfree(mName);
00064 }
00065 
00067 // Public Methods
00068 
00069 PRInt32
00070 tmQueue::Init(const char* aName, PRUint32 aID, tmTransactionManager *aTM) {
00071   PR_ASSERT(mTM == nsnull);
00072 
00073   if (NS_SUCCEEDED(mTransactions.Init()) &&
00074       NS_SUCCEEDED(mListeners.Init()) &&
00075       ((mName = PL_strdup(aName)) != nsnull) ) {
00076     mTM = aTM;
00077     mID = aID;
00078     return NS_OK;
00079   }
00080   return -1;
00081 }
00082 
00083 PRInt32
00084 tmQueue::AttachClient(PRUint32 aClientID) {
00085 
00086   PRInt32 status = NS_OK;                 // success of adding client
00087 
00088   if (!IsAttached(aClientID)) {
00089     // add the client to the listener list -- null safe call
00090     status = mListeners.Append((void*) aClientID);
00091   }
00092   else
00093     status = -2;
00094 
00095   // create & init a reply transaction
00096   tmTransaction trans;
00097   if (NS_SUCCEEDED(trans.Init(aClientID,        // owner's ipc ID
00098                               mID,              // client gets our ID
00099                               TM_ATTACH_REPLY,  // action
00100                               status,           // success of the add
00101                               (PRUint8*)mName,  // client matches name to ID
00102                               PL_strlen(mName)+1))) {
00103     // send the reply
00104     mTM->SendTransaction(aClientID, &trans);
00105   }
00106 
00107   // if we successfully added the client - send all current transactions
00108   if (status >= 0) { // append returns the index of the added element
00109     
00110     PRUint32 size = mTransactions.Size();
00111     for (PRUint32 index = 0; index < size; index++) {
00112       if (mTransactions[index])
00113         mTM->SendTransaction(aClientID, (tmTransaction*) mTransactions[index]);
00114     }
00115   }
00116   return status;
00117 }
00118 
00119 PRInt32
00120 tmQueue::DetachClient(PRUint32 aClientID) {
00121 
00122   PRUint32 size = mListeners.Size();
00123   PRUint32 id = 0;
00124   PRInt32 status = -1;
00125 
00126   for (PRUint32 index = 0; index < size; index++) {
00127     id = (PRUint32)NS_PTR_TO_INT32(mListeners[index]);
00128     if(id == aClientID) {
00129       mListeners.RemoveAt(index);
00130       status = NS_OK;
00131       break;
00132     }
00133   }
00134 
00135   tmTransaction trans;
00136   if (NS_SUCCEEDED(trans.Init(aClientID,
00137                                mID,
00138                                TM_DETACH_REPLY,
00139                                status,
00140                                nsnull,
00141                                0))) {
00142     // send the reply
00143     mTM->SendTransaction(aClientID, &trans);
00144   }
00145 
00146   // if we've removed all the listeners, remove the queue.
00147   if (mListeners.Size() == 0)
00148     return TM_SUCCESS_DELETE_QUEUE;
00149   return status;
00150 }
00151 
00152 void
00153 tmQueue::FlushQueue(PRUint32 aClientID) {
00154 
00155   if(!IsAttached(aClientID))
00156     return;
00157 
00158   PRUint32 size = mTransactions.Size();
00159   for (PRUint32 index = 0; index < size; index++)
00160     if (mTransactions[index])
00161       delete (tmTransaction*)mTransactions[index];
00162 
00163   mTransactions.Clear();
00164 
00165   tmTransaction trans;
00166   if (NS_SUCCEEDED(trans.Init(aClientID,
00167                                mID, 
00168                                TM_FLUSH_REPLY, 
00169                                NS_OK,
00170                                nsnull,
00171                                0))) {
00172     mTM->SendTransaction(aClientID, &trans);
00173   }
00174 }
00175 
00176 PRInt32
00177 tmQueue::PostTransaction(tmTransaction *aTrans) {
00178 
00179   PRInt32 status = -1;
00180   PRUint32 ownerID = aTrans->GetOwnerID();
00181 
00182   // if we are attached, have the right queue and have successfully
00183   //    appended the transaction to the queue, send the transaction
00184   //    to all the listeners.
00185 
00186   if (IsAttached(ownerID) && aTrans->GetQueueID() == mID)
00187     status = mTransactions.Append(aTrans);
00188 
00189   if (status >= 0) {
00190     // send the transaction to all members of mListeners except the owner
00191     PRUint32 size = mListeners.Size();
00192     PRUint32 id = 0;
00193     for (PRUint32 index = 0; index < size; index++) {
00194       id = (PRUint32)NS_PTR_TO_INT32(mListeners[index]);
00195       if (ownerID != id)
00196         mTM->SendTransaction(id, aTrans);
00197     }
00198   }
00199 
00200   tmTransaction trans;
00201   if (NS_SUCCEEDED(trans.Init(ownerID,
00202                               mID,
00203                               TM_POST_REPLY,
00204                               status,
00205                               nsnull,
00206                               0))) {
00207     // send the reply
00208     mTM->SendTransaction(ownerID, &trans);
00209   }
00210   return status;
00211 }
00212 
00213 PRBool
00214 tmQueue::IsAttached(PRUint32 aClientID) {
00215   // XXX could be an issue if the aClientID is 0 and there
00216   // is a "hole" in the mListeners vector. - may NEED to store PRUint32*s
00217   PRUint32 size = mListeners.Size();
00218   for (PRUint32 index = 0; index < size; index++) {
00219     if (aClientID == (PRUint32)NS_PTR_TO_INT32(mListeners[index]))
00220       return PR_TRUE;
00221   }
00222   return PR_FALSE;
00223 }