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
|
// 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/.
#include <config.h>
#include <log/message_dictionary.h>
#include <log/message_initializer.h>
#include <algorithm>
#include <cassert>
#include <cstdlib>
namespace {
using namespace isc::log;
/// @brief Returns the shared pointer to the list of pointers to the
/// log messages defined.
///
/// The returned pointer must be held in the \c MessageInitializer object
/// throughout its lifetime to make sure that the object doesn't outlive
/// the list and may still access it in the destructor. The returned
/// pointer is shared between all \c MessageInitializer instances.
LoggerValuesListPtr
getNonConstLoggerValues() {
static LoggerValuesListPtr logger_values(new LoggerValuesList());
return (logger_values);
}
/// @brief Returns the pointer to the list of message duplicates.
///
/// The returned pointer must be held in the \c MessageInitializer object
/// throughout its lifetime to make sure that the object doesn't outlive
/// the list and may still access it in the destructor. The returned
/// pointer is shared between all \c MessageInitializer instances.
LoggerDuplicatesListPtr
getNonConstDuplicates() {
static LoggerDuplicatesListPtr duplicates(new LoggerDuplicatesList());
return (duplicates);
}
} // end unnamed namespace
namespace isc {
namespace log {
MessageInitializer::MessageInitializer(const char* values[])
: values_(values),
global_dictionary_(MessageDictionary::globalDictionary()),
global_logger_values_(getNonConstLoggerValues()),
global_logger_duplicates_(getNonConstDuplicates()) {
global_logger_values_->push_back(values);
}
MessageInitializer::~MessageInitializer() {
// Search for the pointer to pending messages belonging to our instance.
LoggerValuesList::iterator my_messages = std::find(global_logger_values_->begin(),
global_logger_values_->end(),
values_);
bool pending = (my_messages != global_logger_values_->end());
// Our messages are still pending, so let's remove them from the list
// of pending messages.
if (pending) {
global_logger_values_->erase(my_messages);
} else {
// Our messages are not pending, so they might have been loaded to
// the dictionary and/or duplicates.
int i = 0;
while (values_[i]) {
// Check if the unloaded message is registered as duplicate. If it is,
// remove it from the duplicates list.
LoggerDuplicatesList::iterator dup =
std::find(global_logger_duplicates_->begin(),
global_logger_duplicates_->end(),
values_[i]);
if (dup != global_logger_duplicates_->end()) {
global_logger_duplicates_->erase(dup);
} else {
global_dictionary_->erase(values_[i], values_[i + 1]);
}
i += 2;
}
}
}
// Return the number of arrays registered but not yet loaded.
size_t
MessageInitializer::getPendingCount() {
return (getNonConstLoggerValues()->size());
}
// Load the messages in the arrays registered in the logger_values array
// into the global dictionary.
void
MessageInitializer::loadDictionary(bool ignore_duplicates) {
const MessageDictionaryPtr& global = MessageDictionary::globalDictionary();
const LoggerValuesListPtr& logger_values = getNonConstLoggerValues();
for (auto const& values : *logger_values) {
std::vector<std::string> repeats = global->load(values);
// Append the IDs in the list just loaded (the "repeats") to the
// global list of duplicate IDs.
if (!ignore_duplicates && !repeats.empty()) {
const LoggerDuplicatesListPtr& duplicates = getNonConstDuplicates();
duplicates->insert(duplicates->end(), repeats.begin(), repeats.end());
}
}
// ... and mark that the messages have been loaded. (This avoids a lot
// of "duplicate message ID" messages in some of the unit tests where the
// logging initialization code may be called multiple times.)
logger_values->clear();
}
// Return reference to duplicates vector
const std::list<std::string>&
MessageInitializer::getDuplicates() {
return (*getNonConstDuplicates());
}
// Clear the duplicates vector
void
MessageInitializer::clearDuplicates() {
getNonConstDuplicates()->clear();
}
} // namespace log
} // namespace isc
|