Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

pvminterface.cc

Go to the documentation of this file.
00001 /** @file pvminterface.cc */
00002 /* 
00003  * Copyright (C) 2002 Laird Breyer
00004  *  
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  * 
00010  * This program 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
00013  * GNU General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018  * 
00019  * Author:   Laird Breyer <laird@lbreyer.com>
00020  */
00021 
00022 #include <string.h>
00023 #include <cassert>
00024 #include "pvminterface.h"
00025 
00026 /// Starts the PVM interface and syncs all the tasks.
00027 /**
00028  * Every task collects some information about itself which must
00029  * be sent to all others. The PVMInterface constructor's job is
00030  * to synchronize all tasks, broadcast this task's details and 
00031  * read all other tasks' details into the tasklist array.
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   // get our tid and package the info
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   // join the synchronization group
00068   inum = pvm_joingroup("insync");
00069   if( inum < 0 ) goto bailout;
00070 
00071   // wait for all to join
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   // now that everyone's here...
00078   // broadcast my details to everyone
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   // and read everyone else's details
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   // finally indicate standby mode
00098   JoinStandbyGroup();
00099   // done
00100   return;
00101 
00102  bailout:
00103   pvm_perror("PVMInterface constructor");
00104   pvm_exit();
00105 
00106   throw runtime_error("");
00107 
00108 #endif
00109 }
00110 
00111 /// Closes down the PVM connection and notifies pvmd.
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 /// Returns tasklist index of first task which contains the id number.
00129 /// Returns -1 if not found.
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   // don't send empty messages
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 /// Sends a string command to every member of the STANDBY group
00215 void PVMInterface :: BroadcastCommand(const char* commandline) throw (runtime_error) {
00216 #ifdef DISTRIBUTED_COMPUTING
00217 
00218   int info, bufid;
00219 
00220   // don't send empty messages
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 /// returns the task number of the last received message
00246 /// or -1 if not found
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 /// Waits for and reads a command line sent by the master
00265 /// If no command has arrived after a delay, returns with ""
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   // do nothing with command
00292 #endif
00293 }
00294 /// Fills the countsarray with a list of occupied LeafNodes from another task
00295 /**
00296  * The size parameter should be set to the maximum allowable size of the countsarray.
00297  * The returned value of size is the actual size of the countsarray.
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   // do nothing with command
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 }

Generated on Wed May 29 11:37:15 2002 for MarkovPR by doxygen1.2.15