Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/wroot/directory is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef tools_wroot_directory
0005 #define tools_wroot_directory
0006 
0007 #include "idir"
0008 
0009 #include "date"
0010 #include "key"
0011 #include "ifile"
0012 #include "date"
0013 #include "buffer"
0014 #include "iobject"
0015 
0016 #include "../strip"
0017 #include "../vmanip"
0018 #include "../forit"
0019 
0020 #include <vector>
0021 #include <list>
0022 
0023 namespace tools {
0024 namespace wroot {
0025 
0026 class directory : public virtual idir {
0027   static uint32 class_version() {return 1;}
0028 public:
0029   static const std::string& s_class() {
0030     static const std::string s_v("tools::wroot::directory");
0031     return s_v;
0032   }
0033 public: //idir
0034   virtual ifile& file() {return m_file;}
0035   virtual seek seek_directory() const {return m_seek_directory;}
0036   virtual void append_object(iobject* a_object) {m_objs.push_back(a_object);} //take ownership of a_object
0037 public:
0038   directory(ifile& a_file)
0039   :m_file(a_file)
0040   ,m_parent(0)
0041   ,m_is_valid(false)
0042   ,m_date_C(0)
0043   ,m_date_M(0)
0044   ,m_nbytes_keys(0)
0045   ,m_nbytes_name(0)
0046   ,m_seek_directory(0)
0047   ,m_seek_parent(0)
0048   ,m_seek_keys(0)
0049   {
0050   }
0051   directory(ifile& a_file,const std::string& a_name,const std::string& a_title)
0052   :m_file(a_file)
0053   ,m_parent(0)
0054   ,m_is_valid(false)
0055   ,m_name(a_name)
0056   ,m_title(a_title)
0057   ,m_nbytes_keys(0)
0058   ,m_nbytes_name(0)
0059   ,m_seek_directory(0)
0060   ,m_seek_parent(0)
0061   ,m_seek_keys(0)
0062   {
0063     m_date_C = get_date();
0064     m_date_M = get_date();
0065 
0066     if(m_name.empty()) {
0067       m_file.out() << "tools::wroot::directory::directory :"
0068                    << " directory name cannot be \"\"."
0069                    << std::endl;
0070       return; //FIXME : throw
0071     }
0072     if(m_name.find('/')!=std::string::npos) {
0073       m_file.out() << "tools::wroot::directory::directory :"
0074                    << " directory name " << sout(m_name)
0075                    << " cannot contain a slash."
0076                    << std::endl;
0077       return; //FIXME : throw
0078     }
0079     if(m_title.empty()) m_title = m_name;
0080     m_is_valid = true;
0081   }
0082   directory(ifile& a_file,
0083             directory* a_parent, //assume a_parent not nul.
0084             const std::string& a_name,
0085             const std::string& a_title)
0086   :m_file(a_file)
0087   ,m_parent(a_parent)
0088   ,m_is_valid(false)
0089   ,m_name(a_name)
0090   ,m_title(a_title)
0091   ,m_nbytes_keys(0)
0092   ,m_nbytes_name(0)
0093   ,m_seek_directory(0)
0094   ,m_seek_parent(0)
0095   ,m_seek_keys(0)
0096   {
0097     m_date_C = get_date();
0098     m_date_M = get_date();
0099 
0100     if(m_name.empty()) {
0101       m_file.out() << "tools::wroot::directory::directory :"
0102                    << " directory name cannot be \"\"."
0103                    << std::endl;
0104       return; //FIXME : throw
0105     }
0106     if(m_name.find('/')!=std::string::npos) {
0107       m_file.out() << "tools::wroot::directory::directory :"
0108                    << " directory name " << sout(m_name)
0109                    << " cannot contain a slash."
0110                    << std::endl;
0111       return; //FIXME : throw
0112     }
0113 
0114     if(m_title.empty()) m_title = m_name;
0115 
0116     if(m_parent->find_key(m_name)) {
0117       m_file.out() << "tools::wroot::directory::directory :"
0118                    << " directory " << sout(m_name) << " exists already."
0119                    << std::endl;
0120       return; //FIXME : throw
0121     }
0122 
0123     m_seek_parent = m_parent->seek_directory();
0124     uint32 nbytes = record_size();
0125 
0126     wroot::key* key = new wroot::key(m_file.out(),m_file,m_parent->seek_directory(),
0127                                      m_name,m_title,"TDirectory",nbytes); // It does a m_file.set_END().
0128     m_nbytes_name = key->key_length();
0129     m_seek_directory = key->seek_key(); //at EOF
0130     if(!m_seek_directory) {
0131       m_file.out() << "tools::wroot::directory::directory :"
0132                    << " bad key."
0133                    << std::endl;
0134       delete key;
0135       return; //FIXME : throw
0136     }
0137    {char* buffer = key->data_buffer();
0138     wbuf wb(m_file.out(),m_file.byte_swap(),key->eob(),buffer);
0139     if(!to_buffer(wb)) {
0140       m_file.out() << "tools::wroot::directory::directory :"
0141                    << " directory name " << sout(m_name)
0142                    << " cannot fill buffer."
0143                    << std::endl;
0144       delete key;
0145       return; //FIXME : throw
0146     }}
0147     uint16 cycle = m_parent->append_key(key);
0148     key->set_cycle(cycle);
0149     if(!key->write_self(m_file)) {
0150       m_file.out() << "tools::wroot::directory::directory :"
0151                    << " key.write_self() failed."
0152                    << std::endl;
0153       return; //FIXME : throw
0154     }
0155     uint32 n;
0156     if(!key->write_file(m_file,n)) {
0157       m_file.out() << "tools::wroot::directory::directory :"
0158                    << " directory name " << sout(m_name)
0159                    << " cannot write key to file."
0160                    << std::endl;
0161       return; //FIXME : throw
0162     }
0163 
0164     m_is_valid = true;
0165   }
0166   virtual ~directory(){
0167     clear_dirs();
0168     clear_objs();
0169     clear_keys();
0170   }
0171 protected:
0172   directory(const directory& a_from)
0173   :idir(a_from)
0174   ,m_file(a_from.m_file)
0175   ,m_parent(0)
0176   ,m_is_valid(false){
0177   }
0178   directory& operator=(const directory &){
0179     m_is_valid = false;
0180     return *this;
0181   }
0182 public:
0183   bool is_valid() const {return m_is_valid;}
0184   void set_seek_directory(seek a_seek) {m_seek_directory = a_seek;}
0185 
0186   directory* mkdir(const std::string& a_name,const std::string& a_title = ""){
0187     // Create a sub-directory and return a pointer to the created directory.
0188     // Note that the directory name cannot contain slashes.
0189     if(a_name.empty()) {
0190       m_file.out() << "tools::wroot::directory::mkdir :"
0191                    << " directory name cannot be \"\"."
0192                    << std::endl;
0193       return 0;
0194     }
0195     if(a_name.find('/')!=std::string::npos) {
0196       m_file.out() << "tools::wroot::directory::mkdir :"
0197                    << " " << sout(a_name)
0198                    << " cannot contain a slash."
0199                    << std::endl;
0200       return 0;
0201     }
0202     directory* dir = new directory(m_file,this,a_name,a_title.empty()?a_name:a_title);
0203     if(!dir->is_valid()) {
0204       m_file.out() << "tools::wroot::directory::mkdir :"
0205                    << " directory badly created."
0206                    << std::endl;
0207       delete dir;
0208       return 0;
0209     }
0210     m_dirs.push_back(dir);
0211     return dir;
0212   }
0213 
0214   //uint32 nbytes_name() const {return m_nbytes_name;}
0215   void set_nbytes_name(uint32 a_n) {m_nbytes_name = a_n;}
0216 
0217   uint32 record_size() const {
0218     uint32 nbytes = sizeof(short);
0219     nbytes += sizeof(date); //m_date_C.record_size();
0220     nbytes += sizeof(date); //m_date_M.record_size();
0221     nbytes += sizeof(m_nbytes_keys);
0222     nbytes += sizeof(m_nbytes_name);
0223     //ROOT version >= 40000:
0224     nbytes += sizeof(seek);
0225     nbytes += sizeof(seek);
0226     nbytes += sizeof(seek);
0227     return nbytes;
0228   }
0229 
0230   bool close() {
0231     if(!save()) return false;
0232     clear_dirs();
0233     clear_objs();
0234     clear_keys();
0235     return true;
0236   }
0237 
0238   bool to_buffer(wbuf& a_wb){
0239     // Decode input buffer.
0240     // (Name, title) are stored in the (name, title) of the associated key.
0241     short version = class_version();
0242     version += big_file_version_tag(); //GB : enforce writing on seek (and not seek32).
0243     if(!a_wb.write(version)) return false;
0244     if(!a_wb.write(m_date_C)) return false;
0245     if(!a_wb.write(m_date_M)) return false;
0246     if(!a_wb.write(m_nbytes_keys)) return false;
0247     if(!a_wb.write(m_nbytes_name)) return false;
0248 
0249     if(!a_wb.write(m_seek_directory)) return false;
0250     if(!a_wb.write(m_seek_parent)) return false;
0251     if(!a_wb.write(m_seek_keys)) return false;
0252 
0253     if(m_file.verbose()) {
0254       m_file.out() << "tools::wroot::key::to_buffer :"
0255           << " nbytes keys : " << m_nbytes_keys
0256           << ", pos keys : " << m_seek_keys
0257           << std::endl;
0258     }
0259     return true;
0260   }
0261 
0262   bool write(uint32& a_nbytes){
0263     // Write all objects in memory to disk.
0264     // Loop on all objects in memory (including subdirectories).
0265     // A new key is created in the m_keys linked list for each object.
0266     // For allowed options see TObject::Write().
0267     // The directory header info is rewritten on the directory header record
0268     a_nbytes = 0;
0269     if(m_file.verbose()) {
0270       m_file.out() << "tools::wroot::directory::write :"
0271                    << " " << sout(m_name)
0272                    << " : " << m_dirs.size()
0273                    << " : " << m_objs.size()
0274                    << " objects."
0275                    << std::endl;
0276     }
0277 
0278     uint32 nbytes = 0;
0279 
0280    {tools_vforcit(directory*,m_dirs,it) {
0281       uint32 n;
0282       if(!(*it)->write(n)) return false;
0283       nbytes += n;
0284     }}
0285 
0286    {tools_vforit(iobject*,m_objs,it) {
0287       uint32 n;
0288       if(!write_object(*(*it),n)) {
0289         m_file.out() << "tools::wroot::directory::write :"
0290                      << " for directory " << sout(m_name)
0291                      << ", write_object " << sout((*it)->name())
0292                      << " failed."
0293                      << std::endl;
0294         return false;
0295       }
0296       nbytes += n;
0297     }}
0298 
0299     if(!save_self()) {
0300       m_file.out() << "tools::wroot::directory::write :"
0301                    << " for directory " << sout(m_name)
0302                    << ", save_self failed."
0303                    << std::endl;
0304       return false; //it will write keys of objects.
0305     }
0306 
0307     a_nbytes = nbytes;
0308     return true;
0309   }
0310 
0311   void clear_dirs() {safe_clear<directory>(m_dirs);}
0312   void clear_objs() {safe_clear<iobject>(m_objs);}
0313 
0314   const std::list<key*>& keys() const {return m_keys;}
0315 
0316 protected:
0317   void clear_keys() {
0318     std::list<key*>::iterator it;
0319     for(it=m_keys.begin();it!=m_keys.end();) {
0320       key* k = *it;
0321       it = m_keys.erase(it);
0322       delete k;
0323     }
0324     m_keys.clear();
0325   }
0326 
0327   bool save(){
0328     if(!save_self()) return false;
0329     tools_vforit(directory*,m_dirs,it) {
0330       if(!(*it)->save()) return false;
0331     }
0332     return true;
0333   }
0334 
0335   bool save_self() {
0336     // Save Directory keys and header :
0337     //  If the directory has been modified (fModified set), write the keys
0338     //  and the directory header.
0339     //if (fModified || aForce) {
0340     //  if(!fFile.freeSegments().empty()) {
0341     //    if(!writeKeys()) return false; // Write keys record.
0342     //    if(!writeHeader()) return false; // Update directory record.
0343     //  }
0344     //}
0345     if(!write_keys()) return false;
0346     if(!write_header()) return false;
0347     return true;
0348   }
0349 
0350   key* find_key(const std::string& a_name) {
0351     if(m_file.verbose()) {
0352       m_file.out() << "tools::wroot::directory::find_key :"
0353                    << " " << sout(a_name) << " ..."
0354                    << std::endl;
0355     }
0356     tools_lforcit(key*,m_keys,it) {
0357       if((*it)->object_name()==a_name) return *it;
0358     }
0359 
0360     return 0;
0361   }
0362   seek seek_keys() const {return m_seek_keys;}
0363 
0364   uint16 append_key(key* a_key){ //take ownership of a_key
0365     tools_lforit(key*,m_keys,it) {
0366       if((*it)->object_name()==a_key->object_name()) {
0367         m_keys.insert(it,a_key); //a_key will be before *it.
0368         return ((*it)->cycle() + 1);
0369       }
0370     }
0371     // Not found :
0372     m_keys.push_back(a_key);
0373     return 1;
0374   }
0375 
0376   bool write_keys(){
0377     // The list of keys (m_keys) is written as a single data record
0378     // Delete the old keys structure if it exists
0379 
0380     // Write new keys record :
0381     uint32 nkeys  = uint32(m_keys.size());
0382 
0383     // Compute size of all keys
0384     uint32 nbytes = sizeof(nkeys);
0385 
0386    {tools_lforit(key*,m_keys,it) {
0387       nbytes += (*it)->key_length();
0388     }}
0389 
0390     key headerkey(m_file.out(),m_file,m_seek_directory,m_name,m_title,"TDirectory",nbytes); // m_file.set_END().
0391     if(!headerkey.seek_key()) return false;
0392 
0393    {char* buffer = headerkey.data_buffer();
0394     wbuf wb(m_file.out(),m_file.byte_swap(),headerkey.eob(),buffer);
0395     if(!wb.write(nkeys)) return false;
0396    {tools_lforit(key*,m_keys,it) {
0397       if(!((*it)->to_buffer(wb,m_file.verbose()))) return false;
0398     }}}
0399 
0400     m_seek_keys = headerkey.seek_key();
0401     m_nbytes_keys = headerkey.number_of_bytes();
0402 
0403     if(m_file.verbose()) {
0404       m_file.out() << "tools::wroot::directory::write_keys :"
0405                    << " write header key"
0406                    << " " << sout(m_name)
0407                    << " " << sout(m_title)
0408                    << " (" << nkeys
0409                    << ", " << nbytes
0410                    << ", " << m_seek_keys
0411                    << ", " << m_nbytes_keys
0412                    << "):"
0413                    << std::endl;
0414     }
0415 
0416     headerkey.set_cycle(1);
0417     if(!headerkey.write_self(m_file)) {
0418       m_file.out() << "tools::wroot::directory::write_keys :"
0419                    << " key.write_self() failed."
0420                    << std::endl;
0421       return false;
0422     }
0423 
0424     uint32 n;
0425     return headerkey.write_file(m_file,n);
0426   }
0427 
0428   bool write_header(){
0429     // Overwrite the Directory header record.
0430     uint32 nbytes = record_size();
0431     char* header = new char[nbytes];
0432     char* buffer = header;
0433     m_date_M = get_date();
0434     wbuf wb(m_file.out(),m_file.byte_swap(),header+nbytes,buffer);
0435     if(!to_buffer(wb)) {
0436       delete [] header;
0437       return false;
0438     }
0439     // do not overwrite the name/title part
0440     seek pointer = m_seek_directory + m_nbytes_name;
0441     if(!m_file.set_pos(pointer)) {
0442       delete [] header;
0443       return false;
0444     }
0445     if(!m_file.write_buffer(header,nbytes)) {
0446       delete [] header;
0447       return false;
0448     }
0449     if(!m_file.synchronize()) {
0450       delete [] header;
0451       return false;
0452     }
0453     delete [] header;
0454     return true;
0455   }
0456 
0457   bool write_object(iobject& a_obj,uint32& a_nbytes){
0458     buffer bref(m_file.out(),m_file.byte_swap(),256*128); //32768
0459     if(!a_obj.stream(bref)) {
0460       m_file.out() << "tools::wroot::directory::write_object :"
0461                    << " cannot stream object of store class name "
0462                    << " " << sout(a_obj.store_class_name()) << "."
0463                    << std::endl;
0464       a_nbytes = 0;
0465       return false;
0466     }
0467 
0468     std::string name = a_obj.name();
0469     strip(name);
0470 
0471     //first create the key to get key_length();
0472 
0473     wroot::key* key = new wroot::key(m_file.out(),m_file,m_seek_directory,
0474                                      name,
0475                                      a_obj.title(),a_obj.store_class_name(),
0476                                      bref.length()); // It does a m_file.set_END().
0477 
0478     if(!key->seek_key()) {
0479       delete key;
0480       return false;
0481     }
0482 
0483     if(!bref.displace_mapped(key->key_length())) { //done before compression.
0484       delete key;
0485       return false;
0486     }
0487 
0488     char* kbuf = 0;
0489     uint32 klen = 0;
0490     bool kdelete = false;
0491     m_file.compress_buffer(bref,kbuf,klen,kdelete);
0492 
0493     ::memcpy(key->data_buffer(),kbuf,klen);
0494     if(kdelete) delete [] kbuf;
0495 
0496    {uint32 nkey = key->key_length()+klen;
0497     m_file.set_END(key->seek_key()+nkey);
0498     key->set_number_of_bytes(nkey);}
0499 
0500     uint16 cycle = append_key(key);
0501     key->set_cycle(cycle);
0502 
0503     if(!key->write_self(m_file)) {
0504       m_file.out() << "tools::wroot::directory::write_object :"
0505                    << " key.write_self() failed."
0506                    << std::endl;
0507       return false;
0508     }
0509 
0510     //FIXME m_file.sumBuffer(key->object_size()); //uncompressed data size.
0511 
0512     if(m_file.verbose()) {
0513       m_file.out() << "tools::wroot::directory::_write_buffer :"
0514                    << " " << sout(a_obj.name()) << "."
0515                    << std::endl;
0516     }
0517 
0518     return key->write_file(m_file,a_nbytes);
0519   }
0520 
0521 protected:
0522   ifile& m_file;
0523   directory* m_parent;
0524   bool m_is_valid;
0525   std::string m_name;
0526   std::string m_title;
0527   std::vector<directory*> m_dirs;
0528   std::vector<iobject*> m_objs;
0529   std::list<key*> m_keys;
0530   // Record (stored in file):
0531   date m_date_C;           //Date and time when directory is created
0532   date m_date_M;           //Date and time of last modification
0533   uint32 m_nbytes_keys;    //Number of bytes for the keys
0534   uint32 m_nbytes_name;    //Number of bytes in TNamed at creation time
0535   seek m_seek_directory;   //Location of directory on file
0536   seek m_seek_parent;      //Location of parent directory on file
0537   seek m_seek_keys;        //Location of Keys record on file
0538 };
0539 
0540 }}
0541 
0542 #endif