VOM: logging, populate and stats fixes

logging: allow a client to register a callback handler to recieve log messages
         that way the client can maintain a correctly sequenced log
populate: fix the creation of interface and the setting of the handle
stats: the reset promise idea is not defined behaviour.
       Use an eanble/disable command pair

Change-Id: I347720bb65df2874c7619e722d593bc863ee2bf1
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
diff --git a/src/vpp-api/vom/logger.cpp b/src/vpp-api/vom/logger.cpp
index 07e2749..80f2d92 100644
--- a/src/vpp-api/vom/logger.cpp
+++ b/src/vpp-api/vom/logger.cpp
@@ -43,7 +43,7 @@
 
 log_t::log_t()
   : m_level(log_level_t::ERROR)
-  , m_o_stream(&std::cout)
+  , m_handler(new cout_handler())
 {
 }
 
@@ -54,33 +54,19 @@
 }
 
 void
-log_t::set(const std::string& ofile)
+log_t::set(handler* h)
 {
-  m_file_stream.open(ofile);
-  m_o_stream = &m_file_stream;
+  m_handler = h;
 }
 
-std::ostream&
-log_t::stream(const char* file, int line, const log_level_t& level)
+void
+log_t::write(const std::string& file,
+             const int line,
+             const std::string& function,
+             const log_level_t& level,
+             const std::string& message)
 {
-  auto end = std::chrono::system_clock::now();
-  auto end_time = std::chrono::system_clock::to_time_t(end);
-
-  /*
- * put-time is not support in gcc in 4.8
- * so we play this dance with ctime
- */
-  std::string display = std::ctime(&end_time);
-  display.pop_back();
-
-  std::vector<std::string> dirs;
-  boost::split(dirs, file, boost::is_any_of("/"));
-
-  *m_o_stream << std::endl
-              << display << " [" << level.to_string() << "]"
-              << " " << dirs.back() << ":" << line << ": ";
-
-  return (*m_o_stream);
+  m_handler->handle_message(file, line, function, level, message);
 }
 
 /**
@@ -91,8 +77,90 @@
 {
   return (m_level);
 }
+
+static std::string
+get_filename(const std::string& file)
+{
+  std::vector<std::string> dirs;
+  boost::split(dirs, file, boost::is_any_of("/"));
+
+  return dirs.back();
 }
 
+log_t::entry::entry(const char* file,
+                    const char* function,
+                    int line,
+                    const log_level_t& level)
+  : m_file(get_filename(file))
+  , m_function(function)
+  , m_level(level)
+  , m_line(line)
+{
+}
+
+log_t::entry::~entry()
+{
+  logger().write(m_file, m_line, m_function, m_level, m_stream.str());
+}
+
+std::stringstream&
+log_t::entry::stream()
+{
+  return (m_stream);
+}
+
+static std::string
+get_timestamp()
+{
+  auto end = std::chrono::system_clock::now();
+  auto end_time = std::chrono::system_clock::to_time_t(end);
+
+  /*
+   * put-time is not support in gcc in 4.8
+   * so we play this dance with ctime
+   */
+  std::string display = std::ctime(&end_time);
+  display.pop_back();
+
+  return (display);
+}
+
+file_handler::file_handler(const std::string& ofile)
+{
+  m_file_stream.open(ofile);
+}
+
+file_handler::~file_handler()
+{
+  m_file_stream.close();
+}
+
+void
+file_handler::handle_message(const std::string& file,
+                             const int line,
+                             const std::string& function,
+                             const log_level_t& level,
+                             const std::string& message)
+{
+  m_file_stream << get_timestamp();
+  m_file_stream << " [" << level.to_string() << "]" << file << ":" << line
+                << " " << function << "() " << message << std::endl;
+}
+
+void
+cout_handler::handle_message(const std::string& file,
+                             const int line,
+                             const std::string& function,
+                             const log_level_t& level,
+                             const std::string& message)
+{
+  std::cout << get_timestamp();
+  std::cout << " [" << level.to_string() << "]" << file << ":" << line << " "
+            << function << "() " << message << std::endl;
+}
+
+}; // namespace VOM
+
 /*
  * fd.io coding-style-patch-verification: ON
  *