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

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