Hall A ROOT/C++ Analyzer (podd)
Loading...
Searching...
No Matches
THaEtClient.cxx
Go to the documentation of this file.
1
2//
3// THaEtClient
4// Data from ET Online System
5//
6// THaEtClient contains normal CODA data obtained via
7// the ET (Event Transfer) online system invented
8// by the JLab DAQ group.
9// This code works locally or remotely and uses the
10// ET system in a particular mode favored by hall A.
11//
12// Robert Michaels (rom@jlab.org)
13//
15
16#include "THaEtClient.h"
17#include <iostream>
18#include <cstdlib>
19#include <cerrno>
20#include <cstring>
21#include <ctime> // for timespec
22#include <stdexcept>
23#include "evio.h" // for evioswap
24#include "et_private.h" // for ET_VERSION
25
26using namespace std;
27
28static const int FAST = 25;
29static const int SMALL_TIMEOUT = 10;
30static const int BIG_TIMEOUT = 20;
31
32namespace Decoder {
33
34// Common member initialization for our constructors
35#define initflags \
36nread(0), nused(0), timeout(BIG_TIMEOUT), \
37id(0), my_att(0), \
38daqhost(nullptr), session(nullptr), etfile(nullptr), \
39waitflag(0), didclose(0), notopened(0), firstread(1), \
40firstRateCalc(1), evsum(0), xcnt(0), daqt1(-1), ratesum(0)
41
43 : initflags
44{
45 // uses default server (where CODA runs)
46 const char* defaultcomputer = ADAQS2;
47 THaEtClient::codaOpen(defaultcomputer,smode);
48}
49
50THaEtClient::THaEtClient(const char* computer,Int_t smode)
51 : initflags
52{
53 THaEtClient::codaOpen(computer,smode);
54}
55
56THaEtClient::THaEtClient(const char* computer, const char* mysession, Int_t smode)
57 : initflags
58{
59 THaEtClient::codaOpen(computer, mysession, smode);
60}
61
63 delete [] daqhost;
64 delete [] session;
65 delete [] etfile;
67 if (status == CODA_ERROR) cout << "ERROR: closing THaEtClient"<<endl;
68}
69
70Int_t THaEtClient::init(const char* mystation)
71{
72 static char station[ET_STATNAME_LENGTH];
73 if(!mystation||strlen(mystation)>=ET_STATNAME_LENGTH){
74 cout << "THaEtClient: bad station name\n";
75 return CODA_ERROR;
76 }
77 strcpy(station,mystation);
78 et_openconfig openconfig{};
79 et_open_config_init(&openconfig);
80 et_open_config_sethost(openconfig, daqhost);
81 et_open_config_setcast(openconfig, ET_DIRECT);
82 if (et_open(&id, etfile, openconfig) != ET_OK) {
83 notopened = 1;
84 cout << "THaEtClient: cannot open ET system"<<endl;
85 cout << "Likely causes: "<<endl;
86 cout << " 1. Incorrect SESSION environment variable (it can also be passed to codaOpen)"<<endl;
87 cout << " 2. ET not running (CODA not running) on specified computer"<<endl;
88 return CODA_ERROR;
89 }
90 et_open_config_destroy(openconfig);
91 et_statconfig sconfig{};
92 et_station_config_init(&sconfig);
93 et_station_config_setuser(sconfig, ET_STATION_USER_MULTI);
94 et_station_config_setrestore(sconfig, ET_STATION_RESTORE_OUT);
95 et_station_config_setprescale(sconfig, 1);
96 et_station_config_setcue(sconfig, 100);
97 et_station_config_setselect(sconfig, ET_STATION_SELECT_ALL);
98 et_station_config_setblock(sconfig, ET_STATION_NONBLOCKING);
99 et_stat_id my_stat{};
100 Int_t status = et_station_create(id, &my_stat, station, sconfig);
101 if (status < ET_OK) {
102 if (status == ET_ERROR_EXISTS) {
103 // ok
104 }
105 else if (status == ET_ERROR_TOOMANY) {
106 cout << "THaEtClient: too many stations created"<<endl;
107 return CODA_ERROR;
108 }
109 else if (status == ET_ERROR_REMOTE) {
110 cout << "THaEtClient: memory or improper arg problems"<<endl;
111 return CODA_ERROR;
112 }
113 else if (status == ET_ERROR_READ) {
114 cout << "THaEtClient: network reading problem"<<endl;
115 return CODA_ERROR;
116 }
117 else if (status == ET_ERROR_WRITE) {
118 cout << "THaEtClient: network writing problem"<<endl;
119 return CODA_ERROR;
120 }
121 else {
122 cout << "THaEtClient: error in station creation"<<endl;
123 return CODA_ERROR;
124 }
125 }
126 et_station_config_destroy(sconfig);
127 if (et_station_attach(id, my_stat, &my_att) < 0) {
128 cout << "THaEtClient: error in station attach"<<endl;
129 return CODA_ERROR;
130 }
131 return CODA_OK;
132}
133
135 if (didclose || firstread) return CODA_OK;
136 didclose = 1;
137 if (notopened) return CODA_ERROR;
138 if (et_station_detach(id, my_att) != ET_OK) {
139 cout << "ERROR: codaClose: detaching from ET"<<endl;
140 return CODA_ERROR;
141 }
142 if (et_close(id) != ET_OK) {
143 cout << "ERROR: codaClose: error closing ET"<<endl;
144 return CODA_ERROR;
145 }
146 return CODA_OK;
147}
148
150{
151 // Read a chunk of data, return read status (0 = ok, else not).
152 // To try to use network efficiently, it actually gets
153 // the events in chunks, and passes them to the user.
154
155 uint32_t *data = nullptr;
156#if ET_SYSTEM_NSTATS > 10
157 // CODA >= 2.6.2, including CODA 3
158 size_t nbytes = 0;
159 const size_t bpi = sizeof(UInt_t);
160#else
161 Int_t nbytes = 0;
162 const Int_t bpi = sizeof(UInt_t);
163#endif
164
165 if (firstread) {
166 firstread = 0;
167 Int_t status = init();
168 if (status == CODA_ERROR) {
169 cout << "THaEtClient: ERROR: codaRead, cannot connect to CODA"<<endl;
170 return CODA_ERROR;
171 }
172 }
173
174// pull out a ET_CHUNK_SIZE of events from ET
175 et_event *evs[ET_CHUNK_SIZE];
176 if (nused >= nread) {
177 int err;
178 if (waitflag == 0) {
179 err = et_events_get(id, my_att, evs, ET_SLEEP, nullptr, ET_CHUNK_SIZE, &nread);
180 } else {
181 struct timespec twait{};
182 twait.tv_sec = timeout;
183 twait.tv_nsec = 0;
184 err = et_events_get(id, my_att, evs, ET_TIMED, &twait, ET_CHUNK_SIZE, &nread);
185 }
186 if (err < ET_OK) {
187 if (err == ET_ERROR_TIMEOUT) {
188 printf("et_netclient: timeout calling et_events_get\n");
189 printf("Probably means CODA is not running...\n");
190 }
191 else {
192 printf("et_netclient: error calling et_events_get, %d\n", err);
193 }
194 nread = nused = 0;
195 return CODA_ERROR;
196 }
197
198// reset
199 nused = 0;
200
201 for (Int_t j=0; j < nread; j++) {
202 int swapflg = ET_NOSWAP;
203 et_event_getdata(evs[j], (void **) &data);
204 et_event_needtoswap(evs[j], &swapflg);
205 if (swapflg == ET_SWAP) {
206// The function et_event_CODAswap was removed with CODA 3.05/ET_VERSION 16
207#if ET_VERSION > 15
208 evioswap(data, 1, nullptr);
209#else
210 et_event_CODAswap(evs[j]);
211#endif
212 }
213
214 uint32_t event_size = *data + 1;
215 if( !evbuffer.grow(event_size) )
216 throw runtime_error("THaEtClient: Maximum event buffer size reached");
217 if (verbose > 1) {
218 cout<<"\n\n===== Event "<<j<<" length "<<event_size<<endl;
219 UInt_t *pdata = data;
220 for (UInt_t i=0; i < event_size; i++, pdata++) {
221 cout<<"evbuff["<<dec<<i<<"] = "<<*pdata<<" = 0x"<<hex<<*pdata<<endl;
222 }
223 }
224 }
225
226 if (firstRateCalc) {
227 firstRateCalc = 0;
228 daqt1 = time(nullptr);
229 }
230 else {
231 time_t daqt2 = time(nullptr);
232 double tdiff = difftime(daqt2, daqt1);
233 evsum += nread;
234 if ((tdiff > 4) && (evsum > 30)) {
235 double daqrate = static_cast<double>(evsum)/tdiff;
236 evsum = 0;
237 ratesum += daqrate;
238 double avgrate = ratesum/++xcnt;
239
240 if (verbose > 0) {
241 printf("ET rate %4.1f Hz in %2.0f sec, avg %4.1f Hz\n",
242 daqrate, tdiff, avgrate);
243 }
244 if (waitflag != 0) {
245 timeout = (avgrate > FAST) ? SMALL_TIMEOUT : BIG_TIMEOUT;
246 }
247 daqt1 = time(nullptr);
248 }
249 }
250 }
251
252// return an event
253 et_event_getdata(evs[nused], (void **) &data);
254 et_event_getlength(evs[nused], &nbytes);
255 if( !evbuffer.grow(nbytes/bpi+1) )
256 throw runtime_error("THaEtClient: Maximum event buffer size reached");
257 assert(bpi * evbuffer.size() >= (size_t)nbytes);
258 memcpy(evbuffer.get(), data, nbytes);
259 nused++;
260
261// if we've used all our events, put them back
262 if (nused >= nread) {
263 int err = et_events_put(id, my_att, evs, nread);
264 if (err < ET_OK) {
265 cout<<"THaEtClient::codaRead: ERROR: calling et_events_put"<<endl;
266 cout<<"This is potentially very bad !!\n"<<endl;
267 cout<<"best not continue.... exiting... \n"<<endl;
268 exit(1);
269 }
270 }
271 return CODA_OK;
272}
273
274Int_t THaEtClient::codaOpen(const char* computer,
275 const char* mysession,
276 Int_t smode)
277{
278 // To run codaOpen, you need to know:
279 // 1) What computer is ET running on ? (e.g. computer='adaql2')
280 // 2) What session ? (usually env. variable $SESSION, e.g. 'onla')
281 // 3) mode (0 = wait forever for data, 1 = time-out in a few seconds)
282 delete [] daqhost;
283 delete [] session;
284 delete [] etfile;
285 daqhost = new char[strlen(computer)+1];
286 strcpy(daqhost,computer);
287 etfile = new char[strlen(ETMEM_PREFIX)+strlen(mysession)+1];
288 strcpy(etfile,ETMEM_PREFIX);
289 strcat(etfile,mysession);
290 session = new char[strlen(mysession)+1];
291 strcpy(session,mysession);
292 waitflag = smode;
293 return CODA_OK;
294}
295
296Int_t THaEtClient::codaOpen(const char* computer, Int_t smode)
297{
298 // See comment in the above version of codaOpen()
299 char* s = getenv("SESSION");
300 if (s == nullptr)
301 return CODA_ERROR;
302 TString mysession(s);
303 return codaOpen( computer, mysession, smode );
304}
305
307 return (notopened==1&&didclose==0);
308}
309
310}
311
int Int_t
unsigned int UInt_t
uint32_t time
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
#define CODA_ERROR
Definition THaCodaData.h:30
#define CODA_OK
Definition THaCodaData.h:28
static const int SMALL_TIMEOUT
static const int FAST
static const int BIG_TIMEOUT
#define initflags
#define ETMEM_PREFIX
Definition THaEtClient.h:30
#define ET_CHUNK_SIZE
Definition THaEtClient.h:22
#define ADAQS2
Definition THaEtClient.h:38
UInt_t size() const
Definition THaCodaData.h:49
Bool_t grow(UInt_t newsize=0)
Int_t codaOpen(const char *computer, Int_t mode=1)
Int_t init(const char *computer="hana_sta")
virtual bool isOpen() const
THaEtClient(Int_t mode=1)
STL namespace.
ClassImp(TPyArg)