// HbookFile.cxx #include "dataset_CBNT/HbookFile.h" #include #include #include #include "dataset_util/FileStatus.h" #include "dataset_util/Text.h" using std::cout; using std::endl; using std::string; using std::ostringstream; using std::deque; using std::ostream; //********************************************************************** // Helpers. //********************************************************************** namespace { // Execute a system command. int ssystem(string com) { return system(com.c_str()); } typedef std::deque LunList; // List of LUN's that have been assigned. LunList& used_luns() { static LunList luns; return luns; } // List of LUN's available for assignment. LunList& available_luns() { static LunList luns; if ( used_luns().size() == 0 && luns.size() == 0 ) { for ( int i=30; i<80; ++i ) { luns.push_back(i); } } return luns; } // Assign a LUN. // Zero for error. int get_lun() { if ( available_luns().size() == 0 ) return 0; int lun = available_luns().front(); available_luns().pop_front(); used_luns().push_back(lun); return lun; } // Release a LUN and then zeroes it. // Returns nonzero for error. // For now, do not remove from the used LUN list. int release_lun(int& lun) { if ( lun == 0 ) return 1; if ( find(available_luns().begin(), available_luns().end(), lun) != available_luns().end() ) return 2; if ( find(used_luns().begin(), used_luns().end(), lun) == used_luns().end() ) { cout << "Error in HbookFile release_lun(" << lun << "):" << endl; cout << "Used LUN's:" << endl; for ( LunList::const_iterator ilun=used_luns().begin(); ilun!=used_luns().end(); ++ilun ) { cout << *ilun << endl; } assert(false); return 3; } available_luns().push_back(lun); lun = 0; return 0; } } // end unnamed namespace //********************************************************************** // Fortran declarations. extern "C" { // Initialize HBOOK (and zebra and paw). int pawin_(); // Open an hbook file. void hropen_(int*, const char*, const char*, const char*, int*, int*, int, int, int); // Close a file. void fclose_(const int* lun); // List directory. void hldir_(const char* path, const char* opt, int lpath, int lopt); // Change directory. void hcdir_(const char* path, const char* opt, int lpath, int lopt); // Read into memory. void hrin_(int* id, int* cycle, int* offset); // Write code skeleton for event processing. void evcode_(const int* id); } //********************************************************************** // Member functions. //********************************************************************** // Constructor. HbookFile::HbookFile(string fname) : m_fname(fname), m_lun(0), m_state(INVALID) { if ( fname.size() ) { if ( FileStatus(fname).is_readable() ) { m_state = CLOSED; return; } } m_fname = ""; } //********************************************************************** // Destructor. HbookFile::~HbookFile() { if ( ! is_valid() ) return; if ( is_open() ) close(); ssystem("rm -f " + m_pname); assert( ! FileStatus(m_pname).exists() ); release_lun(m_lun); } //********************************************************************** // Open the file. int HbookFile::open(OpenStatus ostat) { bool read = ostat == READ; bool write = ostat == WRITE; bool forpaw = ostat == FORPAW; if ( !read && !write && !forpaw ) return 100; if ( ! is_valid() ) return 101; if ( is_open() ) return 102; // Initialize PAW. static int hlim = pawin_(); if ( hlim <= 0 ) return 103; // Check physical file status. if ( ! FileStatus(m_fname).is_readable() ) return 104; if ( write && ! FileStatus(m_fname).is_writeable() ) return 105; // Assign LUN and local file name for linking.. // Skip any LUN's for which file names already exist. // These may have been created by a parent process. assert( m_lun == 0 ); assert( m_pname.size() == 0 ); for ( int itry=0; itry<10; ++itry ) { m_lun = get_lun(); if ( m_lun == 0 ) return 106; m_pname = "hbookfile" + slun() + ".hbk"; if ( ! FileStatus(m_pname).exists() ) break; release_lun(m_lun); m_pname = ""; } if ( m_lun == 0 ) return 107; m_hbdir = "LUN" + slun(); // Create link. int sstat = ssystem("ln -s " + m_fname + " " + m_pname); if ( sstat != 0 ) return 108; // Check paw file status. if ( ! FileStatus(m_pname).is_readable() ) return 109; if ( write && ! FileStatus(m_pname).is_writeable() ) return 110; // Open file. if ( read || write ) { string opt = "P"; if ( write ) opt += "U"; int lrec = 0; int stat = 0; // Multiple tries becausae of intermittent and not understood // error opening a file for writing. int ntries = 1; if ( write ) ntries = 2; for ( int itry=0; itry 0 ); fclose_(&m_lun); // Release LUN. release_lun(m_lun); m_hbdir = ""; // Delete link. assert( m_pname.size() ); ssystem("rm -f " + m_pname ); m_pname = ""; m_state = CLOSED; return 0; } //********************************************************************** // Validity. bool HbookFile::is_valid() const { if ( state() != INVALID && m_fname.size() ) { return true; } return false; } //********************************************************************** // Is writeable. bool HbookFile::is_writeable() const { if ( ! is_valid() ) return false; return FileStatus(m_fname).is_writeable(); } //********************************************************************** // Is open. bool HbookFile::is_open() const { return m_state==READ || m_state==WRITE || m_state==FORPAW; } //********************************************************************** // Is open for reading. bool HbookFile::is_open_for_reading() const { return m_state==READ || m_state==WRITE; } //********************************************************************** // Is open for writing. bool HbookFile::is_open_for_writing() const { return m_state==WRITE; } //********************************************************************** // Is open for writing. bool HbookFile::is_open_for_paw() const { return m_state==FORPAW; } //********************************************************************** // Return LUN as a string. string HbookFile::slun() const { if ( m_lun == 0 ) return ""; ostringstream slun; slun.width(2); slun.fill('0'); slun << m_lun; return slun.str(); } //********************************************************************** // PAW command to open the file. string HbookFile::paw_open_command(bool write) const { if ( ! is_open_for_paw() ) return ""; string com = "hi/file " + slun() + " " + hbook_filename(); if ( write ) { com += " CHOPT=U"; } return com; } //********************************************************************** // PAW command to close the file. string HbookFile::paw_close_command() const { if ( ! is_open_for_paw() ) return ""; string com = "close " + slun(); return com; } //********************************************************************** // List directory contents. void HbookFile::ls(string dir, string opt) const { if ( ! is_open_for_reading() ) { cout << "Closed file cannot be listed" << endl; return; } cout << "Listing of " << hbook_filename() << ":" << endl; hldir_(dir.c_str(), opt.c_str(), dir.size(), opt.size()); } //********************************************************************** // Change directory. int HbookFile::cd(string dir, string opt) const { if ( ! is_open_for_reading() ) return 1; hcdir_(dir.c_str(), opt.c_str(), dir.size(), opt.size()); return 0; } //********************************************************************** // Read histograms into memory. int HbookFile::hrin(int id, int cycle, int offset) const { if ( ! is_open_for_reading() ) return 1; hrin_(&id, &cycle, &offset); return 0; } //********************************************************************** // Generate ntuple skeleton code. int HbookFile::evcode(int id) { string fname = "evcode.f"; if ( ! is_valid() ) return 1; if ( is_open_for_paw() ) return 2; bool open = is_open(); if ( ! is_open() ) this->open(); if ( ! is_open() ) return 3; if ( id <= 0 ) return 4; if ( hrin() != 0 ) return 5; evcode_(&id); if ( ! open ) close(); if ( ! FileStatus(fname).is_readable() ) return 6; if ( Text(fname).size() == 0 ) return 7; return 0; } //********************************************************************** // Free functions. //********************************************************************** // Output stream. ostream& operator<<(ostream& lhs, const HbookFile& rhs) { if ( ! rhs.is_valid() ) { lhs << "Invalid HbookFile"; return lhs; } lhs << "HBOOK file " << rhs.full_filename(); lhs << "\n is "; if ( rhs.is_open() ) { lhs << "opened "; if ( rhs.is_open_for_writing() ) { lhs << "for writing"; } else { lhs << "readonly"; } lhs << "\n LUN is " << rhs.lun(); lhs << "\n Local file name is " << rhs.hbook_filename(); lhs << "\n HBOOK directory is " << rhs.hbdir(); } else { lhs << "closed"; } return lhs; } //**********************************************************************