12 #define USE_ASYNC_FILEBUF 1
40 #ifndef USE_ASYNC_FILEBUF
57 ifs.open(
"/dev/null");
60 ifs.std::ios::rdbuf(sb);
61 if (!
ifs.is_open()) {
93 ifs.seekg(0, ios_base::end);
95 ifs.seekg(0, ios_base::beg);
105 #ifdef USE_ASYNC_FILEBUF
106 delete ifs.std::ios::rdbuf();
107 ifs.std::ios::rdbuf(
ifs.rdbuf());
109 if(
ifs.is_open())
ifs.close();
131 #if USE_ASYNC_FILEBUF
138 uint64_t left = ((uint64_t)
fbuff_end - (uint64_t)
fnext)/
sizeof(uint32_t);
141 uint64_t Ncopied = nwords<(int64_t)left ? (uint64_t)nwords:left;
142 _gcount = Ncopied*
sizeof(uint32_t);
151 if( (int64_t)Ncopied < nwords ){
154 uint32_t *myfbuff =
fbuff;
168 ifs.read((
char*)myfbuff, myfbuff_size*
sizeof(uint32_t));
174 uint64_t myleft = ((uint64_t)
fbuff_end - (uint64_t)
fnext)/
sizeof(uint32_t);
176 uint64_t mynwords = nwords - Ncopied;
177 uint64_t myNcopied = mynwords<myleft ? mynwords:myleft;
178 uint64_t mygcount = myNcopied*
sizeof(uint32_t);
179 if(mygcount>0) memcpy((
char*)s, (
char*)
fnext, mygcount);
181 _gcount += myNcopied*
sizeof(uint32_t);
190 #if USE_ASYNC_FILEBUF
196 int64_t off_words = (int64_t)off/(int64_t)
sizeof(uint32_t);
199 int64_t fpos = (int64_t)((uint64_t)
fnext - (uint64_t)
fbuff)/
sizeof(uint32_t);
202 if( way == ios_base::cur ){
209 fnext = &fbuff[fpos];
219 off = (streamoff)fpos - (streamoff)
fbuff_len;
232 _DBG_<<
"buff_seekg called with something other than ios_base::cur is unsupported!" << endl;
249 uint32_t valid_words =
buff_gcount()/
sizeof(uint32_t);
250 if(valid_words != 8){
258 if(
buff[7]!=0xc0da0100 &&
buff[7]!=0x0001dac0){
272 uint32_t block_length =
buff[0];
276 err_mess <<
"ERROR: EVIO block length greater than allocation limit (" << block_length <<
" > " << block_length <<
" words)" << endl;
286 err_mess <<
"ERROR: unable to allocate " << block_length <<
" words" << endl;
297 if(block_length == 8){
307 if(valid_words < block_length){
309 err_mess <<
"Error reading in EVIO entire block! (block number: " <<
buff[1] <<
")" << endl;
310 err_mess <<
"valid_words="<<valid_words <<
" block_length=" << block_length;
329 bool HDEVIO::read(uint32_t *user_buff, uint32_t user_buff_len,
bool allow_swap)
338 return readSparse(user_buff, user_buff_len, allow_swap);
344 uint32_t left =
buff_len - (uint32_t)(((
unsigned long)
next - (
unsigned long)
buff)/
sizeof(uint32_t));
347 if(left < 1 ||
next==NULL){
349 if(!isgood)
return false;
360 uint32_t event_len =
next[0];
366 if( event_len > left ){
368 err_mess <<
"WARNING: EVIO bank indicates a bigger size than block header (" << event_len <<
" > " << left <<
")";
377 if(event_len > user_buff_len){
379 err_mess <<
"user buffer too small for event (" << user_buff_len <<
" < " << event_len <<
")";
388 isgood = (Nswapped == event_len);
390 memcpy(user_buff,
next, event_len*
sizeof(uint32_t));
428 for(; sparse_event_idx < br.
evio_events.size(); sparse_event_idx++){
434 if(sparse_event_idx >= br.
evio_events.size())
continue;
442 if( event_len > user_buff_len ){
444 err_mess <<
"user buffer too small for event (" << user_buff_len <<
" < " << event_len <<
")";
459 ifs.read((
char*)user_buff, event_len*
sizeof(uint32_t));
465 uint32_t Nswapped =
swap_bank(user_buff, user_buff, event_len);
466 isgood = (Nswapped == event_len);
474 if( (user_buff[0]+1) != event_len ){
476 err_mess <<
"WARNING: EVIO bank indicates a different size than block header (" << event_len <<
" != " << (user_buff[0]+1) <<
")";
522 if( words_left_in_file == 8 ){
532 ifs.read((
char*)&bh,
sizeof(bh));
534 err_mess <<
"Error reading EVIO block header (truncated?)"<<endl;
535 err_mess <<
"words_left_in_file (before read): " << words_left_in_file << endl;
544 if(bh.
magic==0x0001dac0){
547 if(bh.
magic!=0xc0da0100){
554 if(swap_needed)
swap_block((uint32_t*)&bh,
sizeof(bh)>>2, (uint32_t*)&bh);
557 streampos pos =
ifs.tellg() - (streampos)
sizeof(bh);
560 err_mess <<
"EVIO block extends past end of file!";
591 if( event_len > user_buff_len ){
593 err_mess <<
"user buffer too small for event (" << user_buff_len <<
" < " << event_len <<
")";
603 ifs.read((
char*)user_buff, event_len*
sizeof(uint32_t));
605 uint64_t bytes_to_read = (uint64_t)(event_len*
sizeof(uint32_t));
608 err_mess <<
"Error reading EVIO event (truncated?)"<<endl;
609 err_mess <<
"words_left_in_file (before read): " << words_left_in_file << endl;
610 err_mess <<
" bytes tried to read : " << bytes_to_read << endl;
628 uint32_t Nswapped =
swap_bank(user_buff, user_buff, event_len);
629 isgood = (Nswapped == event_len);
637 if( (user_buff[0]+1) != event_len ){
639 err_mess <<
"WARNING: EVIO bank indicates a different size than block header (" << event_len <<
" != " << (user_buff[0]+1) <<
")";
665 ifs.seekg(0, ios_base::beg);
742 streampos start_pos =
ifs.tellg();
744 if(print_ticker) cout <<
"Mapping EVIO file ..." << endl;
747 ifs.seekg(0, ios_base::beg);
751 ifs.read((
char*)&bh,
sizeof(bh));
752 if(!
ifs.good())
break;
757 if(bh.
magic==0x0001dac0){
760 if(bh.
magic!=0xc0da0100){
764 br.
pos =
ifs.tellg() - (streampos)
sizeof(bh);
771 if(swap_needed)
swap_block((uint32_t*)&bh,
sizeof(bh)>>2, (uint32_t*)&bh);
774 streampos block_len_bytes = (bh.
length<<2)-
sizeof(bh);
775 streampos pos =
ifs.tellg() - (streampos)
sizeof(bh);
785 uint32_t tag = bh.
header>>16;
786 uint32_t M = bh.
header&0xFF;
806 _DBG_ <<
"Uknown tag: " << hex << tag << dec << endl;
817 if((Nblocks%500) == 0){
819 uint64_t read_MB =
ifs.tellg()>>20;
820 if(Nblocks==0) cout << endl;
821 cout << Nblocks <<
" blocks scanned (" << read_MB <<
"/" << total_MB <<
" MB " << (100*read_MB/total_MB) <<
"%) \r";
827 ifs.seekg(block_len_bytes, ios_base::cur);
830 if(print_ticker) cout << endl;
838 ifs.seekg(start_pos, ios_base::beg);
853 streampos start_pos =
ifs.tellg();
856 streampos pos = start_pos -(streampos)
sizeof(
BLOCKHEADER_t) + (streampos)(8<<2);
857 ifs.seekg(pos, ios_base::beg);
860 for(uint32_t i=0; i<bh.
eventcnt; i++){
870 if(!
ifs.good())
break;
880 std::cout <<
"HDEVIO::MapEvents warning - " <<
"Attempt to swap bank with len<2 (len="<<eh->
event_len<<
" header="<<hex<<eh->
header<<dec<<
" pos=" << pos <<
" tellg=" <<
ifs.tellg() <<
" i=" << i <<
")" << std::endl;
888 _DBG_ <<
"WARNING: This looks like an empty BOR event. BOR configuration" << endl;
889 _DBG_ <<
" data will not be available and it is unlikely you will" << endl;
890 _DBG_ <<
" be able to do anything beyond the digihit level. " << endl;
902 _DBG_ <<
" The program will (probably) stop now." << endl;
903 _DBG_ <<
" To avoid stopping, re-run with EVIO:IGNORE_EMPTY_BOR=1 ." << endl; }
909 streampos delta = (streampos)((eh->
event_len+1)<<2) -
911 ifs.seekg(delta, ios_base::cur);
912 pos += (streampos)((eh->
event_len+1)<<2);
924 uint32_t tag = eh->
header>>16;
925 uint32_t M = eh->
header&0xFF;
955 if(
VERBOSE>1)
_DBG_ <<
"Uknown tag: " << hex << tag << dec << endl;
962 ifs.seekg(delta, ios_base::cur);
963 pos += (streampos)((eh->
event_len+1)<<2);
967 ifs.seekg(start_pos, ios_base::beg);
992 uint32_t bank_len = outbuff[0];
993 if((bank_len+1) > len){
995 err_mess <<
"WARNING: Bank length word exceeds valid words in buffer (" << bank_len+1 <<
" > " << len <<
")";
1002 uint32_t type = (outbuff[1]>>8) & 0xFF;
1003 uint32_t Nwords = bank_len - 1;
1004 uint32_t Nswapped = 2;
1009 swap_block((uint64_t*)&inbuff[2], Nwords/2, (uint64_t*)&outbuff[2]);
1020 swap_block((uint16_t*)&inbuff[2], Nwords*2, (uint16_t*)&outbuff[2]);
1026 if( inbuff!=outbuff ) memcpy((uint8_t*)&outbuff[2], (uint8_t*)&inbuff[2], Nwords*
sizeof(uint32_t));
1030 while(Nswapped < (Nwords+2)){
1031 uint32_t N =
swap_tagsegment(&outbuff[Nswapped], &inbuff[Nswapped], (Nwords+2)-Nswapped);
1032 if(N == 0)
return Nswapped;
1038 while(Nswapped < (Nwords+2)){
1039 uint32_t N =
swap_segment(&outbuff[Nswapped], &inbuff[Nswapped], (Nwords+2)-Nswapped);
1040 if(N == 0)
return Nswapped;
1046 while(Nswapped < (Nwords+2)){
1047 uint32_t N =
swap_bank(&outbuff[Nswapped], &inbuff[Nswapped], (Nwords+2)-Nswapped);
1048 if(N == 0)
return Nswapped;
1054 err_mess <<
"WARNING: unknown bank type (0x" << hex << type << dec <<
")";
1082 uint32_t bank_len = outbuff[0] & 0xFFFF;
1083 if((bank_len) > len){
1085 err_mess <<
"Segment length word exceeds valid words in buffer (" << bank_len <<
" > " << len <<
")";
1092 uint32_t type = (outbuff[0]>>16) & 0x0F;
1093 uint32_t Nwords = bank_len;
1094 uint32_t Nswapped = 1;
1099 swap_block((uint64_t*)&inbuff[1], Nwords/2, (uint64_t*)&outbuff[1]);
1110 swap_block((uint16_t*)&inbuff[1], Nwords*2, (uint16_t*)&outbuff[1]);
1116 memcpy((uint8_t*)&outbuff[1], (uint8_t*)&inbuff[1], Nwords*
sizeof(uint32_t));
1141 uint32_t bank_len = outbuff[0] & 0xFFFF;
1142 if((bank_len) > len){
1144 err_mess <<
"Segment length word exceeds valid words in buffer (" << bank_len <<
" > " << len <<
")";
1151 uint32_t type = (outbuff[0]>>16) & 0x3F;
1152 uint32_t Nwords = bank_len;
1153 uint32_t Nswapped = 1;
1158 swap_block((uint64_t*)&inbuff[1], Nwords/2, (uint64_t*)&outbuff[1]);
1169 swap_block((uint16_t*)&inbuff[1], Nwords*2, (uint16_t*)&outbuff[1]);
1175 if( inbuff!=outbuff ) memcpy((uint8_t*)&outbuff[1], (uint8_t*)&inbuff[1], Nwords*
sizeof(uint32_t));
1189 cout <<
" fbuff: " << hex << (uint64_t)
fbuff << dec << endl;
1190 cout <<
" fnext: " << hex << (uint64_t)
fnext << dec << endl;
1191 cout <<
" fbuff_end: " << hex << (uint64_t)
fbuff_end << dec << endl;
1192 cout <<
" fbuff_size: " <<
fbuff_size << endl;
1193 cout <<
" fbuff_len: " <<
fbuff_len << endl;
1194 cout <<
" _gcount: " <<
_gcount << endl;
1204 cout <<
"EVIO Block Header:" << endl;
1205 cout <<
"------------------------" << endl;
1206 cout <<
" Block Length: " <<
HexStr(
buff[0]) <<
" (" <<
buff[0] <<
" words = " << (
buff[0]>>(10-2)) <<
" kB)" << endl;
1207 cout <<
" Block Number: " <<
HexStr(
buff[1]) << endl;
1208 cout <<
"Header Length: " <<
HexStr(
buff[2]) <<
" (should be 8)" << endl;
1209 cout <<
" Event Count: " <<
HexStr(
buff[3]) << endl;
1210 cout <<
" Reserved 1: " <<
HexStr(
buff[4]) << endl;
1211 cout <<
" Bit Info: " <<
HexStr(
buff[5]>>8) << endl;
1212 cout <<
" Version: " <<
HexStr(
buff[5]&0xFF) << endl;
1213 cout <<
" Reserved 3: " <<
HexStr(
buff[6]) << endl;
1215 cout <<
"Byte swapping is" << (
swap_needed ?
" ":
" not ") <<
"needed" << endl;
1229 for(
auto b :
evio_blocks) Nevents += b.evio_events.size();
1233 cout <<
"EVIO Statistics for " <<
filename <<
" :" << endl;
1234 cout <<
"------------------------" << endl;
1235 cout <<
" Nblocks: " << Nblocks << endl;
1236 cout <<
" Nevents: " << Nevents << endl;
1237 cout <<
" Nerrors: " <<
Nerrors << endl;
1251 uint32_t Nprestart = 0;
1253 uint32_t Npause = 0;
1255 uint32_t Nepics = 0;
1257 uint32_t Nphysics = 0;
1258 uint32_t Nunknown = 0;
1259 uint32_t Nblockunknown = 0;
1261 uint64_t first_event = 0;
1262 uint64_t last_event = 0;
1266 set<uint32_t> block_levels;
1267 set<uint32_t> events_in_block;
1275 uint32_t Nunknown_prev = Nunknown;
1279 uint32_t block_level;
1284 case kBT_GO: Ngo++;
break;
1291 block_levels.insert(block_level);
1292 Nphysics += block_level;
1303 if( (Nunknown-Nunknown_prev) > 0 ) Nblockunknown++;
1308 set<uint32_t>::iterator it = block_levels.begin();
1309 for(; it!=block_levels.end(); it++) ss << *it <<
",";
1310 string sblock_levels = ss.str();
1311 if(!sblock_levels.empty()) sblock_levels.erase(sblock_levels.length()-1);
1315 it = events_in_block.begin();
1316 for(; it!=events_in_block.end(); it++){
1319 if(++it==events_in_block.end())
break;
1322 for(it++; it!=events_in_block.end(); it++){
1324 ss << (val-1) <<
",";
1332 if( it==events_in_block.end() )
break;
1334 string sevents_in_block = ss.str();
1339 cout <<
"EVIO block map size: " << (map_size>>10) <<
" kB" <<endl;
1340 cout <<
"first event: " << first_event << endl;
1341 cout <<
"last event: " << last_event << endl;
1344 cout <<
" block levels = " << sblock_levels << endl;
1345 cout <<
" events per block = " << sevents_in_block << endl;
1346 cout <<
" Nsync = " << Nsync << endl;
1347 cout <<
" Nprestart = " << Nprestart << endl;
1348 cout <<
" Ngo = " << Ngo << endl;
1349 cout <<
" Npause = " << Npause << endl;
1350 cout <<
" Nend = " << Nend << endl;
1351 cout <<
" Nepics = " << Nepics << endl;
1352 cout <<
" Nbor = " << Nbor << endl;
1353 cout <<
" Nphysics = " << Nphysics << endl;
1354 cout <<
" Nunknown = " << Nunknown << endl;
1355 cout <<
" blocks with unknown tags = " << Nblockunknown << endl;
1368 if(fname==
"") fname =
filename +
".map";
1369 ofstream ofs(fname.c_str());
1371 cerr <<
"Unable to open \""<<fname<<
"\" for writing!" << endl;
1375 cout <<
"Writing EVIO file map to: " << fname << endl;
1378 time_t t = time(NULL);
1379 struct tm *tmp = localtime(&t);
1380 strftime(str, 255,
"%c", tmp);
1383 ofs <<
"# HDEVIO block map for " <<
filename << endl;
1385 ofs <<
"# generated " << str << endl;
1387 ofs <<
"# " << endl;
1389 ofs <<
"--------- Start of block data --------" << endl;
1390 ofs <<
"# pos block_len first_evt last_evt block_type" << endl;
1391 ofs <<
"# + pos evt_len evt_header first_evt last_evt event_type" << endl;
1395 sprintf(line,
"0x%08x 0x%06x %8" PRIu64
" %8" PRIu64
" %d", (uint32_t)br.pos, br.block_len, br.first_event, br.last_event, br.block_type);
1396 ofs << line << endl;
1398 for(
auto er : br.evio_events){
1399 sprintf(line,
"+ 0x%08x 0x%06x 0x%08x %8" PRIu64
" %8" PRIu64
" %d", (uint32_t)er.pos, er.event_len, er.event_header, er.first_event, er.last_event, er.event_type);
1400 ofs << line << endl;
1403 ofs <<
"# --- End of map ---" << endl;
1407 cout <<
"Done" << endl;
1416 if(
VERBOSE>4) cout <<
" Attempting to read EVIO map file \"" << fname <<
"\" for \"" <<
filename <<
"\"" << endl;
1423 auto pos =
filename.find_last_of(
"/");
1424 if(pos != string::npos){
1429 vector<string> fnames;
1430 fnames.push_back(
filename +
".map");
1431 fnames.push_back(dname +
"/filemaps/" + bname +
".map");
1432 fnames.push_back(bname +
".map");
1433 fnames.push_back(
filename +
".bmap");
1434 fnames.push_back(dname +
"/filemaps/" + bname +
".bmap");
1435 fnames.push_back(bname +
".bmap");
1438 for(
string f : fnames){
1439 if(
VERBOSE>2) cout <<
"Checking for EVIO map file: " <<
f <<
" ...";
1440 if( access(f.c_str(), R_OK) != 0 ) {
1441 if(
VERBOSE>2) cout <<
"no" << endl;
1444 if(
VERBOSE>2)cout <<
"yes" << endl;
1450 if(fname==
"")
return;
1453 ifstream mifs(fname.c_str());
1454 if(!mifs.is_open()){
1455 if(warn_if_not_found) cerr <<
"Unable to open \""<<fname<<
"\" for reading!" << endl;
1460 string eof_string(
"# --- End of map ---");
1461 mifs.seekg(-eof_string.length()*2, mifs.end);
1462 bool closed_cleanly =
false;
1464 while(getline(mifs,line)){
1465 if(
string(line).find(eof_string)!=string::npos) closed_cleanly =
true;
1467 if(!closed_cleanly){
1468 cerr <<
"Found map file \"" << fname <<
"\" but it wasn't closed cleanly. Ignoring." << endl;
1478 while(getline(mifs, line)){
1480 if(line.length() < 5 )
continue;
1481 if(line.find(
"#") == 0 )
continue;
1482 if(line.find(
"Start of block data") != string::npos)
break;
1487 bool first_block_found =
false;
1489 while(getline(mifs, s)){
1491 if(ss.str().find(eof_string) != string::npos )
break;
1492 if(ss.str().find(
"#") == 0 )
continue;
1494 if(ss.str().find(
"+") == 0 ){
1501 ss >> tmp64; er.
pos = tmp64;
1511 if(first_block_found){
1514 first_block_found =
true;
1519 ss >> tmp64; br.
pos = tmp64;
1530 cout <<
"Read EVIO file map from: " << fname << endl;
uint32_t sparse_event_idx
vector< EVIOBlockRecord > evio_blocks
async_filebuf * open(const std::string fname, std::ios::openmode mode)
HDEVIO(string filename, bool read_map_file=true, int verbose=1)
void buff_seekg(streamoff off, ios_base::seekdir way)
void MapEvents(BLOCKHEADER_t &bh, EVIOBlockRecord &br)
uint32_t AddToEventMask(string type_str)
sprintf(text,"Post KinFit Cut")
void buff_read(char *s, streamsize n)
string HexStr(uint32_t v)
void PrintEVIOBlockHeader(void)
vector< EVIOEventRecord > evio_events
vector< EVIOBlockRecord >::iterator sparse_block_iter
bool readSparse(uint32_t *user_buff, uint32_t user_buff_len, bool allow_swap=true)
uint32_t swap_tagsegment(uint32_t *outbuff, uint32_t *inbuff, uint32_t len)
uint32_t SetEventMask(uint32_t mask)
void SetErrorMessage(string mess)
vector< EVIOBlockRecord > & GetEVIOBlockRecords(void)
bool read(uint32_t *user_buff, uint32_t user_buff_len, bool allow_swap=true)
CDAQPHYSICSHEADER_t cdaqphysics
void MapBlocks(bool print_ticker=true)
void ClearErrorMessage(void)
void ReadFileMap(string fname="", bool warn_if_not_found=false)
bool readNoFileBuff(uint32_t *user_buff, uint32_t user_buff_len, bool allow_swap=true)
void SaveFileMap(string fname="")
streamsize buff_gcount() const
uint32_t roc1_bank_header
uint64_t GetNWordsLeftInFile(void)
void PrintFileSummary(void)
uint64_t total_size_bytes
EVIOBlockRecord NB_block_record
uint32_t swap_bank(uint32_t *outbuff, uint32_t *inbuff, uint32_t len)
void swap_block(uint16_t *inbuff, uint16_t len, uint16_t *outbuff)
uint32_t swap_segment(uint32_t *outbuff, uint32_t *inbuff, uint32_t len)