src/Utility/DiscParticleFunctions.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/DiscParticle.h"
00028 #include "Utility/DiscConfig.h"
00029 #include "Utility/DiscMeta.h"
00030 #include "Message/Communicate.h"
00031 #include "Message/Message.h"
00032 #include "Profile/Profiler.h"
00033 #include "Utility/PAssert.h"
00034 #include "Utility/IpplInfo.h"
00035 #include "Utility/IpplStats.h"
00036 
00037 // debugging macros
00038 #ifdef IPPL_PRINTDEBUG
00039 #define DPFDBG(x) x
00040 #else
00041 #define DPFDBG(x)
00042 #endif
00043 
00045 // Constructor: make a DiscParticle for reading or writing.
00046 // fname = name of file (without extensions)
00047 // config = name of configuration file
00048 // I/O mode
00049 // typestr = string describing the 'type' of the Particles to be written
00050 //           (this is ignored if the data is being read).  The string can
00051 //           be anything the user prefers.
00052 DiscParticle::DiscParticle(const char *base, const char *config,
00053                            int iomode, const char *typestr) {
00054   TAU_TYPE_STRING(taustr, CT(*this) + " void (char *, char *, int, char *)" );
00055   TAU_PROFILE("DiscParticle::DiscParticle()", taustr, 
00056               TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00057   initialize(base, config, typestr, iomode);
00058 }
00059 
00060 
00062 // Constructor: same as above, but without a config file specified.  The
00063 // default config file entry that will be used is "*  .", which means, for
00064 // each SMP machine, assume the directory to put data files in is "."
00065 DiscParticle::DiscParticle(const char *base,
00066                            int iomode, const char *typestr) {
00067   TAU_TYPE_STRING(taustr, CT(*this) + " void (char *, int, char *)" );
00068   TAU_PROFILE("DiscParticle::DiscParticle()", taustr, 
00069               TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00070   initialize(base, 0, typestr, iomode);
00071 }
00072 
00073 
00075 // perform initialization based on the constuctor arguments
00076 void DiscParticle::initialize(const char *base, const char *config,
00077                               const char *typestr, int iomode) {
00078   TAU_TYPE_STRING(taustr, CT(*this) + " void (char *, char *, char *, int )");
00079   TAU_PROFILE("DiscParticle::initialize()", taustr, 
00080               TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00081 
00082   // save which IO mode we're running, and make sure it is OK
00083   if (iomode != INPUT && iomode != OUTPUT && iomode != APPEND)
00084     Ippl::abort("IO mode for DiscParticle must be INPUT, OUTPUT, or APPEND.");
00085   IOMode = iomode;
00086   CurrentOffset = 0;
00087 
00088   // save the name information
00089   BaseFile = base;
00090   if (typestr != 0)
00091     TypeString = typestr;
00092   else
00093     TypeString = "unknown";
00094 
00095   // parse the configuration file to find our SMP's, file directories, etc.
00096   // create a DiscConfig instance, which will parse the file
00097   Config = new DiscConfig(config, BaseFile.c_str(), IOMode != INPUT);
00098   ConfigOK = Config->ok();
00099 
00100   // indicate how many filesets we're reading or writing
00101   if (iomode != INPUT) {
00102     ADDIPPLSTAT(incDiscFilesetWrites,Config->getNumFiles());
00103   } else {
00104     ADDIPPLSTAT(incDiscFilesetReads,Config->getNumFiles());
00105   }
00106 
00107   // read the meta information about numbers of particles, etc. in each record
00108   if (ConfigOK && IOMode != OUTPUT)
00109     ConfigOK = read_meta();
00110 }
00111 
00112 
00114 // Destructor
00115 DiscParticle::~DiscParticle() {
00116   TAU_TYPE_STRING(taustr, CT(*this) +  " void ()" );
00117   TAU_PROFILE("DiscParticle::~DiscParticle()", taustr, 
00118     TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00119 
00120   // delete per-record information
00121   vector<RecordInfo *>::iterator rec = RecordList.begin();
00122   for ( ; rec != RecordList.end(); ++rec)
00123     delete (*rec);
00124 
00125   // delete the configuration file info
00126   if (Config != 0)
00127     delete Config;
00128 }
00129 
00130 
00132 // Query for the DiscType string for the Mth attribute in the Nth record.
00133 // If there not one available, return 0.
00134 const char *DiscParticle::get_DiscType(unsigned int record,
00135                                        unsigned int attrib) const {
00136   // return the string, if it is available
00137   if (record < get_NumRecords() &&
00138       attrib < RecordList[record]->disctypes.size())
00139     return (RecordList[record]->disctypes[attrib].c_str());
00140   else
00141     return 0;
00142 }
00143 
00144 
00146 // Query for how many individual particles are stored in the Nth record,
00147 // for just the local filesets
00148 unsigned int DiscParticle::get_NumLocalParticles(unsigned int record) const {
00149   unsigned int retval = 0;
00150   for (int i=0; i < RecordList[record]->localparticles.size(); ++i)
00151     retval += RecordList[record]->localparticles[i];
00152   return retval;
00153 }
00154 
00155 
00157 // open a file in the given mode.  If an error occurs, print a message
00158 // and return 0.
00159 FILE *DiscParticle::open_file(const string& fnm, const string& mode,
00160                               bool reporterr) {
00161   TAU_TYPE_STRING(taustr, CT(*this) +  " FILE * (string, string, bool )" );
00162   TAU_PROFILE("DiscParticle::open_file()", taustr, 
00163               TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00164 
00165   // open the file, with the given name and mode
00166   FILE *f = fopen(fnm.c_str(), mode.c_str());
00167 
00168   // check for an error
00169   if (f == 0 && reporterr) {
00170     ERRORMSG("DiscParticle: Could not open file '" << fnm.c_str());
00171     ERRORMSG("' on node " << Ippl::myNode() << "." << endl);
00172   }
00173 
00174   // return the file pointer; if an error occurred, this will be zero
00175   return f;
00176 }
00177 
00178 
00180 // write out a new .meta file.  The .meta file contains the following
00181 // information, on each line:
00182 //   String with type of data stored here, supplied by user
00183 //   Number of SMP filesets
00184 //   Number of Records
00185 //   For each record:
00186 //     Number of attributes (if 0, this is just for one attrib, not all)
00187 //     Number of local particles
00188 //     Number of particles total
00189 //     For each attribute in the record:
00190 //       Size of attribute elements, in bytes
00191 //       Offset location of start of attribute data in .data file
00192 // return success of operation.
00193 bool DiscParticle::write_meta() {
00194   TAU_TYPE_STRING(taustr, CT(*this) +  " bool ()" );
00195   TAU_PROFILE("DiscParticle::write_meta()", taustr, 
00196               TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00197 
00198   // Sanity checking
00199   if (!ConfigOK) {
00200     ERRORMSG("Bad config file in DiscParticle::write_meta." << endl);
00201     return false;
00202   } else if (IOMode == INPUT) {
00203     ERRORMSG("Trying to write a DiscParticle .meta file for a DiscParticle");
00204     ERRORMSG(" created for reading." << endl);
00205     return false;
00206   } else if (Config->getNumFiles() > 1) {
00207     ERRORMSG("Only one fileset/SMP max allowed when writing" << endl);
00208     return false;
00209   }
00210 
00211   // no need to write anything if we have no files for this SMP
00212   if (Ippl::myNode() != Config->getSMPBox0() || Config->getNumFiles() == 0)
00213     return true;
00214 
00215   // open the meta data file
00216   string filename = Config->getFilename(0) + ".meta";
00217   FILE *outputMeta = open_file(filename, string("w"));
00218   if (outputMeta == 0)
00219     return false;
00220 
00221   // write the initial header info
00222   long rnum = RecordList.size();
00223   fprintf(outputMeta, "Type =           %s\n", TypeString.c_str());
00224   fprintf(outputMeta, "SMPs =           %d\n", Config->fileSMPs());
00225   fprintf(outputMeta, "Records =        %ld\n", rnum);
00226   fprintf(outputMeta, "NextOffset =     %ld\n", CurrentOffset);
00227 
00228   // write information for each record
00229   for (int r=0; r < RecordList.size(); ++r) {
00230     // general record information
00231     fprintf(outputMeta, "RecordAttribs =  %d  %d\n", r,
00232             RecordList[r]->attributes);
00233     fprintf(outputMeta, "RecordLocPtcl =  %d  %d\n", r,
00234             RecordList[r]->localparticles[0]);
00235     fprintf(outputMeta, "RecordGlobPtcl = %d  %d\n", r,
00236             RecordList[r]->globalparticles);
00237 
00238     // information about each attribute
00239     fprintf(outputMeta, "RecordElemByte = %d ", r);
00240     int b, bmax;
00241     bmax = RecordList[r]->bytesize.size();
00242     for (b=0; b<bmax; ++b)
00243       fprintf(outputMeta, " %d", RecordList[r]->bytesize[b]);
00244     fprintf(outputMeta, "\n");
00245     fprintf(outputMeta, "RecordDiscType = %d ", r);
00246     for (b=0; b<bmax; ++b)
00247       fprintf(outputMeta, " %s", RecordList[r]->disctypes[b].c_str());
00248     fprintf(outputMeta, "\n");
00249     fprintf(outputMeta, "RecordOffset =   %d ", r);
00250     bmax = RecordList[r]->offset[0].size();
00251     for (b=0; b<bmax; ++b)
00252       fprintf(outputMeta, " %ld", RecordList[r]->offset[0][b]);
00253     fprintf(outputMeta, "\n");
00254   }
00255 
00256   // close data file and return
00257   fclose(outputMeta);
00258   DPFDBG(printDebug());
00259   return true;
00260 }
00261 
00262 
00264 // read in data from .meta file, and replace current storage values.
00265 // The format for a .meta file is described in the write_meta routine.
00266 // return success of operation.
00267 bool DiscParticle::read_meta() {
00268   TAU_TYPE_STRING(taustr, CT(*this) +  " bool ()" );
00269   TAU_PROFILE("DiscParticle::read_meta()", taustr, 
00270               TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00271 
00272   // Sanity checking
00273   if (!ConfigOK) {
00274     ERRORMSG("Bad config file in DiscParticle::read_meta." << endl);
00275     return false;
00276   }
00277 
00278   bool iserror = false;
00279   int tag = Ippl::Comm->next_tag(DF_READ_META_TAG, DF_TAG_CYCLE);
00280 
00281   DPFDBG(string dbgmsgname("DP:read_meta:"));
00282   DPFDBG(dbgmsgname += Config->getConfigFile());
00283   DPFDBG(Inform dbgmsg(dbgmsgname.c_str(), INFORM_ALL_NODES));
00284   DPFDBG(dbgmsg << "Starting to read meta info: mySMP=" << Config->mySMP());
00285   DPFDBG(dbgmsg << ", mybox0=" << Config->getSMPBox0());
00286   DPFDBG(dbgmsg << ", numfiles=" << Config->getNumFiles());
00287   DPFDBG(dbgmsg << endl);
00288 
00289   // initialize data before reading .meta file
00290   TypeString = "unknown";
00291   vector<RecordInfo *>::iterator rec = RecordList.begin();
00292   for ( ; rec != RecordList.end(); ++rec)
00293     delete (*rec);
00294   RecordList.erase(RecordList.begin(), RecordList.end());
00295 
00296   // on Box0 nodes, read in the meta data ... on others, wait for
00297   // Box0 nodes to send info to them
00298   if (Ippl::myNode() == Config->getSMPBox0()) {
00299     // loop over all the files on this Box0 node
00300     for (int sf=0; sf < Config->getNumFiles(); ++sf) {
00301       // open and parse the meta data file
00302       string filename = Config->getFilename(sf) + ".meta";
00303       DiscMeta outputMeta(filename.c_str());
00304       if (outputMeta.size() == 0)
00305         return false;
00306 
00307       // keep reading until we have all data
00308       DiscMeta::iterator metaline = outputMeta.begin();
00309       for ( ; metaline != outputMeta.end(); ++metaline) {
00310         // get number of tokens and list of tokens in the line
00311         int linesread  = (*metaline).first;
00312         int numtokens  = (*metaline).second.first;
00313         string *tokens = (*metaline).second.second;
00314 
00315         // action is based on first keyword
00316         if (tokens[0] == "Type") {
00317           if (numtokens > 1 && sf == 0)
00318             TypeString = tokens[1];
00319         } else if (tokens[0] == "SMPs" && numtokens == 2) {
00320           int checkfileSMPs = atoi(tokens[1].c_str());
00321           if (Config->fileSMPs() != checkfileSMPs) {
00322             ERRORMSG("SMP number mismatch in file " << filename);
00323             ERRORMSG(" (" << checkfileSMPs << "!=" << Config->fileSMPs());
00324             ERRORMSG(")" << endl);
00325             iserror = true;
00326           }
00327         } else if (tokens[0] == "NextOffset" && numtokens == 2) {
00328           CurrentOffset = atol(tokens[1].c_str());
00329         } else if (tokens[0] == "Records" && numtokens == 2) {
00330           int numrec = atoi(tokens[1].c_str());
00331           if (RecordList.size() != 0 && RecordList.size() != numrec) {
00332             ERRORMSG("Illegal Records value in file '" << filename << "' ");
00333             ERRORMSG("(" << numrec << " != " << RecordList.size() << ")");
00334             ERRORMSG(endl);
00335             iserror = true;
00336           } else {
00337             // create N empty record storage objects
00338             for (int r=0; r < atoi(tokens[1].c_str()); ++r)
00339               RecordList.push_back(new RecordInfo());
00340           }
00341         } else if (tokens[0] == "RecordAttribs" && numtokens == 3) {
00342           int recnum = atoi(tokens[1].c_str());
00343           int attribs = atoi(tokens[2].c_str());
00344           if (recnum < 0 || recnum >= RecordList.size()) {
00345             ERRORMSG("Illegal record number '" << recnum << "'" << endl);
00346             iserror = true;
00347           } else if (sf > 0 && attribs != RecordList[recnum]->attributes) {
00348             ERRORMSG("Illegal number of attributes in file " << filename);
00349             ERRORMSG(" (" << attribs << " != ");
00350             ERRORMSG(RecordList[recnum]->attributes << ")" << endl);
00351             iserror = true;
00352           } else {
00353             RecordList[recnum]->attributes = attribs;
00354           }
00355         } else if (tokens[0] == "RecordLocPtcl" && numtokens == 3) {
00356           int recnum = atoi(tokens[1].c_str());
00357           int nump = atoi(tokens[2].c_str());
00358           if (recnum < 0 || recnum >= RecordList.size()) {
00359             ERRORMSG("Illegal record number '" << recnum << "'" << endl);
00360             iserror = true;
00361           } else {
00362             RecordList[recnum]->localparticles.push_back(nump);
00363           }
00364         } else if (tokens[0] == "RecordGlobPtcl" && numtokens == 3) {
00365           int recnum = atoi(tokens[1].c_str());
00366           int nump = atoi(tokens[2].c_str());
00367           if (recnum < 0 || recnum >= RecordList.size()) {
00368             ERRORMSG("Illegal record number '" << recnum << "'" << endl);
00369             iserror = true;
00370           } else if (sf > 0 && nump != RecordList[recnum]->globalparticles) {
00371             ERRORMSG("Illegal number of global particles in file "<<filename);
00372             ERRORMSG(" (" << nump << " != ");
00373             ERRORMSG(RecordList[recnum]->globalparticles << ")" << endl);
00374             iserror = true;
00375           } else {
00376             RecordList[recnum]->globalparticles = nump;
00377           }
00378         } else if (tokens[0] == "RecordElemByte" && numtokens >= 2) {
00379           int recnum = atoi(tokens[1].c_str());
00380           if (recnum < 0 || recnum >= RecordList.size()) {
00381             ERRORMSG("Illegal record number '" << recnum << "'" << endl);
00382             iserror = true;
00383           } else {
00384             for (int b=2; b < numtokens; ++b) {
00385               int bytesize = atoi(tokens[b].c_str());
00386               if (sf > 0 && bytesize != RecordList[recnum]->bytesize[b-2]) {
00387                 ERRORMSG("Illegal byte size for attribute " << b-2);
00388                 ERRORMSG(" in file " << filename << "(" << bytesize);
00389                 ERRORMSG(" != " << RecordList[recnum]->bytesize[b-2] << ")");
00390                 ERRORMSG(endl);
00391                 iserror = true;
00392               } else if (sf == 0) {
00393                 RecordList[recnum]->bytesize.push_back(bytesize);
00394               }
00395             }
00396             if (RecordList[recnum]->bytesize.size() !=
00397                 (RecordList[recnum]->attributes == 0 ? 1 :
00398                  RecordList[recnum]->attributes)) {
00399               ERRORMSG("Incorrect number of byte size values in file ");
00400               ERRORMSG(filename << endl);
00401               iserror = true;
00402             }
00403           }
00404         } else if (tokens[0] == "RecordDiscType" && numtokens >= 2) {
00405           int recnum = atoi(tokens[1].c_str());
00406           if (recnum < 0 || recnum >= RecordList.size()) {
00407             ERRORMSG("Illegal record number '" << recnum << "'" << endl);
00408             iserror = true;
00409           } else {
00410             for (int b=2; b < numtokens; ++b) {
00411               if (sf > 0 && tokens[b] != RecordList[recnum]->disctypes[b-2]) {
00412                 ERRORMSG("Inconsistent DiscType for attribute " << b-2);
00413                 ERRORMSG(" in file " << filename << "(" << tokens[b]);
00414                 ERRORMSG(" != " << RecordList[recnum]->disctypes[b-2] << ")");
00415                 ERRORMSG(endl);
00416                 iserror = true;
00417               } else if (sf == 0) {
00418                 RecordList[recnum]->disctypes.push_back(tokens[b]);
00419               }
00420             }
00421             if (RecordList[recnum]->disctypes.size() !=
00422                 (RecordList[recnum]->attributes == 0 ? 1 :
00423                  RecordList[recnum]->attributes)) {
00424               ERRORMSG("Incorrect number of DiscType values in file ");
00425               ERRORMSG(filename << endl);
00426               iserror = true;
00427             }
00428           }
00429         } else if (tokens[0] == "RecordOffset" && numtokens >= 2) {
00430           int recnum = atoi(tokens[1].c_str());
00431           if (recnum < 0 || recnum >= RecordList.size()) {
00432             ERRORMSG("Illegal record number '" << recnum << "'" << endl);
00433             iserror = true;
00434           } else {
00435             vector<Offset_t> offsetvec;
00436             for (int b=2; b < numtokens; ++b) {
00437               Offset_t offset = atol(tokens[b].c_str());
00438               if (sf > 0 && offset != RecordList[recnum]->offset[sf][b-2]) {
00439                 ERRORMSG("Illegal offset for attribute " << b-2);
00440                 ERRORMSG(" in file " << filename << "(");
00441                 ERRORMSG(static_cast<long>(offset) << " != ");
00442                 ERRORMSG(static_cast<long>(
00443                          RecordList[recnum]->offset[sf][b-2]) << ")" << endl);
00444                 iserror = true;
00445               } else if (sf == 0) {
00446                 offsetvec.push_back(offset);
00447               }
00448             }
00449             if (sf == 0) {
00450               if (offsetvec.size() != (RecordList[recnum]->attributes==0 ? 1 :
00451                                        RecordList[recnum]->attributes)) {
00452                 ERRORMSG("Incorrect number of offset values in file ");
00453                 ERRORMSG(filename << endl);
00454                 iserror = true;
00455               } else {
00456                 RecordList[recnum]->offset.push_back(offsetvec);
00457               }
00458             }
00459           }
00460         } else {
00461           // error in line: unknown keyword
00462           iserror = true;
00463         }
00464 
00465         DPFDBG(dbgmsg << "On box0: finished line with tokens[0]='"<<tokens[0]);
00466         DPFDBG(dbgmsg << "' ... iserror = " << iserror << endl);
00467 
00468         // print if there was an error
00469         if (iserror) {
00470           ERRORMSG("Format error on line " << linesread << " in file ");
00471           ERRORMSG(filename << endl);
00472           break;
00473         }
00474       }
00475 
00476       // stop processing meta files is there was an error
00477       if (iserror)
00478         break;
00479     }
00480 
00481     DPFDBG(dbgmsg << "Summary of meta info:" << endl);
00482     DPFDBG(dbgmsg << "  iserror = " << iserror << endl);
00483     DPFDBG(dbgmsg << "  NumRecords = " << RecordList.size() << endl);
00484     DPFDBG(dbgmsg << "  TypeString = " << TypeString << endl);
00485     DPFDBG(dbgmsg << "  NextOffset = " << static_cast<long>(CurrentOffset));
00486     DPFDBG(dbgmsg << endl);
00487 
00488     // now send meta info to all nodes which expect it
00489     int numinform = Config->getNumOtherSMP();
00490     DPFDBG(dbgmsg << "Informing " << numinform << " SMP's of meta info");
00491     DPFDBG(dbgmsg << endl);
00492     for (int s=0; s <= numinform; ++s) {
00493       int smp = Config->mySMP();
00494       if (s != numinform)
00495         smp = Config->getOtherSMP(s);
00496       DPFDBG(dbgmsg << "SMP " << smp << " has " <<Config->getNumSMPNodes(smp));
00497       DPFDBG(dbgmsg << " nodes to check." << endl);
00498       for (int n=0; n < Config->getNumSMPNodes(smp); ++n) {
00499         int node = Config->getSMPNode(smp, n);
00500         if (node != Ippl::myNode()) {
00501           // create a message with meta info
00502           Message *msg = new Message;
00503           ::putMessage(*msg, TypeString);
00504           int errint = iserror;
00505           msg->put(errint);
00506           if (!iserror) {
00507             long curroff = CurrentOffset;
00508             msg->put(curroff);
00509             int recnum = RecordList.size();
00510             msg->put(recnum);
00511             for (int r=0; r < RecordList.size(); ++r) {
00512               int filesnum = RecordList[r]->localparticles.size();
00513               msg->put(filesnum);
00514               msg->put(RecordList[r]->attributes);
00515               msg->put(RecordList[r]->globalparticles);
00516               for (int p=0; p < RecordList[r]->localparticles.size(); ++p)
00517                 msg->put(RecordList[r]->localparticles[p]);
00518               for (int b=0; b < RecordList[r]->bytesize.size(); ++b)
00519                 msg->put(RecordList[r]->bytesize[b]);
00520 
00521               // make sure we have disctypes ... add if necessary
00522               string unknowndtype = "u";
00523               for (int dr = RecordList[r]->disctypes.size();
00524                    dr < RecordList[r]->bytesize.size(); ++dr)
00525                 RecordList[r]->disctypes.push_back(unknowndtype);
00526 
00527               for (int t=0; t < RecordList[r]->bytesize.size(); ++t)
00528                 ::putMessage(*msg, RecordList[r]->disctypes[t]);
00529               for (int z=0; z < RecordList[r]->offset.size(); ++z) {
00530                 for (int o=0; o < RecordList[r]->offset[z].size(); ++o) {
00531                   long value = RecordList[r]->offset[z][o];
00532                   msg->put(value);
00533                 }
00534               }
00535             }
00536           }
00537 
00538           // send the message to the intended node
00539           DPFDBG(dbgmsg<<"Sending meta info to node " << node << " with tag ");
00540           DPFDBG(dbgmsg<< tag << ", on SMP " << smp << endl);
00541           Ippl::Comm->send(msg, node, tag);
00542         }
00543       }
00544     }
00545 
00546   } else {
00547     // all other nodes (which are not Box0 nodes) should get a message
00548     // telling them the meta info
00549     int node = Config->getSMPBox0();
00550     DPFDBG(dbgmsg << "Waiting for meta info from node " << node);
00551     DPFDBG(dbgmsg << " with tag " << tag << endl);
00552     Message *msg = Ippl::Comm->receive_block(node, tag);
00553     PAssert(msg != 0);
00554 
00555     // get info out of message
00556     DPFDBG(dbgmsg << "Summary of received meta info:" << endl);
00557     ::getMessage(*msg, TypeString);
00558     DPFDBG(dbgmsg << "  TypeString = " << TypeString << endl);
00559     int errint, numrec, val;
00560     msg->get(errint);
00561     iserror = (errint != 0);
00562     DPFDBG(dbgmsg << "  iserror = " << iserror << endl);
00563     if (!iserror) {
00564       long curroff;
00565       msg->get(curroff);
00566       CurrentOffset = curroff;
00567       DPFDBG(dbgmsg << "  CurrentOffset = " << curroff << endl);
00568       msg->get(numrec);
00569       DPFDBG(dbgmsg << "  NumRecords = " << numrec << endl);
00570       for (int r=0; r < numrec; ++r) {
00571         DPFDBG(dbgmsg << "  For record " << r << ":" << endl);
00572         RecordList.push_back(new RecordInfo());
00573         int filesnum = RecordList[r]->localparticles.size();
00574         msg->get(filesnum);
00575         DPFDBG(dbgmsg << "    Filesets=" << filesnum << endl);
00576         msg->get(RecordList[r]->attributes);
00577         int numattr = RecordList[r]->attributes;
00578         if (RecordList[r]->attributes == 0)
00579           numattr = 1;
00580         DPFDBG(dbgmsg << "    Attribs=" << numattr << endl);
00581         msg->get(RecordList[r]->globalparticles);
00582         DPFDBG(dbgmsg << "    Global#="<<RecordList[r]->globalparticles<<endl);
00583         for (int p=0; p < filesnum; ++p) {
00584           msg->get(val);
00585           DPFDBG(dbgmsg << "    Local " << p << " = " << val << endl);
00586           RecordList[r]->localparticles.push_back(val);
00587         }
00588         for (int b=0; b < numattr; ++b) {
00589           msg->get(val);
00590           DPFDBG(dbgmsg << "    Bytesize " << b << " = " << val << endl);
00591           RecordList[r]->bytesize.push_back(val);
00592         }
00593         for (int t=0; t < numattr; ++t) {
00594           string dtype;
00595 	  ::getMessage(*msg, dtype);
00596           DPFDBG(dbgmsg << "    Disctype " << t << " = " << dtype << endl);
00597           RecordList[r]->disctypes.push_back(dtype);
00598         }
00599         for (int z=0; z < filesnum; ++z) {
00600           vector<Offset_t> offsetvec;
00601           Offset_t offset;
00602           long value;
00603           for (int o=0; o < numattr; ++o) {
00604             msg->get(value);
00605             offset = value;
00606             DPFDBG(dbgmsg << "    Offset " << z << "," << o << " = ");
00607             DPFDBG(dbgmsg << offset << endl);
00608             offsetvec.push_back(offset);
00609           }
00610           RecordList[r]->offset.push_back(offsetvec);
00611         }
00612       }
00613     }
00614 
00615     // we're done with this message
00616     delete msg;
00617   }
00618 
00619   // at the end, if there was an error, get rid of all the existing record
00620   // info
00621   if (iserror) {
00622     DPFDBG(dbgmsg<<"Cleaning up error record info at end of read_meta"<<endl);
00623     vector<RecordInfo *>::iterator rec = RecordList.begin();
00624     for ( ; rec != RecordList.end(); ++rec)
00625       delete (*rec);
00626     RecordList.erase(RecordList.begin(), RecordList.end());
00627   }
00628 
00629   // print out summary
00630   DPFDBG(printDebug());
00631 
00632   // return whether there was an error
00633   return (!iserror);
00634 }
00635 
00636 
00638 bool DiscParticle::write_data(FILE *outputData, vector<Message *> &msgvec,
00639                               RecordInfo *info) {
00640   TAU_TYPE_STRING(taustr, CT(*this) + " bool (FILE *, vector<Message *>" +
00641                   ", RecordInfo *)");
00642   TAU_PROFILE("DiscParticle::write_data()", taustr, 
00643               TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00644 
00645   DPFDBG(Inform dbgmsg("DiscParticle::write_data", INFORM_ALL_NODES));
00646 
00647   // a vector for storing information about how many particles are in each msg
00648   vector<int> numvec;
00649   vector<Offset_t> offsetvec;
00650   int totalnum = 0;
00651 
00652   // seek to the current offset, since the file may have changed
00653   if (fseek(outputData, CurrentOffset, SEEK_SET) != 0) {
00654     ERRORMSG("Error seeking to position " << static_cast<long>(CurrentOffset));
00655     ERRORMSG(" in .data file for DiscParticle::write_data." << endl);
00656     fclose(outputData);
00657     return false;
00658   }
00659 
00660   // loop over all the attributes in the messages
00661   int numattr = info->attributes;
00662   if (numattr == 0)
00663     numattr = 1;
00664   for (int a=0; a < numattr; ++a) {
00665     DPFDBG(dbgmsg<<"Writing out data from messages for attrib " << a << endl);
00666     offsetvec.push_back(CurrentOffset);
00667 
00668     // loop over all the nodes that provided data
00669     for (int n=0; n < msgvec.size(); ++n) {
00670       // for each node, get out the number of particles, get the data, and
00671       // write it out
00672       int nump;
00673       if (a == 0) {
00674         msgvec[n]->get(nump);
00675         numvec.push_back(nump);
00676         totalnum += nump;
00677       } else {
00678         nump = numvec[n];
00679       }
00680       DPFDBG(dbgmsg << "  Attrib " << a << " has " << nump << " particles ");
00681       DPFDBG(dbgmsg << "from node " << n << endl);
00682 
00683       if (nump > 0) {
00684         // get the data for this attribute
00685         void *msgdata = msgvec[n]->remove();
00686 
00687         // write it out now ...
00688         int totalbytes = nump * info->bytesize[a];
00689         DPFDBG(dbgmsg << "  Writing out block of " << nump << " particles, ");
00690         DPFDBG(dbgmsg << "with " << totalbytes << " bytes." << endl);
00691         if (fwrite(msgdata, 1, totalbytes, outputData) != totalbytes) {
00692           ERRORMSG("Write error in DiscParticle::write_data" << endl);
00693           fclose(outputData);
00694           return false;
00695         }
00696 
00697         // update the current offset position
00698         CurrentOffset += totalbytes;
00699         ADDIPPLSTAT(incDiscBytesWritten, totalbytes);
00700 
00701         // free the message data storage
00702         free(msgdata);
00703       }
00704 
00705       // delete the message, if we can
00706       if ((a+1) == numattr)
00707         delete (msgvec[n]);
00708     }
00709   }
00710 
00711   // save the offset information for each attribute
00712   DPFDBG(dbgmsg << "At end of attrib write; totalnum = " << totalnum << endl);
00713   info->offset.push_back(offsetvec);
00714   info->localparticles.push_back(totalnum);
00715 
00716   // we're done writing; return success
00717   return true;
00718 }
00719 
00720 
00722 // read the data for the Nth attribute of record R, in the Fth fileset,
00723 // and return the newly allocated buffer (or 0 if an error occurs).
00724 void *DiscParticle::read_data(FILE *outputData, unsigned int attrib,
00725                               unsigned int record, unsigned int fileset) {
00726   TAU_TYPE_STRING(taustr, CT(*this) + " void *(FILE *, unsigned int" +
00727                   ", unsigned int, unsigned int)");
00728   TAU_PROFILE("DiscParticle::read_data()", taustr, 
00729               TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00730 
00731   DPFDBG(Inform dbgmsg("DiscParticle::read_data", INFORM_ALL_NODES));
00732 
00733   // determine the byte size of the attribute, and the offset
00734   int nump = RecordList[record]->localparticles[fileset];
00735   int bytesize = RecordList[record]->bytesize[attrib];
00736   DPFDBG(dbgmsg << "Particles=" << nump << ", sizeof(T)=" << bytesize << endl);
00737 
00738   // if there are no particles to read, just return
00739   if (nump < 1 || bytesize < 1)
00740     return 0;
00741 
00742   // seek to proper position first, for the first attribute
00743   if (attrib == 0) {
00744     Offset_t seekpos = RecordList[record]->offset[fileset][attrib];
00745     DPFDBG(dbgmsg << "seekpos = " << seekpos << endl);
00746     if (fseek(outputData, seekpos, SEEK_SET) != 0) {
00747       ERRORMSG("Error seeking to position " << static_cast<long>(seekpos));
00748       ERRORMSG(" in .data file for DiscParticle::read_data." << endl);
00749       fclose(outputData);
00750       return 0;
00751     }
00752   }
00753 
00754   // allocate a block of memory to store the data now
00755   int totalbytes = nump * bytesize;
00756   void *buffer = malloc(totalbytes);
00757 
00758   // read the data into the provided buffer
00759   DPFDBG(dbgmsg << "Reading " << totalbytes << " bytes from file ..." << endl);
00760   if (fread(buffer, 1, totalbytes, outputData) != totalbytes) {
00761     ERRORMSG("Read error in DiscParticle::read_data" << endl);
00762     free(buffer);
00763     fclose(outputData);
00764     return 0;
00765   }
00766 
00767   //DPFDBG(dbgmsg << "Read in block of " << size << " elements:" << endl);
00768   //DPFDBG(for (unsigned int i=0; i < size; ++i))
00769   //DPFDBG(  dbgmsg << "  buffer[" << i << "] = " << buffer[i] << endl);
00770 
00771   ADDIPPLSTAT(incDiscBytesRead, totalbytes);
00772   return buffer;
00773 }
00774 
00775 
00777 // print out debugging information for this DiscParticle
00778 void DiscParticle::printDebug() { printDebug(cout); }
00779 
00780 void DiscParticle::printDebug(ostream& outmsg) {
00781   TAU_TYPE_STRING(taustr, CT(*this) +  " void (ostream )" );
00782   TAU_PROFILE("DiscParticle::printDebug()", taustr, 
00783               TAU_UTILITY | TAU_PARTICLE | TAU_IO);
00784 
00785   Inform msg("DiscParticle", outmsg, INFORM_ALL_NODES);
00786 
00787   msg << "BaseFile   = " << BaseFile << endl;
00788   msg << "NumRecords = " << get_NumRecords() << endl;
00789   msg << "NextOffset = " << static_cast<long>(CurrentOffset) << endl;
00790 
00791   for (int r=0; r < get_NumRecords(); ++r) {
00792     msg << "For record " << r << ":" << endl;
00793     msg << "  Number of attributes = " << get_NumAttributes(r) << endl;
00794     msg << "  Total number of particles = " << get_NumGlobalParticles(r)<<endl;
00795     msg << "  Byte size of attributes =";
00796     for (int b=0; b < get_NumAttributes(r); ++b)
00797       msg << " " << get_ElemByteSize(r, b);
00798     msg << endl;
00799     msg << "  DiscTypes of attributes =";
00800     for (int t=0; t < get_NumAttributes(r); ++t) {
00801       if (get_DiscType(r, t) != 0)
00802         msg << " " << get_DiscType(r, t);
00803     }
00804     msg << endl;
00805     for (int f=0; f < Config->getNumFiles(); ++f) {
00806       msg << "  Local number of particles in fileset " << f << " = ";
00807       msg << RecordList[r]->localparticles[f] << endl;
00808       for (int a=0; a < get_NumAttributes(r); ++a) {
00809         msg << "  Offset of attribute " << a << " in fileset " << f << " = ";
00810         msg << static_cast<long>(RecordList[r]->offset[f][a]) << endl;
00811       }
00812     }
00813   }
00814 
00815   msg << "Configuration file information:" << endl;
00816   Config->printDebug(msg);
00817 
00818   msg << endl;
00819 }
00820 
00821 
00822 /***************************************************************************
00823  * $RCSfile: DiscParticleFunctions.cpp,v $   $Author: adelmann $
00824  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:33 $
00825  * IPPL_VERSION_ID: $Id: DiscParticleFunctions.cpp,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 
00826  ***************************************************************************/

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