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 | |
28 | namespace Poco { |
29 | |
30 | |
31 | // |
32 | // ArchiveCompressor |
33 | // |
34 | |
35 | |
36 | class ArchiveCompressor: public ActiveDispatcher |
37 | { |
38 | public: |
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 | |
50 | protected: |
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 | |
86 | ArchiveStrategy::ArchiveStrategy(): |
87 | _compress(false), |
88 | _pCompressor(0) |
89 | { |
90 | } |
91 | |
92 | |
93 | ArchiveStrategy::~ArchiveStrategy() |
94 | { |
95 | delete _pCompressor; |
96 | } |
97 | |
98 | |
99 | void ArchiveStrategy::compress(bool flag) |
100 | { |
101 | _compress = flag; |
102 | } |
103 | |
104 | |
105 | void 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 | |
131 | bool 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 | |
154 | ArchiveByNumberStrategy::ArchiveByNumberStrategy() |
155 | { |
156 | } |
157 | |
158 | |
159 | ArchiveByNumberStrategy::~ArchiveByNumberStrategy() |
160 | { |
161 | } |
162 | |
163 | |
164 | LogFile* 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 | |