Logo Search packages:      
Sourcecode: poco version File versions

FileChannel.cpp

//
// FileChannel.cpp
//
// $Id: //poco/1.4/Foundation/src/FileChannel.cpp#1 $
//
// Library: Foundation
// Package: Logging
// Module:  FileChannel
//
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
// 
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//


#include "Poco/FileChannel.h"
#include "Poco/ArchiveStrategy.h"
#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"
#include "Poco/String.h"
#include "Poco/Timespan.h"
#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";


FileChannel::FileChannel(): 
      _times("utc"),
      _compress(false),
      _pFile(0),
      _pRotateStrategy(0),
      _pArchiveStrategy(new ArchiveByNumberStrategy),
      _pPurgeStrategy(0)
{
}


00075 FileChannel::FileChannel(const std::string& path):
      _path(path),
      _times("utc"),
      _compress(false),
      _pFile(0),
      _pRotateStrategy(0),
      _pArchiveStrategy(new ArchiveByNumberStrategy),
      _pPurgeStrategy(0)
{
}


FileChannel::~FileChannel()
{
      close();
      delete _pRotateStrategy;
      delete _pArchiveStrategy;
      delete _pPurgeStrategy;
}


00096 void FileChannel::open()
{
      FastMutex::ScopedLock lock(_mutex);
      
      if (!_pFile)
      {
            _pFile = new LogFile(_path);
      }
}


00107 void FileChannel::close()
{
      FastMutex::ScopedLock lock(_mutex);

      delete _pFile;
      _pFile = 0;
}


00116 void FileChannel::log(const Message& msg)
{
      open();

      FastMutex::ScopedLock lock(_mutex);

      if (_pRotateStrategy && _pArchiveStrategy && _pRotateStrategy->mustRotate(_pFile))
      {
            try
            {
                  _pFile = _pArchiveStrategy->archive(_pFile);
                  purge();
            }
            catch (...)
            {
                  _pFile = new LogFile(_path);
            }
            // we must call mustRotate() again to give the
            // RotateByIntervalStrategy a chance to write its timestamp
            // to the new file.
            _pRotateStrategy->mustRotate(_pFile);
      }
      _pFile->write(msg.getText());
}

      
00142 void FileChannel::setProperty(const std::string& name, const std::string& value)
{
      FastMutex::ScopedLock lock(_mutex);

      if (name == PROP_TIMES)
      {
            _times = value;

            if (!_rotation.empty())
                  setRotation(_rotation);

            if (!_archive.empty())
                  setArchive(_archive);
      }
      else if (name == PROP_PATH)
            _path = value;
      else if (name == PROP_ROTATION)
            setRotation(value);
      else if (name == PROP_ARCHIVE)
            setArchive(value);
      else if (name == PROP_COMPRESS)
            setCompress(value);
      else if (name == PROP_PURGEAGE)
            setPurgeAge(value);
      else if (name == PROP_PURGECOUNT)
            setPurgeCount(value);
      else
            Channel::setProperty(name, value);
}


00173 std::string FileChannel::getProperty(const std::string& name) const
{
      if (name == PROP_TIMES)
            return _times;
      else if (name == PROP_PATH)
            return _path;
      else if (name == PROP_ROTATION)
            return _rotation;
      else if (name == PROP_ARCHIVE)
            return _archive;
      else if (name == PROP_COMPRESS)
            return std::string(_compress ? "true" : "false");
      else if (name == PROP_PURGEAGE)
            return _purgeAge;
      else if (name == PROP_PURGECOUNT)
            return _purgeCount;
      else
            return Channel::getProperty(name);
}


00194 Timestamp FileChannel::creationDate() const
{
      if (_pFile)
            return _pFile->creationDate();
      else
            return 0;
}

      
00203 UInt64 FileChannel::size() const
{
      if (_pFile)
            return _pFile->size();
      else
            return 0;
}


00212 const std::string& FileChannel::path() const
{
      return _path;
}


void FileChannel::setRotation(const std::string& rotation)
{
      std::string::const_iterator it  = rotation.begin();
      std::string::const_iterator end = rotation.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;
      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))
      {
            if (_times == "utc")
                  pStrategy = new RotateAtTimeStrategy<DateTime>(rotation);
            else if (_times == "local")
                  pStrategy = new RotateAtTimeStrategy<LocalDateTime>(rotation);
            else
                  throw PropertyNotSupportedException("times", _times);
      }
      else if (unit == "daily")
            pStrategy = new RotateByIntervalStrategy(Timespan(1*Timespan::DAYS));
      else if (unit == "weekly")
            pStrategy = new RotateByIntervalStrategy(Timespan(7*Timespan::DAYS));
      else if (unit == "monthly")
            pStrategy = new RotateByIntervalStrategy(Timespan(30*Timespan::DAYS));
      else if (unit == "seconds") // for testing only
            pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::SECONDS));
      else if (unit == "minutes")
            pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::MINUTES));
      else if (unit == "hours")
            pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::HOURS));
      else if (unit == "days")
            pStrategy = new RotateByIntervalStrategy(Timespan(n*Timespan::DAYS));
      else if (unit == "weeks")
            pStrategy = new RotateByIntervalStrategy(Timespan(n*7*Timespan::DAYS));
      else if (unit == "months")
            pStrategy = new RotateByIntervalStrategy(Timespan(n*30*Timespan::DAYS));
      else if (unit == "K")
            pStrategy = new RotateBySizeStrategy(n*1024);
      else if (unit == "M")
            pStrategy = new RotateBySizeStrategy(n*1024*1024);
      else if (unit.empty())
            pStrategy = new RotateBySizeStrategy(n);
      else if (unit != "never")
            throw InvalidArgumentException("rotation", rotation);
      delete _pRotateStrategy;
      _pRotateStrategy = pStrategy;
      _rotation = rotation;
}


void FileChannel::setArchive(const std::string& archive)
{
      ArchiveStrategy* pStrategy = 0;
      if (archive == "number")
      {
            pStrategy = new ArchiveByNumberStrategy;
      }
      else if (archive == "timestamp")
      {
            if (_times == "utc")
                  pStrategy = new ArchiveByTimestampStrategy<DateTime>;
            else if (_times == "local")
                  pStrategy = new ArchiveByTimestampStrategy<LocalDateTime>;
            else
                  throw PropertyNotSupportedException("times", _times);
      }
      else throw InvalidArgumentException("archive", archive);
      delete _pArchiveStrategy;
      pStrategy->compress(_compress);
      _pArchiveStrategy = pStrategy;
      _archive = archive;
}


void FileChannel::setCompress(const std::string& compress)
{
      _compress = icompare(compress, "true") == 0;
      if (_pArchiveStrategy)
            _pArchiveStrategy->compress(_compress);
}


void FileChannel::setPurgeAge(const std::string& age)
{
      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;
      std::string unit;
      while (it != end && Ascii::isAlpha(*it)) unit += *it++;
      
      Timespan::TimeDiff factor = Timespan::SECONDS;
      if (unit == "minutes")
            factor = Timespan::MINUTES;
      else if (unit == "hours")
            factor = Timespan::HOURS;
      else if (unit == "days")
            factor = Timespan::DAYS;
      else if (unit == "weeks")
            factor = 7*Timespan::DAYS;
      else if (unit == "months")
            factor = 30*Timespan::DAYS;
      else if (unit != "seconds")
            throw InvalidArgumentException("purgeAge", age);
            
      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::purge()
{
      if (_pPurgeStrategy)
      {
            try
            {
                  _pPurgeStrategy->purge(_path);
            }
            catch (...)
            {
            }
      }
}


} // namespace Poco

Generated by  Doxygen 1.6.0   Back to index