[ndnSIM] util: Redirect logger to use the logging facility of NS3

Change-Id: Ib345978575104afa436296d2f5a824a39e3a9721
diff --git a/src/util/logger.cpp b/src/util/logger.cpp
index 64cb5a2..e4b3b41 100644
--- a/src/util/logger.cpp
+++ b/src/util/logger.cpp
@@ -21,7 +21,6 @@
 
 #include "logger.hpp"
 
-#include "logging.hpp"
 #include "time.hpp"
 
 #include <cinttypes>
@@ -102,34 +101,6 @@
 Logger::Logger(const std::string& name)
   : m_moduleName(name)
 {
-  if (!isValidLoggerName(name)) {
-    BOOST_THROW_EXCEPTION(std::invalid_argument("Logger name " + name + " is invalid"));
-  }
-  this->setLevel(LogLevel::NONE);
-  Logging::addLogger(*this);
-}
-
-std::ostream&
-operator<<(std::ostream& os, const LoggerTimestamp&)
-{
-  using namespace ndn::time;
-
-  static const microseconds::rep ONE_SECOND = 1000000;
-  microseconds::rep usecs = duration_cast<microseconds>(
-                            system_clock::now().time_since_epoch()).count();
-
-  // 10 (whole seconds) + '.' + 6 (fraction) + '\0'
-  char buffer[10 + 1 + 6 + 1];
-  BOOST_ASSERT_MSG(usecs / ONE_SECOND <= 9999999999L,
-                   "whole seconds cannot fit in 10 characters");
-
-  static_assert(std::is_same<microseconds::rep, int_least64_t>::value,
-                "PRIdLEAST64 is incompatible with microseconds::rep");
-  // std::snprintf unavailable in some environments <https://redmine.named-data.net/issues/2299>
-  snprintf(buffer, sizeof(buffer), "%" PRIdLEAST64 ".%06" PRIdLEAST64,
-           usecs / ONE_SECOND, usecs % ONE_SECOND);
-
-  return os << buffer;
 }
 
 } // namespace util
diff --git a/src/util/logger.hpp b/src/util/logger.hpp
index 548390b..e406ef6 100644
--- a/src/util/logger.hpp
+++ b/src/util/logger.hpp
@@ -28,10 +28,10 @@
 #include "ndn-cxx-custom-logger.hpp"
 #else
 
-#include <boost/log/common.hpp>
-#include <boost/log/sources/logger.hpp>
 #include <atomic>
 
+#include "ns3/log.h"
+
 namespace ndn {
 namespace util {
 
@@ -63,7 +63,7 @@
 /** \brief represents a logger in logging facility
  *  \note User should declare a new logger with \p NDN_LOG_INIT macro.
  */
-class Logger : public boost::log::sources::logger_mt
+class Logger
 {
 public:
   explicit
@@ -98,15 +98,7 @@
  *  symbols: `~`, `#`, `%`, `_`, `<`, `>`, `.`, `-`
  *  A logger name must not start or end with `.` or contain consecutive `.`
  */
-#define NDN_LOG_INIT(name) \
-  namespace { \
-    inline ::ndn::util::Logger& getNdnCxxLogger() \
-    { \
-      static ::ndn::util::Logger logger(BOOST_STRINGIZE(name)); \
-      return logger; \
-    } \
-  } \
-  struct ndn_cxx__allow_trailing_semicolon
+#define NDN_LOG_INIT(name) NS_LOG_COMPONENT_DEFINE(BOOST_STRINGIZE(name));
 
 /** \brief a tag that writes a timestamp upon stream output
  *  \code
@@ -123,51 +115,12 @@
 std::ostream&
 operator<<(std::ostream& os, const LoggerTimestamp&);
 
-#if (BOOST_VERSION >= 105900) && (BOOST_VERSION < 106000)
-// workaround Boost bug 11549
-#define NDN_BOOST_LOG(x) BOOST_LOG(x) << ""
-#else
-#define NDN_BOOST_LOG(x) BOOST_LOG(x)
-#endif
-
-#define NDN_LOG(lvl, lvlstr, expression) \
-  do { \
-    if (getNdnCxxLogger().isLevelEnabled(::ndn::util::LogLevel::lvl)) { \
-      NDN_BOOST_LOG(getNdnCxxLogger()) << ::ndn::util::LoggerTimestamp{} \
-        << " " BOOST_STRINGIZE(lvlstr) ": [" << getNdnCxxLogger().getModuleName() << "] " \
-        << expression; \
-    } \
-  } while (false)
-
-/** \brief log at TRACE level
- *  \pre A log module must be declared in the same translation unit.
- */
-#define NDN_LOG_TRACE(expression) NDN_LOG(TRACE, TRACE, expression)
-
-/** \brief log at DEBUG level
- *  \pre A log module must be declared in the same translation unit.
- */
-#define NDN_LOG_DEBUG(expression) NDN_LOG(DEBUG, DEBUG, expression)
-
-/** \brief log at INFO level
- *  \pre A log module must be declared in the same translation unit.
- */
-#define NDN_LOG_INFO(expression) NDN_LOG(INFO, INFO, expression)
-
-/** \brief log at WARN level
- *  \pre A log module must be declared in the same translation unit.
- */
-#define NDN_LOG_WARN(expression) NDN_LOG(WARN, WARNING, expression)
-
-/** \brief log at ERROR level
- *  \pre A log module must be declared in the same translation unit.
- */
-#define NDN_LOG_ERROR(expression) NDN_LOG(ERROR, ERROR, expression)
-
-/** \brief log at FATAL level
- *  \pre A log module must be declared in the same translation unit.
- */
-#define NDN_LOG_FATAL(expression) NDN_LOG(FATAL, FATAL, expression)
+#define NDN_LOG_TRACE(expression) NS_LOG_LOGIC(expression)
+#define NDN_LOG_DEBUG(expression) NS_LOG_DEBUG(expression)
+#define NDN_LOG_INFO(expression)  NS_LOG_INFO(expression)
+#define NDN_LOG_WARN(expression)  NS_LOG_ERROR(expression)
+#define NDN_LOG_ERROR(expression) NS_LOG_WARN(expression)
+#define NDN_LOG_FATAL(expression) NS_LOG_FATAL(expression)
 
 } // namespace util
 } // namespace ndn
diff --git a/src/util/logging.cpp b/src/util/logging.cpp
deleted file mode 100644
index 21a573c..0000000
--- a/src/util/logging.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2017 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- */
-
-#include "logging.hpp"
-#include "logger.hpp"
-
-#include <boost/log/expressions.hpp>
-#include <boost/range/adaptor/map.hpp>
-#include <boost/range/algorithm/copy.hpp>
-#include <boost/range/iterator_range.hpp>
-
-#include <cstdlib>
-#include <iostream>
-#include <sstream>
-
-// suppress warning caused by <boost/log/sinks/text_ostream_backend.hpp>
-#ifdef __clang__
-#pragma clang diagnostic ignored "-Wundefined-func-template"
-#endif
-
-namespace ndn {
-namespace util {
-
-static const LogLevel INITIAL_DEFAULT_LEVEL = LogLevel::NONE;
-
-Logging&
-Logging::get()
-{
-  // Initialization of block-scope variables with static storage duration is thread-safe.
-  // See ISO C++ standard [stmt.dcl]/4
-  static Logging instance;
-  return instance;
-}
-
-Logging::Logging()
-{
-  this->setDestinationImpl(shared_ptr<std::ostream>(&std::clog, bind([]{})));
-
-  const char* environ = std::getenv("NDN_LOG");
-  if (environ != nullptr) {
-    this->setLevelImpl(environ);
-  }
-}
-
-void
-Logging::addLoggerImpl(Logger& logger)
-{
-  std::lock_guard<std::mutex> lock(m_mutex);
-
-  const std::string& moduleName = logger.getModuleName();
-  m_loggers.emplace(moduleName, &logger);
-
-  LogLevel level = findLevel(moduleName);
-  logger.setLevel(level);
-}
-
-std::set<std::string>
-Logging::getLoggerNamesImpl() const
-{
-  std::lock_guard<std::mutex> lock(m_mutex);
-
-  std::set<std::string> loggerNames;
-  boost::copy(m_loggers | boost::adaptors::map_keys, std::inserter(loggerNames, loggerNames.end()));
-  return loggerNames;
-}
-
-LogLevel
-Logging::findLevel(const std::string& moduleName) const
-{
-  std::string mn = moduleName;
-  while (!mn.empty()) {
-    auto it = m_enabledLevel.find(mn);
-    if (it != m_enabledLevel.end()) {
-      return it->second;
-    }
-    size_t pos = mn.find_last_of('.');
-    if (pos < mn.size() - 1) {
-      mn = mn.substr(0, pos + 1);
-    }
-    else if (pos == mn.size() - 1) {
-      mn.pop_back();
-      pos = mn.find_last_of('.');
-      if (pos != std::string::npos) {
-        mn = mn.substr(0, pos + 1);
-      }
-      else {
-        mn = "";
-      }
-    }
-    else {
-      mn = "";
-    }
-  }
-  auto it = m_enabledLevel.find(mn);
-  if (it != m_enabledLevel.end()) {
-    return it->second;
-  }
-  else {
-    return INITIAL_DEFAULT_LEVEL;
-  }
-}
-
-#ifdef NDN_CXX_HAVE_TESTS
-bool
-Logging::removeLogger(Logger& logger)
-{
-  const std::string& moduleName = logger.getModuleName();
-  auto range = m_loggers.equal_range(moduleName);
-  for (auto i = range.first; i != range.second; ++i) {
-    if (i->second == &logger) {
-      m_loggers.erase(i);
-      return true;
-    }
-  }
-  return false;
-}
-#endif // NDN_CXX_HAVE_TESTS
-
-void
-Logging::setLevelImpl(const std::string& prefix, LogLevel level)
-{
-  std::lock_guard<std::mutex> lock(m_mutex);
-
-  if (prefix.empty() || prefix.back() == '*') {
-    std::string p = prefix;
-    if (!p.empty()) {
-      p.pop_back();
-    }
-
-    for (auto i = m_enabledLevel.begin(); i != m_enabledLevel.end();) {
-      if (i->first.compare(0, p.size(), p) == 0) {
-        i = m_enabledLevel.erase(i);
-      }
-      else {
-        ++i;
-      }
-    }
-    m_enabledLevel[p] = level;
-
-    for (auto&& it : m_loggers) {
-      if (it.first.compare(0, p.size(), p) == 0) {
-        it.second->setLevel(level);
-      }
-    }
-  }
-  else {
-    m_enabledLevel[prefix] = level;
-    auto range = boost::make_iterator_range(m_loggers.equal_range(prefix));
-    for (auto&& it : range) {
-      it.second->setLevel(level);
-    }
-  }
-}
-
-void
-Logging::setLevelImpl(const std::string& config)
-{
-  std::stringstream ss(config);
-  std::string configModule;
-  while (std::getline(ss, configModule, ':')) {
-    size_t ind = configModule.find('=');
-    if (ind == std::string::npos) {
-      BOOST_THROW_EXCEPTION(std::invalid_argument("malformed logging config: '=' is missing"));
-    }
-
-    std::string moduleName = configModule.substr(0, ind);
-    LogLevel level = parseLogLevel(configModule.substr(ind + 1));
-    this->setLevelImpl(moduleName, level);
-  }
-}
-
-#ifdef NDN_CXX_HAVE_TESTS
-void
-Logging::resetLevels()
-{
-  this->setLevelImpl("*", INITIAL_DEFAULT_LEVEL);
-  m_enabledLevel.clear();
-}
-#endif // NDN_CXX_HAVE_TESTS
-
-void
-Logging::setDestination(std::ostream& os)
-{
-  setDestination(shared_ptr<std::ostream>(&os, bind([]{})));
-}
-
-void
-Logging::setDestinationImpl(shared_ptr<std::ostream> os)
-{
-  std::lock_guard<std::mutex> lock(m_mutex);
-
-  m_destination = std::move(os);
-
-  auto backend = boost::make_shared<boost::log::sinks::text_ostream_backend>();
-  backend->auto_flush(true);
-  backend->add_stream(boost::shared_ptr<std::ostream>(m_destination.get(), bind([]{})));
-
-  if (m_sink != nullptr) {
-    boost::log::core::get()->remove_sink(m_sink);
-    m_sink->flush();
-    m_sink.reset();
-  }
-
-  m_sink = boost::make_shared<Sink>(backend);
-  m_sink->set_formatter(boost::log::expressions::stream << boost::log::expressions::message);
-  boost::log::core::get()->add_sink(m_sink);
-}
-
-#ifdef NDN_CXX_HAVE_TESTS
-shared_ptr<std::ostream>
-Logging::getDestination() const
-{
-  return m_destination;
-}
-
-void
-Logging::setLevelImpl(const std::unordered_map<std::string, LogLevel>& prefixRules)
-{
-  resetLevels();
-  for (const auto& rule : prefixRules) {
-    setLevelImpl(rule.first, rule.second);
-  }
-}
-
-const std::unordered_map<std::string, LogLevel>&
-Logging::getLevels() const
-{
-  return m_enabledLevel;
-}
-#endif // NDN_CXX_HAVE_TESTS
-
-void
-Logging::flushImpl()
-{
-  m_sink->flush();
-}
-
-} // namespace util
-} // namespace ndn
diff --git a/src/util/logging.hpp b/src/util/logging.hpp
deleted file mode 100644
index d85b524..0000000
--- a/src/util/logging.hpp
+++ /dev/null
@@ -1,220 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2017 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- */
-
-#ifndef NDN_UTIL_LOGGING_HPP
-#define NDN_UTIL_LOGGING_HPP
-
-#include "../common.hpp"
-
-#ifdef HAVE_NDN_CXX_CUSTOM_LOGGER
-#include "ndn-cxx-custom-logging.hpp"
-#else
-
-#include <boost/log/sinks.hpp>
-#include <mutex>
-#include <unordered_map>
-
-namespace ndn {
-namespace util {
-
-enum class LogLevel;
-class Logger;
-
-/** \brief controls the logging facility
- *
- *  \note Public static methods are thread safe.
- *        Non-public methods are not guaranteed to be thread safe.
- */
-class Logging : noncopyable
-{
-public:
-  /** \brief register a new logger
-   *  \note App should declare a new logger with \p NDN_LOG_INIT macro.
-   */
-  static void
-  addLogger(Logger& logger);
-
-  /** \brief get list of names of all registered loggers
-   */
-  static std::set<std::string>
-  getLoggerNames();
-
-  /** \brief set severity level
-   *  \param prefix logger prefix; this can be a specific logger name, a general prefix like ndn.a.*
-   *   to apply a setting for all modules that contain this prefix, or "*" for all modules
-   *  \param level minimum severity level
-   *
-   *  Log messages are output only if its severity is greater than the set minimum severity level.
-   *  Initial default severity level is \p LogLevel::NONE which enables FATAL only.
-   */
-  static void
-  setLevel(const std::string& prefix, LogLevel level);
-
-  /** \brief set severity levels with a config string
-   *  \param config colon-separate key=value pairs
-   *  \throw std::invalid_argument config string is malformed
-   *
-   *  \code
-   *  Logging::setSeverityLevels("*=INFO:Face=DEBUG:NfdController=WARN");
-   *  \endcode
-   *  is equivalent to
-   *  \code
-   *  Logging::setSeverityLevel("*", LogLevel::INFO);
-   *  Logging::setSeverityLevel("Face", LogLevel::DEBUG);
-   *  Logging::setSeverityLevel("NfdController", LogLevel::WARN);
-   *  \endcode
-   */
-  static void
-  setLevel(const std::string& config);
-
-  /** \brief set log destination
-   *  \param os a stream for log output
-   *
-   *  Initial destination is \p std::clog .
-   */
-  static void
-  setDestination(shared_ptr<std::ostream> os);
-
-  /** \brief set log destination
-   *  \param os a stream for log output; caller must ensure this is valid
-   *            until setDestination is invoked again or program exits
-   *
-   *  This is equivalent to setDestination(shared_ptr<std::ostream>(&os, nullDeleter))
-   */
-  static void
-  setDestination(std::ostream& os);
-
-  /** \brief flush log backend
-   *
-   *  This ensures log messages are written to the destination stream.
-   */
-  static void
-  flush();
-
-private:
-  Logging();
-
-  void
-  addLoggerImpl(Logger& logger);
-
-  std::set<std::string>
-  getLoggerNamesImpl() const;
-
-  /**
-   * \brief finds the appropriate LogLevel for a logger
-   * \param moduleName name of logger
-   *
-   * This searches m_enabledLevel map to determine which LogLevel is appropriate for
-   * the incoming logger. It looks for the most specific prefix and broadens its
-   * prefix scope if a setting is not found. For example, when an incoming logger
-   * name is "ndn.a.b", it will search for "ndn.a.b" first. If this prefix is not
-   * contained in m_enabledLevel, it will search for "ndn.a.*", then "ndn.*", and
-   * finally "*". It defaults to INITIAL_DEFAULT_LEVEL if a matching prefix is not
-   * found.
-   */
-  LogLevel
-  findLevel(const std::string& moduleName) const;
-
-  void
-  setLevelImpl(const std::string& prefix, LogLevel level);
-
-  void
-  setLevelImpl(const std::string& config);
-
-  void
-  setDestinationImpl(shared_ptr<std::ostream> os);
-
-  void
-  flushImpl();
-
-NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
-  static Logging&
-  get();
-
-#ifdef NDN_CXX_HAVE_TESTS
-  bool
-  removeLogger(Logger& logger);
-
-  void
-  resetLevels();
-
-  shared_ptr<std::ostream>
-  getDestination() const;
-
-  void
-  setLevelImpl(const std::unordered_map<std::string, LogLevel>& prefixRules);
-
-  const std::unordered_map<std::string, LogLevel>&
-  getLevels() const;
-#endif // NDN_CXX_HAVE_TESTS
-
-private:
-  mutable std::mutex m_mutex;
-  std::unordered_map<std::string, LogLevel> m_enabledLevel; ///< module prefix => minimum level
-  std::unordered_multimap<std::string, Logger*> m_loggers; ///< moduleName => logger
-
-  shared_ptr<std::ostream> m_destination;
-  typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_ostream_backend> Sink;
-  boost::shared_ptr<Sink> m_sink;
-};
-
-inline void
-Logging::addLogger(Logger& logger)
-{
-  get().addLoggerImpl(logger);
-}
-
-inline std::set<std::string>
-Logging::getLoggerNames()
-{
-  return get().getLoggerNamesImpl();
-}
-
-inline void
-Logging::setLevel(const std::string& prefix, LogLevel level)
-{
-  get().setLevelImpl(prefix, level);
-}
-
-inline void
-Logging::setLevel(const std::string& config)
-{
-  get().setLevelImpl(config);
-}
-
-inline void
-Logging::setDestination(shared_ptr<std::ostream> os)
-{
-  get().setDestinationImpl(std::move(os));
-}
-
-inline void
-Logging::flush()
-{
-  get().flushImpl();
-}
-
-} // namespace util
-} // namespace ndn
-
-#endif // HAVE_NDN_CXX_CUSTOM_LOGGER
-
-#endif // NDN_UTIL_LOGGING_HPP