// 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 #include #include #include #include #include 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 (LoggerValuesList::const_iterator values = logger_values->begin(); values != logger_values->end(); ++values) { std::vector 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& MessageInitializer::getDuplicates() { return (*getNonConstDuplicates()); } // Clear the duplicates vector void MessageInitializer::clearDuplicates() { getNonConstDuplicates()->clear(); } } // namespace log } // namespace isc