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