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

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