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

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