Mercurial > projects > ldc
comparison tango/tango/util/log/RollingFileAppender.d @ 132:1700239cab2e trunk
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos.
Lots of bugfixes...
This build is not suitable for most things.
author | lindquist |
---|---|
date | Fri, 11 Jan 2008 17:57:40 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
131:5825d48b27d1 | 132:1700239cab2e |
---|---|
1 /******************************************************************************* | |
2 | |
3 copyright: Copyright (c) 2004 Kris Bell. All rights reserved | |
4 | |
5 license: BSD style: $(LICENSE) | |
6 | |
7 version: Initial release: May 2004 | |
8 | |
9 author: Kris | |
10 | |
11 *******************************************************************************/ | |
12 | |
13 module tango.util.log.RollingFileAppender; | |
14 | |
15 private import tango.time.Time; | |
16 | |
17 private import tango.io.FilePath, | |
18 tango.io.FileConst, | |
19 tango.io.FileConduit; | |
20 | |
21 private import tango.io.model.IBuffer; | |
22 | |
23 private import tango.util.log.Appender, | |
24 tango.util.log.FileAppender; | |
25 | |
26 /******************************************************************************* | |
27 | |
28 Append log messages to a file set. | |
29 | |
30 *******************************************************************************/ | |
31 | |
32 public class RollingFileAppender : FileAppender | |
33 { | |
34 private Mask mask; | |
35 private FilePath[] paths; | |
36 private int index; | |
37 private IBuffer buffer; | |
38 private ulong maxSize, | |
39 fileSize; | |
40 | |
41 /*********************************************************************** | |
42 | |
43 Create a RollingFileAppender upon a file-set with the | |
44 specified path and optional layout. | |
45 | |
46 Where a file set already exists, we resume appending to | |
47 the one with the most recent activity timestamp. | |
48 | |
49 ***********************************************************************/ | |
50 | |
51 this (char[] path, int count, ulong maxSize, EventLayout layout = null) | |
52 { | |
53 assert (path); | |
54 assert (count > 1 && count < 10); | |
55 | |
56 // Get a unique fingerprint for this instance | |
57 mask = register (path); | |
58 | |
59 char[1] x; | |
60 Time mostRecent; | |
61 | |
62 for (int i=0; i < count; ++i) | |
63 { | |
64 x[0] = '0' + i; | |
65 | |
66 auto p = new FilePath (path); | |
67 p.name = p.name ~ x; | |
68 paths ~= p; | |
69 | |
70 // use the most recent file in the set | |
71 if (p.exists) | |
72 { | |
73 auto modified = p.modified; | |
74 if (modified > mostRecent) | |
75 { | |
76 mostRecent = modified; | |
77 index = i; | |
78 } | |
79 } | |
80 } | |
81 | |
82 // remember the maximum size | |
83 this.maxSize = maxSize; | |
84 | |
85 // adjust index and open the appropriate log file | |
86 --index; | |
87 nextFile (false); | |
88 | |
89 // set provided layout (ignored when null) | |
90 setLayout (layout); | |
91 } | |
92 | |
93 /*********************************************************************** | |
94 | |
95 Return the fingerprint for this class | |
96 | |
97 ***********************************************************************/ | |
98 | |
99 Mask getMask () | |
100 { | |
101 return mask; | |
102 } | |
103 | |
104 /*********************************************************************** | |
105 | |
106 Return the name of this class | |
107 | |
108 ***********************************************************************/ | |
109 | |
110 char[] getName () | |
111 { | |
112 return this.classinfo.name; | |
113 } | |
114 | |
115 /*********************************************************************** | |
116 | |
117 Append an event to the output. | |
118 | |
119 ***********************************************************************/ | |
120 | |
121 synchronized void append (Event event) | |
122 { | |
123 char[] msg; | |
124 | |
125 // file already full? | |
126 if (fileSize >= maxSize) | |
127 nextFile (true); | |
128 | |
129 // bump file size | |
130 fileSize += FileConst.NewlineString.length; | |
131 | |
132 // write log message and flush it | |
133 auto layout = getLayout (); | |
134 msg = layout.header (event); | |
135 fileSize += msg.length; | |
136 buffer.append (msg); | |
137 | |
138 msg = layout.content (event); | |
139 fileSize += msg.length; | |
140 buffer.append (msg); | |
141 | |
142 msg = layout.footer (event); | |
143 fileSize += msg.length; | |
144 buffer.append (msg); | |
145 | |
146 buffer.append(FileConst.NewlineString).flush; | |
147 } | |
148 | |
149 /*********************************************************************** | |
150 | |
151 Switch to the next file within the set | |
152 | |
153 ***********************************************************************/ | |
154 | |
155 private void nextFile (bool reset) | |
156 { | |
157 // select next file in the set | |
158 if (++index >= paths.length) | |
159 index = 0; | |
160 | |
161 // reset file size | |
162 fileSize = 0; | |
163 | |
164 // close any existing conduit | |
165 close; | |
166 | |
167 // make it shareable for read | |
168 auto style = FileConduit.WriteAppending; | |
169 style.share = FileConduit.Share.Read; | |
170 auto conduit = new FileConduit (paths[index], style); | |
171 | |
172 buffer = setConduit (conduit); | |
173 if (reset) | |
174 conduit.truncate; | |
175 } | |
176 } | |
177 |