00001 #include "SIO/LCIORandomAccessMgr.h"
00002
00003 #include "SIO/LCSIO.h"
00004 #include "SIO/SIORandomAccessHandler.h"
00005 #include "SIO/SIOIndexHandler.h"
00006 #include "SIO/SIOEventHandler.h"
00007 #include "SIO/SIORunHeaderHandler.h"
00008
00009 #include "IOIMPL/LCEventIOImpl.h"
00010 #include "IOIMPL/LCRunHeaderIOImpl.h"
00011
00012 #include "SIO_stream.h"
00013 #include "SIO_blockManager.h"
00014
00015 #include "Exceptions.h"
00016 #include <sstream>
00017
00018 #include <stdio.h>
00019 #include <string.h>
00020
00021 using namespace IO ;
00022
00023 namespace SIO{
00024
00025
00026 LCIORandomAccessMgr::LCIORandomAccessMgr() : _fileRecord(0) {
00027 }
00028
00029 LCIORandomAccessMgr::~LCIORandomAccessMgr() {
00030
00031
00032 for( std::list<LCIORandomAccess* >::iterator i = _list.begin() ; i != _list.end() ; ++i ){
00033
00034 delete *i ;
00035 }
00036
00037 if( _fileRecord != 0 )
00038 delete _fileRecord ;
00039 }
00040
00041 LCIORandomAccess* LCIORandomAccessMgr::createFromEventMap() {
00042
00043 LCIORandomAccess* ra = new LCIORandomAccess ;
00044
00045 ra->_minRunEvt = _runEvtMap.minRunEvent() ;
00046 ra->_maxRunEvt = _runEvtMap.maxRunEvent() ;
00047 ra->_nRunHeaders = _runEvtMap.getNumberOfRunRecords() ;
00048 ra->_nEvents = _runEvtMap.getNumberOfEventRecords() ;
00049
00050 ra->_recordsAreInOrder = true ;
00051 ra->_indexLocation = 0 ;
00052 ra->_prevLocation = 0 ;
00053 ra->_nextLocation = 0 ;
00054 ra->_firstRecordLocation = 0 ;
00055
00056 return ra ;
00057 }
00058
00059
00060
00061 void LCIORandomAccessMgr::createFileRecord(){
00062
00063 if( _fileRecord == 0 ) {
00064
00065 _fileRecord = new LCIORandomAccess ;
00066
00067 _fileRecord->_minRunEvt = RunEvent( 2147483647L, 2147483647L ) ;
00068 _fileRecord->_maxRunEvt = 0 ;
00069 _fileRecord->_nRunHeaders = 0 ;
00070 _fileRecord->_nEvents = 0 ;
00071 _fileRecord->_recordsAreInOrder = 1 ;
00072 _fileRecord->_indexLocation = 0 ;
00073 _fileRecord->_prevLocation = 9223372036854775807LL ;
00074 _fileRecord->_nextLocation = 0 ;
00075 _fileRecord->_firstRecordLocation = 0 ;
00076
00077 }
00078
00079
00080 for( std::list<LCIORandomAccess* >::const_iterator i = _list.begin() ; i != _list.end() ; ++i ){
00081 LCIORandomAccess* ra = *i ;
00082
00083 _fileRecord->_minRunEvt = ( ra->_minRunEvt < _fileRecord->_minRunEvt ? ra->_minRunEvt : _fileRecord->_minRunEvt ) ;
00084 _fileRecord->_maxRunEvt = ( ra->_maxRunEvt > _fileRecord->_maxRunEvt ? ra->_maxRunEvt : _fileRecord->_maxRunEvt ) ;
00085 _fileRecord->_nRunHeaders += ra->_nRunHeaders ;
00086 _fileRecord->_nEvents += ra->_nEvents ;
00087 _fileRecord->_recordsAreInOrder = ( _fileRecord->_recordsAreInOrder * ra->_recordsAreInOrder ) ;
00088 _fileRecord->_indexLocation = 0 ;
00089
00090 if( ra->_nextLocation > _fileRecord->_nextLocation )
00091 _fileRecord->_nextLocation = ra->_nextLocation ;
00092
00093 if( 0 < ra->_prevLocation && ra->_prevLocation < _fileRecord->_prevLocation )
00094 _fileRecord->_prevLocation = ra->_prevLocation ;
00095
00096
00097
00098
00099 }
00100
00101 }
00102
00103 void LCIORandomAccessMgr::addLCIORandomAccess( LCIORandomAccess* ra ) {
00104
00105 _list.push_back( ra ) ;
00106
00107
00108
00109
00110
00111
00112 }
00113
00114
00115 bool LCIORandomAccessMgr::readLCIORandomAccessAt( SIO_stream* stream , long64 pos) {
00116
00117 LCSIO::seekStream( stream, pos ) ;
00118
00119 return readLCIORandomAccess( stream ) ;
00120 }
00121
00122
00123 bool LCIORandomAccessMgr::readLCIORandomAccess( SIO_stream* stream ) {
00124
00125 SIO_record* accessRecord = LCSIO::records()[ SIORecords::Access ] ;
00126
00127 SIORecords::Unpack raUnp( SIORecords::Unpack::All ) ;
00128
00129 SIORandomAccessHandler raHandler( LCSIO_ACCESSRECORDNAME, this ) ;
00130
00131 SIO_blockManager::remove( LCSIO_ACCESSRECORDNAME ) ;
00132 SIO_blockManager::add( &raHandler ) ;
00133
00134 int status = stream->read( &accessRecord ) ;
00135
00136 if( ! (status & 1) ){
00137
00138 status = stream->reset() ;
00139
00140 if( status != SIO_STREAM_SUCCESS ){
00141
00142 throw IOException( std::string(" io error reading LCIORandomAccess on stream: ")
00143 + *stream->getName() ) ;
00144 }
00145
00146
00147
00148 return false ;
00149 }
00150
00151
00152
00153 return true ;
00154 }
00155
00156 bool LCIORandomAccessMgr::readLCIOIndexAt( SIO_stream* stream , long64 pos) {
00157
00158 LCSIO::seekStream( stream, pos ) ;
00159
00160 return readLCIOIndex( stream ) ;
00161 }
00162
00163 bool LCIORandomAccessMgr::readLCIOIndex( SIO_stream* stream ) {
00164
00165 SIORecords::Unpack raUnp( SIORecords::Unpack::All ) ;
00166
00167 SIOIndexHandler raHandler( LCSIO_INDEXRECORDNAME, this ) ;
00168
00169 SIO_blockManager::remove( LCSIO_INDEXRECORDNAME ) ;
00170 SIO_blockManager::add( &raHandler ) ;
00171
00172 SIO_record* indexRecord = LCSIO::records()[ SIORecords::Index ] ;
00173
00174 int status = stream->read( &indexRecord ) ;
00175
00176 if( ! (status & 1) ){
00177
00178 status = stream->reset() ;
00179
00180 if( status != SIO_STREAM_SUCCESS ){
00181
00182 throw IOException( std::string(" io error reading LCIOIndex on stream: ")
00183 + *stream->getName() ) ;
00184 }
00185
00186 std::cout << " ... no LCIOIndex record found - old file ??? " << std::endl ;
00187
00188 return false ;
00189 }
00190
00191 return true ;
00192 }
00193
00194
00195 bool LCIORandomAccessMgr::initAppend( SIO_stream* stream ) {
00196
00197
00198 if( ! readLCIORandomAccessAt( stream , -LCSIO_RANDOMACCESS_SIZE) ) {
00199
00200 recreateEventMap( stream ) ;
00201
00202 return false;
00203 }
00204
00205
00206 _fileRecord = _list.back() ;
00207 _list.pop_back() ;
00208
00209
00210 readLCIORandomAccessAt( stream , _fileRecord->_nextLocation ) ;
00211
00212 return true ;
00213 }
00214
00215
00216 bool LCIORandomAccessMgr::getEventMap( SIO_stream* stream ) {
00217
00218
00219 if( ! readLCIORandomAccessAt( stream , -LCSIO_RANDOMACCESS_SIZE) ) {
00220
00221 return recreateEventMap( stream ) ;
00222 }
00223
00224
00225 _fileRecord = _list.back() ;
00226 _list.pop_back() ;
00227
00228
00229 readLCIORandomAccessAt( stream , _fileRecord->_nextLocation ) ;
00230
00231
00232
00233
00234 const LCIORandomAccess* ra = lastLCIORandomAccess() ;
00235
00236 EVENT::long64 raPos = ra->getPrevLocation() ;
00237
00238 EVENT::long64 indexPos = ra->getIndexLocation() ;
00239
00240 readLCIOIndexAt( stream , indexPos ) ;
00241
00242 while( raPos != 0 ){
00243
00244 if( readLCIORandomAccessAt( stream , raPos) ){
00245
00246 ra = lastLCIORandomAccess() ;
00247
00248 raPos = ra->getPrevLocation() ;
00249
00250
00251
00252 EVENT::long64 indexPos = ra->getIndexLocation() ;
00253
00254 readLCIOIndexAt( stream , indexPos ) ;
00255
00256 }else{
00257 throw IOException( std::string( "[LCIORandomAccessMgr::ReadEventMap()] Could not read previous LCIORandomAccess record" ) ) ;
00258 }
00259 }
00260
00261 LCSIO::seekStream( stream, 0 ) ;
00262
00263 return true ;
00264
00265
00266 }
00267
00268 bool LCIORandomAccessMgr::recreateEventMap( SIO_stream* stream ) {
00269
00270 std::cout << " LCIORandomAccessMgr::getEventMap() recreating event map for direct access (old file) ..."
00271 << std::endl ;
00272
00273 LCSIO::seekStream( stream, 0 ) ;
00274
00275
00276 SIO_record* dummyRecord ;
00277 IOIMPL::LCEventIOImpl* evtPtr ;
00278 IOIMPL::LCRunHeaderIOImpl* runPtr ;
00279
00280 SIORunHeaderHandler runHandler( LCSIO_RUNBLOCKNAME, &runPtr ) ;
00281 SIOEventHandler eventHandler( LCSIO_HEADERBLOCKNAME, &evtPtr ) ;
00282
00283 SIO_blockManager::remove( LCSIO_HEADERBLOCKNAME ) ;
00284 SIO_blockManager::add( &eventHandler ) ;
00285 SIO_blockManager::remove( LCSIO_RUNBLOCKNAME ) ;
00286 SIO_blockManager::add( &runHandler ) ;
00287
00288 {
00289 SIORecords::Unpack hdrUnp( SIORecords::Unpack::Header + SIORecords::Unpack::Run ) ;
00290
00291 while( true ){
00292
00293
00294
00295
00296 if( stream->getState()== SIO_STATE_OPEN ){
00297
00298 unsigned int status = stream->read( &dummyRecord ) ;
00299
00300 if( ! (status & 1) ){
00301
00302 if( status & SIO_STREAM_EOF ){
00303 break ;
00304 }
00305
00306 throw IOException( std::string(" io error on stream: ") + *stream->getName() ) ;
00307 }
00308 } else {
00309 throw IOException( std::string(" stream not open: ")+ *stream->getName() ) ;
00310 }
00311
00312
00313 int runNum = -1 ;
00314 int evtNum = -1 ;
00315
00316 if( ! strcmp( dummyRecord->getName()->c_str() , LCSIO_HEADERRECORDNAME )){
00317
00318 runNum = evtPtr->getRunNumber() ;
00319 evtNum = evtPtr->getEventNumber() ;
00320 }
00321 if( ! strcmp( dummyRecord->getName()->c_str() , LCSIO_RUNRECORDNAME )){
00322
00323 runNum = runPtr->getRunNumber() ;
00324 }
00325
00326 _runEvtMap.add( RunEvent( runNum , evtNum ) , stream->lastRecordStart() ) ;
00327
00328
00329
00330
00331
00332
00333 }
00334
00335
00336 LCSIO::seekStream( stream, 0 ) ;
00337
00338 }
00339
00340
00341
00342 return true ;
00343 }
00344
00345 void LCIORandomAccessMgr::writeRandomAccessRecords(SIO_stream* stream) {
00346
00347 if( _runEvtMap.empty() ) {
00348 return ;
00349 }
00350
00351
00352 SIO_record* accessRecord = LCSIO::records()[ SIORecords::Access ] ;
00353 SIO_record* indexRecord = LCSIO::records()[ SIORecords::Index ] ;
00354
00355 SIORandomAccessHandler raHandler ( LCSIO_ACCESSRECORDNAME, this ) ;
00356 SIOIndexHandler idxHandler( LCSIO_INDEXRECORDNAME, this ) ;
00357
00358 accessRecord->connect( &raHandler ) ;
00359 indexRecord->connect( &idxHandler ) ;
00360
00361
00362 if( stream->getState() != SIO_STATE_OPEN ){
00363 throw IOException( std::string( "[LCIORandomAccessMgr::writeRandomAccessRecords] stream not opened: "
00364 + *stream->getName() ) ) ;
00365 }
00366
00367
00368
00369
00370 unsigned int status = stream->write( LCSIO_INDEXRECORDNAME ) ;
00371
00372 if( !(status & 1) )
00373 throw IOException( std::string( "[LCIORandomAccessMgr::writeRandomAccessRecords] couldn't write LCIOIndex to stream: "
00374 + *stream->getName() ) ) ;
00375
00376
00377
00378
00379 LCIORandomAccess* ra = createFromEventMap() ;
00380
00381 ra->setIndexLocation( stream->lastRecordStart() ) ;
00382
00383
00384 long64 thisPos = stream->currentPosition() ;
00385 ra->setFirstRecordLocation( thisPos ) ;
00386
00387 const LCIORandomAccess* lRa = lastLCIORandomAccess() ;
00388
00389 EVENT::long64 prevPos = ( lRa ? lRa->getFirstRecordLocation() : 0 ) ;
00390
00391
00392
00393 ra->setPreviousLocation( prevPos ) ;
00394
00395
00396
00397 addLCIORandomAccess( ra ) ;
00398
00399
00400
00401 status = stream->write( LCSIO_ACCESSRECORDNAME ) ;
00402
00403 if( !(status & 1) )
00404 throw IOException( std::string( "[LCIORandomAccessMgr::writeRandomAccessRecords] couldn't write LCIORandomAccess to stream: "
00405 + *stream->getName() ) ) ;
00406
00407
00408
00409
00410
00411 createFileRecord() ;
00412
00413 if( thisPos > _fileRecord->_nextLocation )
00414 _fileRecord->_nextLocation = thisPos ;
00415
00416 if( _fileRecord->_prevLocation > thisPos )
00417 _fileRecord->_prevLocation = thisPos ;
00418
00419 addLCIORandomAccess( _fileRecord ) ;
00420
00421 status = stream->write( LCSIO_ACCESSRECORDNAME ) ;
00422
00423 if( !(status & 1) )
00424 throw IOException( std::string( "[LCIORandomAccessMgr::writeRandomAccessRecords] couldn't write LCIORandomAccess file record to stream: "
00425 + *stream->getName() ) ) ;
00426
00427
00428 _list.pop_back() ;
00429
00430 }
00431
00432
00433
00434
00435
00436 std::ostream& operator<<(std::ostream& os, const LCIORandomAccessMgr& ra ){
00437
00438 os << " LCIORandomAccessMgr: ----------------------- " << std::endl ;
00439
00440 for( std::list<LCIORandomAccess* >::const_iterator i = ra._list.begin() ; i != ra._list.end() ; ++i ){
00441
00442 os << **i ;
00443 }
00444
00445 os << ra._runEvtMap << std::endl ;
00446
00447 return os ;
00448 }
00449 }