Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_wroot_key 5 #define tools_wroot_key 6 7 #include "seek" 8 #include "date" 9 #include "ifile" 10 #include "wbuf" 11 #include "../sout" 12 13 #ifdef TOOLS_MEM 14 #include "../mem" 15 #endif 16 17 #include <ostream> 18 19 namespace tools { 20 namespace wroot { 21 22 class key { 23 static uint32 class_version() {return 2;} 24 static const std::string& s_class() { 25 static const std::string s_v("tools::wroot::key"); 26 return s_v; 27 } 28 public: 29 static unsigned int std_string_record_size(const std::string& x) { 30 // Returns size string will occupy on I/O buffer. 31 if (x.size() > 254) 32 return uint32(x.size()+sizeof(unsigned char)+sizeof(int)); 33 else 34 return uint32(x.size()+sizeof(unsigned char)); 35 } 36 public: 37 key(std::ostream& a_out, 38 seek a_seek_directory, 39 const std::string& a_object_name, 40 const std::string& a_object_title, 41 const std::string& a_object_class) //for basket cstor. 42 :m_out(a_out) 43 ,m_buf_size(0) 44 ,m_buffer(0) 45 // Record : 46 ,m_nbytes(0) 47 ,m_version(class_version()) 48 ,m_object_size(0) 49 ,m_date(0) 50 ,m_key_length(0) 51 ,m_cycle(0) 52 ,m_seek_key(0) 53 ,m_seek_directory(0) 54 ,m_object_class(a_object_class) 55 ,m_object_name(a_object_name) 56 ,m_object_title(a_object_title) 57 { 58 #ifdef TOOLS_MEM 59 mem::increment(s_class().c_str()); 60 #endif 61 62 if(a_seek_directory>START_BIG_FILE()) m_version += big_file_version_tag(); 63 64 m_key_length = record_size(m_version); 65 66 initialize_zero(); 67 68 m_seek_directory = a_seek_directory; 69 } 70 71 key(std::ostream& a_out, 72 ifile& a_file, 73 seek a_seek_directory, 74 const std::string& a_object_name, 75 const std::string& a_object_title, 76 const std::string& a_object_class, 77 uint32 a_object_size) //uncompressed data size. 78 :m_out(a_out) 79 ,m_buf_size(0) 80 ,m_buffer(0) 81 // Record : 82 ,m_nbytes(0) 83 ,m_version(class_version()) 84 ,m_object_size(a_object_size) 85 ,m_date(0) 86 ,m_key_length(0) 87 ,m_cycle(0) 88 ,m_seek_key(0) 89 ,m_seek_directory(0) 90 ,m_object_class(a_object_class) 91 ,m_object_name(a_object_name) 92 ,m_object_title(a_object_title) 93 { 94 #ifdef TOOLS_MEM 95 mem::increment(s_class().c_str()); 96 #endif 97 98 if(a_object_size) { 99 if(a_file.END()>START_BIG_FILE()) m_version += big_file_version_tag(); 100 } 101 if(m_version>big_file_version_tag()) { 102 } else { 103 if(a_seek_directory>START_BIG_FILE()) m_version += big_file_version_tag(); 104 } 105 106 m_key_length = record_size(m_version); 107 108 initialize(a_file,a_object_size); 109 110 m_seek_directory = a_seek_directory; 111 } 112 virtual ~key(){ 113 delete [] m_buffer; 114 #ifdef TOOLS_MEM 115 mem::decrement(s_class().c_str()); 116 #endif 117 } 118 protected: 119 key(const key& a_from):m_out(a_from.m_out){ 120 #ifdef TOOLS_MEM 121 mem::increment(s_class().c_str()); 122 #endif 123 } 124 key& operator=(const key &){return *this;} 125 public: 126 uint16 cycle() const {return m_cycle;} 127 void set_cycle(uint16 a_cycle) {m_cycle = a_cycle;} 128 129 const std::string& object_name() const {return m_object_name;} 130 const std::string& object_title() const {return m_object_title;} 131 const std::string& object_class() const {return m_object_class;} 132 133 bool write_self(ifile& a_file) { 134 char* buffer = m_buffer; 135 wbuf wb(m_out,a_file.byte_swap(),eob(),buffer); 136 return to_buffer(wb,a_file.verbose()); 137 } 138 139 bool write_file(ifile& a_file,uint32& a_nbytes) { 140 if(!a_file.set_pos(m_seek_key)) { 141 a_nbytes = 0; 142 return false; 143 } 144 if(!a_file.write_buffer(m_buffer,m_nbytes)) { 145 a_nbytes = 0; 146 return false; 147 } 148 149 if(a_file.verbose()) { 150 m_out << "tools::wroot::key::write_file :" 151 << " writing " << m_nbytes << " bytes" 152 << " at address " << m_seek_key 153 << " for ID=" << sout(m_object_name) 154 << " Title=" << sout(m_object_title) << "." 155 << std::endl; 156 } 157 158 delete [] m_buffer; //??? 159 m_buffer = 0; 160 m_buf_size = 0; 161 162 a_nbytes = m_nbytes; 163 return true; 164 } 165 166 void set_number_of_bytes(uint32 a_n) {m_nbytes = a_n;} 167 uint32 number_of_bytes() const {return m_nbytes;} 168 169 uint32 object_size() const {return m_object_size;} 170 171 seek seek_key() const {return m_seek_key;} 172 short key_length() const {return m_key_length;} 173 174 char* data_buffer() {return m_buffer + m_key_length;} 175 const char* eob() const {return m_buffer + m_buf_size;} 176 177 bool to_buffer(wbuf& a_wb,bool a_verbose) const { 178 if(!a_wb.write(m_nbytes)) return false; 179 short version = m_version; 180 if(!a_wb.write(version)) return false; 181 if(!a_wb.write(m_object_size)) return false; 182 unsigned int _date = 0; //FIXME 183 if(!a_wb.write(_date)) return false; 184 if(!a_wb.write(m_key_length)) return false; 185 if(!a_wb.write(m_cycle)) return false; 186 if(version>(short)big_file_version_tag()) { 187 if(!a_wb.write(m_seek_key)) return false; 188 if(!a_wb.write(m_seek_directory)) return false; 189 } else { 190 if(m_seek_key>START_BIG_FILE()) { 191 m_out << "tools::wroot::key::to_buffer :" 192 << " attempt to write big seek " 193 << m_seek_key << " on 32 bits." 194 << std::endl; 195 return false; 196 } 197 if(!a_wb.write((seek32)m_seek_key)) return false; 198 if(m_seek_directory>START_BIG_FILE()) { 199 m_out << "tools::wroot::key::to_buffer :" 200 << " (2) attempt to write big seek " 201 << m_seek_directory << " on 32 bits." 202 << std::endl; 203 return false; 204 } 205 if(!a_wb.write((seek32)m_seek_directory)) return false; 206 } 207 if(!a_wb.write(m_object_class)) return false; 208 if(!a_wb.write(m_object_name)) return false; 209 if(!a_wb.write(m_object_title)) return false; 210 if(a_verbose) { 211 m_out << "tools::wroot::key::to_buffer :" 212 << " nbytes : " << m_nbytes 213 << ", object class : " << sout(m_object_class) 214 << ", object name : " << sout(m_object_name) 215 << ", object title : " << sout(m_object_title) 216 << ", object size : " << m_object_size 217 << "." 218 << std::endl; 219 } 220 return true; 221 } 222 223 protected: 224 uint32 record_size(uint32 a_version) const { 225 // Return the size in bytes of the key header structure. 226 uint32 nbytes = sizeof(m_nbytes); 227 nbytes += sizeof(short); 228 nbytes += sizeof(m_object_size); 229 nbytes += sizeof(date); 230 nbytes += sizeof(m_key_length); 231 nbytes += sizeof(m_cycle); 232 if(a_version>big_file_version_tag()) { 233 nbytes += sizeof(seek); 234 nbytes += sizeof(seek); 235 } else { 236 nbytes += sizeof(seek32); 237 nbytes += sizeof(seek32); 238 } 239 nbytes += std_string_record_size(m_object_class); 240 nbytes += std_string_record_size(m_object_name); 241 nbytes += std_string_record_size(m_object_title); 242 return nbytes; 243 } 244 245 bool initialize_zero() { 246 uint32 nsize = m_key_length; 247 m_date = get_date(); 248 m_seek_key = 0; 249 delete [] m_buffer; 250 m_buffer = new char[nsize]; 251 m_buf_size = nsize; 252 m_nbytes = nsize; 253 return true; 254 } 255 bool initialize(ifile& a_file,uint32 a_nbytes) { 256 uint32 nsize = m_key_length+a_nbytes; 257 258 m_date = get_date(); 259 260 if(a_nbytes) {//GB 261 m_seek_key = a_file.END(); 262 a_file.set_END(m_seek_key+nsize); 263 264 //NOTE : the free segment logic found in CERN-ROOT/TKey 265 // is not yet needed right now for us, since 266 // we always write at end of file. The update 267 // of the eof free_seg is done in set_END. 268 } else { //basket 269 m_seek_key = 0; 270 } 271 272 delete [] m_buffer; 273 m_buffer = new char[nsize]; 274 m_buf_size = nsize; 275 m_nbytes = nsize; 276 277 return true; 278 } 279 protected: 280 std::ostream& m_out; 281 uint32 m_buf_size; 282 char* m_buffer; 283 // Record (stored in file) : 284 uint32 m_nbytes; //Number of bytes for the object on file 285 uint32 m_version; //Key version identifier 286 uint32 m_object_size; //Length of uncompressed object in bytes 287 date m_date; //Date/Time of insertion in file 288 uint16 m_key_length; //Number of bytes for the key itself 289 uint16 m_cycle; //Cycle number 290 seek m_seek_key; //Location of object on file 291 seek m_seek_directory; //Location of parent directory on file 292 std::string m_object_class; //Object Class name. 293 std::string m_object_name; //name of the object. 294 std::string m_object_title; //title of the object. 295 }; 296 297 }} 298 299 #endif 300 301 //doc : 302 ////////////////////////////////////////////////////////////////////////// 303 // // 304 // The Key class includes functions to book space on a file, // 305 // to create I/O buffers, to fill these buffers // 306 // to compress/uncompress data buffers. // 307 // // 308 // Before saving (making persistent) an object on a file, a key must // 309 // be created. The key structure contains all the information to // 310 // uniquely identify a persistent object on a file. // 311 // fNbytes = number of bytes for the compressed object+key // 312 // version of the Key class // 313 // fObjlen = Length of uncompressed object // 314 // fDatime = Date/Time when the object was written // 315 // fKeylen = number of bytes for the key structure // 316 // fCycle = cycle number of the object // 317 // fSeekKey = Address of the object on file (points to fNbytes) // 318 // This is a redundant information used to cross-check // 319 // the data base integrity. // 320 // fSeekPdir = Pointer to the directory supporting this object // 321 // fClassName = Object class name // 322 // fName = name of the object // 323 // fTitle = title of the object // 324 // // 325 // The Key class is used by ROOT to: // 326 // - to write an object in the Current Directory // 327 // - to write a new ntuple buffer // 328 // // 329 //////////////////////////////////////////////////////////////////////////