g4tools  5.4.0
basket
Go to the documentation of this file.
1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
2 // See the file tools.license for terms.
3 
4 #ifndef tools_wroot_basket
5 #define tools_wroot_basket
6 
7 #include "ibo"
8 #include "key"
9 #include "buffer"
10 
11 namespace tools {
12 namespace wroot {
13 
14 class basket : public virtual ibo, public key {
15  typedef key parent;
16 public:
17  static const std::string& s_class() {
18  static const std::string s_v("tools::wroot::basket");
19  return s_v;
20  }
21 public: //ibo
22  virtual const std::string& store_cls() const {
23  static const std::string s_v("TBasket");
24  return s_v;
25  }
26  virtual bool stream(buffer& a_buffer) const {
27  // in principle we pass here only for the last basket
28  // of a branch when it is streamed from branch::stream().
29 
30  // We pass also here in the case of filling "tree in a tree" (MEMPHYS sim).
31 
32  // some consitency checks :
33  //G.Barrand : the below test is "too much". Someone
34  // may have to write a tree (and then a basket)
35  // which had been never filled.
36  // Moreover with the today branch code, a
37  // basket.write_on_file()
38  // happens only in a branch.fill() that deletes
39  // the basket just after the call.
40  //if(!m_data.length()) {
41  // // to be sure to not work on a basket already written
42  // // with write_on_file()
43  // m_out << "tools::wroot::basket::stream :"
44  // << " m_data.length() is null."
45  // << std::endl;
46  // return false;
47  //}
48  if(m_seek_key) {
49  m_out << "tools::wroot::basket::stream :"
50  << " m_seek_key is not null (" << m_seek_key << ")."
51  << std::endl;
52  return false;
53  }
54  if(m_last) {
55  m_out << "tools::wroot::basket::stream :"
56  << " m_last is not null."
57  << std::endl;
58  return false;
59  }
60  if(!m_entry_offset) {
61  m_out << "tools::wroot::basket::stream :"
62  << " m_entry_offset is null."
63  << std::endl;
64  return false;
65  }
66 
67  {uint32 _last = m_data.length()+m_key_length;
68  if(_last>m_last) {
69  const_cast<basket&>(*this).m_last = _last;
70  }}
71  if(m_last>m_buf_size) {
72  const_cast<basket&>(*this).m_buf_size = m_last;
73  }
74 
75  char flag = 11;
76  if(m_displacement) flag += 40;
77  if(!_stream_header(a_buffer,m_verbose,flag)) return false;
78 
79  if(m_entry_offset && m_nev) {
80  if(!a_buffer.write_array(m_entry_offset,m_nev)) return false;
81  if(m_displacement) {
82  if(!a_buffer.write_array(m_displacement,m_nev)) return false;
83  }
84  }
85 
86  if(m_data.to_displace()) {
87  if(!const_cast<basket&>(*this).m_data.displace_mapped(m_key_length)) {
88  m_out << "tools::wroot::basket::stream :"
89  << " m_data.displace_mapped() failed."
90  << std::endl;
91  return false;
92  }
93  }
94 
95  buffer bref(m_out,a_buffer.byte_swap(),256);
96  if(!_stream_header(bref,m_verbose)) return false; //then header stored twice !
97  //if(bref.length()!=m_key_length) {}
98  if(!bref.write_fast_array(m_data.buf(),m_data.length())) return false;
99  if(!a_buffer.write_fast_array(bref.buf(),bref.length())) return false;
100 
101  return true;
102  }
103 public:
104  basket(std::ostream& a_out,
105  bool a_byte_swap,
106  seek a_seek_directory,
107  const std::string& a_object_name,
108  const std::string& a_object_title,
109  const std::string& a_object_class,
110  uint32 a_basket_size,bool a_verbose)
111  :parent(a_out,a_seek_directory,a_object_name,a_object_title,a_object_class)
112  ,m_verbose(a_verbose)
113  ,m_data(a_out,a_byte_swap,a_basket_size)
114  ,m_nev_buf_size(1000)
115  ,m_nev(0)
116  ,m_last(0)
117  ,m_entry_offset(0)
118  ,m_displacement(0)
119  {
120 #ifdef TOOLS_MEM
121  mem::increment(s_class().c_str());
122 #endif
123 
125  } else {
126  // G.Barrand : April 2016 : WARNING : this is a change in the ROOT/IO format compared to CERN-ROOT/4.x :
127  // We follow the logic found on CERN-ROOT/5.x that enforces "+1000" on all baskets.
129  }
130 
132  initialize_zero();
133 
134  if(m_nev_buf_size) {
135  m_entry_offset = new int[m_nev_buf_size];
136  {for(uint32 i=0;i<m_nev_buf_size;i++) m_entry_offset[i] = 0;}
137  }
138  }
139  virtual ~basket(){
140  delete [] m_entry_offset;
141  delete [] m_displacement;
142  m_entry_offset = 0;
143  m_displacement = 0;
144 #ifdef TOOLS_MEM
145  mem::decrement(s_class().c_str());
146 #endif
147  }
148 protected:
149  basket(const basket& a_from)
150  :ibo(a_from)
151  ,parent(a_from)
152  ,m_verbose(a_from.m_verbose)
153  ,m_data(m_out,a_from.m_data.byte_swap(),256)
155  ,m_nev(a_from.m_nev)
156  ,m_last(a_from.m_last)
157  ,m_entry_offset(0)
158  ,m_displacement(0)
159  {
160 #ifdef TOOLS_MEM
161  mem::increment(s_class().c_str());
162 #endif
163  }
164  basket& operator=(const basket& a_from){
165  parent::operator=(a_from);
167  m_nev = a_from.m_nev;
168  m_last = a_from.m_last;
169  return *this;
170  }
171 public:
172  const buffer& datbuf() const {return m_data;}
173  buffer& datbuf() {return m_data;}
174 
175  const int* entry_offset() const {return m_entry_offset;}
176  int* entry_offset() {return m_entry_offset;}
177 
178  const int* displacement() const {return m_displacement;}
179  int* displacement() {return m_displacement;}
180 
182  uint32 nev() const {return m_nev;}
183  uint32 last() const {return m_last;}
184 
185  void set_nev(uint32 a_last,uint32 a_nev_buf_size,uint32 a_nev,const int* a_entry_offset,const int* a_displacement) {
186  m_last = a_last;
187  m_nev_buf_size = a_nev_buf_size;
188  m_nev = a_nev;
189  delete [] m_entry_offset;
190  m_entry_offset = 0;
191  delete [] m_displacement;
192  m_displacement = 0;
193 
194  if(a_entry_offset && m_nev_buf_size) {
195  m_entry_offset = new int[m_nev_buf_size];
196  for(uint32 i=0;i<m_nev;i++) m_entry_offset[i] = a_entry_offset[i];
197  }
198 
199  if(a_displacement && m_nev_buf_size) {
200  m_displacement = new int[m_nev_buf_size];
201  for(uint32 i=0;i<m_nev;i++) m_displacement[i] = a_displacement[i];
202  }
203  }
204 
205  bool update(uint32 a_offset) {
206  if(m_entry_offset) {
207  if((m_nev+1)>=m_nev_buf_size) { // for the +1, we follow CERN-ROOT/TBasket logic that wants to store
208  // nev+1 elements for m_entry_offset in the write_on_file() method.
209  uint32 newsize = mx<uint32>(10,2*m_nev_buf_size);
210  if(!realloc<int>(m_entry_offset,newsize,m_nev_buf_size,true)){
211  m_out << "tools::wroot::basket::update : realloc failed." << std::endl;
212  return false;
213  }
214  if(m_displacement) {
215  if(!realloc<int>(m_displacement,newsize,m_nev_buf_size,true)){
216  m_out << "tools::wroot::basket::update : realloc failed." << std::endl;
217  return false;
218  }
219  }
220  m_nev_buf_size = newsize;
221  }
222  m_entry_offset[m_nev] = (int)a_offset;
223  }
224  m_nev++;
225  return true;
226  }
227 
228  bool write_on_file(ifile& a_file,uint16 a_cycle,uint32& a_nbytes) {
229  // write m_data buffer into file.
230  //NOTE : m_data does not contain the key at its head.
231  // At this point m_seek_key should be 0.
232 
233  a_nbytes = 0;
234 
235  if(m_seek_key) {
236  m_out << "tools::wroot::basket::write_on_file :"
237  << " m_seek_key should be 0 (" << m_seek_key << ")."
238  << std::endl;
239  return false;
240  }
241 
243  } else {
244  m_out << "tools::wroot::basket::write_on_file : "
245  << " we should not pass here (1)."
246  << std::endl;
247  return false;
248 /*
249  if(a_file.END()>START_BIG_FILE()) {
250  //GB : enforce m_version>big_file_version_tag() if m_version is still 2 but
251  // seek_key>START_BIG_FILE. If not doing that we shall
252  // write a big m_seek_key on a seek32 and then have
253  // a problem when reading.
254 
255  //m_out << "tools::wroot::basket::write_on_file : "
256  // << " WARNING : pos>START_BIG_FILE."
257  // << std::endl;
258 
259  m_version += big_file_version_tag();
260  m_key_length += 8;
261 
262  if(m_entry_offset) {
263  for(uint32 i=0;i<m_nev;i++) m_entry_offset[i] += 8;
264  if(m_displacement) {
265  //??? Do we have to shift them ?
266  m_out << "tools::wroot::basket::write_on_file : "
267  << " displace logic : m_displacement not null."
268  << std::endl;
269  }
270  }
271 
272  }
273 */
274  }
275 
276  // Transfer m_entry_offset table at the end of fBuffer. Offsets to fBuffer
277  // are transformed in entry length to optimize compression algorithm.
279  if(m_entry_offset) {
280  if(!m_data.write_array<int>(m_entry_offset,m_nev+1)) { // for the +1 we follow CERN-ROOT/TBasket logic.
281  delete [] m_entry_offset;
282  m_entry_offset = 0;
283  return false;
284  }
285  delete [] m_entry_offset;
286  m_entry_offset = 0;
287  if(m_displacement) {
288  if(!m_data.write_array<int>(m_displacement,m_nev+1)) {
289  delete [] m_displacement;
290  m_displacement = 0;
291  return false;
292  }
293  delete [] m_displacement;
294  m_displacement = 0;
295  }
296  }
297 
298  m_object_size = m_data.length(); //uncompressed size.
299 
300  m_cycle = a_cycle;
301 
302  if(!m_data.displace_mapped(m_key_length)) return false;
303 
304  char* kbuf = 0;
305  uint32 klen = 0;
306  bool kdelete = false;
307  a_file.compress_buffer(m_data,kbuf,klen,kdelete);
308 
309  if(klen>m_object_size) {
310  m_out << "tools::wroot::basket::write_on_file :"
311  << " compression anomaly "
312  << " m_object_size " << m_object_size
313  << " klen " << klen
314  << std::endl;
315  if(kdelete) delete [] kbuf;
316  return false;
317  }
318 
319  if(!initialize(a_file,klen)) { //it will do a m_seek_key = a_file.END() and then a_file.set_END(...)
320  m_out << "tools::wroot::basket::write_on_file :"
321  << " initialize() failed."
322  << std::endl;
323  if(kdelete) delete [] kbuf;
324  return false;
325  }
326 
327  //write header of the key :
328  {buffer bref(m_out,a_file.byte_swap(),256);
329  if(!_stream_header(bref,a_file.verbose())) return false;
330  if(bref.length()!=m_key_length) {
331  m_out << "tools::wroot::basket::write_on_file :"
332  << " key len anomaly " << bref.length()
333  << " m_key_length " << m_key_length
334  << std::endl;
335  if(kdelete) delete [] kbuf;
336  return false;
337  }
338  ::memcpy(m_buffer,bref.buf(),m_key_length);}
339 
340  ::memcpy(m_buffer+m_key_length,kbuf,klen);
341  if(kdelete) delete [] kbuf;
342 
343  uint32 nbytes;
344  if(!parent::write_file(a_file,nbytes)) return false;
345 
346  m_data.pos() = m_data.buf(); //empty m_data.
347 
348  a_nbytes = m_key_length + klen;
349  return true;
350  }
351 protected:
352  uint32 header_record_size(uint32 a_version) const {
353  // header only.
354  uint32 nbytes = parent::record_size(a_version);
355 
356  nbytes += sizeof(short); //version
357  nbytes += sizeof(uint32); //m_buf_size
358  nbytes += sizeof(uint32); //m_nev_buf_size
359  nbytes += sizeof(uint32); //m_nev
360  nbytes += sizeof(uint32); //m_last
361  nbytes += sizeof(char); //flag
362 
363  return nbytes;
364  }
365  bool _stream_header(buffer& a_buffer,bool a_verbose,char a_flag = 0) const {
367  if((a_buffer.length()+l)>a_buffer.size()) {
368  if(!a_buffer.expand(a_buffer.size()+l)) return false;
369  }
370  wbuf wb(m_out,a_buffer.byte_swap(),a_buffer.max_pos(),a_buffer.pos());
371  if(!parent::to_buffer(wb,a_verbose)) return false;}
372 
373  if(!a_buffer.write_version(2)) return false;
374  if(!a_buffer.write(m_buf_size)) return false;
375  if(!a_buffer.write(m_nev_buf_size)) return false;
376  if(!a_buffer.write(m_nev)) return false;
377  if(!a_buffer.write(m_last)) return false;
378  if(!a_buffer.write(a_flag)) return false;
379  return true;
380  }
381 protected:
382  bool m_verbose;
384 protected:
385  uint32 m_nev_buf_size; //Length in Int_t of m_entry_offset
386  uint32 m_nev; //Number of entries in basket
387  uint32 m_last; //Pointer to last used byte in basket
388  int* m_entry_offset; //[m_nev] Offset of entries in fBuffer(TKey)
390 };
391 
392 }}
393 
394 #endif
tools::wroot::basket::operator=
basket & operator=(const basket &a_from)
Definition: basket:164
tools::wroot::basket::s_class
static const std::string & s_class()
Definition: basket:17
tools::wroot::seek
int64 seek
Definition: seek:16
tools::wroot::basket::stream
virtual bool stream(buffer &a_buffer) const
Definition: basket:26
tools::wroot::key::operator=
key & operator=(const key &)
Definition: key:124
tools::wroot::basket::write_on_file
bool write_on_file(ifile &a_file, uint16 a_cycle, uint32 &a_nbytes)
Definition: basket:228
tools::wroot::basket::m_verbose
bool m_verbose
Definition: basket:382
tools::wroot::buffer::max_pos
char * max_pos() const
Definition: buffer:93
tools::wroot::basket::m_displacement
int * m_displacement
Definition: basket:389
tools::wroot::buffer::byte_swap
bool byte_swap() const
Definition: buffer:82
tools::wroot::buffer::expand
bool expand(uint32 a_new_size)
Definition: buffer:276
tools::wroot::ifile
Definition: ifile:18
tools::wroot::basket::displacement
const int * displacement() const
Definition: basket:178
tools::wroot::buffer::length
uint32 length() const
Definition: buffer:89
tools::wroot::buffer::size
uint32 size() const
Definition: buffer:90
tools::wroot::basket::_stream_header
bool _stream_header(buffer &a_buffer, bool a_verbose, char a_flag=0) const
Definition: basket:365
tools::wroot::key::m_key_length
uint16 m_key_length
Definition: key:288
tools::wroot::basket::datbuf
const buffer & datbuf() const
Definition: basket:172
tools::wroot::basket::~basket
virtual ~basket()
Definition: basket:139
buffer
tools::wroot::basket::datbuf
buffer & datbuf()
Definition: basket:173
tools::wroot::ibo
Definition: ibo:17
tools::wroot::big_file_version_tag
uint32 big_file_version_tag()
Definition: seek:21
tools::wroot::key::m_cycle
uint16 m_cycle
Definition: key:289
tools::wroot::basket::entry_offset
const int * entry_offset() const
Definition: basket:175
tools::wroot::wbuf
Definition: wbuf:22
tools::wroot::key
Definition: key:22
tools::wroot::key::m_seek_key
seek m_seek_key
Definition: key:290
tools::wroot::key::m_buffer
char * m_buffer
Definition: key:282
tools::wroot::buffer::buf
char * buf()
Definition: buffer:87
tools::wroot::buffer::displace_mapped
bool displace_mapped(unsigned int a_num)
Definition: buffer:297
tools::wroot::key::initialize_zero
bool initialize_zero()
Definition: key:245
tools::wroot::basket::store_cls
virtual const std::string & store_cls() const
Definition: basket:22
tools::wroot::basket::basket
basket(std::ostream &a_out, bool a_byte_swap, seek a_seek_directory, const std::string &a_object_name, const std::string &a_object_title, const std::string &a_object_class, uint32 a_basket_size, bool a_verbose)
Definition: basket:104
tools::wroot::basket::header_record_size
uint32 header_record_size(uint32 a_version) const
Definition: basket:352
key
tools::wroot::key::m_version
uint32 m_version
Definition: key:285
tools::wroot::basket::m_nev
uint32 m_nev
Definition: basket:386
tools::wroot::buffer::write_version
bool write_version(short a_version)
Definition: buffer:169
tools::wroot::buffer::write_array
bool write_array(const T *a_a, uint32 a_n)
Definition: buffer:148
tools::wroot::basket::entry_offset
int * entry_offset()
Definition: basket:176
tools::wroot::buffer::write
bool write(T x)
Definition: buffer:97
tools::wroot::basket::basket
basket(const basket &a_from)
Definition: basket:149
tools::wroot::buffer::write_fast_array
bool write_fast_array(const char *a_a, uint32 a_n)
Definition: buffer:114
tools::wroot::key::m_out
std::ostream & m_out
Definition: key:280
tools::wroot::basket::m_last
uint32 m_last
Definition: basket:387
tools
inlined C code : ///////////////////////////////////
Definition: aida_ntuple:26
ibo
tools::wroot::basket::update
bool update(uint32 a_offset)
Definition: basket:205
tools::wroot::key::record_size
uint32 record_size(uint32 a_version) const
Definition: key:224
tools::wroot::ifile::byte_swap
virtual bool byte_swap() const =0
tools::wroot::basket::displacement
int * displacement()
Definition: basket:179
tools::wroot::basket
Definition: basket:14
tools::uint16
unsigned short uint16
Definition: typedefs:102
tools::wroot::buffer
Definition: buffer:28
tools::wroot::key::m_buf_size
uint32 m_buf_size
Definition: key:281
tools::wroot::key::m_object_size
uint32 m_object_size
Definition: key:286
tools::wroot::buffer::pos
char *& pos()
Definition: buffer:92
tools::wroot::buffer::to_displace
size_t to_displace() const
Definition: buffer:295
tools::wroot::basket::m_data
buffer m_data
Definition: basket:383
tools::wroot::basket::nev
uint32 nev() const
Definition: basket:182
tools::wroot::key::initialize
bool initialize(ifile &a_file, uint32 a_nbytes)
Definition: key:255
tools::wroot::ifile::verbose
virtual bool verbose() const =0
tools::wroot::ifile::compress_buffer
virtual void compress_buffer(const buffer &, char *&, uint32 &, bool &)=0
tools::wroot::basket::last
uint32 last() const
Definition: basket:183
tools::uint32
unsigned int uint32
Definition: typedefs:71
tools::wroot::key::to_buffer
bool to_buffer(wbuf &a_wb, bool a_verbose) const
Definition: key:177
tools::wroot::basket::m_nev_buf_size
uint32 m_nev_buf_size
Definition: basket:385
tools::wroot::basket::nev_buf_size
uint32 nev_buf_size() const
Definition: basket:181
tools::wroot::key::write_file
bool write_file(ifile &a_file, uint32 &a_nbytes)
Definition: key:139
tools::wroot::basket::set_nev
void set_nev(uint32 a_last, uint32 a_nev_buf_size, uint32 a_nev, const int *a_entry_offset, const int *a_displacement)
Definition: basket:185
tools::wroot::basket::m_entry_offset
int * m_entry_offset
Definition: basket:388