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