NCBI C++ Toolkit Cross Reference

C++/src/util/logrotate.cpp


  1 /*  $Id: logrotate.cpp 103491 2007-05-04 17:18:18Z kazimird $
  2 * ===========================================================================
  3 *
  4 *                            PUBLIC DOMAIN NOTICE
  5 *               National Center for Biotechnology Information
  6 *
  7 *  This software/database is a "United States Government Work" under the
  8 *  terms of the United States Copyright Act.  It was written as part of
  9 *  the author's official duties as a United States Government employee and
 10 *  thus cannot be copyrighted.  This software/database is freely available
 11 *  to the public for use. The National Library of Medicine and the U.S.
 12 *  Government have not placed any restriction on its use or reproduction.
 13 *
 14 *  Although all reasonable efforts have been taken to ensure the accuracy
 15 *  and reliability of the software and data, the NLM and the U.S.
 16 *  Government do not and cannot warrant the performance or results that
 17 *  may be obtained by using this software or data. The NLM and the U.S.
 18 *  Government disclaim all warranties, express or implied, including
 19 *  warranties of performance, merchantability or fitness for any particular
 20 *  purpose.
 21 *
 22 *  Please cite the author in any work or product based on this material.
 23 *
 24 * ===========================================================================
 25 *
 26 * Author:  Aaron Ucko, NCBI
 27 *
 28 * File Description:
 29 *   File streams supporting log rotation
 30 *
 31 * ===========================================================================
 32 */
 33 
 34 #include <ncbi_pch.hpp>
 35 #include <util/logrotate.hpp>
 36 #include <corelib/ncbifile.hpp>
 37 
 38 BEGIN_NCBI_SCOPE
 39 
 40 class CRotatingLogStreamBuf : public CNcbiFilebuf {
 41 public:
 42     CRotatingLogStreamBuf(CRotatingLogStream* stream, const string& filename,
 43                           CNcbiStreamoff limit, IOS_BASE::openmode mode);
 44     CNcbiStreamoff Rotate(void); // returns number of bytes in old log
 45 
 46 protected:
 47     virtual CT_INT_TYPE overflow(CT_INT_TYPE c = CT_EOF);
 48     virtual int sync(void);
 49 
 50 private:
 51     CRotatingLogStream* m_Stream;
 52     string              m_FileName;
 53     CNcbiStreampos      m_Size;
 54     CNcbiStreamoff      m_Limit; // in bytes
 55     IOS_BASE::openmode  m_Mode;
 56 };
 57 
 58 
 59 CRotatingLogStreamBuf::CRotatingLogStreamBuf(CRotatingLogStream* stream,
 60                                              const string&       filename,
 61                                              CT_OFF_TYPE         limit,
 62                                              IOS_BASE::openmode  mode)
 63     : m_Stream(stream),
 64       m_FileName(filename),
 65       m_Size(0),
 66       m_Limit(limit),
 67       m_Mode(mode)
 68 {
 69     open(m_FileName.c_str(), m_Mode);
 70     m_Size = seekoff(0, IOS_BASE::cur, IOS_BASE::out);
 71 }
 72 
 73 
 74 CNcbiStreamoff CRotatingLogStreamBuf::Rotate(void)
 75 {
 76     CNcbiStreampos old_size = m_Size;
 77     close();
 78     string old_name = m_FileName; // Copy in case x_BackupName mutates.
 79     string new_name = m_Stream->x_BackupName(m_FileName);
 80     if ( !new_name.empty() ) {
 81         CFile(new_name).Remove();
 82         CFile(old_name).Rename(new_name);
 83     }
 84     open(m_FileName.c_str(), m_Mode);
 85     m_Size = seekoff(0, IOS_BASE::cur, IOS_BASE::out);
 86     return m_Size - old_size;
 87 }
 88 
 89 
 90 // The use of new_size in overflow and sync is to avoid
 91 // double-counting when one calls the other.  (Which, if either, is
 92 // actually lower-level seems to vary with compiler.)
 93 
 94 CT_INT_TYPE CRotatingLogStreamBuf::overflow(CT_INT_TYPE c)
 95 {
 96     // The only operators CNcbiStreampos reliably seems to support
 97     // are += and -=, so stick to those. :-/
 98     CNcbiStreampos new_size = m_Size, old_size = m_Size;
 99     new_size += pptr() - pbase();
100     if ( !CT_EQ_INT_TYPE(c, CT_EOF) ) {
101         new_size += 1;
102     }
103     // Perform output first, in case switching files discards data.
104     CT_INT_TYPE result = CNcbiFilebuf::overflow(c);
105     if (m_Size - old_size < 0) {
106         return result; // assume filebuf::overflow called Rotate via sync.
107     }
108     // Don't assume the buffer's actually empty; some implementations
109     // seem to handle the case of pptr() being null by setting the
110     // pointers and writing c to the buffer but not actually flushing
111     // it to disk. :-/
112     new_size -= pptr() - pbase();
113     m_Size = new_size;
114     // Hold off on rotating logs until actually producing new output
115     // (even if they were already overdue for rotation), to avoid a
116     // possible recursive double-rotation scenario.
117     if (m_Size - CNcbiStreampos(0) >= m_Limit  &&  m_Size != old_size) {
118         Rotate();
119     }
120     return result;
121 }
122 
123 
124 int CRotatingLogStreamBuf::sync(void)
125 {
126     // Perform output first, in case switching files discards data.
127     CNcbiStreampos new_size = m_Size, old_size = m_Size;
128     new_size += pptr() - pbase();
129     int result = CNcbiFilebuf::sync();
130     if (m_Size - old_size < 0) {
131         return result; // assume filebuf::sync called Rotate via overflow.
132     }
133     // pptr() ought to equal pbase() now, but just in case...
134     new_size -= pptr() - pbase();
135     m_Size = new_size;
136     // Hold off on rotating logs until actually producing new output.
137     if (m_Size - CNcbiStreampos(0) >= m_Limit  &&  m_Size != old_size) {
138         Rotate();
139     }
140     return result;
141 }
142 
143 
144 
145 CRotatingLogStream::CRotatingLogStream(const string& filename,
146                                        CNcbiStreamoff limit, openmode mode)
147     : CNcbiOstream(new CRotatingLogStreamBuf(this, filename, limit, mode))
148 {
149 }
150 
151 CRotatingLogStream::~CRotatingLogStream()
152 {
153     delete rdbuf();
154 }
155 
156 
157 CNcbiStreamoff CRotatingLogStream::Rotate(void)
158 {
159     flush();
160     return dynamic_cast<CRotatingLogStreamBuf*>(rdbuf())->Rotate();
161 }
162 
163 
164 string CRotatingLogStream::x_BackupName(string& name)
165 {
166 #if defined(NCBI_OS_UNIX) && !defined(NCBI_OS_CYGWIN)
167     return name + CurrentTime().AsString(".Y-M-D-Z-h:m:s");
168 #else
169     // Colons are special; avoid them.
170     return name + CurrentTime().AsString(".Y-M-D-Z-h-m-s");
171 #endif
172 }
173 
174 
175 END_NCBI_SCOPE
176 

source navigation ]   [ diff markup ]   [ identifier search ]   [ freetext search ]   [ file search ]  

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.