source: trunk/FACT++/src/EventBuilderWrapper.h@ 14177

Last change on this file since 14177 was 14020, checked in by tbretz, 12 years ago
Updated and fixed the event selection for the event display and the feedback
File size: 46.2 KB
Line 
1#ifndef FACT_EventBuilderWrapper
2#define FACT_EventBuilderWrapper
3
4#include <sstream>
5
6#if BOOST_VERSION < 104400
7#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4))
8#undef BOOST_HAS_RVALUE_REFS
9#endif
10#endif
11#include <boost/thread.hpp>
12#include <boost/filesystem.hpp>
13#include <boost/date_time/posix_time/posix_time_types.hpp>
14
15#include "DimWriteStatistics.h"
16
17#include "DataCalib.h"
18#include "DataWriteRaw.h"
19
20#ifdef HAVE_FITS
21#include "DataWriteFits.h"
22#else
23#define DataWriteFits DataWriteFits2
24#endif
25
26#include "DataWriteFits2.h"
27
28namespace ba = boost::asio;
29namespace bs = boost::system;
30namespace fs = boost::filesystem;
31
32using ba::ip::tcp;
33
34using namespace std;
35
36// ========================================================================
37
38#include "EventBuilder.h"
39
40extern "C" {
41 extern void StartEvtBuild();
42 extern int CloseRunFile(uint32_t runId, uint32_t closeTime, uint32_t maxEvt);
43}
44
45// ========================================================================
46
47class EventBuilderWrapper
48{
49public:
50 // FIXME
51 static EventBuilderWrapper *This;
52
53 MessageImp &fMsg;
54
55private:
56 boost::thread fThread;
57
58 enum CommandStates_t // g_runStat
59 {
60 kAbort = -2, // quit as soon as possible ('abort')
61 kExit = -1, // stop reading, quit when buffered events done ('exit')
62 kInitialize = 0, // 'initialize' (e.g. dim not yet started)
63 kHybernate = 1, // do nothing for long time ('hybernate') [wakeup within ~1sec]
64 kSleep = 2, // do nothing ('sleep') [wakeup within ~10msec]
65 kModeFlush = 10, // read data from camera, but skip them ('flush')
66 kModeTest = 20, // read data and process them, but do not write to disk ('test')
67 kModeFlag = 30, // read data, process and write all to disk ('flag')
68 kModeRun = 40, // read data, process and write selected to disk ('run')
69 };
70
71 enum
72 {
73 kCurrent = 0,
74 kTotal = 1,
75 kEventId = 2,
76 kTriggerId = 3,
77 };
78
79 FAD::FileFormat_t fFileFormat;
80
81 uint32_t fMaxRun;
82 uint32_t fLastOpened;
83 uint32_t fLastClosed;
84 uint32_t fNumEvts[4];
85
86 DimWriteStatistics fDimWriteStats;
87 DimDescribedService fDimRuns;
88 DimDescribedService fDimEvents;
89 DimDescribedService fDimRawData;
90 DimDescribedService fDimEventData;
91 DimDescribedService fDimFeedbackData;
92 DimDescribedService fDimFwVersion;
93 DimDescribedService fDimRunNumber;
94 DimDescribedService fDimStatus;
95 DimDescribedService fDimDNA;
96 DimDescribedService fDimTemperature;
97 DimDescribedService fDimPrescaler;
98 DimDescribedService fDimRefClock;
99 DimDescribedService fDimRoi;
100 DimDescribedService fDimDac;
101 DimDescribedService fDimDrsRuns;
102 DimDescribedService fDimDrsCalibration;
103 DimDescribedService fDimStatistics1;
104 DimDescribedService fDimStatistics2;
105 DimDescribedService fDimFileFormat;
106
107 bool fDebugStream;
108 bool fDebugRead;
109 bool fDebugLog;
110
111 string fPath;
112 uint32_t fRunNumber;
113
114protected:
115 int64_t InitRunNumber()
116 {
117 fRunNumber = 1000;
118
119 // Ensure that the night doesn't change during our check
120 const int check = Time().NightAsInt();
121
122 while (--fRunNumber>0)
123 {
124 const string name = DataProcessorImp::FormFileName(fPath, fRunNumber, "");
125
126 if (access((name+"bin").c_str(), F_OK) == 0)
127 break;
128 if (access((name+"fits").c_str(), F_OK) == 0)
129 break;
130 if (access((name+"drs.fits").c_str(), F_OK) == 0)
131 break;
132
133 }
134
135 if (check != Time().NightAsInt())
136 return InitRunNumber();
137
138 fRunNumber++;
139
140 if (fRunNumber==1000)
141 {
142 fMsg.Error("You have a file with run-number 1000 in "+fPath);
143 return -1;
144 }
145
146 ostringstream str;
147 str << "Set next run-number to " << fRunNumber << " determined from '" << (fPath.empty()?".":fPath) << "'";
148 fMsg.Message(str);
149
150 //fMsg.Info(" ==> TODO: Crosscheck with database!");
151
152 return check;
153 }
154
155 int64_t InitRunNumber(const string &path)
156 {
157 if (!DimWriteStatistics::DoesPathExist(path, fMsg))
158 {
159 fMsg.Error("Data path "+path+" does not exist!");
160 return -1;
161 }
162
163 //const fs::path fullPath = fs::system_complete(fs::path(path));
164
165 fPath = path;
166
167 fDimWriteStats.SetCurrentFolder(fPath);
168
169 return InitRunNumber();
170 }
171
172public:
173 EventBuilderWrapper(MessageImp &imp) : fMsg(imp),
174 fFileFormat(FAD::kNone), fMaxRun(0), fLastOpened(0), fLastClosed(0),
175 fDimWriteStats ("FAD_CONTROL", imp),
176 fDimRuns ("FAD_CONTROL/RUNS", "I:5;C",
177 "Run files statistics"
178 "|stats[int]:num of open run files, min/max run no, lastest opened or closed run"
179 "|file[string]:filename of last opened file"),
180 fDimEvents ("FAD_CONTROL/EVENTS", "I:4",
181 "Event counts"
182 "|evtsCount[int]:Num evts cur. run, total (all run), evt ID, trig. Num"),
183 fDimRawData ("FAD_CONTROL/RAW_DATA", "S:1;I:1;S:1;I:1;I:2;I:40;S:1440;S:160;F", ""),
184 fDimEventData ("FAD_CONTROL/EVENT_DATA", "F:1440;F:1440;F:1440;F:1440", ""),
185 fDimFeedbackData("FAD_CONTROL/FEEDBACK_DATA", "F:1440", ""),
186 fDimFwVersion ("FAD_CONTROL/FIRMWARE_VERSION", "F:42",
187 "Firmware version number of fad boards"
188 "|firmware[float]:Version number of firmware, for each board. 40=min, 41=max"),
189 fDimRunNumber ("FAD_CONTROL/RUN_NUMBER", "I:42",
190 "Run numbers coming from FAD boards"
191 "|runNumbers[int]:current run number of each FAD board. 40=min, 41=max"),
192 fDimStatus ("FAD_CONTROL/STATUS", "S:42",
193 "Status of FAD boards"
194 "|status[bitpattern]:Status of each FAD board. Maybe buggy"),
195 fDimDNA ("FAD_CONTROL/DNA", "X:40",
196 "DNA of FAD boards"
197 "|DNA[hex]:Hex identifier of each FAD board"),
198 fDimTemperature ("FAD_CONTROL/TEMPERATURE", "F:82",
199 "FADs temperatures"
200 "|temp[deg. C]:0 global min, 1-40 min, 41 global max, 42-81 max"),
201 fDimPrescaler ("FAD_CONTROL/PRESCALER", "S:42",
202 "Trigger generator prescaler of fad boards"
203 "|prescaler[int]:Trigger generator prescaler value, for each board"),
204 fDimRefClock ("FAD_CONTROL/REFERENCE_CLOCK", "I:42",
205 "Reference clock of FAD boards"
206 "|refClocks[t]:ref clocks of FAD boards. 40=min, 41=max"),
207 fDimRoi ("FAD_CONTROL/REGION_OF_INTEREST", "S:2", ""),
208 fDimDac ("FAD_CONTROL/DAC", "S:336",
209 "DAC settings of each FAD board"
210 "|DAC[int]:DAC counts, sequentially DAC 0 board 0, 0/1, 0/2... (plus min max)"),
211 fDimDrsRuns ("FAD_CONTROL/DRS_RUNS", "I:1;I:3", ""),
212 fDimDrsCalibration("FAD_CONTROL/DRS_CALIBRATION", "I:1;I:3;F:1474560;F:1474560;F:1474560;F:1474560;F:1474560;F:1474560;F:163840;F:163840", ""),
213 fDimStatistics1 ("FAD_CONTROL/STATISTICS1", "I:3;I:5;X:4;I:3;I:3;I:40;I:1;I:2;C:40;I:40;I:40;X:40",
214 "Event Builder status for GUI display"
215 "|threadInfo[int]:Number of read, proc and writes"
216 "|bufferInfo[int]:Events in buffer, incomp., comp., tot., max past cycle, total"
217 "|memInfo[int]:total buf. mem, used mem, max used, max past cycle"
218 "|EvtCnt[int]:Number of events skipped, written, with errors"
219 "|badRoi[int]:Num boards with wrong ROI in event, run or board"
220 "|badRoiBoard[int]:Num boards with wrong ROI"
221 "|deltaT[ms]:Time in ms for rates"
222 "|rateNew[int]:Number of new start events received"
223 "|numConn[int]:Number of connections per board"
224 "|errConn[int]:IO errors per board"
225 "|rateBytes[int]:Bytes read this cycle"
226 "|totBytes[int]:Bytes read (counter)"),
227 fDimStatistics2 ("FAD_CONTROL/STATISTICS2", "I:1;I:280;X:40;I:40;I:4;I:4;I:2;I:2;I:3;C:40",
228 "Event Builder status, events oriented"
229 "|reset[int]:If increased, reset all counters"
230 "|numRead[int]:How often sucessful read from N sockets per loop"
231 "|gotByte[int]:number of bytes read per board"
232 "|gotErr[int]:number of com. errors per board"
233 "|evtStat[int]:number of evts read, completed, with errors, incomplete"
234 "|procStat[int]:num. of evts proc., w probs, acc. or rej. by SW trigger"
235 "|feedStat[int]:number of evts used or rejected by feedback system"
236 "|wrtStat[int]:number of evts written to disk, with errors"
237 "|runStat[int]:number of run opened, closed, with open or close errors"
238 "|numConn[int]:number of sockets successfully opened per board"),
239 fDimFileFormat ("FAD_CONTROL/FILE_FORMAT", "S:1", ""),
240 fDebugStream(false), fDebugRead(false), fDebugLog(false)
241 {
242 if (This)
243 throw logic_error("EventBuilderWrapper cannot be instantiated twice.");
244
245 This = this;
246
247 memset(fNumEvts, 0, sizeof(fNumEvts));
248 fDimEvents.Update(fNumEvts);
249
250 for (size_t i=0; i<40; i++)
251 ConnectSlot(i, tcp::endpoint());
252 }
253 virtual ~EventBuilderWrapper()
254 {
255 Abort();
256
257 // FIXME: Used timed_join and abort afterwards
258 // What's the maximum time the eb need to abort?
259 fThread.join();
260 //ffMsg.Info("EventBuilder stopped.");
261
262 for (vector<DataProcessorImp*>::iterator it=fFiles.begin(); it!=fFiles.end(); it++)
263 delete *it;
264 }
265
266 set<uint32_t> fIsRunStarted;
267 map<uint32_t, FAD::RunDescription> fExpectedRuns;
268
269 uint32_t StartNewRun(int64_t maxtime, int64_t maxevt, const pair<string, FAD::Configuration> &ref)
270 {
271 if (maxtime<=0 || maxtime>24*60*60)
272 maxtime = 24*60*60;
273 if (maxevt<=0 || maxevt>INT32_MAX)
274 maxevt = INT32_MAX;
275
276 const FAD::RunDescription descr =
277 {
278 uint32_t(maxtime),
279 uint32_t(maxevt),
280 ref.first,
281 ref.second,
282 };
283
284 // FIMXE: Maybe reset an event counter so that the mcp can count events?
285
286 //fMsg.Info(" ==> TODO: Set a limit on the size of fExpectedRuns!");
287
288 fExpectedRuns[fRunNumber] = descr;
289 fIsRunStarted.insert(fRunNumber);
290 return fRunNumber++;
291 }
292
293 bool IsThreadRunning()
294 {
295 return !fThread.timed_join(boost::posix_time::microseconds(0));
296 }
297
298 void SetMaxMemory(unsigned int mb) const
299 {
300 /*
301 if (mb*1000000<GetUsedMemory())
302 {
303 // ffMsg.Warn("...");
304 return;
305 }*/
306
307 g_maxMem = size_t(mb)*1000000;
308 }
309
310 void StartThread(const vector<tcp::endpoint> &addr)
311 {
312 if (IsThreadRunning())
313 {
314 fMsg.Warn("Start - EventBuilder still running");
315 return;
316 }
317
318 fLastMessage.clear();
319
320 for (size_t i=0; i<40; i++)
321 ConnectSlot(i, addr[i]);
322
323 g_runStat = kModeRun;
324 g_maxProc = 3;
325
326 fMsg.Message("Starting EventBuilder thread");
327
328 fThread = boost::thread(StartEvtBuild);
329 }
330 void ConnectSlot(unsigned int i, const tcp::endpoint &addr)
331 {
332 if (i>39)
333 return;
334
335 if (addr==tcp::endpoint())
336 {
337 DisconnectSlot(i);
338 return;
339 }
340
341 g_port[i].sockAddr.sin_family = AF_INET;
342 g_port[i].sockAddr.sin_addr.s_addr = htonl(addr.address().to_v4().to_ulong());
343 g_port[i].sockAddr.sin_port = htons(addr.port());
344 // In this order
345 g_port[i].sockDef = 1;
346 }
347 void DisconnectSlot(unsigned int i)
348 {
349 if (i>39)
350 return;
351
352 g_port[i].sockDef = 0;
353 // In this order
354 g_port[i].sockAddr.sin_family = AF_INET;
355 g_port[i].sockAddr.sin_addr.s_addr = 0;
356 g_port[i].sockAddr.sin_port = 0;
357 }
358 void IgnoreSlot(unsigned int i)
359 {
360 if (i>39)
361 return;
362 if (g_port[i].sockAddr.sin_port==0)
363 return;
364
365 g_port[i].sockDef = -1;
366 }
367
368
369 void Abort()
370 {
371 fMsg.Message("Signal abort to EventBuilder thread...");
372 g_runStat = kAbort;
373 }
374
375 void ResetThread(bool soft)
376 {
377 /*
378 if (g_reset > 0)
379
380 * suspend reading
381 * reset = g_reset;
382 * g_reset=0
383
384 * reset% 10
385 == 0 leave event Buffers as they are
386 == 1 let all buffers drain (write (incomplete) events)
387 > 1 flush all buffers (do not write buffered events)
388
389 * (reset/10)%10
390 > 0 close all sockets and destroy them (also free the
391 allocated read-buffers)
392 recreate before resuming operation
393 [ this is more than just close/open that can be
394 triggered by e.g. close/open the base-socket ]
395
396 * (reset/100)%10
397 > 0 close all open run-files
398
399 * (reset/1000)
400 sleep so many seconds before resuming operation
401 (does not (yet) take into account time left when waiting
402 for buffers getting empty ...)
403
404 * resume_reading
405
406 */
407 fMsg.Message("Signal reset to EventBuilder thread...");
408 g_reset = soft ? 101 : 102;
409 }
410
411 void Exit()
412 {
413 fMsg.Message("Signal exit to EventBuilder thread...");
414 g_runStat = kExit;
415 }
416
417 /*
418 void Wait()
419 {
420 fThread.join();
421 ffMsg.Message("EventBuilder stopped.");
422 }*/
423
424 void Hybernate() const { g_runStat = kHybernate; }
425 void Sleep() const { g_runStat = kSleep; }
426 void FlushMode() const { g_runStat = kModeFlush; }
427 void TestMode() const { g_runStat = kModeTest; }
428 void FlagMode() const { g_runStat = kModeFlag; }
429 void RunMode() const { g_runStat = kModeRun; }
430
431 // FIXME: To be removed
432 //void SetMode(int mode) const { g_runStat = mode; }
433
434 bool IsConnected(int i) const { return gi_NumConnect[i]==7; }
435 bool IsConnecting(int i) const { return !IsConnected(i) && !IsDisconnected(i); }
436 bool IsDisconnected(int i) const { return gi_NumConnect[i]<=0 && g_port[i].sockDef==0; }
437 int GetNumConnected(int i) const { return gi_NumConnect[i]; }
438 int GetNumFilesOpen() const { return fFiles.size(); }
439
440 /*
441 bool IsConnected(int i) const { return gi_NumConnect[i]>0; }
442 bool IsConnecting(int i) const { return !IsConnected(i) && !IsDisconnected(i); }
443 bool IsDisconnected(int i) const { return gi_NumConnect[i]<=0 && g_port[i].sockDef==0; }
444 int GetNumConnected(int i) const { return gi_NumConnect[i]; }
445 */
446
447 void SetIgnore(int i, bool b) const { if (g_port[i].sockDef!=0) g_port[i].sockDef=b?-1:1; }
448 bool IsIgnored(int i) const { return g_port[i].sockDef==-1; }
449
450 void SetOutputFormat(FAD::FileFormat_t f)
451 {
452 fFileFormat = f;
453 fDimFileFormat.Update(uint16_t(f));
454 if (fFileFormat==FAD::kCalib)
455 {
456 DataCalib::Restart();
457 DataCalib::Update(fDimDrsCalibration, fDimDrsRuns);
458 fMsg.Message("Resetted DRS calibration.");
459 }
460 }
461
462 virtual int ResetSecondaryDrsBaseline()
463 {
464 if (DataCalib::ResetTrgOff(fDimDrsCalibration, fDimDrsRuns))
465 {
466 fFileFormat = FAD::kCalib;
467 fDimFileFormat.Update(uint16_t(fFileFormat));
468 fMsg.Message("Resetted DRS calibration for secondary baseline.");
469 }
470 else
471 fMsg.Warn("Could not reset DRS calibration of secondary baseline.");
472
473 return 0;
474 }
475
476 void SetDebugLog(bool b) { fDebugLog = b; }
477
478 void SetDebugStream(bool b)
479 {
480 fDebugStream = b;
481 if (b)
482 return;
483
484 for (int i=0; i<40; i++)
485 {
486 if (!fDumpStream[i].is_open())
487 continue;
488
489 fDumpStream[i].close();
490
491 ostringstream name;
492 name << "socket_dump-" << setfill('0') << setw(2) << i << ".bin";
493 fMsg.Message("Closed file '"+name.str()+"'");
494 }
495 }
496
497 void SetDebugRead(bool b)
498 {
499 fDebugRead = b;
500 if (b || !fDumpRead.is_open())
501 return;
502
503 fDumpRead.close();
504 fMsg.Message("Closed file 'socket_events.txt'");
505 }
506
507// size_t GetUsedMemory() const { return gi_usedMem; }
508
509 void LoadDrsCalibration(const char *fname)
510 {
511 if (!DataCalib::ReadFits(fname, fMsg))
512 return;
513 fMsg.Info("Successfully loaded DRS calibration from "+string(fname));
514 DataCalib::Update(fDimDrsCalibration, fDimDrsRuns);
515 }
516
517 virtual int CloseOpenFiles() { CloseRunFile(0, 0, 0); return 0; }
518
519
520 /*
521 struct OpenFileToDim
522 {
523 int code;
524 char fileName[FILENAME_MAX];
525 };
526
527 SignalRunOpened(runid, filename);
528 // Send num open files
529 // Send runid, (more info about the run?), filename via dim
530
531 SignalEvtWritten(runid);
532 // Send num events written of newest file
533
534 SignalRunClose(runid);
535 // Send new num open files
536 // Send empty file-name if no file is open
537
538 */
539
540 // -------------- Mapped event builder callbacks ------------------
541
542 void UpdateRuns(const string &fname="")
543 {
544 uint32_t values[5] =
545 {
546 static_cast<uint32_t>(fFiles.size()),
547 0xffffffff,
548 0,
549 fLastOpened,
550 fLastClosed
551 };
552
553 for (vector<DataProcessorImp*>::const_iterator it=fFiles.begin();
554 it!=fFiles.end(); it++)
555 {
556 const DataProcessorImp *file = *it;
557
558 if (file->GetRunId()<values[1])
559 values[1] = file->GetRunId();
560
561 if (file->GetRunId()>values[2])
562 values[2] = file->GetRunId();
563 }
564
565 fMaxRun = values[2];
566
567 vector<char> data(sizeof(values)+fname.size()+1);
568 memcpy(data.data(), values, sizeof(values));
569 strcpy(data.data()+sizeof(values), fname.c_str());
570
571 fDimRuns.Update(data);
572 }
573
574 vector<DataProcessorImp*> fFiles;
575
576 FileHandle_t runOpen(uint32_t runid, RUN_HEAD *h, size_t)
577 {
578 //fMsg.Info(" ==> TODO: Update run configuration in database!");
579
580 map<uint32_t,FAD::RunDescription>::iterator it = fExpectedRuns.begin();
581 while (it!=fExpectedRuns.end())
582 {
583 if (it->first<runid)
584 {
585 ostringstream str;
586 str << "runOpen - Missed run " << it->first << ".";
587 fMsg.Info(str);
588
589 fExpectedRuns.erase(it++);
590 continue;
591 }
592 if (it->first==runid)
593 break;
594 it++;
595 }
596
597 FAD::RunDescription desc;
598
599 if (it==fExpectedRuns.end())
600 {
601 ostringstream str;
602 str << "runOpen - Run " << runid << " wasn't expected (maybe manual triggers)";
603 fMsg.Warn(str);
604 }
605 else
606 {
607 desc = it->second;
608 fExpectedRuns.erase(it);
609 }
610
611 // Check if file already exists...
612 DataProcessorImp *file = 0;
613 switch (fFileFormat)
614 {
615 case FAD::kNone: file = new DataDump(fPath, runid, fMsg); break;
616 case FAD::kDebug: file = new DataDebug(fPath, runid, fMsg); break;
617 case FAD::kCfitsio: file = new DataWriteFits(fPath, runid, fMsg); break;
618 case FAD::kFits: file = new DataWriteFits2(fPath, runid, fMsg); break;
619 case FAD::kRaw: file = new DataWriteRaw(fPath, runid, fMsg); break;
620 case FAD::kCalib: file = new DataCalib(fPath, runid, fDimDrsCalibration, fDimDrsRuns, fMsg); break;
621 }
622
623 try
624 {
625 if (!file->Open(h, desc))
626 return 0;
627 }
628 catch (const exception &e)
629 {
630 fMsg.Error("Exception trying to open file: "+string(e.what()));
631 return 0;
632 }
633
634 fFiles.push_back(file);
635
636 ostringstream str;
637 str << "Opened: " << file->GetFileName() << " (" << file->GetRunId() << ")";
638 fMsg.Info(str);
639
640 fDimWriteStats.FileOpened(file->GetFileName());
641
642 fLastOpened = runid;
643 UpdateRuns(file->GetFileName());
644
645 fNumEvts[kEventId] = 0;
646 fNumEvts[kTriggerId] = 0;
647
648 fNumEvts[kCurrent] = 0;
649 fDimEvents.Update(fNumEvts);
650 // fDimCurrentEvent.Update(uint32_t(0));
651
652 return reinterpret_cast<FileHandle_t>(file);
653 }
654
655 int runWrite(FileHandle_t handler, EVENT *e, size_t /*sz*/)
656 {
657 DataProcessorImp *file = reinterpret_cast<DataProcessorImp*>(handler);
658
659 if (!file->WriteEvt(e))
660 return -1;
661
662 if (file->GetRunId()==fMaxRun)
663 {
664 fNumEvts[kCurrent]++;
665 fNumEvts[kEventId] = e->EventNum;
666 fNumEvts[kTriggerId] = e->TriggerNum;
667 }
668
669 fNumEvts[kTotal]++;
670
671 static Time oldt(boost::date_time::neg_infin);
672 Time newt;
673 if (newt>oldt+boost::posix_time::seconds(1))
674 {
675 fDimEvents.Update(fNumEvts);
676 oldt = newt;
677 }
678
679
680 // ===> SignalEvtWritten(runid);
681 // Send num events written of newest file
682
683 /* close run runId (all all runs if runId=0) */
684 /* return: 0=close scheduled / >0 already closed / <0 does not exist */
685 //CloseRunFile(file->GetRunId(), time(NULL)+2) ;
686
687 return 0;
688 }
689
690 virtual void CloseRun(uint32_t /*runid*/) { }
691
692 int runClose(FileHandle_t handler, RUN_TAIL *tail, size_t)
693 {
694 //fMsg.Info(" ==> TODO: Update run configuration in database!");
695
696 DataProcessorImp *file = reinterpret_cast<DataProcessorImp*>(handler);
697
698 const vector<DataProcessorImp*>::iterator it = find(fFiles.begin(), fFiles.end(), file);
699 if (it==fFiles.end())
700 {
701 ostringstream str;
702 str << "File handler (" << handler << ") requested to close by event builder doesn't exist.";
703 fMsg.Fatal(str);
704 return -1;
705 }
706
707 fFiles.erase(it);
708
709 fLastClosed = file->GetRunId();
710 CloseRun(fLastClosed);
711 UpdateRuns();
712
713 fDimEvents.Update(fNumEvts);
714
715 const bool rc = file->Close(tail);
716 if (!rc)
717 {
718 // Error message
719 }
720
721 ostringstream str;
722 str << "Closed: " << file->GetFileName() << " (" << file->GetRunId() << ")";
723 fMsg.Info(str);
724
725 delete file;
726
727 // ==> SignalRunClose(runid);
728 // Send new num open files
729 // Send empty file-name if no file is open
730
731 return rc ? 0 : -1;
732 }
733
734 ofstream fDumpStream[40];
735
736 void debugStream(int isock, void *buf, int len)
737 {
738 if (!fDebugStream)
739 return;
740
741 const int slot = isock/7;
742 if (slot<0 || slot>39)
743 return;
744
745 if (!fDumpStream[slot].is_open())
746 {
747 ostringstream name;
748 name << "socket_dump-" << setfill('0') << setw(2) << slot << ".bin";
749
750 fDumpStream[slot].open(name.str().c_str(), ios::app);
751 if (!fDumpStream[slot])
752 {
753 ostringstream str;
754 str << "Open file '" << name << "': " << strerror(errno) << " (errno=" << errno << ")";
755 fMsg.Error(str);
756
757 return;
758 }
759
760 fMsg.Message("Opened file '"+name.str()+"' for writing.");
761 }
762
763 fDumpStream[slot].write(reinterpret_cast<const char*>(buf), len);
764 }
765
766 ofstream fDumpRead; // Stream to possibly dump docket events
767
768 void debugRead(int isock, int ibyte, uint32_t event, uint32_t ftmevt, uint32_t runno, int state, uint32_t tsec, uint32_t tusec)
769 {
770 // isock = socketID (0-279)
771 // ibyte = #bytes gelesen
772 // event = eventId (oder 0 wenn noch nicht bekannt)
773 // state : 1=finished reading data
774 // 0=reading data
775 // -1=start reading data (header)
776 // -2=start reading data,
777 // eventId not known yet (too little data)
778 // tsec, tusec = time when reading seconds, microseconds
779 //
780 if (!fDebugRead || ibyte==0)
781 return;
782
783 if (!fDumpRead.is_open())
784 {
785 fDumpRead.open("socket_events.txt", ios::app);
786 if (!fDumpRead)
787 {
788 ostringstream str;
789 str << "Open file 'socket_events.txt': " << strerror(errno) << " (errno=" << errno << ")";
790 fMsg.Error(str);
791
792 return;
793 }
794
795 fMsg.Message("Opened file 'socket_events.txt' for writing.");
796
797 fDumpRead << "# START: " << Time().GetAsStr() << endl;
798 fDumpRead << "# state time_sec time_usec socket slot runno event_id trigger_id bytes_received" << endl;
799 }
800
801 fDumpRead
802 << setw(2) << state << " "
803 << setw(8) << tsec << " "
804 << setw(9) << tusec << " "
805 << setw(3) << isock << " "
806 << setw(2) << isock/7 << " "
807 << runno << " "
808 << event << " "
809 << ftmevt << " "
810 << ibyte << endl;
811 }
812
813 array<uint16_t,2> fVecRoi;
814
815 int eventCheck(uint32_t runNr, PEVNT_HEADER *fadhd, EVENT *event, int /*iboard*/)
816 {
817 /*
818 fadhd[i] ist ein array mit den 40 fad-headers
819 (falls ein board nicht gelesen wurde, ist start_package_flag =0 )
820
821 event ist die Struktur, die auch die write routine erhaelt;
822 darin sind im header die 'soll-werte' fuer z.B. eventID
823 als auch die ADC-Werte (falls Du die brauchst)
824
825 Wenn die routine einen negativen Wert liefert, wird das event
826 geloescht (nicht an die write-routine weitergeleitet [mind. im Prinzip]
827 */
828
829 const array<uint16_t,2> roi = {{ event->Roi, event->RoiTM }};
830
831 if (roi!=fVecRoi)
832 {
833 Update(fDimRoi, roi);
834 fVecRoi = roi;
835 }
836
837 const FAD::EventHeader *beg = reinterpret_cast<FAD::EventHeader*>(fadhd);
838 const FAD::EventHeader *end = reinterpret_cast<FAD::EventHeader*>(fadhd)+40;
839
840 // FIMXE: Compare with target configuration
841
842 for (const FAD::EventHeader *ptr=beg; ptr!=end; ptr++)
843 {
844 // FIXME: Compare with expectations!!!
845 if (ptr->fStartDelimiter==0)
846 {
847 if (ptr==beg)
848 beg++;
849 continue;
850 }
851
852 if (beg->fStatus != ptr->fStatus)
853 {
854 fMsg.Error("Inconsistency in FAD status detected.... closing run.");
855 CloseRunFile(runNr, 0, 0);
856 return -1;
857 }
858
859 if (beg->fRunNumber != ptr->fRunNumber)
860 {
861 fMsg.Error("Inconsistent run number detected.... closing run.");
862 CloseRunFile(runNr, 0, 0);
863 return -1;
864 }
865
866 /*
867 if (beg->fVersion != ptr->fVersion)
868 {
869 Error("Inconsist firmware version detected.... closing run.");
870 CloseRunFile(runNr, 0, 0);
871 break;
872 }
873 */
874 if (beg->fEventCounter != ptr->fEventCounter)
875 {
876 fMsg.Error("Inconsistent FAD event number detected.... closing run.");
877 CloseRunFile(runNr, 0, 0);
878 return -1;
879 }
880
881 if (beg->fTriggerCounter != ptr->fTriggerCounter)
882 {
883 fMsg.Error("Inconsistent FTM trigger number detected.... closing run.");
884 CloseRunFile(runNr, 0, 0);
885 return -1;
886 }
887
888 if (beg->fAdcClockPhaseShift != ptr->fAdcClockPhaseShift)
889 {
890 fMsg.Error("Inconsistent phase shift detected.... closing run.");
891 CloseRunFile(runNr, 0, 0);
892 return -1;
893 }
894
895 if (memcmp(beg->fDac, ptr->fDac, sizeof(beg->fDac)))
896 {
897 fMsg.Error("Inconsistent DAC values detected.... closing run.");
898 CloseRunFile(runNr, 0, 0);
899 return -1;
900 }
901
902 if (beg->fTriggerType != ptr->fTriggerType)
903 {
904 fMsg.Error("Inconsistent trigger type detected.... closing run.");
905 CloseRunFile(runNr, 0, 0);
906 return -1;
907 }
908 }
909
910 // check REFCLK_frequency
911 // check consistency with command configuration
912 // how to log errors?
913 // need gotNewRun/closedRun to know it is finished
914
915 return 0;
916 }
917
918 void SendRawData(PEVNT_HEADER *fadhd, EVENT *event)
919 {
920 // Currently we send any event no matter what its trigger id is...
921 // To be changed.
922 static Time oldt(boost::date_time::neg_infin);
923 Time newt;
924
925 static int skip = 0;
926
927 // FIXME: Only send events if the have newer run-numbers
928 if (newt<oldt+boost::posix_time::milliseconds(skip>0 ? 100 : 1000))
929 return;
930 oldt = newt;
931
932 // Workaround to find a valid header.....
933 const FAD::EventHeader *beg = reinterpret_cast<FAD::EventHeader*>(fadhd);
934 const FAD::EventHeader *end = reinterpret_cast<FAD::EventHeader*>(fadhd)+40;
935
936 // FIMXE: Compare with target configuration
937 const FAD::EventHeader *ptr=beg;
938 for (; ptr!=end; ptr++)
939 {
940 if (ptr->fStartDelimiter!=0)
941 break;
942 }
943 if (ptr==end)
944 return;
945
946
947 vector<char> data(sizeof(EVENT)+event->Roi*sizeof(float)*(1440+160));
948 memcpy(data.data(), event, sizeof(EVENT));
949
950 float *vec = reinterpret_cast<float*>(data.data()+sizeof(EVENT));
951
952 DataCalib::Apply(vec, event->Adc_Data, event->StartPix, event->Roi);
953 DrsCalibrate::RemoveSpikes(vec, event->Roi);
954
955 vector<float> data2(1440*4); // Mean, RMS, Max, Pos
956 const double max = DrsCalibrate::GetPixelStats(data2.data(), vec, event->Roi);
957
958 // Maximum above roughly 5pe
959 if (ptr->IsTriggerPhys() && max<100 && skip<10)
960 {
961 skip++;
962 return;
963 }
964
965 skip = 0;
966
967 fDimRawData.setQuality(ptr->fTriggerType);
968 fDimRawData.Update(data);
969
970 fDimEventData.setQuality(ptr->fTriggerType);
971 fDimEventData.Update(data2);
972 }
973
974 void SendFeedbackData(PEVNT_HEADER *fadhd, EVENT *event)
975 {
976 if (!DataCalib::IsValid())
977 return;
978
979 // Workaround to find a valid header.....
980 const FAD::EventHeader *beg = reinterpret_cast<FAD::EventHeader*>(fadhd);
981 const FAD::EventHeader *end = reinterpret_cast<FAD::EventHeader*>(fadhd)+40;
982
983 // FIMXE: Compare with target configuration
984
985 const FAD::EventHeader *ptr=beg;
986 for (; ptr<end; ptr++)
987 {
988 if (ptr->fStartDelimiter!=0)
989 break;
990 }
991
992 if (ptr==end)
993 return;
994
995 if (!ptr->HasTriggerLPext() && !ptr->HasTriggerLPint())
996 return;
997
998 vector<float> data(event->Roi*1440);
999 DataCalib::Apply(data.data(), event->Adc_Data, event->StartPix, event->Roi);
1000
1001 DrsCalibrate::RemoveSpikes(data.data(), event->Roi);
1002
1003 vector<float> data2(1440); // Mean, RMS, Max, Pos, first, last
1004 DrsCalibrate::GetPixelMax(data2.data(), data.data(), event->Roi, 0, event->Roi-1);
1005
1006 fDimFeedbackData.Update(data2);
1007 }
1008
1009 int subProcEvt(int threadID, PEVNT_HEADER *fadhd, EVENT *event, int16_t /*iboard*/, void */*buffer*/)
1010 {
1011 switch (threadID)
1012 {
1013 case 0:
1014 SendRawData(fadhd, event);
1015 return 1;
1016 case 1:
1017 SendFeedbackData(fadhd, event);
1018 return 2;
1019 }
1020 return 100;
1021 }
1022
1023
1024 bool IsRunStarted() const
1025 {
1026 const set<uint32_t>::const_iterator it = fIsRunStarted.find(fRunNumber-1);
1027 return it==fIsRunStarted.end();// ? true : it->second.started;
1028 }
1029
1030 uint32_t GetRunNumber() const
1031 {
1032 return fRunNumber;
1033 }
1034
1035 void IncreaseRunNumber(uint32_t run)
1036 {
1037 if (run>fRunNumber)
1038 fRunNumber = run;
1039 }
1040
1041 void gotNewRun(uint32_t runnr, PEVNT_HEADER */*headers*/)
1042 {
1043 // This function is called even when writing is switched off
1044 set<uint32_t>::iterator it = fIsRunStarted.begin();
1045 while (it!=fIsRunStarted.end())
1046 {
1047 if (*it<runnr)
1048 {
1049 ostringstream str;
1050 str << "gotNewRun - Missed run " << *it << ".";
1051 fMsg.Info(str);
1052
1053 fIsRunStarted.erase(it++);
1054 continue;
1055 }
1056 if (*it==runnr)
1057 break;
1058 it++;
1059 }
1060 if (it==fIsRunStarted.end())
1061 {
1062 ostringstream str;
1063 str << "gotNewRun - Not waiting for run " << runnr << ".";
1064 fMsg.Warn(str);
1065 return;
1066 }
1067
1068 map<uint32_t,FAD::RunDescription>::iterator i2 = fExpectedRuns.find(runnr);
1069 if (i2==fExpectedRuns.end())
1070 {
1071 ostringstream str;
1072 str << "gotNewRun - Run " << runnr << " wasn't expected.";
1073 fMsg.Warn(str);
1074 return;
1075 }
1076
1077 CloseRunFile(runnr, time(NULL)+i2->second.maxtime, i2->second.maxevt);
1078 // return: 0=close scheduled / >0 already closed / <0 does not exist
1079
1080 // FIXME: Move configuration from expected runs to runs which will soon
1081 // be opened/closed
1082
1083 fIsRunStarted.erase(it);
1084 }
1085
1086 map<boost::thread::id, string> fLastMessage;
1087
1088 void factOut(int severity, int err, const char *message)
1089 {
1090 if (!fDebugLog && severity==99)
1091 return;
1092
1093 ostringstream str;
1094 //str << boost::this_thread::get_id() << " ";
1095 str << "EventBuilder(";
1096 if (err<0)
1097 str << "---";
1098 else
1099 str << err;
1100 str << "): " << message;
1101
1102 string &old = fLastMessage[boost::this_thread::get_id()];
1103
1104 if (str.str()==old)
1105 return;
1106 old = str.str();
1107
1108 fMsg.Update(str, severity);
1109 }
1110/*
1111 void factStat(int64_t *stat, int len)
1112 {
1113 if (len!=7)
1114 {
1115 fMsg.Warn("factStat received unknown number of values.");
1116 return;
1117 }
1118
1119 vector<int64_t> data(1, g_maxMem);
1120 data.insert(data.end(), stat, stat+len);
1121
1122 static vector<int64_t> last(8);
1123 if (data==last)
1124 return;
1125 last = data;
1126
1127 fDimStatistics.Update(data);
1128
1129 // len ist die Laenge des arrays.
1130 // array[4] enthaelt wieviele bytes im Buffer aktuell belegt sind; daran
1131 // kannst Du pruefen, ob die 100MB voll sind ....
1132
1133 ostringstream str;
1134 str
1135 << "Wait=" << stat[0] << " "
1136 << "Skip=" << stat[1] << " "
1137 << "Del=" << stat[2] << " "
1138 << "Tot=" << stat[3] << " "
1139 << "Mem=" << stat[4] << "/" << g_maxMem << " "
1140 << "Read=" << stat[5] << " "
1141 << "Conn=" << stat[6];
1142
1143 fMsg.Info(str);
1144 }
1145 */
1146
1147 void factStat(const EVT_STAT &stat)
1148 {
1149 fDimStatistics2.Update(stat);
1150 }
1151
1152 void factStat(const GUI_STAT &stat)
1153 {
1154 fDimStatistics1.Update(stat);
1155 }
1156
1157
1158 array<FAD::EventHeader, 40> fVecHeader;
1159
1160 template<typename T, class S>
1161 array<T, 42> Compare(const S *vec, const T *t)
1162 {
1163 const int offset = reinterpret_cast<const char *>(t) - reinterpret_cast<const char *>(vec);
1164
1165 const T *min = NULL;
1166 const T *val = NULL;
1167 const T *max = NULL;
1168
1169 array<T, 42> arr;
1170
1171 // bool rc = true;
1172 for (int i=0; i<40; i++)
1173 {
1174 const char *base = reinterpret_cast<const char*>(vec+i);
1175 const T *ref = reinterpret_cast<const T*>(base+offset);
1176
1177 arr[i] = *ref;
1178
1179 if (gi_NumConnect[i]!=7)
1180 {
1181 arr[i] = 0;
1182 continue;
1183 }
1184
1185 if (!val)
1186 {
1187 min = ref;
1188 val = ref;
1189 max = ref;
1190 }
1191
1192 if (*ref<*min)
1193 min = ref;
1194
1195 if (*ref>*max)
1196 max = ref;
1197
1198 // if (*val!=*ref)
1199 // rc = false;
1200 }
1201
1202 arr[40] = val ? *min : 1;
1203 arr[41] = val ? *max : 0;
1204
1205 return arr;
1206 }
1207
1208 template<typename T>
1209 array<T, 42> CompareBits(const FAD::EventHeader *h, const T *t)
1210 {
1211 const int offset = reinterpret_cast<const char *>(t) - reinterpret_cast<const char *>(h);
1212
1213 T val = 0;
1214 T rc = 0;
1215
1216 array<T, 42> vec;
1217
1218 bool first = true;
1219
1220 for (int i=0; i<40; i++)
1221 {
1222 const char *base = reinterpret_cast<const char*>(&fVecHeader[i]);
1223 const T *ref = reinterpret_cast<const T*>(base+offset);
1224
1225 vec[i+2] = *ref;
1226
1227 if (gi_NumConnect[i]!=7)
1228 {
1229 vec[i+2] = 0;
1230 continue;
1231 }
1232
1233 if (first)
1234 {
1235 first = false;
1236 val = *ref;
1237 rc = 0;
1238 }
1239
1240 rc |= val^*ref;
1241 }
1242
1243 vec[0] = rc;
1244 vec[1] = val;
1245
1246 return vec;
1247 }
1248
1249 template<typename T, size_t N>
1250 void Update(DimDescribedService &svc, const array<T, N> &data, int n=N)
1251 {
1252// svc.setQuality(vec[40]<=vec[41]);
1253 svc.setData(const_cast<T*>(data.data()), sizeof(T)*n);
1254 svc.Update();
1255 }
1256
1257 template<typename T>
1258 void Print(const char *name, const pair<bool,array<T, 43>> &data)
1259 {
1260 cout << name << "|" << data.first << "|" << data.second[1] << "|" << data.second[0] << "<x<" << data.second[1] << ":";
1261 for (int i=0; i<40;i++)
1262 cout << " " << data.second[i+3];
1263 cout << endl;
1264 }
1265
1266 vector<uint> fNumConnected;
1267
1268 void debugHead(int /*socket*/, const FAD::EventHeader &h)
1269 {
1270 const uint16_t id = h.Id();
1271 if (id>39)
1272 return;
1273
1274 if (fNumConnected.size()!=40)
1275 fNumConnected.resize(40);
1276
1277 const vector<uint> con(gi_NumConnect, gi_NumConnect+40);
1278
1279 const bool changed = con!=fNumConnected || !IsThreadRunning();
1280
1281 fNumConnected = con;
1282
1283 const FAD::EventHeader old = fVecHeader[id];
1284 fVecHeader[id] = h;
1285
1286 if (old.fVersion != h.fVersion || changed)
1287 {
1288 const array<uint16_t,42> ver = Compare(&fVecHeader[0], &fVecHeader[0].fVersion);
1289
1290 array<float,42> data;
1291 for (int i=0; i<42; i++)
1292 {
1293 ostringstream str;
1294 str << (ver[i]>>8) << '.' << (ver[i]&0xff);
1295 data[i] = stof(str.str());
1296 }
1297 Update(fDimFwVersion, data);
1298 }
1299
1300 if (old.fRunNumber != h.fRunNumber || changed)
1301 {
1302 const array<uint32_t,42> run = Compare(&fVecHeader[0], &fVecHeader[0].fRunNumber);
1303 fDimRunNumber.Update(run);
1304 }
1305
1306 if (old.fTriggerGeneratorPrescaler != h.fTriggerGeneratorPrescaler || changed)
1307 {
1308 const array<uint16_t,42> pre = Compare(&fVecHeader[0], &fVecHeader[0].fTriggerGeneratorPrescaler);
1309 fDimPrescaler.Update(pre);
1310 }
1311
1312 if (old.fDNA != h.fDNA || changed)
1313 {
1314 const array<uint64_t,42> dna = Compare(&fVecHeader[0], &fVecHeader[0].fDNA);
1315 Update(fDimDNA, dna, 40);
1316 }
1317
1318 if (old.fStatus != h.fStatus || changed)
1319 {
1320 const array<uint16_t,42> sts = CompareBits(&fVecHeader[0], &fVecHeader[0].fStatus);
1321 Update(fDimStatus, sts);
1322 }
1323
1324 if (memcmp(old.fDac, h.fDac, sizeof(h.fDac)) || changed)
1325 {
1326 array<uint16_t, FAD::kNumDac*42> dacs;
1327
1328 for (int i=0; i<FAD::kNumDac; i++)
1329 {
1330 const array<uint16_t, 42> dac = Compare(&fVecHeader[0], &fVecHeader[0].fDac[i]);
1331 memcpy(&dacs[i*42], &dac[0], sizeof(uint16_t)*42);
1332 }
1333
1334 Update(fDimDac, dacs);
1335 }
1336
1337 // -----------
1338
1339 static Time oldt(boost::date_time::neg_infin);
1340 Time newt;
1341
1342 if (newt>oldt+boost::posix_time::seconds(1))
1343 {
1344 oldt = newt;
1345
1346 // --- RefClock
1347
1348 const array<uint32_t,42> clk = Compare(&fVecHeader[0], &fVecHeader[0].fFreqRefClock);
1349 Update(fDimRefClock, clk);
1350
1351 // --- Temperatures
1352
1353 const array<int16_t,42> tmp[4] =
1354 {
1355 Compare(&fVecHeader[0], &fVecHeader[0].fTempDrs[0]), // 0-39:val, 40:min, 41:max
1356 Compare(&fVecHeader[0], &fVecHeader[0].fTempDrs[1]), // 0-39:val, 40:min, 41:max
1357 Compare(&fVecHeader[0], &fVecHeader[0].fTempDrs[2]), // 0-39:val, 40:min, 41:max
1358 Compare(&fVecHeader[0], &fVecHeader[0].fTempDrs[3]) // 0-39:val, 40:min, 41:max
1359 };
1360
1361 vector<int16_t> data;
1362 data.reserve(82);
1363 data.push_back(tmp[0][40]); // min: 0
1364 data.insert(data.end(), tmp[0].data(), tmp[0].data()+40); // val: 1-40
1365 data.push_back(tmp[0][41]); // max: 41
1366 data.insert(data.end(), tmp[0].data(), tmp[0].data()+40); // val: 42-81
1367
1368 for (int j=1; j<=3; j++)
1369 {
1370 const array<int16_t,42> &ref = tmp[j];
1371
1372 // Gloabl min
1373 if (ref[40]<data[0]) // 40=min
1374 data[0] = ref[40];
1375
1376 // Global max
1377 if (ref[41]>data[41]) // 41=max
1378 data[41] = ref[41];
1379
1380 for (int i=0; i<40; i++)
1381 {
1382 // min per board
1383 if (ref[i]<data[i+1]) // data: 1-40
1384 data[i+1] = ref[i]; // ref: 0-39
1385
1386 // max per board
1387 if (ref[i]>data[i+42]) // data: 42-81
1388 data[i+42] = ref[i]; // ref: 0-39
1389 }
1390
1391
1392 }
1393
1394 vector<float> deg(82); // 0: global min, 1-40: min
1395 for (int i=0; i<82; i++) // 41: global max, 42-81: max
1396 deg[i] = data[i]/16.;
1397 fDimTemperature.Update(deg);
1398 }
1399 }
1400};
1401
1402EventBuilderWrapper *EventBuilderWrapper::This = 0;
1403
1404// ----------- Event builder callbacks implementation ---------------
1405extern "C"
1406{
1407 FileHandle_t runOpen(uint32_t irun, RUN_HEAD *runhd, size_t len)
1408 {
1409 return EventBuilderWrapper::This->runOpen(irun, runhd, len);
1410 }
1411
1412 int runWrite(FileHandle_t fileId, EVENT *event, size_t len)
1413 {
1414 return EventBuilderWrapper::This->runWrite(fileId, event, len);
1415 }
1416
1417 int runClose(FileHandle_t fileId, RUN_TAIL *runth, size_t len)
1418 {
1419 return EventBuilderWrapper::This->runClose(fileId, runth, len);
1420 }
1421
1422 // -----
1423
1424 //void *runStart(uint32_t /*irun*/, RUN_HEAD */*runhd*/, size_t /*len*/)
1425 //{
1426 // return NULL;
1427 //}
1428
1429 int subProcEvt(int threadID, PEVNT_HEADER *fadhd, EVENT *event, int16_t mboard, void *runPtr)
1430 {
1431 return EventBuilderWrapper::This->subProcEvt(threadID, fadhd, event, mboard, runPtr);
1432 }
1433
1434 int runEnd(uint32_t, void */*runPtr*/)
1435 {
1436 return 0;
1437 }
1438
1439 // -----
1440
1441 int eventCheck(uint32_t runNr, PEVNT_HEADER *fadhd, EVENT *event, int mboard)
1442 {
1443 return EventBuilderWrapper::This->eventCheck(runNr, fadhd, event, mboard);
1444 }
1445
1446 void gotNewRun(uint32_t runnr, PEVNT_HEADER *headers)
1447 {
1448 return EventBuilderWrapper::This->gotNewRun(runnr, headers);
1449 }
1450
1451 // -----
1452
1453 void factOut(int severity, int err, const char *message)
1454 {
1455 EventBuilderWrapper::This->factOut(severity, err, message);
1456 }
1457
1458 void factStat(GUI_STAT stat)
1459 {
1460 EventBuilderWrapper::This->factStat(stat);
1461 }
1462
1463 void factStatNew(EVT_STAT stat)
1464 {
1465 EventBuilderWrapper::This->factStat(stat);
1466 }
1467
1468 // ------
1469
1470 void debugHead(int socket, int/*board*/, void *buf)
1471 {
1472 const FAD::EventHeader &h = *reinterpret_cast<FAD::EventHeader*>(buf);
1473 EventBuilderWrapper::This->debugHead(socket, h);
1474 }
1475
1476 void debugStream(int isock, void *buf, int len)
1477 {
1478 return EventBuilderWrapper::This->debugStream(isock, buf, len);
1479 }
1480
1481 void debugRead(int isock, int ibyte, int32_t event, int32_t ftmevt, int32_t runno, int state, uint32_t tsec, uint32_t tusec)
1482 {
1483 EventBuilderWrapper::This->debugRead(isock, ibyte, event, ftmevt, runno, state, tsec, tusec);
1484 }
1485}
1486
1487#endif
Note: See TracBrowser for help on using the repository browser.