inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/wroot/branch
Go to the documentation of this file.
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
00002 // See the file inlib.license for terms.
00003 
00004 #ifndef inlib_wroot_branch
00005 #define inlib_wroot_branch
00006 
00007 #include "leaf"
00008 #include "basket"
00009 #include "itree"
00010 #include "idir"
00011 
00012 namespace inlib {
00013 namespace wroot {
00014 
00015 class branch : public virtual ibo {
00016   static uint32 START_BIG_FILE() {return 2000000000;}
00017   //static uint32 kDoNotProcess() {return (1<<10);} // Active bit for branches
00018 #ifdef INLIB_MEM
00019   static const std::string& s_class() {
00020     static const std::string s_v("inlib::wroot::branch");
00021     return s_v;
00022   }
00023 #endif
00024 public: //ibo
00025   virtual const std::string& store_cls() const {
00026     static const std::string s_v("TBranch");
00027     return s_v;
00028   }
00029   virtual bool stream(buffer& a_buffer) const {
00030     unsigned int c;
00031     if(!a_buffer.write_version(8,c)) return false;
00032     if(!Named_stream(a_buffer,m_name,m_title)) return false;
00033 
00034     if(!AttFill_stream(a_buffer)) return false;
00035 
00036     int fCompress = m_tree.dir().file().compression();
00037     int fEntryOffsetLen = 1000;
00038     int fOffset = 0;
00039     int fSplitLevel = 0;
00040 
00041     if(!a_buffer.write(fCompress)) return false;
00042     if(!a_buffer.write(m_basket_size)) return false;
00043     if(!a_buffer.write(fEntryOffsetLen)) return false;
00044     if(!a_buffer.write(m_write_basket)) return false;
00045     int fEntryNumber = (int)m_entry_number;
00046     if(!a_buffer.write(fEntryNumber)) return false;
00047     if(!a_buffer.write(fOffset)) return false;
00048     if(!a_buffer.write(m_max_baskets)) return false;
00049     if(!a_buffer.write(fSplitLevel)) return false;
00050     double fEntries = (double)m_entries;
00051     if(!a_buffer.write(fEntries)) return false;
00052     double fTotBytes = (double)m_tot_bytes;
00053     double fZipBytes = (double)m_zip_bytes;
00054     if(!a_buffer.write(fTotBytes)) return false;
00055     if(!a_buffer.write(fZipBytes)) return false;
00056 
00057     if(!m_branches.stream(a_buffer)) return false;
00058     if(!m_leaves.stream(a_buffer)) return false;
00059     if(!m_baskets.stream(a_buffer)) return false;
00060 
00061     // See TStreamerInfo::ReadBuffer::WriteBasicPointer
00062     if(!a_buffer.write((char)1)) return false;
00063     if(!a_buffer.write_fast_array(fBasketBytes,m_max_baskets)) return false;
00064     if(!a_buffer.write((char)1)) return false;
00065     if(!a_buffer.write_fast_array(fBasketEntry,m_max_baskets)) return false;
00066 
00067     char isBigFile = 1;
00068     //GB : begin
00069     //if(fTree.directory().file().end()>RIO_START_BIG_FILE()) isBigFile = 2;
00070    {for(uint32 i=0;i<m_max_baskets;i++) {
00071       if(fBasketSeek[i]>START_BIG_FILE()) {
00072         isBigFile = 2;
00073         break;
00074       }
00075     }}
00076     //GB : end
00077    
00078     if(!a_buffer.write(isBigFile)) return false;
00079     if(isBigFile==2) {
00080       if(!a_buffer.write_fast_array(fBasketSeek,m_max_baskets)) return false;
00081     } else {
00082       for(uint32 i=0;i<m_max_baskets;i++) {
00083         if(fBasketSeek[i]>START_BIG_FILE()) { //G.Barrand : add this test.
00084           m_out << "inlib::wroot::branch::stream :"
00085                 << " attempt to write big Seek "
00086                 << fBasketSeek[i] << " on 32 bits."
00087                 << std::endl;
00088           return false;
00089         }
00090 
00091         if(!a_buffer.write((seek32)fBasketSeek[i])) return false;
00092       }
00093     }
00094 
00095     // fFileName
00096     if(!a_buffer.write(std::string(""))) return false;
00097 
00098     if(!a_buffer.set_byte_count(c)) return false;
00099     return true;
00100   }
00101 
00102 public:
00103   branch(itree& a_tree,
00104                 const std::string& a_name,
00105                 const std::string& a_title)
00106   :m_tree(a_tree)
00107   ,m_out(a_tree.dir().file().out())
00108   ,m_name(a_name)
00109   ,m_title(a_title)
00110   ,fAutoDelete(false)
00111 
00112   //,m_branches(true)
00113   //,m_leaves(true)
00114   ,m_basket_size(32000)
00115   ,m_write_basket(0)
00116   ,m_entry_number(0)
00117   ,m_entries(0)
00118   ,m_tot_bytes(0)
00119   ,m_zip_bytes(0)
00120   ,m_max_baskets(10)
00121   ,fBasketBytes(0)
00122   ,fBasketEntry(0)
00123   ,fBasketSeek(0)
00124   {
00125 #ifdef INLIB_MEM
00126     mem::increment(s_class().c_str());
00127 #endif
00128     fBasketBytes = new uint32[m_max_baskets];
00129     fBasketEntry = new uint32[m_max_baskets];
00130     fBasketSeek = new seek[m_max_baskets];
00131    {for(uint32 i=0;i<m_max_baskets;i++) {
00132       fBasketBytes[i] = 0;
00133       fBasketEntry[i] = 0;
00134       fBasketSeek[i] = 0;
00135     }}
00136     m_baskets.push_back(new basket(m_tree.dir().file(),
00137                                    m_tree.dir().seek_directory(),
00138                                    m_name,m_title,"TBasket",
00139                                    m_basket_size));
00140   }
00141   virtual ~branch(){
00142     delete [] fBasketBytes;
00143     delete [] fBasketEntry;
00144     delete [] fBasketSeek;
00145     fBasketBytes = 0;
00146     fBasketEntry = 0;
00147     fBasketSeek = 0;
00148 #ifdef INLIB_MEM
00149     mem::decrement(s_class().c_str());
00150 #endif
00151   }
00152 protected:
00153   branch(const branch& a_from)
00154   : ibo(a_from)
00155   ,m_tree(a_from.m_tree)
00156   ,m_out(a_from.m_out)
00157   {}
00158   branch& operator=(const branch&){return *this;}
00159 public:
00160   void set_basket_size(uint32 a_size) {m_basket_size = a_size;}
00161 
00162   template <class T>
00163   leaf<T>* create_leaf(const std::string& a_name,
00164                               const std::string& a_title){
00165     leaf<T>* lf = new leaf<T>(m_out,*this,a_name,a_title);
00166     m_leaves.push_back(lf);
00167     return lf;
00168   }
00169 
00170   const std::vector<base_leaf*>& leaves() const {return m_leaves;}
00171 
00172   bool fill(uint32& a_nbytes) {
00173     a_nbytes = 0;
00174 
00175     //FIXME if (TestBit(kDoNotProcess)) return 0;
00176 
00177     basket* bk = m_baskets[m_write_basket];
00178     if(!bk) {
00179       m_out << "inlib::wroot::branch::fill :"
00180             << " get_basket failed."
00181             << std::endl;
00182       return false;
00183     }
00184 
00185     buffer& buf = bk->datbuf();
00186     
00187     uint32 lold = buf.length();
00188   
00189     bk->update(bk->key_length()+lold);
00190     m_entries++;
00191     m_entry_number++;
00192   
00193     if(!fill_leaves(buf)) return false;
00194   
00195     uint32 lnew   = buf.length();
00196     uint32 nbytes = lnew - lold;
00197     uint32 nsize  = 0;
00198 
00199     // Should we create a new basket?
00200     // Compare expected next size with m_basket_size.
00201     if((lnew+2*nsize+nbytes)>=m_basket_size) { 
00202       uint32 nout;
00203       if(!bk->write_on_file(m_write_basket,nout)) {
00204         m_out << "inlib::wroot::branch::fill :"
00205               << " basket.write_buffer() failed."
00206               << std::endl;
00207         return false;
00208       }
00209       fBasketBytes[m_write_basket]  = bk->number_of_bytes();
00210     //fBasketEntry[m_write_basket] //can't be set here.
00211       fBasketSeek[m_write_basket]   = bk->seek_key();
00212       uint32 add_bytes = bk->object_size() + bk->key_length();
00213 
00214       delete bk;
00215       m_baskets[m_write_basket] = 0;
00216 
00217       m_tot_bytes += add_bytes;
00218       m_zip_bytes += nout;
00219 
00220       m_tree.add_tot_bytes(add_bytes);
00221       m_tree.add_zip_bytes(nout);
00222 
00223       bk = new basket(m_tree.dir().file(),m_tree.dir().seek_directory(),
00224                       m_name,m_title,"TBasket",m_basket_size);
00225 
00226       m_write_basket++;
00227 
00228       if(m_write_basket>=m_baskets.size())  {
00229         m_baskets.resize(2*m_write_basket,0);
00230       }
00231       m_baskets[m_write_basket] = bk;
00232   
00233       if(m_write_basket>=m_max_baskets) {
00234         //Increase BasketEntry buffer of a minimum of 10 locations
00235         // and a maximum of 50 per cent of current size
00236         uint32 newsize = mx<uint32>(10,uint32(1.5*m_max_baskets));
00237         if(newsize>=START_BIG_FILE()) {
00238           //we are going to have pb with uint32[] indexing.
00239           m_out << "inlib::wroot::branch::fill :"
00240                 << " new size for fBasket[Bytes,Entry,Seek] arrays"
00241                 << " is too close of 32 bits limit."
00242                 << std::endl;
00243           m_out << "inlib::wroot::branch::fill :"
00244                 << " you have to work with larger basket size."
00245                 << std::endl;
00246           return false;
00247         }
00248 
00249         if(!realloc<uint32>(fBasketBytes,newsize,m_max_baskets,true)) {
00250           m_out << "inlib::wroot::branch::fill : realloc failed." << std::endl;
00251           return false;
00252         }
00253         if(!realloc<uint32>(fBasketEntry,newsize,m_max_baskets,true)){
00254           m_out << "inlib::wroot::branch::fill : realloc failed." << std::endl;
00255           return false;
00256         }
00257         if(!realloc<seek>(fBasketSeek,newsize,m_max_baskets,true)){
00258           m_out << "inlib::wroot::branch::fill : realloc failed." << std::endl;
00259           return false;
00260         }
00261         m_max_baskets = newsize;
00262       }
00263       fBasketBytes[m_write_basket] = 0;
00264       fBasketEntry[m_write_basket] = (uint32)m_entry_number;
00265       fBasketSeek[m_write_basket]  = 0;
00266     }
00267     a_nbytes = nbytes;
00268     return true;
00269   }
00270 protected:
00271   bool fill_leaves(buffer& a_buffer) {
00272     std::vector<base_leaf*>::iterator it;
00273     for(it=m_leaves.begin();it!=m_leaves.end();++it) {
00274       if(!(*it)->fill_basket(a_buffer)) return false;
00275     }
00276     return true;
00277   }
00278 protected:
00279   itree& m_tree;
00280   std::ostream& m_out;
00281   ObjArray<basket> m_baskets;
00282 protected:
00283   //Object
00284   //uint32 m_bits;
00285   //Named
00286   std::string m_name;
00287   std::string m_title;
00288 
00289   bool fAutoDelete;
00290   ObjArray<branch> m_branches;
00291   ObjArray<base_leaf> m_leaves;
00292   uint32 m_basket_size;  //  Initial Size of Basket Buffer
00293   uint32 m_write_basket; //  Last basket number written
00294   uint64 m_entry_number; // Current entry number (last one filled in this branch)
00295   uint64 m_entries;      //  Number of entries
00296   uint64 m_tot_bytes;
00297   uint64 m_zip_bytes;
00298   uint32 m_max_baskets;
00299   uint32* fBasketBytes;  //[m_max_baskets] Lenght of baskets on file
00300   uint32* fBasketEntry;  //[m_max_baskets] Table of first entry in eack basket
00301   seek* fBasketSeek;     //[m_max_baskets] Addresses of baskets on file
00302 };
00303 
00304 }}
00305 
00306 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines