LCIO  02.17
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SIOWriter.cc
Go to the documentation of this file.
1 #include "SIO/SIOWriter.h"
2 
3 // -- lcio headers
4 #include "EVENT/LCEvent.h"
5 #include "EVENT/LCRunHeader.h"
6 #include "EVENT/LCIO.h"
7 #include "EVENT/LCCollection.h"
8 #include "SIO/LCSIO.h"
9 
10 // -- sio headers
11 #include <sio/exception.h>
12 #include <sio/api.h>
13 #include <sio/compression/zlib.h>
14 
15 // -- std headers
16 #include <sys/stat.h>
17 
18 namespace SIO {
19 
20  void SIOWriter::open(const std::string & filename) {
21  std::string sioFilename ;
22  getSIOFileName( filename, sioFilename ) ;
23  struct stat fileinfo ;
24  // if the file exists we throw an exception
25  if ( ::stat( sioFilename.c_str(), &fileinfo ) == 0 ) {
26  throw IO::IOException( std::string( "[SIOWriter::open()] File already exists: "
27  + sioFilename
28  + " \n open it in append or new mode !\n"
29  )) ;
30  }
31  // open new file for writing
32  open( filename, EVENT::LCIO::WRITE_NEW ) ;
33  }
34 
35  //----------------------------------------------------------------------------
36 
37  //----------------------------------------------------------------------------
38 
39  void SIOWriter::getSIOFileName(const std::string& filename, std::string& sioFilename ) {
40  if( filename.rfind( LCSIO::FileExtension ) == std::string::npos || // .slcio not found at all
41  !( filename.rfind(LCSIO::FileExtension) + strlen( LCSIO::FileExtension ) == filename.length() ) ) { // found, but not at end
42  sioFilename = filename + LCSIO::FileExtension ;
43  }
44  else {
45  sioFilename = filename ;
46  }
47  }
48 
49  //----------------------------------------------------------------------------
50 
51  void SIOWriter::open(const std::string& filename, int writeMode) {
52  // make sure filename has the proper extension (.slcio)
53  std::string sioFilename ;
54  getSIOFileName( filename, sioFilename ) ;
55  switch( writeMode ) {
56  case EVENT::LCIO::WRITE_NEW :
57  _stream.open( sioFilename , std::ios::binary ) ;
58  break ;
59  case EVENT::LCIO::WRITE_APPEND :
60  // try to read the last LCIORandomAccess record at the end --------------------
61  SIO_DEBUG( "SIOWriter::open: Opening in write append mode" );
62  sio::ifstream istr ;
63  istr.open( sioFilename, std::ios::binary ) ;
64  // status = _stream->open( sioFilename.c_str() , SIO_MODE_READ ) ;
65  if( not istr.is_open() ) {
66  throw IO::IOException( std::string( "[SIOWriter::open()] Can't open stream for reading TOC: " + sioFilename ) ) ;
67  }
68  SIO_DEBUG( "SIOWriter::open: Opening in write append mode 1" );
69  bool hasRandomAccess = _raMgr.initAppend(istr ) ;
70  istr.close() ;
71  SIO_DEBUG( "SIOWriter::open: Opening in write append mode 2" );
72  if( hasRandomAccess ) {
73  _stream.open( sioFilename.c_str() , std::ios::binary | std::ios::out | std::ios::in ) ;
74  // position at the beginnning of the file record which will then be overwritten with the next record ...
75  _stream.seekp( 0 , std::ios_base::end ) ;
76  auto endg = _stream.tellp() ;
77  if( endg < LCSIO::RandomAccessSize ) {
78  std::stringstream s ; s << "[SIOWriter::open()] Can't seek stream to " << LCSIO::RandomAccessSize ;
79  throw IO::IOException( s.str() ) ;
80  }
82  _stream.seekp( endg - tpos , std::ios_base::beg ) ;
83  }
84  else {
85  _stream.open( sioFilename.c_str() , std::ios::binary | std::ios::out | std::ios::ate ) ;
86  }
87  SIO_DEBUG( "SIOWriter::open: Opening in write append mode ... OK" );
88  break ;
89  }
90  if( not _stream.good() or not _stream.is_open() ) {
91  SIO_THROW( sio::error_code::not_open, "[SIOWriter::open()] Couldn't open file: '" + sioFilename + "'" ) ;
92  }
93  }
94 
95  //----------------------------------------------------------------------------
96 
97  //----------------------------------------------------------------------------
98 
100  _compressor.set_level( level ) ;
101  }
102 
103  //----------------------------------------------------------------------------
104 
106  if( not _stream.is_open() ) {
107  throw IO::IOException( "[SIOWriter::writeRunHeader] stream not opened") ;
108  }
109  sio::record_info recinfo {} ;
110  SIORunHeaderRecord::writeRecord( _rawBuffer, const_cast<EVENT::LCRunHeader*>(hdr), recinfo, 0 ) ;
111  // deal with zlib compression here
112  if( _compressor.level() != 0 ) {
113  sio::api::compress_record( recinfo, _rawBuffer, _compBuffer, _compressor ) ;
114  sio::api::write_record( _stream, _rawBuffer.span(0, recinfo._header_length), _compBuffer.span(), recinfo ) ;
115  }
116  else {
117  sio::api::write_record( _stream, _rawBuffer.span(), recinfo ) ;
118  }
119  // random access treatment
120  _raMgr.add( RunEvent( hdr->getRunNumber(), -1 ) , recinfo._file_start ) ;
121  }
122 
123  //----------------------------------------------------------------------------
124 
126 
127  if( not _stream.is_open() ) {
128  throw IO::IOException( "[SIOWriter::writeEvent] stream not opened") ;
129  }
130  // 1) write the event header record
131  sio::record_info rechdrinfo {} ;
132  SIOEventHeaderRecord::writeRecord( _rawBuffer, const_cast<EVENT::LCEvent*>(evt), rechdrinfo, 0 ) ;
133  // deal with zlib compression here
134  if( _compressor.level() != 0 ) {
135  sio::api::compress_record( rechdrinfo, _rawBuffer, _compBuffer, _compressor ) ;
136  sio::api::write_record( _stream, _rawBuffer.span(0, rechdrinfo._header_length), _compBuffer.span(), rechdrinfo ) ;
137  }
138  else {
139  sio::api::write_record( _stream, _rawBuffer.span(), rechdrinfo ) ;
140  }
141  // random access treatment
142  _raMgr.add( RunEvent( evt->getRunNumber(), evt->getEventNumber() ) , rechdrinfo._file_start ) ;
143 
144  // 2) write the event record
145  sio::record_info recinfo {} ;
146  SIOEventRecord::writeRecord( _rawBuffer, const_cast<EVENT::LCEvent*>(evt), _eventHandlerMgr, recinfo, 0 ) ;
147  // deal with zlib compression here
148  if( _compressor.level() != 0 ) {
149  sio::api::compress_record( recinfo, _rawBuffer, _compBuffer, _compressor ) ;
150  sio::api::write_record( _stream, _rawBuffer.span(0, recinfo._header_length), _compBuffer.span(), recinfo ) ;
151  }
152  else {
153  sio::api::write_record( _stream, _rawBuffer.span(), recinfo ) ;
154  }
155  }
156 
157  //----------------------------------------------------------------------------
158 
161  _raMgr.clear() ;
162  _stream.close();
163  }
164 
165  //----------------------------------------------------------------------------
166 
168  _stream.flush() ;
169  }
170 
171 } // namespace
static void writeRecord(sio::buffer &outbuf, EVENT::LCEvent *event, sio::record_info &rec_info, sio::options_type opts=0)
Write an event header to the raw sio buffer.
Definition: LCIORecords.cc:28
void getSIOFileName(const std::string &filename, std::string &sioFilename)
Creates a proper filename with extension &#39;slcio&#39; in sioFilename.
Definition: SIOWriter.cc:39
SIOHandlerMgr _eventHandlerMgr
The collection block handler manager for events.
Definition: SIOWriter.h:112
static constexpr int RandomAccessSize
Definition: LCSIO.h:31
Interface for the run header.
Definition: LCRunHeader.h:23
virtual void close()
Closes the output file/stream etc.
Definition: SIOWriter.cc:159
T rfind(T...args)
bool initAppend(sio::ifstream &stream)
Initialize random access for append mode: read last LCIORandomAccess record if it exists - recreate t...
static void writeRecord(sio::buffer &outbuf, EVENT::LCRunHeader *rhdr, sio::record_info &rec_info, sio::options_type opts=0)
Write a run header record to the sio buffer.
Definition: LCIORecords.cc:105
Helper struct that stores run and event positions in the file.
Definition: RunEventMap.h:14
sio::ofstream _stream
The output file stream.
Definition: SIOWriter.h:104
virtual int getRunNumber() const =0
Return the run number off this event.
static void writeRecord(sio::buffer &outbuf, EVENT::LCEvent *event, const SIOHandlerMgr &handlerMgr, sio::record_info &rec_info, sio::options_type opts=0)
Write an event record.
Definition: LCIORecords.cc:78
sio::buffer _rawBuffer
The raw buffer for writing bytes to the stream.
Definition: SIOWriter.h:106
sio::buffer _compBuffer
The raw buffer for compression.
Definition: SIOWriter.h:108
virtual void flush()
Flushes the output file/stream etc.
Definition: SIOWriter.cc:167
virtual void writeRunHeader(const EVENT::LCRunHeader *hdr)
Writes the given run header to file.
Definition: SIOWriter.cc:105
STL class.
virtual void setCompressionLevel(int level)
Set the compression level - needs to be called before open() otherwise call will have no effect...
Definition: SIOWriter.cc:99
virtual int getRunNumber() const =0
Returns the run number.
void add(const RunEvent &re, long64 pos)
Add a new entry to the event map - if the RunEvent already exists the new position will be stored...
sio::zlib_compression _compressor
The compression in use.
Definition: SIOWriter.h:110
T str(T...args)
IOException used for reading/writing errors.
Definition: Exceptions.h:92
static constexpr const char * FileExtension
The lcio file extension name.
Definition: LCSIO.h:20
T length(T...args)
The main event interface.
Definition: LCEvent.h:31
virtual int getEventNumber() const =0
Returns this event&#39;s number .
T c_str(T...args)
void writeRandomAccessRecords(sio::ofstream &stream)
Write the current random access records LCIOIndex and LCIORandomAccess to the stream.
pair< int, string > level
Definition: lsh.cc:50
virtual void writeEvent(const EVENT::LCEvent *evt)
Writes the given event to file.
Definition: SIOWriter.cc:125
virtual void open(const std::string &filename)
Opens a file for writing.
Definition: SIOWriter.cc:20
void clear()
Clear all lists and maps before closing a file.
LCIORandomAccessMgr _raMgr
The random access manager.
Definition: SIOWriter.h:114