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

Last change on this file since 15156 was 15099, checked in by tbretz, 12 years ago
Output if new file format was set; do not update the Feedback data anymore
File size: 49.0 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 IncreaseRunNumber(uint32_t run)
1072 {
1073 if (!InitRunNumber())
1074 return false;
1075
1076 if (run<fRunNumber)
1077 {
1078 ostringstream msg;
1079 msg <<
1080 "Run number " << run << " smaller than next available "
1081 "run number " << fRunNumber << " in " << fPath << " [" << fNightAsInt << "]";
1082 fMsg.Error(msg);
1083 return false;
1084 }
1085
1086 fRunNumber = run;
1087
1088 return true;
1089 }
1090
1091 void gotNewRun(uint32_t runnr, PEVNT_HEADER */*headers*/)
1092 {
1093 // This function is called even when writing is switched off
1094 set<uint32_t>::iterator it = fIsRunStarted.begin();
1095 while (it!=fIsRunStarted.end())
1096 {
1097 if (*it<runnr)
1098 {
1099 ostringstream str;
1100 str << "gotNewRun - Missed run " << *it << ".";
1101 fMsg.Info(str);
1102
1103 fIsRunStarted.erase(it++);
1104 continue;
1105 }
1106 if (*it==runnr)
1107 break;
1108 it++;
1109 }
1110 if (it==fIsRunStarted.end())
1111 {
1112 ostringstream str;
1113 str << "gotNewRun - Not waiting for run " << runnr << ".";
1114 fMsg.Warn(str);
1115 return;
1116 }
1117
1118 map<uint32_t,FAD::RunDescription>::iterator i2 = fExpectedRuns.find(runnr);
1119 if (i2==fExpectedRuns.end())
1120 {
1121 ostringstream str;
1122 str << "gotNewRun - Run " << runnr << " wasn't expected.";
1123 fMsg.Warn(str);
1124 return;
1125 }
1126
1127 CloseRunFile(runnr, time(NULL)+i2->second.maxtime, i2->second.maxevt);
1128 // return: 0=close scheduled / >0 already closed / <0 does not exist
1129
1130 // FIXME: Move configuration from expected runs to runs which will soon
1131 // be opened/closed
1132
1133 fIsRunStarted.erase(it);
1134 }
1135
1136 map<boost::thread::id, string> fLastMessage;
1137
1138 void factOut(int severity, int err, const char *message)
1139 {
1140 if (!fDebugLog && severity==99)
1141 return;
1142
1143 ostringstream str;
1144 //str << boost::this_thread::get_id() << " ";
1145 str << "EventBuilder(";
1146 if (err<0)
1147 str << "---";
1148 else
1149 str << err;
1150 str << "): " << message;
1151
1152 string &old = fLastMessage[boost::this_thread::get_id()];
1153
1154 if (str.str()==old)
1155 return;
1156 old = str.str();
1157
1158 fMsg.Update(str, severity);
1159 }
1160
1161/*
1162 void factStat(int64_t *stat, int len)
1163 {
1164 if (len!=7)
1165 {
1166 fMsg.Warn("factStat received unknown number of values.");
1167 return;
1168 }
1169
1170 vector<int64_t> data(1, g_maxMem);
1171 data.insert(data.end(), stat, stat+len);
1172
1173 static vector<int64_t> last(8);
1174 if (data==last)
1175 return;
1176 last = data;
1177
1178 fDimStatistics.Update(data);
1179
1180 // len ist die Laenge des arrays.
1181 // array[4] enthaelt wieviele bytes im Buffer aktuell belegt sind; daran
1182 // kannst Du pruefen, ob die 100MB voll sind ....
1183
1184 ostringstream str;
1185 str
1186 << "Wait=" << stat[0] << " "
1187 << "Skip=" << stat[1] << " "
1188 << "Del=" << stat[2] << " "
1189 << "Tot=" << stat[3] << " "
1190 << "Mem=" << stat[4] << "/" << g_maxMem << " "
1191 << "Read=" << stat[5] << " "
1192 << "Conn=" << stat[6];
1193
1194 fMsg.Info(str);
1195 }
1196 */
1197
1198 void factStat(const EVT_STAT &stat)
1199 {
1200 fDimStatistics2.Update(stat);
1201 }
1202
1203 void factStat(const GUI_STAT &stat)
1204 {
1205 fDimStatistics1.Update(stat);
1206 }
1207
1208
1209 array<FAD::EventHeader, 40> fVecHeader;
1210
1211 template<typename T, class S>
1212 array<T, 42> Compare(const S *vec, const T *t)
1213 {
1214 const int offset = reinterpret_cast<const char *>(t) - reinterpret_cast<const char *>(vec);
1215
1216 const T *min = NULL;
1217 const T *val = NULL;
1218 const T *max = NULL;
1219
1220 array<T, 42> arr;
1221
1222 // bool rc = true;
1223 for (int i=0; i<40; i++)
1224 {
1225 const char *base = reinterpret_cast<const char*>(vec+i);
1226 const T *ref = reinterpret_cast<const T*>(base+offset);
1227
1228 arr[i] = *ref;
1229
1230 if (gi_NumConnect[i]!=7)
1231 {
1232 arr[i] = 0;
1233 continue;
1234 }
1235
1236 if (!val)
1237 {
1238 min = ref;
1239 val = ref;
1240 max = ref;
1241 }
1242
1243 if (*ref<*min)
1244 min = ref;
1245
1246 if (*ref>*max)
1247 max = ref;
1248
1249 // if (*val!=*ref)
1250 // rc = false;
1251 }
1252
1253 arr[40] = val ? *min : 1;
1254 arr[41] = val ? *max : 0;
1255
1256 return arr;
1257 }
1258
1259 template<typename T>
1260 array<T, 42> CompareBits(const FAD::EventHeader *h, const T *t)
1261 {
1262 const int offset = reinterpret_cast<const char *>(t) - reinterpret_cast<const char *>(h);
1263
1264 T val = 0;
1265 T rc = 0;
1266
1267 array<T, 42> vec;
1268
1269 bool first = true;
1270
1271 for (int i=0; i<40; i++)
1272 {
1273 const char *base = reinterpret_cast<const char*>(&fVecHeader[i]);
1274 const T *ref = reinterpret_cast<const T*>(base+offset);
1275
1276 vec[i+2] = *ref;
1277
1278 if (gi_NumConnect[i]!=7)
1279 {
1280 vec[i+2] = 0;
1281 continue;
1282 }
1283
1284 if (first)
1285 {
1286 first = false;
1287 val = *ref;
1288 rc = 0;
1289 }
1290
1291 rc |= val^*ref;
1292 }
1293
1294 vec[0] = rc;
1295 vec[1] = val;
1296
1297 return vec;
1298 }
1299
1300 template<typename T, size_t N>
1301 void Update(DimDescribedService &svc, const array<T, N> &data, int n=N)
1302 {
1303// svc.setQuality(vec[40]<=vec[41]);
1304 svc.setData(const_cast<T*>(data.data()), sizeof(T)*n);
1305 svc.Update();
1306 }
1307
1308 template<typename T>
1309 void Print(const char *name, const pair<bool,array<T, 43>> &data)
1310 {
1311 cout << name << "|" << data.first << "|" << data.second[1] << "|" << data.second[0] << "<x<" << data.second[1] << ":";
1312 for (int i=0; i<40;i++)
1313 cout << " " << data.second[i+3];
1314 cout << endl;
1315 }
1316
1317 vector<uint> fNumConnected;
1318
1319 void debugHead(int /*socket*/, const FAD::EventHeader &h)
1320 {
1321 const uint16_t id = h.Id();
1322 if (id>39)
1323 return;
1324
1325 if (fNumConnected.size()!=40)
1326 fNumConnected.resize(40);
1327
1328 const vector<uint> con(gi_NumConnect, gi_NumConnect+40);
1329
1330 const bool changed = con!=fNumConnected || !IsThreadRunning();
1331
1332 fNumConnected = con;
1333
1334 const FAD::EventHeader old = fVecHeader[id];
1335 fVecHeader[id] = h;
1336
1337 if (old.fVersion != h.fVersion || changed)
1338 {
1339 const array<uint16_t,42> ver = Compare(&fVecHeader[0], &fVecHeader[0].fVersion);
1340
1341 array<float,42> data;
1342 for (int i=0; i<42; i++)
1343 {
1344 ostringstream str;
1345 str << (ver[i]>>8) << '.' << (ver[i]&0xff);
1346 data[i] = stof(str.str());
1347 }
1348 Update(fDimFwVersion, data);
1349 }
1350
1351 if (old.fRunNumber != h.fRunNumber || changed)
1352 {
1353 const array<uint32_t,42> run = Compare(&fVecHeader[0], &fVecHeader[0].fRunNumber);
1354 fDimRunNumber.Update(run);
1355 }
1356
1357 if (old.fTriggerGeneratorPrescaler != h.fTriggerGeneratorPrescaler || changed)
1358 {
1359 const array<uint16_t,42> pre = Compare(&fVecHeader[0], &fVecHeader[0].fTriggerGeneratorPrescaler);
1360 fDimPrescaler.Update(pre);
1361 }
1362
1363 if (old.fDNA != h.fDNA || changed)
1364 {
1365 const array<uint64_t,42> dna = Compare(&fVecHeader[0], &fVecHeader[0].fDNA);
1366 Update(fDimDNA, dna, 40);
1367 }
1368
1369 if (old.fStatus != h.fStatus || changed)
1370 {
1371 const array<uint16_t,42> sts = CompareBits(&fVecHeader[0], &fVecHeader[0].fStatus);
1372 Update(fDimStatus, sts);
1373 }
1374
1375 if (memcmp(old.fDac, h.fDac, sizeof(h.fDac)) || changed)
1376 {
1377 array<uint16_t, FAD::kNumDac*42> dacs;
1378
1379 for (int i=0; i<FAD::kNumDac; i++)
1380 {
1381 const array<uint16_t, 42> dac = Compare(&fVecHeader[0], &fVecHeader[0].fDac[i]);
1382 memcpy(&dacs[i*42], &dac[0], sizeof(uint16_t)*42);
1383 }
1384
1385 Update(fDimDac, dacs);
1386 }
1387
1388 // -----------
1389
1390 static Time oldt(boost::date_time::neg_infin);
1391 Time newt;
1392
1393 if (newt>oldt+boost::posix_time::seconds(1))
1394 {
1395 oldt = newt;
1396
1397 // --- RefClock
1398
1399 const array<uint32_t,42> clk = Compare(&fVecHeader[0], &fVecHeader[0].fFreqRefClock);
1400 Update(fDimRefClock, clk);
1401
1402 // --- Temperatures
1403
1404 const array<int16_t,42> tmp[4] =
1405 {
1406 Compare(&fVecHeader[0], &fVecHeader[0].fTempDrs[0]), // 0-39:val, 40:min, 41:max
1407 Compare(&fVecHeader[0], &fVecHeader[0].fTempDrs[1]), // 0-39:val, 40:min, 41:max
1408 Compare(&fVecHeader[0], &fVecHeader[0].fTempDrs[2]), // 0-39:val, 40:min, 41:max
1409 Compare(&fVecHeader[0], &fVecHeader[0].fTempDrs[3]) // 0-39:val, 40:min, 41:max
1410 };
1411
1412 vector<int16_t> data;
1413 data.reserve(82);
1414 data.push_back(tmp[0][40]); // min: 0
1415 data.insert(data.end(), tmp[0].data(), tmp[0].data()+40); // val: 1-40
1416 data.push_back(tmp[0][41]); // max: 41
1417 data.insert(data.end(), tmp[0].data(), tmp[0].data()+40); // val: 42-81
1418
1419 for (int j=1; j<=3; j++)
1420 {
1421 const array<int16_t,42> &ref = tmp[j];
1422
1423 // Gloabl min
1424 if (ref[40]<data[0]) // 40=min
1425 data[0] = ref[40];
1426
1427 // Global max
1428 if (ref[41]>data[41]) // 41=max
1429 data[41] = ref[41];
1430
1431 for (int i=0; i<40; i++)
1432 {
1433 // min per board
1434 if (ref[i]<data[i+1]) // data: 1-40
1435 data[i+1] = ref[i]; // ref: 0-39
1436
1437 // max per board
1438 if (ref[i]>data[i+42]) // data: 42-81
1439 data[i+42] = ref[i]; // ref: 0-39
1440 }
1441
1442
1443 }
1444
1445 vector<float> deg(82); // 0: global min, 1-40: min
1446 for (int i=0; i<82; i++) // 41: global max, 42-81: max
1447 deg[i] = data[i]/16.;
1448 fDimTemperature.Update(deg);
1449 }
1450 }
1451};
1452
1453EventBuilderWrapper *EventBuilderWrapper::This = 0;
1454
1455// ----------- Event builder callbacks implementation ---------------
1456extern "C"
1457{
1458 FileHandle_t runOpen(uint32_t irun, RUN_HEAD *runhd, size_t len)
1459 {
1460 return EventBuilderWrapper::This->runOpen(irun, runhd, len);
1461 }
1462
1463 int runWrite(FileHandle_t fileId, EVENT *event, size_t len)
1464 {
1465 return EventBuilderWrapper::This->runWrite(fileId, event, len);
1466 }
1467
1468 int runClose(FileHandle_t fileId, RUN_TAIL *runth, size_t len)
1469 {
1470 return EventBuilderWrapper::This->runClose(fileId, runth, len);
1471 }
1472
1473 // -----
1474
1475 //void *runStart(uint32_t /*irun*/, RUN_HEAD */*runhd*/, size_t /*len*/)
1476 //{
1477 // return NULL;
1478 //}
1479
1480 int subProcEvt(int threadID, PEVNT_HEADER *fadhd, EVENT *event, int16_t mboard, void *runPtr)
1481 {
1482 return EventBuilderWrapper::This->subProcEvt(threadID, fadhd, event, mboard, runPtr);
1483 }
1484
1485 int runEnd(uint32_t, void */*runPtr*/)
1486 {
1487 return 0;
1488 }
1489
1490 // -----
1491
1492 int eventCheck(uint32_t runNr, PEVNT_HEADER *fadhd, EVENT *event, int mboard)
1493 {
1494 return EventBuilderWrapper::This->eventCheck(runNr, fadhd, event, mboard);
1495 }
1496
1497 void gotNewRun(uint32_t runnr, PEVNT_HEADER *headers)
1498 {
1499 return EventBuilderWrapper::This->gotNewRun(runnr, headers);
1500 }
1501
1502 // -----
1503
1504 void factOut(int severity, int err, const char *message)
1505 {
1506 EventBuilderWrapper::This->factOut(severity, err, message);
1507 }
1508
1509 void factStat(GUI_STAT stat)
1510 {
1511 EventBuilderWrapper::This->factStat(stat);
1512 }
1513
1514 void factStatNew(EVT_STAT stat)
1515 {
1516 EventBuilderWrapper::This->factStat(stat);
1517 }
1518
1519 // ------
1520
1521 void debugHead(int socket, int/*board*/, void *buf)
1522 {
1523 const FAD::EventHeader &h = *reinterpret_cast<FAD::EventHeader*>(buf);
1524 EventBuilderWrapper::This->debugHead(socket, h);
1525 }
1526
1527 void debugStream(int isock, void *buf, int len)
1528 {
1529 return EventBuilderWrapper::This->debugStream(isock, buf, len);
1530 }
1531
1532 void debugRead(int isock, int ibyte, int32_t event, int32_t ftmevt, int32_t runno, int state, uint32_t tsec, uint32_t tusec)
1533 {
1534 EventBuilderWrapper::This->debugRead(isock, ibyte, event, ftmevt, runno, state, tsec, tusec);
1535 }
1536}
1537
1538#endif
Note: See TracBrowser for help on using the repository browser.