Jpp 21.0.0-rc.1-88-g0130508c4
the software that should make you happy
Loading...
Searching...
No Matches
JDataFilter.cc
Go to the documentation of this file.
1#include <string>
2#include <iostream>
3#include <iomanip>
4#include <deque>
5#include <limits>
6#include <algorithm>
7#include <unistd.h>
8#include <random>
9
15
17#include "JLang/JLangToolkit.hh"
18#include "JLang/JException.hh"
19#include "JLang/JVectorize.hh"
20#include "JLang/JStatus.hh"
21#include "Jeep/JParser.hh"
22#include "Jeep/JProperties.hh"
23#include "Jeep/JTimer.hh"
24#include "Jeep/JTimekeeper.hh"
25#include "Jeep/JMessage.hh"
26#include "Jeep/JPrint.hh"
27#include "Jeep/JeepToolkit.hh"
29#include "JDAQ/JDAQTags.hh"
30#include "JDAQ/JDAQEventIO.hh"
34#include "JTrigger/JHit.hh"
39#include "JTrigger/JHitL0.hh"
40#include "JTrigger/JHitL1.hh"
41#include "JTrigger/JBuildL1.hh"
42#include "JTrigger/JBuildL2.hh"
54#include "JTrigger/JChecksum.hh"
57#include "JNet/JControlHost.hh"
59#include "JNet/JTCPSocket.hh"
61#include "JNet/JServerSocket.hh"
63#include "JTools/JStats.hh"
64#include "JSupport/JSupport.hh"
66#include "JSupport/JMeta.hh"
67#include "JSystem/JStat.hh"
68#include "JSystem/JTime.hh"
70#include "JSystem/JNetwork.hh"
72
73
74namespace JNET {
75
76 /**
77 * Get size of packeet.
78 *
79 * \param preamble DAQ data preamble
80 * \return size [B]
81 */
82 template<>
84 {
85 return preamble.getLength();
86 }
87}
88
89namespace KM3NETDAQ {
90
91 using namespace JPP;
92
93
94 /**
95 * Get expected number of frames according a given allowed fraction of active modules.
96 *
97 * \param number_of_frames number of frames
98 * \param factor factor
99 * \return number of frames
100 */
101 inline size_t getNumberOfFrames(const size_t number_of_frames, const double factor)
102 {
103 if (factor <= 0.0) {
104 return 1;
105 }
106
107 if (factor >= 1.0) {
108 return number_of_frames;
109 }
110
111 const size_t n = (size_t) (number_of_frames * factor);
112
113 return (n == 0 ? 1 : n);
114 }
115
116
117 /**
118 * Main class for real-time filtering of data.
119 *
120 * This class implements the action methods for each transition of the state machine.\n
121 * When the state machine is entered, data are continually collected using
122 * custom implementation of virtual methods
123 * JDataFilter::setSelect and
124 * JDataFilter::actionSelect.
125 *
126 * In state <tt>Running</tt>, all incoming data from the DataQueue.cc are buffered, referred to as "queue".\n
127 * These data are formatted as a JDAQSuperFrame and aggregated into a JDAQTimeslice.\n
128 * When a JDAQTimeslice is complete,
129 * it processed in the same way as applications JTriggerProcessor.cc and JTriggerEfficiency.cc.
130 *
131 * The completeness of a time slice is defined by two parameters, namely
132 * <tt>frames_per_slice</tt> and
133 * <tt>factor_per_slice</tt>.\n
134 * These are parsed in method actionConfigure as follows.
135 * <pre>
136 * numberOfFramesPerSlice = <frames per slice> = 1;
137 * factorOfFramesPerSlice = <factor per slice> = 1.0;
138 * </pre>
139 * The expected number of frames in a time slices is defined by their product.\n
140 * Note that the first parameter can change during operation (see below).
141 *
142 * A timeout may occur when the total amount of data or the number of incomplete time slices
143 * in the queue exceeds one of the limits <tt>queueSize</tt> or <tt>queueDepth</tt>.\n
144 * These are parsed in method actionConfigure as follows.
145 * <pre>
146 * queueSize = <maximal queue size [B]>;
147 * queueDepth = <maximal queue depth>;
148 * </pre>
149 * Note that these values apply per JDataFilter.\n
150 *
151 * The parameter <tt>frames_per_slice</tt> is subject to a servo mechanism.\n
152 * When a timeout occurs,
153 * it is set to the number of frames in the oldest time slice.\n
154 * When data are received with a frame index below the current frame index,
155 * it is incremented by one.
156 *
157 * In addition, a circular buffer based on a ROOT TTree for each JDAQTimeslice type can be maintained.\n
158 * The following parameters can be used to configure the circular buffer.\n
159 * <pre>
160 * path = <write directory for temporary circular buffer>;
161 * archive = <write directory for archival of circular buffer>;
162 * c_sizeL0 = <L0 buffer size>;
163 * c_sizeL1 = <L1 buffer size>;
164 * c_sizeL2 = <L2 buffer size>;
165 * c_sizeSN = <SN buffer size>;
166 * </pre>
167 *
168 * Note that when one (or more) of the buffer sizes is non-zero and the path corresponds to a valid directory:
169 * - There will always be a file created which is deleted when the state machine is exited;
170 * - The temporary file name is <tt><path>/KM3NeT_<tag>.root</tt>;
171 * - Following an alert, the temporary file is archived to a file with name <tt><path>/KM3NeT_YYYY-MM-DD_<tag>[_<index>].root</tt>;
172 * - After archival of the temporary file, a new temporary file will be opened;
173 * - L0, L1, L2 and SN buffer sizes are per JDataFilter;
174 * - The tag KM3NETDAQ::RC_ALERT defined in JDAQTags.hh has tentatively been reserved to trigger the archival of the temporary file following an external alert;
175 *
176 * In this, <tt>YYYY</tt>, <tt>MM</tt> and <tt>DD</tt> correspond to the year, month and day at the time of the alert, respectively.\n
177 * The <tt><tag></tt> corresponds to the unique JNET::JTag of the JDataFilter process.\n
178 * The <tt><index></tt> is optional and will only be used to prevent overwriting of an existing file
179 * (e.g. when there is more than one alert on a given day).
180 *
181 * Data can be discarded for various reasons.\n
182 * The list of criteria includes validity ranges of the PMT number and TDC values as well as the sorted times per PMT.\n
183 * The discarded data can be written to disk according to the parameters:
184 * <pre>
185 * dumpLimit = <maximum number of time slices to be dumped>
186 * dumpMask = <mask for data to be dumped>
187 * </pre>
188 * The first limits the number of time slices with discarded data that will be dumped and \n
189 * the latter corresponds to bits according to the enumeration JChecksum::error_types.\n
190 * The discarded data will be stored as JDAQTimeslice.
191 *
192 * Note that the application JConvert.cc can be used to readily convert multiple input files to a single output file.
193 *
194 * The script <tt>$JPP_DIR/tests/JDataFilter/JDataFilter.sh</tt> can be used to test this application.
195 */
197 public JDAQClient
198 {
199 public:
200
203
204 typedef double hit_type;
207 typedef JTimeslice <hit_type> JTimeslice_t;
208 typedef JBuildL1 <hit_type> JBuildL1_t;
209 typedef JBuildL2 <hit_type> JBuildL2_t;
210
211
212
213 /**
214 * Circular buffer.
215 */
217 public JTreeRecorder<JDAQTimesliceTypes_t>
218 {
221
222
223 static const int MAXIMUM_FILE_NUMBER = 100; //!< maximum file number for overwrite protection.
224
225
226 /**
227 * Constructor.
228 *
229 * \param path directory for temporary storage
230 * \param archive directory for permanent archival
231 * \param tag tag
232 */
233 JCircularBuffer_t(const std::string& path,
234 const std::string& archive,
235 const JTag& tag) :
236 path (path),
238 tag (tag)
239 {
240 disable();
241 }
242
243
244 /**
245 * Open file.
246 *
247 * If file with same name exists, remove it beforehand.
248 */
249 void open()
250 {
251 using namespace std;
252 using namespace JPP;
253
254 gErrorIgnoreLevel = kFatal;
255
256 std::ostringstream os;
257
258 os << getFullPath(path) << "KM3NeT" << "_" << tag << ".root";
259
260 if (getFileStatus(os.str().c_str())) {
261 std::remove(os.str().c_str());
262 }
263
264 this->open(os.str().c_str());
265 }
266
267
268 /**
269 * Close file.
270 *
271 * If option is true, archive file; else delete file.
272 *
273 * \param option option
274 */
275 void close(const bool option)
276 {
277 using namespace std;
278 using namespace JPP;
279
280 const JDateAndTime cal;
281
282 if (this->is_open()) {
283
284 const string file_name = this->getFile()->GetName();
285
286 this->close();
287
288 if (option) {
289
290 for (int i = 0; i != MAXIMUM_FILE_NUMBER; ++i) {
291
292 ostringstream os;
293
294 os << getFullPath(this->archive)
295 << "KM3NeT"
296 << "_" << cal.getYear() << '-' << FILL(2,'0') << cal.getMonth() << '-' << FILL(2,'0') << cal.getDay()
297 << "_" << this->tag;
298
299 if (i != 0) {
300 os << "_" << i;
301 }
302
303 os << ".root";
304
305 if (!getFileStatus(os.str().c_str())) {
306
307 if (JSYSTEM::rename(file_name, os.str()) == 0)
308 return;
309 else
310 THROW(JFileOpenException, "Failure in renaming file " << file_name << " to " << os.str());
311 }
312 }
313
314 } else {
315
316 std::remove(file_name.c_str());
317 }
318 }
319 }
320
321
322 /**
323 * Disable writing.
324 */
325 void disable()
326 {
327 sizeL0 = 0;
328 sizeL1 = 0;
329 sizeL2 = 0;
330 sizeSN = 0;
331 }
332
333
334 /**
335 * Check whether writing of data is enabled.
336 *
337 * \return true if writing enabled; else false
338 */
339 bool is_enabled() const
340 {
341 return (sizeL0 > 0 ||
342 sizeL1 > 0 ||
343 sizeL2 > 0 ||
344 sizeSN > 0);
345 }
346
347
348 /**
349 * Write circular buffer to output stream.
350 *
351 * \param out output stream
352 * \param object circular buffer
353 * \return output stream
354 */
355 friend inline std::ostream& operator<<(std::ostream& out, const JCircularBuffer_t& object)
356 {
357 if (object.is_open())
358 out << object.getFile()->GetName();
359 else
360 out << "void";
361
362 out << ' ';
363
364 out << object.sizeL0 << '/'
365 << object.sizeL1 << '/'
366 << object.sizeL2 << '/'
367 << object.sizeSN << '/';
368
369 return out;
370 }
371
372 Long64_t sizeL0; //!< Number of L0 time slices
373 Long64_t sizeL1; //!< Number of L1 time slices
374 Long64_t sizeL2; //!< Number of L2 time slices
375 Long64_t sizeSN; //!< Number of SN time slices
376
377 std::string path; //!< Directory for temporary storage
378 std::string archive; //!< Directory for permanent archival
379 JTag tag; //!< Unique tag of this process
380 };
381
382
383 /**
384 * Sort DAQ process by index.
385 *
386 * \param first first DAQ process
387 * \param second second DAQ process
388 * \return true if index of first DAQ process less than that of second; else false
389 */
390 static inline bool compare(const JDAQProcess& first, const JDAQProcess& second)
391 {
392 return first.index < second.index;
393 }
394
395
396 /**
397 * Constructor.
398 *
399 * \param name name of client
400 * \param server name of command message server
401 * \param hostname name of data server
402 * \param logger pointer to logger
403 * \param level debug level
404 * \param port server port
405 * \param backlog server backlog
406 * \param path directory for temporary storage
407 * \param archive directory for parmanent archival
408 */
409 JDataFilter(const std::string& name,
410 const std::string& server,
411 const std::string& hostname,
413 const int level,
414 const int port,
415 const int backlog,
416 const std::string& path,
417 const std::string& archive) :
420 port (port),
422 c_buffer (path, archive, getUniqueTag())
423 {
424 replaceEvent(RC_CMD, RC_DFILTER, ev_configure); /// replace tag to receive dfilter specific messages in configure
425
427
428 totalCPURAM = getRAM();
430 dataqueue_slice_index.clear();
431 reporting = false;
432
433 this->server->setReceiveBufferSize(DFILTER_RECEIVE_BUFFER_SIZE);
434 }
435
436
437 virtual void actionEnter() override
438 {}
439
440
441 virtual void actionExit() override
442 {
443 if (c_buffer.is_open()) {
444
445 JStatusStream(logger) << "Close and remove circular buffer " << c_buffer;
446
447 c_buffer.close(false);
448 }
449
450 datawriter.reset();
451 }
452
453
454 virtual void actionInit(int length, const char* buffer) override
455 {
456 JDebugStream(logger) << "actionInit() " << std::string(buffer,length);
457
458 try {
459
460 JDebugStream(logger) << "Start server.";
461
462 if (serversocket.is_valid()) {
463 serversocket->shutdown();
464 }
465
467 }
468 catch(const std::exception& error) {
469 JErrorStream(logger) << "Error \"" << error.what() << "\"; trigger ev_error.";
470 ev_error();
471 }
472 }
473
474
475 virtual void actionConfigure(int length, const char* buffer) override
476 {
477 using namespace std;
478
479 JDebugStream(logger) << "actionConfigure() " << endl << std::string(buffer,length);
480
481 string _hostname_ = "";
482
483 long long int update_s = 20;
484 long long int logger_s = 10;
485
486 parameters .reset();
487 dataFilters.clear();
488 dataQueues .clear();
489
490 reporting = false;
491 dumpCount = 0;
492 dumpLimit = numeric_limits<int>::max();
493 dumpMask = 0;
497 //dumpMask.set(JChecksum::EUDP_t);
499
500 detector.comment.clear();
501 detector.clear();
502
503 JProperties properties(JEquationParameters("=", ";", "", ""), 0);
504
505 properties["dataWriter"] = _hostname_;
506 properties["numberOfFramesPerSlice"] = frames_per_slice = 1;
507 properties["factorOfFramesPerSlice"] = factor_per_slice = 1.0;
508 properties["detector"] = detector;
509 properties["triggerParameters"] = parameters;
510 properties["queueSize"] = maxQueueSize = (totalCPURAM - GIGABYTE); // leave 1 GB left ...
511 properties["queueDepth"] = maxQueueDepth = 20; // to be optimized
512 properties["frameIndex"] = maximal_frame_index = 100000;
513 properties["logger_s"] = logger_s;
514 properties["update_s"] = update_s;
515 properties["JDataFilter"] = dataFilters;
516 properties["DataQueue"] = dataQueues;
517 properties["path"] = c_buffer.path;
518 properties["archive"] = c_buffer.archive;
519 properties["c_sizeL0"] = c_buffer.sizeL0;
520 properties["c_sizeL1"] = c_buffer.sizeL1;
521 properties["c_sizeL2"] = c_buffer.sizeL2;
522 properties["c_sizeSN"] = c_buffer.sizeSN;
523 properties["dumpLimit"] = dumpLimit;
524 properties["dumpMask"] = dumpMask;
525
526 try {
527 properties.read(string(buffer, length));
528 }
529 catch(const std::exception& error) {
530 JErrorStream(logger) << error.what();
531 }
532
533 if (update_s <= 0) { update_s = 20; }
534 if (logger_s <= 0) { logger_s = 10; }
535
536 setClockInterval(update_s * 1000000LL);
537
538 _hostname_ = trim(_hostname_);
539
540 if (_hostname_ != "" && _hostname_ != hostname) {
541
542 datawriter.reset();
543
544 hostname = _hostname_;
545 }
546
547 bool status = datawriter.is_valid();
548
549 if (status) {
550
551 try {
552 status = datawriter->Connected() == 0;
553 }
554 catch (const exception&) {
555 status = false;
556 }
557 }
558
559 if (!status) {
560
562
563 datawriter->MyId(getFullName());
564 }
565
566 datawriter->setSendBufferSize(DFILTER_SEND_BUFFER_SIZE);
567
568 // process processlist
569
570 if (dataFilters.empty()) {
571 JNoticeStream(logger) << "No DataFilters in process list, or no process list. "
572 << "Assuming that this process is the only process on this CPU and setting parameters accordingly.";
573 }
574
575 sort(dataFilters.begin(), dataFilters.end(), compare);
576
577 unsigned int numberOfDataFiltersOnThisMachine = 0;
578 vector<JDAQProcess>::iterator thisProcess = dataFilters.end();
579
581
582 for (vector<JDAQProcess>::iterator i = dataFilters.begin(); i != dataFilters.end(); ++i) {
583
584 if (find(IP.begin(), IP.end(), i->hostname) != IP.end()) {
585
586 numberOfDataFiltersOnThisMachine++;
587
588 if (i->port == this->port) {
589 thisProcess = i;
590 }
591 }
592 }
593
594 if (numberOfDataFiltersOnThisMachine == 0) {
595 JNoticeStream(logger) << "Zero data filters on this machine according to process list (if it exists). "
596 << "Assuming one datafilter on this machine.";
597 numberOfDataFiltersOnThisMachine = 1;
598 }
599
600 if (thisProcess == dataFilters.end()) {
601
602 JErrorStream error(logger);
603
604 error << "This process cannot be found in the process list. Why do I exist?";
605 error << " my IP addresses:";
606
607 for (vector<string>::const_iterator i = IP.begin(); i != IP.end(); ++i) {
608 error << ' ' << *i;
609 }
610
611 error << " my port: " << this->port;
612 error << " process list";
613
614 for (vector<JDAQProcess>::iterator i = dataFilters.begin(); i != dataFilters.end(); ++i) {
615 error << ' ' << i->hostname << ':' << i->port;
616 }
617 }
618
619 if (thisProcess != dataFilters.end() && thisProcess->index != getName()) {
620 JErrorStream(logger) << "Mismatch between given process names: "
621 << "I am called " << getName()
622 << ", but in the process list I am referred to as " << thisProcess->index;
623 }
624
625 if (dataFilters.begin() == thisProcess || dataFilters.empty()) { // set reporting
626 reporting = true;
627 }
628
629 if (maxQueueSize > (totalCPURAM-GIGABYTE)/(numberOfDataFiltersOnThisMachine)) { // check maximum size of queue
630
631 maxQueueSize = (totalCPURAM-GIGABYTE)/(numberOfDataFiltersOnThisMachine);
632
633 JNoticeStream(logger) << "Maximum queue size is too large given the number of processes on this machine. "
634 << "Queue size reduced to "
635 << maxQueueSize << " bytes." ;
636 }
637
638 // detector
639
640 if (parameters.disableHighRateVeto) {
641
642 JNoticeStream(logger) << "Disabling high-rate veto of all PMTs.";
643
644 detector.setPMTStatus(HIGH_RATE_VETO_DISABLE);
645 }
646
647 // trigger parameters
648
650
651 triggerNB .reset(new JTriggerNB (parameters));
655
657
658 if (reporting) {
659 JNoticeStream(logger) << "This data filter process will report.";
660 JNoticeStream(logger) << "Detector version/size " << detector.getVersion() << '/' << detector.size();
661 JDebugStream (logger) << "Trigger parameters: " << parameters;
662 JDebugStream (logger) << "Detector description: " << endl << detector;
663 JNoticeStream(logger) << "Update period [s]: " << getClockInterval();
664 }
665
666 timesliceRouter.reset(new JTimesliceRouter(parameters.numberOfBins));
667
668 // set L1, L2 and SN builders
669
670 buildL1.reset(new JBuildL1_t(parameters));
671 buildL2.reset(new JBuildL2_t(parameters.L2));
672 buildSN.reset(new JBuildL2_t(parameters.SN));
673 buildNB.reset(new JBuildL2_t(parameters.NB));
674
675 if (buildL1.get() == NULL) { JErrorStream(logger) << "Failed to allocate buildL1."; }
676 if (buildL2.get() == NULL) { JErrorStream(logger) << "Failed to allocate buildL2."; }
677 if (buildSN.get() == NULL) { JErrorStream(logger) << "Failed to allocate buildSN."; }
678 if (buildNB.get() == NULL) { JErrorStream(logger) << "Failed to allocate buildSN."; }
679
680 logErrorRun = JMessageScheduler(logger, JTimekeeper(logger_s * 1000000LL));
681 logErrorDetector = JMessageScheduler(logger, JTimekeeper(logger_s * 1000000LL));
682 logErrorIndex = JMessageScheduler(logger, JTimekeeper(logger_s * 1000000LL));
683 logErrorIncomplete = JMessageScheduler(logger, JTimekeeper(logger_s * 1000000LL));
685
686 if (c_buffer.is_enabled()) {
687
688 if (!c_buffer.is_open()) {
689
690 c_buffer.open();
691
692 if (c_buffer.is_open()) {
693
695
696 JStatusStream(logger) << "Created circular buffer " << c_buffer;
697
698 } else {
699
700 JErrorStream (logger) << "Failed to create circular buffer in directory <" << c_buffer.path << ">; disable functionality.";
701 }
702
703 } else {
704
705 JNoticeStream(logger) << "Continue using circular buffer " << c_buffer;
706 }
707 }
708
709 if (c_buffer.is_open()) {
710 if (c_buffer.sizeL0 > 0) { static_cast<JTreeWriterObjectOutput<JDAQTimesliceL0>&>(c_buffer).SetCircular(c_buffer.sizeL0); }
711 if (c_buffer.sizeL1 > 0) { static_cast<JTreeWriterObjectOutput<JDAQTimesliceL1>&>(c_buffer).SetCircular(c_buffer.sizeL1); }
712 if (c_buffer.sizeL2 > 0) { static_cast<JTreeWriterObjectOutput<JDAQTimesliceL2>&>(c_buffer).SetCircular(c_buffer.sizeL2); }
713 if (c_buffer.sizeSN > 0) { static_cast<JTreeWriterObjectOutput<JDAQTimesliceSN>&>(c_buffer).SetCircular(c_buffer.sizeSN); }
714 } else {
716 }
717 }
718
719
720 virtual void actionStart(int length, const char* buffer) override
721 {
722 using namespace std;
723
724 if (reporting) {
725 JNoticeStream(logger) << "Start run " << getRunNumber();
726 }
727
728 timeslices.clear();
729
731 dataqueue_slice_index.clear();
732 queueSize = 0;
733
734 numberOfEvents = 0;
735 numberOfBytes = 0;
738
742 number_of_reads = 0;
743
744 minFrameNumber = numeric_limits<int>::max();
745 maxFrameNumber = numeric_limits<int>::min();
746
747 // Reset global trigger counter.
748
750
756
757 timer.reset();
758 timer.start();
759
760 Qt.reset();
761 Qx.reset();
762
763 // send trigger parameters to the datawriter
764
765 ostringstream os;
766
767 os << getRunNumber() << ' ' << parameters;
768
769 datawriter->PutFullString(IO_TRIGGER_PARAMETERS, os.str());
770 }
771
772
773 virtual void actionPause(int length, const char* buffer) override
774 {
775 using namespace std;
776
777 if (!timeslices.empty()) {
778
779 JNoticeStream(logger) << "Flushing " << timeslices.size() << " slices.";
780
781 for (deque<JDAQTimesliceL0>::const_iterator i = timeslices.begin(); i != timeslices.end(); ++i) {
782 queueSize -= getSizeof(*i);
783 }
784
785 timeslices.clear();
786 }
787
788 { // force clearance of memory
789
790 deque<JDAQTimesliceL0> buffer;
791
792 timeslices.swap(buffer);
793 }
794
795 if (queueSize != 0) {
796 JWarningStream(logger) << "Pending data in queue " << queueSize << " [B]";
797 }
798
800 dataqueue_slice_index.clear();
801 queueSize = 0;
802
803 timer.stop();
804 }
805
806
807 virtual void actionContinue(int length, const char* buffer) override
808 {
809 timer.start();
810 }
811
812
813 virtual void actionStop(int length, const char* buffer) override
814 {
815 typeout();
816 }
817
818
819 virtual void actionReset(int length, const char* buffer) override
820 {
821 if (serversocket.is_valid()) {
822 serversocket->shutdown();
823 }
824
825 serversocket.reset();
826 }
827
828
829 virtual void actionQuit(int length, const char* buffer) override
830 {
831 datawriter.reset();
832 }
833
834
835 virtual void setSelect(JFileDescriptorMask& mask) const override
836 {
837 if (serversocket.is_valid()) {
838 mask.set(*serversocket);
839 }
840
841 for (JChannelList_t::const_iterator channel = channelList.begin(); channel != channelList.end(); ++channel) {
842 if (!channel->isReady()) {
843 mask.set(channel->getFileDescriptor());
844 }
845 }
846 }
847
848
849 virtual void actionSelect(const JFileDescriptorMask& mask) override
850 {
851 using namespace std;
852
853 for (JChannelList_t::iterator channel = channelList.begin(); channel != channelList.end(); ) {
854
855 try {
856
857 if (mask.has(channel->getFileDescriptor())) {
858 channel->read();
859 }
860
861 if (channel->isReady()) {
862
864 number_of_reads += channel->getCounter();
865 number_of_bytes_received += channel->size();
866
867 if (isRunning()) {
868
869 try {
870 updateFrameQueue(*channel);
871 }
872 catch(const std::exception& error) {
873
874 JErrorStream(logErrorRun) << "Update frame queue " << channel->getFileDescriptor() << ' ' << channel->size() << ' ' << error.what();
875
877 }
878
879 } else {
880
881 JErrorStream(logErrorRun) << "Receiving data while not running.";
882
884 }
885
886 channel->reset();
887 }
888
889 ++channel;
890 }
891 catch(const std::exception& error) {
892
893 if (isRunning()) {
894 JErrorStream(logger) << "Disconnect channel " << channel->getFileDescriptor() << ' ' << error.what();
895 }
896
897 channel->shutdown();
898
899 channel = channelList.erase(channel);
900 }
901 }
902
903
904 if (serversocket.is_valid()) {
905
906 if (mask.has(*serversocket)) {
907
908 JTCPSocket socket(serversocket->getFileDescriptor());
909
911
912 socket.setKeepAlive (true);
913 socket.setNonBlocking(false);
914
915 JStatusStream(logger) << "New channel" << '[' << socket.getFileDescriptor() << ']' << ' ' << socket.getReceiveBufferSize();
916
917 channelList.push_back(JSocketInputChannel_t(socket));
918 }
919 }
920
921
922 if (!timeslices.empty()) {
923
924 const size_t number_of_frames = getNumberOfFrames(frames_per_slice, factor_per_slice);
925 const size_t maximum_in_queue = getMaximum(make_array(next(timeslices.begin()), timeslices.end(), &JDAQTimesliceL0::size), (size_t) 0);
926
927 if (((timeslices[0].size() >= number_of_frames && // normal
928 timeslices[0].getFrameIndex() < dataqueue_slice_index.min()) ||
929
930 (maximum_in_queue >= number_of_frames && // intermittent problem
931 timeslices[0].getFrameIndex() < dataqueue_slice_index.min()) ||
932
933 (timeslices.size() >= maxQueueDepth) || // timeout
934 (queueSize >= maxQueueSize))) {
935
936
937 const JDAQTimesliceL0& pending_slice = timeslices.front();
938 queueSize -= getSizeof(pending_slice);
939
940 current_slice_index = pending_slice.getFrameIndex();
941 minFrameNumber = min(minFrameNumber, pending_slice.getFrameIndex());
942 maxFrameNumber = max(maxFrameNumber, pending_slice.getFrameIndex());
943
944 for (JDAQTimesliceL0::const_iterator i = pending_slice.begin(); i != pending_slice.end(); ++i) {
945 modules.insert(i->getModuleID());
946 }
947
948
949 if (isRunning()) {
950
951 const localtime_t t0 = getLocalTime();
952
953 if (!pending_slice.empty()) {
954 processTimeSlice(pending_slice);
955 }
956
957 const localtime_t t1 = getLocalTime();
958
960
961 Qt.put(t1 - t0);
962
963 } else {
964
965 JErrorStream(logErrorRun) << "Skip processing of data while not running.";
966 }
967
968
969 if (modules.size() > frames_per_slice) {
970
971 JErrorStream(logErrorOvercomplete) << "More active modules than expected "
972 << modules.size() << " > " << frames_per_slice
973 << " adjusting frames per slice to " << modules.size();
974
975 frames_per_slice = modules.size();
976 }
977
978
979 if (pending_slice.size() < number_of_frames) {
980
982
983 ostringstream error;
984
985 error << "Timeout -> processed incomplete timeslice: "
986 << "Frame index = " << pending_slice.getFrameIndex() << ';'
987 << "Size of timeslice = " << pending_slice.size() << ';'
988 << "Queue depth = " << timeslices.size() << ';'
989 << "Queue size = " << queueSize << ';'
990 << "DataQueue min = " << dataqueue_slice_index.min() << ';'
991 << "DataQueue max = " << dataqueue_slice_index.max() << ';';
992
993 if (maximum_in_queue >= number_of_frames) {
994
995 error << " intermittent problem -> continues as-is";
996
997 } else {
998
999 modules.clear(); // remove history
1000
1001 for (JDAQTimesliceL0::const_iterator i = pending_slice.begin(); i != pending_slice.end(); ++i) {
1002 modules.insert(i->getModuleID());
1003 }
1004
1005 error << " adjusting frames per timeslice from " << frames_per_slice << " to " << modules.size();
1006
1007 frames_per_slice = modules.size();
1008 }
1009
1010 JErrorStream(logErrorIncomplete) << error.str();
1011 }
1012
1013
1014 timeslices.pop_front();
1015 }
1016 }
1017 }
1018
1019
1020 virtual void actionRunning() override
1021 {
1022 if (reporting) {
1023 typeout();
1024 }
1025 }
1026
1027
1028 /**
1029 * Update queue with data frames.
1030 *
1031 * Note that any discarded data will be reported.
1032 *
1033 * \param channel incoming data channel
1034 */
1036 {
1037 using namespace std;
1038
1039 JByteArrayReader in(channel.data(), channel.size());
1040
1041 JDAQPreamble preamble;
1042 JDAQSuperFrameHeader header;
1043
1044 in >> preamble;
1045 in >> header;
1046
1047 if (preamble.getLength() != channel.size()) {
1048
1049 JErrorStream(logErrorRun) << "Size of received data does not match size reported by preamble: "
1050 << "preamble.getLength() = " << preamble.getLength() << ';'
1051 << "channel.size(): " << channel.size() << ';';
1052
1054
1055 return;
1056 }
1057
1058 if (header.getRunNumber() != getRunNumber()) {
1059
1060 JErrorStream(logErrorRun) << "Run number " << header.getRunNumber()
1061 << " != " << getRunNumber()
1062 << " -> Dropping frame.";
1063
1065
1066 return;
1067 }
1068
1069 if (header.getFrameIndex() <= current_slice_index) {
1070
1072
1073 if (modules.insert(header.getModuleID()).second) {
1074
1075 frames_per_slice = modules.size();
1076
1077 JErrorStream(logErrorIndex) << "Frame index " << header.getFrameIndex() << " <= " << current_slice_index
1078 << " module " << header.getModuleID()
1079 << " -> dropping frame;"
1080 << " increase number of frames expected to: " << frames_per_slice;
1081 }
1082
1083 return;
1084 }
1085
1087
1089
1090 JErrorStream(logErrorIndex) << "Frame index " << header.getFrameIndex() << " > " << current_slice_index + maximal_frame_index
1091 << " module " << header.getModuleID()
1092 << " -> Dropping frame.";
1093
1094 return;
1095 }
1096
1097 deque<JDAQTimesliceL0>::iterator timesliceIterator = timeslices.begin();
1098
1099 while (timesliceIterator != timeslices.end() && timesliceIterator->getFrameIndex() < header.getFrameIndex()) {
1100 ++timesliceIterator;
1101 }
1102
1103 if (timesliceIterator != timeslices.end() && timesliceIterator->getFrameIndex() == header.getFrameIndex()) {
1104
1105 // The corresponding time slice already exists
1106
1107 } else {
1108
1109 // This is the first frame of this time slice; insert a new time slice in the buffer at the right position in the list
1110
1111 timesliceIterator = timeslices.insert(timesliceIterator, JDAQTimesliceL0());
1112
1113 timesliceIterator->setDAQChronometer(header.getDAQChronometer());
1114
1115 queueSize += getSizeof(*timesliceIterator);
1116 }
1117
1118 timesliceIterator->push_back(JDAQSuperFrame(header));
1119
1120 in >> static_cast<JDAQFrame&>(*(timesliceIterator->rbegin()));
1121
1122 queueSize += getSizeof(*timesliceIterator->rbegin());
1123
1125 }
1126
1127
1128 /**
1129 * Process time slice.
1130 *
1131 * \param timeslice time slice
1132 */
1133 void processTimeSlice(const JDAQTimesliceL0& timeslice)
1134 {
1135 using namespace std;
1136
1137 try {
1138
1139 timesliceRouter->configure(timeslice);
1140
1141 if (parameters.writeSummary()) {
1142 this->put(JDAQSummaryslice(timeslice));
1143 }
1144
1145 if (parameters.trigger3DMuon.enabled ||
1146 parameters.trigger3DShower.enabled ||
1147 parameters.triggerMXShower.enabled ||
1148 parameters.triggerNB.enabled ||
1149 parameters.triggerRandom.enabled ||
1150 parameters.writeL0.prescale ||
1151 parameters.writeL1.prescale ||
1152 parameters.writeL2.prescale ||
1153 parameters.writeSN.prescale ||
1154 c_buffer.is_enabled()) {
1155
1156 JTimeslice_t timesliceL0(timeslice.getDAQChronometer());
1157 JTimeslice_t timesliceL1(timeslice.getDAQChronometer());
1158 JTimeslice_t timesliceL2(timeslice.getDAQChronometer());
1159 JTimeslice_t timesliceSN(timeslice.getDAQChronometer());
1160 JTimeslice_t timesliceNB(timeslice.getDAQChronometer());
1161 JDAQTimeslice timesliceTX(timeslice.getDAQChronometer());
1162
1163 for (JDAQTimesliceL0::const_iterator frame = timeslice.begin(); frame != timeslice.end(); ++frame) {
1164
1165 if (moduleRouter->hasModule(frame->getModuleID())) {
1166
1167 const JChecksum::result_type& result = checksum(*frame);
1168
1169 if (!result) {
1170
1171 JWarningStream(logger) << "Invalid data at "
1172 << "run = " << timeslice.getRunNumber() << ";"
1173 << "frame index = " << timeslice.getFrameIndex() << ";"
1174 << "module = " << frame->getModuleID() << ";"
1175 << "discard" << (dumpCount < dumpLimit ? " and dump" : "");
1176
1177 if (dumpCount < dumpLimit && result.has(dumpMask)) {
1178 timesliceTX.push_back(*frame);
1179 }
1180
1181 continue;
1182 }
1183
1184 const JModule& module = moduleRouter->getModule(frame->getModuleID());
1185 JSuperFrame2D_t& buffer = JSuperFrame2D_t::demultiplex(*frame, module);
1186
1187 // Apply high-rate veto
1188
1189 buffer.applyHighRateVeto(parameters.highRateVeto_Hz);
1190
1191 // L0
1192
1193 timesliceL0.push_back(JSuperFrame1D_t(buffer));
1194
1195 // Nano-beacon trigger
1196
1197 if (parameters.triggerNB.enabled) {
1198
1199 JSuperFrame2D_t::iterator __end = partition(buffer.begin(), buffer.end(), parameters.triggerNB.pmts);
1200
1201 if (buffer.begin() != __end) {
1202
1203 timesliceNB.push_back(JSuperFrame1D_t(frame->getDAQChronometer(),
1204 frame->getModuleIdentifier(),
1205 module.getPosition()));
1206
1207 JSuperFrame1D_t zbuf;
1208
1209 (*buildL1)(buffer.begin(), __end, back_inserter(zbuf));
1210
1211 (*buildNB)(buffer.begin(), __end, zbuf, back_inserter(*timesliceNB.rbegin()));
1212 }
1213 }
1214
1215 // L1
1216
1217 timesliceL1.push_back(JSuperFrame1D_t(frame->getDAQChronometer(),
1218 frame->getModuleIdentifier(),
1219 module.getPosition()));
1220
1221 (*buildL1)(*timesliceL0.rbegin(), back_inserter(*timesliceL1.rbegin()));
1222
1223 // L2
1224
1225 timesliceL2.push_back(JSuperFrame1D_t(frame->getDAQChronometer(),
1226 frame->getModuleIdentifier(),
1227 module.getPosition()));
1228
1229 (*buildL2)(buffer, *timesliceL1.rbegin(), back_inserter(*timesliceL2.rbegin()));
1230
1231 // SN
1232 {
1233 JTimeslice_t::value_type tv(frame->getDAQChronometer(),
1234 frame->getModuleIdentifier(),
1235 module.getPosition());
1236
1237 (*buildSN)(buffer, *timesliceL1.rbegin(), back_inserter(tv));
1238
1239 if (!tv.empty()) {
1240 timesliceSN.push_back(tv);
1241 }
1242 }
1243
1244 } else {
1245
1246 JErrorStream(logErrorDetector) << "No detector information for module " << frame->getModuleID();
1247 }
1248 }
1249
1250 if (!timesliceTX.empty()) {
1251
1252 if (dumpCount < dumpLimit) {
1253
1254 this->put(timesliceTX);
1255
1256 dumpCount += 1;
1257 }
1258 }
1259
1260 // Triggers
1261
1262 if (parameters.triggerNB.enabled) {
1263
1264 const JTriggerInput trigger_input(timesliceNB);
1265
1266 for (JTriggerInput::const_iterator hit = trigger_input.begin(); hit != trigger_input.end(); ++hit) {
1267
1268 if (parameters.triggerNB.write()) {
1269
1270 JTriggeredEvent tev(timesliceNB.getDAQChronometer(),
1271 getTriggerMask(triggerNB->getTriggerBit()),
1272 *hit,
1274 *moduleRouter,
1275 parameters.TMaxLocal_ns,
1276 parameters.triggerNB.DMax_m,
1277 getTimeRange(parameters.triggerNB));
1278
1279 this->put(tev);
1280 }
1281 }
1282 }
1283
1284 if (parameters.triggerRandom.enabled) {
1285
1286 if (parameters.triggerRandom.rate_Hz > 0.0) {
1287
1288 exponential_distribution<double> f1(parameters.triggerRandom.rate_Hz * 1.0e-9);
1289
1290 while (rabbit.t1_ns < getTimeOfFrame(timeslice.getFrameIndex())) {
1291 rabbit.t1_ns += f1(rabbit.gr);
1292 }
1293
1294 for (double t1_ns; (t1_ns = rabbit.t1_ns - getTimeOfFrame(timeslice.getFrameIndex())) <= getFrameTime(); ) {
1295
1296 JTriggeredEvent tev(t1_ns,
1297 parameters.triggerRandom.TMax_ns,
1300 *moduleRouter);
1301
1302 this->put(tev);
1303
1304 rabbit.t1_ns += f1(rabbit.gr);
1305 }
1306 }
1307 }
1308
1309 JTriggerInput trigger_input(timesliceL2);
1310 JTriggerOutput trigger_output;
1311
1312 (*trigger3DMuon) (trigger_input, back_inserter(trigger_output));
1313 (*trigger3DShower)(trigger_input, back_inserter(trigger_output));
1314 (*triggerMXShower)(trigger_input, timesliceL0, back_inserter(trigger_output));
1315
1316 trigger_output.merge(JEventOverlap(parameters.TMaxEvent_ns));
1317
1318 for (JTriggerOutput::const_iterator event = trigger_output.begin(); event != trigger_output.end(); ++event) {
1319
1320 const JTriggeredEvent object(*event, *timesliceRouter, *moduleRouter, parameters.TMaxLocal_ns, getTimeRange(parameters));
1321
1322 this->put(object);
1323
1324 numberOfEvents += 1;
1325 }
1326
1327 if (parameters.writeL1() || c_buffer.sizeL1 > 0) {
1328
1329 const JTimesliceL1<JDAQTimesliceL1> object(timesliceL1, *timesliceRouter, *moduleRouter, parameters.TMaxLocal_ns);
1330
1331 if (parameters.writeL1) { this->put(object); }
1332 if (c_buffer.sizeL1 > 0) { c_buffer.put(object); }
1333 }
1334
1335 if (parameters.writeL2() || c_buffer.sizeL2 > 0) {
1336
1337 const JTimesliceL1<JDAQTimesliceL2> object(timesliceL2, *timesliceRouter, *moduleRouter, parameters.L2.TMaxLocal_ns);
1338
1339 if (parameters.writeL2) { this->put(object); }
1340 if (c_buffer.sizeL2 > 0) { c_buffer.put(object); }
1341 }
1342
1343 if (parameters.writeSN() || c_buffer.sizeSN > 0) {
1344
1345 const JTimesliceL1<JDAQTimesliceSN> object(timesliceSN, *timesliceRouter, *moduleRouter, parameters.SN.TMaxLocal_ns);
1346
1347 if (parameters.writeSN) { this->put(object); }
1348 if (c_buffer.sizeSN > 0) { c_buffer.put(object); }
1349 }
1350
1351 if (parameters.writeL0() || c_buffer.sizeL0 > 0) {
1352
1353 if (parameters.writeL0) { this->put(timeslice); }
1354 if (c_buffer.sizeL0 > 0) { c_buffer.put(timeslice); }
1355 }
1356 }
1357
1358 } catch(const std::exception& error) {
1359
1360 JErrorStream(logger) << "Error = " << error.what() << ";"
1361 << "run = " << timeslice.getRunNumber() << ";"
1362 << "frame index = " << timeslice.getFrameIndex() << ";"
1363 << "time slice not correctly processed;"
1364 << "discard" << (dumpCount < dumpLimit ? " and dump" : "");
1365
1366 if (dumpCount < dumpLimit) {
1367
1368 this->put(static_cast<const JDAQTimeslice&>(timeslice));
1369
1370 dumpCount += 1;
1371 }
1372 }
1373
1374 timesliceRouter->reset();
1375 }
1376
1377
1378 /**
1379 * Report status to message logger.
1380 */
1381 void typeout()
1382 {
1383 timer.stop();
1384
1385 const double T_us = (double) timer.usec_wall;
1386
1387 JStatusStream(logger) << "Elapsed real (wall) time [s] " << T_us / 1e6;
1388 JStatusStream(logger) << "Elapsed user CPU time [s] " << (double) timer.usec_ucpu/ 1e6;
1389 JStatusStream(logger) << "Elapsed system CPU time [s] " << (double) timer.usec_scpu/ 1e6;
1390 JStatusStream(logger) << "Elapsed real time per time slice [ms] " << Qt.getMean(0.0) * 1.0e-3 << " <= " << Qt.getXmax() * 1.0e-3;
1391 JStatusStream(logger) << "Number of packets received/discarded " << number_of_packets_received << "/" << number_of_packets_discarded;
1392 JStatusStream(logger) << "Number of events/MB/us " << numberOfEvents << "/" << numberOfBytes/1e6 << "/" << Qx.getMean(0.0);
1393
1395 JStatusStream(logger) << "Number of reads/packet " << (double) number_of_reads / (double) number_of_packets_received;
1396 }
1397
1398 JStatusStream(logger) << "Current queue depth/size " << timeslices.size() << "/" << queueSize;
1399 JStatusStream(logger) << "Current number of frames per slice expected: " << frames_per_slice << ' ' << FIXED(5,3) << factor_per_slice;
1400
1401 JStatusStream(logger) << "Number of timeslices processed total/incomplete " << numberOfTimeslicesProcessed << "/" << numberOfIncompleteTimeslicesProcessed;
1402
1403 const double processedSlicesTime_us = numberOfTimeslicesProcessed * getFrameTime() / 1000;
1404 const double processedDetectorTime_us = (maxFrameNumber - minFrameNumber) * getFrameTime() / 1000;
1405
1406 if (processedSlicesTime_us > 0) {
1407 JStatusStream(logger) << "Performance factor (inaccurate estimate): " << T_us / processedSlicesTime_us;
1408 }
1409 if (processedDetectorTime_us > 0) {
1410 JStatusStream(logger) << "Performance factor whole detector (inaccurate estimate): " << T_us / processedDetectorTime_us;
1411 }
1412
1413 timer.start();
1414 }
1415
1416
1417 /**
1418 * Tagged action to handle alerts.
1419 *
1420 * \param tag tag
1421 * \param length number of characters
1422 * \param buffer message
1423 */
1424 virtual void actionTagged(const JTag& tag, int length, const char* buffer) override
1425 {
1426 using namespace std;
1427
1428 JDebugStream(logger) << "Received message <" << tag.toString() << "> \"" << string(buffer, length) << "\"";
1429
1430 if (tag == RC_ALERT) {
1431
1432 if (c_buffer.is_open()) {
1433
1434 JStatusStream(logger) << "Archive circular buffer in <" << c_buffer.archive << ">";
1435
1436 c_buffer.close(true);
1437 }
1438
1439 if (c_buffer.is_enabled()) {
1440
1441 c_buffer.open();
1442
1443 if (c_buffer.is_open()) {
1444
1445 JStatusStream(logger) << "Created circular buffer " << c_buffer;
1446
1448
1449 } else {
1450
1451 JErrorStream (logger) << "Failed to create circular buffer in directory <" << c_buffer.path << ">; disable functionality.";
1452
1453 c_buffer.disable();
1454 }
1455 }
1456
1457 } else {
1458
1459 JWarningStream(logger) << "Tag <" << tag.toString() << "> not implemented";
1460 }
1461 }
1462
1463 JMeta meta; //!< meta data
1464
1465 private:
1466
1468 JSinglePointer<JControlHost_t> datawriter; //!< controlhost of data server (to which data writer should be connected)
1469 std::string hostname; //!< host name of data server
1470
1471 /**
1472 * Auxiliary method to send object to data server.
1473 *
1474 * \param object object to be sent
1475 */
1476 template<class T>
1477 void put(const T& object)
1478 {
1479 try {
1480
1481 const localtime_t t0 = getLocalTime();
1482
1483 datawriter->put(object);
1484
1485 const localtime_t t1 = getLocalTime();
1486
1487 numberOfBytes += getSizeof(object);
1488
1489 Qx.put(t1 - t0);
1490 }
1491 catch(const std::exception& error) {
1492 JErrorStream(logger) << "Error \"" << error.what() << "\"; trigger ev_error.";
1493 ev_error();
1494 }
1495 }
1496
1497
1498 int port; //!< server socket port
1500
1501 JSinglePointer<JServerSocket> serversocket; //!< server for data queue connections
1502 JChannelList_t channelList; //!< connections to data queue
1503
1506
1507 std::deque<JDAQTimesliceL0> timeslices; //!< buffer with pending time slice data
1513
1514 struct :
1515 public std::map<int, int>
1516 {
1517 /**
1518 * Get minimal frame index.
1519 *
1520 * \return frame index
1521 */
1522 int min() const
1523 {
1524 if (this->empty()) {
1525
1526 return -1;
1527
1528 } else {
1529
1530 int min = std::numeric_limits<int>::max();
1531
1532 for (const_iterator i = this->begin(); i != this->end(); ++i) {
1533 if (i->second < min) {
1534 min = i->second;
1535 }
1536 }
1537
1538 return min;
1539 }
1540 }
1541
1542 /**
1543 * Get maximal frame index.
1544 *
1545 * \return frame index
1546 */
1547 int max() const
1548 {
1549 if (this->empty()) {
1550
1551 return -1;
1552
1553 } else {
1554
1555 int max = std::numeric_limits<int>::lowest();
1556
1557 for (const_iterator i = this->begin(); i != this->end(); ++i) {
1558 if (i->second > max) {
1559 max = i->second;
1560 }
1561 }
1562
1563 return max;
1564 }
1565 }
1566
1568
1569 // trigger
1570
1573
1580
1585
1591
1593 int dumpLimit; //!< maximum number of time slices to be dumped
1594 JStatus dumpMask; //!< mask for data to be dumped
1595
1596 // process management
1597
1600
1601 // memory management
1602
1603 long long int totalCPURAM;
1605 long long int maxQueueSize;
1606 long long int queueSize;
1607
1608 // statistics
1609
1611
1612 long long int numberOfEvents;
1613 long long int numberOfBytes;
1616
1619
1620 // temporary
1621
1624 long long int number_of_reads;
1626
1627 // circular buffer
1628
1630
1631 // random trigger
1632
1634
1636 gr(rd()),
1637 t1_ns(0.0)
1638 {}
1639
1640 std::random_device rd;
1641 std::mt19937_64 gr;
1642 double t1_ns;
1643
1645 };
1646}
1647
1648/**
1649 * \file
1650 *
1651 * Application for real-time filtering of data.
1652 * For more information, see KM3NETDAQ::JDataFilter.
1653 *
1654 * \author rbruijn and mdejong
1655 */
1656int main(int argc, char* argv[])
1657{
1658 using namespace std;
1659 using namespace JPP;
1660 using namespace KM3NETDAQ;
1661
1662 string server;
1663 string logger;
1664 string hostname;
1665 string client_name;
1666 int port;
1667 int backlog;
1668 bool use_cout;
1669 string path;
1670 string archive;
1671 int debug;
1672
1673
1674 try {
1675
1676 JParser<> zap("Application for real-time filtering of data.");
1677
1678 zap['H'] = make_field(server, "host name of server for command messages") = "localhost";
1679 zap['M'] = make_field(logger, "host name of server for logger messages") = "localhost";
1680 zap['D'] = make_field(hostname, "host name of server of data writer") = "";
1681 zap['u'] = make_field(client_name, "client name") = "%";
1682 zap['P'] = make_field(port, "port to listen for incoming data from data queue");
1683 zap['q'] = make_field(backlog, "back log") = 1024;
1684 zap['c'] = make_field(use_cout, "print to terminal");
1685 zap['p'] = make_field(path, "directory for temporary storage of circular buffer") = "/tmp/";
1686 zap['A'] = make_field(archive, "directory for permanent archival of circular buffer") = "/tmp/";
1687 zap['d'] = make_field(debug, "debug level") = 0;
1688
1689 zap(argc, argv);
1690 }
1691 catch(const std::exception& error) {
1692 FATAL(error.what() << endl);
1693 }
1694
1695
1696 JLogger* out = NULL;
1697
1698 if (use_cout)
1699 out = new JStreamLogger(cout);
1700 else
1701 out = new JControlHostLogger(logger);
1702
1703 JDataFilter dfilter(client_name,
1704 server,
1705 hostname,
1706 out,
1707 debug,
1708 port,
1709 backlog,
1710 path,
1711 archive);
1712
1713 dfilter.meta = JMeta(argc, argv);
1714
1715 dfilter.enter();
1716 dfilter.run();
1717}
Fixed parameters and ControlHost tags for KM3NeT DAQ.
KM3NeT DAQ constants, bit handling, etc.
Data structure for detector geometry and calibration.
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Basic data structure for L0 hit.
Basic data structure for L1 hit.
Tools for handling different hit types.
General purpose messaging.
#define FATAL(A)
Definition JMessage.hh:67
int debug
debug level
Definition JSirene.cc:74
ROOT I/O of application specific meta data.
Hostname and IP address functions.
Utility class to parse command line options.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition JParser.hh:2140
Physics constants.
I/O formatting auxiliaries.
Utility class to parse parameter values.
File status.
ROOT TTree parameter settings of various packages.
System auxiliaries.
System time information.
Scheduling of actions via fixed latency intervals.
Setting of trigger bits.
Basic data structure for time and time over threshold information of hit.
Auxiliary methods to convert data members or return values of member methods of a set of objects to a...
Auxiliary methods for handling file names, type names and environment.
void merge(const JMatch_t &match)
Merge events.
int getRunNumber() const
Get run number.
Definition JDAQCHSM.hh:111
std::string name
Definition JDAQCHSM.hh:165
JDAQStateMachine::ev_error_event ev_error
JDAQStateMachine::ev_configure_event ev_configure
Detector data structure.
Definition JDetector.hh:96
Router for direct addressing of module data in detector data structure.
Data structure for a composite optical module.
Definition JModule.hh:76
Utility class to parse parameter values.
bool read(const JEquation &equation)
Read equation.
Time keeper.
Auxiliary class for CPU timing and usage.
Definition JTimer.hh:33
unsigned long long usec_ucpu
Definition JTimer.hh:239
unsigned long long usec_wall
Definition JTimer.hh:238
void stop()
Stop timer.
Definition JTimer.hh:127
void reset()
Reset timer.
Definition JTimer.hh:93
unsigned long long usec_scpu
Definition JTimer.hh:240
void start()
Start timer.
Definition JTimer.hh:106
const JPosition3D & getPosition() const
Get position.
Byte array binary input.
const char * data() const
Get data.
int size() const
Get size.
int getFileDescriptor() const
Get file descriptor.
virtual bool is_open() const =0
Check is device is open.
Simple data structure to support I/O of equations (see class JLANG::JEquation).
Auxiliary class for method select.
void set(const int file_descriptor)
Set file descriptor.
bool has(const int file_descriptor) const
Has file descriptor.
Exception for opening of file.
The template JSinglePointer class can be used to hold a pointer to an object.
Message logging based on ControlHost.
Interface for logging messages.
Definition JLogger.hh:22
Message logger with time scheduler.
Message logging based on std::ostream.
Implemenation of object output through ControlHost.
TCP server socket.
Socket input channel.
void setReceiveBufferSize(const int size)
Set receive buffer size.
Definition JSocket.hh:148
int getReceiveBufferSize() const
Set receive buffer size.
Definition JSocket.hh:159
void setKeepAlive(const bool on)
Set keep alive of socket.
Definition JSocket.hh:104
TCP socket.
Definition JTCPSocket.hh:30
void setNonBlocking(const bool on)
Set non-blocking of I/O.
Definition JTCPSocket.hh:56
ControlHost tag.
Definition JTag.hh:38
std::string toString() const
Convert tag to string.
Definition JTag.hh:171
Utility class to parse command line options.
Definition JParser.hh:1697
TFile * getFile() const
Get file.
Definition JRootFile.hh:66
virtual bool is_open() const override
Check is file is open.
Definition JRootFile.hh:77
JTreeWriter< T, JRootCreateFlatTree< T >::value > * out
virtual bool put(const T &object) override
Object output.
ROOT TTree object output.
1-dimensional frame with time calibrated data from one optical module.
2-dimensional frame with time calibrated data from one optical module.
static JSuperFrame2D< JElement_t, JAllocator_t > demultiplex
Demultiplexer.
std::vector< value_type >::iterator iterator
void applyHighRateVeto(const double rate_Hz)
Apply high-rate veto.
Auxiliary class to build JDAQTimeslice for L1 timeslice.
Time slice with calibrated data.
Definition JTimeslice.hh:29
Data structure for input to trigger algorithm.
Nano-beacon trigger.
Definition JTriggerNB.hh:21
Auxiliary class to build KM3NETDAQ::JDAQEvent for a triggered event.
Simple data structure for the DAQ preamble required for a correct calculation of the object size for ...
const JDAQChronometer & getDAQChronometer() const
Get DAQ chronometer.
int getRunNumber() const
Get run number.
int getFrameIndex() const
Get frame index.
Control unit client base class.
JSharedPointer< JControlHost > server
message server
bool isRunning() const
Check if this client is in runnig state.
void replaceEvent(const JTag &oldTag, const JTag &newTag, JDAQEvent_t &event)
Replace tag of given event in event table.
void run()
Run as run control client following command messages via JNET::JControlHost.
JMessageLogger logger
message logger
virtual bool enter(const JArgs &args)
Enter the state machine.
void addSubscription(const JSubscription &subscription)
Add custom subscription.
int getModuleID() const
Get module identifier.
Auxiliary class for itemization of process list.
std::string index
index in process list
Data frame of one optical module.
static void reset()
Reset counter of unique instance of this class object.
Main class for real-time filtering of data.
long long int number_of_packets_received
JMessageScheduler logErrorRun
int dumpLimit
maximum number of time slices to be dumped
JSinglePointer< JServerSocket > serversocket
server for data queue connections
JMessageScheduler logErrorDetector
virtual void actionRunning() override
This method is repeatedly called when this client machine is in state Running and the clock interval ...
JCircularBuffer_t c_buffer
virtual void actionSelect(const JFileDescriptorMask &mask) override
Action method following last select call.
long long int numberOfBytes
long long int number_of_packets_discarded
JMessageScheduler logErrorIndex
static bool compare(const JDAQProcess &first, const JDAQProcess &second)
Sort DAQ process by index.
virtual void actionInit(int length, const char *buffer) override
void put(const T &object)
Auxiliary method to send object to data server.
JSocketInputChannel< JDAQAbstractPreamble > JSocketInputChannel_t
long long int number_of_bytes_received
virtual void actionContinue(int length, const char *buffer) override
long long int maxQueueSize
int port
server socket port
long long int totalCPURAM
void processTimeSlice(const JDAQTimesliceL0 &timeslice)
Process time slice.
std::deque< JDAQTimesliceL0 > timeslices
buffer with pending time slice data
std::vector< JDAQProcess > dataQueues
JMessageScheduler logErrorOvercomplete
long long int number_of_reads
std::vector< JSocketInputChannel_t > JChannelList_t
virtual void actionStop(int length, const char *buffer) override
JSinglePointer< JBuildL2_t > buildNB
JSinglePointer< JBuildL2_t > buildL2
JBuildL1< hit_type > JBuildL1_t
JSinglePointer< JBuildL1_t > buildL1
virtual void actionExit() override
virtual void actionQuit(int length, const char *buffer) override
virtual void actionTagged(const JTag &tag, int length, const char *buffer) override
Tagged action to handle alerts.
std::string hostname
host name of data server
virtual void actionConfigure(int length, const char *buffer) override
long long int numberOfTimeslicesProcessed
void updateFrameQueue(const JSocketInputChannel_t &channel)
Update queue with data frames.
JChannelList_t channelList
connections to data queue
long long int numberOfIncompleteTimeslicesProcessed
JSinglePointer< JTrigger3DMuon > trigger3DMuon
JDataFilter(const std::string &name, const std::string &server, const std::string &hostname, JLogger *logger, const int level, const int port, const int backlog, const std::string &path, const std::string &archive)
Constructor.
JSuperFrame1D< hit_type > JSuperFrame1D_t
virtual void setSelect(JFileDescriptorMask &mask) const override
Set the file descriptor mask for the select call.
JMessageScheduler logErrorIncomplete
JSuperFrame2D< hit_type > JSuperFrame2D_t
virtual void actionEnter() override
Interface methods for actions corresponding to state transitions.
JTimeslice< hit_type > JTimeslice_t
JStatus dumpMask
mask for data to be dumped
struct KM3NETDAQ::JDataFilter::rabbit_type rabbit
JSinglePointer< JModuleRouter > moduleRouter
JSinglePointer< JControlHost_t > datawriter
controlhost of data server (to which data writer should be connected)
JSinglePointer< JTimesliceRouter > timesliceRouter
JControlHostObjectOutput< JDAQTypes_t > JControlHost_t
JSinglePointer< JTriggerNB > triggerNB
JBuildL2< hit_type > JBuildL2_t
long long int numberOfEvents
std::vector< JDAQProcess > dataFilters
JSinglePointer< JTrigger3DShower > trigger3DShower
virtual void actionStart(int length, const char *buffer) override
virtual void actionPause(int length, const char *buffer) override
JSinglePointer< JTriggerMXShower > triggerMXShower
virtual void actionReset(int length, const char *buffer) override
std::set< int > modules
JSinglePointer< JBuildL2_t > buildSN
JTriggerParameters parameters
void typeout()
Report status to message logger.
int main()
double getMaximalDistance(const JDetector &detector, const bool option=false)
Get maximal distance between modules in detector.
std::string getFullPath(const std::string &path)
Get full path, i.e. add JEEP::PATHNAME_SEPARATOR if necessary.
T getMaximum(const array_type< T > &buffer, const T value)
Get maximum of values.
array_type< JValue_t > make_array(const JValue_t(&array)[N])
Method to create array of values.
Definition JVectorize.hh:69
std::string trim(const std::string &buffer)
Trim string.
static const long long int GIGABYTE
Number of bytes in a mega-byte.
int getSizeOfPacket(const KM3NETDAQ::JDAQAbstractPreamble &preamble)
Get size of packeet.
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
bool putObject(TDirectory &dir, const TObject &object)
Write object to ROOT directory.
const char * getName()
Get ROOT name of given data type.
static const JLocalTime getLocalTime
Function object to get local time in micro seconds.
long long int localtime_t
Type definition of local time.
unsigned long long int getRAM()
Get RAM of this CPU.
std::vector< std::string > getListOfIPaddresses()
Get list of IP address (decimal-dot notation).
Definition JNetwork.hh:216
int rename(const std::string &inputFile, const std::string &outputFile)
Rename file across file systems.
static JStat getFileStatus
Function object for file status.
Definition JStat.hh:173
return result
Definition JPolint.hh:862
const int n
Definition JPolint.hh:791
static const JChecksum checksum
Function object to perform check-sum of raw data.
Definition JChecksum.hh:200
KM3NeT DAQ data structures and auxiliaries.
Definition DataQueue.cc:39
size_t getNumberOfFrames(const size_t number_of_frames, const double factor)
Get expected number of frames according a given allowed fraction of active modules.
static const JNET::JTag RC_DFILTER
Definition JDAQTags.hh:73
double getFrameTime()
Get frame time duration.
Definition JDAQClock.hh:162
double getTimeOfFrame(const int frame_index)
Get start time of frame in ns since start of run for a given frame index.
Definition JDAQClock.hh:185
static const JNET::JTag RC_ALERT
Definition JDAQTags.hh:79
static const int DFILTER_DQUEUE_BUFFER_SIZE
socket JDataFilter.cc <- DataQueue.cc
Definition JDAQTags.hh:36
static const int DFILTER_RECEIVE_BUFFER_SIZE
socket JDataFilter.cc <- JLigier.cc
Definition JDAQTags.hh:37
static const JNET::JTag RC_CMD
Definition JDAQTags.hh:66
static const int DFILTER_SEND_BUFFER_SIZE
socket JDataFilter.cc -> JDataWriter.cc
Definition JDAQTags.hh:38
static const JNET::JTag IO_TRIGGER_PARAMETERS
Definition JDAQTags.hh:90
size_t getSizeof()
Definition of method to get size of data type.
static const int HIGH_RATE_VETO_DISABLE
Enable (disable) use of high-rate veto test if this status bit is 0 (1);.
Definition pmt_status.hh:14
Auxiliary data structure for sequence of same character.
Definition JManip.hh:330
Auxiliary data structure for floating point format specification.
Definition JManip.hh:448
Detector file.
Definition JHead.hh:227
Match of two events considering overlap in time and position.
Auxiliary class for handling status.
Definition JStatus.hh:31
void set(const int bit)
Set PMT status.
Definition JStatus.hh:209
Type list.
Definition JTypeList.hh:23
Level specific message streamers.
Auxiliary class for all subscription.
Auxiliary class for ROOT I/O of application specific meta data.
Definition JMeta.hh:72
Auxiliary class for date and time.
int getYear() const
year a.d.
int getDay() const
day of the month [1-31]
int getMonth() const
month of the year [1-12]
Auxiliary data structure for running average and standard deviation.
Definition JStats.hh:44
double getXmax() const
Get maximum value.
Definition JStats.hh:201
void put(const double x, const double w=1.0)
Put value.
Definition JStats.hh:119
double getMean() const
Get mean value.
Definition JStats.hh:234
void reset()
Reset.
Definition JStats.hh:79
Auxiliary data structure for result of checksum.
Definition JChecksum.hh:90
@ ETDC_t
TDC value error.
Definition JChecksum.hh:47
@ SIZE_t
size error
Definition JChecksum.hh:50
@ EPMT_t
PMT number error.
Definition JChecksum.hh:46
@ TIME_t
Time order error.
Definition JChecksum.hh:48
Router for fast addressing of hits in KM3NETDAQ::JDAQTimeslice data structure as a function of the op...
const JTag & getUniqueTag() const
Get unique tag of this run control client.
const std::string & getFullName() const
Get full name of this run control client.
void setClockInterval(const long long int interval_us)
Set interval time.
long long int getClockInterval() const
Get interval time.
Timeslice data structure for L0 data.
std::string archive
Directory for permanent archival.
std::string path
Directory for temporary storage.
Long64_t sizeL1
Number of L1 time slices.
Long64_t sizeSN
Number of SN time slices.
friend std::ostream & operator<<(std::ostream &out, const JCircularBuffer_t &object)
Write circular buffer to output stream.
static const int MAXIMUM_FILE_NUMBER
maximum file number for overwrite protection.
JTag tag
Unique tag of this process.
Long64_t sizeL0
Number of L0 time slices.
void close(const bool option)
Close file.
Long64_t sizeL2
Number of L2 time slices.
JCircularBuffer_t(const std::string &path, const std::string &archive, const JTag &tag)
Constructor.
bool is_enabled() const
Check whether writing of data is enabled.
static const int JTRIGGERRANDOM
Random trigger.
Definition trigger.hh:17