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
|
// Copyright (C) 2011,2015 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef MESSAGEINITIALIZER_H
#define MESSAGEINITIALIZER_H
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <cstdlib>
#include <list>
#include <string>
namespace isc {
namespace log {
// Declare the MessageDictionary class to allow a pointer to it to be defined.
class MessageDictionary;
/// @name Type definitions for containers shared among instances of the class.
///
//\{
/// \brief List of pointers to the messages.
typedef std::list<const char**> LoggerValuesList;
/// \brief Shared pointer to the list of pointers to the messages.
typedef boost::shared_ptr<LoggerValuesList> LoggerValuesListPtr;
/// \brief List of duplicated messages.
typedef std::list<std::string> LoggerDuplicatesList;
/// \brief Shared pointer to the list of duplicated messages.
typedef boost::shared_ptr<LoggerDuplicatesList> LoggerDuplicatesListPtr;
//\}
/// \brief Initialize Message Dictionary
///
/// This is a helper class to add a set of message IDs and associated text to
/// the global dictionary.
///
/// It should be declared outside an execution unit and initialized with a
/// an array of values, alternating identifier, associated text and ending with
/// a NULL, e.g.
///
/// static const char* values[] = {
/// "IDENT1", "message for ident 1",
/// "IDENT2", "message for ident 2",
/// :
/// NULL
/// };
/// MessageInitializer xyz(values);
///
/// All that needed is for the module containing the definitions to be
/// included in the execution unit.
///
/// Dynamically loaded modules should call the initializer as well on the
/// moment they are instantiated.
///
/// To avoid static initialization fiasco problems, the containers shared by
/// all instances of this class are dynamically allocated on first use, and
/// held in the smart pointers which are de-allocated only when all instances
/// of the class are destructred. After the object has been created with the
/// constructor, the \c MessageInitializer::loadDictionary static function is
/// called to populate the messages defined in various instances of the
/// \c MessageInitializer class to the global dictionary.
///
/// When messages are added to the dictionary, the are added via the
/// MessageDictionary::add() method, so any duplicates are stored in the
/// global dictionary's overflow lince whence they can be retrieved at
/// run-time.
class MessageInitializer : public boost::noncopyable {
public:
/// \brief Constructor
///
/// Adds a pointer to the array of messages to the global array of
/// pointers to message arrays.
///
/// \param values NULL-terminated array of alternating identifier strings
/// and associated message text. N.B. This object stores a pointer to the
/// passed array; the array MUST remain valid at least until
/// loadDictionary() has been called.
MessageInitializer(const char* values[]);
/// \brief Destructor
///
/// Removes pending messages from the array or loaded messages from the
/// global dictionary.
///
/// If the messages initialized with the destructed have already been
/// loaded to the global dictionary the destructor will remove these
/// messages and preserve messages loaded by other instances of the
/// \c MessageInitializer. If there are any duplicates, only the instance
/// of the duplicated message initialized by the destructed object will
/// be removed.
~MessageInitializer();
/// \brief Obtain pending load count
///
/// Returns the number of message arrays that will be loaded by the next
/// call to loadDictionary().
///
/// \return Number of registered message arrays. This is reset to zero
/// when loadDictionary() is called.
static size_t getPendingCount();
/// \brief Run-Time Initialization
///
/// Loops through the internal array of pointers to message arrays
/// and adds the messages to the internal dictionary. This is called
/// during run-time initialization.
///
/// \param ignore_duplicates If true, duplicate IDs, and IDs already
/// loaded, are ignored instead of stored in the global duplicates
/// list.
static void loadDictionary(bool ignore_duplicates = false);
/// \brief Return Duplicates
///
/// When messages are added to the global dictionary, any duplicates are
/// recorded. They can later be output through the logging system.
///
/// \return List of duplicate message IDs when the global dictionary was
/// loaded. Note that the duplicates list itself may contain duplicates.
static const std::list<std::string>& getDuplicates();
/// \brief Clear the static duplicates list
///
/// Empties the list returned by getDuplicates()
static void clearDuplicates();
private:
/// \brief Holds the pointer to the array of messages.
const char** values_;
/// \brief Holds the pointer to the global dictionary.
///
/// One or more instances of \c MessageInitalizer are created statically,
/// the \c MessageDictionary being created by the first one to run. As the
/// \c MessageDictionary is also accessed by the \c MessageInitializer
/// destructor, a smart pointer to it is kept. This avoids the possibility
/// that, during shutdown, the \c MessageDictionary is destroyed before all
/// instances of \c MessageInitializer.
boost::shared_ptr<MessageDictionary> global_dictionary_;
/// \brief Holds the shared pointer to the list of pointers to the
/// log messages defined by various instances of this class.
///
/// This pointer must be initialized in the constructor and held
/// throughout the lifetime of the \c MessageInitializer object. This
/// prevents static deinitialization fiasco when trying to access the
/// values in the list from the destructor of this class.
LoggerValuesListPtr global_logger_values_;
/// \brief Holds the shared pointer to the collection od duplicated
/// messages.
///
/// This pointer must be initialized in the constructor and held
/// throughout the lifetime of the \c MessageInitializer object. This
/// prevents static deinitialization fiasco when trying to access the
/// values in the list from the destructor of this class.
LoggerDuplicatesListPtr global_logger_duplicates_;
};
} // namespace log
} // namespace isc
#endif // MESSAGEINITIALIZER_H
|