- Poco::FileChannel now supports a new rotateOnOpen property (true/false) which can be used

to force rotation of the log file when it's opened.
This commit is contained in:
Guenter Obiltschnig 2012-11-10 11:55:54 +01:00
parent 4f66c0e1d8
commit b402881343
2 changed files with 98 additions and 90 deletions

View File

@ -1,7 +1,7 @@
//
// FileChannel.h
//
// $Id: //poco/1.4/Foundation/include/Poco/FileChannel.h#2 $
// $Id: //poco/1.4/Foundation/include/Poco/FileChannel.h#5 $
//
// Library: Foundation
// Package: Logging
@ -140,7 +140,7 @@ class Foundation_API FileChannel: public Channel
/// * local: Rotation strategy is based on local time.
///
/// Archived log files can be compressed using the gzip compression
/// method. Compressing can be controlled with the "compression"
/// method. Compressing can be controlled with the "compress"
/// property. The following values for the "compress" property
/// are supported:
///
@ -154,7 +154,6 @@ class Foundation_API FileChannel: public Channel
///
/// The purgeAge property can have the following values:
///
/// * "none" or "" no purging
/// * <n> [seconds]: the maximum age is <n> seconds.
/// * <n> minutes: the maximum age is <n> minutes.
/// * <n> hours: the maximum age is <n> hours.
@ -162,19 +161,27 @@ class Foundation_API FileChannel: public Channel
/// * <n> weeks: the maximum age is <n> weeks.
/// * <n> months: the maximum age is <n> months, where a month has 30 days.
///
/// The purgeCount property has an integer value that specifies the maximum number
/// of archived log files. If the number is exceeded, archived log files are
/// deleted, starting with the oldest. When "none" or empty string are
/// supplied, they reset purgeCount to none (no purging).
/// The purgeCount property has an integer value that
/// specifies the maximum number of archived log files.
/// If the number is exceeded, archived log files are
/// deleted, starting with the oldest.
///
/// The flush property specifies whether each log message is flushed
/// immediately to the log file (which may hurt application performance,
/// but ensures that everything is in the log in case of a system crash),
// or whether it's allowed to stay in the system's file buffer for some time.
// or whether it's allowed to stay in the system's file buffer for some time.
/// Valid values are:
///
/// * true: Every essages is immediately flushed to the log file (default).
/// * false: Messages are not immediately flushed to the log file.
/// * true: Every essages is immediately flushed to the log file (default).
/// * false: Messages are not immediately flushed to the log file.
///
/// The rotateOnOpen property specifies whether an existing log file should be
/// rotated (and archived) when the channel is opened. Valid values are:
///
/// * true: The log file is rotated (and archived) when the channel is opened.
/// * false: Log messages will be appended to an existing log file,
/// if it exists (unless other conditions for a rotation are met).
/// This is the default.
///
/// For a more lightweight file channel class, see SimpleFileChannel.
{
@ -198,25 +205,27 @@ public:
/// Sets the property with the given name.
///
/// The following properties are supported:
/// * path: The log file's path.
/// * rotation: The log file's rotation mode. See the
/// FileChannel class for details.
/// * archive: The log file's archive mode. See the
/// FileChannel class for details.
/// * times: The log file's time mode. See the
/// FileChannel class for details.
/// * compress: Enable or disable compression of
/// archived files. See the FileChannel class
/// for details.
/// * purgeAge: Maximum age of an archived log file before
/// it is purged. See the FileChannel class for
/// details.
/// * purgeCount: Maximum number of archived log files before
/// files are purged. See the FileChannel class
/// for details.
/// * flush: Specifies whether messages are immediately
/// flushed to the log file. See the FileChannel class
/// for details.
/// * path: The log file's path.
/// * rotation: The log file's rotation mode. See the
/// FileChannel class for details.
/// * archive: The log file's archive mode. See the
/// FileChannel class for details.
/// * times: The log file's time mode. See the
/// FileChannel class for details.
/// * compress: Enable or disable compression of
/// archived files. See the FileChannel class
/// for details.
/// * purgeAge: Maximum age of an archived log file before
/// it is purged. See the FileChannel class for
/// details.
/// * purgeCount: Maximum number of archived log files before
/// files are purged. See the FileChannel class
/// for details.
/// * flush: Specifies whether messages are immediately
/// flushed to the log file. See the FileChannel class
/// for details.
/// * rotateOnOpen: Specifies whether an existing log file should be
/// rotated and archived when the channel is opened.
std::string getProperty(const std::string& name) const;
/// Returns the value of the property with the given name.
@ -240,6 +249,7 @@ public:
static const std::string PROP_PURGEAGE;
static const std::string PROP_PURGECOUNT;
static const std::string PROP_FLUSH;
static const std::string PROP_ROTATEONOPEN;
protected:
~FileChannel();
@ -249,6 +259,7 @@ protected:
void setPurgeAge(const std::string& age);
void setPurgeCount(const std::string& count);
void setFlush(const std::string& flush);
void setRotateOnOpen(const std::string& rotateOnOpen);
void purge();
private:
@ -260,6 +271,7 @@ private:
std::string _purgeAge;
std::string _purgeCount;
bool _flush;
bool _rotateOnOpen;
LogFile* _pFile;
RotateStrategy* _pRotateStrategy;
ArchiveStrategy* _pArchiveStrategy;

View File

@ -1,7 +1,7 @@
//
// FileChannel.cpp
//
// $Id: //poco/1.4/Foundation/src/FileChannel.cpp#1 $
// $Id: //poco/1.4/Foundation/src/FileChannel.cpp#3 $
//
// Library: Foundation
// Package: Logging
@ -39,6 +39,7 @@
#include "Poco/RotateStrategy.h"
#include "Poco/PurgeStrategy.h"
#include "Poco/Message.h"
#include "Poco/NumberParser.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTime.h"
#include "Poco/LocalDateTime.h"
@ -47,23 +48,25 @@
#include "Poco/Exception.h"
#include "Poco/Ascii.h"
namespace Poco {
const std::string FileChannel::PROP_PATH = "path";
const std::string FileChannel::PROP_ROTATION = "rotation";
const std::string FileChannel::PROP_ARCHIVE = "archive";
const std::string FileChannel::PROP_TIMES = "times";
const std::string FileChannel::PROP_COMPRESS = "compress";
const std::string FileChannel::PROP_PURGEAGE = "purgeAge";
const std::string FileChannel::PROP_PURGECOUNT = "purgeCount";
const std::string FileChannel::PROP_FLUSH = "flush ";
const std::string FileChannel::PROP_PATH = "path";
const std::string FileChannel::PROP_ROTATION = "rotation";
const std::string FileChannel::PROP_ARCHIVE = "archive";
const std::string FileChannel::PROP_TIMES = "times";
const std::string FileChannel::PROP_COMPRESS = "compress";
const std::string FileChannel::PROP_PURGEAGE = "purgeAge";
const std::string FileChannel::PROP_PURGECOUNT = "purgeCount";
const std::string FileChannel::PROP_FLUSH = "flush ";
const std::string FileChannel::PROP_ROTATEONOPEN = "rotateOnOpen";
FileChannel::FileChannel():
_times("utc"),
_compress(false),
_flush(true),
_rotateOnOpen(false),
_pFile(0),
_pRotateStrategy(0),
_pArchiveStrategy(new ArchiveByNumberStrategy),
@ -77,6 +80,7 @@ FileChannel::FileChannel(const std::string& path):
_times("utc"),
_compress(false),
_flush(true),
_rotateOnOpen(false),
_pFile(0),
_pRotateStrategy(0),
_pArchiveStrategy(new ArchiveByNumberStrategy),
@ -101,6 +105,18 @@ void FileChannel::open()
if (!_pFile)
{
_pFile = new LogFile(_path);
if (_rotateOnOpen && _pFile->size() > 0)
{
try
{
_pFile = _pArchiveStrategy->archive(_pFile);
purge();
}
catch (...)
{
_pFile = new LogFile(_path);
}
}
}
}
@ -168,6 +184,8 @@ void FileChannel::setProperty(const std::string& name, const std::string& value)
setPurgeCount(value);
else if (name == PROP_FLUSH)
setFlush(value);
else if (name == PROP_ROTATEONOPEN)
setRotateOnOpen(value);
else
Channel::setProperty(name, value);
}
@ -191,6 +209,8 @@ std::string FileChannel::getProperty(const std::string& name) const
return _purgeCount;
else if (name == PROP_FLUSH)
return std::string(_flush ? "true" : "false");
else if (name == PROP_ROTATEONOPEN)
return std::string(_rotateOnOpen ? "true" : "false");
else
return Channel::getProperty(name);
}
@ -230,6 +250,7 @@ void FileChannel::setRotation(const std::string& rotation)
while (it != end && Ascii::isSpace(*it)) ++it;
std::string unit;
while (it != end && Ascii::isAlpha(*it)) unit += *it++;
RotateStrategy* pStrategy = 0;
if ((rotation.find(',') != std::string::npos) || (rotation.find(':') != std::string::npos))
{
@ -306,28 +327,14 @@ void FileChannel::setCompress(const std::string& compress)
void FileChannel::setPurgeAge(const std::string& age)
{
delete _pPurgeStrategy;
_pPurgeStrategy = 0;
_purgeAge = "none";
if (age.empty() || 0 == icompare(age, "none"))
return;
std::string::const_iterator it = age.begin();
std::string::const_iterator it = age.begin();
std::string::const_iterator end = age.end();
int n = 0;
while (it != end && Ascii::isSpace(*it))
++it;
while (it != end && Ascii::isDigit(*it))
{
n *= 10;
n += *it++ - '0';
}
while (it != end && Ascii::isSpace(*it))
++it;
while (it != end && Ascii::isSpace(*it)) ++it;
while (it != end && Ascii::isDigit(*it)) { n *= 10; n += *it++ - '0'; }
while (it != end && Ascii::isSpace(*it)) ++it;
std::string unit;
while (it != end && Ascii::isAlpha(*it))
unit += *it++;
while (it != end && Ascii::isAlpha(*it)) unit += *it++;
Timespan::TimeDiff factor = Timespan::SECONDS;
if (unit == "minutes")
@ -339,51 +346,40 @@ void FileChannel::setPurgeAge(const std::string& age)
else if (unit == "weeks")
factor = 7*Timespan::DAYS;
else if (unit == "months")
factor = 30 * Timespan::DAYS;
factor = 30*Timespan::DAYS;
else if (unit != "seconds")
throw InvalidArgumentException("purgeAge", age);
if (0 == n)
throw InvalidArgumentException("Zero is not valid purge age.");
_pPurgeStrategy = new PurgeByAgeStrategy(Timespan(factor * n));
delete _pPurgeStrategy;
_pPurgeStrategy = new PurgeByAgeStrategy(Timespan(factor*n));
_purgeAge = age;
}
void FileChannel::setPurgeCount(const std::string& count)
{
std::string::const_iterator it = count.begin();
std::string::const_iterator end = count.end();
int n = 0;
while (it != end && Ascii::isSpace(*it)) ++it;
while (it != end && Ascii::isDigit(*it)) { n *= 10; n += *it++ - '0'; }
while (it != end && Ascii::isSpace(*it)) ++it;
delete _pPurgeStrategy;
_pPurgeStrategy = new PurgeByCountStrategy(n);
_purgeCount = count;
}
void FileChannel::setFlush(const std::string& flush)
{
_flush = icompare(flush, "true") == 0;
}
void FileChannel::setPurgeCount(const std::string& count)
void FileChannel::setRotateOnOpen(const std::string& rotateOnOpen)
{
delete _pPurgeStrategy;
_pPurgeStrategy = 0;
_purgeAge = "none";
if (count.empty() || 0 == icompare(count, "none"))
return;
int n = 0;
std::string::const_iterator it = count.begin();
std::string::const_iterator end = count.end();
while (it != end && Ascii::isSpace(*it))
++it;
while (it != end && Ascii::isDigit(*it))
{
n *= 10;
n += *it++ - '0';
}
while (it != end && Ascii::isSpace(*it))
++it;
if (0 == n)
throw InvalidArgumentException("Zero is not valid purge count.");
_pPurgeStrategy = new PurgeByCountStrategy(n);
_purgeCount = count;
_rotateOnOpen = icompare(rotateOnOpen, "true") == 0;
}