DUNE-DAQ
DUNE Trigger and Data Acquisition software
Loading...
Searching...
No Matches
StreamManager.cpp
Go to the documentation of this file.
1/*
2 * DUNE DAQ modification notice:
3 * This file has been modified from the original ATLAS ers source for the DUNE DAQ project.
4 * Fork baseline commit: 8267df82a4f6fe6bf02c4014923eba19eddc4614 (2020-04-14).
5 * Renamed since fork: yes (from src/StreamManager.cxx to src/StreamManager.cpp).
6 *
7 * Original copyright:
8 * Copyright (C) 2001-2020 CERN for the benefit of the ATLAS collaboration.
9 * Licensed under the Apache License, Version 2.0.
10 */
11
12/*
13 * StreamManager.cxx
14 * ERS
15 *
16 * Created by Matthias Wiesmann on 21.01.05.
17 * Modified by Serguei Kolos on 12.09.06.
18 * Copyright 2005 CERN. All rights reserved.
19 *
20 */
21
22#include <assert.h>
23#include <iostream>
24
25#include <ers/Issue.hpp>
26#include <ers/InputStream.hpp>
27#include <ers/OutputStream.hpp>
28#include <ers/StreamManager.hpp>
29#include <ers/StreamFactory.hpp>
30#include <ers/Severity.hpp>
31#include <ers/Configuration.hpp>
32#include <ers/ers.hpp>
34#include <ers/internal/Util.hpp>
38
40 BadConfiguration,
41 "The stream configuration string \"" << config << "\" has syntax errors.",
42 ((std::string)config) )
43
44namespace
45{
49 const char SEPARATOR = ',';
50
51 const char * const DefaultOutputStreams[] =
52 {
53 "lstdout", // Debug
54 "lstdout", // Log
55 "throttle,lstdout", // Information
56 "throttle,lstderr", // Warning
57 "throttle,lstderr", // Error
58 "lstderr" // Fatal
59 };
60
61 const char *
62 get_stream_description( ers::severity severity )
63 {
64 assert( ers::Debug <= severity && severity <= ers::Fatal );
65
66 std::string env_name( "DUNEDAQ_ERS_" );
67 env_name += ers::to_string( severity );
68 const char * env = ::getenv( env_name.c_str() );
69 return env ? env : DefaultOutputStreams[severity];
70 }
71
72 void
73 parse_stream_definition( const std::string & text,
74 std::vector<std::string> & result )
75 {
76 std::string::size_type start_p = 0, end_p = 0;
77 short brackets_open = 0;
78 while ( end_p < text.length() )
79 {
80 switch ( text[end_p] )
81 {
82 case '(':
83 ++brackets_open;
84 break;
85 case ')':
86 --brackets_open;
87 break;
88 case SEPARATOR:
89 if ( !brackets_open )
90 {
91 result.push_back( text.substr( start_p, end_p - start_p ) );
92 start_p = end_p + 1;
93 }
94 break;
95 default:
96 break;
97 }
98 end_p++;
99 }
100 if ( brackets_open )
101 {
102 throw ers::BadConfiguration( ERS_HERE, text );
103 }
104 if ( start_p != end_p )
105 {
106 result.push_back( text.substr( start_p, end_p - start_p ) );
107 }
108 }
109}
110
111namespace ers
112{
113 // Performs lazy srteam initialization. Stream instances are created
114 // at the first attempt of writing to the stream
116 {
117 public:
119 : m_manager( manager ),
120 m_in_progress( false )
121 { ; }
122
123 void write( const Issue & issue )
124 {
125 ers::severity s = issue.severity();
126 std::scoped_lock lock( m_mutex );
127
128 if ( !m_in_progress ) {
129 m_in_progress = true;
130 }
131 else {
132 // The issue is coming from the stream constructor
133 // We can't use ERS streams, so print it to std
134 if ( s < ers::Warning )
135 std::cout << issue << std::endl;
136 else
137 std::cerr << issue << std::endl;
138 return ;
139 }
140
141 if ( m_manager.m_out_streams[s].get() == this ) {
142 m_manager.m_out_streams[s] =
143 std::shared_ptr<OutputStream>( m_manager.setup_stream( s ) );
144 }
145 m_manager.report_issue( s, issue );
146 m_in_progress = false;
147 }
148
149 private:
150 std::recursive_mutex m_mutex;
153 };
154
155}
156
170
175{
176 for( short ss = ers::Debug; ss <= ers::Fatal; ++ss )
177 {
178 m_init_streams[ss] = std::make_shared<StreamInitializer>( *this );
180 }
181}
182
187
188void
190{
191 std::shared_ptr<OutputStream> head = m_out_streams[severity];
192 if ( head && !head->isNull() )
193 {
194 OutputStream * parent = head.get();
195 for ( OutputStream * stream = parent; !stream->isNull(); parent = stream,
196 stream = &parent->chained() )
197 ;
198
199 parent->chained( new_stream );
200 }
201 else
202 {
203 m_out_streams[severity] = std::shared_ptr<OutputStream>( new_stream );
204 }
205}
206
207void
208ers::StreamManager::add_receiver( const std::string & stream,
209 const std::string & filter,
210 ers::IssueReceiver * receiver )
211{
212 InputStream * in = ers::StreamFactory::instance().create_in_stream( stream, filter );
213 in->set_receiver( receiver );
214
215 std::scoped_lock lock( m_mutex );
216 m_in_streams.push_back( std::shared_ptr<InputStream>( in ) );
217}
218
219void
220ers::StreamManager::add_receiver( const std::string & stream,
221 const std::initializer_list<std::string> & params,
222 ers::IssueReceiver * receiver )
223{
224 InputStream * in = ers::StreamFactory::instance().create_in_stream( stream, params );
225 in->set_receiver( receiver );
226
227 std::scoped_lock lock( m_mutex );
228 m_in_streams.push_back( std::shared_ptr<InputStream>( in ) );
229}
230
231void
233{
234 std::scoped_lock lock( m_mutex );
235 for( std::list<std::shared_ptr<InputStream> >::iterator it = m_in_streams.begin();
236 it != m_in_streams.end(); )
237 {
238 if ( (*it) -> m_receiver == receiver )
239 m_in_streams.erase( it++ );
240 else
241 ++it;
242 }
243}
244
247{
248 std::string config = get_stream_description( severity );
249 std::vector<std::string> streams;
250 try
251 {
252 parse_stream_definition( config, streams );
253 }
254 catch ( ers::BadConfiguration & ex )
255 {
256 ERS_INTERNAL_ERROR( "Configuration for the \"" << severity << "\" stream is invalid. "
257 "Default configuration will be used." );
258 }
259
260 ers::OutputStream * main = setup_stream( streams );
261
262 if ( !main )
263 {
264 std::vector<std::string> default_streams;
265 try
266 {
267 parse_stream_definition( DefaultOutputStreams[severity], default_streams );
268 main = setup_stream( default_streams );
269 }
270 catch ( ers::BadConfiguration & ex )
271 {
272 ERS_INTERNAL_ERROR( "Can not configure the \"" << severity
273 << "\" stream because of the following issue {" << ex << "}" );
274 }
275 }
276 return ( main ? main : new ers::NullStream() );
277}
278
280ers::StreamManager::setup_stream( const std::vector<std::string> & streams )
281{
282 size_t cnt = 0;
284 for ( ; cnt < streams.size(); ++cnt )
285 {
286 main = ers::StreamFactory::instance().create_out_stream( streams[cnt] );
287 if ( main )
288 break;
289 }
290
291 if ( !main )
292 {
293 return 0;
294 }
295
296 ers::OutputStream * head = main;
297 for ( ++cnt; cnt < streams.size(); ++cnt )
298 {
299 ers::OutputStream * chained = ers::StreamFactory::instance().create_out_stream( streams[cnt] );
300
301 if ( chained )
302 {
303 head->chained( chained );
304 head = chained;
305 }
306 }
307
308 return main;
309}
310
315void
317{
318 ers::severity old_severity = issue.set_severity( type );
319 m_out_streams[type]->write( issue );
320 issue.set_severity( old_severity );
321} // error
322
326void
328{
329 report_issue( ers::Error, issue );
330} // error
331
336void
337ers::StreamManager::debug( const Issue & issue, int level )
338{
339 if ( Configuration::instance().debug_level() >= level )
340 {
341 ers::severity old_severity = issue.set_severity( ers::Severity( ers::Debug, level ) );
342 m_out_streams[ers::Debug]->write( issue );
343 issue.set_severity( old_severity );
344 }
345}
346
350void
352{
353 report_issue( ers::Fatal, issue );
354}
355
359void
361{
362 report_issue( ers::Warning, issue );
363}
364
368void
370{
372}
373
377void
379{
380 report_issue( ers::Log, issue );
381}
382
383std::ostream &
384ers::operator<<( std::ostream & out, const ers::StreamManager & )
385{
386 for( short ss = ers::Debug; ss <= ers::Fatal; ++ss )
387 {
388 out << (ers::severity)ss << "\t\""
389 << get_stream_description( (ers::severity)ss ) << "\"" << std::endl;
390 }
391 return out;
392}
#define ERS_HERE
static Configuration & instance()
return the singleton
ERS Issue input stream interface.
void set_receiver(IssueReceiver *receiver)
ERS Issue receiver interface.
Base class for any user define issue.
Definition Issue.hpp:80
ers::Severity severity() const
severity of the issue
Definition Issue.hpp:123
ers::Severity set_severity(ers::Severity severity) const
Definition Issue.cpp:191
ERS abstract output stream interface.
virtual bool isNull() const
friend class StreamManager
OutputStream & chained()
void write(const Issue &issue)
std::recursive_mutex m_mutex
StreamManager & m_manager
StreamInitializer(StreamManager &manager)
This class manages and provides access to ERS streams.
void add_output_stream(ers::severity severity, ers::OutputStream *new_stream)
void error(const Issue &issue)
sends an issue to the error stream
std::shared_ptr< OutputStream > m_init_streams[ers::Fatal+1]
array of pointers to streams per severity
OutputStream * setup_stream(ers::severity severity)
void warning(const Issue &issue)
sends an issue to the warning stream
static StreamManager & instance()
return the singleton
std::list< std::shared_ptr< InputStream > > m_in_streams
void report_issue(ers::severity type, const Issue &issue)
void log(const Issue &issue)
sends an issue to the log stream
void fatal(const Issue &issue)
sends an issue to the fatal stream
void add_receiver(const std::string &stream, const std::string &filter, ers::IssueReceiver *receiver)
void debug(const Issue &issue, int level)
sends an Issue to the debug stream
void information(const Issue &issue)
sends an issue to the information stream
std::shared_ptr< OutputStream > m_out_streams[ers::Fatal+1]
array of pointers to streams per severity
void remove_receiver(ers::IssueReceiver *receiver)
int main(int argc, char *argv[])
#define ERS_INTERNAL_ERROR(message)
Definition macro.hpp:63
#define ERS_DECLARE_ISSUE( namespace_name, class_name, message_, attributes)
Definition macro.hpp:65
int debug_level()
Definition ers.hpp:77
std::string to_string(severity s)
std::ostream & operator<<(std::ostream &, const ers::Configuration &)
severity
Definition Severity.hpp:37
@ Debug
Definition Severity.hpp:37
@ Error
Definition Severity.hpp:37
@ Fatal
Definition Severity.hpp:37
@ Log
Definition Severity.hpp:37
@ Warning
Definition Severity.hpp:37
@ Information
Definition Severity.hpp:37
Null stream.