1//
2// ArchiveStrategy.cpp
3//
4// Library: Foundation
5// Package: Logging
6// Module: FileChannel
7//
8// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/ArchiveStrategy.h"
16#include "Poco/NumberFormatter.h"
17#include "Poco/File.h"
18#include "Poco/Path.h"
19#include "Poco/DeflatingStream.h"
20#include "Poco/StreamCopier.h"
21#include "Poco/Exception.h"
22#include "Poco/ActiveDispatcher.h"
23#include "Poco/ActiveMethod.h"
24#include "Poco/Void.h"
25#include "Poco/FileStream.h"
26
27
28namespace Poco {
29
30
31//
32// ArchiveCompressor
33//
34
35
36class ArchiveCompressor: public ActiveDispatcher
37{
38public:
39 ArchiveCompressor():
40 compress(this, &ArchiveCompressor::compressImpl)
41 {
42 }
43
44 ~ArchiveCompressor()
45 {
46 }
47
48 ActiveMethod<void, std::string, ArchiveCompressor, ActiveStarter<ActiveDispatcher> > compress;
49
50protected:
51 void compressImpl(const std::string& path)
52 {
53 std::string gzPath(path);
54 gzPath.append(".gz");
55 FileInputStream istr(path);
56 FileOutputStream ostr(gzPath);
57 try
58 {
59 DeflatingOutputStream deflater(ostr, DeflatingStreamBuf::STREAM_GZIP);
60 StreamCopier::copyStream(istr, deflater);
61 if (!deflater.good() || !ostr.good()) throw WriteFileException(gzPath);
62 deflater.close();
63 ostr.close();
64 istr.close();
65 }
66 catch (Poco::Exception&)
67 {
68 // deflating failed - remove gz file and leave uncompressed log file
69 ostr.close();
70 Poco::File gzf(gzPath);
71 gzf.remove();
72 return;
73 }
74 File f(path);
75 f.remove();
76 return;
77 }
78};
79
80
81//
82// ArchiveStrategy
83//
84
85
86ArchiveStrategy::ArchiveStrategy():
87 _compress(false),
88 _pCompressor(0)
89{
90}
91
92
93ArchiveStrategy::~ArchiveStrategy()
94{
95 delete _pCompressor;
96}
97
98
99void ArchiveStrategy::compress(bool flag)
100{
101 _compress = flag;
102}
103
104
105void ArchiveStrategy::moveFile(const std::string& oldPath, const std::string& newPath)
106{
107 bool compressed = false;
108 Path p(oldPath);
109 File f(oldPath);
110 if (!f.exists())
111 {
112 f = oldPath + ".gz";
113 compressed = true;
114 }
115 std::string mvPath(newPath);
116 if (_compress || compressed)
117 mvPath.append(".gz");
118 if (!_compress || compressed)
119 {
120 f.renameTo(mvPath);
121 }
122 else
123 {
124 f.renameTo(newPath);
125 if (!_pCompressor) _pCompressor = new ArchiveCompressor;
126 _pCompressor->compress(newPath);
127 }
128}
129
130
131bool ArchiveStrategy::exists(const std::string& name)
132{
133 File f(name);
134 if (f.exists())
135 {
136 return true;
137 }
138 else if (_compress)
139 {
140 std::string gzName(name);
141 gzName.append(".gz");
142 File gzf(gzName);
143 return gzf.exists();
144 }
145 else return false;
146}
147
148
149//
150// ArchiveByNumberStrategy
151//
152
153
154ArchiveByNumberStrategy::ArchiveByNumberStrategy()
155{
156}
157
158
159ArchiveByNumberStrategy::~ArchiveByNumberStrategy()
160{
161}
162
163
164LogFile* ArchiveByNumberStrategy::archive(LogFile* pFile)
165{
166 std::string basePath = pFile->path();
167 delete pFile;
168 int n = -1;
169 std::string path;
170 do
171 {
172 path = basePath;
173 path.append(".");
174 NumberFormatter::append(path, ++n);
175 }
176 while (exists(path));
177
178 while (n >= 0)
179 {
180 std::string oldPath = basePath;
181 if (n > 0)
182 {
183 oldPath.append(".");
184 NumberFormatter::append(oldPath, n - 1);
185 }
186 std::string newPath = basePath;
187 newPath.append(".");
188 NumberFormatter::append(newPath, n);
189 moveFile(oldPath, newPath);
190 --n;
191 }
192 return new LogFile(basePath);
193}
194
195
196} // namespace Poco
197