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


schunk_svh_driver
Author(s): Georg Heppner
autogenerated on Fri Aug 28 2015 12:59:18