inlib
1.2.0
|
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