core: Make logger thread-safe

Change-Id: Ic45dc0912da9c2e3f074d3f74921bfe33741bf63
Refs: #2489
diff --git a/core/logger-factory.cpp b/core/logger-factory.cpp
index 483387f..20578c3 100644
--- a/core/logger-factory.cpp
+++ b/core/logger-factory.cpp
@@ -25,6 +25,8 @@
 
 #include "logger-factory.hpp"
 
+#include <boost/range/adaptor/map.hpp>
+
 #ifdef HAVE_CUSTOM_LOGGER
 #error "This file should not be compiled when custom logger is used"
 #endif
@@ -70,44 +72,37 @@
   // std::cerr << m_levelNames.begin()->first << std::endl;
 
   LevelMap::const_iterator levelIt = m_levelNames.find(upperLevel);
-  if (levelIt != m_levelNames.end())
-    {
-      return levelIt->second;
-    }
-  try
-    {
-      uint32_t levelNo = boost::lexical_cast<uint32_t>(level);
+  if (levelIt != m_levelNames.end()) {
+    return levelIt->second;
+  }
+  try {
+    uint32_t levelNo = boost::lexical_cast<uint32_t>(level);
 
-      if ((boost::lexical_cast<uint32_t>(LOG_NONE) <= levelNo &&
-           levelNo <= boost::lexical_cast<uint32_t>(LOG_TRACE)) ||
-          levelNo == LOG_ALL)
-        {
-          return static_cast<LogLevel>(levelNo);
-        }
+    if ((boost::lexical_cast<uint32_t>(LOG_NONE) <= levelNo &&
+         levelNo <= boost::lexical_cast<uint32_t>(LOG_TRACE)) ||
+        levelNo == LOG_ALL) {
+      return static_cast<LogLevel>(levelNo);
     }
-  catch (const boost::bad_lexical_cast& error)
-    {
-    }
-  throw LoggerFactory::Error("Unsupported logging level \"" +
-                             level + "\"");
+  }
+  catch (const boost::bad_lexical_cast& error) {
+  }
+
+  throw LoggerFactory::Error("Unsupported logging level \"" + level + "\"");
 }
 
 LogLevel
 LoggerFactory::extractLevel(const ConfigSection& item, const std::string& key)
 {
   std::string levelString;
-  try
-    {
-      levelString = item.get_value<std::string>();
-    }
-  catch (const boost::property_tree::ptree_error& error)
-    {
-    }
+  try {
+    levelString = item.get_value<std::string>();
+  }
+  catch (const boost::property_tree::ptree_error& error) {
+  }
 
-  if (levelString.empty())
-    {
-      throw LoggerFactory::Error("No logging level found for option \"" + key + "\"");
-    }
+  if (levelString.empty()) {
+    throw LoggerFactory::Error("No logging level found for option \"" + key + "\"");
+  }
 
   return parseLevel(levelString);
 }
@@ -131,58 +126,51 @@
 //   Forwarder WARN
 // }
 
-  if (!isDryRun)
-    {
-      ConfigSection::const_assoc_iterator item = section.find("default_level");
-      if (item != section.not_found())
-        {
-          LogLevel level = extractLevel(item->second, "default_level");
-          setDefaultLevel(level);
-        }
-      else
-        {
-          setDefaultLevel(LOG_INFO);
-        }
+  if (!isDryRun) {
+    ConfigSection::const_assoc_iterator item = section.find("default_level");
+    if (item != section.not_found()) {
+      LogLevel level = extractLevel(item->second, "default_level");
+      setDefaultLevel(level);
     }
-
-  for (ConfigSection::const_iterator item = section.begin();
-       item != section.end();
-       ++item)
-    {
-      LogLevel level = extractLevel(item->second, item->first);
-
-      if (item->first == "default_level")
-        {
-          // do nothing
-        }
-      else
-        {
-          LoggerMap::iterator loggerIt = m_loggers.find(item->first);
-          if (loggerIt == m_loggers.end())
-            {
-              NFD_LOG_DEBUG("Failed to configure logging level for module \"" <<
-                            item->first << "\" (module not found)");
-            }
-          else if (!isDryRun)
-            {
-              // std::cerr << "changing level for module " << item->first << " to " << level << std::endl;
-              loggerIt->second.setLogLevel(level);
-            }
-        }
+    else {
+      setDefaultLevel(LOG_INFO);
     }
+  }
+
+  for (const auto& i : section) {
+    LogLevel level = extractLevel(i.second, i.first);
+
+    if (i.first == "default_level") {
+      // do nothing
+    }
+    else {
+      std::unique_lock<std::mutex> lock(m_loggersGuard);
+      LoggerMap::iterator loggerIt = m_loggers.find(i.first);
+      if (loggerIt == m_loggers.end()) {
+        lock.unlock();
+        NFD_LOG_DEBUG("Failed to configure logging level for module \"" <<
+                      i.first << "\" (module not found)");
+      }
+      else if (!isDryRun) {
+        loggerIt->second.setLogLevel(level);
+        lock.unlock();
+        NFD_LOG_DEBUG("Changing level for module " << i.first << " to " << level);
+      }
+    }
+  }
 }
 
 void
 LoggerFactory::setDefaultLevel(LogLevel level)
 {
   // std::cerr << "changing to default_level " << level << std::endl;
+  std::lock_guard<std::mutex> lock(m_loggersGuard);
 
   m_defaultLevel = level;
-  for (LoggerMap::iterator i = m_loggers.begin(); i != m_loggers.end(); ++i)
-    {
-      // std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
-      i->second.setLogLevel(m_defaultLevel);
-    }
+  for (auto&& logger : m_loggers) {
+    // std::cerr << "changing " << i->first << " to default " << m_defaultLevel << std::endl;
+    logger.second.setLogLevel(m_defaultLevel);
+  }
 }
 
 Logger&
@@ -197,6 +185,8 @@
   // std::cerr << "creating logger for " << moduleName
   //           << " with level " << m_defaultLevel << std::endl;
 
+  std::lock_guard<std::mutex> lock(m_loggersGuard);
+
   std::pair<LoggerMap::iterator, bool> loggerIt =
     m_loggers.insert(NameAndLogger(moduleName, Logger(moduleName, m_defaultLevel)));
 
@@ -206,11 +196,12 @@
 std::list<std::string>
 LoggerFactory::getModules() const
 {
+  std::lock_guard<std::mutex> lock(m_loggersGuard);
+
   std::list<std::string> modules;
-  for (LoggerMap::const_iterator i = m_loggers.begin(); i != m_loggers.end(); ++i)
-    {
-      modules.push_back(i->first);
-    }
+  for (const auto& loggerName : m_loggers | boost::adaptors::map_keys) {
+    modules.push_back(loggerName);
+  }
 
   return modules;
 }