This file is indexed.

/usr/include/arc/Logger.h is in nordugrid-arc-dev 4.0.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
// -*- indent-tabs-mode: nil -*-

#ifndef __ARC_LOGGER__
#define __ARC_LOGGER__

#include <string>
#include <list>
#include <map>
#include <iostream>
#include <fstream>

#include <arc/Thread.h>
#include <arc/IString.h>

namespace Arc {

  /** \addtogroup common
   *  @{ */
  /// Logging levels for tagging and filtering log messages.
  enum LogLevel {
    DEBUG = 1,   ///< DEBUG level designates finer-grained informational events
                 ///< which should only be used for debugging purposes.
    VERBOSE = 2, ///< VERBOSE level designates fine-grained informational events
                 ///< that will give additional information about the application.
    INFO = 4,    ///< INFO level designates informational messages that highlight
                 ///< the progress of the application at coarse-grained level.
    WARNING = 8, ///< WARNING level designates potentially harmful situations.
    ERROR = 16,  ///< ERROR level designates error events that might still allow
                 ///< the application to continue running.
    FATAL = 32   ///< FATAL level designates very severe error events that will
                 ///< presumably lead the application to abort.
  };

  /// Output formats. Defines prefix for each message.
  enum LogFormat {
    LongFormat,  ///< all information about message is printed
    MediumFormat,///< all information except domain is printed
    ShortFormat, ///< only message level is printed
    DebugFormat, ///< message time (microsecond precision) and time difference
                 ///< from previous message are printed. This format is mostly
                 ///< meant for profiling.
    EmptyFormat  ///< only message is printed
  };

  /// Struct to contain LogFormat, to use with operator<<(std::ostream&, const LoggerFormat&)
  struct LoggerFormat {
    /// Make a new LoggerFormat with the given LogFormat.
    LoggerFormat(LogFormat format)
      : format(format) {};
    LogFormat format;
  };

  /// Allows printing of messages to streams using ARC Logger formatting.
  std::ostream& operator<<(std::ostream& os, const LoggerFormat& format);

  /// Printing of LogLevel values to ostreams.
  /** Output operator so that LogLevel values can be printed in a
     nicer way.
   */
  std::ostream& operator<<(std::ostream& os, LogLevel level);
  /// Convert string to a LogLevel.
  LogLevel string_to_level(const std::string& str);
  /// Case-insensitive parsing of a string to a LogLevel with error response.
  /**
   * The method will try to parse (case-insensitive) the argument string
   * to a corresponding LogLevel. If the method succeeds, true will
   * be returned and the argument \a ll will be set to
   * the parsed LogLevel. If the parsing fails \c false will be
   * returned. The parsing succeeds if \a llStr match
   * (case-insensitively) one of the names of the LogLevel members.
   *
   * @param llStr a string which should be parsed to a Arc::LogLevel.
   * @param ll a Arc::LogLevel reference which will be set to the
   *        matching Arc::LogLevel upon successful parsing.
   * @return \c true in case of successful parsing, otherwise \c false.
   * @see LogLevel
   */
  bool istring_to_level(const std::string& llStr, LogLevel& ll);
  /// Same as istring_to_level except it is case-sensitive.
  bool string_to_level(const std::string& str, LogLevel& ll);
  /// Convert LogLevel to a string.
  std::string level_to_string(const LogLevel& level);
  /// Convert an old-style log level (int from 0 to 5) to a LogLevel.
  LogLevel old_level_to_level(unsigned int old_level);



  /// A class for log messages.
  /** This class is used to represent log messages internally. It
     contains the time the message was created, its level, from which
     domain it was sent, an identifier and the message text itself.
     \headerfile Logger.h arc/Logger.h
   */
  class LogMessage {
  public:

    /// Creates a LogMessage with the specified level and message text.
    /** This constructor creates a LogMessage with the specified level
       and message text. The time is set automatically, the domain is
       set by the Logger to which the LogMessage is sent and the
       identifier is composed from the process ID and the address of
       the Thread object corresponding to the calling thread.
       @param level The level of the LogMessage.
       @param message The message text.
     */
    LogMessage(LogLevel level,
               const IString& message);

    /// Creates a LogMessage with the specified attributes.
    /** This constructor creates a LogMessage with the specified
       level, message text and identifier. The time is set
       automatically and the domain is set by the Logger to which the
       LogMessage is sent.
       @param level The level of the LogMessage.
       @param message The message text.
       @param identifier The identifier of the LogMessage.
     */
    LogMessage(LogLevel level,
               const IString& message,
               const std::string& identifier);

    /// Returns the level of the LogMessage.
    /** Returns the level of the LogMessage.
       @return The level of the LogMessage.
     */
    LogLevel getLevel() const;

  protected:

    /// Sets the identifier of the LogMessage.
    /** The purpose of this method is to allow subclasses (in case
       there are any) to set the identifier of a LogMessage.
       @param identifier The identifier.
     */
    void setIdentifier(std::string identifier);

  private:

    /// Composes a default identifier.
    /** This method composes a default identifier by combining the the
       process ID and the address of the Thread object corresponding to
       the calling thread.
       @return A default identifier.
     */
    static std::string getDefaultIdentifier();

    /// Sets the domain of the LogMessage
    /** This method sets the domain (origin) of the LogMessage. It is
       called by the Logger to which the LogMessage is sent.
       @param domain The domain.
     */
    void setDomain(std::string domain);

    /// The time when the LogMessage was created.
    std::string time;

    /// The level (severity) of the LogMessage.
    LogLevel level;

    /// The domain (origin) of the LogMessage.
    std::string domain;

    /// An identifier that may be used for filtering.
    std::string identifier;

    /// The message text.
    IString message;

    /// Printing of LogMessages to ostreams.
    /** Output operator so that LogMessages can be printed
       conveniently by LogDestinations.
     */
    friend std::ostream& operator<<(std::ostream& os,
                                    const LogMessage& message);

    /// The Logger class is a friend.
    /** The Logger class must have some privileges (e.g. ability to
       call the setDomain() method), therefore it is a friend.
     */
    friend class Logger;

  };



  /// A base class for log destinations.
  /** This class defines an interface for LogDestinations.
     LogDestination objects will typically contain synchronization
     mechanisms and should therefore never be copied. If setlocale()
     has been called with a supported locale, log messages will be
     logged in that locale.
     \headerfile Logger.h arc/Logger.h
   */
  class LogDestination {
  public:

    /// Logs a LogMessage to this LogDestination.
    virtual void log(const LogMessage& message) = 0;

    virtual ~LogDestination() {}

    /// Set format for this log destination.
    void setFormat(const LogFormat& newformat);

    /// Set a prefix for this log destination to be logged before messages.
    /** The prefix is prepended to messages in all formats except EmptyFormat.
     */
    void setPrefix(const std::string& prefix);

  protected:

    /// Default constructor. Protected since subclasses should be used instead.
    LogDestination();

  private:

    /// Private copy constructor
    /** LogDestinations should never be copied, therefore the copy
       constructor is private.
     */
    LogDestination(const LogDestination& unique);

    /// Private assignment operator
    /** LogDestinations should never be assigned, therefore the
       assignment operator is private.
     */
    void operator=(const LogDestination& unique);

    /// Sets iword and pword for format and prefix
    friend std::ostream& operator<<(std::ostream& os, const LogDestination& dest);

  protected:
    /// Format to use in this LogDestination.
    LogFormat format;

    /// Prefix to use in this log destination.
    std::string prefix;
  };



  /// A class for logging to ostreams.
  /** This class is used for logging to ostreams (cout, cerr, files).
     It provides synchronization in order to prevent different
     LogMessages to appear mixed with each other in the stream. In
     order not to break the synchronization, LogStreams should never be
     copied. Therefore the copy constructor and assignment operator are
     private. Furthermore, it is important to keep a LogStream object
     as long as the Logger to which it has been registered.
     \headerfile Logger.h arc/Logger.h
   */
  class LogStream
    : public LogDestination {
  public:

    /// Creates a LogStream connected to an ostream.
    /** Creates a LogStream connected to the specified ostream. In
       order not to break synchronization, it is important not to
       connect more than one LogStream object to a certain stream.
       @param destination The ostream to which to write LogMessages.
     */
    LogStream(std::ostream& destination);

    /// Writes a LogMessage to the stream.
    /** This method writes a LogMessage to the ostream that is
       connected to this LogStream object. It is synchronized so that
       not more than one LogMessage can be written at a time.
       @param message The LogMessage to write.
     */
    virtual void log(const LogMessage& message);

  private:

    /// Private copy constructor
    /** LogStreams should never be copied, therefore the copy
       constructor is private.
     */
    LogStream(const LogStream& unique);

    /// Private assignment operator
    /** LogStreams should never be assigned, therefore the assignment
       operator is private.
     */
    void operator=(const LogStream& unique);

    /// The ostream to which to write LogMessages
    /** This is the ostream to which LogMessages sent to this
       LogStream will be written.
     */
    std::ostream& destination;

    /// A mutex for synchronization.
    /** This mutex is locked before a LogMessage is written and it is
       not unlocked until the entire message has been written and the
       stream flushed. This is done in order to prevent LogMessages to
       appear mixed in the stream.
     */
    Glib::Mutex mutex;

  };

  /// A class for logging to files.
  /** This class is used for logging to files.
     It provides synchronization in order to prevent different
     LogMessages to appear mixed with each other in the stream.
     It is possible to limit size of created file. Whenever
     specified size is exceeded file is deleted and new one is
     created. Old files may be moved into backup files instead of
     being deleted. Those files have names same as initial file with
     additional number suffix - similar to those found in /var/log
     of many Unix-like systems.
     \headerfile Logger.h arc/Logger.h
   */
  class LogFile
    : public LogDestination {
  public:

    /// Creates a LogFile connected to a file.
    /** Creates a LogFile connected to the file located at
       specified path. In order not to break synchronization,
       it is important not to connect more than one LogFile object
       to a certain file. If file does not exist it will be created.
       @param path The path to file to which to write LogMessages.
     */
    LogFile(const std::string& path);

    /// Set maximal allowed size of file.
    /** Set maximal allowed size of file. This value is not
       obeyed exactly. Specified size may be exceeded by amount
       of one LogMessage. To disable limit specify -1.
       @param newsize Max size of log file.
     */
    void setMaxSize(int newsize);

    /// Set number of backups to store.
    /** Set number of backups to store. When file size exceeds one
       specified with setMaxSize() file is closed and moved to one
       named path.1. If path.1 exists it is moved to path.2 and so
       on. Number of path.# files is one set in newbackup.
       @param newbackup Number of backup files.
     */
    void setBackups(int newbackup);

    /// Set file reopen on every write.
    /** Set file reopen on every write. If set to true file is opened
       before writing every log record and closed afterward.
       @param newreopen If file to be reopened for every log record.
     */
    void setReopen(bool newreopen);

    /// Returns true if this instance is valid.
    operator bool(void);

    /// Returns true if this instance is invalid.
    bool operator!(void);

    /// Writes a LogMessage to the file.
    /** This method writes a LogMessage to the file that is
       connected to this LogFile object. If after writing
       size of file exceeds one set by setMaxSize() file is moved
       to backup and new one is created.
       @param message The LogMessage to write.
     */
    virtual void log(const LogMessage& message);
  private:
    LogFile(void);
    LogFile(const LogFile& unique);
    void operator=(const LogFile& unique);
    void backup(void);
    std::string path;
    std::ofstream destination;
    int maxsize;
    int backups;
    bool reopen;
    Glib::Mutex mutex;
  };

  class LoggerContextRef;

  /** \cond Container for internal logger configuration.
     \headerfile Logger.h arc/Logger.h */
  class LoggerContext {
    friend class Logger;
    friend class LoggerContextRef;
    private:
      /// This counts how many threads are using this object.
      int usage_count;

      /// Protection for usage_count.
      Glib::Mutex mutex;

      /// A list of pointers to LogDestinations.
      std::list<LogDestination*> destinations;

      /// The threshold of Logger.
      LogLevel threshold;

      LoggerContext(LogLevel thr):usage_count(0),threshold(thr) { };

      LoggerContext(const LoggerContext& ctx):
             usage_count(0),destinations(ctx.destinations),threshold(ctx.threshold) { };

      ~LoggerContext(void);

      void Acquire(void);

      void Release(void);
  };
  /** \endcond */
 

  /// A logger class.
  /** This class defines a Logger to which LogMessages can be sent.

     Every Logger (except for the rootLogger) has a parent Logger. The
     domain of a Logger (a string that indicates the origin of
     LogMessages) is composed by adding a subdomain to the domain of
     its parent Logger.

     A Logger also has a threshold. Every LogMessage that have a level
     that is greater than or equal to the threshold is forwarded to any
     LogDestination connected to this Logger as well as to the parent
     Logger.

     Typical usage of the Logger class is to declare a global Logger
     object for each library/module/component to be used by all classes
     and methods there.

     Logger messages may be localised according to the current locale. Some
     locales are better supported than others.

     Example code for setting up logger in main():
     @code
  // Set up stderr as a log stream
  Arc::LogStream logcerr(std::cerr);
  // Log message is prefixed by level only
  logcerr.setFormat(Arc::ShortFormat);
  // Add the stderr destination to the root logger
  Arc::Logger::getRootLogger().addDestination(logcerr);
  // Set the logging threshold to WARNING
  Arc::Logger::getRootLogger().setThreshold(Arc::WARNING);

  // Logger to use in main() - it inherits all properties from the root Logger
  Arc::Logger logger(Arc::Logger::getRootLogger(), "main");
  // this message will not be logged since it is below the threshold
  logger.msg(Arc::INFO, "main started");
  int i = 5;
  // This message will be logged
  logger.msg(Arc::ERROR, "Oops, an error occurred when i was %i", i);
     @endcode
   */
  class Logger {
  public:

    /// The root Logger.
    /** This is the root Logger. It is an ancestor of any other Logger
       and always exists.
     */
    //static Logger rootLogger;
    static Logger& getRootLogger();

    /// Creates a logger.
    /** The threshold is inherited from its parent Logger.
       @param parent The parent Logger of the new Logger.
       @param subdomain The subdomain of the new logger.
     */
    Logger(Logger& parent,
           const std::string& subdomain);

    /// Creates a logger.
    /** @param parent The parent Logger of the new Logger.
       @param subdomain The subdomain of the new logger.
       @param threshold The threshold of the new logger.
     */
    Logger(Logger& parent,
           const std::string& subdomain,
           LogLevel threshold);

    /// Destroys a logger.
    ~Logger();

    /// Adds a LogDestination.
    /** Adds a LogDestination to which to forward LogMessages sent to
       this logger (if they pass the threshold). Since LogDestinations
       should not be copied, the new LogDestination is passed by
       reference and a pointer to it is kept for later use. It is
       therefore important that the LogDestination passed to this
       Logger exists at least as long as the Logger itself.
     */
    void addDestination(LogDestination& destination);

    /// Adds LogDestinations.
    /** See addDestination(LogDestination& destination).
     */
    void addDestinations(const std::list<LogDestination*>& destinations);

    /// Set LogDestinations.
    /** A safe atomic way to remove and add LogDestinations.
     */
    void setDestinations(const std::list<LogDestination*>& destinations);

    /// Obtains current LogDestinations.
    /** Returns list of pointers to LogDestination objects. Returned result
       refers directly to internal member of Logger instance. Hence it
       should not be used after this Logger is destroyed.
     */
    const std::list<LogDestination*>& getDestinations(void) const;

    /// Removes all LogDestinations.
    void removeDestinations(void);

    /// Remove all LogDestinations and delete LogDestination objects.
    void deleteDestinations(void);

    /// Sets the logging threshold.
    /** This method sets the threshold of the Logger. Any message sent
       to this Logger that has a level below this threshold will be
       discarded.
       @param threshold The threshold
     */
    void setThreshold(LogLevel threshold);

    /// Sets the threshold for domain.
    /** This method sets the default threshold of the domain. All new loggers
       created with specified domain will have specified threshold set by default.
       The subdomains of all loggers in chain are matched against list of provided
       subdomains.
       @param threshold The threshold
       @param subdomains The subdomains of all loggers in chain
     */
    static void setThresholdForDomain(LogLevel threshold,
                                      const std::list<std::string>& subdomains);

    /// Sets the threshold for domain.
    /** This method sets the default threshold of the domain. All new loggers
       created with specified domain will have specified threshold set by default.
       The domain is composed of all subdomains of all loggers in chain by merging
       them with '.' as separator.
       @param threshold The threshold
       @param domain The domain of logger
     */
    static void setThresholdForDomain(LogLevel threshold,
                                      const std::string& domain);

    /// Returns the threshold of this logger.
    LogLevel getThreshold() const;

    /// Creates per-thread context.
    /** Creates new context for this logger which becomes effective
       for operations initiated by this thread. All new threads 
       started by this one will inherit new context. Context
       stores current threshold and pointers to destinations.
       Hence new context is identical to current one. One can 
       modify new context using setThreshold(), removeDestinations()
       and addDestination(). All such operations will not affect
       old context.
     */
    void setThreadContext(void);

    /// Sends a LogMessage.
    /** @param message The LogMessage to send.
     */
    void msg(LogMessage message);

    /// Logs a message text.
    /** Logs a message text string at the specified LogLevel. This is
       a convenience method to save some typing. It simply creates a
       LogMessage and sends it to the other msg() methods. It is also possible
       to use msg() with multiple arguments and printf-style string formatting,
       for example
       @code
       logger.msg(INFO, "Operation no %i failed: %s", number, reason);
       @endcode
       @param level The level of the message.
       @param str The message text.
     */
    void msg(LogLevel level, const std::string& str) {
      msg(LogMessage(level, IString(str)));
    }

    template<class T0>
    void msg(LogLevel level, const std::string& str,
             const T0& t0) {
      msg(LogMessage(level, IString(str, t0)));
    }

    template<class T0, class T1>
    void msg(LogLevel level, const std::string& str,
             const T0& t0, const T1& t1) {
      msg(LogMessage(level, IString(str, t0, t1)));
    }

    template<class T0, class T1, class T2>
    void msg(LogLevel level, const std::string& str,
             const T0& t0, const T1& t1, const T2& t2) {
      msg(LogMessage(level, IString(str, t0, t1, t2)));
    }

    template<class T0, class T1, class T2, class T3>
    void msg(LogLevel level, const std::string& str,
             const T0& t0, const T1& t1, const T2& t2, const T3& t3) {
      msg(LogMessage(level, IString(str, t0, t1, t2, t3)));
    }

    template<class T0, class T1, class T2, class T3, class T4>
    void msg(LogLevel level, const std::string& str,
             const T0& t0, const T1& t1, const T2& t2, const T3& t3,
             const T4& t4) {
      msg(LogMessage(level, IString(str, t0, t1, t2, t3, t4)));
    }

    template<class T0, class T1, class T2, class T3, class T4,
             class T5>
    void msg(LogLevel level, const std::string& str,
             const T0& t0, const T1& t1, const T2& t2, const T3& t3,
             const T4& t4, const T5& t5) {
      msg(LogMessage(level, IString(str, t0, t1, t2, t3, t4, t5)));
    }

    template<class T0, class T1, class T2, class T3, class T4,
             class T5, class T6>
    void msg(LogLevel level, const std::string& str,
             const T0& t0, const T1& t1, const T2& t2, const T3& t3,
             const T4& t4, const T5& t5, const T6& t6) {
      msg(LogMessage(level, IString(str, t0, t1, t2, t3, t4, t5, t6)));
    }

    template<class T0, class T1, class T2, class T3, class T4,
             class T5, class T6, class T7>
    void msg(LogLevel level, const std::string& str,
             const T0& t0, const T1& t1, const T2& t2, const T3& t3,
             const T4& t4, const T5& t5, const T6& t6, const T7& t7) {
      msg(LogMessage(level, IString(str, t0, t1, t2, t3, t4, t5, t6, t7)));
    }

  private:

    /// A private constructor.
    /** Every Logger (except the root logger) must have a parent,
       therefore the default constructor (which does not specify a
       parent) is private to prevent accidental use. It is only used
       when creating the root logger.
     */
    Logger();

    /// Private copy constructor
    /** Loggers should never be copied, therefore the copy constructor
       is private.
     */
    Logger(const Logger& unique);

    /// Private assignment operator
    /** Loggers should never be assigned, therefore the assignment
       operator is private.
     */
    void operator=(const Logger& unique);

    /// Returns the domain.
    /** This method returns the domain of this logger, i.e. the string
       that is attached to all LogMessages sent from this logger to
       indicate their origin.
     */
    std::string getDomain();

    /// Forwards a log message.
    /** This method is called by the msg() method and by child
       Loggers. It filters messages based on their level and forwards
       them to the parent Logger and any LogDestination that has been
       added to this Logger.
       @param message The message to send.
     */
    void log(const LogMessage& message);

    /// A pointer to the parent of this logger.
    Logger *parent;

    /// The domain of this logger.
    std::string domain;

    /// Per-trhread storage id for context;
    std::string context_id;

    LoggerContext context;

    LoggerContext& getContext(void);

    Glib::Mutex mutex;

#define rootLoggerMagic (0xF6569201)
    static Logger *rootLogger;
    static std::map<std::string,LogLevel>* defaultThresholds;
    static unsigned int rootLoggerMark;
  };

  /** @} */

} // namespace Arc

#define rootLogger getRootLogger()

#define LOG(LGR, THR, FSTR, ...) { if ((LGR).getThreshold() >= (THR)(LGR).msg((THR), (FSTR), ...); }

#endif // __ARC_LOGGER__