Warning, /include/Geant4/tools/wroot/basket is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_wroot_basket
0005 #define tools_wroot_basket
0006
0007 #include "ibo"
0008 #include "key"
0009 #include "buffer"
0010
0011 namespace tools {
0012 namespace wroot {
0013
0014 class basket : public virtual ibo, public key {
0015 typedef key parent;
0016 public:
0017 static const std::string& s_class() {
0018 static const std::string s_v("tools::wroot::basket");
0019 return s_v;
0020 }
0021 public: //ibo
0022 virtual const std::string& store_cls() const {
0023 static const std::string s_v("TBasket");
0024 return s_v;
0025 }
0026 virtual bool stream(buffer& a_buffer) const {
0027 // in principle we pass here only for the last basket
0028 // of a branch when it is streamed from branch::stream().
0029
0030 // We pass also here in the case of filling "tree in a tree" (MEMPHYS sim).
0031
0032 // some consitency checks :
0033 //G.Barrand : the below test is "too much". Someone
0034 // may have to write a tree (and then a basket)
0035 // which had been never filled.
0036 // Moreover with the today branch code, a
0037 // basket.write_on_file()
0038 // happens only in a branch.fill() that deletes
0039 // the basket just after the call.
0040 //if(!m_data.length()) {
0041 // // to be sure to not work on a basket already written
0042 // // with write_on_file()
0043 // m_out << "tools::wroot::basket::stream :"
0044 // << " m_data.length() is null."
0045 // << std::endl;
0046 // return false;
0047 //}
0048 if(m_seek_key) {
0049 m_out << "tools::wroot::basket::stream :"
0050 << " m_seek_key is not null (" << m_seek_key << ")."
0051 << std::endl;
0052 return false;
0053 }
0054 if(m_last) {
0055 m_out << "tools::wroot::basket::stream :"
0056 << " m_last is not null."
0057 << std::endl;
0058 return false;
0059 }
0060 if(!m_entry_offset) {
0061 m_out << "tools::wroot::basket::stream :"
0062 << " m_entry_offset is null."
0063 << std::endl;
0064 return false;
0065 }
0066
0067 {uint32 _last = m_data.length()+m_key_length;
0068 if(_last>m_last) {
0069 const_cast<basket&>(*this).m_last = _last;
0070 }}
0071 if(m_last>m_buf_size) {
0072 const_cast<basket&>(*this).m_buf_size = m_last;
0073 }
0074
0075 char flag = 11;
0076 if(m_displacement) flag += 40;
0077 if(!_stream_header(a_buffer,m_verbose,flag)) return false;
0078
0079 if(m_entry_offset && m_nev) {
0080 if(!a_buffer.write_array(m_entry_offset,m_nev)) return false;
0081 if(m_displacement) {
0082 if(!a_buffer.write_array(m_displacement,m_nev)) return false;
0083 }
0084 }
0085
0086 if(m_data.to_displace()) {
0087 if(!const_cast<basket&>(*this).m_data.displace_mapped(m_key_length)) {
0088 m_out << "tools::wroot::basket::stream :"
0089 << " m_data.displace_mapped() failed."
0090 << std::endl;
0091 return false;
0092 }
0093 }
0094
0095 buffer bref(m_out,a_buffer.byte_swap(),256);
0096 if(!_stream_header(bref,m_verbose)) return false; //then header stored twice !
0097 //if(bref.length()!=m_key_length) {}
0098 if(!bref.write_fast_array(m_data.buf(),m_data.length())) return false;
0099 if(!a_buffer.write_fast_array(bref.buf(),bref.length())) return false;
0100
0101 return true;
0102 }
0103 public:
0104 basket(std::ostream& a_out,
0105 bool a_byte_swap,
0106 seek a_seek_directory,
0107 const std::string& a_object_name,
0108 const std::string& a_object_title,
0109 const std::string& a_object_class,
0110 uint32 a_basket_size,bool a_verbose)
0111 :parent(a_out,a_seek_directory,a_object_name,a_object_title,a_object_class)
0112 ,m_verbose(a_verbose)
0113 ,m_data(a_out,a_byte_swap,a_basket_size)
0114 ,m_nev_buf_size(1000)
0115 ,m_nev(0)
0116 ,m_last(0)
0117 ,m_entry_offset(0)
0118 ,m_displacement(0)
0119 {
0120 #ifdef TOOLS_MEM
0121 mem::increment(s_class().c_str());
0122 #endif
0123
0124 if(m_version>big_file_version_tag()) {
0125 } else {
0126 // G.Barrand : April 2016 : WARNING : this is a change in the ROOT/IO format compared to CERN-ROOT/4.x :
0127 // We follow the logic found on CERN-ROOT/5.x that enforces "+1000" on all baskets.
0128 m_version += big_file_version_tag();
0129 }
0130
0131 m_key_length = header_record_size(m_version);
0132 initialize_zero();
0133
0134 if(m_nev_buf_size) {
0135 m_entry_offset = new int[m_nev_buf_size];
0136 {for(uint32 i=0;i<m_nev_buf_size;i++) m_entry_offset[i] = 0;}
0137 }
0138 }
0139 virtual ~basket(){
0140 delete [] m_entry_offset;
0141 delete [] m_displacement;
0142 m_entry_offset = 0;
0143 m_displacement = 0;
0144 #ifdef TOOLS_MEM
0145 mem::decrement(s_class().c_str());
0146 #endif
0147 }
0148 protected:
0149 basket(const basket& a_from)
0150 :ibo(a_from)
0151 ,parent(a_from)
0152 ,m_verbose(a_from.m_verbose)
0153 ,m_data(m_out,a_from.m_data.byte_swap(),256)
0154 ,m_nev_buf_size(a_from.m_nev_buf_size)
0155 ,m_nev(a_from.m_nev)
0156 ,m_last(a_from.m_last)
0157 ,m_entry_offset(0)
0158 ,m_displacement(0)
0159 {
0160 #ifdef TOOLS_MEM
0161 mem::increment(s_class().c_str());
0162 #endif
0163 }
0164 basket& operator=(const basket& a_from){
0165 parent::operator=(a_from);
0166 m_nev_buf_size = a_from.m_nev_buf_size;
0167 m_nev = a_from.m_nev;
0168 m_last = a_from.m_last;
0169 return *this;
0170 }
0171 public:
0172 const buffer& datbuf() const {return m_data;}
0173 buffer& datbuf() {return m_data;}
0174
0175 const int* entry_offset() const {return m_entry_offset;}
0176 int* entry_offset() {return m_entry_offset;}
0177
0178 const int* displacement() const {return m_displacement;}
0179 int* displacement() {return m_displacement;}
0180
0181 uint32 nev_buf_size() const {return m_nev_buf_size;}
0182 uint32 nev() const {return m_nev;}
0183 uint32 last() const {return m_last;}
0184
0185 void set_nev(uint32 a_last,uint32 a_nev_buf_size,uint32 a_nev,const int* a_entry_offset,const int* a_displacement) {
0186 m_last = a_last;
0187 m_nev_buf_size = a_nev_buf_size;
0188 m_nev = a_nev;
0189 delete [] m_entry_offset;
0190 m_entry_offset = 0;
0191 delete [] m_displacement;
0192 m_displacement = 0;
0193
0194 if(a_entry_offset && m_nev_buf_size) {
0195 m_entry_offset = new int[m_nev_buf_size];
0196 for(uint32 i=0;i<m_nev;i++) m_entry_offset[i] = a_entry_offset[i];
0197 }
0198
0199 if(a_displacement && m_nev_buf_size) {
0200 m_displacement = new int[m_nev_buf_size];
0201 for(uint32 i=0;i<m_nev;i++) m_displacement[i] = a_displacement[i];
0202 }
0203 }
0204
0205 bool update(uint32 a_offset) {
0206 if(m_entry_offset) {
0207 if((m_nev+1)>=m_nev_buf_size) { // for the +1, we follow CERN-ROOT/TBasket logic that wants to store
0208 // nev+1 elements for m_entry_offset in the write_on_file() method.
0209 uint32 newsize = mx<uint32>(10,2*m_nev_buf_size);
0210 if(!realloc<int>(m_entry_offset,newsize,m_nev_buf_size,true)){
0211 m_out << "tools::wroot::basket::update : realloc failed." << std::endl;
0212 return false;
0213 }
0214 if(m_displacement) {
0215 if(!realloc<int>(m_displacement,newsize,m_nev_buf_size,true)){
0216 m_out << "tools::wroot::basket::update : realloc failed." << std::endl;
0217 return false;
0218 }
0219 }
0220 m_nev_buf_size = newsize;
0221 }
0222 m_entry_offset[m_nev] = (int)a_offset;
0223 }
0224 m_nev++;
0225 return true;
0226 }
0227
0228 bool write_on_file(ifile& a_file,uint16 a_cycle,uint32& a_nbytes) {
0229 // write m_data buffer into file.
0230 //NOTE : m_data does not contain the key at its head.
0231 // At this point m_seek_key should be 0.
0232
0233 a_nbytes = 0;
0234
0235 if(m_seek_key) {
0236 m_out << "tools::wroot::basket::write_on_file :"
0237 << " m_seek_key should be 0 (" << m_seek_key << ")."
0238 << std::endl;
0239 return false;
0240 }
0241
0242 if(m_version>big_file_version_tag()) {
0243 } else {
0244 m_out << "tools::wroot::basket::write_on_file : "
0245 << " we should not pass here (1)."
0246 << std::endl;
0247 return false;
0248 /*
0249 if(a_file.END()>START_BIG_FILE()) {
0250 //GB : enforce m_version>big_file_version_tag() if m_version is still 2 but
0251 // seek_key>START_BIG_FILE. If not doing that we shall
0252 // write a big m_seek_key on a seek32 and then have
0253 // a problem when reading.
0254
0255 //m_out << "tools::wroot::basket::write_on_file : "
0256 // << " WARNING : pos>START_BIG_FILE."
0257 // << std::endl;
0258
0259 m_version += big_file_version_tag();
0260 m_key_length += 8;
0261
0262 if(m_entry_offset) {
0263 for(uint32 i=0;i<m_nev;i++) m_entry_offset[i] += 8;
0264 if(m_displacement) {
0265 //??? Do we have to shift them ?
0266 m_out << "tools::wroot::basket::write_on_file : "
0267 << " displace logic : m_displacement not null."
0268 << std::endl;
0269 }
0270 }
0271
0272 }
0273 */
0274 }
0275
0276 // Transfer m_entry_offset table at the end of fBuffer. Offsets to fBuffer
0277 // are transformed in entry length to optimize compression algorithm.
0278 m_last = m_key_length+m_data.length();
0279 if(m_entry_offset) {
0280 if(!m_data.write_array<int>(m_entry_offset,m_nev+1)) { // for the +1 we follow CERN-ROOT/TBasket logic.
0281 delete [] m_entry_offset;
0282 m_entry_offset = 0;
0283 return false;
0284 }
0285 delete [] m_entry_offset;
0286 m_entry_offset = 0;
0287 if(m_displacement) {
0288 if(!m_data.write_array<int>(m_displacement,m_nev+1)) {
0289 delete [] m_displacement;
0290 m_displacement = 0;
0291 return false;
0292 }
0293 delete [] m_displacement;
0294 m_displacement = 0;
0295 }
0296 }
0297
0298 m_object_size = m_data.length(); //uncompressed size.
0299
0300 m_cycle = a_cycle;
0301
0302 if(!m_data.displace_mapped(m_key_length)) return false;
0303
0304 char* kbuf = 0;
0305 uint32 klen = 0;
0306 bool kdelete = false;
0307 a_file.compress_buffer(m_data,kbuf,klen,kdelete);
0308
0309 if(klen>m_object_size) {
0310 m_out << "tools::wroot::basket::write_on_file :"
0311 << " compression anomaly "
0312 << " m_object_size " << m_object_size
0313 << " klen " << klen
0314 << std::endl;
0315 if(kdelete) delete [] kbuf;
0316 return false;
0317 }
0318
0319 if(!initialize(a_file,klen)) { //it will do a m_seek_key = a_file.END() and then a_file.set_END(...)
0320 m_out << "tools::wroot::basket::write_on_file :"
0321 << " initialize() failed."
0322 << std::endl;
0323 if(kdelete) delete [] kbuf;
0324 return false;
0325 }
0326
0327 //write header of the key :
0328 {buffer bref(m_out,a_file.byte_swap(),256);
0329 if(!_stream_header(bref,a_file.verbose())) return false;
0330 if(bref.length()!=m_key_length) {
0331 m_out << "tools::wroot::basket::write_on_file :"
0332 << " key len anomaly " << bref.length()
0333 << " m_key_length " << m_key_length
0334 << std::endl;
0335 if(kdelete) delete [] kbuf;
0336 return false;
0337 }
0338 ::memcpy(m_buffer,bref.buf(),m_key_length);}
0339
0340 ::memcpy(m_buffer+m_key_length,kbuf,klen);
0341 if(kdelete) delete [] kbuf;
0342
0343 uint32 nbytes;
0344 if(!parent::write_file(a_file,nbytes)) return false;
0345
0346 m_data.pos() = m_data.buf(); //empty m_data.
0347
0348 a_nbytes = m_key_length + klen;
0349 return true;
0350 }
0351 protected:
0352 uint32 header_record_size(uint32 a_version) const {
0353 // header only.
0354 uint32 nbytes = parent::record_size(a_version);
0355
0356 nbytes += sizeof(short); //version
0357 nbytes += sizeof(uint32); //m_buf_size
0358 nbytes += sizeof(uint32); //m_nev_buf_size
0359 nbytes += sizeof(uint32); //m_nev
0360 nbytes += sizeof(uint32); //m_last
0361 nbytes += sizeof(char); //flag
0362
0363 return nbytes;
0364 }
0365 bool _stream_header(buffer& a_buffer,bool a_verbose,char a_flag = 0) const {
0366 {uint32 l = parent::record_size(m_version);
0367 if((a_buffer.length()+l)>a_buffer.size()) {
0368 if(!a_buffer.expand(a_buffer.size()+l)) return false;
0369 }
0370 wbuf wb(m_out,a_buffer.byte_swap(),a_buffer.max_pos(),a_buffer.pos());
0371 if(!parent::to_buffer(wb,a_verbose)) return false;}
0372
0373 if(!a_buffer.write_version(2)) return false;
0374 if(!a_buffer.write(m_buf_size)) return false;
0375 if(!a_buffer.write(m_nev_buf_size)) return false;
0376 if(!a_buffer.write(m_nev)) return false;
0377 if(!a_buffer.write(m_last)) return false;
0378 if(!a_buffer.write(a_flag)) return false;
0379 return true;
0380 }
0381 protected:
0382 bool m_verbose;
0383 buffer m_data;
0384 protected:
0385 uint32 m_nev_buf_size; //Length in Int_t of m_entry_offset
0386 uint32 m_nev; //Number of entries in basket
0387 uint32 m_last; //Pointer to last used byte in basket
0388 int* m_entry_offset; //[m_nev] Offset of entries in fBuffer(TKey)
0389 int* m_displacement; //![m_nev] Displacement of entries in fBuffer(TKey)
0390 };
0391
0392 }}
0393
0394 #endif