00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <string.h>
00023 #include <cassert>
00024 #include "pvminterface.h"
00025
00026
00027
00028
00029
00030
00031
00032
00033 PVMInterface :: PVMInterface(const char *name,
00034 bool ismaster, int ntasks,
00035 int startid, int stopid) throw (runtime_error) {
00036 #ifndef DISTRIBUTED_COMPUTING
00037
00038 num_tasks = 0;
00039 is_master = true;
00040
00041 last_message_tid = 0;
00042 last_message_size = 0;
00043 last_message_msgtag = 0;
00044
00045
00046 #else
00047 assert(startid < stopid);
00048
00049 int info, inum, bufid;
00050
00051 is_master = ismaster;
00052 num_tasks = ntasks;
00053 tasklist = new PVMTaskInfo[num_tasks - 1];
00054
00055 last_message_tid = 0;
00056 last_message_size = 0;
00057 last_message_msgtag = 0;
00058
00059
00060 strncpy(myinfo.name, name, PVMINTERFACE_NAMELEN);
00061 myinfo.name[PVMINTERFACE_NAMELEN] = 0;
00062 myinfo.start_id = startid;
00063 myinfo.stop_id = stopid;
00064 myinfo.tid = pvm_mytid();
00065 if( myinfo.tid < 0 ) goto bailout;
00066
00067
00068 inum = pvm_joingroup("insync");
00069 if( inum < 0 ) goto bailout;
00070
00071
00072
00073 cerr << "pvm: waiting to sync with " << (num_tasks-1) << " other(s)" << endl;
00074 info = pvm_barrier("insync", num_tasks);
00075 if( info < 0 ) goto bailout;
00076
00077
00078
00079
00080 bufid = pvm_initsend(PvmDataDefault);
00081 if( bufid < 0 ) goto bailout;
00082
00083 info = pvm_pkbyte((char*)&myinfo, sizeof(PVMTaskInfo), 1);
00084 if( info < 0 ) goto bailout;
00085
00086 info = pvm_bcast("insync", PVMINTERFACE_SENDINFO);
00087 if( info < 0 ) goto bailout;
00088
00089
00090 for(int k = 0; k < num_tasks - 1; k++) {
00091 bufid = pvm_recv( -1, PVMINTERFACE_SENDINFO);
00092 if( bufid < 0 ) goto bailout;
00093 info = pvm_upkbyte((char*)&tasklist[k], sizeof(PVMTaskInfo), 1);
00094 if( info < 0 ) goto bailout;
00095 }
00096
00097
00098 JoinStandbyGroup();
00099
00100 return;
00101
00102 bailout:
00103 pvm_perror("PVMInterface constructor");
00104 pvm_exit();
00105
00106 throw runtime_error("");
00107
00108 #endif
00109 }
00110
00111
00112 PVMInterface :: ~PVMInterface() {
00113 #ifdef DISTRIBUTED_COMPUTING
00114
00115 delete[] tasklist;
00116 pvm_exit();
00117
00118 #endif
00119 }
00120
00121 bool PVMInterface :: MessagePending() {
00122 #ifdef DISTRIBUTED_COMPUTING
00123 return (pvm_probe(-1,PVMINTERFACE_SENDCOMMAND) > 0);
00124 #else
00125 return false;
00126 #endif
00127 }
00128
00129
00130 int PVMInterface :: FindTask(uint32 id) {
00131 #ifdef DISTRIBUTED_COMPUTING
00132
00133 for(int i = 0; i < num_tasks - 1; i++) {
00134 if( (tasklist[i].start_id <= id) && (tasklist[i].stop_id >= id) ) {
00135 return i;
00136 }
00137 }
00138 return -1;
00139
00140 #else
00141 return -1;
00142 #endif
00143 }
00144
00145 const char* PVMInterface :: Name(int k) {
00146 #ifdef DISTRIBUTED_COMPUTING
00147 assert(k < num_tasks);
00148 return tasklist[k].name;
00149 #else
00150 return "";
00151 #endif
00152 }
00153
00154 bool PVMInterface :: AllStandby() throw (runtime_error) {
00155 #ifdef DISTRIBUTED_COMPUTING
00156 int size = pvm_gsize("standby");
00157 if( size < 0 ) {
00158 pvm_perror("PVMInterface::BroadcastCommand");
00159 pvm_exit();
00160 throw runtime_error("");
00161 } else {
00162 return (size >= num_tasks);
00163 }
00164 #else
00165 return true;
00166 #endif
00167 }
00168
00169 void PVMInterface :: LeaveStandbyGroup() {
00170 #ifdef DISTRIBUTED_COMPUTING
00171 cerr << "pvm: now leaving STANDBY" << endl;
00172 pvm_lvgroup("standby");
00173 #endif
00174 }
00175
00176 void PVMInterface :: JoinStandbyGroup() {
00177 #ifdef DISTRIBUTED_COMPUTING
00178 cerr << "pvm: now joining STANDBY" << endl;
00179 pvm_joingroup("standby");
00180 #endif
00181 }
00182
00183 void PVMInterface :: SendCommand(int taskno, const char* commandline) throw (runtime_error) {
00184 #ifdef DISTRIBUTED_COMPUTING
00185
00186 int info, bufid;
00187
00188 assert( taskno >= 0);
00189 assert( taskno < num_tasks - 1);
00190
00191 if( !*commandline ) {
00192 return;
00193 }
00194
00195 bufid = pvm_initsend(PvmDataDefault);
00196 if( bufid < 0 ) goto bailout;
00197
00198 info = pvm_pkstr(const_cast<char*>(commandline));
00199 if( info < 0 ) goto bailout;
00200
00201 info = pvm_send(tasklist[taskno].tid, PVMINTERFACE_SENDCOMMAND);
00202 if( info < 0 ) goto bailout;
00203
00204 return;
00205
00206 bailout:
00207 pvm_perror("PVMInterface::SendCommand");
00208 pvm_exit();
00209
00210 throw runtime_error("");
00211
00212 #endif
00213 }
00214
00215 void PVMInterface :: BroadcastCommand(const char* commandline) throw (runtime_error) {
00216 #ifdef DISTRIBUTED_COMPUTING
00217
00218 int info, bufid;
00219
00220
00221 if( !*commandline ) {
00222 return;
00223 }
00224
00225 bufid = pvm_initsend(PvmDataDefault);
00226 if( bufid < 0 ) goto bailout;
00227
00228 info = pvm_pkstr(const_cast<char*>(commandline));
00229 if( info < 0 ) goto bailout;
00230
00231 info = pvm_bcast("standby", PVMINTERFACE_SENDCOMMAND);
00232 if( info < 0 ) goto bailout;
00233
00234 return;
00235
00236 bailout:
00237 pvm_perror("PVMInterface::BroadcastCommand");
00238 pvm_exit();
00239
00240 throw runtime_error("");
00241
00242 #endif
00243 }
00244
00245
00246
00247 int PVMInterface :: LastMessageOriginator() {
00248 #ifdef DISTRIBUTED_COMPUTING
00249
00250 for(int k = 0; k < num_tasks - 1; k++) {
00251 if( last_message_tid == tasklist[k].tid ) {
00252 return k;
00253 }
00254 }
00255 return -1;
00256
00257 #else
00258
00259 return 0;
00260
00261 #endif
00262 }
00263
00264
00265
00266 void PVMInterface :: GetCommandWithTimeout(char* commandline) throw (runtime_error) {
00267 #ifdef DISTRIBUTED_COMPUTING
00268 struct timeval tmout;
00269 tmout.tv_sec = 1;
00270 tmout.tv_usec = 0;
00271
00272 int bufid;
00273 if( (bufid = pvm_trecv(-1,PVMINTERFACE_SENDCOMMAND,&tmout)) > 0 ) {
00274 int info;
00275 info = pvm_bufinfo(bufid, &last_message_size, &last_message_msgtag, &last_message_tid);
00276 if( info < 0 ) goto bailout;
00277
00278 info = pvm_upkstr(commandline);
00279 if( info < 0 ) goto bailout;
00280 }
00281
00282 return;
00283
00284 bailout:
00285 pvm_perror("PVMInterface::GetCommandWithTimeout");
00286 pvm_exit();
00287
00288 throw runtime_error("");
00289
00290 #else
00291
00292 #endif
00293 }
00294
00295
00296
00297
00298
00299 void PVMInterface :: GetLeafCounts(unsigned int* countsarray, uint32* size) throw (runtime_error) {
00300 #ifdef DISTRIBUTED_COMPUTING
00301
00302 int bufid;
00303 uint32 maxsize = *size;
00304 if( (bufid = pvm_recv(-1,PVMINTERFACE_SENDLEAFUPD)) > 0 ) {
00305 int info;
00306 info = pvm_upkuint(size, 1, 1);
00307 if( info < 0 ) goto bailout;
00308 assert(maxsize >= *size);
00309 info = pvm_upkuint(countsarray, *size, 1);
00310 if( info < 0 ) goto bailout;
00311 }
00312
00313 return;
00314
00315 bailout:
00316 pvm_perror("PVMInterface::GetCommandWithTimeout");
00317 pvm_exit();
00318
00319 throw runtime_error("");
00320
00321 #else
00322
00323 #endif
00324 }
00325
00326 void PVMInterface :: SendLeafCounts(int taskno, unsigned int* countsarray, uint32 size) throw (runtime_error) {
00327 #ifdef DISTRIBUTED_COMPUTING
00328
00329 int bufid, info;
00330 assert( taskno >= 0);
00331 assert( taskno < num_tasks - 1);
00332
00333 bufid = pvm_initsend(PvmDataDefault);
00334 if( bufid < 0 ) goto bailout;
00335
00336 info = pvm_pkuint(&size, 1, 1);
00337 info = pvm_pkuint(countsarray, size, 1);
00338 if( info < 0 ) goto bailout;
00339
00340 info = pvm_send(tasklist[taskno].tid, PVMINTERFACE_SENDLEAFUPD);
00341 if( info < 0 ) goto bailout;
00342
00343 return;
00344
00345 bailout:
00346 pvm_perror("PVMInterface::SendLeafCounts");
00347 pvm_exit();
00348
00349 throw runtime_error("");
00350
00351 #endif
00352
00353 }