Jpp 21.0.0-rc.1-88-g0130508c4
the software that should make you happy
Loading...
Searching...
No Matches
JDataWriter.cc
Go to the documentation of this file.
1#include <string>
2#include <iostream>
3#include <sstream>
4#include <iomanip>
5#include <map>
6
8
10#include "JLang/JException.hh"
13#include "JDAQ/JDAQTags.hh"
14#include "JDAQ/JDAQEventIO.hh"
20#include "JIO/JByteArrayIO.hh"
21#include "JTools/JAutoMap.hh"
22#include "JSupport/JMeta.hh"
23#include "JSupport/JSupport.hh"
25#include "Jeep/JParser.hh"
26#include "Jeep/JProperties.hh"
27#include "Jeep/JTimer.hh"
28#include "Jeep/JTimekeeper.hh"
29#include "Jeep/JPrint.hh"
30#include "Jeep/JeepToolkit.hh"
31
32
33/**
34 * Type definition of auto map.
35 */
37
38
39namespace JSUPPORT {
40
41 /**
42 * Get key for given DAQ data type.
43 *
44 * \param type data type
45 * \return map element
46 */
47 template<>
48 template<class T>
50 {
51 return getTag<T>();
52 }
53}
54
55
56namespace KM3NETDAQ {
57
58 /**
59 * Runcontrol client to write data to disk.
60 * In state running, this application will write ROOT formatted data from the data filters to disk.
61 */
63 public JDAQClient
64 {
65 public:
66 /**
67 * Constructor.
68 *
69 * \param name name of client
70 * \param server name of command message server
71 * \param hostname name of data server
72 * \param logger pointer to logger
73 * \param level debug level
74 * \param path default path
75 */
76 JDataWriter(const std::string& name,
77 const std::string& server,
78 const std::string& hostname,
80 const int level,
81 const std::string& path) :
82 JDAQClient(name, server, logger, level),
83 datawriter(),
84 path (path),
86 {
88
90
91 // map ControlHost tag to TTree writer.
92
94 }
95
96
97 virtual void actionInit(int length, const char* buffer) override
98 {
99 using namespace std;
100 using namespace JPP;
101
102 // start server
103
104 try {
105
106 datawriter.reset(new JControlHost(hostname));
107
108 datawriter->setReceiveBufferSize(DWRITER_RECEIVE_BUFFER_SIZE);
109
110 datawriter->MyId(getFullName());
111
113
114 for (JTreeWriter_t::iterator i = writer.begin(); i != writer.end(); ++i) {
115 buffer.add(JSubscriptionAll(i->first));
116 }
117
119
120 datawriter->Subscribe(buffer);
121 datawriter->SendMeAlways();
122
123 JNoticeStream(logger) << "Established connection to " << hostname;
124 }
125 catch(const std::exception& exception) {
126 JErrorStream(logger) << exception.what();
127 }
128 }
129
130
131 virtual void actionConfigure(int length, const char* buffer) override
132 {
133 using namespace std;
134
135 long long int update_s = 10;
136 long long int logger_s = 5;
137
138 JProperties properties(JEquationParameters("=", ";", "", ""));
139
140 properties["path"] = path;
141 properties["update_s"] = update_s;
142 properties["logger_s"] = logger_s;
143
144 properties.read(string(buffer, length));
145
146 if (update_s <= 0) { update_s = 1; }
147 if (logger_s <= 0) { logger_s = 1; }
148
149 setClockInterval(update_s * 1000000LL);
150
151 JDebugStream(logger) << "Path <" << path << ">";
152 JDebugStream(logger) << "Update period [s] " << update_s;
153
154 logErrorRun = JMessageScheduler(logger, JTimekeeper(logger_s * 1000000LL));
155 logErrorFile = JMessageScheduler(logger, JTimekeeper(logger_s * 1000000LL));
156 logErrorTag = JMessageScheduler(logger, JTimekeeper(logger_s * 1000000LL));
157 logErrorState = JMessageScheduler(logger, JTimekeeper(logger_s * 1000000LL));
158
159 numberOfEvents = 0;
160 numberOfBytes = 0;
161 }
162
163
164 virtual void actionReset(int length, const char* buffer) override
165 {
166 datawriter.reset();
167 }
168
169
170 virtual void actionQuit(int length, const char* buffer) override
171 {}
172
173
174 virtual void actionStart(int length, const char* buffer) override
175 {
176 using namespace std;
177 using namespace JPP;
178
179 JStatusStream(logger) << "Start run " << getDetectorID() << ' ' << getRunNumber();
180
181 if (writer.is_open()) {
182
183 JErrorStream (logger) << "Previous file still open -> close";
184
185 writer.close();
186 }
187
188 ostringstream os;
189
190 for (int i = 0; !writer.is_open() && i != MAXIMUM_FILE_NUMBER; ++i) {
191
192 os.str("");
193
194 os << getFullPath(path)
195 << "KM3NeT"
196 << "_" << FILL(8,'0') << getDetectorID()
197 << "_" << FILL(8,'0') << getRunNumber();
198
199 if (i != 0) {
200 os << "_" << i;
201 }
202
203 os << ".root";
204
205 try {
206 writer.open(os.str().c_str());
207 }
208 catch(const std::exception& exception) {
209 JErrorStream(logger) << exception.what();
210 }
211 }
212
213 if (writer.is_open())
214 JNoticeStream(logger) << "Output file " << os.str();
215 else
216 JErrorStream (logger) << "File not opened " << os.str();
217
218 numberOfEvents = 0;
219 numberOfBytes = 0;
220
222
223 timer.reset();
224
229
231 }
232
233
234 virtual void actionStop(int length, const char* buffer) override
235 {
236 typeout();
237
238 if (timer.usec_wall > 0) {
239 JStatusStream(logger) << "I/O " << (int) (numberOfBytes / timer.usec_wall) << " MB/s";
240 }
241
243 JErrorStream(logger) << "No trigger parameters written for run " << getRunNumber();
244 }
245
246 writer.close();
247
248 // Release resources.
249
251
252 this->buffer.swap(null);
253 }
254
255
256 virtual void setSelect(JFileDescriptorMask& mask) const override
257 {
258 if (datawriter.is_valid()) {
259 mask.set(*datawriter);
260 }
261 }
262
263
264 virtual void actionSelect(const JFileDescriptorMask& mask) override
265 {
266 using namespace std;
267 using namespace JPP;
268
269 if (datawriter.is_valid() && mask.has(*datawriter)) {
270
271 try {
272
273 JPrefix prefix;
274
275 try {
276
277 datawriter->WaitHead(prefix);
278
279 timer.start();
280
281 buffer.resize(prefix.getSize());
282
283 datawriter->GetFullData(buffer.data(), buffer.size());
284 }
285 catch(const JSocketException& error) {
286
287 JErrorStream(logger) << "Fatal error receiving data: \"" << error.what() << "\" -> disconnect and trigger ev_error.";
288
289 datawriter.reset();
290
291 ev_error();
292 }
293
294 if (prefix.getTag() == IO_TRIGGER_PARAMETERS) {
295
296 try {
297 run_db.read(buffer.data(), buffer.size());
298 }
299 catch(const std::exception& error) {
300
301 JErrorStream(logger) << "Fatal error reading trigger parameters \"" << error.what() << "\"; trigger ev_error.";
302
303 ev_error();
304 }
305 }
306
307
308 if (isRunning()) {
309
310 // Write trigger parameters for current run if not yet done
311
313
314 JTreeWriter_t::iterator i = writer.find(prefix.toString());
315
316 if (i != writer.end()) {
317
318 TFile* out = i->second->GetCurrentFile();
319
320 if (out != NULL && out->IsOpen()) {
321
322 JDAQPreamble preamble;
323 Version_t version;
324 JDAQHeader header;
325
326 JByteArrayReader in(buffer.data(), buffer.size());
327
328 in >> preamble >> version >> header;
329
330 in.seekg(0); // rewind
331
332 if (header.getRunNumber() == getRunNumber()) {
333
334 const Int_t nb = i->second->copy(in);
335
336 if (nb < (int) buffer.size() || in.tellg() != (int) buffer.size()) {
337 JWarningStream(logger) << "Inconsistency at copy of "
338 << prefix.toString() << ' '
339 << buffer.size() << ' '
340 << in.tellg() << ' '
341 << nb;
342 }
343
344 if (prefix.getTag() == IO_EVENT)
345 numberOfEvents += 1;
346 numberOfBytes += buffer.size();
347
348 if (prefix.getTag() == IO_EVENT && numberOfEvents == 1) {
349 typeout();
350 }
351
352 } else {
353 JErrorStream(logErrorRun) << "Inconsistent run number "
354 << header.getRunNumber()
355 << " != "
356 << getRunNumber();
357 }
358 } else {
359 JErrorStream(logErrorFile) << "Output file not open";
360 }
361 } else {
362 if (prefix.getTag() != IO_TRIGGER_PARAMETERS) {
363 JErrorStream(logErrorTag) << "Unknown tag <" << prefix.toString() << ">, no data written";
364 }
365 }
366 } else {
367 JWarningStream(logErrorState) << "Not in running state <" << prefix.toString() << ">, no data written";
368 }
369
370 timer.stop();
371 }
372 catch(const std::exception& error) {
373
374 JErrorStream(logger) << "Fatal error \"" << error.what() << "\"; trigger ev_error.";
375
376 ev_error();
377 }
378 }
379 }
380
381
382 virtual void actionRunning() override
383 {
384 typeout();
385 }
386
387
388 /**
389 * Report status of data writing.
390 */
391 void typeout()
392 {
393 std::ostringstream message;
394
396
397 logger.typeout(RC_LOG, message.str());
398 logger.status(message.str());
399 }
400
401 JMeta meta; //!< meta data
402
403 static const int MAXIMUM_FILE_NUMBER = 100; //!< maximum file number for overwrite protection.
404
405 private:
406
408 std::string path; // directory for output file
409
410 JEEP::JTimer timer; // timer for I/O measurement
411 Long64_t numberOfEvents; // total number of events
412 long long int numberOfBytes; // total number of bytes
413
418
419 std::string hostname; //!< host name of data server
420 JTreeWriter_t writer; //!< TTree writer
421 std::vector<char> buffer; //!< internal buffer for incoming data
422
423
424 /**
425 * Auxiliary data structure for I/O of trigger parameters.
426 */
427 struct JValue_t {
428 /**
429 * Default constructor.
430 */
432 count(0),
433 is_written(false)
434 {}
435
436 JTriggerParameters parameters; //!< trigger parameters
437 int count; //!< reader count
438 bool is_written; //!< writer status
439 };
440
441
442 /**
443 * Map run number to trigger parameters.
444 */
445 struct JRunDB :
446 public std::map<int, JValue_t>
447 {
448 /**
449 * Remove all entries before given run.
450 *
451 * \param run run number
452 */
453 inline void reset(const int run)
454 {
455 while (!this->empty() && this->begin()->first < run) {
456 this->erase(this->begin());
457 }
458 }
459
460 /**
461 * Check if trigger parameters have been written for given run.
462 *
463 * \param run run number
464 * \return true if written; else false.
465 */
466 inline bool is_written(const int run) const
467 {
468 const_iterator p = this->find(run);
469
470 return p != this->end() && p->second.is_written;
471 }
472
473 /**
474 * Read trigger parameters.
475 *
476 * \param data data
477 * \param size size
478 */
479 void read(const char* const data, const size_t size)
480 {
481 using namespace std;
482 using namespace JPP;
483
484
485 const string buffer(data, size);
486
487 istringstream in(buffer);
488
489 int run = -1;
490 JTriggerParameters parameters;
491
492 in >> run;
493
494 if (!in) {
495 THROW(JIOException, "Error reading run number for trigger parameters " << run << endl << in.rdbuf());
496 }
497
498 in >> parameters;
499
500 in.clear(std::ios::eofbit);
501
502 if (!in) {
503 THROW(JIOException, "Error reading trigger parameters " << in.rdbuf());
504 }
505
506 JValue_t& value = (*this)[run];
507
508 if (value.count == 0) {
509 value.parameters = parameters;
510 }
511
512 value.count += 1;
513
514 if (!parameters.equals(value.parameters)) {
515 THROW(JException, "Inconsistent trigger parameters " << endl << value.parameters << " != " << endl << parameters);
516 }
517 }
518
519 /**
520 * Write trigger parameters for given run if not yet done.
521 *
522 * \param run run number
523 * \param file pointer to ROOT file
524 */
525 inline void write(const int run, TFile* file)
526 {
527 if (file != NULL) {
528
529 iterator p = this->find(run);
530
531 if (p != this->end() && p->second.count != 0 && !p->second.is_written) {
532
533 file->WriteTObject(&p->second.parameters);
534
535 p->second.is_written = true;
536 }
537 }
538 }
539 };
540
542 };
543}
544
545
546/**
547 * \file
548 *
549 * Application for writing real-time data to disk.
550 * \author mdejong
551 */
552int main(int argc, char* argv[])
553{
554 using namespace std;
555 using namespace JPP;
556 using namespace KM3NETDAQ;
557
558 string server;
559 string logger;
560 string hostname;
561 string client_name;
562 bool use_cout;
563 string path;
564 int debug;
565
566 try {
567
568 JParser<> zap("Application for writing real-time data to disk.");
569
570 zap['H'] = make_field(server, "host name of server for command messages") = "localhost";
571 zap['M'] = make_field(logger, "host name of server for logger messages") = "localhost";
572 zap['D'] = make_field(hostname, "host name of server for incoming data from data filter") = "localhost";
573 zap['u'] = make_field(client_name, "client name") = "%";
574 zap['c'] = make_field(use_cout, "print to terminal");
575 zap['p'] = make_field(path, "directory for permanent archival of data") = "";
576 zap['d'] = make_field(debug, "debug level") = 0;
577
578
579 zap(argc, argv);
580 }
581 catch(const exception &error) {
582 FATAL(error.what() << endl);
583 }
584
585
586 JLogger* out = NULL;
587
588 if (use_cout)
589 out = new JStreamLogger(cout);
590 else
591 out = new JControlHostLogger(logger);
592
593 JDataWriter dwriter(getProcessName(client_name, argv[0]), server, hostname, out, debug, path);
594
595 dwriter.meta = JMeta(argc, argv);
596
597 dwriter.enter();
598 dwriter.run();
599}
Fixed parameters and ControlHost tags for KM3NeT DAQ.
KM3NeT DAQ constants, bit handling, etc.
JSUPPORT::JAutoTreeWriter< JNET::JTag > JTreeWriter_t
Type definition of auto map.
Exceptions.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
#define FATAL(A)
Definition JMessage.hh:67
int debug
debug level
Definition JSirene.cc:74
ROOT I/O of application specific meta data.
Utility class to parse command line options.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition JParser.hh:2140
I/O formatting auxiliaries.
Utility class to parse parameter values.
ROOT TTree parameter settings of various packages.
Scheduling of actions via fixed latency intervals.
Auxiliary methods for handling file names, type names and environment.
int getDetectorID() const
Get detector identifier.
Definition JDAQCHSM.hh:100
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
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_wall
Definition JTimer.hh:238
void stop()
Stop timer.
Definition JTimer.hh:127
void reset()
Reset timer.
Definition JTimer.hh:93
void start()
Start timer.
Definition JTimer.hh:106
Byte array binary input.
int tellg() const
Get read position.
void seekg(const int pos)
Set read position.
Simple data structure to support I/O of equations (see class JLANG::JEquation).
General exception.
Definition JException.hh:25
virtual const char * what() const override
Get error message.
Definition JException.hh:65
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 I/O.
The template JSharedPointer class can be used to share a pointer to an object.
Exception for socket.
static void Throw(const bool option)
Definition JThrow.hh:37
Message logging based on ControlHost.
Interface for logging messages.
Definition JLogger.hh:22
virtual void typeout(const std::string &tag, const std::string &message) override
Report message.
void status(const JMessage_t &message)
Message logger with time scheduler.
Message logging based on std::ostream.
ControlHost class.
ControlHost prefix.
Definition JPrefix.hh:33
int getSize() const
Get size.
Definition JPrefix.hh:62
Subscription list.
ControlHost tag.
Definition JTag.hh:38
std::string toString() const
Convert tag to string.
Definition JTag.hh:171
const JTag & getTag() const
Get tag.
Definition JTag.hh:86
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
Auxiliary class to copy input data to corresponding TTree.
virtual void open(const char *file_name) override
Open file.
void insert()
Insert (list of) data type(s).
virtual void close() override
Close file.
static JKey_t getKey(JType< T > type)
Get key.
int getRunNumber() const
Get run number.
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.
Runcontrol client to write data to disk.
virtual void actionStop(int length, const char *buffer) override
void typeout()
Report status of data writing.
std::string hostname
host name of data server
long long int numberOfBytes
virtual void actionSelect(const JFileDescriptorMask &mask) override
Action method following last select call.
virtual void actionInit(int length, const char *buffer) override
JTreeWriter_t writer
TTree writer.
JLANG::JSharedPointer< JControlHost > datawriter
JMessageScheduler logErrorFile
JMessageScheduler logErrorRun
virtual void actionRunning() override
This method is repeatedly called when this client machine is in state Running and the clock interval ...
virtual void actionQuit(int length, const char *buffer) override
virtual void setSelect(JFileDescriptorMask &mask) const override
Set the file descriptor mask for the select call.
JMessageScheduler logErrorState
std::vector< char > buffer
internal buffer for incoming data
virtual void actionReset(int length, const char *buffer) override
JDataWriter(const std::string &name, const std::string &server, const std::string &hostname, JLogger *logger, const int level, const std::string &path)
Constructor.
virtual void actionStart(int length, const char *buffer) override
virtual void actionConfigure(int length, const char *buffer) override
static const int MAXIMUM_FILE_NUMBER
maximum file number for overwrite protection.
JMessageScheduler logErrorTag
int main()
std::string getFullPath(const std::string &path)
Get full path, i.e. add JEEP::PATHNAME_SEPARATOR if necessary.
static JNullStream null
Null I/O stream.
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.
Support classes and methods for experiment specific I/O.
KM3NeT DAQ data structures and auxiliaries.
Definition DataQueue.cc:39
static const JNET::JTag RC_DWRITER
Definition JDAQTags.hh:71
static const JNET::JTag IO_EVENT
Definition JDAQTags.hh:88
static const int DWRITER_RECEIVE_BUFFER_SIZE
socket JDataWriter.cc <- JDataFilter.cc
Definition JDAQTags.hh:39
static const JNET::JTag RC_CMD
Definition JDAQTags.hh:66
static const JNET::JTag RC_LOG
Definition JDAQTags.hh:72
std::string getProcessName(const std::string &name, const std::string &process)
Get process name of run control client.
char getTokenDelimeter()
Get the token delimeter for command messages.
static const JNET::JTag IO_TRIGGER_PARAMETERS
Definition JDAQTags.hh:90
Auxiliary data structure for sequence of same character.
Definition JManip.hh:330
Type list.
Definition JTypeList.hh:23
Auxiliary class for a type holder.
Definition JType.hh:19
Level specific message streamers.
Auxiliary class for all subscription.
Auxiliary class for ROOT I/O of application specific meta data.
Definition JMeta.hh:72
const std::string & getFullName() const
Get full name of this run control client.
void setClockInterval(const long long int interval_us)
Set interval time.
Map run number to trigger parameters.
void reset(const int run)
Remove all entries before given run.
void write(const int run, TFile *file)
Write trigger parameters for given run if not yet done.
bool is_written(const int run) const
Check if trigger parameters have been written for given run.
void read(const char *const data, const size_t size)
Read trigger parameters.
Auxiliary data structure for I/O of trigger parameters.
JValue_t()
Default constructor.
JTriggerParameters parameters
trigger parameters