00001 #include "Reader.hh"
00002 #include "Message.hh"
00003 #include "ConfigHandler.hh"
00004 #include "EventHandler.hh"
00005 #include <fstream>
00006 #include <stdexcept>
00007 #include <iomanip>
00008
00009 Reader::Reader(const std::string& filename) :
00010 _filename(filename), _fin(0), _ok(true),
00011 _current_index(-1), _current_event(), _current_file_index(_unset_file_index),
00012 _current_file_name(""),
00013 _end_last_file(false)
00014 {
00015
00016 if(!OpenNextFile()){
00017
00018 if(ConfigHandler::GetInstance()->GetSavedCfgFile()==""){
00019 std::string cfgfile = _current_file_name+".";
00020 size_t pos;
00021 bool cfgfound = false;
00022 while( (pos = cfgfile.rfind('.')) != std::string::npos){
00023 cfgfile.resize(pos);
00024 std::string testfile = cfgfile+".cfg";
00025 Message(DEBUG2)<<"Testing for config file with name "<<testfile<<"\n";
00026 std::ifstream cfgfin(testfile.c_str());
00027 if(cfgfin.is_open()){
00028 ConfigHandler::GetInstance()->SetSavedCfgFile(testfile);
00029 Message(DEBUG)<<"Found saved cfg file at "<<testfile<<"\n";
00030 cfgfound = true;
00031 break;
00032 }
00033 cfgfin.close();
00034 }
00035 if(!cfgfound)
00036 Message(WARNING)<<"Unable to locate configuration file for raw file "
00037 <<filename<<"\n";
00038 }
00039
00040 if(_ghead.global_header_version>0)
00041 EventHandler::GetInstance()->SetRunID(_ghead.run_id);
00042 else
00043 EventHandler::GetInstance()->SetRunIDFromFilename(filename);
00044 }
00045
00046 }
00047
00048 Reader::~Reader()
00049 {
00050 if(_fin) CloseCurrentFile();
00051 }
00052
00053 bool Reader::ErrorCheck(int bytes_read, int bytes_requested)
00054 {
00055
00056 if(bytes_read == -1){
00057 Message(ERROR)<<"Error encountered when reading from file.\n";
00058 _ok = false;
00059 return true;
00060 }
00061 else if(bytes_read == 0){
00062 Message(DEBUG)<<"End of file reached.\n";
00063 return true;
00064 }
00065 else if(bytes_read < bytes_requested){
00066 Message(ERROR)<<"Problem reading header for next event.\n";
00067 _ok = false;
00068 return true;
00069 }
00070 return false;
00071 }
00072
00073
00074 int Reader::ReadNextHeader()
00075 {
00076 if(!_ok){
00077 Message(ERROR)<<"Attempt to read from file in bad state.\n";
00078 return 1;
00079 }
00080
00081 if(eof()){
00082 Message(DEBUG)<<"Reached end of files to search.\n";
00083 return 1;
00084 }
00085 int bytes_read = 0;
00086 switch(_ghead.event_header_version){
00087 case 0:
00088
00089 event_header_v0 head;
00090 bytes_read = gzread(_fin, &head, sizeof(event_header_v0));
00091 if(ErrorCheck(bytes_read, sizeof(event_header_v0)))
00092 return 1;
00093
00094 _ehead.event_size = head.event_size;
00095 _ehead.event_id = head.event_id;
00096 _ehead.timestamp = head.timestamp;
00097 _ehead.nblocks = 1;
00098 break;
00099 case latest_event_version:
00100
00101 bytes_read = gzread(_fin, &_ehead, sizeof(_ehead));
00102 if(ErrorCheck(bytes_read, sizeof(_ehead))){
00103 if(bytes_read==0)
00104 return ReadNextHeader();
00105
00106 return 1;
00107 }
00108 break;
00109 default:
00110 Message(CRITICAL)<<"Unknown event header version number!\n";
00111 }
00112 return 0;
00113 }
00114
00115 z_off_t Reader::SkipNextEvent(bool skip_header)
00116 {
00117
00118 if(gzeof(_fin) && OpenNextFile()){
00119 Message(DEBUG)<<"Reached end of files to search.\n";
00120 return 0;
00121 }
00122
00123 z_off_t seekpos=0;
00124 if(skip_header){
00125
00126 uint32_t esize = 0;
00127 int bytes_read = gzread(_fin, &esize, sizeof(uint32_t));
00128 if(ErrorCheck(bytes_read, sizeof(uint32_t)))
00129 return 0;
00130 z_off_t seek_length = esize - sizeof(uint32_t);
00131 seekpos = gzseek(_fin, seek_length, SEEK_CUR);
00132 }
00133 else{
00134 z_off_t seek_length = _ehead.event_size - sizeof(event_header);
00135 if(_ghead.event_header_version == 0)
00136 seek_length = _ehead.event_size - sizeof(event_header_v0);
00137 seekpos = gzseek(_fin, seek_length, SEEK_CUR);
00138 }
00139 _current_index++;
00140 return seekpos;
00141
00142 }
00143
00144 RawEventPtr Reader::GetNextEvent(bool read_header)
00145 {
00146 if(read_header)
00147 ReadNextHeader();
00148 if(!_ok){
00149 Message(ERROR)<<"Attempt to read from file in bad state.\n";
00150 return RawEventPtr();
00151 }
00152 if(eof()){
00153 return RawEventPtr();
00154 }
00155
00156 RawEventPtr next(new RawEvent);
00157
00158 switch(_ghead.event_header_version){
00159 case 0:{
00160
00161
00162 uint32_t evsize = _ehead.event_size - sizeof(event_header_v0);
00163 int blockn = next->AddDataBlock(RawEvent::CAEN_V172X, evsize);
00164 int bytes_read = gzread(_fin, next->GetRawDataBlock(blockn), evsize);
00165 if(ErrorCheck(bytes_read, evsize))
00166 return RawEventPtr();
00167 break;
00168 }
00169 case latest_event_version: {
00170
00171 datablock_header bh;
00172 uint32_t thisblock = 0;
00173 int bytes_read = 0;
00174 while(thisblock < _ehead.nblocks &&
00175 (uint32_t)bytes_read<_ehead.event_size-sizeof(event_header)){
00176 int head_read = gzread(_fin, &bh, sizeof(bh));
00177 if(ErrorCheck(head_read, sizeof(bh)))
00178 return RawEventPtr();
00179
00180 int blockn = next->AddDataBlock(bh.type, bh.datasize);
00181
00182 std::vector<char> buf(bh.total_blocksize_disk);
00183 int block_read = gzread(_fin, &(buf[0]),
00184 bh.total_blocksize_disk-sizeof(bh));
00185 if(ErrorCheck(block_read, bh.total_blocksize_disk-sizeof(bh))){
00186 Message(ERROR)<<"Incorrect blocksize for block "<<thisblock<<" in event "
00187 <<_ehead.event_id;
00188 return RawEventPtr();
00189 }
00190
00191 uLongf decomp = bh.datasize;
00192 int err = uncompress(next->GetRawDataBlock(blockn), &decomp,
00193 (Bytef*)(&(buf[0])), block_read);
00194 if(err != Z_OK){
00195 Message(ERROR)<<"uncompress function returned "<<err
00196 <<" while reading event!\n";
00197 return RawEventPtr();
00198 }
00199 next->SetDataBlockSize(blockn,decomp);
00200
00201 thisblock++;
00202 bytes_read += head_read + block_read;
00203 }
00204
00205 if((uint32_t)bytes_read != _ehead.event_size-sizeof(event_header) ||
00206 thisblock != _ehead.nblocks){
00207 Message(ERROR)<<"The event with id "<<_ehead.event_id
00208 <<" was not fully read out!\n";
00209 return RawEventPtr();
00210 }
00211 break;
00212 }
00213 default:
00214 Message(CRITICAL)<<"Unknown event header version number!\n";
00215 return RawEventPtr();
00216 }
00217
00218
00219 next->SetID(_ehead.event_id);
00220 next->SetTimestamp(_ehead.timestamp);
00221 if(_ghead.global_header_version > 0)
00222 next->SetRunID(_ghead.run_id);
00223
00224 _current_index++;
00225 _current_event = next;
00226 return next;
00227 }
00228
00229 RawEventPtr Reader::GetLastEvent()
00230 {
00231 if(!_ok){
00232 Message(ERROR)<<"Attempt to read from file in bad state.\n";
00233 return RawEventPtr();
00234 }
00235 int last_id=0;
00236 while(!ReadNextHeader()){
00237 last_id = _ehead.event_id;
00238 SkipNextEvent(false);
00239 }
00240 if(!_ok)
00241 return RawEventPtr();
00242 Reset();
00243 return GetEventWithID(last_id);
00244 }
00245
00246
00247 RawEventPtr Reader::GetEventWithIndex(int index)
00248 {
00249 if(!_ok){
00250 Message(ERROR)<<"Attempt to read from file in bad state.\n";
00251 return RawEventPtr();
00252 }
00253 if(index == _current_index)
00254 return _current_event;
00255
00256
00257 if(index < _current_index){
00258 Message(DEBUG)<<"Rewinding raw file...\n";
00259 Reset();
00260 }
00261
00262 while(_ok && _current_index < index-1){
00263 if(SkipNextEvent())
00264 return RawEventPtr();
00265 }
00266
00267 if(!_ok || _end_last_file)
00268 return RawEventPtr();
00269 else if(_current_index == index-1)
00270 return GetNextEvent();
00271 else{
00272 Message(ERROR)<<"Unknown problem occurred trying to seek to index "
00273 <<index<<"\n";
00274 return RawEventPtr();
00275 }
00276 }
00277
00278 RawEventPtr Reader::GetEventWithID(uint32_t id)
00279 {
00280 if(!_ok){
00281 Message(ERROR)<<"Attempt to read from file in bad state.\n";
00282 return RawEventPtr();
00283 }
00284 if(id == 0){
00285 Reset();
00286 return GetNextEvent();
00287 }
00288 if(id == _ehead.event_id)
00289 return _current_event;
00290
00291
00292 if(id != 0 && id < _ehead.event_id ){
00293 Message(DEBUG)<<"Rewinding raw file...\n;";
00294 if(Reset())
00295 return RawEventPtr();
00296 }
00297
00298 while( _ghead.global_header_version > 0 && _ghead.event_id_max > 0 &&
00299 _ghead.nevents>0 && id > _ghead.event_id_max ){
00300 if(OpenNextFile()){
00301 Message(ERROR)<<"Event with id "<<id
00302 <<" is not present in this file set.\n";
00303 return RawEventPtr();
00304 }
00305 }
00306
00307 while(_ok && !_end_last_file ){
00308
00309 if(ReadNextHeader())
00310 return RawEventPtr();
00311 if(_ehead.event_id == id){
00312 return GetNextEvent(false);
00313 }
00314 else if(_ehead.event_id > id){
00315 Message(ERROR)<<"Event with id "<<id<<" is not present in this file.\n";
00316 return RawEventPtr();
00317 }
00318
00319 SkipNextEvent(false);
00320 }
00321
00322 if(!_ok || _end_last_file)
00323 return RawEventPtr();
00324
00325 return _current_event;
00326 }
00327
00328 bool Reader::GetAssociatedParameter(VParameterNode* par, std::string key)
00329 {
00330 if(key == "")
00331 key = par->GetDefaultKey();
00332 bool cfg_found = true;
00333 if(!(par->ReadFromFile((_filename+".cfg").c_str(),key,true))){
00334
00335 std::string fnamecopy(_filename);
00336 fnamecopy.resize(fnamecopy.size()-3);
00337 if(!(par->ReadFromFile((fnamecopy+".cfg").c_str(),
00338 key, true))){
00339
00340 Message(INFO)<<"Unable to find associated config file.\n";
00341 cfg_found = false;
00342 }
00343 }
00344 return cfg_found;
00345 }
00346
00347 int Reader::Reset()
00348 {
00349 if(!_ok)
00350 return 0;
00351 if(_fin)
00352 CloseCurrentFile();
00353 _current_file_index = _unset_file_index;
00354 _current_index = -1;
00355 _current_event = RawEventPtr();
00356 _ehead.reset();
00357 _end_last_file = false;
00358 return OpenNextFile();
00359 }
00360
00361 int Reader::CloseCurrentFile()
00362 {
00363 if(_fin)
00364 gzclose(_fin);
00365 _fin = 0;
00366 return 0;
00367 }
00368
00369 int Reader::OpenNextFile()
00370 {
00371 using std::string;
00372 if(_fin)
00373 CloseCurrentFile();
00374 if(_current_file_index == _unset_file_index &&
00375 ( _filename.substr(_filename.size()-7) == ".out.gz" ||
00376 _filename.substr(_filename.size()-4) == ".out" ) ){
00377
00378
00379 Message(DEBUG)<<"Attempting to open file "<<_filename.c_str()
00380 <<" as legacy format."<<std::endl;
00381 _current_file_name = _filename;
00382 _fin = gzopen(_current_file_name.c_str(),"rb");
00383 }
00384 if(!_fin && _current_file_name != _filename){
00385
00386 std::stringstream fname;
00387 fname<<_current_file_name.substr(0,_current_file_name.size()-7)
00388 <<std::setw(3)<<std::setfill('0')<<_current_file_index+1 <<".out";
00389 _current_file_name = fname.str();
00390 Message(DEBUG)<<"Next file in series should be "<<_current_file_name
00391 <<"\n";
00392 _fin = gzopen(_current_file_name.c_str(),"rb");
00393 }
00394 if(!_fin){
00395 Message(DEBUG)<<"No file with name "<<_filename<<" exists; "
00396 <<"trying alterations for new format.\n";
00397
00398
00399 string filename = _filename;
00400 size_t last_slash = filename.rfind('/');
00401
00402 string dirpart="", filepart=filename;
00403 if(last_slash == filename.size()-1){
00404 dirpart = filename;
00405 filepart = "";
00406 }
00407 else if(last_slash != string::npos){
00408 dirpart = filename.substr(0, last_slash+1);
00409 filepart = filename.substr(last_slash+1, string::npos);
00410 }
00411
00412
00413
00414 while(!filepart.empty()){
00415 std::stringstream fname;
00416 fname<<dirpart<<filepart<<"."
00417 <<std::setw(3)<<std::setfill('0')<<_current_file_index+1<<".out";
00418 _current_file_name = fname.str();
00419 Message(DEBUG2)<<"Testing filename "<<_current_file_name<<" ...\n";
00420 _fin = gzopen(_current_file_name.c_str(),"rb");
00421 if(_fin)
00422 break;
00423 size_t last_dot = filepart.rfind('.');
00424 if(last_dot == string::npos)
00425 break;
00426 filepart.resize(last_dot);
00427 }
00428
00429 if(!_fin){
00430
00431
00432 if(!filepart.empty()){
00433 dirpart += filepart + "/";
00434 std::stringstream fname;
00435 fname<<dirpart<<filepart<<"."
00436 <<std::setw(3)<<std::setfill('0')<<_current_file_index+1<<".out";
00437 _current_file_name = fname.str();
00438 Message(DEBUG2)<<"Testing filename "<<_current_file_name<<" ...\n";
00439 _fin = gzopen(_current_file_name.c_str(),"rb");
00440 }
00441 else{
00442
00443 if(!dirpart.empty() && dirpart[dirpart.size()-1]=='/'){
00444 last_slash = dirpart.rfind('/',dirpart.size()-2);
00445 if(last_slash == string::npos)
00446 last_slash = -1;
00447 filepart = dirpart.substr(last_slash+1,string::npos);
00448 filepart.resize(filepart.size()-1);
00449 std::stringstream fname;
00450 fname<<dirpart<<filepart<<"."
00451 <<std::setw(3)<<std::setfill('0')<<_current_file_index+1
00452 <<".out";
00453 _current_file_name = fname.str();
00454 Message(DEBUG2)<<"Testing filename "<<_current_file_name<<" ...\n";
00455 _fin = gzopen(_current_file_name.c_str(),"rb");
00456 }
00457 }
00458 }
00459 if(_fin){
00460 _current_file_index++;
00461
00462 }
00463 }
00464
00465 if(!_fin){
00466 if(_current_file_index == _unset_file_index){
00467 Message(ERROR)<<"Unable to open file "<<_filename<<" for reading!\n";
00468 _ok = false;
00469 }
00470 _end_last_file = true;
00471 return 1;
00472 }
00473
00474 _ehead.reset();
00475
00476
00477 gzread(_fin, &_ghead, _ghead.global_header_size);
00478
00479 if(_ghead.magic_num_check != magic_number){
00480
00481 _ghead.global_header_version = 0;
00482 _ghead.event_header_version = 0;
00483 _ghead.run_id = 0;
00484 _ghead.nevents = 0;
00485 _ghead.event_id_min = 0;
00486 _ghead.event_id_max = 0;
00487 _current_file_index = 0;
00488 gzrewind(_fin);
00489 }
00490 else{
00491 if(_ghead.global_header_version != latest_global_version ||
00492 _ghead.event_header_version != latest_event_version){
00493
00494 Message(CRITICAL)<<"Header version number stored in this file is larger"
00495 <<" than latest version!\n";
00496 throw std::out_of_range("incorrect header version number");
00497 }
00498 else if(_ghead.global_header_size != sizeof(global_header) ||
00499 _ghead.event_header_size != sizeof(event_header) ){
00500 Message(CRITICAL)<<"Incorrect size of headers in raw file!\n";
00501 throw std::out_of_range("incorrect header size");
00502 }
00503 Message(DEBUG)<<"Successfully opened file "<<_current_file_name
00504 <<"\nFile header information:"
00505 <<"\n\tMagic number: 0x"<<std::hex<<_ghead.magic_num_check
00506 <<std::dec
00507 <<"\n\tHeader size: "<<_ghead.global_header_size
00508 <<"\n\tHeader version: "<<_ghead.global_header_version
00509 <<"\n\tEvent header size: "<<_ghead.event_header_size
00510 <<"\n\tEvent header version: "<<_ghead.event_header_version
00511 <<"\n\tStart time: "<<_ghead.start_time
00512 <<"\n\tEnd time: "<<_ghead.end_time
00513 <<"\n\tRun ID: "<<_ghead.run_id
00514 <<"\n\tFileIndex: "<<_ghead.file_index
00515 <<"\n\tEvents: "<<_ghead.nevents
00516 <<"\n\tMin Event: "<<_ghead.event_id_min
00517 <<"\n\tMax Event: "<<_ghead.event_id_max
00518 <<std::endl;
00519 _current_file_index = _ghead.file_index;
00520 }
00521 return 0;
00522 }