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
00026
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
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
00048 extern "C" {
00049 extern int gethostname(char*, int);
00050 }
00051 #elif defined(IPPL_TFLOP)
00052
00053
00054 #endif
00055
00056
00057
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
00068
00069
00070
00071 int DiscConfig::dc_tokenize_string(const char *s, const char *tok,
00072 string *&slist) {
00073
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
00085
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
00104
00105
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
00127 DiscConfig::~DiscConfig() {
00128 TAU_PROFILE("DiscConfig::~DiscConfig()", "void ()",
00129 TAU_UTILITY | TAU_FIELD | TAU_IO);
00130
00131
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
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
00150
00151
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
00159
00160
00161 return numnodes;
00162 }
00163
00164
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
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
00186 string retval;
00187
00188
00189 if (s.length() == 0 || machine.length() == 0)
00190 return retval;
00191
00192
00193 string scpy(s);
00194 char *sptrbase = (char*) scpy.c_str();
00195
00196
00197 if (s.length() > 2 && s[0] == '.' && s[1] == '/')
00198 sptrbase += 2;
00199
00200
00201 char *sptr = sptrbase;
00202 while (*sptr != '\0') {
00203 if (*sptr != '$') {
00204 ++sptr;
00205 } else {
00206
00207 if (sptr != sptrbase) {
00208 *sptr = '\0';
00209 retval += sptrbase;
00210 sptrbase = sptr + 1;
00211 }
00212
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
00225
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
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
00248 retval += token;
00249 sptr = sptrbase = tok2 + 1;
00250 }
00251 }
00252
00253
00254 if (sptr != sptrbase)
00255 retval += sptrbase;
00256
00257
00258 return retval;
00259 }
00260
00261
00263
00264
00265
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
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
00285
00286 if (s.length() == 0)
00287 return;
00288
00289
00290 string basename = replace_wildcards(s, machine);
00291
00292
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
00302
00303
00304
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
00314
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
00326
00327
00328
00329
00330
00331
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
00351 int tag = Ippl::Comm->next_tag(DF_MAKE_HOST_MAP_TAG, DF_TAG_CYCLE);
00352
00353
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
00362 for (i=0; i < Ippl::getNodes(); ++i)
00363 NodeList.push_back(new NodeData);
00364
00365
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
00376
00377
00378 if (Ippl::myNode() != 0) {
00379
00380 Message *msg = new Message;
00381 ::putMessage(*msg,NodeNameItems);
00382 Ippl::Comm->send(msg, 0, tag);
00383
00384
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
00393
00394 if ((inC = fopen(ConfigFile.c_str(), "r")) != 0) {
00395
00396 while (fgets(bufferstore, bufferSize, inC) != 0) {
00397 CDCDBG(dbgmsg << "Read config line '" << bufferstore << "'." << endl);
00398
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
00411
00412 if (ConfigItems.length() == 0) {
00413 CDCDBG(dbgmsg << "Using default DiscConfig configuration '* .'" << endl);
00414 ConfigItems = "* .";
00415 ConfigItems += "\n";
00416 }
00417
00418
00419
00420 NodeNameItems += " 0";
00421 int unreceived = Ippl::getNodes() - 1;
00422 while (unreceived-- > 0) {
00423
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
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
00446
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
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
00473 if (tokens[1].c_str()[tokens[1].length() - 1] != '/')
00474 tokens[1] += "/";
00475 tokens[1] += BaseFile;
00476 if (tokens[0] == "*") {
00477
00478 CDCDBG(dbgmsg << " ... Wildcard token." << endl);
00479 WildCard = tokens[1];
00480 } else {
00481
00482
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
00493 if (tokens != 0)
00494 delete [] tokens;
00495 }
00496
00497
00498 if (conflines != 0)
00499 delete [] conflines;
00500
00501
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
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
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
00529 SMPData *smpdata = 0;
00530 vmap<string,SMPData *>::iterator smpiter = SMPMap.find(machine);
00531 if (smpiter != SMPMap.end()) {
00532
00533 CDCDBG(dbgmsg << " SMP " << machine << " found in SMPMap." << endl);
00534 smpdata = (*smpiter).second;
00535 } else {
00536
00537
00538
00539 CDCDBG(dbgmsg << " SMP " << machine << " not found in SMPMap." << endl);
00540 add_SMP_directory(smpdata, WildCard, machine, WritingFile);
00541 }
00542
00543
00544 NodeList[node]->HostName = machine;
00545 smpdata->NodeList.push_back(node);
00546 }
00547
00548
00549 if (nodenames != 0)
00550 delete [] nodenames;
00551
00552
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
00558 SMPData *smpdata = (*smpa).second;
00559 smpdata->SMPIndex = NumSMPs++;
00560 SMPList.push_back(smpdata);
00561
00562
00563
00564
00565 if (firstSMPWithFiles < 0 && smpdata->BaseFileNum > 0)
00566 firstSMPWithFiles = smpdata->SMPIndex;
00567
00568
00569
00570
00571
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
00584 vector<int>::iterator nodea = smpdata->NodeList.begin();
00585 for ( ; nodea != smpdata->NodeList.end(); ++nodea)
00586 NodeList[*nodea]->SMPIndex = smpdata->SMPIndex;
00587
00588
00589
00590 FileSMPs += smpdata->BaseFileNum;
00591 }
00592
00593
00594 MySMP = NodeList[Ippl::myNode()]->SMPIndex;
00595
00596
00597
00598 for (smpa = SMPMap.begin() ; smpa != SMPMap.end(); ++smpa) {
00599 SMPData *smpdata = (*smpa).second;
00600 if (smpdata->BaseFileNum == 0) {
00601
00602 smpdata->Box0Node = SMPList[firstSMPWithFiles]->Box0Node;
00603 SMPList[firstSMPWithFiles]->InformSMPList.push_back(smpdata->SMPIndex);
00604 }
00605 }
00606
00607
00608 CDCDBG(printDebug(dbgmsg));
00609 CDCDBG(dbgmsg << endl);
00610
00611 return true;
00612 }
00613
00614
00616
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
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
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
00656
00657
00658