1 // -*- C++ -*-
2 // Module:  Log4CPLUS
3 // File:    fileap.h
4 // Created: 6/2001
5 // Author:  Tad E. Smith
6 //
7 //
8 // Copyright 2001-2010 Tad E. Smith
9 //
10 // Licensed under the Apache License, Version 2.0 (the "License");
11 // you may not use this file except in compliance with the License.
12 // You may obtain a copy of the License at
13 //
14 //     http://www.apache.org/licenses/LICENSE-2.0
15 //
16 // Unless required by applicable law or agreed to in writing, software
17 // distributed under the License is distributed on an "AS IS" BASIS,
18 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 // See the License for the specific language governing permissions and
20 // limitations under the License.
21 
22 /** @file */
23 
24 #ifndef DCMTK_LOG4CPLUS_FILE_APPENDER_HEADER_
25 #define DCMTK_LOG4CPLUS_FILE_APPENDER_HEADER_
26 
27 #include "dcmtk/oflog/config.h"
28 
29 #if defined (DCMTK_LOG4CPLUS_HAVE_PRAGMA_ONCE)
30 #pragma once
31 #endif
32 
33 #include "dcmtk/oflog/appender.h"
34 #include "dcmtk/oflog/fstreams.h"
35 #include "dcmtk/oflog/helpers/timehelp.h"
36 #include "dcmtk/oflog/helpers/lockfile.h"
37 #include <fstream>
38 #include <locale>
39 #include <memory>
40 
41 
42 namespace dcmtk
43 {
44 namespace log4cplus
45 {
46 
47     /**
48      * Appends log events to a file.
49      *
50      * <h3>Properties</h3>
51      * <dl>
52      * <dt><tt>File</tt></dt>
53      * <dd>This property specifies output file name.</dd>
54      *
55      * <dt><tt>ImmediateFlush</tt></dt>
56      * <dd>When it is set true, output stream will be flushed after
57      * each appended event.</dd>
58      *
59      * <dt><tt>Append</tt></dt>
60      * <dd>When it is set true, output file will be appended to
61      * instead of being truncated at opening.</dd>
62      *
63      * <dt><tt>ReopenDelay</tt></dt>
64      * <dd>This property sets a delay after which the appender will try
65      * to reopen log file again, after last logging failure.
66      * </dd>
67      *
68      * <dt><tt>BufferSize</tt></dt>
69      * <dd>Non-zero value of this property sets up buffering of output
70      * stream using a buffer of given size.
71      * </dd>
72      *
73      * <dt><tt>UseLockFile</tt></dt>
74      * <dd>Set this property to <tt>true</tt> if you want your output
75      * to go into a log file shared by multiple processes. When this
76      * property is set to true then log4cplus uses OS specific
77      * facilities (e.g., <code>lockf()</code>) to provide
78      * inter-process file locking.
79      * \sa Appender
80      * </dd>
81      *
82      * <dt><tt>LockFile</tt></dt>
83      * <dd>This property specifies lock file, file used for
84      * inter-process synchronization of log file access. When this
85      * property is not specified, the value is derived from
86      * <tt>File</tt> property by addition of ".lock" suffix. The
87      * property is only used when <tt>UseLockFile</tt> is set to true.
88      * \sa Appender
89      * </dd>
90      *
91      * <dt><tt>Locale</tt></dt>
92      * <dd>This property specifies a locale name that will be imbued
93      * into output stream. Locale can be specified either by system
94      * specific locale name, e.g., <tt>en_US.UTF-8</tt>, or by one of
95      * four recognized keywords: <tt>GLOBAL</tt>, <tt>DEFAULT</tt>
96      * (which is an alias for <tt>GLOBAL</tt>), <tt>USER</tt> and
97      * <tt>CLASSIC</tt>. When specified locale is not available,
98      * <tt>GLOBAL</tt> is used instead. It is possible to register
99      * additional locale keywords by registering an instance of
100      * <code>spi::LocaleFactory</code> in
101      * <code>spi::LocaleFactoryRegistry</code>.
102      * \sa spi::getLocaleFactoryRegistry()
103      * </dd>
104      *
105      * </dl>
106      */
107     class DCMTK_LOG4CPLUS_EXPORT FileAppender : public Appender {
108     public:
109       // Ctors
110         FileAppender(const log4cplus::tstring& filename,
111                      STD_NAMESPACE ios_base::openmode mode = STD_NAMESPACE ios_base::trunc,
112                      bool immediateFlush = true);
113         FileAppender(const log4cplus::helpers::Properties& properties,
114                      STD_NAMESPACE ios_base::openmode mode = STD_NAMESPACE ios_base::trunc);
115 
116       // Dtor
117         virtual ~FileAppender();
118 
119       // Methods
120         virtual void close();
121 
122       //! Redefine default locale for output stream. It may be a good idea to
123       //! provide UTF-8 locale in case UNICODE macro is defined.
124         virtual STD_NAMESPACE locale imbue(STD_NAMESPACE locale const& loc);
125 
126       //! \returns Locale imbued in fstream.
127         virtual STD_NAMESPACE locale getloc () const;
128 
129     protected:
130         virtual void append(const spi::InternalLoggingEvent& event);
131 
132         void open(STD_NAMESPACE ios_base::openmode mode);
133         bool reopen();
134 
135       // Data
136         /**
137          * Immediate flush means that the underlying writer or output stream
138          * will be flushed at the end of each append operation. Immediate
139          * flush is slower but ensures that each append request is actually
140          * written. If <code>immediateFlush</code> is set to
141          * <code>false</code>, then there is a good chance that the last few
142          * logs events are not actually written to persistent media if and
143          * when the application crashes.
144          *
145          * The <code>immediateFlush</code> variable is set to
146          * <code>true</code> by default.
147          */
148         bool immediateFlush;
149 
150         /**
151          * When any append operation fails, <code>reopenDelay</code> says
152          * for how many seconds the next attempt to re-open the log file and
153          * resume logging will be delayed. If <code>reopenDelay</code> is zero,
154          * each failed append operation will cause log file to be re-opened.
155          * By default, <code>reopenDelay</code> is 1 second.
156          */
157         int reopenDelay;
158 
159         unsigned long bufferSize;
160         log4cplus::tchar * buffer;
161 
162         log4cplus::tofstream out;
163         log4cplus::tstring filename;
164         log4cplus::tstring localeName;
165 
166         log4cplus::helpers::Time reopen_time;
167 
168     private:
169         DCMTK_LOG4CPLUS_PRIVATE void init(const log4cplus::tstring& filename,
170             STD_NAMESPACE ios_base::openmode mode,
171             const log4cplus::tstring& lockFileName);
172 
173       // Disallow copying of instances of this class
174         FileAppender(const FileAppender&);
175         FileAppender& operator=(const FileAppender&);
176     };
177 
178 
179 
180     /**
181      * RollingFileAppender extends FileAppender to backup the log
182      * files when they reach a certain size.
183      *
184      * <h3>Properties</h3>
185      * <p>Properties additional to {@link FileAppender}'s properties:
186      *
187      * <dl>
188      * <dt><tt>MaxFileSize</tt></dt>
189      * <dd>This property specifies maximal size of output file. The
190      * value is in bytes. It is possible to use <tt>MB</tt> and
191      * <tt>KB</tt> suffixes to specify the value in megabytes or
192      * kilobytes instead.</dd>
193      *
194      * <dt><tt>MaxBackupIndex</tt></dt>
195      * <dd>This property limits the number of backup output
196      * files; e.g. how many <tt>log.1</tt>, <tt>log.2</tt> etc. files
197      * will be kept.</dd>
198      * </dl>
199      */
200     class DCMTK_LOG4CPLUS_EXPORT RollingFileAppender : public FileAppender {
201     public:
202       // Ctors
203         RollingFileAppender(const log4cplus::tstring& filename,
204                             long maxFileSize = 10*1024*1024, // 10 MB
205                             int maxBackupIndex = 1,
206                             bool immediateFlush = true);
207         RollingFileAppender(const log4cplus::helpers::Properties& properties);
208 
209       // Dtor
210         virtual ~RollingFileAppender();
211 
212     protected:
213         virtual void append(const spi::InternalLoggingEvent& event);
214         void rollover(bool alreadyLocked = false);
215 
216       // Data
217         long maxFileSize;
218         int maxBackupIndex;
219 
220     private:
221         DCMTK_LOG4CPLUS_PRIVATE void init(long maxFileSize, int maxBackupIndex);
222     };
223 
224 
225 
226     enum DailyRollingFileSchedule { MONTHLY, WEEKLY, DAILY,
227                                     TWICE_DAILY, HOURLY, MINUTELY};
228 
229     /**
230      * DailyRollingFileAppender extends {@link FileAppender} so that the
231      * underlying file is rolled over at a user chosen frequency.
232      *
233      * <h3>Properties</h3>
234      * <p>Properties additional to {@link FileAppender}'s properties:
235      *
236      * <dl>
237      * <dt><tt>Schedule</tt></dt>
238      * <dd>This property specifies rollover schedule. The possible
239      * values are <tt>MONTHLY</tt>, <tt>WEEKLY</tt>, <tt>DAILY</tt>,
240      * <tt>TWICE_DAILY</tt>, <tt>HOURLY</tt> and
241      * <tt>MINUTELY</tt>.</dd>
242      *
243      * <dt><tt>MaxBackupIndex</tt></dt>
244      * <dd>This property limits how many backup files are kept per
245      * single logging period; e.g. how many <tt>log.2009-11-07.1</tt>,
246      * <tt>log.2009-11-07.2</tt> etc. files are kept.</dd>
247      *
248      * </dl>
249      */
250     class DCMTK_LOG4CPLUS_EXPORT DailyRollingFileAppender : public FileAppender {
251     public:
252       // Ctors
253         DailyRollingFileAppender(const log4cplus::tstring& filename,
254                                  DailyRollingFileSchedule schedule = DAILY,
255                                  bool immediateFlush = true,
256                                  int maxBackupIndex = 10);
257         DailyRollingFileAppender(const log4cplus::helpers::Properties& properties);
258 
259       // Dtor
260         virtual ~DailyRollingFileAppender();
261 
262       // Methods
263         virtual void close();
264 
265     protected:
266         virtual void append(const spi::InternalLoggingEvent& event);
267         void rollover(bool alreadyLocked = false);
268         log4cplus::helpers::Time calculateNextRolloverTime(const log4cplus::helpers::Time& t) const;
269         log4cplus::tstring getFilename(const log4cplus::helpers::Time& t) const;
270 
271       // Data
272         DailyRollingFileSchedule schedule;
273         log4cplus::tstring scheduledFilename;
274         log4cplus::helpers::Time nextRolloverTime;
275         int maxBackupIndex;
276 
277     private:
278         DCMTK_LOG4CPLUS_PRIVATE void init(DailyRollingFileSchedule schedule);
279     };
280 
281 } // end namespace log4cplus
282 } // end namespace dcmtk
283 
284 #endif // DCMTK_LOG4CPLUS_FILE_APPENDER_HEADER_
285 
286