1 : <?php
2 : /**
3 : * Licensed to the Apache Software Foundation (ASF) under one or more
4 : * contributor license agreements. See the NOTICE file distributed with
5 : * this work for additional information regarding copyright ownership.
6 : * The ASF licenses this file to You under the Apache License, Version 2.0
7 : * (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : *
18 : * @package log4php
19 : */
20 :
21 : /**
22 : * LoggerAppenderRollingFile extends LoggerAppenderFile to backup the log files
23 : * when they reach a certain size.
24 : *
25 : * This appender uses a layout.
26 : *
27 : * Parameters are:
28 : * - file - The target file to write to
29 : * - filename - The target file to write to (deprecated, use "file" instead).
30 : * - append - Sets if the appender should append to the end of the file or overwrite content ("true" or "false")
31 : * - maxBackupIndex - Set the maximum number of backup files to keep around (int)
32 : * - maxFileSize - Set the maximum size that the output file is allowed to
33 : * reach before being rolled over to backup files.
34 : * Suffixes like "KB", "MB" or "GB" are allowed, f. e. "10KB" is interpreted as 10240
35 : * - maximumFileSize - Alias to maxFileSize (deprecated, use "maxFileSize" instead)
36 : *
37 : * <p>Contributors: Sergio Strampelli.</p>
38 : *
39 : * An example:
40 : *
41 : * {@example ../../examples/php/appender_socket.php 19}
42 : *
43 : * {@example ../../examples/resources/appender_socket.properties 18}
44 : *
45 : * @version $Revision: 1213283 $
46 : * @package log4php
47 : * @subpackage appenders
48 : */
49 : class LoggerAppenderRollingFile extends LoggerAppenderFile {
50 :
51 : /**
52 : * Set the maximum size that the output file is allowed to reach
53 : * before being rolled over to backup files.
54 : *
55 : * <p>In configuration files, the <var>MaxFileSize</var> option takes a
56 : * long integer in the range 0 - 2^63. You can specify the value
57 : * with the suffixes "KB", "MB" or "GB" so that the integer is
58 : * interpreted being expressed respectively in kilobytes, megabytes
59 : * or gigabytes. For example, the value "10KB" will be interpreted
60 : * as 10240.</p>
61 : * <p>The default maximum file size is 10MB.</p>
62 : *
63 : * <p>Note that MaxFileSize cannot exceed <b>2 GB</b>.</p>
64 : *
65 : * @var integer
66 : */
67 : protected $maxFileSize = 10485760;
68 :
69 : /**
70 : * Set the maximum number of backup files to keep around.
71 : *
72 : * <p>The <var>MaxBackupIndex</var> option determines how many backup
73 : * files are kept before the oldest is erased. This option takes
74 : * a positive integer value. If set to zero, then there will be no
75 : * backup files and the log file will be truncated when it reaches
76 : * MaxFileSize.</p>
77 : * <p>There is one backup file by default.</p>
78 : *
79 : * @var integer
80 : */
81 : protected $maxBackupIndex = 1;
82 :
83 : /**
84 : * @var string the filename expanded
85 : */
86 : private $expandedFileName = null;
87 :
88 : /**
89 : * Returns the value of the MaxBackupIndex option.
90 : * @return integer
91 : */
92 : private function getExpandedFileName() {
93 2 : return $this->expandedFileName;
94 : }
95 :
96 : /**
97 : * Get the maximum size that the output file is allowed to reach
98 : * before being rolled over to backup files.
99 : * @return integer
100 : */
101 : public function getMaximumFileSize() {
102 0 : return $this->maxFileSize;
103 : }
104 :
105 : /**
106 : * Implements the usual roll over behaviour.
107 : *
108 : * <p>If MaxBackupIndex is positive, then files File.1, ..., File.MaxBackupIndex -1 are renamed to File.2, ..., File.MaxBackupIndex.
109 : * Moreover, File is renamed File.1 and closed. A new File is created to receive further log output.
110 : *
111 : * <p>If MaxBackupIndex is equal to zero, then the File is truncated with no backup files created.
112 : *
113 : * Rollover must be called while the file is locked so that it is safe for concurrent access.
114 : */
115 : private function rollOver() {
116 : // If maxBackups <= 0, then there is no file renaming to be done.
117 2 : if($this->maxBackupIndex > 0) {
118 2 : $fileName = $this->getExpandedFileName();
119 :
120 : // Delete the oldest file, to keep Windows happy.
121 2 : $file = $fileName . '.' . $this->maxBackupIndex;
122 2 : if(is_writable($file))
123 2 : unlink($file);
124 :
125 : // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2}
126 2 : for($i = $this->maxBackupIndex - 1; $i >= 1; $i--) {
127 2 : $file = $fileName . "." . $i;
128 2 : if(is_readable($file)) {
129 2 : $target = $fileName . '.' . ($i + 1);
130 2 : rename($file, $target);
131 2 : }
132 2 : }
133 :
134 : // Backup the active file
135 2 : copy($fileName, "$fileName.1");
136 2 : }
137 :
138 : // Truncate the active file
139 2 : ftruncate($this->fp, 0);
140 2 : rewind($this->fp);
141 2 : }
142 :
143 : public function setFile($fileName) {
144 3 : $this->file = $fileName;
145 : // As LoggerAppenderFile does not create the directory, it has to exist.
146 : // realpath() fails if the argument does not exist so the filename is separated.
147 3 : $this->expandedFileName = realpath(dirname($fileName));
148 3 : if ($this->expandedFileName === false) throw new Exception("Directory of $fileName does not exist!");
149 3 : $this->expandedFileName .= DIRECTORY_SEPARATOR . basename($fileName);
150 3 : }
151 :
152 :
153 : /**
154 : * Set the maximum number of backup files to keep around.
155 : *
156 : * <p>The <b>MaxBackupIndex</b> option determines how many backup
157 : * files are kept before the oldest is erased. This option takes
158 : * a positive integer value. If set to zero, then there will be no
159 : * backup files and the log file will be truncated when it reaches
160 : * MaxFileSize.
161 : *
162 : * @param mixed $maxBackups
163 : */
164 : public function setMaxBackupIndex($maxBackups) {
165 2 : $this->setPositiveInteger('maxBackupIndex', $maxBackups);
166 2 : }
167 :
168 : /**
169 : * Set the maximum size that the output file is allowed to reach
170 : * before being rolled over to backup files.
171 : *
172 : * @param mixed $maxFileSize
173 : * @see setMaxFileSize()
174 : * @deprecated
175 : */
176 : public function setMaximumFileSize($maxFileSize) {
177 0 : return $this->setMaxFileSize($maxFileSize);
178 : }
179 :
180 : /**
181 : * Set the maximum size that the output file is allowed to reach
182 : * before being rolled over to backup files.
183 : * <p>In configuration files, the <b>maxFileSize</b> option takes an
184 : * long integer in the range 0 - 2^63. You can specify the value
185 : * with the suffixes "KB", "MB" or "GB" so that the integer is
186 : * interpreted being expressed respectively in kilobytes, megabytes
187 : * or gigabytes. For example, the value "10KB" will be interpreted
188 : * as 10240.
189 : *
190 : * @param mixed $value
191 : * @return the actual file size set
192 : */
193 : public function setMaxFileSize($value) {
194 3 : $this->setFileSize('maxFileSize', $value);
195 3 : }
196 :
197 : public function append(LoggerLoggingEvent $event) {
198 2 : if($this->fp and $this->layout !== null) {
199 2 : if(flock($this->fp, LOCK_EX)) {
200 2 : fwrite($this->fp, $this->layout->format($event));
201 :
202 : // Stats cache must be cleared, otherwise filesize() returns cached results
203 2 : clearstatcache();
204 :
205 : // Rollover if needed
206 2 : if (filesize($this->expandedFileName) > $this->maxFileSize) {
207 2 : $this->rollOver();
208 2 : }
209 :
210 2 : flock($this->fp, LOCK_UN);
211 2 : } else {
212 0 : $this->closed = true;
213 : }
214 2 : }
215 2 : }
216 :
217 : /**
218 : * @return Returns the maximum number of backup files to keep around.
219 : */
220 : public function getMaxBackupIndex() {
221 0 : return $this->maxBackupIndex;
222 : }
223 :
224 : /**
225 : * @return Returns the maximum size that the output file is allowed to reach
226 : * before being rolled over to backup files.
227 : */
228 : public function getMaxFileSize() {
229 1 : return $this->maxFileSize;
230 : }
231 : }
|