jni: Android-specific custom logger for NFD
Change-Id: I4d98a58b8320735e40b5da3d358b9c71b558d995
Refs: #2508
diff --git a/app/src/main/jni/nfd-android/config.hpp b/app/src/main/jni/nfd-android/config.hpp
index 78b3f8b..f26c0f6 100644
--- a/app/src/main/jni/nfd-android/config.hpp
+++ b/app/src/main/jni/nfd-android/config.hpp
@@ -8,5 +8,6 @@
#define HAVE_LIBRESOLV
/*#undef HAVE_UNIX_SOCKETS*/
#define DEFAULT_CONFIG_FILE "./nfd.conf"
+#define HAVE_CUSTOM_LOGGER 1
#endif /* W_CONFIG_HPP_WAF */
diff --git a/app/src/main/jni/nfd-android/custom-logger-factory.cpp b/app/src/main/jni/nfd-android/custom-logger-factory.cpp
new file mode 100644
index 0000000..f84a663
--- /dev/null
+++ b/app/src/main/jni/nfd-android/custom-logger-factory.cpp
@@ -0,0 +1,213 @@
+/* -*- 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
+ *
+ * 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 "custom-logger-factory.hpp"
+
+namespace nfd {
+
+NFD_LOG_INIT("LoggerFactory");
+
+LoggerFactory&
+LoggerFactory::getInstance()
+{
+ static LoggerFactory globalLoggerFactory;
+
+ return globalLoggerFactory;
+}
+
+LoggerFactory::LoggerFactory()
+ : m_defaultLevel(LOG_INFO)
+{
+ m_levelNames["NONE"] = LOG_NONE;
+ m_levelNames["ERROR"] = LOG_ERROR;
+ m_levelNames["WARN"] = LOG_WARN;
+ m_levelNames["INFO"] = LOG_INFO;
+ m_levelNames["DEBUG"] = LOG_DEBUG;
+ m_levelNames["TRACE"] = LOG_TRACE;
+ m_levelNames["ALL"] = LOG_ALL;
+}
+
+void
+LoggerFactory::setConfigFile(ConfigFile& config)
+{
+ config.addSectionHandler("log", bind(&LoggerFactory::onConfig, this, _1, _2, _3));
+}
+
+LogLevel
+LoggerFactory::parseLevel(const std::string& level)
+{
+ std::string upperLevel = level;
+ boost::to_upper(upperLevel);
+
+ // std::cerr << "parsing level: " << upperLevel << std::endl;;
+ // std::cerr << "# levels: " << m_levelNames.size() << std::endl;
+ // 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 ((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 + "\"");
+}
+
+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)
+ {
+ }
+
+ if (levelString.empty())
+ {
+ throw LoggerFactory::Error("No logging level found for option \"" + key + "\"");
+ }
+
+ return parseLevel(levelString);
+}
+
+void
+LoggerFactory::onConfig(const ConfigSection& section,
+ bool isDryRun,
+ const std::string& filename)
+{
+// log
+// {
+// ; default_level specifies the logging level for modules
+// ; that are not explicitly named. All debugging levels
+// ; listed above the selected value are enabled.
+//
+// default_level INFO
+//
+// ; You may also override the default for specific modules:
+//
+// FibManager DEBUG
+// 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);
+ }
+ }
+
+ 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);
+ }
+ }
+ }
+}
+
+void
+LoggerFactory::setDefaultLevel(LogLevel level)
+{
+ // std::cerr << "changing to default_level " << level << std::endl;
+
+ 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);
+ }
+}
+
+Logger&
+LoggerFactory::create(const std::string& moduleName)
+{
+ return LoggerFactory::getInstance().createLogger(moduleName);
+}
+
+Logger&
+LoggerFactory::createLogger(const std::string& moduleName)
+{
+ // std::cerr << "creating logger for " << moduleName
+ // << " with level " << m_defaultLevel << std::endl;
+
+ std::pair<LoggerMap::iterator, bool> loggerIt =
+ m_loggers.insert(NameAndLogger(moduleName, Logger(moduleName, m_defaultLevel)));
+
+ return loggerIt.first->second;
+}
+
+std::list<std::string>
+LoggerFactory::getModules() const
+{
+ std::list<std::string> modules;
+ for (LoggerMap::const_iterator i = m_loggers.begin(); i != m_loggers.end(); ++i)
+ {
+ modules.push_back(i->first);
+ }
+
+ return modules;
+}
+
+} // namespace nfd
diff --git a/app/src/main/jni/nfd-android/custom-logger-factory.hpp b/app/src/main/jni/nfd-android/custom-logger-factory.hpp
new file mode 100644
index 0000000..394c90b
--- /dev/null
+++ b/app/src/main/jni/nfd-android/custom-logger-factory.hpp
@@ -0,0 +1,111 @@
+/* -*- 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
+ *
+ * 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/>.
+ **/
+
+#ifndef NFD_ANDROID_CUSTOM_LOGGER_FACTORY_HPP
+#define NFD_ANDROID_CUSTOM_LOGGER_FACTORY_HPP
+
+#include "common.hpp"
+
+#include "config-file.hpp"
+#include "logger.hpp"
+
+namespace nfd {
+
+class LoggerFactory : noncopyable
+{
+public:
+
+ class Error : public std::runtime_error
+ {
+ public:
+ explicit
+ Error(const std::string& error)
+ : std::runtime_error(error)
+ {
+ }
+ };
+
+ static LoggerFactory&
+ getInstance();
+
+ void
+ setConfigFile(ConfigFile& config);
+
+ void
+ onConfig(const ConfigSection& section, bool isDryRun, const std::string& filename);
+
+ std::list<std::string>
+ getModules() const;
+
+ static Logger&
+ create(const std::string& moduleName);
+
+
+PUBLIC_WITH_TESTS_ELSE_PRIVATE:
+
+ // these methods are used during unit-testing
+
+ LogLevel
+ getDefaultLevel() const;
+
+ void
+ setDefaultLevel(LogLevel level);
+
+private:
+
+ LoggerFactory();
+
+ Logger&
+ createLogger(const std::string& moduleName);
+
+ LogLevel
+ parseLevel(const std::string& level);
+
+ LogLevel
+ extractLevel(const ConfigSection& item, const std::string& key);
+
+private:
+
+ typedef std::map<std::string, LogLevel> LevelMap;
+ typedef std::pair<std::string, LogLevel> NameAndLevel;
+
+ LevelMap m_levelNames;
+
+ typedef std::map<std::string, Logger> LoggerMap;
+ typedef std::pair<std::string, Logger> NameAndLogger;
+
+ LoggerMap m_loggers;
+
+ LogLevel m_defaultLevel;
+};
+
+inline LogLevel
+LoggerFactory::getDefaultLevel() const
+{
+ return m_defaultLevel;
+}
+
+} // namespace nfd
+
+#endif // NFD_ANDROID_CUSTOM_LOGGER_FACTORY_HPP
diff --git a/app/src/main/jni/nfd-android/custom-logger.cpp b/app/src/main/jni/nfd-android/custom-logger.cpp
new file mode 100644
index 0000000..6b5d3ae
--- /dev/null
+++ b/app/src/main/jni/nfd-android/custom-logger.cpp
@@ -0,0 +1,36 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, 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 "custom-logger.hpp"
+
+namespace nfd {
+
+Logger::Logger(const std::string& name, LogLevel level)
+ : m_moduleName(name)
+ , m_enabledLogLevel(level)
+{
+}
+
+} // namespace nfd
diff --git a/app/src/main/jni/nfd-android/custom-logger.hpp b/app/src/main/jni/nfd-android/custom-logger.hpp
new file mode 100644
index 0000000..5355657
--- /dev/null
+++ b/app/src/main/jni/nfd-android/custom-logger.hpp
@@ -0,0 +1,140 @@
+/* -*- 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/>.
+ */
+
+#ifndef NFD_ANDROID_CUSTOM_LOGGER_HPP
+#define NFD_ANDROID_CUSTOM_LOGGER_HPP
+
+#include "common.hpp"
+#include <android/log.h>
+
+namespace nfd {
+
+/** \brief indicates a log level
+ * \note This type is internal. Logger should be accessed through NFD_LOG_* macros.
+ */
+enum LogLevel {
+ LOG_FATAL = -1, // fatal (will be logged unconditionally)
+ LOG_NONE = 0, // no messages
+ LOG_ERROR = 1, // serious error messages
+ LOG_WARN = 2, // warning messages
+ LOG_INFO = 3, // informational messages
+ LOG_DEBUG = 4, // debug messages
+ LOG_TRACE = 5, // trace messages (most verbose)
+ 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);
+
+ bool
+ isEnabled(LogLevel level) const
+ {
+ return m_enabledLogLevel >= level;
+ }
+
+ void
+ setLogLevel(LogLevel level)
+ {
+ m_enabledLogLevel = level;
+ }
+
+ const std::string&
+ getName() const
+ {
+ return m_moduleName;
+ }
+
+ void
+ setName(const std::string& name)
+ {
+ m_moduleName = name;
+ }
+
+private:
+ std::string m_moduleName;
+ LogLevel m_enabledLogLevel;
+};
+
+inline std::ostream&
+operator<<(std::ostream& output, const Logger& logger)
+{
+ output << logger.getName();
+ return output;
+}
+
+} // namespace nfd
+
+#include "core/logger-factory.hpp"
+
+namespace nfd {
+
+#define NFD_LOG_INIT(name) \
+static nfd::Logger& g_logger = nfd::LoggerFactory::create(name)
+
+#define NFD_LOG_INCLASS_DECLARE() \
+static nfd::Logger& g_logger
+
+#define NFD_LOG_INCLASS_DEFINE(cls, name) \
+nfd::Logger& cls::g_logger = nfd::LoggerFactory::create(name)
+
+#define NFD_LOG_INCLASS_TEMPLATE_DEFINE(cls, name) \
+template<class T> \
+nfd::Logger& cls<T>::g_logger = nfd::LoggerFactory::create(name)
+
+#define NFD_LOG_INCLASS_TEMPLATE_SPECIALIZATION_DEFINE(cls, specialization, name) \
+template<> \
+nfd::Logger& cls<specialization>::g_logger = nfd::LoggerFactory::create(name)
+
+#define NFD_LOG_INCLASS_2TEMPLATE_SPECIALIZATION_DEFINE(cls, s1, s2, name) \
+template<> \
+nfd::Logger& cls<s1, s2>::g_logger = nfd::LoggerFactory::create(name)
+
+#define NFD_LOG(nfdLevel, androidLevel, msg, expression) \
+do { \
+ if (g_logger.isEnabled(::nfd::LOG_##nfdLevel)) { \
+ std::ostringstream os; \
+ os << expression; \
+ __android_log_print(ANDROID_LOG_##androidLevel, \
+ g_logger.getName().c_str(), "%s", os.str().c_str()); \
+ } \
+} while (false)
+
+#define NFD_LOG_TRACE(expression) NFD_LOG(TRACE, VERBOSE, TRACE, expression)
+#define NFD_LOG_DEBUG(expression) NFD_LOG(DEBUG, DEBUG, DEBUG, expression)
+#define NFD_LOG_INFO(expression) NFD_LOG(INFO, INFO, INFO, expression)
+#define NFD_LOG_WARN(expression) NFD_LOG(WARN, WARN, WARNING, expression)
+#define NFD_LOG_ERROR(expression) NFD_LOG(ERROR, ERROR, ERROR, expression)
+#define NFD_LOG_FATAL(expression) NFD_LOG(FATAL, FATAL, FATAL, expression)
+
+} // namespace nfd
+
+#endif // NFD_ANDROID_CUSTOM_LOGGER_HPP
diff --git a/app/src/main/jni/nfd-android/version.hpp b/app/src/main/jni/nfd-android/version.hpp
index d9aa54a..afa7ae1 100644
--- a/app/src/main/jni/nfd-android/version.hpp
+++ b/app/src/main/jni/nfd-android/version.hpp
@@ -38,13 +38,13 @@
*
* MAJOR*1000000 + MINOR*1000 + PATCH
*/
-#define NFD_VERSION 2000
+#define NFD_VERSION 3000
/** \brief NFD version represented as a string
*
* MAJOR.MINOR.PATCH
*/
-#define NFD_VERSION_STRING "0.2.0"
+#define NFD_VERSION_STRING "0.3.0"
/** \brief NFD version string, including git commit information, if NFD is build from
* specific git commit
@@ -60,12 +60,12 @@
*
* Example, 0.1.0-rc1-1-g5c86570
*/
-#define NFD_VERSION_BUILD_STRING "0.2.0-134-gde88b46"
+#define NFD_VERSION_BUILD_STRING "0.3.0-8-g6f570de"
/// MAJOR version
#define NFD_VERSION_MAJOR 0
/// MINOR version
-#define NFD_VERSION_MINOR 2
+#define NFD_VERSION_MINOR 3
/// PATCH version
#define NFD_VERSION_PATCH 0