/*! \file \version $Id: TAGmbsIStream.cxx,v 1.5 2003/07/22 18:27:37 mueller Exp $ \brief Implementation of TATOFmbsIStream. */ #include extern "C" { #include "typedefs.h" #ifndef R__BYTESWAP #include "s_filhe_swap.h" #include "s_bufhe_swap.h" #include "s_ve10_1_swap.h" #include "s_ves10_1_swap.h" #include "s_evhe_swap.h" #else #include "s_filhe.h" #include "s_bufhe.h" #include "s_ve10_1.h" #include "s_ves10_1.h" #include "s_evhe.h" #endif #include "f_evt.h" } #include "TSystem.h" #include "TString.h" #include "TATOFtimestamp.h" #include "TATOFmbsIStream.h" /*! \class TATOFmbsIStream TATOFmbsIStream.h "TATOFmbsIStream.h" \brief Representation of MBS raw data input stream. ** */ ClassImp(TATOFmbsIStream); //------------------------------------------+----------------------------------- //! Default constructor. TATOFmbsIStream::TATOFmbsIStream() : TATOFnamed("TATOFmbsIStream",""), fiRetCode(kSuccess), fpChannelDsc(0), fiTime(-1), fpData(0) {} //------------------------------------------+----------------------------------- //! Destructor. TATOFmbsIStream::~TATOFmbsIStream() { Close(); } //------------------------------------------+----------------------------------- //! Open data source \a name . /*! Open the data source with the name \a name and returns \a false on success and \c true on failure. The data source name has the URL-style format: \verbatim protocol:pathname \endverbatim The following protocol types are currently supported: - \c file: -- local files - \c eserv: -- event server - \c rserv: -- remote event server - \c stream: -- stream server - \c trans: -- transport server If no protocol is specified \c file: is assumed. For the local file protocol the pathname is just the local file name. In all other cases the pathname is the node name of the server. */ Bool_t TATOFmbsIStream::Open(const TString& name) { int i_rc; int i_mode = 0; TString uri = name; TString protname; TString filename; Close(); fiRetCode = kSuccess; if (uri.BeginsWith("file:")) { i_mode = GETEVT__FILE; protname = "file:"; filename = name.Data()+protname.Length(); // ??? use substrings properly !!! } else if (uri.BeginsWith("rfio:")) { i_mode = GETEVT__FILE; protname = "rfio:"; filename = name.Data()+protname.Length(); } else if (uri.BeginsWith("eserv:")) { i_mode = GETEVT__EVENT; protname = "eserv:"; filename = name.Data()+protname.Length(); } else if (uri.BeginsWith("rserv:")) { i_mode = GETEVT__REVSERV; protname = "rserv:"; filename = name.Data()+protname.Length(); } else if (uri.BeginsWith("stream:")) { i_mode = GETEVT__STREAM; protname = "stream:"; filename = name.Data()+protname.Length(); } else if (uri.BeginsWith("trans:")) { i_mode = GETEVT__TRANS; protname = "trans:"; filename = name.Data()+protname.Length(); } else { i_mode = GETEVT__FILE; protname = "file:"; filename = name; } gSystem->ExpandPathName(filename); uri = protname + filename; fpChannelDsc = malloc(sizeof(s_evt_channel)); i_rc = f_evt_get_open(i_mode, (char*) filename.Data(), (s_evt_channel*)fpChannelDsc, 0, 0, 0); if (i_rc != 0) { switch (i_rc) { case GETEVT__NOFILE: Error("Open()", "no such file `%s'", filename.Data()); break; case GETEVT__RDERR: Error("Open()", "server read error on `%s'", filename.Data()); break; case GETEVT__NOSERVER: Error("Open()", "no such server `%s'", filename.Data()); break; default: Error("Open()", "Unknown open error code = %d for `%s'", i_rc, filename.Data()); break; } free(fpChannelDsc); fpChannelDsc = 0; fiRetCode = kFail; return kTRUE; } // ??? should f_evt_timeout() be setup ??? SetTitle(uri); return kFALSE; } //------------------------------------------+----------------------------------- //! Close data source. void TATOFmbsIStream::Close() { ResetBit(kValid|kEof|kFail); if (fpChannelDsc) { f_evt_get_close((s_evt_channel*)fpChannelDsc); free(fpChannelDsc); fpChannelDsc = 0; fiTime = -1; fpData = 0; } SetTitle(""); return; } //------------------------------------------+----------------------------------- //! Fetch next event. /*! Reads the next event from the data source. The methods returns 0 on success, 1 if the end of file is reached or any hard error occurs. In case of timeouts a -1 is returned. The \a i_timeout parameter is currently ignored and always the buildin timeout of the event server used. */ Int_t TATOFmbsIStream::FetchEvent(Int_t i_timeout) { ResetBit(kValid); fpData = 0; fiTime = -1; if (!fpChannelDsc) { Error("FetchEvent()", "Stream not connected"); SetBit(kFail); return 1; } if (Eof()) return 1; INTS4* p_evtdata; INTS4* p_bufdata; int i_rc = f_evt_get_event((s_evt_channel*)fpChannelDsc, &p_evtdata, &p_bufdata); if (i_rc != 0) { switch (i_rc) { case GETEVT__TIMEOUT: SetBit(kValid); return -1; case GETEVT__NOMORE: SetBit(kEof|kFail); return 1; case GETEVT__FRAGMENT: Error("FetchEvent()", "data format error"); SetBit(kFail); return 1; case GETEVT__RDERR: Error("FetchEvent()", "read error"); SetBit(kFail); return 1; case GETEVT__FAILURE: Error("FetchEvent()", "communication failure"); SetBit(kFail); return 1; default: Error("FetchEvent()", "Unknown read error code = %d", i_rc); SetBit(kFail); return 1; } } if (p_bufdata) { s_bufhe* p_bufhead = (s_bufhe*) p_bufdata; fiTime = p_bufhead->l_time[0]; } else { TATOFtimestamp time; time.SetCurrent(); fiTime = time.ToUnixTime(); } fpData = (UInt_t*) p_evtdata; SetBit(kValid); return 0; } //------------------------------------------+----------------------------------- //! Fill TATOFmbsEvent object with sub event according to filter. /*! \a p_evt must point to an already allocated TATOFmbsEvent object. */ void TATOFmbsIStream::FillEvent(TATOFmbsEvent* p_evt, TATOFmbsEventFilter* p_filt) { p_evt->Clear(); if (!fpData) return; const s_ve10_1* p_evthead = (const s_ve10_1*)fpData; p_evt->SetEventInfo(TATOFmbsEventInfo(p_evthead->l_count, p_evthead->i_trigger, fiTime)); Int_t i_nrest = (p_evthead->l_dlen+4)/2 - 4; Int_t i_offset = 4; Int_t i_nsub = 0; Int_t i_nword = 0; fOffset.clear(); while (i_nrest >= 3) { const s_ves10_1* p_subhead = (const s_ves10_1*)(fpData+i_offset); Int_t i_size = (p_subhead->l_dlen-2)/2; Int_t i_typ = p_subhead->i_type; Int_t i_styp = p_subhead->i_subtype; Int_t i_pid = p_subhead->i_procid; Int_t i_ptyp = p_subhead->h_control; Int_t i_crate = p_subhead->h_subcrate; if (!p_filt || (*p_filt)(i_typ, i_styp, i_pid, i_ptyp, i_crate)) { fOffset.push_back(i_offset); i_nsub += 1; i_nword += i_size; } else { fOffset.push_back(0); } i_nrest -= i_size + 3; i_offset += i_size + 3; } p_evt->Reserve(i_nsub, i_nword); for (Int_t i = 0; i < (Int_t)fOffset.size(); i++) { Int_t i_offset = fOffset[i]; if (i_offset > 0) { const s_ves10_1* p_subhead = (const s_ves10_1*)(fpData+i_offset); Int_t i_size = (p_subhead->l_dlen-2)/2; Int_t i_typ = p_subhead->i_type; Int_t i_styp = p_subhead->i_subtype; Int_t i_pid = p_subhead->i_procid; Int_t i_ptyp = p_subhead->h_control; Int_t i_crate = p_subhead->h_subcrate; p_evt->AddSubEvent(i_typ, i_styp, i_pid, i_ptyp, i_crate, i_size, fpData+i_offset+3); } } p_evt->SetBit(kValid); return; } //------------------------------------------+----------------------------------- //! Fetch next event and fill \a p_evt . /*! \a p_evt must point to an already allocated TATOFmbsEvent object. */ Int_t TATOFmbsIStream::ReadEvent(TATOFmbsEvent* p_evt, TATOFmbsEventFilter* p_filt) { p_evt->Clear(); Int_t i_rc = FetchEvent(); if (i_rc != 0) return i_rc; FillEvent(p_evt, p_filt); return 0; } /*------------------------------------------+---------------------------------*/ //! ostream insertion. void TATOFmbsIStream::ToStream(ostream& os, Option_t* option) const { TATOFnamed::ToStream(os); // ??? return; }