FileLogOutput.cpp
Go to the documentation of this file.
00001 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
00002 
00003 // -- BEGIN LICENSE BLOCK ----------------------------------------------
00004 // This file is part of FZIs ic_workspace.
00005 //
00006 // This program is free software licensed under the LGPL
00007 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
00008 // You can find a copy of this license in LICENSE folder in the top
00009 // directory of the source code.
00010 //
00011 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
00012 //
00013 // -- END LICENSE BLOCK ------------------------------------------------
00014 
00015 //----------------------------------------------------------------------
00022 //----------------------------------------------------------------------
00023 #include "icl_core_logging/FileLogOutput.h"
00024 
00025 #include <boost/filesystem/path.hpp>
00026 #include <boost/filesystem/operations.hpp>
00027 #include <iostream>
00028 
00029 #include "icl_core/os_fs.h"
00030 #include "icl_core_config/Config.h"
00031 #include "icl_core_logging/Logging.h"
00032 
00033 #if defined(_SYSTEM_POSIX_) && !defined(__ANDROID__)
00034 # include <wordexp.h>
00035 #endif
00036 
00037 namespace icl_core {
00038 namespace logging {
00039 
00040 REGISTER_LOG_OUTPUT_STREAM(File, &FileLogOutput::create)
00041 
00042 LogOutputStream *FileLogOutput::create(const icl_core::String& name, const icl_core::String& config_prefix,
00043                                        icl_core::logging::LogLevel log_level)
00044 {
00045   return new FileLogOutput(name, config_prefix, log_level);
00046 }
00047 
00048 FileLogOutput::FileLogOutput(const icl_core::String& name, const icl_core::String& config_prefix,
00049                              icl_core::logging::LogLevel log_level)
00050   : LogOutputStream(name, config_prefix, log_level),
00051     m_rotate(false),
00052     m_last_rotation(0),
00053     m_delete_old_files(false),
00054     m_delete_older_than_days(0)
00055 #if defined(_IC_BUILDER_ZLIB_)
00056   , m_zipped_log_file(NULL)
00057 #endif
00058 {
00059   icl_core::config::get<bool>(config_prefix + "/Rotate", m_rotate);
00060   if (m_rotate)
00061   {
00062     m_last_rotation = icl_core::TimeStamp::now().days();
00063   }
00064 
00065   if (icl_core::config::get<uint32_t>(config_prefix + "/DeleteOlderThan", m_delete_older_than_days))
00066   {
00067     m_delete_old_files = true;
00068   }
00069 
00070 #if defined(_IC_BUILDER_ZLIB_)
00071   m_online_zip = icl_core::config::getDefault<bool>(config_prefix + "/Zip", false);
00072 #endif
00073 
00074   m_flush = icl_core::config::getDefault<bool>(config_prefix + "/Flush", true);
00075 
00076   if (icl_core::config::get<icl_core::String>(config_prefix + "/FileName", m_filename))
00077   {
00078     expandFilename();
00079 
00080     // Determine the last write time of the log file, if it already
00081     // exists.
00082     boost::filesystem::path log_file_path(m_filename);
00083     if (boost::filesystem::exists(log_file_path))
00084     {
00085       if (boost::filesystem::is_directory(log_file_path))
00086       {
00087         std::cerr << "The filename specified for log output stream "
00088                   << config_prefix << " is a directory." << std::endl;
00089       }
00090       else
00091       {
00092         m_last_rotation = icl_core::TimeStamp(boost::filesystem::last_write_time(log_file_path)).days();
00093         rotateLogFile();
00094       }
00095     }
00096 
00097     openLogFile();
00098   }
00099   else
00100   {
00101     std::cerr << "No filename specified for file log output stream " << config_prefix << std::endl;
00102   }
00103 }
00104 
00105 FileLogOutput::FileLogOutput(const icl_core::String& name, const icl_core::String& filename,
00106                              icl_core::logging::LogLevel log_level, bool flush)
00107   : LogOutputStream(name, log_level),
00108     m_filename(filename),
00109     m_rotate(false),
00110     m_last_rotation(0),
00111     m_delete_old_files(false),
00112     m_delete_older_than_days(0),
00113     m_flush(flush)
00114 #if defined(_IC_BUILDER_ZLIB_)
00115   , m_online_zip(false),
00116     m_zipped_log_file(NULL)
00117 #endif
00118 {
00119   expandFilename();
00120   openLogFile();
00121 }
00122 
00123 FileLogOutput::~FileLogOutput()
00124 {
00125   closeLogFile();
00126 }
00127 
00128 void FileLogOutput::pushImpl(const icl_core::String& log_line)
00129 {
00130   rotateLogFile();
00131 
00132   if (!isOpen())
00133   {
00134     openLogFile();
00135   }
00136 
00137   if (isOpen())
00138   {
00139 #ifdef _IC_BUILDER_ZLIB_
00140     if (m_online_zip)
00141     {
00142       gzwrite(m_zipped_log_file, log_line.c_str(), static_cast<unsigned int>(log_line.length()));
00143     }
00144     else
00145 #endif
00146     {
00147       m_log_file << log_line;
00148     }
00149 
00150     if (m_flush)
00151     {
00152       flush();
00153     }
00154   }
00155 }
00156 
00157 bool FileLogOutput::isOpen()
00158 {
00159 #ifdef _IC_BUILDER_ZLIB_
00160   if (m_online_zip)
00161   {
00162     return m_zipped_log_file != NULL;
00163   }
00164   else
00165 #endif
00166   {
00167     return m_log_file.is_open();
00168   }
00169 }
00170 
00171 void FileLogOutput::flush()
00172 {
00173 #ifdef _IC_BUILDER_ZLIB_
00174   if (m_online_zip)
00175   {
00176     gzflush(m_zipped_log_file, Z_SYNC_FLUSH);
00177   }
00178   else
00179 #endif
00180   {
00181     m_log_file.flush();
00182   }
00183 }
00184 
00185 void FileLogOutput::closeLogFile()
00186 {
00187 #ifdef _IC_BUILDER_ZLIB_
00188   if (m_online_zip)
00189   {
00190     if (m_zipped_log_file != NULL)
00191     {
00192       gzclose(m_zipped_log_file);
00193       m_zipped_log_file = NULL;
00194     }
00195   }
00196   else
00197 #endif
00198   {
00199     if (m_log_file.is_open())
00200     {
00201       m_log_file.close();
00202     }
00203   }
00204 }
00205 
00206 void FileLogOutput::openLogFile()
00207 {
00208 #if defined(_IC_BUILDER_ZLIB_)
00209   if (m_online_zip)
00210   {
00211     m_zipped_log_file = gzopen(m_filename.c_str(), "a+b");
00212     if (m_zipped_log_file == NULL)
00213     {
00214       std::cerr << "Could not open log file " << m_filename << std::endl;
00215     }
00216     else
00217     {
00218       const char *buffer = "\n\n-------------FILE (RE-)OPENED------------------\n";
00219       gzwrite(m_zipped_log_file, buffer, static_cast<unsigned int>(strlen(buffer)));
00220     }
00221   }
00222   else
00223 #endif
00224     if (!m_log_file.is_open())
00225     {
00226       m_log_file.open(m_filename.c_str(), std::ios::out | std::ios::app);
00227       if (m_log_file.is_open())
00228       {
00229         m_log_file << "\n\n-------------FILE (RE-)OPENED------------------\n";
00230         m_log_file.flush();
00231       }
00232       else
00233       {
00234         std::cerr << "Could not open log file " << m_filename << std::endl;
00235       }
00236     }
00237 }
00238 
00239 void FileLogOutput::rotateLogFile()
00240 {
00241   if (m_rotate)
00242   {
00243     int64_t current_day = icl_core::TimeStamp::now().days();
00244     if (m_last_rotation != current_day)
00245     {
00246       // First, close the log file if it's open.
00247       closeLogFile();
00248 
00249       // Move the file. ZIP it, if libz is available.
00250       char time_str[12];
00251       icl_core::TimeStamp(24*3600*m_last_rotation).strfTime(time_str, 12, ".%Y-%m-%d");
00252 #ifdef _IC_BUILDER_ZLIB_
00253       if (!m_online_zip)
00254       {
00255         icl_core::os::zipFile(m_filename.c_str(), time_str);
00256         icl_core::os::unlink(m_filename.c_str());
00257       }
00258       else
00259 #endif
00260       {
00261         icl_core::os::rename(m_filename.c_str(), (m_filename + time_str).c_str());
00262       }
00263 
00264       // Delete old log files.
00265       if (m_delete_old_files)
00266       {
00267 #if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2
00268         boost::filesystem::path log_file_path = boost::filesystem::path(m_filename).branch_path();
00269         std::string log_file_name = boost::filesystem::path(m_filename).leaf();
00270 #else
00271         boost::filesystem::path log_file_path = boost::filesystem::path(m_filename).parent_path();
00272         std::string log_file_name = boost::filesystem::path(m_filename).filename().string();
00273 #endif
00274         if (boost::filesystem::exists(log_file_path) && boost::filesystem::is_directory(log_file_path))
00275         {
00276           icl_core::TimeStamp delete_older_than(24*3600*(current_day - m_delete_older_than_days));
00277           for (boost::filesystem::directory_iterator it(log_file_path), end; it != end; ++it)
00278           {
00279             // If the found file starts with the name of the log file the check its last write time.
00280             if (!is_directory(*it)
00281                 && icl_core::TimeStamp(boost::filesystem::last_write_time(*it)) < delete_older_than
00282 #if !defined(BOOST_FILESYSTEM_VERSION) || BOOST_FILESYSTEM_VERSION == 2
00283                 && it->leaf().find(log_file_name) == 0
00284 #else
00285                 && it->path().filename().string().find(log_file_name) == 0
00286 #endif
00287                 )
00288             {
00289               boost::filesystem::remove(*it);
00290             }
00291           }
00292         }
00293       }
00294 
00295       // Store the rotation time.
00296       m_last_rotation = current_day;
00297 
00298       // Re-open the log file.
00299       openLogFile();
00300     }
00301   }
00302 }
00303 
00304 void FileLogOutput::expandFilename()
00305 {
00306   // Expand environment variables.
00307 #if defined(_SYSTEM_POSIX_) && !defined(__ANDROID__)
00308   wordexp_t p;
00309   if (wordexp(m_filename.c_str(), &p, 0) == 0)
00310   {
00311     if (p.we_wordc > 0)
00312     {
00313       m_filename = p.we_wordv[0];
00314     }
00315   }
00316   //wordfree(&p);
00317 #elif defined(_SYSTEM_WIN32_)
00318   // TODO: Implement this with ExpandEnvironmenStrings()
00319 #endif
00320 }
00321 
00322 }
00323 }


fzi_icl_core
Author(s):
autogenerated on Tue Aug 8 2017 02:28:03