Created and integrated levelized log

Change-Id: Ibfed76796a880bab2709b77b0c9540be7b75fad7
diff --git a/src/main.cpp b/src/main.cpp
index 8ae511f..5500ada 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -23,6 +23,7 @@
 #include "sequential-data-fetcher.hpp"
 #include "torrent-file.hpp"
 #include "util/io-util.hpp"
+#include "util/logging.hpp"
 
 #include <iostream>
 #include <iterator>
@@ -31,8 +32,11 @@
 
 #include <boost/program_options.hpp>
 #include <boost/program_options/errors.hpp>
+#include <boost/log/utility/setup/common_attributes.hpp>
 
+namespace logging = boost::log;
 namespace po = boost::program_options;
+
 using namespace ndn::ntorrent;
 
 namespace ndn {
@@ -53,6 +57,9 @@
 int main(int argc, char *argv[])
 {
   try {
+   LoggingUtil::init();
+   logging::add_common_attributes();
+
     po::options_description desc("Allowed options");
     desc.add_options()
     // TODO(msweatt) Consider  adding  flagged args for other parameters
@@ -100,14 +107,14 @@
       // write all the torrent segments
       for (const TorrentFile& t : torrentSegments) {
         if (!IoUtil::writeTorrentSegment(t, torrentPath)) {
-          std::cerr << "Write failed: " << t.getName() << std::endl;
+          LOG_ERROR << "Write failed: " << t.getName() << std::endl;
           return -1;
         }
       }
       auto manifestPath = outputPath + "/manifests/";
       for (const FileManifest& m : manifests) {
         if (!IoUtil::writeFileManifest(m, manifestPath)) {
-          std::cerr << "Write failed: " << m.getName() << std::endl;
+          LOG_ERROR << "Write failed: " << m.getName() << std::endl;
           return -1;
         }
       }
diff --git a/src/sequential-data-fetcher.cpp b/src/sequential-data-fetcher.cpp
index 06b3f02..b994384 100644
--- a/src/sequential-data-fetcher.cpp
+++ b/src/sequential-data-fetcher.cpp
@@ -20,6 +20,7 @@
 */
 
 #include "sequential-data-fetcher.hpp"
+#include "util/logging.hpp"
 #include "util/io-util.hpp"
 
 namespace ndn {
@@ -67,7 +68,7 @@
   std::vector<ndn::Name> returnedNames;
   returnedNames = m_manager->downloadTorrentFile(".appdata/torrent_files/");
   if (!returnedNames.empty() && IoUtil::NAME_TYPE::FILE_MANIFEST == IoUtil::findType(returnedNames[0])) {
-    std::cout << "Torrent File Received: "
+    LOG_INFO  << "Torrent File Received: "
               << m_torrentFileName.getSubName(0, m_torrentFileName.size() - 1) << std::endl;
   }
   return returnedNames;
@@ -121,13 +122,13 @@
 SequentialDataFetcher::onDataPacketReceived(const ndn::Data& data)
 {
   // Data Packet Received
-  std::cout << "Data Packet Received: " << data.getName();
+  LOG_INFO << "Data Packet Received: " << data.getName();
 }
 
 void
 SequentialDataFetcher::onManifestReceived(const std::vector<Name>& packetNames)
 {
-  std::cout << "Manifest File Received: "
+  LOG_INFO << "Manifest File Received: "
             << packetNames[0].getSubName(0, packetNames[0].size()- 3) << std::endl;
   this->downloadPackets(packetNames);
 }
@@ -136,26 +137,32 @@
 SequentialDataFetcher::onDataRetrievalFailure(const ndn::Interest& interest,
                                               const std::string& errorCode)
 {
-  // std::cerr << "Data Retrieval Failed: " << interest.getName() << std::endl;
-
   // Data retrieval failure
   uint32_t nameType = IoUtil::findType(interest.getName());
   if (nameType == IoUtil::TORRENT_FILE) {
     // this should never happen
-    // std::cerr << "Torrent File Segment Downloading Failed: " << interest.getName();
+    LOG_ERROR << "Torrent File Segment Downloading Failed: " << interest.getName();
     this->downloadTorrentFile();
   }
   else if (nameType == IoUtil::FILE_MANIFEST) {
-    // std::cerr << "Manifest File Segment Downloading Failed: " << interest.getName();
+    LOG_ERROR << "Manifest File Segment Downloading Failed: " << interest.getName();
     this->downloadManifestFiles({ interest.getName() });
   }
   else if (nameType == IoUtil::DATA_PACKET) {
-    // std::cerr << "Data Packet Downloading Failed: " << interest.getName();
+    LOG_ERROR << "Torrent File Segment Downloading Failed: " << interest.getName();
+    this->downloadTorrentFile();
+  }
+  else if (nameType == IoUtil::FILE_MANIFEST) {
+    LOG_ERROR << "Manifest File Segment Downloading Failed: " << interest.getName();
+    this->downloadManifestFiles({ interest.getName() });
+  }
+  else if (nameType == IoUtil::DATA_PACKET) {
+    LOG_ERROR << "Data Packet Downloading Failed: " << interest.getName();
     this->downloadPackets({ interest.getName() });
   }
   else {
     // This should never happen
-    // std::cerr << "Unknown Packet Type Downloading Failed: " << interest.getName();
+    LOG_ERROR << "Unknown Packet Type Downloading Failed: " << interest.getName();
   }
 }
 
diff --git a/src/torrent-manager.cpp b/src/torrent-manager.cpp
index 790e166..c976cb1 100644
--- a/src/torrent-manager.cpp
+++ b/src/torrent-manager.cpp
@@ -3,6 +3,7 @@
 #include "file-manifest.hpp"
 #include "torrent-file.hpp"
 #include "util/io-util.hpp"
+#include "util/logging.hpp"
 
 #include <boost/filesystem.hpp>
 #include <boost/filesystem/fstream.hpp>
@@ -613,7 +614,7 @@
   }
   else {
     // TODO(msweatt) NACK
-    std::cerr << "NACK: " << interest << std::endl;
+    LOG_ERROR << "NACK: " << interest << std::endl;
   }
   return;
 }
@@ -621,7 +622,7 @@
 void
 TorrentManager::onRegisterFailed(const Name& prefix, const std::string& reason)
 {
-  std::cerr << "ERROR: Failed to register prefix \""
+  LOG_ERROR << "ERROR: Failed to register prefix \""
             << prefix << "\" in local hub's daemon (" << reason << ")"
             << std::endl;
   m_face->shutdown();
diff --git a/src/update-handler.cpp b/src/update-handler.cpp
index 3d13b21..5c942da 100644
--- a/src/update-handler.cpp
+++ b/src/update-handler.cpp
@@ -20,6 +20,7 @@
 */
 
 #include "update-handler.hpp"
+#include "util/logging.hpp"
 
 #include <ndn-cxx/security/signing-helpers.hpp>
 
@@ -106,7 +107,7 @@
   // RoutableName ::= NAME-TYPE TLV-LENGTH
   //                  Name
 
-  std::cout << "ALIVE data packet received: " << data.getName() << std::endl;
+  LOG_INFO << "ALIVE data packet received: " << data.getName() << std::endl;
 
   if (data.getContentType() != tlv::ContentType_Blob) {
       BOOST_THROW_EXCEPTION(Error("Expected Content Type Blob"));
@@ -160,7 +161,7 @@
   };
 
   auto prefixRetrievalFailed = [this] (const Interest&) {
-    std::cerr << "Own Routable Prefix Retrieval Failed. Trying again." << std::endl;
+    LOG_ERROR << "Own Routable Prefix Retrieval Failed. Trying again." << std::endl;
     // TODO(Spyros): This could lead to an infinite loop. Figure out something better...
     this->learnOwnRoutablePrefix();
   };
@@ -172,7 +173,7 @@
 void
 UpdateHandler::onInterestReceived(const InterestFilter& filter, const Interest& interest)
 {
-  std::cout << "Interest Received: " << interest.getName().toUri() << std::endl;
+  LOG_INFO << "Interest Received: " << interest.getName().toUri() << std::endl;
   shared_ptr<Data> data = this->createDataPacket(interest.getName());
   m_keyChain->sign(*data, signingWithSha256());
   m_face->put(*data);
@@ -181,7 +182,7 @@
 void
 UpdateHandler::onRegisterFailed(const Name& prefix, const std::string& reason)
 {
-  std::cerr << "ERROR: Failed to register prefix \""
+ LOG_ERROR << "ERROR: Failed to register prefix \""
             << prefix << "\" in local hub's daemon (" << reason << ")"
             << std::endl;
   m_face->shutdown();
diff --git a/src/util/io-util.cpp b/src/util/io-util.cpp
index 0d02475..12572b3 100644
--- a/src/util/io-util.cpp
+++ b/src/util/io-util.cpp
@@ -2,6 +2,7 @@
 
 #include "file-manifest.hpp"
 #include "torrent-file.hpp"
+#include "util/logging.hpp"
 
 #include <boost/filesystem.hpp>
 #include <boost/filesystem/fstream.hpp>
@@ -148,7 +149,7 @@
     return true;
   }
   catch (io::Error &e) {
-    std::cerr << e.what() << std::endl;
+    LOG_ERROR << e.what() << std::endl;
     return false;
   }
 }
@@ -166,14 +167,14 @@
   is.sync();
   is.seekg(start_offset + packetNum * dataPacketSize);
   if (is.tellg() < 0) {
-    std::cerr << "bad seek" << std::endl;
+    LOG_ERROR << "bad seek" << std::endl;
   }
  // read contents
  std::vector<char> bytes(dataPacketSize);
  is.read(&bytes.front(), dataPacketSize);
  auto read_size = is.gcount();
  if (is.bad() || read_size < 0) {
-  std::cerr << "Bad read" << std::endl;
+  LOG_ERROR << "Bad read" << std::endl;
   return nullptr;
  }
  // construct packet
diff --git a/src/util/logging.cpp b/src/util/logging.cpp
new file mode 100644
index 0000000..b067c80
--- /dev/null
+++ b/src/util/logging.cpp
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+* Copyright (c) 2016 Regents of the University of California.
+*
+* This file is part of the nTorrent codebase.
+*
+* nTorrent 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.
+*
+* nTorrent 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 nTorrent, e.g., in COPYING.md file. If not, see
+* <http://www.gnu.org/licenses/>.
+*
+* See AUTHORS for complete list of nTorrent authors and contributors.
+*/
+
+
+#include "util/logging.hpp"
+
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/expressions.hpp>
+#include <boost/log/sinks/text_file_backend.hpp>
+#include <boost/log/sources/record_ostream.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/support/date_time.hpp>
+#include <boost/log/trivial.hpp>
+#include <boost/log/utility/setup/file.hpp>
+
+// ===== log macros =====
+namespace logging = boost::log;
+namespace src = boost::log::sources;
+namespace sinks = boost::log::sinks;
+namespace keywords = boost::log::keywords;
+namespace expr = boost::log::expressions;
+
+namespace ndn {
+namespace ntorrent {
+
+void LoggingUtil::init()
+{
+  logging::core::get()->set_filter
+  (
+      logging::trivial::severity >= SEVERITY_THRESHOLD
+  );
+
+  logging::add_file_log
+  (
+     keywords::file_name = "sample_%N.log",                                        // < file name pattern >
+     keywords::rotation_size = 10 * 1024 * 1024,                                   // < rotate files every 10 MiB... >
+     keywords::time_based_rotation = sinks::file::rotation_at_time_point(0, 0, 0), // < ...or at midnight >
+     keywords::format =                                                            // < log record format >
+     (
+       expr::stream
+           << expr::attr< unsigned int >("LineID")
+           << ": [" << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S") << "]"
+           << ": <" << logging::trivial::severity
+           << "> " << expr::smessage
+    )
+  );
+}
+
+} // end ntorrent
+} // end ndn
+
+
diff --git a/src/util/logging.hpp b/src/util/logging.hpp
new file mode 100644
index 0000000..bb926a4
--- /dev/null
+++ b/src/util/logging.hpp
@@ -0,0 +1,58 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+* Copyright (c) 2016 Regents of the University of California.
+*
+* This file is part of the nTorrent codebase.
+*
+* nTorrent 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.
+*
+* nTorrent 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 nTorrent, e.g., in COPYING.md file. If not, see
+* <http://www.gnu.org/licenses/>.
+*
+* See AUTHORS for complete list of nTorrent authors and contributors.
+*/
+#ifndef UTIL_LOGGING_HPP
+#define UTIL_LOGGING_HPP
+
+#define BOOST_LOG_DYN_LINK 1
+
+#include <boost/log/core.hpp>
+#include <boost/log/sources/global_logger_storage.hpp>
+#include <boost/log/sources/severity_logger.hpp>
+#include <boost/log/trivial.hpp>
+
+enum { SEVERITY_THRESHOLD = boost::log::trivial::warning };
+
+// register a global logger
+BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(logger, boost::log::sources::severity_logger_mt<boost::log::trivial::severity_level>)
+
+// just a helper macro used by the macros below - don't use it in your code
+#define LOG(severity) BOOST_LOG_SEV(logger::get(), boost::log::trivial::severity)
+
+// ===== log macros =====
+#define LOG_TRACE   LOG(trace)
+#define LOG_DEBUG   LOG(debug)
+#define LOG_INFO    LOG(info)
+#define LOG_WARNING LOG(warning)
+#define LOG_ERROR   LOG(error)
+#define LOG_FATAL   LOG(fatal)
+
+namespace ndn {
+namespace ntorrent {
+
+struct LoggingUtil {
+  static void init();
+  // Initialize the log for the application. THis method must be called in the main function in
+  // the application before any logging may be performed.
+};
+
+} // end ntorrent
+} // end ndn
+#endif // UTIL_LOGGING_HPP