00001 // -*- C++ -*- 00002 /*************************************************************************** 00003 * 00004 * The IPPL Framework 00005 * 00006 * 00007 * Visit http://people.web.psi.ch/adelmann/ for more details 00008 * 00009 ***************************************************************************/ 00010 00011 #ifndef DISC_CONFIG_H 00012 #define DISC_CONFIG_H 00013 00014 /*************************************************************************** 00015 * DiscConfig is a utility class which will read in a configuration file 00016 * for use by classes such as DiscField that read or write parallel data 00017 * files. It should be given a config file name, which will be parsed by 00018 * the constructor; the config file should have the format: 00019 * 00020 * # comment line(s), starting with '#' 00021 * machine1 directory1-1 00022 * machine2 directory2-1 00023 * machine2 directory2-2 00024 * 00025 * Instead of an SMP machine name, you can specify '*', which acts as a 00026 * default line for all machines which are not listed elsewhere in the config 00027 * file. There are also some allowed variables in the directory names, 00028 * which have the form '$(varname)'. Allowed variables are 00029 * $(n) ... the node ID, from 0 ... (total nodes - 1) 00030 * $(*) ... the SMP machine name 00031 * $(ENV) ... the value of environment variable 'ENV' 00032 * Examples of using these kinds of wildcards 00033 * 00034 * ###################################################################### 00035 * # a sample config file with wildcards and variables 00036 * 00037 * # first, a wildcard, for the directory /scratch/<username>/<hostname> 00038 * * /scratch/$(USER)/$(*) 00039 * 00040 * # specific host commands 00041 * host3 /usr/local/data/host3/dir1 00042 * host3 /usr/local/data/host3/dir2 00043 * host4 /tmp/dir3/$(n) 00044 * # 00045 * ###################################################################### 00046 * 00047 * Machines may be listed more than once; they may also be omitted (that is, 00048 * the config file may be read by a job running on several different SMP's, 00049 * where the config file contains listings for only some of the SMP's). 00050 * 00051 ***************************************************************************/ 00052 00053 // include files 00054 #include "Utility/Pstring.h" 00055 #include "Utility/vmap.h" 00056 #include "Utility/Inform.h" 00057 00058 00059 class DiscConfig { 00060 00061 public: 00062 // Constructor: read in and parse the given config file. We must know 00063 // whether the configuration file is being used to read or write data. 00064 DiscConfig(const char *, const char *, bool); 00065 00066 // Destructor. 00067 ~DiscConfig(); 00068 00069 // 00070 // general accessor functions 00071 // 00072 00073 // did everything in the config file parse OK? 00074 bool ok() const { return ConfigOK; } 00075 00076 // return the name of our config file 00077 const string &getConfigFile() const { return ConfigFile; } 00078 00079 // return the number of SMP's there are, in total, and the number 00080 // of SMP 'filesets' which will be read or written. 00081 unsigned int numSMPs() const { return NumSMPs; } 00082 unsigned int fileSMPs() const { return FileSMPs; } 00083 unsigned int mySMP() const { return MySMP; } 00084 00085 // 00086 // SMP accessor functions 00087 // 00088 00089 // return the SMP index for the SMP with the given name, or for my own 00090 unsigned int getSMPIndex() const { return MySMP; } 00091 unsigned int getSMPIndex(const string &smpname) const { 00092 return SMPMap[smpname]->SMPIndex; 00093 } 00094 00095 // return the host name of the Nth SMP 00096 const string &getSMPHost() const { return getSMPHost(MySMP); } 00097 const string &getSMPHost(unsigned int smp) const { 00098 return SMPList[smp]->HostName; 00099 } 00100 00101 // return the number of nodes in the Nth SMP 00102 unsigned int getNumSMPNodes() const { return getNumSMPNodes(MySMP); } 00103 unsigned int getNumSMPNodes(unsigned int smp) const { 00104 return SMPList[smp]->NodeList.size(); 00105 } 00106 00107 // return the mth node ID for the Nth SMP 00108 unsigned int getSMPNode(unsigned int n) const { return getSMPNode(MySMP,n);} 00109 unsigned int getSMPNode(unsigned int smp, unsigned int n) const { 00110 return SMPList[smp]->NodeList[n]; 00111 } 00112 00113 // return the Box0 node of the Nth SMP 00114 unsigned int getSMPBox0() const { return getSMPBox0(MySMP); } 00115 unsigned int getSMPBox0(unsigned int smp) const { 00116 return SMPList[smp]->Box0Node; 00117 } 00118 00119 // return the number of filesets being read/written on the Nth smp 00120 unsigned int getNumFiles() const { return getNumFiles(MySMP); } 00121 unsigned int getNumFiles(unsigned int smp) const { 00122 return SMPList[smp]->BaseFileNum; 00123 } 00124 00125 // return the base name of the mth fileset on the Nth smp 00126 const string &getFilename(unsigned int fn) const { 00127 return getFilename(MySMP, fn); 00128 } 00129 const string &getFilename(unsigned int smp, unsigned int fn) const { 00130 return SMPList[smp]->BaseFileName[fn]; 00131 } 00132 00133 // return the number of SMP's which depend on getting info from the Nth SMP 00134 unsigned int getNumOtherSMP() const { return getNumOtherSMP(MySMP); } 00135 unsigned int getNumOtherSMP(unsigned int smp) const { 00136 return SMPList[smp]->InformSMPList.size(); 00137 } 00138 00139 // return the index of the mth SMP which depends on info from the Nth SMP 00140 unsigned int getOtherSMP(unsigned int sn) const { 00141 return getOtherSMP(MySMP, sn); 00142 } 00143 unsigned int getOtherSMP(unsigned int smp, unsigned int sn) const { 00144 return SMPList[smp]->InformSMPList[sn]; 00145 } 00146 00147 // 00148 // Node accessor functions 00149 // 00150 00151 // compute how many physical nodes there are on the same SMP as that w/node 00152 unsigned int pNodesPerSMP(unsigned int node) const; 00153 00154 // return the total number of nodes 00155 unsigned int getNumNodes() const { return NodeList.size(); } 00156 00157 // return the SMP index for the Nth node 00158 unsigned int getNodeSMPIndex(unsigned int n) const { 00159 return NodeList[n]->SMPIndex; 00160 } 00161 00162 // return the hostname for the Nth node 00163 const string &getNodeHost(unsigned int n) const { 00164 return NodeList[n]->HostName; 00165 } 00166 00167 00168 // 00169 // utility functions 00170 // 00171 00172 // a simple routine to take an input string and a list of token separators, 00173 // and return the number of tokens plus fill in a new array of strings 00174 // with the words. We had a nicer way to do this with a vector of strings, 00175 // but a #*#^@($ bug in KCC requires this workaround. 00176 static int dc_tokenize_string(const char *s, const char *tok, string *&); 00177 00178 // print out debugging information to the given Inform stream 00179 void printDebug(Inform &); 00180 00181 private: 00182 // Data needed for each SMP being used to read/write data. 00183 // Note that BaseFileNameStringList is being used here to store 00184 // a list of names only for use in constructing the BaseFileName list; 00185 // due to a bug in the use of vector<string> with KCC (debug only), 00186 // we cannot use the much more useful vector<string> to store the 00187 // fileset directory names. Sigh. 00188 struct SMPData { 00189 string HostName; 00190 string * BaseFileName; 00191 string BaseFileNameStringList; 00192 vector<int> NodeList; 00193 vector<int> InformSMPList; 00194 unsigned int Box0Node; 00195 unsigned int SMPIndex; 00196 unsigned int BaseFileNum; 00197 }; 00198 00199 // Data needed for each pnode 00200 struct NodeData { 00201 string HostName; 00202 unsigned int SMPIndex; 00203 }; 00204 00205 // The name of the configuration file 00206 string ConfigFile; 00207 00208 // the number of SMP boxes found during setup and in the files, 00209 // and which SMP this node is on (0 ... NumSMPs - 1) 00210 unsigned int NumSMPs; 00211 unsigned int FileSMPs; 00212 unsigned int MySMP; 00213 00214 // was the configuration file read successfully? If not, we cannot 00215 // do any read/write operations. 00216 bool ConfigOK; 00217 00218 // data for each SMP, and for each physical node. These are built 00219 // when the config file is parsed and the system is analyzed. 00220 // vmap: key = hostname for SMP, value = SMPData structure 00221 vmap<string,SMPData *> SMPMap; 00222 vector<SMPData *> SMPList; 00223 vector<NodeData *> NodeList; 00224 00225 // take a string with configuration filename wildcards, and substitute 00226 // in the specific values. 00227 // The first argument is the original string with wildcards (listed below), 00228 // and the second is the machine name to use when substituting in the 00229 // machine name. 00230 // Return a new string with the changes in place. 00231 string replace_wildcards(const string& s, const string& machine); 00232 00233 // take the information about the directory and hostname for a given 00234 // SMP, and add it to the list of directories for that SMP. Make sure 00235 // the directory is not repeated. If it is, issue a warning and continue. 00236 // Must be told if we're writing a file (otherwise, we're reading) 00237 void add_SMP_directory(SMPData *&, const string& s, const string& m, bool); 00238 00239 // parse the IO configuration file and store the information. Must be 00240 // told if we're writing a file (otherwise, we're reading) 00241 bool parse_config(const char *, bool); 00242 }; 00243 00244 #endif // DISC_CONFIG_H 00245 00246 /*************************************************************************** 00247 * $RCSfile: DiscConfig.h,v $ $Author: adelmann $ 00248 * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:33 $ 00249 * IPPL_VERSION_ID: $Id: DiscConfig.h,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 00250 ***************************************************************************/