// evio2et.cc // reads EVIO events from file, enters into ET system // events in ET are in evio buffer format // still to do: // overflow events? // use evio buffer interface // allow more than one event per buffer // ejw, 16-Nov-2012 // to link: // g++ -o evio2et -I/group/halld-online/coda/Linux-x86_64/include evio2et.cc -L/group/halld-online/coda/Linux-x86_64/lib -levioxx -levio -let -lexpat -lpthread -ldl -lrt extern "C" { #include #include } #include "et.h" #include "evioUtil.hxx" #include "evioFileChannel.hxx" #include "evioBufferChannel.hxx" #include using namespace std; using namespace evio; // global vars string evioFileName; string etFileName = "/local/scratch/evio2et.dat"; int max_file = 0; int max_event = 0; int max_event_file = 0; int max_event_size = 20000; // in 4-byte words int chunk = 1; bool no_rate = false; bool no_evio = false; bool no_et = false; bool debug = false; bool done = false; // misc prototypes void decode_command_line(int argc, char**argv); // for monitoring int64_t last_time = 0; int evcount = 0; int last_evcount = 0; // evio buffer block headers (from Carl) uint32_t evioFirstHeader[8] = {0,1,8,1,0,4,0,0xc0da100}; // 1st word is total length uint32_t evioLastHeader[8] = {8,2,8,0,0,0x204,0,0xc0da100}; //------------------------------------------------------------------------------- static void *monitor_thread (void *arg) { int64_t now; struct timespec tnow; int rate; while(true) { // get time clock_gettime(CLOCK_REALTIME, &tnow); now = 1000L*tnow.tv_sec + tnow.tv_nsec/1000000L; // in msec // get count rate = ((now-last_time)>0)?(1000*(evcount-last_evcount))/(now-last_time):0; if(!no_rate)cout << "event rate: " << rate << endl; last_time=now; last_evcount=evcount; // sleep usleep(2000000); } } //------------------------------------------------------------------------------- int main(int argc, char **argv) { int filecount = 0; int evfilecount = 0; int status,handle; bool eof; struct timespec timeout = {0,30*1000*1000}; // 30 ms uint32_t *pdata; const uint32_t *pevio = NULL; int length,etBufferCount; uint32_t evioBufferLength; evioFileChannel *chan; et_sys_id et_system_id; et_att_id et_attach_id; et_event *event; et_event **pevents; et_openconfig openconfig; // decode command line arguments decode_command_line(argc,argv); if(evioFileName.empty())evioFileName="fakeEvents.evio"; // create monitoring thread pthread_t tid; pthread_create(&tid, NULL, monitor_thread, (void *)NULL); try { // create evio file channel, will read the file many times chan = new evioFileChannel(evioFileName,"r",max_event_size); // create et station config et_open_config_init(&openconfig); et_open_config_setcast(openconfig, ET_DIRECT); et_open_config_setwait(openconfig, ET_OPEN_WAIT); et_open_config_sethost(openconfig, ET_HOST_LOCAL); // open et system if (et_open(&et_system_id, etFileName.c_str(), openconfig) != ET_OK) { cerr << "?unable to open et file " << etFileName << endl; exit(EXIT_FAILURE); } // attach to grandcentral if(et_station_attach(et_system_id, ET_GRANDCENTRAL, &et_attach_id)<0) { cerr << "?unable to attach to Grand Central" << endl; exit(EXIT_FAILURE); } // done with config et_open_config_destroy(openconfig); // allocate pevents array pevents = (et_event **) calloc(chunk, sizeof(et_event *)); if (pevents == NULL) { cerr << "unable to allocate events array, chunk is " << chunk << endl; exit(EXIT_FAILURE); } // open/read/close evio file as many times as needed while(!done && ((max_file<=0)||(filecountopen(); filecount++; // fill et buffers with evio events evfilecount=0; eof=false; while(!done && !eof && ((max_event_file<=0)||(evfilecountreadNoCopy(); if(!eof) { evcount++; evfilecount++; pevio=chan->getNoCopyBuffer(); length=pevio[0]+1; // check if event fits into et buffer, must account for block headers if(length<(max_event_size-20)) { // get ET buffer data pointer et_event_getdata(pevents[i],(void**)&pdata); if(pdata==NULL) { cerr << "?null pdata" << endl; exit(EXIT_FAILURE); } // copy event into et buffer as evio buffer // eventually will use Carl's evioBuffer functions, doing it by hand for the moment... evioFirstHeader[0]=8+pevio[0]+1; memcpy((void*)pdata,(void*)evioFirstHeader,8*sizeof(uint32_t)); memcpy((void*)&(pdata[8]),(void*)pevio,(pevio[0]+1)*sizeof(uint32_t)); memcpy((void*)&(pdata[8+pevio[0]+1]),(void*)evioLastHeader,8*sizeof(uint32_t)); // evOpenBuffer((char*)pdata,length,"w",&handle); // evWrite(handle,pevio); // evGetBufferLength(handle,&evioBufferLength) // evClose(handle); // set length in bytes evioBufferLength=(evioFirstHeader[0]+8)*sizeof(uint32_t); et_event_setlength(pevents[i],evioBufferLength); } else { // if event is too large for et buffer need special et event buffer ??? cerr << "event too large: " << length << endl; } } else { // eof, dump extra events nDumped=etBufferCount-i; status = et_events_dump(et_system_id, et_attach_id, &(pevents[i]), nDumped); break; } } // return et buffers status = et_events_put(et_system_id, et_attach_id, pevents, etBufferCount-nDumped); if (status != ET_OK) { cerr << "?unable to put events" << endl; exit(EXIT_FAILURE); } } // done...close channel chan->close(); } } catch (evioException e) { cerr << e.toString() << endl; } catch (...) { cerr << "?unknown exception" << endl; } cout << endl << " *** total files processed is " << filecount << " ***" << endl; cout << endl << " *** total events read is " << evcount << " ***" << endl << endl; et_close(et_system_id); delete(chan); } //------------------------------------------------------------------------------- void decode_command_line(int argc, char**argv) { static string help = "\nUsage:\n\n evio2et [-maxfile max_file] [-maxevt max_event] [-maxevtfile max_event_file]\n" " [-maxevtsize max_event_size] [-et_file etFileName] [-chunk chunk]\n" " [-no_evio] [-no_et] [-debug] evioFileName\n"; if(argc<2) { cout << help << endl; exit(EXIT_SUCCESS); } /* loop over arguments */ int i=1; while (i