~ubuntu-branches/ubuntu/gutsy/poco/gutsy

« back to all changes in this revision

Viewing changes to Foundation/src/FileChannel.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Krzysztof Burghardt
  • Date: 2007-04-27 18:33:48 UTC
  • Revision ID: james.westby@ubuntu.com-20070427183348-xgnpct0qd6a2ip34
Tags: upstream-1.2.9
ImportĀ upstreamĀ versionĀ 1.2.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// FileChannel.cpp
 
3
//
 
4
// $Id: //poco/1.2/Foundation/src/FileChannel.cpp#2 $
 
5
//
 
6
// Library: Foundation
 
7
// Package: Logging
 
8
// Module:  FileChannel
 
9
//
 
10
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
 
11
// and Contributors.
 
12
//
 
13
// Permission is hereby granted, free of charge, to any person or organization
 
14
// obtaining a copy of the software and accompanying documentation covered by
 
15
// this license (the "Software") to use, reproduce, display, distribute,
 
16
// execute, and transmit the Software, and to prepare derivative works of the
 
17
// Software, and to permit third-parties to whom the Software is furnished to
 
18
// do so, all subject to the following:
 
19
// 
 
20
// The copyright notices in the Software and this entire statement, including
 
21
// the above license grant, this restriction and the following disclaimer,
 
22
// must be included in all copies of the Software, in whole or in part, and
 
23
// all derivative works of the Software, unless such copies or derivative
 
24
// works are solely in the form of machine-executable object code generated by
 
25
// a source language processor.
 
26
// 
 
27
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
28
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
29
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 
30
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 
31
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 
32
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
33
// DEALINGS IN THE SOFTWARE.
 
34
//
 
35
 
 
36
 
 
37
#include "Poco/FileChannel.h"
 
38
#include "Poco/ArchiveStrategy.h"
 
39
#include "Poco/RotateStrategy.h"
 
40
#include "Poco/PurgeStrategy.h"
 
41
#include "Poco/Message.h"
 
42
#include "Poco/NumberParser.h"
 
43
#include "Poco/DateTimeFormatter.h"
 
44
#include "Poco/DateTime.h"
 
45
#include "Poco/LocalDateTime.h"
 
46
#include "Poco/String.h"
 
47
#include "Poco/Timespan.h"
 
48
#include "Poco/Exception.h"
 
49
#include <ctype.h>
 
50
 
 
51
 
 
52
namespace Poco {
 
53
 
 
54
 
 
55
const std::string FileChannel::PROP_PATH       = "path";
 
56
const std::string FileChannel::PROP_ROTATION   = "rotation";
 
57
const std::string FileChannel::PROP_ARCHIVE    = "archive";
 
58
const std::string FileChannel::PROP_TIMES      = "times";
 
59
const std::string FileChannel::PROP_COMPRESS   = "compress";
 
60
const std::string FileChannel::PROP_PURGEAGE   = "purgeAge";
 
61
const std::string FileChannel::PROP_PURGECOUNT = "purgeCount";
 
62
 
 
63
 
 
64
FileChannel::FileChannel(): 
 
65
        _times("utc"),
 
66
        _compress(false),
 
67
        _pFile(0),
 
68
        _pRotateStrategy(0),
 
69
        _pArchiveStrategy(new ArchiveByNumberStrategy),
 
70
        _pPurgeStrategy(0)
 
71
{
 
72
}
 
73
 
 
74
 
 
75
FileChannel::FileChannel(const std::string& path):
 
76
        _path(path),
 
77
        _times("utc"),
 
78
        _compress(false),
 
79
        _pFile(0),
 
80
        _pRotateStrategy(0),
 
81
        _pArchiveStrategy(new ArchiveByNumberStrategy),
 
82
        _pPurgeStrategy(0)
 
83
{
 
84
}
 
85
 
 
86
 
 
87
FileChannel::~FileChannel()
 
88
{
 
89
        close();
 
90
        delete _pRotateStrategy;
 
91
        delete _pArchiveStrategy;
 
92
        delete _pPurgeStrategy;
 
93
}
 
94
 
 
95
 
 
96
void FileChannel::open()
 
97
{
 
98
        FastMutex::ScopedLock lock(_mutex);
 
99
        
 
100
        if (!_pFile)
 
101
        {
 
102
                _pFile = new LogFile(_path);
 
103
        }
 
104
}
 
105
 
 
106
 
 
107
void FileChannel::close()
 
108
{
 
109
        FastMutex::ScopedLock lock(_mutex);
 
110
 
 
111
        delete _pFile;
 
112
        _pFile = 0;
 
113
}
 
114
 
 
115
 
 
116
void FileChannel::log(const Message& msg)
 
117
{
 
118
        open();
 
119
 
 
120
        FastMutex::ScopedLock lock(_mutex);
 
121
 
 
122
        if (_pRotateStrategy && _pArchiveStrategy && _pRotateStrategy->mustRotate(_pFile))
 
123
        {
 
124
                try
 
125
                {
 
126
                        _pFile = _pArchiveStrategy->archive(_pFile);
 
127
                        purge();
 
128
                }
 
129
                catch (...)
 
130
                {
 
131
                        _pFile = new LogFile(_path);
 
132
                }
 
133
        }
 
134
        _pFile->write(msg.getText());
 
135
}
 
136
 
 
137
        
 
138
void FileChannel::setProperty(const std::string& name, const std::string& value)
 
139
{
 
140
        FastMutex::ScopedLock lock(_mutex);
 
141
 
 
142
        if (name == PROP_TIMES)
 
143
        {
 
144
                _times = value;
 
145
 
 
146
                if (!_rotation.empty())
 
147
                        setRotation(_rotation);
 
148
 
 
149
                if (!_archive.empty())
 
150
                        setArchive(_archive);
 
151
        }
 
152
        else if (name == PROP_PATH)
 
153
                _path = value;
 
154
        else if (name == PROP_ROTATION)
 
155
                setRotation(value);
 
156
        else if (name == PROP_ARCHIVE)
 
157
                setArchive(value);
 
158
        else if (name == PROP_COMPRESS)
 
159
                setCompress(value);
 
160
        else if (name == PROP_PURGEAGE)
 
161
                setPurgeAge(value);
 
162
        else if (name == PROP_PURGECOUNT)
 
163
                setPurgeCount(value);
 
164
        else
 
165
                Channel::setProperty(name, value);
 
166
}
 
167
 
 
168
 
 
169
std::string FileChannel::getProperty(const std::string& name) const
 
170
{
 
171
        if (name == PROP_TIMES)
 
172
                return _times;
 
173
        else if (name == PROP_PATH)
 
174
                return _path;
 
175
        else if (name == PROP_ROTATION)
 
176
                return _rotation;
 
177
        else if (name == PROP_ARCHIVE)
 
178
                return _archive;
 
179
        else if (name == PROP_COMPRESS)
 
180
                return std::string(_compress ? "true" : "false");
 
181
        else if (name == PROP_PURGEAGE)
 
182
                return _purgeAge;
 
183
        else if (name == PROP_PURGECOUNT)
 
184
                return _purgeCount;
 
185
        else
 
186
                return Channel::getProperty(name);
 
187
}
 
188
 
 
189
 
 
190
Timestamp FileChannel::creationDate() const
 
191
{
 
192
        if (_pFile)
 
193
                return _pFile->creationDate();
 
194
        else
 
195
                return 0;
 
196
}
 
197
 
 
198
        
 
199
UInt64 FileChannel::size() const
 
200
{
 
201
        if (_pFile)
 
202
                return _pFile->size();
 
203
        else
 
204
                return 0;
 
205
}
 
206
 
 
207
 
 
208
const std::string& FileChannel::path() const
 
209
{
 
210
        return _path;
 
211
}
 
212
 
 
213
 
 
214
void FileChannel::setRotation(const std::string& rotation)
 
215
{
 
216
        std::string::const_iterator it  = rotation.begin();
 
217
        std::string::const_iterator end = rotation.end();
 
218
        int n = 0;
 
219
        while (it != end && isspace(*it)) ++it;
 
220
        while (it != end && isdigit(*it)) { n *= 10; n += *it++ - '0'; }
 
221
        while (it != end && isspace(*it)) ++it;
 
222
        std::string unit;
 
223
        while (it != end && isalpha(*it)) unit += *it++;
 
224
        
 
225
        RotateStrategy* pStrategy = 0;
 
226
        if ((rotation.find(',') != std::string::npos) || (rotation.find(':') != std::string::npos))
 
227
        {
 
228
                if (_times == "utc")
 
229
                        pStrategy = new RotateAtTimeStrategy<DateTime>(rotation);
 
230
                else if (_times == "local")
 
231
                        pStrategy = new RotateAtTimeStrategy<LocalDateTime>(rotation);
 
232
                else
 
233
                        throw PropertyNotSupportedException("times", _times);
 
234
        }
 
235
        else if (unit == "daily")
 
236
                pStrategy = new RotateByIntervalStrategy(Timespan(1*Timespan::DAYS));
 
237
        else if (unit == "weekly")
 
238
                pStrategy = new RotateByIntervalStrategy(Timespan(7*Timespan::DAYS));
 
239
        else if (unit == "monthly")
 
240
                pStrategy = new RotateByIntervalStrategy(Timespan(30*Timespan::DAYS));
 
241
        else if (unit == "seconds") // for testing only
 
242
                pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::SECONDS));
 
243
        else if (unit == "hours")
 
244
                pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::HOURS));
 
245
        else if (unit == "days")
 
246
                pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::DAYS));
 
247
        else if (unit == "weeks")
 
248
                pStrategy = new RotateByIntervalStrategy(Timespan(n*7*Timespan::DAYS));
 
249
        else if (unit == "months")
 
250
                pStrategy = new RotateByIntervalStrategy(Timespan(n*30*Timespan::DAYS));
 
251
        else if (unit == "K")
 
252
                pStrategy = new RotateBySizeStrategy(n*1024);
 
253
        else if (unit == "M")
 
254
                pStrategy = new RotateBySizeStrategy(n*1024*1024);
 
255
        else if (unit.empty())
 
256
                pStrategy = new RotateBySizeStrategy(n);
 
257
        else if (unit != "never")
 
258
                throw InvalidArgumentException("rotation", rotation);
 
259
        delete _pRotateStrategy;
 
260
        _pRotateStrategy = pStrategy;
 
261
        _rotation = rotation;
 
262
}
 
263
 
 
264
 
 
265
void FileChannel::setArchive(const std::string& archive)
 
266
{
 
267
        ArchiveStrategy* pStrategy = 0;
 
268
        if (archive == "number")
 
269
        {
 
270
                pStrategy = new ArchiveByNumberStrategy;
 
271
        }
 
272
        else if (archive == "timestamp")
 
273
        {
 
274
                if (_times == "utc")
 
275
                        pStrategy = new ArchiveByTimestampStrategy<DateTime>;
 
276
                else if (_times == "local")
 
277
                        pStrategy = new ArchiveByTimestampStrategy<LocalDateTime>;
 
278
                else
 
279
                        throw PropertyNotSupportedException("times", _times);
 
280
        }
 
281
        else throw InvalidArgumentException("archive", archive);
 
282
        delete _pArchiveStrategy;
 
283
        pStrategy->compress(_compress);
 
284
        _pArchiveStrategy = pStrategy;
 
285
        _archive = archive;
 
286
}
 
287
 
 
288
 
 
289
void FileChannel::setCompress(const std::string& compress)
 
290
{
 
291
        _compress = icompare(compress, "true") == 0;
 
292
        if (_pArchiveStrategy)
 
293
                _pArchiveStrategy->compress(_compress);
 
294
}
 
295
 
 
296
 
 
297
void FileChannel::setPurgeAge(const std::string& age)
 
298
{
 
299
        std::string::const_iterator it  = age.begin();
 
300
        std::string::const_iterator end = age.end();
 
301
        int n = 0;
 
302
        while (it != end && isspace(*it)) ++it;
 
303
        while (it != end && isdigit(*it)) { n *= 10; n += *it++ - '0'; }
 
304
        while (it != end && isspace(*it)) ++it;
 
305
        std::string unit;
 
306
        while (it != end && isalpha(*it)) unit += *it++;
 
307
        
 
308
        Timespan::TimeDiff factor = Timespan::SECONDS;
 
309
        if (unit == "minutes")
 
310
                factor = Timespan::MINUTES;
 
311
        else if (unit == "hours")
 
312
                factor = Timespan::HOURS;
 
313
        else if (unit == "days")
 
314
                factor = Timespan::DAYS;
 
315
        else if (unit == "weeks")
 
316
                factor = 7*Timespan::DAYS;
 
317
        else if (unit == "months")
 
318
                factor = 30*Timespan::DAYS;
 
319
        else if (unit != "seconds")
 
320
                throw InvalidArgumentException("purgeAge", age);
 
321
                
 
322
        delete _pPurgeStrategy;
 
323
        _pPurgeStrategy = new PurgeByAgeStrategy(Timespan(factor*n));
 
324
        _purgeAge = age;
 
325
}
 
326
 
 
327
 
 
328
void FileChannel::setPurgeCount(const std::string& count)
 
329
{
 
330
        std::string::const_iterator it  = count.begin();
 
331
        std::string::const_iterator end = count.end();
 
332
        int n = 0;
 
333
        while (it != end && isspace(*it)) ++it;
 
334
        while (it != end && isdigit(*it)) { n *= 10; n += *it++ - '0'; }
 
335
        while (it != end && isspace(*it)) ++it;
 
336
 
 
337
        delete _pPurgeStrategy;
 
338
        _pPurgeStrategy = new PurgeByCountStrategy(n);
 
339
        _purgeCount = count;
 
340
}
 
341
 
 
342
 
 
343
void FileChannel::purge()
 
344
{
 
345
        if (_pPurgeStrategy)
 
346
        {
 
347
                try
 
348
                {
 
349
                        _pPurgeStrategy->purge(_path);
 
350
                }
 
351
                catch (...)
 
352
                {
 
353
                }
 
354
        }
 
355
}
 
356
 
 
357
 
 
358
} // namespace Poco