// ---------------------------------------------------------------------- // // HepHBookFileManager.cc - implementation the wrapper for the CERNlib // HBook histogram Fortran package // // HepHBookFileManager is a C++ wrapper class that controls the // initialization and creation of histograms and ntuples and allows // them to be written to a file in the HBook format. // // This class is derived from the HepFileManager, and is not an abstract // class. It should be instantiated before any histograms or ntuples - a // pointer to the manager is passed to every histogram and ntuple upon // creation. // // The code presumes that Fortran is callable from C by the (mostly) // standard BSD convention: all lowercase symbol names with an // underscore ("_") appended. // // write() writes the managed HBook objects to a file, as does the // destructor. // dumpAllData() and clearAllData() initiate calls of dumpData() or // clearData() to all managed objects. // // Storage for HBOOK is initialized in the routine "hbfinit" in // HepHBookFile.f. You will need to override this routine if you need // more space. // // // History // ??-Jul-1994 Paul Rensing Initial draft // ??-Aug-1994 Bob Jacobsen Added Histos and numbering // 25-Jul-1995 Kral Change limit of 8000 records to 32000 // records with the ZEBRA common block variable IQUEST(10) // 28-Jan-1997 John Marraffino Added directory functionality // 20-May-1997 Walter Brown General cleanup // 29-May-1997 Jason Luther Added comments // 12-Jun-1997 Walter Brown Let constructor croak (exit) on error // 27-Jun-1997 Walter Brown Replaced HepString by standard string // 30-Jun-1997 Walter Brown Conserve memory by keeping in memory // only inUse histograms // 08-Jul-1997 Walter Brown Call hbfinit_() in lieu of hlimit_() // to assure linking with Fortran common block // 18-Jul-1997 Philippe Canal Added HepNtuple constructor // still need to add actual filemanager and Hbook stuff to it. // 25-Jul-1997 Walter Brown Added interlock to prevent multiple // calls to hrendc_ // 05-Aug-1997 Walter Brown Added writeOne() // 06-Aug-1997 Walter Brown Fleshed out directory-handling // 08-Aug-1997 Walter Brown Added/corrected logic re proper 1st // setting for an object's dirty bit: true (dirty) if it's been // created via a hepXxx call, false (not dirty) if via retrieveHepXxx; // disallowed HepNtuple with duplicate titles or ids // 11-Aug-1997 Walter Brown Mess with case of file names, to meet // HBook's inconsistent wonder-workings // 12-Aug-1997 Walter Brown Fix up writeDirectory() // 14-Aug-1997 Walter Brown Added root directory name to the // constructor's arg list so as to conform more closely to the // base class constructor arg list; added release() // 15-Aug-1997 Walter Brown Fleshed out ls() // 19-Aug-1997 Walter Brown Fleshed out rm() // 21-Aug-1997 Walter Brown Renamed newX() to makeX() and oldX() // to retrieveX(); changed return values from pointers to references; // added retrieveNtuple() prototype // 27-Aug-1997 Walter Brown Renamed makeX() to x() per committee // 10-Sep-1997 Walter Brown Updated to excise CLHEP's AList usage // 9-Oct-1997 Marraffino Add code to re-instantiate an existing // ntuple from a file // 31-Oct-1997 Philippe Canal Add dead object creator for use after // an ignored exceptions // 20-Nov-1997 Philippe Canal Readied for exceptions // 30-Jul-1998 Philippe Canal Fixes directory bugs // 13-Nov-1998 J. Marraffino Put include "ZMutility/iostream" ahead of // include to get timer structures // defined properly under IRIX 6.4 // 25-Feb-1999 Philippe Canal Add read-only files // 21-Feb-2000 Walter Brown Improved C++ standard compliance // 7-Jul-2000 Marraffino Override the base class list method to force // upper case for HBook directory names // 19-Mar-2001 Fischler hepFileFormat // // ---------------------------------------------------------------------- #include "ZMutility/ZMenvironment.h" #include "ZMutility/iostream" // moved here from below to get time.h right #include #include #include #include USING( std::string ) //#include "ZMutility/iostream" // moved upstairs as noted #ifndef ISOCXX__ISOCXX #include #endif #include USING( std::deque ) #ifndef HEPTRACE_H #include "HepTuple/HepTrace.h" #endif #ifndef HEPHBOOKFILEMANAGER_H #include "HepTuple/HepHBookFileManager.h" #endif #ifndef HEPHBOOKHIST1D_H #include "HepTuple/HepHBookHist1D.h" #endif #ifndef HEPHBOOKHIST2D_H #include "HepTuple/HepHBookHist2D.h" #endif #ifndef HEPHBOOKHISTPROF_H #include "HepTuple/HepHBookHistProf.h" #endif #ifndef HEPHBOOKWRAPPERS_H #include "HepTuple/HepHBookWrappers.h" #include "ZMtools/pretendToUse.h" #endif #ifndef HEPHBOOKTUPLE_H #include "HepTuple/HepHBookNtuple.h" #endif #ifndef HEPOBJ_H #include "HepTuple/HepObj.h" #endif #ifndef HEPDIR_H #include "HepTuple/HepDir.h" #endif // for sprintf, remove, mkstemp, rename and close #include #include #include #include #include #include #ifdef WIN32 #include "io.h" #endif #ifdef __KCC extern "C" { int mkstemp( char* ); } #endif // for setting the size of the zebra store #include "HepTuple/hbook/pawsize.h" ZM_BEGIN_NAMESPACE( zmht ) /* namespace zmht { */ #define NOTYET(fctnName) \ ZMthrow(ZMxHepNotYet( \ "Warning: this manager class does not yet fully support the " \ #fctnName " call; some results may be anomalous.")); bool HepHBookFileManager::init_done = false; // HepHBook initialized? int HepHBookFileManager::lun_ = 10; // dummy lun as placeholder static const long lqpaw =(long)LQPAW; static const int HBookDefaultRecordLength = 1024; // HBook manual p.166 says 8, but internally uses this number: static const int ROOTDIRNAMELENGTH = 16; // is this an absolute path name? static bool isAbsHBookPath( const string & fileName ) { return (fileName.length() >=2) && (fileName[0] == '/') && (fileName[1] == '/'); } // is this a relative path name? static bool isRelHBookPath( const string & fileName ) { return ! isAbsHBookPath( fileName ); } // get this file's simple name static string HBookBaseName( const string & fileName ) { return string( fileName, fileName.rfind( '/' ) + 1 #ifdef WIN32 , string::npos #endif ); } #ifdef NEVER // get this file's directory path static string HBookDirName( const string & fileName ) { return string( fileName, 0, fileName.rfind( '/' ) ); } #endif // is this a memory-resident version of a file name? static bool isHBookMemVersion( const string & fileName ) { return ( 0 == fileName.find( "//PAWC" ) ); } // is this a file version of a file name? static bool isHBookFileVersion( const string & fileName ) { return ! isHBookMemVersion( fileName ); } // where are we now within the current tree? static const char* HBookPwd() { static char reply[256]; reply[0] = '\0'; // avoid purify warning; reply[255] = '\0'; // avoid running off into hyperspace char* chopt = "R"; HCDIR( reply, chopt ); for ( char * p = reply+254; (p > reply) && (*p == ' '); --p ) *p = '\0'; return reply; } // ensure that a path name is all upcase & enforce length requirements on root static string validHBookPath( const string & pathName, const HepFileManager* man ) { string s = pathName; std::string::size_type start, end, i; // enforce HBook's upper-case requirement for ( i = 0 ; i < s.length() ; ++i ) s[i] = toupper( s[i] ); if ( isAbsHBookPath( s ) ) { if ( s == "//" ) // Modified 19 July 2001 JMM // s = "\\"; s += man->rootDir(); // enforce HBook req's on root directory name start = 2; } else { start = 0; } end = s.find( '/' , start ); if ( end == string::npos ) end = s.length(); while ( start < s.length() ) { if ( end > start+ROOTDIRNAMELENGTH ) { // is root name part too long? // yes, truncate that part s.replace( start+ROOTDIRNAMELENGTH, end-1, string("") ); end = start + ROOTDIRNAMELENGTH + 1; } start = end + 1; end = s.find( '/', start ); if ( end == string::npos ) end = s.length(); } return s; } // navigate within the HBook directory tree static void HBookChdir( const string & moveTo ) { HEP_DEBUG( " HBookChdir( \"" << moveTo << "\" )" ); char* chopt = " "; HCDIR( ((char*)moveTo.c_str()), chopt ); } // create a new directory in the HBook directory tree static inline void HBookMkdir( const string & newDir ) { HEP_DEBUG( " HBookMkdir( \"" << newDir << "\" )" ); char* chopt = " "; HMDIR( ((char*)newDir.c_str()), chopt ); } // remove a directory in the HBook directory tree static inline void HBookRmdir( const string & goner ) { HEP_DEBUG( " HBookRmdir( \"" << goner << "\" )" ); HDDIR( ((char*)goner.c_str()) ); } // make memory-resident version of file name static string HBookMemVersion( const string& path ) { if ( isHBookFileVersion( path ) ) { string mem = path; if ( isRelHBookPath ( path ) ) { mem.insert(0, HBookPwd()).insert( 0, "//PAWC/" ); } else { mem.insert( 2, "PAWC/" ); } return mem; } else { return path; } } // make file version of file name static string HBookFileVersion( string fileName ) { return isHBookMemVersion( fileName ) ? fileName.replace( 2, strlen( "PAWC/" ), string("") ) : fileName; } // Eventually push/pop a new hbook directory // Only ONE level deep! // path HAVE TO BE absolute !!! static string pushed_from = ""; static bool pushed = false; static bool destructor = false; void HBookPushd( const string & moveTo ) { if ( destructor ) { HBookChdir( HBookMemVersion( moveTo ) ); HBookChdir( HBookFileVersion( moveTo ) ); return; } pushed_from = HBookPwd(); if ( !( pushed_from == moveTo) ) { pushed = true; HBookChdir( HBookMemVersion( moveTo ) ); HBookChdir( HBookFileVersion( moveTo ) ); } else { pushed = false; } } void HBookPopd() { if ( pushed ) { HBookChdir( HBookMemVersion( pushed_from ) ); HBookChdir( HBookFileVersion( pushed_from ) ); pushed = false; } } // close an HBook file static void HBookClose( string fileName ) { HEP_DEBUG( " HBookClose( \"" << fileName << "\" )" ); HRENDC ( ((char*)fileName.c_str()) ); } // upcase the whole string, enforcing HBook's length requirement const string HBookRootDir( const string & S ) { string rootDir = HBookBaseName( S ); if ( rootDir.length() > (std::string::size_type)ROOTDIRNAMELENGTH ) rootDir.replace( ROOTDIRNAMELENGTH, rootDir.length(), string("") ); for ( std::string::size_type i = 0; i < rootDir.length(); ++i ) rootDir[i] = toupper( rootDir[i] ); return rootDir; } static void checkModeSanity( HepFileManager::mode_ & req_mode ) { // Check the validity of the requested file open mode. For the moment, // we only consider modes that are either single members of the mode_ // enum or two members of that enum or'ed together. // Default mode. That's clearly sane. if(req_mode == 0 ) return; // First look at the case of a single req_mode request. // By definition, these are sane. if((req_mode | HepFileManager::HEP_READONLY) == HepFileManager::HEP_READONLY) return; if((req_mode | HepFileManager::HEP_UPDATE ) == HepFileManager::HEP_UPDATE ) return; if((req_mode | HepFileManager::HEP_REFRESH ) == HepFileManager::HEP_REFRESH ) return; if((req_mode | HepFileManager::HEP_REMOVE ) == HepFileManager::HEP_REMOVE ) return; if((req_mode | HepFileManager::HEP_RENAME ) == HepFileManager::HEP_RENAME ) return; // count how many modes are turned on int numBits = 0; int mode = req_mode; while( mode != 0 ) { if( mode & 1 ) ++numBits; mode = (mode >> 1); } if( numBits == 2 ) { // READONLY may not be or'ed with anything else. if((req_mode & HepFileManager::HEP_READONLY) != 0 ) { ZMthrow(ZMxHepIncompatible( string("HEP_READONLY may not be combined with any other mode") +string("\n Resetting mode to HEP_READONLY"))); req_mode = HepFileManager::HEP_READONLY; return; } // REFRESH may be or'ed with anything except READONLY // The READONLY test above has already caught this // REMOVE may be or'ed with REFRESH only if((req_mode & HepFileManager::HEP_REMOVE) != 0 ) { if(req_mode == (HepFileManager::HEP_REMOVE | HepFileManager::HEP_REFRESH)) { return; } else { ZMthrow(ZMxHepIncompatible( string("HEP_REMOVE may only be combined with HEP_REFRESH") +string("\n Resetting mode to HEP_REMOVE only"))); req_mode = HepFileManager::HEP_REMOVE; return; } } // RENAME may be or'ed with REFRESH only if((req_mode & HepFileManager::HEP_RENAME) != 0 ) { if(req_mode == (HepFileManager::HEP_RENAME | HepFileManager::HEP_REFRESH)) { return; } else { ZMthrow(ZMxHepIncompatible( string("HEP_RENAME may only be combined with HEP_REFRESH") +string("\n Resetting mode to HEP_RENAME only"))); req_mode = HepFileManager::HEP_RENAME; return; } } // UPDATE may be or'ed with REFRESH and nothing else if((req_mode & HepFileManager::HEP_UPDATE) != 0 ) { if(req_mode == (HepFileManager::HEP_UPDATE | HepFileManager::HEP_REFRESH)) { return; } else { ZMthrow(ZMxHepIncompatible( string("HEP_UPDATE may only be combined with HEP_REFRESH") +string("\n Resetting mode to HEP_REFRESH only"))); req_mode = HepFileManager::HEP_REFRESH; return; } } return; } else { ZMthrow(ZMxHepUnsupported( string("File open modes may only be OR'ed in pairs"))); return; } } void HepHBookFileManager::init( const string& fName, // desired file name HepFileManager::mode req_mode, // desired opening mode const string& rootDirName, // desired name of root directory const string& gSect, // 4-character global section name (default 0) int record_length // HBook record length(for new file) ) { // First of all, check that the req_mode is sensible checkModeSanity( req_mode ); // one-time class initialization if ( ! init_done ) { int slen = gSect.length(); int lpaw = lqpaw; if ( slen > 0 && slen < 5 ) HLIMAP( lpaw, ((char*)gSect.c_str()) ); else HBFINIT(); // in lieu of hlimit_( & lpaw ); init_done = true; } // Kral 7/25/95 - Change limit of 8000 records to 32000 records with // the ZEBRA common block variable IQUEST(10). // JMM 5/18/00 - Change limit to 65000 records, the structural limit // for Hbook/Zebra long flen = 65000; HBFLEN( flen ); // check status of this file: if exists, then open it & read its contents; // if non-existent, create it afresh: int rc = 0; if ( fileName() == "PAWC" ) return; // special file name; nothing to do (above initialization only) filemode mode = checkFile ( fName ); bool fileExists = ( mode != HEP_ABSENT ); string action; if ( ((req_mode & HEP_READONLY) !=0 ) && (mode == HEP_ALL) ) { mode = HEP_READ; } if( fileExists && ( (req_mode & HEP_REMOVE) != 0 ) ) { int rc = remove( fName.c_str() ); if( rc != 0 ) { char tmp[20]; sprintf(tmp,"%d",errno); ZMthrow(ZMxHepCantDeleteFile( string("In HepHBookFileManager: Cannot delete file ") +string( "\"" ) +fName +string( "\"\n") +string(" RC = ") +string( tmp ))); } fileExists = false; mode = checkFile ( fName ); } if( fileExists && ( (req_mode & HEP_RENAME) != 0 ) ) { string tempName = fName + string("XXXXXX"); char * temp = new char[1024]; strcpy( temp, tempName.c_str() ); int fd = mkstemp( temp ); if( fd == -1 ) ZMthrow(ZMxHepCantGenerateName( string("In HepHBookFileManager: Cannot generate new file name "))); int rc = rename( fName.c_str(), temp ); if( rc != 0 ) { char tmp[20]; sprintf(tmp,"%d",errno); ZMthrow(ZMxHepCantRenameFile( string("In HepHBookFileManager: Cannot rename file ") +string( "\"" ) +fName +string( "\"\n") +string(" RC = ") +string( tmp ))); } delete [] temp; close( fd ); fileExists = false; mode = checkFile ( fName ); } if ( fileExists ) { if ( mode == HEP_ALL ) { HEP_DEBUG( " Opening \"" << fName << "\" with root \"" << rootDir() << "\"" ); int reclen = 0; char* chopt = "XPCU"; HROPEN( lun_, ((char*)rootDir().c_str()), ((char*)fName.c_str()), chopt, reclen, rc ); action = "update"; } else if ( mode == HEP_READ ) { HEP_DEBUG( " Opening Read-Only \"" << fName << "\" with root \"" << rootDir() << "\"" ); int reclen = 0; char* chopt = "XPC"; HROPEN( lun_, ((char*)rootDir().c_str()), ((char*)fName.c_str()), chopt, reclen, rc ); action = "read"; setReadOnly ( true ); } else { // mode == HEP_NONE or mode == HEP_WRITE ZMthrow(ZMxHepCantOpenFile(string("in HepHBookFileManager: can't ") +string( "open" ) +string( "\"" ) +fName +string( "\"\n") )); setReadOnly ( true ); return; } } else { // file needs to be created: HEP_DEBUG( " Creating \"" << fName << "\" with root \"" << rootDir() << "\"" ); int reclen = record_length; char* chopt = "XPCNQ"; HROPEN( lun_, ((char*)rootDir().c_str()), ((char*)fName.c_str()), chopt, reclen, rc ); } lun_++; /* insure almost uniqueness of lun_ */ if ( rc != 0 ) { // oops, got a problem! char tmp[20]; sprintf(tmp,"%d",rc); ZMthrow(ZMxHepCantOpenFile(string("in HepHBookFileManager: can't ") +string( fileExists ? "open" : "create" ) +string( "\"" ) +fName +string( "\"\n") +string(" RC = ") +string( tmp ))); setReadOnly ( true ); return; } string memDir = HBookMemVersion( "//" + rootDir() ); HBookMkdir( memDir ); //HEP_DEBUG( " now have \"" << HBookPwd() << "\" and \"" << memDir << "\"" ); cd( "//"+rootDir() ); // position ourselves to root directory (both of 'em!) if ( fileExists ) retrieveExistingItems(); // create file's structure in memory } HepHBookFileManager::HepHBookFileManager(// constructor const string& fName, // desired file name HepFileManager::mode req_mode, // desired opening mode const string& rootDirName, // desired name of root directory const string& gSect // 4-character global section name (default 0) ) : HepFileManager( fName, HBookRootDir(rootDirName.length()!=0? rootDirName:fName) ) , isOpen( true ) { HEP_DEBUG( "HepHBookFileManager::constructor( \"" << fName << "\" )" ); init ( fName, req_mode, rootDirName, gSect, HBookDefaultRecordLength ); } HepHBookFileManager::HepHBookFileManager(// constructor const string& fName, // desired file name const string& rootDirName, // desired name of root directory const string& gSect // 4-character global section name (default 0) ) : HepFileManager( fName, HBookRootDir(rootDirName.length()!=0? rootDirName:fName) ) , isOpen( true ) { HEP_DEBUG( "HepHBookFileManager::constructor( \"" << fName << "\" )" ); init ( fName, HEP_UPDATE, rootDirName, gSect, HBookDefaultRecordLength ); } // HepHBookFileManager::HepHBookFileManager() HepHBookFileManager::HepHBookFileManager(// constructor const string& fName, // desired file name HepFileManager::mode req_mode, // desired opening mode const int record_length, // desired HBOOK record length // (for new file only). const string& rootDirName, // desired name of root directory const string& gSect // 4-character global section name // (default 0) ) : HepFileManager( fName, HBookRootDir(rootDirName.length()!=0? rootDirName:fName) ) , isOpen( true ) { HEP_DEBUG( "HepHBookFileManager::constructor( \"" << fName << "\" )" ); init ( fName, req_mode, rootDirName, gSect, record_length ); } // HepHBookFileManager::HepHBookFileManager() HepHBookFileManager::HepHBookFileManager(// constructor const string& fName, // desired file name const int record_length, // desired HBOOK record length // (for new file only). const string& rootDirName, // desired name of root directory const string& gSect // 4-character global section name (default 0) ) : HepFileManager( fName, HBookRootDir(rootDirName.length()!=0? rootDirName:fName) ) , isOpen( true ) { HEP_DEBUG( "HepHBookFileManager::constructor( \"" << fName << "\" )" ); init ( fName, HEP_UPDATE, rootDirName, gSect, record_length ); } // HepHBookFileManager::HepHBookFileManager() HepHBookFileManager::~HepHBookFileManager() { // destructor HEP_DEBUG( "HepHBookFileManager::destructor()" ); destructor = true; write(); if ( isOpen ) { HBookClose( rootDir() ); HBookChdir( "//PAWC" ); HBookRmdir( HBookMemVersion( "//" + rootDir() ) ); } destructor = false; } // HepHBookFileManager::~HepHBookFileManager() void HepHBookFileManager::cd( const string & path ) { // change dir HEP_DEBUG( "HepHBookFileManager::cd( \"" << path << "\" )" ); // For this function ONLY we assume that the hbook current directory // is really the same as pwd(). If other function want to // inforce this they can do cd(pwd()) // If not path is given, we go the rootdir. if ( path.length() == 0 ) { cd( "//" + rootDir() ); } else { string moveTo = validHBookPath(path, this); // The path could be an old fashion HBook path :( // let's be backward compatible and replace // "\\" by ".." int cursor = moveTo.find("\\",0); while ( cursor != -1 ) { moveTo.replace( cursor, 2, ".."); cursor = moveTo.find("\\",cursor); } HepFileManager::cd( moveTo ); // Get the hbook full path name moveTo = validHBookPath( pwd(), this ); // Now mirror the changes in memory and on disk, and we're done! HBookChdir( HBookMemVersion( moveTo ) ); HBookChdir( HBookFileVersion( moveTo ) ); } //HEP_DEBUG( " now in \"" << HBookPwd() << "\" == \"" << pwd() << "\"" ); } // HepHBookFileManager::cd() void HepHBookFileManager::mkdir( const string & path ) { // create a dir HEP_DEBUG( "HepHBookFileManager::mkdir( \"" << path << "\" )" ); if ( isReadOnly() ) { ZMthrow(ZMxHepCantWriteFile( fileName() + " is read only. Can not make directory " + path + "." )); return; } string newDir = validHBookPath( path, this ); if (newDir.length() == 0 ) return; // Go to where this manager think it should be HBookPushd(pwd()); // Make the requested directory, and go there HBookMkdir( newDir ); HBookChdir( newDir ); HepFileManager::mkdir(HBookPwd()); // Now make the mirror of the directory if ( isHBookFileVersion( newDir = HBookPwd() ) ) HBookMkdir( HBookMemVersion( newDir ) ); else HBookMkdir( HBookFileVersion( newDir ) ); HEP_DEBUG( " created \"" << HBookMemVersion( newDir ) << "\" and \"" << HBookFileVersion( newDir ) << "\"" ); HBookPopd(); // back to our starting point //(void)nextID( 0 ); // assigns unique IDs to directory entries } // HepHBookFileManager::mkdir() HepFileManager::ItemList HepHBookFileManager::list( // make an itemlist const string & path , const string & chopt ) const { string p = validHBookPath(path, this ); return HepFileManager::list(p,chopt); } string HepHBookFileManager::ls( // list a dir const string & path , const string & chopt ) const { string p = validHBookPath(path, this); return HepFileManager::ls(p,chopt); #if 0 // NOTE: The following code is deprecated because the HepFileManager // is now smart enough to do recursive listing. string p = validHBookPath( (path == "") ? pwd() : string(path), this ); // Go to where this manager think it should be (for relative path!) HBookPushd(pwd()); HBookChdir(p); string result = hbook_ls(HBookPwd(),chopt); HBookPopd(); // back to our starting point return result; #endif } string HepHBookFileManager::hbook_ls( // list a dir const string & path , const string & chopt ) const { // Assume that path is passed correctly (by ::ls) // and that the internal hbook current directory is properly set. string res = HepFileManager::ls( path, chopt ); // See if the user wants recursive ls bool recursive = ((int)chopt.find("r") != -1); int id( 0 ); // req'd initial value to start scanning int oid = 0; char rtype[2]; // type of histogram located rtype[0] = ' '; rtype[1] = '\0'; const int maxTitleLen = 80; char rtitle[maxTitleLen+1]; // title of the histogram/directory // Prefill rtitle to keep Purify happy for (int i=0; iid(); // Put this seems to actually try to delete the object twice :( // HBookChdir( HBookMemVersion ( (*i)->dir() ) ); // HDELET( id ); HBookChdir( HBookFileVersion( (*i)->dir() ) ); HDELET( id ); int id_all = 0; char* chopt = " "; HSCR( id, id_all, chopt ); HBookPopd(); HepFileManager::rm( title ); } void HepHBookFileManager::writeDirectory() { // write the managed objects to the file HEP_DEBUG( "HepHBookFileManager::writeDirectory()" ); if ( isOpen ) HepFileManager::writeDirectory(); } // HepHBookFileManager::writeDirectory() int HepHBookFileManager::write() { // write the managed objects to the file HEP_DEBUG( "HepHBookFileManager::write()" ); // NOTE: Have to find a better way to really flush the // column wise ntuple :( // if ( ! isOpen ) // return 1; int result = HepFileManager::write(); // HBookClose( rootDir() ); // HBookChdir( "//PAWC" ); // HBookRmdir( HBookMemVersion( "//" + rootDir() ) ); // isOpen = false; return result; } // HepHBookFileManager::write() void HepHBookFileManager::writeOne( HepObj * o ) { int id = o->id(); HEP_DEBUG( "HepHBookFileManager::writeOne( " << id << " )" ); HBookPushd( o->dir() ); //HEP_DEBUG( " \"" << o->dir() << "\" == \"" << HBookPwd() // << "\" == \"" << pwd() << "\"" ); //std::cerr << " \"" << o->dir() << "\" == \"" << HBookPwd() // << "\" == \"" << pwd() << "\"" << endl; int cycle; char* chopt = " "; HROUT( id, cycle, chopt ); HepFileManager::writeOne( o ); HBookPopd(); } // HepHBookFileManager::writeOne() #ifdef LATER void HepHBookFileManager::dumpAllData() { // call dumpData() for all listed tuples HepAListIterator i( ntuples_ ); HepHBookTuple *p; while ( p = i() ) p->dumpData(); } // HepHBookFileManager::dumpAllData() void HepHBookFileManager::clearAllData() { // call clearData() for all listed tuples HepAListIterator i( ntuples_ ); HepHBookTuple *p; while ( p = i() ) p->clearData(); } // HepHBookFileManager::clearAllData() #endif // LATER // Create HepHBook-specific histograms: -------------------------------- // Using title as a key, find the plot with the given title. If it is // not found, create a new plot with the given title, and return that. // The HepHBook ID of the plot is optionally specified by the user. HepHist1D & HepHBookFileManager::hist1D( const string& title , const int nBins, const float low, const float high , const int id ) { if ( isReadOnly() ) { ZMthrow(ZMxHepCantMakeHist( fileName() + " is read-only; " + title + " can not be created." )); return deadHist1D(); } if ( findObj( title ) == objList_.end() && findObj( id ) == objList_.end() ) { HepHBookHist1D * h = new HepHBookHist1D( this, title, nBins, low, high, id ); isInUse( h, true ); isDirty( h, true ); // make the Fortran object float temp_vmx = 0.0; int ID = h->id(); HBookPushd( pwd() ); HBOOK1( ID, ((char*)title.c_str()), nBins, low, high, temp_vmx ); isCreated( h, true ); HBookPopd(); return *h; } else { ZMthrow(ZMxHepCantMakeHist( "Can not create a hist1D with an existing name or id")); return deadHist1D(); } } HepHist2D & HepHBookFileManager::hist2D( const string& title , const int nBinsX, const float lowX, const float highX , const int nBinsY, const float lowY, const float highY , const int id ) { if ( isReadOnly() ) { ZMthrow(ZMxHepCantMakeHist( fileName() + " is read-only; " + title + " can not be created." )); return deadHist2D(); } if ( findObj( title ) == objList_.end() && findObj( id ) == objList_.end() ) { HepHBookHist2D * h = new HepHBookHist2D( this, title, nBinsX, lowX, highX, nBinsY, lowY, highY, id ); isInUse( h, true ); isDirty( h, true ); // make the Fortran object float temp_vmx = 0.0; int ID = h->id(); HBookPushd( pwd() ); HBOOK2( ID, ((char*)title.c_str()), nBinsX, lowX, highX, nBinsY, lowY, highY, temp_vmx ); HBookPopd(); isCreated( h, true ); return *h; } else { ZMthrow(ZMxHepCantMakeHist( "Can not create a hist2D with an existing name or id")); return deadHist2D(); } } HepHistProf & HepHBookFileManager::histProf( const string& title , const int nBinsX, const float lowX, const float highX , const float lowY, const float highY , const string& chopt , const int id ) { if ( isReadOnly() ) { ZMthrow(ZMxHepCantMakeHist( fileName() + " is read-only; " + title + " can not be created." )); return deadHistProf(); } if ( findObj( title ) == objList_.end() && findObj( id ) == objList_.end() ) { HepHBookHistProf * h = new HepHBookHistProf( this, title, nBinsX, lowX, highX, lowY, highY, chopt, id ); isInUse( h, true ); isDirty( h, true ); // make the Fortran object int ID = h->id(); HBookPushd( pwd() ); HBPROF( ID, ((char*)title.c_str()), nBinsX, lowX, highX, lowY, highY, ((char*)chopt.c_str()) ); HBookPopd(); isCreated( h, true ); return *h; } else { ZMthrow(ZMxHepCantMakeHist( "Can not create a histProf with an existing name or id")); return deadHistProf(); } } HepHistProf & HepHBookFileManager::histProf( const string& title , const int nBinsX, const float lowX, const float highX , const float lowY, const float highY , const int id ) { return histProf( title, nBinsX, lowX, highX, lowY, highY, " ", id ); } // attach to existing histograms: ------------------------------------ HepHist1D & HepHBookFileManager::retrieveHist1D( // 1-D const string& title, const int hid ) { HepHist1D & h = HepFileManager::retrieveHist1D( title, hid ); isInUse( &h, true ); int id = h.id(); int latestVersion = 99999; int offset = 0; HBookPushd( pwd() ); HRIN( id, latestVersion, offset ); // grab this histogram's contents HBookPopd(); return h; } HepHist2D & HepHBookFileManager::retrieveHist2D( // 2-D const string& title, const int hid ) { HepHist2D & h = HepFileManager::retrieveHist2D( title, hid ); isInUse( &h, true ); int id = h.id(); int latestVersion = 99999; int offset = 0; HBookPushd( pwd() ); HRIN( id, latestVersion, offset ); // grab this histogram's contents HBookPopd(); return h; } HepHistProf & HepHBookFileManager::retrieveHistProf( // profile plot const string& title, const int hid ) { HepHistProf & h = HepFileManager::retrieveHistProf( title, hid ); isInUse( &h, true ); int id = h.id(); int latestVersion = 99999; int offset = 0; HBookPushd( pwd() ); HRIN( id, latestVersion, offset ); // grab this histogram's contents HBookPopd(); return h; } // Create HepNtuple HepNtuple & HepHBookFileManager::ntuple( // ntuple const string& title, const int id ) { HEP_DEBUG( "HepHBookFileManager::ntuple( \"" << title << "\", " << id << " )" ); if ( isReadOnly() ) { ZMthrow(ZMxHepCantMakeNtuple( fileName() + " is read-only; " + title + " can not be created." )); return deadNtuple(); } if ( findObj( title ) == objList_.end() && findObj( id ) == objList_.end() ) { HepNtuple * t = new HepHBookNtuple( this, title, id ); isInUse( t, true ); isDirty( t, true ); return *t; } else { ZMthrow(ZMxHepCantMakeNtuple( "Can not create an Ntuple with an existing name or id")); return deadNtuple(); } } HepNtuple & HepHBookFileManager::retrieveNtuple( // Ntuple const string& title, const int hid ) { HepNtuple & h = HepFileManager::retrieveNtuple( title, hid ); isInUse( &h, true ); int id = h.id(); int latestVersion = 99999; int offset = 0; HBookPushd( pwd() ); HRIN( id, latestVersion, offset ); // grab this histogram's contents HBookPopd(); return h; } // user is finished with the indicated object void HepHBookFileManager::release( HepObj & o ) { HEP_DEBUG( "HepHBookFileManager::release()" ); HepFileManager::release( o ); } // traverse the directories in the file to create C++ objects for existing // histograms & ntuples: void HepHBookFileManager::retrieveExistingItems() { HEP_DEBUG( "HepHBookFileManager::retrieveExistingItems()" ); // make a list for the subdirectories STL_DEQUE(string) dirs; // variables for call to HLNXTF int id( 0 ); // req'd initial value to start scanning char rtype[2]; // type of histogram located rtype[0] = ' '; rtype[1] = '\0'; const int maxTitleLen = 80; char rtitle[maxTitleLen+1]; // title of the histogram/directory string newdir; // Prefill rtitle to keep Purify happy for (int i=0; i rtitle) && (*p == ' '); --p ) *p = '\0'; // create a C++ handler by constructing a HepHBookHist switch ( rtype[0] ) { case 'D': // directory dirs.push_back( rtitle ); newdir = ( HBookPwd() ); newdir.append("/").append( rtitle ); HBookMkdir( HBookMemVersion( newdir ) ); break; case '1': // 1D hist HKIND( id, kind, kindOpts ); // distinguish 1D and profile hist's if ( kind[0] == 1 ) { h = new HepHBookHist1D( this, rtitle, nx, xmi, xma, id ); } else if ( kind[0] == 8 ) h = new HepHBookHistProf( this, rtitle, nx, xmi, xma, ymi, yma, id ); else { char temp[16]; sprintf(temp,"%d",kind[0]); ZMthrow(ZMxHepUnknownType( string("retrieveExistingItems: unknown item kind (") +string(temp)+string(")"))); } isDirty( h, false ); isCreated( h, true ); break; case '2': // 2D hist h = new HepHBookHist2D( this, rtitle, nx, xmi, xma, ny, ymi, yma, id ); isDirty( h, false ); isCreated( h, true ); break; case 'N': // ntuple // Create an ntuple object with the correct title and id ... th = new HepHBookNtuple( this, rtitle, id ); // and restore a lot of dirty details about it's internal structure. if( ! th->restoreNtuple() ) { ZMthrow(ZMxHepCantMakeNtuple(string("Failed to restore Ntuple with title")+ rtitle)); } break; default: // shouldn't happen ZMthrow(ZMxHepUnknownType( string("HepHBookFileManager: unknown item type (") +string(" in \"")+fileName()+string("\")"))); break; } // switch // Remove the Histogram data from ZEBRA memory (it can be recovered // from file later. if ( rtype[0] == '1' || rtype[0] == '2' ) HDELET( id ); } // while // call this function for each subdirectory in the list while ( ! dirs.empty() ) { string cwd( pwd() ); // remember current directory mkdir_( dirs.front() ); // create the internal representation cd( dirs.front() ); // change to given directory retrieveExistingItems(); // handle histograms & ntuples there dirs.pop_front(); // free up list resource cd( cwd ); // back to remembered directory } } // HepHBookFileManager::retrieveExistingItems() HepTupleFileFormat HepHBookFileManager::hepFileFormat() const { return HEPTUPLE_HBOOK; } bool HepHBookFileManager::switchFile( const string& newFileName, const bool resetHists ) { // We don't do file switching for the HBook manager but we can at least // write out the old file and exit cleanly. write(); ZMthrow(ZMxHepUnsupported(string("File switching is not supported for this manager"))); return false; } bool HepHBookFileManager::switchFile( const string& newFileName, const bool resetHists, HepFileSwitch& userHandler ) { // We don't do file switching for the HBook manager but we can at least // write out the old file and exit cleanly. write(); ZMthrow(ZMxHepUnsupported(string("File switching is not supported for this manager"))); return false; } // ************************************ // // ******* Dead Object creators ******* // // ************************************ // HepNtuple& HepHBookFileManager::deadNtuple() const { return HepHBookFileManager::deadHBookNtuple(); } HepHist1D& HepHBookFileManager::deadHist1D() const { return HepHBookFileManager::deadHBookHist1D(); } HepHist2D& HepHBookFileManager::deadHist2D() const { return HepHBookFileManager::deadHBookHist2D(); } HepHistProf& HepHBookFileManager::deadHistProf() const { return HepHBookFileManager::deadHBookHistProf(); } HepHBookNtuple& HepHBookFileManager::deadHBookNtuple() { static HepHBookNtuple deadHBook; return deadHBook; } HepHBookHist1D& HepHBookFileManager::deadHBookHist1D() { static HepHBookHist1D deadHBook; return deadHBook; } HepHBookHist2D& HepHBookFileManager::deadHBookHist2D() { static HepHBookHist2D deadHBook; return deadHBook; } HepHBookHistProf& HepHBookFileManager::deadHBookHistProf() { static HepHBookHistProf deadHBook; return deadHBook; } void HepHBookFileManager::silenceCompiler() { pretendToUse(&(__cf__HEXIST)); pretendToUse(&(__cf__HSUM)); pretendToUse(&(__cf__HI)); pretendToUse(&(__cf__HIE)); pretendToUse(&(__cf__HIF)); pretendToUse(&(__cf__HIJ)); pretendToUse(&(__cf__HIJE)); pretendToUse(&(__cf__HMIN)); pretendToUse(&(__cf__HMAX)); pretendToUse(&(__cf__HRNDM1)); pretendToUse(&(__cf__HSPFUN)); pretendToUse(&(__cf__HLNXTF)); pretendToUse(&(__cf__HSTATI)); pretendToUse(&(__cf__HX)); pretendToUse(&(__cf__HXE)); pretendToUse(&(__cf__HXY)); pretendToUse(&(__cf__ISCWN)); pretendToUse(&c2fstrv); pretendToUse(&f2cstrv); pretendToUse(&vkill_trailing); pretendToUse(&num_elem); } ZM_END_NAMESPACE( zmht ) /* } // namespace zmht */