1//
2// SimpleFileChannel.cpp
3//
4// Library: Foundation
5// Package: Logging
6// Module: SimpleFileChannel
7//
8// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/SimpleFileChannel.h"
16#include "Poco/LogFile.h"
17#include "Poco/File.h"
18#include "Poco/Message.h"
19#include "Poco/Exception.h"
20#include "Poco/Ascii.h"
21#include "Poco/String.h"
22
23
24namespace Poco {
25
26
27const std::string SimpleFileChannel::PROP_PATH = "path";
28const std::string SimpleFileChannel::PROP_SECONDARYPATH = "secondaryPath";
29const std::string SimpleFileChannel::PROP_ROTATION = "rotation";
30const std::string SimpleFileChannel::PROP_FLUSH = "flush";
31
32
33SimpleFileChannel::SimpleFileChannel():
34 _limit(0),
35 _flush(true),
36 _pFile(0)
37{
38}
39
40
41SimpleFileChannel::SimpleFileChannel(const std::string& rPath):
42 _path(rPath),
43 _secondaryPath(rPath + ".0"),
44 _limit(0),
45 _flush(true),
46 _pFile(0)
47{
48}
49
50
51SimpleFileChannel::~SimpleFileChannel()
52{
53 try
54 {
55 close();
56 }
57 catch (...)
58 {
59 poco_unexpected();
60 }
61}
62
63
64void SimpleFileChannel::open()
65{
66 FastMutex::ScopedLock lock(_mutex);
67
68 if (!_pFile)
69 {
70 File primary(_path);
71 File secondary(_secondaryPath);
72 Timestamp pt = primary.exists() ? primary.getLastModified() : 0;
73 Timestamp st = secondary.exists() ? secondary.getLastModified() : 0;
74 std::string pathString;
75 if (pt >= st)
76 pathString = _path;
77 else
78 pathString = _secondaryPath;
79 _pFile = new LogFile(pathString);
80 }
81}
82
83
84void SimpleFileChannel::close()
85{
86 FastMutex::ScopedLock lock(_mutex);
87
88 delete _pFile;
89 _pFile = 0;
90}
91
92
93void SimpleFileChannel::log(const Message& msg)
94{
95 open();
96
97 FastMutex::ScopedLock lock(_mutex);
98
99 if (_limit > 0 && _pFile->size() >= _limit)
100 {
101 rotate();
102 }
103 _pFile->write(msg.getText(), _flush);
104}
105
106
107void SimpleFileChannel::setProperty(const std::string& name, const std::string& value)
108{
109 FastMutex::ScopedLock lock(_mutex);
110
111 if (name == PROP_PATH)
112 {
113 _path = value;
114 if (_secondaryPath.empty())
115 _secondaryPath = _path + ".0";
116 }
117 else if (name == PROP_SECONDARYPATH)
118 _secondaryPath = value;
119 else if (name == PROP_ROTATION)
120 setRotation(value);
121 else if (name == PROP_FLUSH)
122 setFlush(value);
123 else
124 Channel::setProperty(name, value);
125}
126
127
128std::string SimpleFileChannel::getProperty(const std::string& name) const
129{
130 if (name == PROP_PATH)
131 return _path;
132 else if (name == PROP_SECONDARYPATH)
133 return _secondaryPath;
134 else if (name == PROP_ROTATION)
135 return _rotation;
136 else if (name == PROP_FLUSH)
137 return std::string(_flush ? "true" : "false");
138 else
139 return Channel::getProperty(name);
140}
141
142
143Timestamp SimpleFileChannel::creationDate() const
144{
145 if (_pFile)
146 return _pFile->creationDate();
147 else
148 return 0;
149}
150
151
152UInt64 SimpleFileChannel::size() const
153{
154 if (_pFile)
155 return _pFile->size();
156 else
157 return 0;
158}
159
160
161const std::string& SimpleFileChannel::path() const
162{
163 return _path;
164}
165
166
167const std::string& SimpleFileChannel::secondaryPath() const
168{
169 return _secondaryPath;
170}
171
172
173void SimpleFileChannel::setRotation(const std::string& rotation)
174{
175 std::string::const_iterator it = rotation.begin();
176 std::string::const_iterator end = rotation.end();
177 UInt64 n = 0;
178 while (it != end && Ascii::isSpace(*it)) ++it;
179 while (it != end && Ascii::isDigit(*it)) { n *= 10; n += *it++ - '0'; }
180 while (it != end && Ascii::isSpace(*it)) ++it;
181 std::string unit;
182 while (it != end && Ascii::isAlpha(*it)) unit += *it++;
183
184 if (unit == "K")
185 _limit = n*1024;
186 else if (unit == "M")
187 _limit = n*1024*1024;
188 else if (unit.empty())
189 _limit = n;
190 else if (unit == "never")
191 _limit = 0;
192 else
193 throw InvalidArgumentException("rotation", rotation);
194 _rotation = rotation;
195}
196
197
198void SimpleFileChannel::setFlush(const std::string& flush)
199{
200 _flush = icompare(flush, "true") == 0;
201}
202
203
204void SimpleFileChannel::rotate()
205{
206 std::string newPath;
207 if (_pFile->path() == _path)
208 newPath = _secondaryPath;
209 else
210 newPath = _path;
211 File f(newPath);
212 if (f.exists())
213 {
214 try
215 {
216 f.remove();
217 }
218 catch (...)
219 {
220 }
221 }
222 delete _pFile;
223 _pFile = new LogFile(newPath);
224}
225
226
227} // namespace Poco
228