FileAppender.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2004 Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2005 Novell, Inc. All rights reserved.
00004 *
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 *
00008 *  - Redistributions of source code must retain the above copyright notice,
00009 *    this list of conditions and the following disclaimer.
00010 *
00011 *  - Redistributions in binary form must reproduce the above copyright notice,
00012 *    this list of conditions and the following disclaimer in the documentation
00013 *    and/or other materials provided with the distribution.
00014 *
00015 *  - Neither the name of Vintela, Inc., Novell, Inc., nor the names of its
00016 *    contributors may be used to endorse or promote products derived from this
00017 *    software without specific prior written permission.
00018 *
00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc., Novell, Inc., OR THE 
00023 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00024 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00025 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00026 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00027 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00028 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00029 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 *******************************************************************************/
00031 
00032 
00037 #include "blocxx/BLOCXX_config.h"
00038 #include "blocxx/FileAppender.hpp"
00039 #include "blocxx/Format.hpp"
00040 #include "blocxx/Logger.hpp"
00041 #include "blocxx/LogMessage.hpp"
00042 #include "blocxx/Mutex.hpp"
00043 #include "blocxx/MutexLock.hpp"
00044 #include "blocxx/FileSystem.hpp"
00045 
00046 #include <fstream>
00047 
00048 namespace BLOCXX_NAMESPACE
00049 {
00050 
00052 FileAppender::FileAppender(const StringArray& components,
00053    const StringArray& categories,
00054    const char* filename,
00055    const String& pattern,
00056    UInt64 maxFileSize,
00057    unsigned int maxBackupIndex,
00058    bool flushLog)
00059    : LogAppender(components, categories, pattern)
00060    , m_filename(filename)
00061    , m_maxFileSize(maxFileSize)
00062    , m_maxBackupIndex(maxBackupIndex)
00063    , m_flushLog(flushLog)
00064 {
00065    m_log.open(m_filename.c_str(), std::ios::out | std::ios::app);
00066    if (!m_log)
00067    {
00068       BLOCXX_THROW(LoggerException, Format("FileAppender: Unable to open file: %1", m_filename).toString().c_str() );
00069    }
00070 }
00071 
00073 FileAppender::~FileAppender()
00074 {
00075 }
00076 
00078 namespace
00079 {
00080    Mutex fileGuard;
00081 }
00082 void
00083 FileAppender::doProcessLogMessage(const String& formattedMessage, const LogMessage& message) const
00084 {
00085    MutexLock lock(fileGuard);
00086 
00087    // take into account external log rotators, if the file we have open no longer exists, then reopen it.
00088    if (!FileSystem::exists(m_filename.c_str()))
00089    {
00090       m_log.close();
00091       m_log.open(m_filename.c_str(), std::ios::out | std::ios::app);
00092    }
00093 
00094    if (!m_log)
00095    {
00096       // hmm, not much we can do here.  doProcessLogMessage can't throw.
00097       return;
00098    }
00099 
00100    m_log.write(formattedMessage.c_str(), formattedMessage.length());
00101    m_log << '\n';
00102 
00103    if (m_flushLog)
00104    {
00105       m_log.flush();
00106    }
00107 
00108    // handle log rotation
00109    if (m_maxFileSize != NO_MAX_LOG_SIZE && m_log.tellp() >= static_cast<std::streampos>(m_maxFileSize * 1024))
00110    {
00111       // since we can't throw an exception, or log any errors, it something fails here, we'll just return silently :-(
00112 
00113       // do the roll over
00114       m_log.close();
00115 
00116       if (m_maxBackupIndex > 0)
00117       {
00118          // delete the oldest file first - this may or may not exist, we try anyway.
00119          FileSystem::removeFile(m_filename + '.' + String(m_maxBackupIndex));
00120 
00121          // increment the numbers on all the files - some may exist or not, but try anyway.
00122          for (unsigned int i = m_maxBackupIndex - 1; i >= 1; --i)
00123          {
00124             FileSystem::renameFile(m_filename + '.' + String(i), m_filename + '.' + String(i + 1));
00125          }
00126 
00127          if (!FileSystem::renameFile(m_filename, m_filename + ".1"))
00128          {
00129             // if we can't rename it, avoid truncating it.
00130             return;
00131          }
00132       }
00133 
00134       // truncate the existing one
00135       m_log.open(m_filename.c_str(), std::ios_base::out | std::ios_base::trunc);
00136    }
00137 }
00138 
00140 const String FileAppender::STR_DEFAULT_MESSAGE_PATTERN("%d{%a %b %d %H:%M:%S %Y} [%t]: %m");
00141 
00142 } // end namespace BLOCXX_NAMESPACE
00143 
00144 
00145 
00146 

Generated on Fri Jun 16 15:39:08 2006 for blocxx by  doxygen 1.4.6