core: simplify Logger with C++11 features
refs #2146
Change-Id: I6ad9e7281c8a6b60c46b51de727bcddded42ba3d
diff --git a/core/logger.cpp b/core/logger.cpp
new file mode 100644
index 0000000..7d92aa3
--- /dev/null
+++ b/core/logger.cpp
@@ -0,0 +1,65 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "logger.hpp"
+#include <ndn-cxx/util/time.hpp>
+#include <cinttypes>
+#include <cstdio>
+#include <type_traits>
+
+namespace nfd {
+
+Logger::Logger(const std::string& name, LogLevel level)
+ : m_moduleName(name)
+ , m_enabledLogLevel(level)
+{
+}
+
+const char*
+Logger::now()
+{
+ using namespace ndn::time;
+
+ static const microseconds::rep ONE_SECOND = 1000000;
+ microseconds::rep microsecondsSinceEpoch = duration_cast<microseconds>(
+ system_clock::now().time_since_epoch()).count();
+
+ // 10 (whole seconds) + '.' + 6 (fraction) + '\0'
+ static char buffer[10 + 1 + 6 + 1];
+ BOOST_ASSERT_MSG(microsecondsSinceEpoch / 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(buffer, sizeof(buffer), "%" PRIdLEAST64 ".%06" PRIdLEAST64,
+ microsecondsSinceEpoch / ONE_SECOND,
+ microsecondsSinceEpoch % ONE_SECOND);
+
+ // It's okay to return a statically allocated buffer, because Logger::now() is invoked
+ // only once per log macro.
+ return buffer;
+}
+
+} // namespace nfd
diff --git a/core/logger.hpp b/core/logger.hpp
index 01ab1e6..5efee3c 100644
--- a/core/logger.hpp
+++ b/core/logger.hpp
@@ -1,11 +1,12 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014 Regents of the University of California,
- * Arizona Board of Regents,
- * Colorado State University,
- * University Pierre & Marie Curie, Sorbonne University,
- * Washington University in St. Louis,
- * Beijing Institute of Technology
+ * Copyright (c) 2014, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis
*
* This file is part of NFD (Named Data Networking Forwarding Daemon).
* See AUTHORS.md for complete list of NFD authors and contributors.
@@ -20,19 +21,18 @@
*
* You should have received a copy of the GNU General Public License along with
* NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- **/
+ */
#ifndef NFD_CORE_LOGGER_HPP
#define NFD_CORE_LOGGER_HPP
#include "common.hpp"
-#include <ndn-cxx/util/time.hpp>
-
-/// \todo use when we enable C++11 (see todo in now())
-// #include <cinttypes>
namespace nfd {
+/** \brief indicates a log level
+ * \note This type is internal. Logger should be accessed through NFD_LOG_* macros.
+ */
enum LogLevel {
LOG_NONE = 0, // no messages
LOG_ERROR = 1, // serious error messages
@@ -44,15 +44,15 @@
LOG_ALL = 255 // all messages
};
+/** \brief provides logging for a module
+ * \note This type is internal. Logger should be accessed through NFD_LOG_* macros.
+ * \note This type is copyable because logger can be declared as a field of
+ * (usually template) classes, and shouldn't prevent those classes to be copyable.
+ */
class Logger
{
public:
-
- Logger(const std::string& name, LogLevel level)
- : m_moduleName(name)
- , m_enabledLogLevel(level)
- {
- }
+ Logger(const std::string& name, LogLevel level);
bool
isEnabled(LogLevel level) const
@@ -81,29 +81,12 @@
m_moduleName = name;
}
- /// \brief return a string representation of time since epoch: seconds.microseconds
- static std::string
- now()
- {
- using namespace ndn::time;
-
- static const microseconds::rep ONE_SECOND = 1000000;
- microseconds::rep microseconds_since_epoch =
- duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
-
- // 10 (whole seconds) + '.' + 6 (fraction) + 1 (\0)
- char buffer[10 + 1 + 6 + 1];
- ::snprintf(buffer, sizeof(buffer), "%lld.%06lld",
- static_cast<long long int>(microseconds_since_epoch / ONE_SECOND),
- static_cast<long long int>(microseconds_since_epoch % ONE_SECOND));
-
- /// \todo use this version when we enable C++11 to avoid casting
- // ::snprintf(buffer, sizeof(buffer), "%" PRIdLEAST64 ".%06" PRIdLEAST64,
- // microseconds_since_epoch / ONE_SECOND,
- // microseconds_since_epoch % ONE_SECOND);
-
- return std::string(buffer);
- }
+ /** \return string representation of time since epoch: seconds.microseconds
+ * \warning Return value is in a statically allocated buffer,
+ * which subsequent calls will overwrite.
+ */
+ static const char*
+ now();
private:
std::string m_moduleName;
@@ -145,32 +128,25 @@
nfd::Logger& cls<s1, s2>::g_logger = nfd::LoggerFactory::create(name)
-#define NFD_LOG(level, expression) \
-do { \
- if (g_logger.isEnabled(::nfd::LOG_##level)) \
- std::clog << ::nfd::Logger::now() << " "#level": " \
- << "[" << g_logger << "] " << expression << "\n"; \
+#define NFD_LOG(level, msg, expression) \
+do { \
+ if (g_logger.isEnabled(::nfd::LOG_##level)) \
+ std::clog << ::nfd::Logger::now() << " "#msg": " \
+ << "[" << g_logger << "] " << expression << "\n"; \
} while (false)
-#define NFD_LOG_TRACE(expression) NFD_LOG(TRACE, expression)
-#define NFD_LOG_DEBUG(expression) NFD_LOG(DEBUG, expression)
-#define NFD_LOG_INFO(expression) NFD_LOG(INFO, expression)
-#define NFD_LOG_ERROR(expression) NFD_LOG(ERROR, expression)
+#define NFD_LOG_TRACE(expression) NFD_LOG(TRACE, TRACE, expression)
+#define NFD_LOG_DEBUG(expression) NFD_LOG(DEBUG, DEBUG, expression)
+#define NFD_LOG_INFO(expression) NFD_LOG(INFO, INFO, expression)
+#define NFD_LOG_WARN(expression) NFD_LOG(WARN, WARNING, expression)
+#define NFD_LOG_ERROR(expression) NFD_LOG(ERROR, ERROR, expression)
-// specialize WARN because the message is "WARNING" instead of "WARN"
-#define NFD_LOG_WARN(expression) \
-do { \
- if (g_logger.isEnabled(::nfd::LOG_WARN)) \
- std::clog << ::nfd::Logger::now() << " WARNING: " \
- << "[" << g_logger << "] " << expression << "\n"; \
+#define NFD_LOG_FATAL(expression) \
+do { \
+ std::clog << ::nfd::Logger::now() << " FATAL: " \
+ << "[" << g_logger << "] " << expression << "\n"; \
} while (false)
-#define NFD_LOG_FATAL(expression) \
-do { \
- std::clog << ::nfd::Logger::now() << " FATAL: " \
- << "[" << g_logger << "] " << expression << "\n"; \
-} while (false)
+} // namespace nfd
-} //namespace nfd
-
-#endif
+#endif // NFD_CORE_LOGGER_HPP