00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
00081
00082
00083 int res, availEntry = -1;
00084
00085
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
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
00102 break;
00103 }
00104 if (!(this->tbl[res]->inUse) &&
00105 (this->tbl[res]->srpc == (SRPC *)NULL)) {
00106
00107 availEntry = res;
00108 }
00109 }
00110 }
00111 catch(...)
00112 {
00113 this->mu.unlock();
00114 throw;
00115 }
00116
00117
00118
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
00128 if (availEntry >= 0) {
00129
00130 res = availEntry;
00131 tbl[res]->hostname = hostname;
00132 tbl[res]->interface = tIntf;
00133 } else {
00134
00135 if (this->next >= this->num) {
00136
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];
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
00155 this->tbl[res]->inUse = true;
00156
00157
00158 this->mu.unlock();
00159
00160
00161 SRPC *new_srpc = 0;
00162 try
00163 {
00164 new_srpc = NEW_CONSTR(SRPC, (SRPC::caller, tIntf, hostname));
00165 }
00166 catch(...)
00167 {
00168
00169
00170 this->mu.lock();
00171 this->tbl[res]->inUse = false;
00172 this->mu.unlock();
00173 throw;
00174 }
00175
00176
00177
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
00191
00192
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
00224
00225
00226 int res, availEntry = -1;
00227
00228
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 }