Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/wroot/branch 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_branch
0005 #define tools_wroot_branch
0006 
0007 #include "leaf"
0008 #include "basket"
0009 #include "../cmemT"
0010 #include "../forit"
0011 
0012 #include "imutex"
0013 
0014 namespace tools {
0015 namespace wroot {
0016 
0017 class branch : public virtual ibo {
0018 public: //ibo
0019   virtual const std::string& store_cls() const {
0020     static const std::string s_v("TBranch");
0021     return s_v;
0022   }
0023   virtual bool stream(buffer& a_buffer) const {
0024     unsigned int c;
0025     if(!a_buffer.write_version(8,c)) return false;
0026     if(!Named_stream(a_buffer,m_name,m_title)) return false;
0027 
0028     if(!AttFill_stream(a_buffer)) return false;
0029 
0030     int fEntryOffsetLen = 1000;
0031     int fOffset = 0;
0032     int fSplitLevel = 0;
0033 
0034     if(!a_buffer.write(fCompress)) return false;
0035     if(!a_buffer.write(m_basket_size)) return false;
0036     if(!a_buffer.write(fEntryOffsetLen)) return false;
0037     if(!a_buffer.write(m_write_basket)) return false;
0038     int fEntryNumber = (int)m_entry_number;
0039     if(!a_buffer.write(fEntryNumber)) return false;
0040     if(!a_buffer.write(fOffset)) return false;
0041     if(!a_buffer.write(m_max_baskets)) return false;
0042     if(!a_buffer.write(fSplitLevel)) return false;
0043     double fEntries = (double)m_entries;
0044     if(!a_buffer.write(fEntries)) return false;
0045     double fTotBytes = (double)m_tot_bytes;
0046     double fZipBytes = (double)m_zip_bytes;
0047     if(!a_buffer.write(fTotBytes)) return false;
0048     if(!a_buffer.write(fZipBytes)) return false;
0049 
0050     if(!m_branches.stream(a_buffer)) return false;
0051     if(!m_leaves.stream(a_buffer)) return false;
0052     if(!m_baskets.stream(a_buffer)) return false;
0053 
0054     // See TStreamerInfo::ReadBuffer::WriteBasicPointer
0055     if(!a_buffer.write((char)1)) return false;
0056     if(!a_buffer.write_fast_array(fBasketBytes,m_max_baskets)) return false;
0057     if(!a_buffer.write((char)1)) return false;
0058     if(!a_buffer.write_fast_array(fBasketEntry,m_max_baskets)) return false;
0059 
0060     char isBigFile = 1;
0061     //GB : begin
0062    {for(uint32 i=0;i<m_max_baskets;i++) {
0063       if(fBasketSeek[i]>START_BIG_FILE()) {
0064         isBigFile = 2;
0065         break;
0066       }
0067     }}
0068     //GB : end
0069 
0070     if(!a_buffer.write(isBigFile)) return false;
0071     if(isBigFile==2) {
0072       if(!a_buffer.write_fast_array(fBasketSeek,m_max_baskets)) return false;
0073     } else {
0074       for(uint32 i=0;i<m_max_baskets;i++) {
0075         if(fBasketSeek[i]>START_BIG_FILE()) { //G.Barrand : add this test.
0076           m_out << "tools::wroot::branch::stream :"
0077                 << " attempt to write big Seek "
0078                 << fBasketSeek[i] << " on 32 bits."
0079                 << std::endl;
0080           return false;
0081         }
0082 
0083         if(!a_buffer.write((seek32)fBasketSeek[i])) return false;
0084       }
0085     }
0086 
0087     // fFileName
0088     if(!a_buffer.write(std::string(""))) return false;
0089 
0090     if(!a_buffer.set_byte_count(c)) return false;
0091     return true;
0092   }
0093 
0094 public:
0095   branch(std::ostream& a_out,bool a_byte_swap,uint32 a_compression,
0096          seek a_seek_directory,const std::string& a_name,const std::string& a_title,bool a_verbose)
0097   :m_out(a_out)
0098   ,m_byte_swap(a_byte_swap)
0099   ,m_verbose(a_verbose)
0100   ,m_seek_directory(a_seek_directory)
0101   ,m_name(a_name)
0102   ,m_title(a_title)
0103   ,fAutoDelete(false)
0104   ,fCompress(a_compression)
0105   ,m_basket_size(32000)
0106   ,m_write_basket(0)
0107   ,m_entry_number(0)
0108   ,m_entries(0)
0109   ,m_tot_bytes(0)
0110   ,m_zip_bytes(0)
0111   ,m_max_baskets(10)
0112   ,fBasketBytes(0)
0113   ,fBasketEntry(0)
0114   ,fBasketSeek(0)
0115   {
0116     m_baskets.resize(m_max_baskets,0);
0117     fBasketBytes = new uint32[m_max_baskets];
0118     fBasketEntry = new uint32[m_max_baskets];
0119     fBasketSeek = new seek[m_max_baskets];
0120    {for(uint32 i=0;i<m_max_baskets;i++) {
0121       m_baskets[i] = 0;
0122       fBasketBytes[i] = 0;
0123       fBasketEntry[i] = 0;
0124       fBasketSeek[i] = 0;
0125     }}
0126     m_baskets[m_write_basket] = new basket(m_out,m_byte_swap,a_seek_directory,m_name,m_title,"TBasket",m_basket_size,m_verbose);
0127     fBasketEntry[m_write_basket] = (uint32)m_entry_number;
0128   }
0129   virtual ~branch(){
0130     delete [] fBasketBytes;
0131     delete [] fBasketEntry;
0132     delete [] fBasketSeek;
0133     fBasketBytes = 0;
0134     fBasketEntry = 0;
0135     fBasketSeek = 0;
0136   }
0137 protected:
0138   branch(const branch& a_from)
0139   :ibo(a_from)
0140   ,m_out(a_from.m_out)
0141   ,m_seek_directory(a_from.m_seek_directory)
0142   {}
0143   branch& operator=(const branch&){return *this;}
0144 public:
0145   const std::string& name() const {return m_name;}
0146   const std::string& title() const {return m_title;}
0147 
0148   uint64 entries() const {return m_entries;}
0149 
0150   uint64 tot_bytes() const {return m_tot_bytes;}
0151   void set_tot_bytes(uint64 a_value) {m_tot_bytes = a_value;}
0152 
0153   uint64 zip_bytes() const {return m_zip_bytes;}
0154   void set_zip_bytes(uint64 a_value) {m_zip_bytes = a_value;}
0155 
0156   void set_basket_size(uint32 a_size) {m_basket_size = a_size;}
0157   uint32 basket_size() const {return m_basket_size;}
0158 
0159   ////////////////////////////////////////////////
0160   ////////////////////////////////////////////////
0161   ////////////////////////////////////////////////
0162   template <class T>
0163   leaf_ref<T>* create_leaf_ref(const std::string& a_name,const T& a_ref){
0164     leaf_ref<T>* lf = new leaf_ref<T>(m_out,a_name,a_ref);
0165     m_leaves.push_back(lf);
0166     return lf;
0167   }
0168 
0169   leaf_string_ref* create_leaf_string_ref(const std::string& a_name,const std::string& a_ref){
0170     leaf_string_ref* lf = new leaf_string_ref(m_out,a_name,a_ref);
0171     m_leaves.push_back(lf);
0172     return lf;
0173   }
0174   ////////////////////////////////////////////////
0175   ////////////////////////////////////////////////
0176   ////////////////////////////////////////////////
0177 
0178   template <class T>
0179   leaf<T>* create_leaf(const std::string& a_name){
0180     leaf<T>* lf = new leaf<T>(m_out,a_name);
0181     m_leaves.push_back(lf);
0182     return lf;
0183   }
0184 
0185   leaf_string* create_leaf_string(const std::string& a_name){
0186     leaf_string* lf = new leaf_string(m_out,a_name);
0187     m_leaves.push_back(lf);
0188     return lf;
0189   }
0190 
0191   leaf_element* create_leaf_element(const std::string& a_name,int a_id,int a_type){
0192     leaf_element* lf = new leaf_element(m_out,a_name,a_id,a_type);
0193     m_leaves.push_back(lf);
0194     return lf;
0195   }
0196 
0197   // for row_wise ntuple :
0198   template <class T>
0199   leaf_std_vector_ref<T>* create_leaf_std_vector_ref(const std::string& a_name,
0200                                                      base_leaf& a_leaf_count,const std::vector<T>& a_ref) {
0201     leaf_std_vector_ref<T>* lf = new leaf_std_vector_ref<T>(m_out,a_name,a_leaf_count,a_ref);
0202     m_leaves.push_back(lf);
0203     return lf;
0204   }
0205 
0206   const std::vector<base_leaf*>& leaves() const {return m_leaves;}
0207 
0208   void reset() {
0209     m_baskets.clear_objs();
0210     delete [] fBasketBytes;
0211     delete [] fBasketEntry;
0212     delete [] fBasketSeek;
0213     fBasketBytes = 0;
0214     fBasketEntry = 0;
0215     fBasketSeek = 0;
0216 
0217     m_max_baskets = 10;
0218 
0219     m_write_basket = 0;
0220     m_entry_number = 0;
0221     m_entries = 0;
0222     m_tot_bytes = 0;
0223     m_zip_bytes = 0;
0224 
0225     m_baskets.resize(m_max_baskets,0);
0226     fBasketBytes = new uint32[m_max_baskets];
0227     fBasketEntry = new uint32[m_max_baskets];
0228     fBasketSeek = new seek[m_max_baskets];
0229    {for(uint32 i=0;i<m_max_baskets;i++) {
0230       m_baskets[i] = 0;
0231       fBasketBytes[i] = 0;
0232       fBasketEntry[i] = 0;
0233       fBasketSeek[i] = 0;
0234     }}
0235     fBasketEntry[m_write_basket] = (uint32)m_entry_number;
0236     m_baskets[m_write_basket] = new basket(m_out,m_byte_swap,m_seek_directory,m_name,m_title,"TBasket",m_basket_size,m_verbose);
0237 
0238    {tools_vforit(branch*,m_branches,it) (*it)->reset();}
0239   }
0240 
0241   bool fill(ifile& a_file,uint32& a_nbytes,uint32& a_add_bytes,uint32& a_nout) {
0242     a_nbytes = 0;
0243     a_add_bytes = 0;
0244     a_nout = 0;
0245 
0246     if(m_write_basket>=m_max_baskets) {
0247       m_out << "tools::wroot::branch::fill :"
0248             << " potential overflow : m_write_basket (" << m_write_basket << ")"
0249             << " >= m_max_baskets (" << m_max_baskets << ")."
0250             << std::endl;
0251       return false;
0252     }
0253 
0254     basket* bk = m_baskets[m_write_basket];
0255     if(!bk) {
0256       m_out << "tools::wroot::branch::fill :"
0257             << " m_baskets[m_write_basket] should not be null."
0258             << std::endl;
0259       return false;
0260     }
0261 
0262     buffer& buf = bk->datbuf();
0263 
0264     buf.reset_objs_map();
0265 
0266     uint32 lold = buf.length();
0267 
0268     bk->update(bk->key_length()+lold);
0269     m_entries++;
0270     m_entry_number++;
0271 
0272     if(!fill_leaves(buf)) {
0273       m_out << "tools::wroot::branch::fill :"
0274             << " fill_leaves() failed."
0275             << std::endl;
0276       return false;
0277     }
0278 
0279     uint32 lnew   = buf.length();
0280     uint32 nbytes = lnew - lold;
0281     uint32 nsize  = 0;
0282 
0283     uint32 add_bytes  = 0;
0284     uint32 nout  = 0;
0285 
0286     // Should we create a new basket?
0287     // Compare expected next size with m_basket_size.
0288     if((lnew+2*nsize+nbytes)>=m_basket_size) {
0289       if(!bk->write_on_file(a_file,m_write_basket,nout)) {//it set bk m_seek_key, set a_file.m_END.
0290                                                           //Does a a_file.set_END().
0291         m_out << "tools::wroot::branch::fill :"
0292               << " basket.write_on_file() failed."
0293               << std::endl;
0294         return false;
0295       }
0296       fBasketBytes[m_write_basket]  = bk->number_of_bytes();
0297     //fBasketEntry[m_write_basket]  = // not done here since we do not know here the first entry.
0298       fBasketSeek[m_write_basket]   = bk->seek_key();
0299 
0300       add_bytes = bk->object_size() + bk->key_length();
0301 
0302       delete bk;
0303       m_baskets[m_write_basket] = 0;
0304 
0305       m_tot_bytes += add_bytes;
0306       m_zip_bytes += nout;
0307 
0308       m_write_basket++;
0309       if(!check_alloc_fBasketXxx()) return false;
0310 
0311       m_baskets[m_write_basket] = new basket(m_out,m_byte_swap,
0312                                              m_seek_directory,m_name,m_title,"TBasket",m_basket_size,
0313                                              m_verbose);
0314       fBasketEntry[m_write_basket] = (uint32)m_entry_number;
0315     }
0316     a_nbytes = nbytes;
0317     a_add_bytes = add_bytes;
0318     a_nout = nout;
0319     return true;
0320   }
0321 
0322   ///////////////////////////////////////////////////////////////////////////
0323   /// for parallelization : /////////////////////////////////////////////////
0324   ///////////////////////////////////////////////////////////////////////////
0325   bool add_basket(ifile& a_file,basket& a_basket,uint32& a_add_bytes,uint32& a_nout) {
0326     //done on a (main) ntuple/branch.
0327 
0328     if(m_write_basket>=m_max_baskets) {
0329       m_out << "tools::wroot::branch::add_basket :"
0330             << " potential overflow : m_write_basket (" << m_write_basket << ")"
0331             << " >= m_max_baskets (" << m_max_baskets << ")."
0332             << std::endl;
0333       return false;
0334     }
0335 
0336     uint32 nout;
0337     if(!a_basket.write_on_file(a_file,m_write_basket,nout)) { //a_file is the main file (a true file).
0338       //the upper set a_basket.m_seek_key, set a_file.m_END. Does a a_file.set_END().
0339       m_out << "tools::wroot::branch::add_basket :"
0340             << " basket.write_on_file() failed."
0341             << std::endl;
0342       return false;
0343     }
0344 
0345     fBasketBytes[m_write_basket]  = a_basket.number_of_bytes();
0346     fBasketEntry[m_write_basket]  = (uint32)m_entry_number;
0347     fBasketSeek[m_write_basket]   = a_basket.seek_key();
0348 
0349     m_entries += a_basket.nev();
0350     m_entry_number += a_basket.nev();
0351 
0352     uint32 add_bytes = a_basket.object_size() + a_basket.key_length();
0353 
0354     delete m_baskets[m_write_basket];
0355     m_baskets[m_write_basket] = 0;
0356 
0357     m_write_basket++;
0358     if(!check_alloc_fBasketXxx()) return false;
0359 
0360     m_baskets[m_write_basket] = new basket(m_out,m_byte_swap,
0361                                            m_seek_directory,m_name,m_title,"TBasket",m_basket_size,
0362                                            m_verbose);
0363     fBasketEntry[m_write_basket] = (uint32)m_entry_number;
0364 
0365     a_add_bytes = add_bytes;
0366     a_nout = nout;
0367     return true;
0368   }
0369 
0370   class iadd_basket {
0371   public:
0372     virtual ~iadd_basket() {}
0373   public:
0374     virtual bool add_basket(basket*) = 0;
0375   };
0376 
0377   bool pfill(iadd_basket& a_badd,uint32 a_nev) {
0378     //done on a pntuple/branch.
0379 
0380     //a_nbytes = 0;
0381     //a_add_bytes = 0;
0382     //a_nout = 0;
0383 
0384     // this method uses always m_baskets[0].
0385 
0386     basket* bk = m_baskets[m_write_basket];
0387     if(!bk) {
0388       m_out << "tools::wroot::branch::parallel_fill :"
0389             << " get_basket failed."
0390             << std::endl;
0391       return false;
0392     }
0393 
0394     buffer& buf = bk->datbuf();
0395 
0396     uint32 lold = buf.length();
0397 
0398     bk->update(bk->key_length()+lold);
0399 
0400     //m_entries++;      //not used by parallel branches.
0401     //m_entry_number++; //idem.
0402 
0403     if(!fill_leaves(buf)) {
0404       m_out << "tools::wroot::branch::parallel_fill :"
0405             << " fill_leaves() failed."
0406             << std::endl;
0407       return false;
0408     }
0409 
0410     uint32 lnew   = buf.length();
0411     uint32 nbytes = lnew - lold;
0412 
0413     // Should we create a new basket?
0414     bool store_basket = false;
0415     if(a_nev) {
0416       store_basket = (bk->nev()>=a_nev);              // trigger add_basket per number of entries reached.
0417     } else {
0418       store_basket = ((lnew+nbytes)>=m_basket_size);  // trigger add_basket when reaching m_basket_size.
0419     }
0420 
0421     if(store_basket) {
0422       if(!a_badd.add_basket(bk)) {  //we give ownership of bk.
0423         m_out << "tools::wroot::branch::parallel_fill :"
0424               << " main_branch.add_basket() failed."
0425               << std::endl;
0426         return false;
0427       }
0428       //delete bk; //no, it is deleted by the a_badd.add_basket().
0429       bool main_branch_byte_swap = m_byte_swap; //NOTE : it assumes that pntuple/branch and main/branch have same byte_swap.
0430       bool main_branch_verbose = m_verbose;
0431       m_baskets[m_write_basket] = new basket(m_out,main_branch_byte_swap,
0432                                              m_seek_directory,m_name,m_title,"TBasket",m_basket_size,
0433                                              main_branch_verbose);
0434     }
0435 
0436     return true;
0437   }
0438 
0439   bool end_pfill(iadd_basket& a_badd) {
0440     //done on a pntuple/branch.
0441 
0442     basket* bk = m_baskets[m_write_basket];
0443     if(!bk) {
0444       m_out << "tools::wroot::branch::end_pfill :"
0445             << " m_baskets[m_write_basket] should not be null."
0446             << std::endl;
0447       return false;
0448     }
0449 
0450     buffer& buf = bk->datbuf();
0451     uint32 lold = buf.length();
0452 
0453     if(lold) {
0454       if(!a_badd.add_basket(bk)) {  //we give ownership of bk.
0455         m_out << "tools::wroot::branch::parallel_fill :"
0456               << " main_branch.add_basket() failed."
0457               << std::endl;
0458         return false;
0459       }
0460     } else {
0461       delete bk;
0462     }
0463 
0464     m_baskets[m_write_basket] = 0; // no need to recreate a basket since it is end of fill.
0465 
0466     return true;
0467   }
0468 
0469   ///////////////////////////////////////////////////////////////////////////
0470   ///////////////////////////////////////////////////////////////////////////
0471   ///////////////////////////////////////////////////////////////////////////
0472 protected:
0473   bool check_alloc_fBasketXxx() {
0474     if(m_write_basket>=m_max_baskets) {
0475       //Increase BasketEntry buffer of a minimum of 10 locations
0476       // and a maximum of 50 per cent of current size
0477       uint32 newsize = max_of<uint32>(10,uint32(1.5*m_max_baskets));
0478       if(newsize>=START_BIG_FILE()) {
0479         //we are going to have pb with uint32[] indexing.
0480         m_out << "tools::wroot::branch::add_basket :"
0481               << " new size for fBasket[Bytes,Entry,Seek] arrays"
0482               << " is too close of 32 bits limit."
0483               << std::endl;
0484         m_out << "tools::wroot::branch::add_basket :"
0485               << " you have to work with larger basket size."
0486               << std::endl;
0487         return false;
0488       }
0489 
0490       m_baskets.resize(newsize,0);
0491 
0492       if(!cmem_realloc<uint32>(fBasketBytes,newsize,m_max_baskets,true)) {
0493         m_out << "tools::wroot::branch::add_basket : realloc failed." << std::endl;
0494         return false;
0495       }
0496       if(!cmem_realloc<uint32>(fBasketEntry,newsize,m_max_baskets,true)){
0497         m_out << "tools::wroot::branch::add_basket : realloc failed." << std::endl;
0498         return false;
0499       }
0500       if(!cmem_realloc<seek>(fBasketSeek,newsize,m_max_baskets,true)){
0501         m_out << "tools::wroot::branch::add_basket : realloc failed." << std::endl;
0502         return false;
0503       }
0504       m_max_baskets = newsize;
0505     }
0506 
0507     m_baskets[m_write_basket] = 0;
0508     fBasketBytes[m_write_basket] = 0;
0509     fBasketEntry[m_write_basket] = 0;
0510     fBasketSeek[m_write_basket]  = 0;
0511 
0512     return true;
0513   }
0514 
0515   virtual bool fill_leaves(buffer& a_buffer) { //virtual for branch_element.
0516     tools_vforit(base_leaf*,m_leaves,it) {
0517       if(!(*it)->fill_buffer(a_buffer)) return false;
0518     }
0519     return true;
0520   }
0521 protected:
0522   std::ostream& m_out;
0523   bool m_byte_swap;
0524   bool m_verbose;
0525   seek m_seek_directory;
0526   obj_array<basket> m_baskets;
0527   /// for parallelization :
0528 public:
0529   std::vector<basket*> m_parallel_baskets;
0530 protected:
0531   //Object
0532   //uint32 m_bits;
0533   //Named
0534   std::string m_name;
0535   std::string m_title;
0536 
0537   bool fAutoDelete;
0538 private: //be sure that sub branches are not used for the moment.
0539   obj_array<branch> m_branches;
0540 protected:
0541   obj_array<base_leaf> m_leaves;
0542   uint32 fCompress;      //  Compression level and algorithm
0543   uint32 m_basket_size;  //  Initial Size of Basket Buffer
0544   uint32 m_write_basket; //  Last basket number written
0545   uint64 m_entry_number; // Current entry number (last one filled in this branch)
0546   uint64 m_entries;      //  Number of entries
0547   uint64 m_tot_bytes;
0548   uint64 m_zip_bytes;
0549   uint32 m_max_baskets;
0550   uint32* fBasketBytes;  //[m_max_baskets] Length of baskets on file
0551   uint32* fBasketEntry;  //[m_max_baskets] Table of first entry in eack basket
0552   seek* fBasketSeek;     //[m_max_baskets] Addresses of baskets on file
0553 };
0554 
0555 }}
0556 
0557 #endif