src/Utility/DiscConfig.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  * This program was prepared by PSI. 
00007  * All rights in the program are reserved by PSI.
00008  * Neither PSI nor the author(s)
00009  * makes any warranty, express or implied, or assumes any liability or
00010  * responsibility for the use of this software
00011  *
00012  * Visit http://www.acl.lanl.gov/POOMS for more details
00013  *
00014  ***************************************************************************/
00015 
00016 // -*- C++ -*-
00017 /***************************************************************************
00018  *
00019  * The IPPL Framework
00020  * 
00021  *
00022  * Visit http://people.web.psi.ch/adelmann/ for more details
00023  *
00024  ***************************************************************************/
00025 
00026 // include files
00027 #include "Utility/DiscConfig.h"
00028 #include "Utility/IpplInfo.h"
00029 #include "Utility/PAssert.h"
00030 #include "Message/Communicate.h"
00031 #include "Message/Message.h"
00032 #include "Profile/Profiler.h"
00033 
00034 #ifdef IPPL_STDSTL
00035 // Standard STL names this header "algorithm"
00036 #include <algorithm>
00037 using namespace std;
00038 #else
00039 #include <algo.h>
00040 #endif // IPPL_STDSTL
00041 
00042 #include <string.h>
00043 #include <unistd.h>
00044 #include <stdio.h>
00045 
00046 #if defined(IPPL_SUN)
00047 // Declaration of function gethostname is not in the SunOS header files!
00048 extern "C" {
00049 extern int gethostname(char*, int);
00050 }
00051 #elif defined(IPPL_TFLOP)
00052 // need an extra header for gethostname function
00053 //#include <sysent.h>
00054 #endif
00055 
00056 
00057 // debugging macros
00058 #ifdef IPPL_PRINTDEBUG
00059 #define DCDBG(x) x
00060 #define CDCDBG(x) x
00061 #else
00062 #define DCDBG(x)
00063 #define CDCDBG(x)
00064 #endif
00065 
00067 // a simple routine to take an input string and a list of token separators,
00068 // and return the number of tokens plus fill in a new array of strings
00069 // with the words.  We had a nicer way to do this with a vector of strings,
00070 // but a #*#^@($ bug in KCC requires this workaround.
00071 int DiscConfig::dc_tokenize_string(const char *s, const char *tok,
00072                                    string *&slist) {
00073   // first determine how many words there are
00074   int num = 0;
00075   char *tempstring = new char[strlen(s) + 1];
00076   strcpy(tempstring, s);
00077   slist = 0;
00078   char* tokenp = strtok(tempstring, tok);
00079   while (tokenp) {
00080     num++;
00081     tokenp = strtok(0, tok);
00082   }
00083 
00084   // create an array of strings, and find the words and copy them into strings
00085   // but only if we have any words at all
00086   if (num > 0) {
00087     slist = new string[num];
00088     num = 0;
00089     strcpy(tempstring, s);
00090     tokenp = strtok(tempstring, tok);
00091     while (tokenp) {
00092       slist[num++] = tokenp;
00093       tokenp = strtok(0, tok);
00094     }
00095   }
00096 
00097   delete [] tempstring;
00098   return num;
00099 }
00100 
00101 
00103 // Constructor: read in and parse the given config file.  We must know
00104 // whether the configuration file is being used to read or write data,
00105 // and the base filename for the input/output file.
00106 DiscConfig::DiscConfig(const char *config, const char *BaseFile,
00107                        bool WritingFile)
00108   : ConfigOK(false), NumSMPs(0), FileSMPs(0), MySMP(0) {
00109   TAU_PROFILE("DiscConfig::DiscConfig()", "void (char *, bool)",
00110               TAU_UTILITY | TAU_FIELD | TAU_IO);
00111 
00112   if (config != 0)
00113     ConfigFile = config;
00114 
00115   if (BaseFile == 0) {
00116     ERRORMSG("Null base filename in DiscConfig constructor." << endl);
00117     Ippl::abort("Exiting due to DiscConfig error.");
00118     ConfigOK = false;
00119   } else {
00120     ConfigOK = parse_config(BaseFile, WritingFile);
00121   }
00122 }
00123 
00124 
00126 // Destructor
00127 DiscConfig::~DiscConfig() {
00128   TAU_PROFILE("DiscConfig::~DiscConfig()", "void ()",
00129               TAU_UTILITY | TAU_FIELD | TAU_IO);
00130 
00131   // delete the SMP structures
00132   vector<SMPData *>::iterator smpiter = SMPList.begin();
00133   vector<SMPData *>::iterator smpend  = SMPList.end();
00134   while (smpiter != smpend) {
00135     if ((*smpiter)->BaseFileNum > 0)
00136       delete [] (*smpiter)->BaseFileName;
00137     delete (*smpiter++);
00138   }
00139 
00140   // delete the node structures
00141   vector<NodeData *>::iterator nodeiter = NodeList.begin();
00142   vector<NodeData *>::iterator nodeend  = NodeList.end();
00143   while (nodeiter != nodeend)
00144     delete (*nodeiter++);
00145 }
00146 
00147 
00149 // compute how many physical nodes there are on the same SMP as the given
00150 // pnode.  This returns the total number of nodes which are writing data
00151 // to this SMP.
00152 unsigned int DiscConfig::pNodesPerSMP(unsigned int node) const {
00153   unsigned int nodesmp = NodeList[node]->SMPIndex;
00154   if (getNumFiles(nodesmp) == 0)
00155     return 0;
00156 
00157   unsigned int numnodes = SMPList[nodesmp]->NodeList.size();
00158   //unsigned int extrasmps = SMPList[nodesmp]->InformSMPList.size();
00159   //for (unsigned int i=0; i < extrasmps; ++i)
00160   //  numnodes += SMPList[SMPList[nodesmp]->InformSMPList[i]]->NodeList.size();
00161   return numnodes;
00162 }
00163 
00164 
00166 // take a string with configuration filename wildcards, and substitute
00167 // in the specific values.
00168 // The first argument is the original string with wildcards (listed below),
00169 // and the second is the machine name to use when substituting in the
00170 // machine name.
00171 //
00172 // Possible wildcards (can be upper or lower case, must start with $ and
00173 // have the name enclosed in () ):
00174 //   $(*) ... use the machine name given in the second argument
00175 //   $(n) ... our node number
00176 //   $(env var name) ... environment variable, if not one of the above names
00177 //
00178 // Return a new string with the changes in place.
00179 string DiscConfig::replace_wildcards(const string& s,
00180                                      const string& machine) {
00181   TAU_TYPE_STRING(taustr, CT(*this) +  " string (string, string )" );
00182   TAU_PROFILE("DiscConfig::replace_wildcards()", taustr, 
00183               TAU_UTILITY | TAU_FIELD | TAU_IO);
00184 
00185   // the return string
00186   string retval;
00187 
00188   // make sure we have non-null input
00189   if (s.length() == 0 || machine.length() == 0)
00190     return retval;
00191 
00192   // copy of input string
00193   string scpy(s);
00194   char *sptrbase = (char*) scpy.c_str();
00195 
00196   // skip leading "./" if necessary
00197   if (s.length() > 2 && s[0] == '.' && s[1] == '/')
00198     sptrbase += 2;
00199 
00200   // start moving along the string until we get to a $
00201   char *sptr = sptrbase;
00202   while (*sptr != '\0') {
00203     if (*sptr != '$') {
00204       ++sptr;
00205     } else {
00206       // append previous text to return value
00207       if (sptr != sptrbase) {
00208         *sptr = '\0';
00209         retval += sptrbase;
00210         sptrbase = sptr + 1;
00211       }
00212       // find name of wildcard, enclosed by ()'s
00213       ++sptr;
00214       char *tok1 = sptr;
00215       char *tok2 = sptr;
00216       while (*tok1 != '(' && *tok1 != '\0') ++tok1;
00217       while (*tok2 != ')' && *tok2 != '\0') ++tok2;
00218       if (tok1 == '\0' || tok2 == '\0' || tok2 <= tok1) {
00219         ERRORMSG("Unbalanced parenthesis in DiscConfig config file in line ");
00220         ERRORMSG(s.c_str() << endl);
00221         Ippl::abort("Exiting due to DiscConfig error.");
00222         break;
00223       }
00224       // make string object with the wildcard name, and look for name.
00225       // replace token with new name
00226       *tok2 = '\0';
00227       string token(tok1 + 1);
00228       if (token == "*") {
00229         token = machine;
00230       } else if (token == "node" || token == "n" || token == "N") {
00231         char buf[32];
00232         sprintf(buf, "%d", Ippl::myNode());
00233         token = buf;
00234       } else {
00235         // look for an env var with this name
00236         char *env = getenv(token.c_str());
00237         if (env != 0) {
00238           token = env;
00239         } else {
00240           ERRORMSG("Unknown wildcard name '" << token.c_str()<<"' in line ");
00241           ERRORMSG(s.c_str() << endl);
00242           Ippl::abort("Exiting due to DiscConfig error.");
00243           break;
00244         }
00245       }
00246 
00247       // add this token to the return string, and move on past wildcard
00248       retval += token;
00249       sptr = sptrbase = tok2 + 1;
00250     }
00251   }
00252 
00253   // append the final word to the return string
00254   if (sptr != sptrbase)
00255     retval += sptrbase;
00256 
00257   // done with substitution; return the string
00258   return retval;
00259 }
00260 
00261 
00263 // take the information about the directory and hostname for a given
00264 // SMP, and add it to the list of directories for that SMP.  Make sure
00265 // the directory is not repeated.  If it is, issue a warning and continue.
00266 void DiscConfig::add_SMP_directory(SMPData *&smpd,
00267                                    const string& s,
00268                                    const string& machine,
00269                                    bool WritingFile) {
00270   TAU_TYPE_STRING(taustr, CT(*this) +  " void (SMPData *, string, string )" );
00271   TAU_PROFILE("DiscConfig::add_SMP_directory()", taustr, 
00272               TAU_UTILITY | TAU_FIELD | TAU_IO);
00273 
00274   // create a new smpd if necessary, and add it to the list
00275   if (smpd == 0) {
00276     smpd = new SMPData;
00277     smpd->Box0Node = Ippl::getNodes();
00278     smpd->HostName = machine;
00279     smpd->BaseFileNum = 0;
00280     smpd->BaseFileName = 0;
00281     SMPMap.insert(vmap<string,SMPData *>::value_type(machine, smpd));
00282   }
00283 
00284   // if necessary, try to add a new directory.  Buf if no directory
00285   // was specified, we're done
00286   if (s.length() == 0) 
00287     return;
00288 
00289   // create a string with the wildcards replaced, etc.
00290   string basename = replace_wildcards(s, machine);
00291 
00292   // check to make sure it does already occur in the list of BaseFileName's
00293   for (unsigned int sptr=0; sptr < smpd->BaseFileNum; ++sptr) {
00294     if (strcmp(basename.c_str(), (smpd->BaseFileName[sptr]).c_str()) == 0) {
00295       WARNMSG("DiscConfig: Duplicate configuration file entry '" << basename);
00296       WARNMSG("' for host " << machine << " ... second one ignored." << endl);
00297       return;
00298     }
00299   }
00300 
00301   // check to make sure we're not trying to write to more than one output
00302   // file on an SMP (multipple read files are OK, but we can only write
00303   // to one file, since we cannot determine how to partition items among
00304   // the files)
00305   if (WritingFile && smpd->BaseFileNum > 0) {
00306     WARNMSG("DiscConfig: Cannot write to more than one file per");
00307     WARNMSG(" SMP.  Only the first file listed for host '");
00308     WARNMSG(smpd->HostName << "', " << smpd->BaseFileName[0]);
00309     WARNMSG(", will be used." << endl);
00310     return;
00311   }
00312 
00313   // if we're here, the entry is not duplicated, so add the name.  We'll
00314   // need to add the name, then regenerate our tokenized list
00315   smpd->BaseFileNameStringList += " ";
00316   smpd->BaseFileNameStringList += basename;
00317   if (smpd->BaseFileNum > 0)
00318     delete [] smpd->BaseFileName;
00319   smpd->BaseFileNum = dc_tokenize_string(smpd->BaseFileNameStringList.c_str(),
00320                                          " ", smpd->BaseFileName);
00321 }
00322 
00323 
00325 // read in from configuration file - an ascii file of token pairs.
00326 // On each line, the first token is the hostname and the second
00327 // token is the directory where the file is to be placed on this
00328 // host.
00329 // This will construct the vector with SMP data and set how many SMP's
00330 // we expect to find.  If this does not match later, an error will be
00331 // reported then.
00332 bool DiscConfig::parse_config(const char *BaseFile, bool WritingFile) {
00333   TAU_TYPE_STRING(taustr, CT(*this) +  " bool (bool)" );
00334   TAU_PROFILE("DiscConfig::parse_config()", taustr,
00335               TAU_UTILITY | TAU_FIELD | TAU_IO);
00336 
00337   unsigned int i;
00338   const int bufferSize = 1024;
00339   char bufferstore[bufferSize];
00340   char *buffer;
00341   FILE *inC;
00342   string WildCard;
00343   string ConfigItems;
00344   string NodeNameItems;
00345 
00346   CDCDBG(string dbgmsgname("DC:parse_config:"));
00347   CDCDBG(dbgmsgname += ConfigFile);
00348   CDCDBG(Inform dbgmsg(dbgmsgname.c_str(), INFORM_ALL_NODES));
00349 
00350   // create a tag for use in sending info to/from other nodes
00351   int tag = Ippl::Comm->next_tag(DF_MAKE_HOST_MAP_TAG, DF_TAG_CYCLE);
00352 
00353   // save the number of nodes and which node we're on
00354   NumSMPs = 0;
00355   FileSMPs = 0;
00356   MySMP = 0;
00357 
00358   CDCDBG(dbgmsg << "Parsing config file info on node " << Ippl::myNode());
00359   CDCDBG(dbgmsg << " of " << Ippl::getNodes() << " nodes." << endl);
00360 
00361   // initialize the list of node information
00362   for (i=0; i < Ippl::getNodes(); ++i)
00363     NodeList.push_back(new NodeData);
00364 
00365   // obtain the hostname and processor ID to send out
00366   char name[1024];
00367   if (gethostname(name, 1023) != 0) {
00368     WARNMSG("DiscConfig: Could not get hostname.  Using localhost." << endl);
00369     strcpy(name, "localhost");
00370   }
00371   NodeNameItems = name;
00372 
00373   CDCDBG(dbgmsg << "  My hostname is " << NodeNameItems << endl);
00374 
00375   // all other nodes send their hostname to node 0; node 0 gets the names,
00376   // reads the config file, then broadcasts all the necessary info to all
00377   // other nodes
00378   if (Ippl::myNode() != 0) {
00379     // other nodes send their node name to node 0
00380     Message *msg = new Message;
00381     ::putMessage(*msg,NodeNameItems);
00382     Ippl::Comm->send(msg, 0, tag);
00383 
00384     // receive back the config file and node name info
00385     int node = 0;
00386     msg = Ippl::Comm->receive_block(node, tag);
00387     PAssert(msg != 0 && node == 0);
00388     ::getMessage(*msg,ConfigItems);
00389     ::getMessage(*msg,NodeNameItems);
00390     delete msg;
00391   } else {
00392     // only node 0 reads config file - others get a broadcast message
00393     // open the configuration file
00394     if ((inC = fopen(ConfigFile.c_str(), "r")) != 0) {
00395       // read in each line, and append it to end of broadcast string
00396       while (fgets(bufferstore, bufferSize, inC) != 0) {
00397         CDCDBG(dbgmsg << "Read config line '" << bufferstore << "'." << endl);
00398         // skip leading spaces, and any comment lines starting with '#'
00399         buffer = bufferstore;
00400         while (*buffer == ' ' || *buffer == '\t' || *buffer == '\n')
00401           ++buffer;
00402         if (*buffer == '#' || *buffer == '\0')
00403           continue;
00404         ConfigItems += buffer;
00405         ConfigItems += "\n";
00406       }
00407       fclose(inC);
00408     }
00409 
00410     // see if there was an error, or no config file was specified ...
00411     // if so, use default
00412     if (ConfigItems.length() == 0) {
00413       CDCDBG(dbgmsg << "Using default DiscConfig configuration '* .'" << endl);
00414       ConfigItems = "* .";
00415       ConfigItems += "\n";
00416     }
00417 
00418     // collect node names from everyone else, and then retransmit the collected
00419     // list.  The first name should be the node 0 name.
00420     NodeNameItems += " 0";
00421     int unreceived = Ippl::getNodes() - 1;
00422     while (unreceived-- > 0) {
00423       // get the hostname from the remote node, and append to a list
00424       int node = COMM_ANY_NODE;
00425       Message *msg = Ippl::Comm->receive_block(node, tag);
00426       PAssert(msg != 0);
00427       string nodename;
00428       ::getMessage(*msg,nodename);
00429       sprintf(name, " %s %d", nodename.c_str(), node);
00430       NodeNameItems += name;
00431       delete msg;
00432     }
00433 
00434     // broadcast string to all other nodes
00435     if (Ippl::getNodes() > 1) {
00436       Message *msg = new Message;
00437       ::putMessage(*msg,ConfigItems);
00438       ::putMessage(*msg,NodeNameItems);
00439       CDCDBG(dbgmsg << "  Broadcasting config info " << ConfigItems << endl);
00440       CDCDBG(dbgmsg << "  Broadcasting node names " << NodeNameItems << endl);
00441       Ippl::Comm->broadcast_others(msg, tag);
00442     }
00443   }
00444 
00445   // from the configuration string, break it up into single lines and parse.
00446   // This sets up the SMP information list.
00447   CDCDBG(dbgmsg << "  My ConfigItems = " << ConfigItems << endl);
00448   string *conflines;
00449   int conflinenum = dc_tokenize_string(ConfigItems.c_str(), "\n", conflines);
00450   CDCDBG(dbgmsg << "  Parsed config line list into " << conflinenum);
00451   CDCDBG(dbgmsg << " words." << endl);
00452   for (int is=0; is < conflinenum; ++is) {
00453     CDCDBG(dbgmsg << "  Examining confline " << is << " = '");
00454     CDCDBG(dbgmsg << conflines[is] << "'." << endl);
00455 
00456     // tokenize string, and store values
00457     string *tokens;
00458     int ntok = dc_tokenize_string(conflines[is].c_str(), " \t,\n", tokens);
00459     CDCDBG(dbgmsg << "  Parsed config line " << is << " into " << ntok);
00460     CDCDBG(dbgmsg << " words:");
00461     for (int ntok2=0; ntok2 < ntok; ++ntok2) {
00462       CDCDBG(dbgmsg << "  '" << tokens[ntok2] << "'");
00463     }
00464     CDCDBG(dbgmsg << endl);
00465     if (ntok != 2) {
00466       ERRORMSG("Wrong number of parameters in DiscConfig config file ");
00467       ERRORMSG("'" << ConfigFile << "' (" << ntok << " != 2)" << endl);
00468       Ippl::abort("Exiting due to DiscConfig error.");
00469     } else {
00470       CDCDBG(dbgmsg << "Looking at tokens '" << tokens[0].c_str());
00471       CDCDBG(dbgmsg << "'  '" << tokens[1].c_str() << "'." << endl);
00472       // append / to directory name if necessary, and also the base filename
00473       if (tokens[1].c_str()[tokens[1].length() - 1] != '/')
00474         tokens[1] += "/";
00475       tokens[1] += BaseFile;
00476       if (tokens[0] == "*") {
00477         // save the wildcard string
00478         CDCDBG(dbgmsg << "  ... Wildcard token." << endl);
00479         WildCard = tokens[1];
00480       } else {
00481         // line was good ... store the values found there.  If a line is
00482         // repeated, we just replace the value.
00483         CDCDBG(dbgmsg << "  ... SMP info token." << endl);
00484         SMPData *smpd = 0;
00485         vmap<string,SMPData *>::iterator smpiter = SMPMap.find(tokens[0]);
00486         if (smpiter != SMPMap.end())
00487           smpd = (*smpiter).second;
00488         add_SMP_directory(smpd, tokens[1], tokens[0], WritingFile);
00489       }
00490     }
00491 
00492     // delete the tokens
00493     if (tokens != 0)
00494       delete [] tokens;
00495   }
00496 
00497   // delete the conf lines
00498   if (conflines != 0)
00499     delete [] conflines;
00500 
00501   // make sure we found SOMETHING ...
00502   if (SMPMap.size() < 1 && WildCard.length() == 0) {
00503     ERRORMSG("No hostname/directory pairs found in DiscConfig config file ");
00504     ERRORMSG("'" << ConfigFile << "' " << endl);
00505     Ippl::abort("Exiting due to DiscConfig error.");
00506     return false;
00507   }
00508 
00509   // set up the node information list
00510   CDCDBG(dbgmsg << "  My NodeNameItems = " << NodeNameItems << endl);
00511   string *nodenames;
00512 #ifdef IPPL_PRINTDEBUG
00513   int nodenamenum = dc_tokenize_string(NodeNameItems.c_str(), " ", nodenames);
00514   CDCDBG(dbgmsg << "  Parsed node name list into " << nodenamenum);
00515   CDCDBG(dbgmsg << " words." << endl);
00516 #else
00517   dc_tokenize_string(NodeNameItems.c_str(), " ", nodenames);
00518 #endif
00519   for (int in=0; in < Ippl::getNodes(); ++in) {
00520     // get node number and node name from list of node information
00521     CDCDBG(dbgmsg << "  converting to node from nodestring '");
00522     CDCDBG(dbgmsg << nodenames[2*in + 1] << "'" << endl);
00523     CDCDBG(dbgmsg << "  converting to node from nodename   '");
00524     CDCDBG(dbgmsg << nodenames[2*in] << "'" << endl);
00525     int node = atoi(nodenames[2*in + 1].c_str());
00526     string machine = nodenames[2*in];
00527 
00528     // find the host name in our list of SMP's
00529     SMPData *smpdata = 0;
00530     vmap<string,SMPData *>::iterator smpiter = SMPMap.find(machine);
00531     if (smpiter != SMPMap.end()) {
00532       // this SMP has already been set up earlier
00533       CDCDBG(dbgmsg << "  SMP " << machine << " found in SMPMap." << endl);
00534       smpdata = (*smpiter).second;
00535     } else {
00536       // we must make a new info structure for this SMP, since it was
00537       // not mentioned in the configuration file.  The routine
00538       // sets the value of smpdata to a newly allocated pointer
00539       CDCDBG(dbgmsg << "  SMP " << machine << " not found in SMPMap." << endl);
00540       add_SMP_directory(smpdata, WildCard, machine, WritingFile);
00541     }
00542 
00543     // fill in the SMP info and node info
00544     NodeList[node]->HostName = machine;
00545     smpdata->NodeList.push_back(node);
00546   }
00547 
00548   // delete the node names
00549   if (nodenames != 0)
00550     delete [] nodenames;
00551 
00552   // go through the SMP list, assign them numbers, and sort the node data
00553   int firstSMPWithFiles = (-1);
00554   CDCDBG(dbgmsg << "Assigning numbers to " << SMPMap.size()<<" SMP's"<< endl);
00555   vmap<string,SMPData *>::iterator smpa;
00556   for (smpa = SMPMap.begin() ; smpa != SMPMap.end(); ++smpa) {
00557     // add this SMP info to our SMPList array (for fast access)
00558     SMPData *smpdata   = (*smpa).second;
00559     smpdata->SMPIndex  = NumSMPs++;
00560     SMPList.push_back(smpdata);
00561 
00562     // find out if this SMP is the first one we find with files.  There
00563     // must be at least one, since by this point we know the config
00564     // file was not empty, or we used a wildcard.
00565     if (firstSMPWithFiles < 0 && smpdata->BaseFileNum > 0)
00566       firstSMPWithFiles = smpdata->SMPIndex;
00567 
00568     // sort the list of nodes so that all nodes have them in the same order
00569     // (this is needed in find_processors).  But if an SMP has 0 nodes,
00570     // it is an error since the configuration file lists an SMP on which
00571     // we are not running.
00572     if (smpdata->NodeList.size() > 0) {
00573       sort(smpdata->NodeList.begin(), smpdata->NodeList.end());
00574       smpdata->Box0Node = smpdata->NodeList[0];
00575     } else {
00576       ERRORMSG("DiscConfig: The SMP '" << smpdata->HostName);
00577       ERRORMSG("' was listed in the config file\n");
00578       ERRORMSG("'" << ConfigFile << "' but you are not running on that SMP.");
00579       ERRORMSG(endl);
00580       Ippl::abort("Exiting due to DiscConfig error.");
00581     }
00582 
00583     // tell the proper nodes which SMP they're on
00584     vector<int>::iterator nodea = smpdata->NodeList.begin();
00585     for ( ; nodea != smpdata->NodeList.end(); ++nodea)
00586       NodeList[*nodea]->SMPIndex = smpdata->SMPIndex;
00587       
00588 
00589     // increment how many file sets we're dealing with
00590     FileSMPs += smpdata->BaseFileNum;
00591   }
00592 
00593   // determine our parent SMP
00594   MySMP = NodeList[Ippl::myNode()]->SMPIndex;
00595 
00596   // determine Box0 nodes, and whether we need to make sure to send
00597   // layout and other info to other SMP's
00598   for (smpa = SMPMap.begin() ; smpa != SMPMap.end(); ++smpa) {
00599     SMPData *smpdata = (*smpa).second;
00600     if (smpdata->BaseFileNum == 0) {
00601       // we'll need to send data to another SMP's Node 0
00602       smpdata->Box0Node = SMPList[firstSMPWithFiles]->Box0Node;
00603       SMPList[firstSMPWithFiles]->InformSMPList.push_back(smpdata->SMPIndex);
00604     }
00605   }
00606 
00607   // print out summary
00608   CDCDBG(printDebug(dbgmsg));
00609   CDCDBG(dbgmsg << endl);
00610 
00611   return true;
00612 }
00613 
00614 
00616 // print out debugging information for this DiscConfig
00617 void DiscConfig::printDebug(Inform& msg) {
00618   msg << "ConfigFile   = " << getConfigFile() << endl;
00619   msg << "Num Filesets = " << fileSMPs() << endl;
00620   msg << "NumSMPs = " << numSMPs() << endl;
00621   msg << "MySMP   = " << mySMP() << " (" << getSMPHost(mySMP()) << ")" << endl;
00622   msg << "MyBox0  = " << getSMPBox0() << endl;
00623   msg << "MyNode  = " << Ippl::myNode() << endl;
00624 
00625   // print out summary of SMP info
00626   msg << "DiscConfig SMP Summary:" << endl;
00627   for (int smp=0; smp < numSMPs(); ++smp) {
00628     msg << "  SMP host=" << getSMPHost(smp);
00629     msg << ", numnodes=" << getNumSMPNodes(smp);
00630     msg << ", box0=" << getSMPBox0(smp) << endl;
00631     msg << "    FileList =";
00632     for (int fl=0; fl < getNumFiles(smp); ++fl)
00633       msg << " " << getFilename(smp, fl);
00634     msg << endl;
00635     msg << "    OtherSMPList =";
00636     for (int sl=0; sl < getNumOtherSMP(smp); ++sl)
00637       msg << " " << getOtherSMP(smp, sl);
00638     msg << endl;
00639     msg << "    NodeList =";
00640     for (int nl=0; nl < getNumSMPNodes(smp); ++nl)
00641       msg << " " << getSMPNode(smp,nl);
00642     msg << endl;
00643   }
00644 
00645   // print out summary of node info
00646   msg << "DiscConfig Node Summary:" << endl;
00647   for (int n=0; n < getNumNodes(); ++n) {
00648     msg << "  Node " << n << " on SMP " << getNodeSMPIndex(n);
00649     msg << " (" << getNodeHost(n) << ")" << endl;
00650   }
00651 }
00652 
00653 
00654 /***************************************************************************
00655  * $RCSfile: DiscConfig.cpp,v $   $Author: adelmann $
00656  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:33 $
00657  * IPPL_VERSION_ID: $Id: DiscConfig.cpp,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 
00658  ***************************************************************************/

Generated on Mon Jan 16 13:23:57 2006 for IPPL by  doxygen 1.4.6