RawMilliSlice.cpp
Go to the documentation of this file.
1 #include "DAQDataFormats/RawMilliSlice.h"
2 #include "DAQDataFormats/DataFormatException.h"
3 #include <sys/time.h> // gettimeofday
4 #include <stdarg.h> // va_start
5 #include <cstdio>
6 
7 #include <boost/format.hpp>
8 
9 namespace daqdataformats{
10 
11 //------------------------------------------------------------------------------
12 RawMilliSlice::RawMilliSlice (const uint32_t size, const uint32_t tlvl) :
13  RawDAQData(0
14  ,(init_t) &RawMilliSlice::init
15  ,(sizeofdata_t) &RawMilliSlice::predefinedSize
16  ,(setBufferSource_t) &RawMilliSlice::setBufferSource
17  ,(print_t) &RawMilliSlice::printStandard
18  ,(readData_t) &RawMilliSlice::readDataFromBuffer)
19  ,_Header (NULL)
20  ,_Index (NULL)
21  ,_FloatingMicroSlice (NULL)
22  ,_FloatingMicroSliceNumber(-1)
23  ,_fd_read_bytes (0)
24  ,_tlvl (tlvl)
25 {
28 }
29 
30 //------------------------------------------------------------------------------
32  RawDAQData(copy_in)
33  ,_Header (NULL)
34  ,_Index (NULL)
35  ,_FloatingMicroSlice (NULL)
37  ,_fd_read_bytes (0)
38  ,_tlvl (copy_in._tlvl)
39 {
40  lastOperationsInDeepCopy(copy_in);
41 }
42 
43 //------------------------------------------------------------------------------
44 RawMilliSlice::RawMilliSlice(const void* millislice_buffer, const uint32_t size):
45  RawDAQData(0
51  ,_Header (NULL)
52  ,_Index (NULL)
53  ,_FloatingMicroSlice (NULL)
55  ,_fd_read_bytes (0)
56  ,_tlvl (0)
57 {
58 
60  copy(millislice_buffer);
61 }
62 //------------------------------------------------------------------------------
63 // Destructor
65  if(_Header) delete _Header;
66  if(_Index) delete _Index;
68  }
69 
70 //------------------------------------------------------------------------------
71 // Initialization of Data members
73 
74  /// This is needed for the formats with variable size
75  /// If buffer is internal, need to resize it
76  if(isInternalBuffer())
78 
79  /// Initialize the header
80  _Header->init();
81 
82  /// Initialize the _FloatingMicroSliceNumber
84 }
85 
86 
87 //------------------------------------------------------------------------------
88 // Add a MicroSlice into the MilliSlice changing the Header appropriately
89 bool RawMilliSlice::addMicroSlice(const void* microslice_buffer, const bool indexate, const bool check_mc_flag){
90 
91  /// Construct a temporary nanoslice with external buffer
92  const RawMicroSlice tmp_nanoslice(microslice_buffer);
93  /// This is its size
94  const uint32_t microslice_size = tmp_nanoslice.sizeofdata();
95 
96  // Add one microslice
97  addData(microslice_buffer, microslice_size, 1, false);
98 
99  /// Add an index if told so.
100  if(indexate){
101  /// Get Time length and offset
102  const uint32_t time = tmp_nanoslice.getTime() - getTimeStart();
104 
105  /// If MilliSlice Index is not constructed yet, do it now
106  if(!_Index) _Index = new RawMilliSliceIndex();
107 
108  // Add the index
109  _Index->addIndex(time, offset);
110  }// end of adding index
111 
112  // Check if the MicroSlice is MC generated
113  // If it is, set the appropriate MilliSlice MC flag
114  if(check_mc_flag){ setMonteCarloFlag(tmp_nanoslice.getMonteCarloFlag());}
115 
116  return true;
117 }
118 
119 //------------------------------------------------------------------------------
120 // Add a chunk of MicroSlices into the MilliSlice changing the Header appropriately
121 bool RawMilliSlice::addData(const void* buffer, const uint32_t size, const uint32_t number_of_microslices, const bool check_mc_flag){
122 
123  /// Just read the chunk of Microslices straight from the buffer into the end of the (internal) Buffer
124  readDataGeneral(buffer, size);
125 
127 
128  /// Advance the MilliSlice frame number (MicroSlice number in the MilliSlice)
129  _Header->setMicrosliceNumber(_Header->getMicrosliceNumber() + number_of_microslices);
130  /// Change the MilliSlice size
131  _Header->addSliceSize(size);
132 
133  /// Check if the first MicroSlice is MC generated
134  /// If it is, set the appropriate MilliSlice MC flag
135  /// checking/setting MC flag making it consistent with the MicroSlice
136  if(check_mc_flag){
137  RawMicroSliceHeader micro_header(buffer);
138  setMonteCarloFlag(micro_header.getMonteCarloFlag());
139  }// end of checking/setting MC flag making it consistent with the MicroSlice
140 
141  return true;
142 }
143 
144 //------------------------------------------------------------------------------
145 uint32_t RawMilliSlice::getCRC() const{
146 
147  if(!_Header->isCRCCalculationUsed()) return 0;
148 
149  return RAWBUFF32[sizeofdata() - 1];
150 }
151 
152 
153 
154 //------------------------------------------------------------------------------
155 // Closing the MilliSlice by adding the Index (if available), tail and the CRC
156 bool RawMilliSlice::close(const bool produce_crc){
157 
158  PRINT_ON_DEBUG(__PRETTY_FUNCTION__<<" 0 ");
159  /// First add the MilliSliceIndex if available
160  if(_Index){
161  PRINT_ON_DEBUG(__PRETTY_FUNCTION__<<" 1 ");
162 
163  /// Close the index - produce the tail
164  _Index->close();
165  PRINT_ON_DEBUG(__PRETTY_FUNCTION__<<" 2 ");
166 
167  const uint32_t size_of_index = _Index->sizeofdata();
168 
169  PRINT_ON_DEBUG(__PRETTY_FUNCTION__<<" 3 ");
170  // Copy the index to the end
171  readDataGeneral(_Index->getBuffer(), size_of_index);
173  PRINT_ON_DEBUG(__PRETTY_FUNCTION__<<" 4 ");
174 
175  /// Adjust the MilliSlice size
176  _Header->addSliceSize(size_of_index);
177 
178  /// Set MilliSlice Index number in the header
179  _Header->setMilliSliceIndexNumber(_Index->getIndexNumber());
180 
181  }// end of adding MilliSliceIndex
182 
183  const uint32_t size_before_adding_tail_and_crc = sizeofdata();
184 
185  /// Remember the current Buffer position
186  const void* current_buffer = &RAWBUFF32[size_before_adding_tail_and_crc];
187 
188  /// Add MILLISLICEHEADER_SIZE + 1 words to tthe size.
189  /// We will add the tail (another MilliSlice header) and the CRC-word in the end of the MilliSlice
191  /// If CRC is calculated, set the isCRCCalculationUsed flag
192  if(produce_crc)_Header->setCRCCalculationUsed(true);
193 
194  /// Adding a tail
195  /// Create a new Tail and assigning its pointer
196  readDataGeneral(_Header->getBuffer(), rawmillihdr::MILLISLICEHEADER_SIZE, size_before_adding_tail_and_crc);
198 
199  /// Make it a tail
200  RawMilliSliceHeader tail_tmp(current_buffer);
201  /// Set an appropriate Marker for the tail
202  tail_tmp.setMarker(rawmillihdr::Marker_value[1]);
203 
204  // Finally, add CRC at the very end of _Buffer if requested
205  if(produce_crc)
206  addCheckSum();
207  else{
208  /// If not, we still need to make zero at the end
209  /// Check if we need to assign or push_back
210  if(isInternalBuffer() && _InternalBuffer.size() < sizeofdata())
211  _InternalBuffer.push_back(0);
212  else
213  RAWBUFF32[sizeofdata() - 1] = 0;
214  }
215 
216  return true;
217 } // close
218 
219 //------------------------------------------------------------------------------
220 // This is a general method to read the microslice from millislice_buffer to _Buffer
221 void* RawMilliSlice::readDataFromBuffer(const void* millislice_buffer)
222 {
223  /// Read the header and find out the size of the millislice
224  void* millislice_buffer_new = readDataGeneral(millislice_buffer, rawmillihdr::MILLISLICEHEADER_SIZE, 0);
225 
226 
227  /// No need to check if the MilliSlice internal buffer went out.
228  /// MilliSlice size is at least of the size of the header
229 
230  /// Now, read the rest of the millislice
231  millislice_buffer_new = readDataGeneral(millislice_buffer_new, sizeofdata() - rawmillihdr::MILLISLICEHEADER_SIZE, rawmillihdr::MILLISLICEHEADER_SIZE);
232 
233  /// Check pointers after each read or resize buffer
235 
236  return millislice_buffer_new;
237 }// end of readData(void*)
238 
239 
240 // Method to read data in to a file descriptor
241 // The assumption is that the read will not block because a poll or select
242 // (in the case that the fd is a socket) has determined that data is ready.
243 // (Of course, the fd is always "ready" if the fd is associate with a file
244 // on disk). But no assumption is made that a 2nd read will not block, so
245 // only one read (within this readData routine) is every done. The caller
246 // is responsible for doing the necessary number of readData calls to get a
247 // "complete" millislice.
249 {
250  if (fd >= 0)
251  {
252  if (isInternalBuffer())
253  {
254  size_t bytes_to_read;
255 
256  if (_fd_read_bytes < rawmillihdr::MILLISLICEHEADER_SIZE*sizeof(uint32_t))
257  { const size_t min_words = rawmillihdr::MILLISLICEHEADER_SIZE;
258  const size_t min_bytes = min_words*sizeof (uint32_t);
259  if (_InternalBuffer.size() < min_words)
260  {
261  _InternalBuffer.resize(min_words);
263  }
264 
265  bytes_to_read = min_bytes - _fd_read_bytes;
266  }
267  else
268  {
269  uint32_t ss=sizeofdata();
270  // check before using size
271  if ( (getMarker() != rawmillihdr::Marker_value[0])
272  || (ss > 0x400000/*arbitrary val*/) )
273  { tprintf(30,"no marker or size too big\n");
274  return rds_error;
275  }
276  if (_InternalBuffer.size() < (size_t)ss)
277  { _InternalBuffer.resize( ss );
279  }
280  bytes_to_read = (size_t)ss*sizeof(uint32_t) - _fd_read_bytes;
281  }
282 
283  const ssize_t ss = read(fd, (char*)_Buffer+_fd_read_bytes, bytes_to_read );
284  if (ss==-1 || ss==0)
285  { tprintf(30,"read returned %ld\n", (long int)ss);
286  return rds_error;
287  }
288  _fd_read_bytes += ss;
289  if (ss != (int)bytes_to_read)
290  { return rds_incomplete;
291  }
292 
293  const uint32_t size_of_data = sizeofdata();
294 
295  // at this point, the header should have been read in and the
296  // size from within can be examined.
297  // check for resonableness
298  if ( (getMarker() != rawmillihdr::Marker_value[0])
299  || (size_of_data > 0x400000/*arbitrary val*/) )
300  { tprintf(30,"no marker or size too big (2)\n");
301  return rds_error;
302  }
303 
304  if (((size_t)size_of_data*sizeof (uint32_t)) == _fd_read_bytes)
305  return rds_complete;
306  return rds_incomplete;
307  }
308  else
309  {
310  printf("external buffer\n");
311  // assume there is enough space???
312  return RawDAQData::readData(fd);
313  }
314  }
315 
316  return rds_error;
317 } // readData( int )
318 
319 
320 //------------------------------------------------------------------------------
322  _fd_read_bytes = 0;
323 
324  return RawDAQData::clear();
325 }
326 
327 //------------------------------------------------------------------------------
329  _fd_read_bytes = 0;
330  return true;
331 }
332 
333 //------------------------------------------------------------------------------
334 bool RawMilliSlice::setFloatingMicroSlice(const uint32_t imicro) const{
335 
336  /// Check whether MicroSlice is valid
337  if(imicro >= getMicrosliceNumber())
338  return false;
339 
340  /// If it's already the same, nothing needs to be done
341  if((int)imicro == _FloatingMicroSliceNumber)
342  return true;
343 
344  /// Pointer that we are going to use
345  uint32_t* pointer;
346 
347  /// If microslice number is greater than current floating Microslice number, then no need
348  /// to loop over all MicroSlices, just start from the current floating MicroSlice
349  if((int)imicro > _FloatingMicroSliceNumber && _FloatingMicroSliceNumber > -1){
350  pointer = (uint32_t*)_FloatingMicroSlice->getBuffer();
351  }
352  else{
353  /// Otherwise, start from scratch
354  /// First point to the first MicroSlice
355  pointer = (uint32_t*)&RAWBUFF32[rawmillihdr::MILLISLICEHEADER_SIZE];
356 
357  /// Set floating MicroSlice to pointer
358  /// If it doesn't exist, create it
361  }// end of setting the first floating MicroSlice
362 
363  /// Pointer to the end of the buffer for checks
364  const uint32_t* end_of_buffer_pointer = &RAWBUFF32[sizeofdata()];
365 
366  /// Start loop over microslices
368  pointer += _FloatingMicroSlice->sizeofdata();
369 
370  /// Check if the pointer is not valid
371  if (pointer >= end_of_buffer_pointer)
372  return false;
373 
375  }
376 
377  return true;
378 }
379 
380 //------------------------------------------------------------------------------
382 
383  /// If it exists, just set its buffer
385  return _FloatingMicroSlice->setBufferSource(buffer);
386 
387  /// Otherwise, create new Floating MicroSlice pointing to the buffer
388  _FloatingMicroSlice = new RawMicroSlice(buffer);
389 
390  return true;
391 }
392 
393 //------------------------------------------------------------------------------
394 // Printing the MilliSlice structure
395 void RawMilliSlice::printStandard(std::ostream& os) const{
396 
397  _Header->print(os);
398 
399  const uint32_t size_of_data = sizeofdata();
400 
401  os<<boost::format("\n---MilliSlice---------------------------------------------size = %u words\n")% size_of_data;
402 
403  os<<"\nMilliSlice Data RAW 32bit WORDs (converted, if required, to native endian format):";
404  for(uint32_t i = 0; i < size_of_data; ++i){
405  this->printWord(i, false, os);
406  os<<" ";
407  }
408 
409  os<<"\nMilliSlice Data RAW 32bit Bits (converted, if required, to native endian format):";
410  for(uint32_t i = 0; i < size_of_data; ++i){
411  os<<"\n ";
412  this->printWord(i, true, os);
413  }
414 
415  const uint32_t num_microslices = getMicrosliceNumber();
416  os<<std::endl<<"----------NumMicroSlices-------="<<num_microslices<<std::endl;
417 
418  /// If number is nonzero, need to print them
419  if(num_microslices){
420  /// Get a copy of the MilliSlice this is so that we don't screw up the internal structure
421  RawMilliSlice milli_copy(_Buffer, 0);
422 
423  for(uint32_t i = 0; i < num_microslices; ++i){
424  milli_copy.setFloatingMicroSlice(i);
425  milli_copy.getFloatingMicroSlice()->print(os);
426  }// end of loop over nanoslices
427  }// end of checking whether the number of nanoslices is non-zero
428 
429 }
430 
431 //------------------------------------------------------------------------------
432 bool RawMilliSlice::setBufferSource(const void* pointer){
433 
434  _Buffer = (void*)pointer;
435 
437 
438  /// If Header is already defined, then set its buffer source
439  /// Otherwise, need to construct it
440  if(_Header)return _Header->setBufferSource(pointer);
441 
442  _Header = new RawMilliSliceHeader(_Buffer); ///< version of the MilliSLiceSliceHeader equals the version of the MilliSlice
443 
444  _function_sizeofdata = (sizeofdata_t) &RawMilliSlice::sizeofdata;
445 
446  return true;
447 }
448 
449 //------------------------------------------------------------------------------
450 void RawMilliSlice::tprintf( unsigned lvl, const char *fmt, ... ) {
451 
452  if (lvl > 31) lvl=31;
453  if (_tlvl & (1<<lvl))
454  { timeval tv;
455  char str[80];
456  time_t local;
457  const char* indent=" ";//32 spaces
458  va_list ap;
459  va_start( ap, fmt);
460  gettimeofday( &tv, NULL );
461  local = tv.tv_sec;
462  strftime( str, sizeof(str), "%T", localtime(&local) );
463  printf( "%s.%06ld%s", str, (long)tv.tv_usec, &indent[31-lvl] );
464  vprintf( fmt, ap );
465  }
466 } // tprintf
467 
468 //------------------------------------------------------------------------------
470 
471  /// If there are no MilliSlices Indeces in the header,
472  /// then nothing to return - MilliSlice Index was not constructed
473  if(getMilliSliceIndexNumber() == 0)
474  return NULL;
475 
476  /// If the MilliSlice Index does not exist,
477  /// then we need to figure out its pointer and construct the Index
478  if(!_Index){
479  /// At this point it is assumed that the MilliSlice is fully closed
480 
481  /// Get the tail. It's the end of the buffer, minus CRC and MilliSliceTail
482  /// Actually it's only tail, but we declare it as the MilliSliceIndex, because we need to know the size of the whole MilliSliceIndex
483  const uint32_t* pointer_to_tail = &RAWBUFF32[sizeofdata() - rawmillihdr::MILLISLICEHEADER_SIZE_PLUS_ONE];
484  const RawMilliSliceIndex tail(pointer_to_tail);
485 
486  /// The true pointer to Index is pointer to the tail minus the size
487  const uint32_t* pointer_to_millislice_index = pointer_to_tail + 1 - tail.sizeofdata();
488 
489  /// Construct the Index
490  _Index = new RawMilliSliceIndex(pointer_to_millislice_index);
491  }// end of checking whether Index is not constructed
492 
493  return _Index;
494 }
495 
496 } // end of namespace
bool clear()
Clear Internal Buffer and zero out _fd_read_bytes.
void * readDataGeneral(const void *buffer)
General ReadData method when the sizeofdata is known.
Definition: RawDAQData.cpp:186
uint32_t getMilliSliceIndexNumber() const
Definition: RawMilliSlice.h:68
#define sizeofdata_t
Definition: FunctionBind.h:30
bool setBufferSource(const void *)
bool setBufferSource(const void *pointer)
Setting Buffer, Header and Timing marker. Don&#39;t bother Floating NanoSlice.
bool setFloatingMicroSlice(const uint32_t) const
bool setBufferSource(const void *)
We are not going to overload these funtions, so no need to declare them virtual.
Definition: RawDAQData.cpp:880
void * _Buffer
All data formats need to have _Buffer and a Data structure. _Buffer will be common.
Definition: RawDAQData.h:276
bool setFloatingMicroSliceToBufferSource(const void *) const
readDataStatus readData(const int fd)
From the File descriptor.
virtual bool addCheckSum()
Add the CRC into the end of fBuffer. CRC of all but the last words of the _Buffer.
Definition: RawDAQData.cpp:550
Float_t ss
Definition: plot.C:24
void tprintf(unsigned lvl, const char *fmt,...) __attribute__((format(printf
daqdataformats::RawMicroSlice * getFloatingMicroSlice() const
Definition: RawMilliSlice.h:48
void * getBuffer() const
Definition: RawDAQData.h:131
virtual void copy(const RawDAQData &)
Deep copy from the DAQDataFormat.
Definition: RawDAQData.cpp:830
bool close(const bool produce_crc=false)
bool checkBufferInternalness()
If the buffer should be internal, check it&#39;s pointers and reassign them.
Definition: RawDAQData.cpp:612
bool _shouldBufferBeInternal
Auxillary variable that holds whether the buffer should be external or internal.
Definition: RawDAQData.h:286
::xsd::cxx::tree::buffer< char > buffer
Definition: Database.h:179
uint64_t getTime() const
Get method for upper half of timing word.
void lastOperationsInDeepCopy(const RawDAQData &copy_in)
Need to perform these operations in Deep Copy constructor.
Definition: RawDAQData.cpp:151
void print(std::ostream &os=std::cout) const
Method for printing the content of the Buffer.
Definition: RawDAQData.cpp:500
int _FloatingMicroSliceNumber
Floating MicroSlice.
void printStandard(std::ostream &os=std::cout) const
daqdataformats::RawMilliSliceHeader * _Header
uint32_t getMicrosliceNumber() const
Definition: RawMilliSlice.h:63
bool setMonteCarloFlag(const bool a)
Definition: RawMilliSlice.h:98
#define local
Definition: gzguts.h:107
std::vector< uint32_t > _InternalBuffer
Definition: RawDAQData.h:283
std::string indent(std::size_t const i)
daqdataformats::RawMicroSlice * _FloatingMicroSlice
MilliSlice Index.
printf("%d Experimental points found\n", nlines)
bool isInternalBuffer() const
Definition: RawDAQData.h:141
#define print_t
Definition: FunctionBind.h:31
uint32_t predefinedSize() const
std::string format(const int32_t &value, const int &ndigits=8)
Definition: HexUtils.cpp:14
virtual bool clear()
reset _Buffer to point to InternalBuffer
Definition: RawDAQData.cpp:573
uint32_t getMarker() const
Definition: RawMilliSlice.h:52
Class to hold the MicroSlice data.
Definition: RawMicroSlice.h:48
#define setBufferSource_t
Definition: FunctionBind.h:33
void * readDataFromBuffer(const void *)
#define RAWBUFF32
Definition: RawDAQData.h:16
void * readData(const void *buffer)
Shallow copy constructor.
Definition: RawDAQData.cpp:181
#define readData_t
Definition: FunctionBind.h:32
daqdataformats::RawMilliSliceIndex * getMilliSliceIndex() const
bool softclear()
zero out _fd_read_bytes, but leaving buffer alone
bool getMonteCarloFlag() const
Get the Data Present bit of the Header.
void printWord(const uint32_t iword, const bool is_bynary_printing, std::ostream &os=std::cout) const
Print word from Buffer.
Definition: RawDAQData.cpp:440
def tail(path, window=20)
Definition: log_trawl.py:24
bool addData(const void *buffer, const uint32_t size, const uint32_t number_of_microslices, const bool check_mc_flag=false)
bool reserveInternalBuffer(const uint32_t size_of_data)
Reserve space for the internal buffer to some predetermined size.
Definition: RawDAQData.cpp:271
#define PRINT_ON_DEBUG(x)
Definition: RawDAQData.h:35
bool addMicroSlice(const void *microslice_buffer, const bool indexate=false, const bool check_mc_flag=false)
uint32_t sizeofdata() const
Definition: RawMilliSlice.h:25
size_t _fd_read_bytes
Floating MicroSlice Number.
Class to hold the data from the FEBs in correct formats.
bool addIndex(const uint32_t, const uint32_t)
#define init_t
Definition: FunctionBind.h:29
daqdataformats::RawMilliSliceIndex * _Index
MilliSlice Header.
uint64_t getTimeStart() const
Definition: RawMilliSlice.h:55
RawMilliSlice(const uint32_t bufsize=DEFAULT_MILLISLICE_SIZE, const uint32_t tlvl=0)