inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/wroot/basket
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_basket
00005 #define inlib_wroot_basket
00006 
00007 #include "ibo"
00008 #include "key"
00009 #include "buffer"
00010 
00011 namespace inlib {
00012 namespace wroot {
00013 
00014 class basket : public virtual ibo, public key {
00015   static uint32 START_BIG_FILE() {return 2000000000;}
00016 public:
00017   static const std::string& s_class() {
00018     static const std::string s_v("inlib::wroot::basket");
00019     return s_v;
00020   }
00021 public: //ibo
00022   virtual const std::string& store_cls() const {
00023     static const std::string s_v("TBasket");
00024     return s_v;
00025   }
00026   virtual bool stream(buffer& a_buffer) const {
00027     // in principle we pass here only for the last basket
00028     // of a branch when it is streamed from branch::stream().
00029 
00030     // some consitency checks :
00031     if(!m_data.length()) {
00032       // to be sure to not work on a basket already written
00033       // with write_on_file()
00034       m_file.out() << "inlib::wroot::basket::stream :" 
00035                    << " m_data.length() is null."
00036                    << std::endl;
00037       return false;
00038     }
00039     if(m_seek_key) {
00040       m_file.out() << "inlib::wroot::basket::stream :" 
00041                    << " m_seek_key is not null."
00042                    << std::endl;
00043       return false;
00044     }
00045     if(m_last) {
00046       m_file.out() << "inlib::wroot::basket::stream :" 
00047                    << " m_last is not null."
00048                    << std::endl;
00049       return false;
00050     }
00051     if(!m_entry_offset) {
00052       m_file.out() << "inlib::wroot::basket::stream :" 
00053                    << " m_entry_offset is null."
00054                    << std::endl;
00055       return false;
00056     }
00057 
00058    {uint32 last = m_data.length()+m_key_length;
00059     if(last>m_last) {
00060       const_cast<basket&>(*this).m_last = last;
00061     }}
00062     if(m_last>m_buf_size) {
00063       const_cast<basket&>(*this).m_buf_size = m_last;
00064     }
00065 
00066     char flag = 11;
00067     if(m_displacement)  flag += 40;
00068     if(!_stream_header(a_buffer,flag)) return false;
00069 
00070     if(m_entry_offset && m_nev) {
00071       if(!a_buffer.write_array(m_entry_offset,m_nev)) return false;
00072       if(m_displacement) {
00073         if(!a_buffer.write_array(m_displacement,m_nev)) return false;
00074       }
00075     }
00076  
00077     if(m_data.to_displace()) {
00078       //NOTE : how / when handle the displacements ?
00079       m_file.out() << "inlib::wroot::basket::stream :" 
00080                    << " WARNING : m_data buffer has offsets to displace."
00081                    << std::endl;
00082       //if(!const_cast<basket&>(*this).m_data.displace_mapped(m_key_length))
00083       //  return false; //???
00084     }
00085 
00086     buffer bref(m_file.out(),m_file.byte_swap(),256);
00087     if(!_stream_header(bref)) return false; //then header stored twice !
00088     //if(bref.length()!=m_key_length) {}
00089     if(!bref.write_fast_array(m_data.buf(),m_data.length())) return false;
00090     if(!a_buffer.write_fast_array(bref.buf(),bref.length())) return false;
00091 
00092     return true;
00093   }
00094 public:
00095   basket(ifile& a_file,
00096                 seek a_seek_parent_dir,
00097                 const std::string& a_object_name,
00098                 const std::string& a_object_title,
00099                 const std::string& a_object_class,
00100                 uint32 a_basket_size)
00101   :key(a_file,a_seek_parent_dir,
00102        a_object_name,a_object_title,a_object_class,0)
00103   ,m_data(a_file.out(),a_file.byte_swap(),a_basket_size)
00104   ,m_nev_buf_size(1000)
00105   ,m_nev(0)
00106   ,m_last(0)
00107   ,m_entry_offset(0)
00108   ,m_displacement(0)
00109   {
00110 #ifdef INLIB_MEM
00111     mem::increment(s_class().c_str());
00112 #endif
00113 
00114     m_key_length = header_record_size(m_version);
00115     initialize(0);
00116 
00117     if(m_nev_buf_size) m_entry_offset = new uint32[m_nev_buf_size];
00118   }
00119   virtual ~basket(){
00120     delete [] m_entry_offset;
00121     delete [] m_displacement;
00122     m_entry_offset = 0;
00123     m_displacement = 0;
00124 #ifdef INLIB_MEM
00125     mem::decrement(s_class().c_str());
00126 #endif
00127   }
00128 protected:
00129   basket(const basket& a_from)
00130   : ibo(a_from)
00131   ,key(a_from)
00132   ,m_data(m_file.out(),m_file.byte_swap(),256)
00133   ,m_nev_buf_size(a_from.m_nev_buf_size)
00134   ,m_nev(a_from.m_nev)
00135   ,m_last(a_from.m_last)
00136   ,m_entry_offset(0)
00137   ,m_displacement(0)
00138   {
00139 #ifdef INLIB_MEM
00140     mem::increment(s_class().c_str());
00141 #endif
00142   }
00143   basket& operator=(const basket& a_from){
00144     key::operator=(a_from);
00145     m_nev_buf_size = a_from.m_nev_buf_size;
00146     m_nev = a_from.m_nev;
00147     m_last = a_from.m_last;
00148     return *this;
00149   }
00150 public:
00151   buffer& datbuf() {return m_data;}
00152 
00153   bool update(uint32 a_offset) {
00154     if(m_entry_offset) {
00155       if((m_nev+1)>=m_nev_buf_size) { //why +1 ?
00156         uint32 newsize = mx<uint32>(10,2*m_nev_buf_size);
00157         if(!realloc<uint32>(m_entry_offset,newsize,m_nev_buf_size,true)){
00158           m_file.out() << "inlib::wroot::basket::update : realloc failed."
00159                 << std::endl;
00160           return false;
00161         }
00162         if(m_displacement) {
00163           if(!realloc<int>(m_displacement,newsize,m_nev_buf_size,true)){
00164             m_file.out() << "inlib::wroot::basket::update : realloc failed."
00165                   << std::endl;
00166             return false;
00167           }
00168         }
00169 
00170         m_nev_buf_size = newsize;
00171 
00172         // Update branch only for the first 10 baskets
00173         //if (fBranch.writeBasket() < 10) 
00174         //  fBranch.setEntryOffsetLength(newsize);
00175       }
00176       m_entry_offset[m_nev] = a_offset;
00177 
00178       //if (skipped!=offset && !m_displacement){
00179       //  m_displacement = new int[m_nevSize];
00180       //  for(int i=0;i<m_nev_buf_size;i++)
00181       //     m_displacement[i] = m_entry_offset[i];
00182       //}
00183       //if (m_displacement) {
00184       //  m_displacement[m_nev] = skipped;
00185       //  fBufferRef->setDisplacement(skipped);
00186       //}
00187 
00188     }
00189     m_nev++;
00190     return true;
00191   }
00192 
00193   bool write_on_file(uint16 a_cycle,uint32& a_nbytes) {
00194     // write m_data buffer into file.
00195     //NOTE : m_data does not contain the key at its head.
00196     //       At this point m_seek_key should be 0.
00197 
00198     a_nbytes = 0;
00199 
00200     if(m_seek_key) {
00201       m_file.out() << "inlib::wroot::basket::write_on_file :" 
00202                    << " m_seek_key should be 0."
00203                    << std::endl;
00204       return false;
00205     }
00206 
00207     if(m_version>1000) {
00208     } else {
00209       if(m_file.END()>START_BIG_FILE()) {
00210         //GB : enforce m_version>1000 if m_version is still 2 but
00211         //     seek_key>START_BIG_FILE. If not doing that we shall
00212         //     write a big m_seek_key on a seek32 and then have
00213         //     a problem when reading.
00214   
00215         //m_file.out() << "inlib::wroot::basket::write_on_file : " 
00216         //             << " WARNING : pos>START_BIG_FILE."
00217         //             << std::endl;
00218 
00219         m_version += 1000;
00220         m_key_length += 8;
00221   
00222         if(m_entry_offset) {
00223           for(uint32 i=0;i<m_nev;i++) m_entry_offset[i] += 8;
00224           if(m_displacement) {
00225             //??? Do we have to shift them ?
00226             m_file.out() << "inlib::wroot::basket::write_on_file : " 
00227                          << " displace logic : m_displacement not null."
00228                          << std::endl;
00229           }
00230         }
00231   
00232       }
00233     }
00234 
00235     // Transfer m_entry_offset table at the end of fBuffer. Offsets to fBuffer
00236     // are transformed in entry length to optimize compression algorithm.
00237     m_last = m_key_length+m_data.length();
00238     if(m_entry_offset) {
00239       if(!m_data.write_array<uint32>(m_entry_offset,m_nev+1)) { //GB : why +1 ?
00240         delete [] m_entry_offset; 
00241         m_entry_offset = 0;
00242         return false;
00243       }
00244       delete [] m_entry_offset; 
00245       m_entry_offset = 0;
00246       if(m_displacement) {
00247         if(!m_data.write_array<int>(m_displacement,m_nev+1)) {
00248           delete [] m_displacement; 
00249           m_displacement = 0;
00250           return false;
00251         }
00252         delete [] m_displacement; 
00253         m_displacement = 0;
00254       }
00255     }
00256     
00257     m_object_size = m_data.length(); //uncompressed size.
00258 
00259     m_cycle = a_cycle;
00260 
00261     if(!m_data.displace_mapped(m_key_length)) return false;
00262 
00263     char* kbuf = 0;
00264     uint32 klen = 0;
00265     bool kdelete = false;
00266     m_file.compress_buffer(m_data,kbuf,klen,kdelete);
00267 
00268     if(klen>m_object_size) {
00269       m_file.out() << "inlib::wroot::basket::write_on_file :" 
00270                    << " compression anomaly "
00271                    << " m_object_size " << m_object_size
00272                    << " klen " << klen
00273                    << std::endl;
00274       if(kdelete) delete [] kbuf;
00275       return false;
00276     }
00277 
00278     if(!initialize(klen)) { //it will do a file.set_END()
00279       m_file.out() << "inlib::wroot::basket::write_on_file :" 
00280                    << " initialize() failed." 
00281                    << std::endl;
00282       if(kdelete) delete [] kbuf;
00283       return false;
00284     }
00285 
00286     //write header of the key :
00287    {buffer bref(m_file.out(),m_file.byte_swap(),256);
00288     if(!_stream_header(bref)) return false;
00289     if(bref.length()!=m_key_length) {
00290       m_file.out() << "inlib::wroot::basket::write_on_file :" 
00291                    << " key len anomaly " << bref.length()
00292                    << " m_key_length " << m_key_length
00293                    << std::endl;
00294       if(kdelete) delete [] kbuf;
00295       return false;
00296     }
00297     ::memcpy(m_buffer,bref.buf(),m_key_length);}
00298 
00299     ::memcpy(m_buffer+m_key_length,kbuf,klen);
00300     if(kdelete) delete [] kbuf;
00301     
00302     uint32 nbytes;
00303     if(!key::write_file(nbytes)) return false;
00304   
00305     m_data.pos() = m_data.buf(); //empty m_data.
00306 
00307     a_nbytes = m_key_length + klen;
00308     return true;
00309   }
00310 protected:
00311   uint32 header_record_size(uint32 a_version) const {
00312     // header only.
00313     uint32 nbytes = key::record_size(a_version);
00314 
00315     nbytes += sizeof(short);   //version
00316     nbytes += sizeof(uint32); //m_buf_size
00317     nbytes += sizeof(uint32); //m_nev_buf_size
00318     nbytes += sizeof(uint32); //m_nev
00319     nbytes += sizeof(uint32); //m_last
00320     nbytes += sizeof(char);   //flag
00321 
00322     return nbytes;
00323   }
00324   bool _stream_header(buffer& a_buffer,char a_flag = 0) const {
00325    {uint32 l = key::record_size(m_version);
00326     if((a_buffer.length()+l)>a_buffer.size()) {
00327       if(!a_buffer.expand(a_buffer.size()+l)) return false;
00328     }
00329     wbuf wb(m_file.out(),m_file.byte_swap(),a_buffer.max_pos(),a_buffer.pos());
00330     if(!key::to_buffer(wb)) return false;}
00331 
00332     if(!a_buffer.write_version(2)) return false;
00333     if(!a_buffer.write(m_buf_size)) return false;
00334     if(!a_buffer.write(m_nev_buf_size)) return false;
00335     if(!a_buffer.write(m_nev)) return false;
00336     if(!a_buffer.write(m_last)) return false;
00337     if(!a_buffer.write(a_flag)) return false;
00338     return true;
00339   }
00340 protected:
00341   buffer m_data;
00342 protected:
00343   uint32 m_nev_buf_size;  //Length in Int_t of m_entry_offset
00344   uint32 m_nev;           //Number of entries in basket
00345   uint32 m_last;          //Pointer to last used byte in basket
00346   uint32* m_entry_offset; //[m_nev] Offset of entries in fBuffer(TKey)
00347   int* m_displacement; 
00348 };
00349 
00350 }}
00351 
00352 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines