Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

MultiSRPC.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Last modified on Fri Apr 22 14:19:09 EDT 2005 by irina.furman@intel.com 
00020 //      modified on Wed Oct 29 16:13:25 EST 2003 by ken@xorian.net   
00021 //      modified on Tue Feb  8 14:00:08 PST 2000 by mann   
00022 //      modified on Mon Jun 16 11:07:42 PDT 1997 by heydon 
00023 //      modified on Mon Jun 24 15:31:30 PDT 1996 by levin  
00024 
00025 #include <Basics.H>
00026 
00027 #include "SRPC.H"
00028 #include "MultiSRPC.H"
00029 
00030 const int DefaultConnections = 3;
00031 
00032 #define LOCK(mu) (mu).lock(); try {
00033 #define UNLOCK(mu) } catch (...) { (mu).unlock(); throw; } (mu).unlock()
00034 
00035 MultiSRPC::Entry::~Entry() throw ()
00036 {
00037     if (this->srpc != (SRPC *)NULL) {
00038         delete this->srpc;
00039         this->srpc = (SRPC *)NULL;
00040     }
00041 }
00042 
00043 MultiSRPC::MultiSRPC(const Text &interface)
00044   : intf(interface), next(0), num(DefaultConnections)
00045 {
00046     this->tbl = NEW_ARRAY(MultiSRPC::EntryPtr, this->num);
00047     for (int i = 0; i < this->num; i++) {
00048         this->tbl[i] = (MultiSRPC::EntryPtr)NULL;
00049     }
00050 }
00051 
00052 MultiSRPC::~MultiSRPC()
00053 {
00054     // free up table of connections
00055     LOCK(this->mu);
00056     if (this->tbl != (MultiSRPC::EntryPtr *)NULL) {
00057         for (int i = 0; i < this->next; i++) {
00058             delete this->tbl[i];
00059             this->tbl[i] = (MultiSRPC::EntryPtr)NULL;
00060         }
00061         delete[] this->tbl;
00062         this->tbl = (MultiSRPC::EntryPtr *)NULL;
00063     }
00064     UNLOCK(this->mu);
00065 }
00066 
00067 MultiSRPC::ConnId
00068 MultiSRPC::Start(const Text &hostname, const Text &interface, SRPC*& srpc)
00069   throw(SRPC::failure)
00070 {
00071     Text tIntf(this->intf);
00072     if (this->intf.Empty()) {
00073       if (interface.Empty())
00074         throw(SRPC::failure(SRPC::invalid_parameter,
00075                             "Interface not specified"));
00076       else tIntf = interface;
00077     } else if (!interface.Empty())
00078       throw(SRPC::failure(SRPC::invalid_parameter,
00079                           "Interface specified in constructor"));
00080     // assert: precisely one of intf and interface is Empty()
00081     // assert: tIntf != ""
00082 
00083     int res, availEntry = -1;
00084 
00085     // Search for existing connection not in use.
00086     this->mu.lock();
00087     try
00088       {
00089         for (res = 0; res < this->next; res++) {
00090           if (!(this->tbl[res]->inUse) &&
00091               (this->tbl[res]->srpc != (SRPC *)NULL) &&
00092               !(this->tbl[res]->srpc->alive())) {
00093             // Delete dead connection
00094             delete this->tbl[res]->srpc;
00095             this->tbl[res]->srpc = (SRPC *)NULL;
00096           }         
00097           if (!(this->tbl[res]->inUse) &&
00098               (this->tbl[res]->srpc != (SRPC *)NULL) &&
00099               (hostname == this->tbl[res]->hostname) &&
00100               (tIntf == this->tbl[res]->interface)) {
00101             // Found existing connection
00102             break;
00103           }
00104           if (!(this->tbl[res]->inUse) &&
00105               (this->tbl[res]->srpc == (SRPC *)NULL)) {
00106             // Remember available slot
00107             availEntry = res;
00108           }
00109         }
00110       }
00111     catch(...)
00112       {
00113         this->mu.unlock();
00114         throw;
00115       }
00116 
00117     // If we found an entry, note that it's in use and return it to
00118     // the caller.
00119     if(res < this->next)
00120       {
00121         this->tbl[res]->inUse = true;
00122         srpc = this->tbl[res]->srpc;
00123         this->mu.unlock();
00124         return res;
00125       }
00126 
00127     // no existing connection found -- create a new one
00128     if (availEntry >= 0) {
00129       // use an existing entry
00130       res = availEntry;
00131       tbl[res]->hostname = hostname;
00132       tbl[res]->interface = tIntf;
00133     } else {
00134       // use the next available entry in the array
00135       if (this->next >= this->num) {
00136         // no more space in table -- make it larger
00137         this->num *= 2;
00138         MultiSRPC::EntryPtr *newTbl = 
00139           NEW_ARRAY(MultiSRPC::EntryPtr, this->num);
00140         int i;
00141         for (i = 0; i < this->next; i++) {
00142           newTbl[i] = this->tbl[i]; // pointer copy
00143           this->tbl[i] = (MultiSRPC::EntryPtr)NULL;
00144         }
00145         while (i < this->num) newTbl[i++] = (MultiSRPC::EntryPtr)NULL;
00146         delete[] this->tbl;
00147         this->tbl = newTbl;
00148       }
00149       res = this->next++;
00150       this->tbl[res] = NEW(Entry);
00151       this->tbl[res]->hostname = hostname;
00152       this->tbl[res]->interface = tIntf;
00153     }
00154     // Note that this entry is in use.
00155     this->tbl[res]->inUse = true;
00156     // Release the lock on this object during connection establishment
00157     // (as it is potentially long-running).
00158     this->mu.unlock();
00159 
00160     // Create the new SRPC object.
00161     SRPC *new_srpc = 0;
00162     try
00163       {
00164         new_srpc = NEW_CONSTR(SRPC, (SRPC::caller, tIntf, hostname));
00165       }
00166     catch(...)
00167       {
00168         // If we fail to create the new SRPC object, mark this table
00169         // entry as not in use.
00170         this->mu.lock();
00171         this->tbl[res]->inUse = false;
00172         this->mu.unlock();
00173         throw;
00174       }
00175 
00176     // Re-acquire the lock, record the new SRPC object in the table,
00177     // and return it to the caller.
00178     this->mu.lock();
00179     srpc = this->tbl[res]->srpc = new_srpc;
00180     this->mu.unlock();
00181     return res;
00182 }
00183 
00184 void MultiSRPC::End(MultiSRPC::ConnId id) throw ()
00185 {
00186     if (id >= 0) {
00187         LOCK(this->mu);
00188         this->tbl[id]->inUse = false;
00189         if (!(this->tbl[id]->srpc->alive())) {
00190             // A failure has occurred on this SRPC, so delete the SRPC resource
00191             // and set the "srpc" field to NULL to indicate that this entry is
00192             // available for re-use.
00193             delete this->tbl[id]->srpc;
00194             this->tbl[id]->srpc = (SRPC *)NULL;
00195         }
00196         UNLOCK(this->mu);
00197     }
00198 }
00199 
00200 void MultiSRPC::Discard(MultiSRPC::ConnId id) throw ()
00201 {
00202     if (id >= 0) {
00203         LOCK(this->mu);
00204         this->tbl[id]->inUse = false;
00205         delete this->tbl[id]->srpc;
00206         this->tbl[id]->srpc = (SRPC *)NULL;
00207         UNLOCK(this->mu);
00208     }
00209 }
00210 
00211 void
00212 MultiSRPC::Purge(const Text &hostname, const Text &interface) throw(SRPC::failure)
00213 {
00214     Text tIntf(this->intf);
00215     if (this->intf.Empty()) {
00216       if (interface.Empty())
00217         throw(SRPC::failure(SRPC::invalid_parameter,
00218                             "Interface not specified"));
00219       else tIntf = interface;
00220     } else if (!interface.Empty())
00221       throw(SRPC::failure(SRPC::invalid_parameter,
00222                           "Interface specified in constructor"));
00223     // assert: precisely one of intf and interface is Empty()
00224     // assert: tIntf != ""
00225 
00226     int res, availEntry = -1;
00227 
00228     // search for existing connections not in use
00229     LOCK(this->mu);
00230     for (res = 0; res < this->next; res++) {
00231         if ((hostname == this->tbl[res]->hostname) &&
00232             (tIntf == this->tbl[res]->interface) &&
00233             !(this->tbl[res]->inUse)) {
00234             if ((this->tbl[res]->srpc != (SRPC *)NULL)) {
00235                 delete this->tbl[res]->srpc;
00236                 this->tbl[res]->srpc = (SRPC *)NULL;
00237             }
00238         }
00239     }
00240     UNLOCK(this->mu);
00241 }

Generated on Mon May 8 00:48:57 2006 for Vesta by  doxygen 1.4.2