inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/rroot/key
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_rroot_key
00005 #define inlib_rroot_key
00006 
00007 #include "rbuf"
00008 #include "seek"
00009 #include "date"
00010 #include "ifile"
00011 
00012 #ifdef INLIB_MEM
00013 #include "../mem"
00014 #endif
00015 
00016 #include <map>
00017 #include <ostream>
00018 
00019 //#include <zlib.h>
00020 
00021 extern "C" {
00022   void csz__Init_Inflate(long,unsigned char*,long,unsigned char*);
00023   int csz__Inflate();
00024   unsigned char* csz__obufptr();
00025 }
00026 
00027 namespace inlib {
00028 namespace rroot {
00029 
00030 class key {
00031   static uint32 class_version() {return 2;}
00032 public:
00033   static uint32 std_string_record_size(const std::string& x) {
00034     // Returns size string will occupy on I/O buffer.
00035     if (x.size() > 254)
00036       return x.size()+sizeof(unsigned char)+sizeof(int);
00037     else
00038       return x.size()+sizeof(unsigned char);
00039   }
00040 
00041 public:
00042   key(ifile& a_file)
00043   :m_file(a_file)
00044   ,m_buf_size(0)
00045   ,m_buffer(0)
00046   // Record :
00047   ,m_nbytes(0)
00048   ,m_version(class_version())
00049   ,m_object_size(0)
00050   ,m_date(0)
00051   ,m_key_length(0)
00052   ,m_cycle(0)
00053   ,m_seek_key(0)
00054   ,m_seek_parent_dir(0)
00055   //,m_object_class
00056   //,m_object_name
00057   //,m_object_title
00058   {
00059 #ifdef INLIB_MEM
00060     mem::increment(s_class().c_str());
00061 #endif
00062     m_key_length = record_size(m_version);
00063     //fDate.setDate(0);
00064   }
00065 
00066   key(ifile& a_file,seek a_pos,uint32 a_nbytes)
00067   :m_file(a_file)
00068   ,m_buf_size(0)
00069   ,m_buffer(0)
00070   // Record :
00071   ,m_nbytes(a_nbytes) //key len + compressed object size
00072   ,m_version(class_version())
00073   ,m_object_size(0)
00074   ,m_date(0)
00075   ,m_key_length(0)
00076   ,m_cycle(0)
00077   ,m_seek_key(a_pos)
00078   ,m_seek_parent_dir(0)
00079   //,m_object_class
00080   //,m_object_name
00081   //,m_object_title
00082   {
00083 #ifdef INLIB_MEM
00084     mem::increment(s_class().c_str());
00085 #endif
00086     if(a_pos>START_BIG_FILE) m_version += 1000;
00087     m_buffer = new char[a_nbytes];
00088     if(!m_buffer) {
00089       m_file.out() << "inlib::rroot::key::key(cpcstor) :"
00090                    << " can't alloc " << a_nbytes << "." 
00091                    << std::endl;
00092     } else {
00093       m_buf_size = a_nbytes;
00094     }
00095   }
00096   virtual ~key(){
00097     delete [] m_buffer;
00098 #ifdef INLIB_MEM
00099     mem::decrement(s_class().c_str());
00100 #endif
00101   }
00102 protected:
00103   key(const key& a_from)
00104   :m_file(a_from.m_file)
00105   ,m_buf_size(0)
00106   ,m_buffer(0)
00107   ,m_nbytes(a_from.m_nbytes)
00108   ,m_version(a_from.m_version)
00109   ,m_object_size(a_from.m_object_size)
00110   ,m_date(a_from.m_date)
00111   ,m_key_length(a_from.m_key_length)
00112   ,m_cycle(a_from.m_cycle)
00113   ,m_seek_key(a_from.m_seek_key)
00114   ,m_seek_parent_dir(a_from.m_seek_parent_dir)
00115   ,m_object_class(a_from.m_object_class)
00116   ,m_object_name(a_from.m_object_name)
00117   ,m_object_title(a_from.m_object_title)
00118   {
00119 #ifdef INLIB_MEM
00120     mem::increment(s_class().c_str());
00121 #endif
00122     if(a_from.m_buf_size && a_from.m_buffer) {
00123       m_buffer = new char[a_from.m_buf_size];
00124       if(!m_buffer) {
00125         m_file.out() << "inlib::rroot::key::key(cpcstor) :"
00126                      << " can't alloc " << a_from.m_buf_size << "." 
00127                      << std::endl;
00128       } else {
00129         m_buf_size = a_from.m_buf_size;
00130         ::memcpy(m_buffer,a_from.m_buffer,a_from.m_buf_size);
00131       }
00132     }
00133   }
00134 public:
00135   key& operator=(const key& a_from){
00136     m_nbytes = a_from.m_nbytes;
00137     m_version = a_from.m_version;
00138     m_object_size = a_from.m_object_size;
00139     m_date = a_from.m_date;
00140     m_key_length = a_from.m_key_length;
00141     m_cycle = a_from.m_cycle;
00142     m_seek_key = a_from.m_seek_key;
00143     m_seek_parent_dir = a_from.m_seek_parent_dir;
00144     m_object_class = a_from.m_object_class;
00145     m_object_name = a_from.m_object_name;
00146     m_object_title = a_from.m_object_title;
00147 
00148     delete [] m_buffer;
00149     m_buffer = 0;
00150     m_buf_size = 0;
00151 
00152     if(a_from.m_buf_size && a_from.m_buffer) {
00153       m_buffer = new char[a_from.m_buf_size];
00154       if(!m_buffer) {
00155         m_file.out() << "inlib::rroot::key::operator=() :"
00156                      << " can't alloc " << a_from.m_buf_size << "." 
00157                      << std::endl;
00158       } else {
00159         m_buf_size = a_from.m_buf_size;
00160         ::memcpy(m_buffer,a_from.m_buffer,a_from.m_buf_size);
00161       }
00162     }
00163 
00164     return *this;
00165   }
00166 
00167 public:
00168   ifile& file() {return m_file;}
00169 
00170   uint32 nbytes() const {return m_nbytes;}
00171   seek seek_key() const {return m_seek_key;}
00172   uint32 object_size() const {return m_object_size;}
00173 
00174   const std::string& object_name() const {return m_object_name;}
00175   std::string object_name() {return m_object_name;}
00176 
00177   const std::string& object_title() const {return m_object_title;}
00178   std::string object_title() {return m_object_title;}
00179 
00180   const std::string& object_class() const {return m_object_class;}
00181   std::string object_class() {return m_object_class;}
00182 
00183   bool read_file(){
00184     // Read the key structure from the file.
00185     if(!m_file.set_pos(m_seek_key)) return false;
00186     if(!m_file.read_buffer(m_buffer,m_nbytes)) return false;
00187     if(m_file.verbose()) {
00188       m_file.out() << "inlib::rroot::key::read_file :"
00189                    << " reading " << m_nbytes << " bytes"
00190                    << " at position " << m_seek_key
00191                    << "." 
00192                    << std::endl;
00193     }
00194     return true;
00195   }
00196 
00197   char* buf() const {return m_buffer;}
00198   char* data_buffer() const {return m_buffer + m_key_length;}
00199   const char* eob() const {return m_buffer + m_buf_size;}
00200   uint32 buf_size() const {return m_buf_size;}
00201   uint32 key_length() const {return m_key_length;}
00202 
00203   bool from_buffer(const char* aEOB,char*& a_pos) {
00204     rbuf rb(m_file.out(),m_file.byte_swap(),aEOB,a_pos);
00205     int nbytes;
00206     if(!rb.read(nbytes)) return false;
00207 /*
00208     if(m_nbytes) {
00209       if(nbytes!=int(m_nbytes)) {
00210         out << "inlib::rroot::key::from_buffer :"
00211             << " nbytes not consistent."
00212             << " read " << nbytes
00213             << ", expected " << m_nbytes
00214             << ". Continue with " << nbytes
00215             << std::endl;
00216         m_nbytes = nbytes;
00217       }
00218     } else {
00219 */
00220     m_nbytes = nbytes;
00221     //}
00222     short version;
00223     if(!rb.read(version)) return false;
00224     m_version = version;
00225    {int v;
00226     if(!rb.read(v)) return false;
00227     m_object_size = v;}
00228     unsigned int date;
00229     if(!rb.read(date)) return false;
00230     //fDate.setDate(date);
00231    {short v;
00232     if(!rb.read(v)) return false;
00233     m_key_length = v;}
00234    {short v;
00235     if(!rb.read(v)) return false;
00236     m_cycle = v;}
00237     if(version>1000) {
00238       if(!rb.read(m_seek_key)) return false;
00239       if(!rb.read(m_seek_parent_dir)) return false;
00240     } else {
00241      {seek32 i;
00242       if(!rb.read(i)) return false;
00243       m_seek_key = i;}    
00244      {seek32 i;
00245       if(!rb.read(i)) return false;
00246       m_seek_parent_dir = i;}
00247     }
00248     if(!rb.read(m_object_class)) return false;
00249     if(!rb.read(m_object_name)) return false;
00250     if(!rb.read(m_object_title)) return false;
00251     if(m_file.verbose()) {
00252       m_file.out() << "inlib::rroot::key::from_buffer :"
00253                    << " nbytes : " << m_nbytes
00254                    << ", object class : " << sout(m_object_class)
00255                    << ", object name : " << sout(m_object_name)
00256                    << ", object title : " << sout(m_object_title)
00257                    << ", object size : " << m_object_size
00258                    << "." 
00259                    << std::endl;
00260     }
00261     return true;
00262   }
00263 
00264   char* get_object_buffer(uint32& a_size) {
00265     if(!m_key_length) {
00266       m_file.out() << "inlib::rroot::key::get_object_buffer :" 
00267                    << " WARNING : m_key_length is zero."
00268                    << std::endl;
00269       //delete [] m_buffer;
00270       //m_buffer = 0;
00271       //m_buf_size = 0;
00272       //a_size = 0;
00273       //return 0;
00274     }
00275     if(!m_nbytes) {
00276       m_file.out() << "inlib::rroot::key::get_object_buffer :" 
00277                    << " m_nbytes is zero."
00278                    << std::endl;
00279       delete [] m_buffer;
00280       m_buffer = 0;
00281       m_buf_size = 0;
00282       a_size = 0;
00283       return 0;
00284     }
00285     if(!m_object_size) {
00286       m_file.out() << "inlib::rroot::key::get_object_buffer :" 
00287                    << " WARNING : m_object_size is zero."
00288                    << std::endl;
00289     }
00290 
00291     if(m_file.verbose()) {
00292       m_file.out() << "inlib::rroot::key::get_object_buffer :" 
00293                    << " m_nbytes : " << m_nbytes
00294                    << " m_key_length : " << m_key_length
00295                    << " m_object_size : " << m_object_size << "."
00296                    << " m_seek_key : " << m_seek_key << "."
00297                    << std::endl;
00298     }
00299 
00300     if(m_object_size <= (m_nbytes-m_key_length)) {
00301       delete [] m_buffer;
00302       m_buf_size = m_key_length+m_object_size;
00303       if(m_buf_size<m_nbytes) {
00304         m_file.out() << "inlib::rroot::key::get_object_buffer :" 
00305                      << " WARNING : m_buf_size<m_nbytes."
00306                      << " m_buf_size " << m_buf_size
00307                      << " m_nbytes " << m_nbytes
00308                      << ". Raise m_buf_size to " << m_nbytes << "."
00309                      << std::endl;
00310         m_buf_size = m_nbytes; //for read_file()
00311       }
00312       m_buffer = new char[m_buf_size];
00313       if(!m_buffer) {
00314         m_file.out() << "inlib::rroot::key::get_object_buffer :" 
00315                      << " can't alloc " << m_buf_size
00316                      << std::endl;
00317         m_buffer = 0;
00318         m_buf_size = 0;
00319         a_size = 0;
00320         return 0;
00321       }
00322 
00323       if(!read_file()) {
00324         delete [] m_buffer;
00325         m_buffer = 0;
00326         m_buf_size = 0;
00327         a_size = 0;
00328         return 0;
00329       }
00330 
00331     } else {
00332       // have to decompress. Need a second buffer.
00333 
00334       uint32 decsiz = m_key_length+m_object_size;
00335       char* decbuf = new char[decsiz];
00336       if(!decbuf) {
00337         m_file.out() << "inlib::rroot::key::get_object_buffer :" 
00338                      << " can't alloc " << decsiz
00339                      << std::endl;
00340         a_size = 0;
00341         return 0;
00342       }
00343 
00344       delete [] m_buffer;
00345       m_buffer = new char[m_nbytes];
00346       m_buf_size = m_nbytes;
00347       if(!read_file()) {
00348         delete [] decbuf;
00349         decbuf = 0;
00350         delete [] m_buffer;
00351         m_buffer = 0;
00352         m_buf_size = 0;
00353         a_size = 0;
00354         return 0;
00355       }
00356 
00357       ::memcpy(decbuf,m_buffer,m_key_length);
00358 
00359       // decompress :
00360       unsigned char* objbuf = (unsigned char*)(decbuf+m_key_length);
00361       unsigned char* bufcur = (unsigned char*)(m_buffer+m_key_length);
00362       int nout = 0;
00363       uint32 noutot = 0;
00364       while(true) {
00365         int nin  = 
00366          9 + ((int)bufcur[3] | ((int)bufcur[4] << 8) | ((int)bufcur[5] << 16));
00367         int nbuf = 
00368           (int)bufcur[6] | ((int)bufcur[7] << 8) | ((int)bufcur[8] << 16);
00369         if(!unzip(m_file.out(),nin,bufcur, nbuf,objbuf, nout)) break;
00370         if(!nout) break;
00371         noutot += nout;
00372         if(noutot >= m_object_size) break;
00373         bufcur += nin;
00374         objbuf += nout;
00375       }
00376 
00377       delete [] m_buffer;
00378       m_buffer = 0;
00379       m_buf_size = 0;
00380 
00381       if(!noutot) {
00382         m_file.out() << "inlib::rroot::key::get_object_buffer :"
00383                      << " nothing from decompression."
00384                      << std::endl;
00385         delete [] decbuf;
00386         decbuf = 0;
00387         a_size = 0;
00388         return 0;
00389       }
00390       if(noutot!=m_object_size) {
00391         m_file.out() << "inlib::rroot::key::get_object_buffer :" 
00392                      << " decompression mismatch."
00393                      << " noutot " << noutot
00394                      << " m_object_size " << m_object_size
00395                      << std::endl;
00396         delete [] decbuf;
00397         decbuf = 0;
00398         a_size = 0;
00399         return 0;
00400       }
00401 
00402       m_buffer = decbuf;
00403       m_buf_size = decsiz;
00404 
00405     }
00406     a_size = m_object_size;
00407     return m_buffer+m_key_length;
00408   }
00409   //NOTE : print is a Python keyword.
00410   void dump(std::ostream& a_out) const {
00411     a_out << "class : " << sout(m_object_class)
00412           << ", name : " << sout(m_object_name)
00413           << ", title : " << sout(m_object_title)
00414           << ", size : " << m_object_size
00415           << "." 
00416           << std::endl;
00417   }
00418 
00419 protected:
00420   static const uint32 START_BIG_FILE = 2000000000;
00421 protected:
00422   uint32 record_size(uint32 a_version) const {
00423     // Return the size in bytes of the key header structure.
00424     uint32 nbytes = sizeof(m_nbytes);
00425     nbytes += sizeof(short);         //2
00426     nbytes += sizeof(m_object_size);
00427     nbytes += sizeof(date);
00428     nbytes += sizeof(m_key_length);
00429     nbytes += sizeof(m_cycle);       //2+4*4=18
00430     if(a_version>1000) {
00431       nbytes += sizeof(seek);
00432       nbytes += sizeof(seek);        //18+2*8=34
00433     } else {
00434       nbytes += sizeof(seek32); 
00435       nbytes += sizeof(seek32);      //18+2*4=26
00436     }
00437     nbytes += std_string_record_size(m_object_class);
00438     nbytes += std_string_record_size(m_object_name);
00439     nbytes += std_string_record_size(m_object_title);
00440     //::printf("debug : record_size %d\n",nbytes);   
00441     return nbytes;
00442   }
00443   static std::string sout(const std::string& a_string) {
00444     return std::string("\"")+a_string+"\"";
00445   }
00446 
00447   bool unzip(std::ostream& a_out,
00448                            int a_srcsize,unsigned char* a_src,
00449                            int a_tgtsize,unsigned char* a_tgt,
00450                            int& a_irep) {
00451 
00452     // Author: E.Chernyaev (IHEP/Protvino)
00453     // Input: scrsize - size of input buffer
00454     //       src     - input buffer
00455     //       tgtsize - size of target buffer
00456     //
00457     // Output: tgt - target buffer (decompressed)
00458     //        irep - size of decompressed data
00459     //        0 - if error
00460 
00461     a_irep = 0;
00462 
00463     // C H E C K   H E A D E R
00464     const int HDRSIZE = 9;
00465 
00466     if (a_srcsize < HDRSIZE) {
00467       a_out << "inlib::rroot::key::unzip : too small source" << std::endl;
00468       return false;
00469     }
00470 
00471     unsigned char DEFLATE = 8;
00472 
00473     if ((a_src[0] != 'C' && a_src[0] != 'Z') ||
00474         (a_src[1] != 'S' && a_src[1] != 'L') ||
00475         a_src[2] != DEFLATE) {
00476       a_out << "inlib::rroot::key::unzip : error in header" << std::endl;
00477       return false;
00478     }
00479 
00480     long _ibufcnt = 
00481       (long)a_src[3] | ((long)a_src[4] << 8) | ((long)a_src[5] << 16);
00482     long isize = 
00483       (long)a_src[6] | ((long)a_src[7] << 8) | ((long)a_src[8] << 16);
00484 
00485     if(a_tgtsize<isize) {
00486       a_out << "inlib::rroot::key::unzip : too small target." << std::endl;
00487       return false;
00488     }
00489 
00490     if(_ibufcnt + HDRSIZE != a_srcsize) {
00491       a_out << "inlib::rroot::key::unzip :"
00492             << " discrepancy in source length." << std::endl;
00493       return false;
00494     }
00495 
00496     // D E C O M P R E S S   D A T A
00497 
00498     if (a_src[0] == 'Z' && a_src[1] == 'L') { //compressed with zlib.
00499       ifile::unzip_func func;
00500       if(!m_file.unziper('Z',func)) {
00501         a_out << "inlib::rroot::key::unzip : "
00502               << " zlib unziper not found." << std::endl;
00503         return false;
00504       }
00505   
00506       if(!func(a_out,a_srcsize,a_src + HDRSIZE,a_tgtsize,a_tgt,a_irep)) {
00507         a_out << "inlib::rroot::key::unzip : "
00508               << " unzip function failed." << std::endl;
00509         return false;
00510       }
00511 
00512     } else if (a_src[0] == 'C' && a_src[1] == 'S') {
00513       //compressed with Chernyaev & Smirnov
00514       
00515       csz__Init_Inflate(_ibufcnt,a_src + HDRSIZE,a_tgtsize,a_tgt);
00516 
00517       if (csz__Inflate()) {
00518         a_out << "inlib::rroot::key::unzip :"
00519               << " error during decompression." << std::endl;
00520         return false;
00521       }
00522 
00523       unsigned char* obufptr = csz__obufptr();
00524 
00525       // if (obufptr - a_tgt != isize) {
00526       // There are some rare cases when a few more bytes are required
00527       if (obufptr - a_tgt > a_tgtsize) {
00528         a_out << "inlib::rroot::key::_unzip :"
00529               << " discrepancy " << (int)(obufptr - a_tgt)
00530               << " with initial size: " << (int)isize
00531               << ", tgtsize= " << a_tgtsize
00532               << std::endl;
00533         a_irep = obufptr - a_tgt;
00534         //return false;
00535       }
00536       a_irep = isize;
00537 
00538       //a_out << "inlib::rroot::key::unzip : CS : ok "
00539       //        << a_irep << std::endl;
00540 
00541     } else {
00542       a_out << "inlib::rroot::key::_unzip : unknown a_src[0,1]."
00543             << " [0] = " << a_src[0] << ", [1] = " << a_src[1]
00544             << std::endl;
00545       a_irep = 0;
00546       return false;
00547     }
00548     return true;
00549   }
00550 
00551   static const std::string& s_class() {
00552     static const std::string s_v("inlib::rroot::key");
00553     return s_v;
00554   }
00555 protected:
00556   ifile& m_file;
00557   uint32 m_buf_size;
00558   char* m_buffer;
00559   // Record (stored in file) :
00560   uint32 m_nbytes;               //Number of bytes for the object on file
00561   uint32 m_version;              //Key version identifier
00562   uint32 m_object_size;          //Length of uncompressed object in bytes
00563   date m_date;                //Date/Time of insertion in file
00564   uint16 m_key_length;         //Number of bytes for the key itself
00565   uint16 m_cycle;              //Cycle number
00566   seek m_seek_key;            //Location of object on file
00567   seek m_seek_parent_dir;     //Location of parent directory on file
00568   std::string m_object_class; //Object Class name.
00569   std::string m_object_name;  //name of the object.
00570   std::string m_object_title; //title of the object.
00571 };
00572 
00573 }}
00574 
00575 #endif
00576 
00577 //doc :
00579 //                                                                      //
00580 //  The Key class includes functions to book space on a file,           //
00581 //   to create I/O buffers, to fill these buffers                       //
00582 //   to compress/uncompress data buffers.                               //
00583 //                                                                      //
00584 //  Before saving (making persistent) an object on a file, a key must   //
00585 //  be created. The key structure contains all the information to       //
00586 //  uniquely identify a persistent object on a file.                    //
00587 //     fNbytes    = number of bytes for the compressed object+key       //
00588 //     version of the Key class                                         //
00589 //     fObjlen    = Length of uncompressed object                       //
00590 //     fDatime    = Date/Time when the object was written               //
00591 //     fKeylen    = number of bytes for the key structure               //
00592 //     fCycle     = cycle number of the object                          //
00593 //     fSeekKey   = Address of the object on file (points to fNbytes)   //
00594 //                  This is a redundant information used to cross-check //
00595 //                  the data base integrity.                            //
00596 //     fSeekPdir  = Pointer to the directory supporting this object     //
00597 //     fClassName = Object class name                                   //
00598 //     fName      = name of the object                                  //
00599 //     fTitle     = title of the object                                 //
00600 //                                                                      //
00601 //  The Key class is used by ROOT to:                                   //
00602 //    - to write an object in the Current Directory                     //
00603 //    - to write a new ntuple buffer                                    //
00604 //                                                                      //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines