/[zanavi_public1]/navit/navit/log.c
ZANavi

Contents of /navit/navit/log.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (8 years, 9 months ago) by zoff99
File MIME type: text/plain
File size: 8022 byte(s)
import files
1 /**
2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21 #ifdef HAVE_UNISTD_H
22 #include <unistd.h>
23 #endif
24 #ifdef HAVE_SYS_TIME_H
25 #include <sys/time.h>
26 #endif
27 #include <fcntl.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <time.h>
33 #include <glib.h>
34 #include "file.h"
35 #include "item.h"
36 #include "event.h"
37 #include "callback.h"
38 #include "debug.h"
39 #include "log.h"
40
41 struct log_data {
42 int len;
43 int max_len;
44 char *data;
45 };
46
47 struct log {
48 FILE *f;
49 int overwrite;
50 int empty;
51 int lazy;
52 int mkdir;
53 int flush_size;
54 int flush_time;
55 struct event_timeout *timer;
56 struct callback *timer_callback;
57 #ifdef HAVE_SYS_TIME_H
58 struct timeval last_flush;
59 #endif
60 char *filename;
61 char *filename_ex1;
62 char *filename_ex2;
63 struct log_data header;
64 struct log_data data;
65 struct log_data trailer;
66 struct attr **attrs;
67 };
68
69 static void
70 strftime_localtime(char *buffer, int size, char *fmt)
71 {
72 time_t t;
73 struct tm *tm;
74
75 t=time(NULL);
76 tm=localtime(&t);
77 strftime(buffer, 4096, fmt, tm);
78 }
79
80 static void
81 expand_filenames(struct log *this_)
82 {
83 char *pos,buffer[4096];
84 int i;
85
86 strftime_localtime(buffer, 4096, this_->filename);
87 this_->filename_ex1=g_strdup(buffer);
88 if ((pos=strstr(this_->filename_ex1,"%i"))) {
89 #ifdef HAVE_API_ANDROID
90 pos[1]='d';
91 #endif
92 i=0;
93 do {
94 g_free(this_->filename_ex2);
95 this_->filename_ex2=g_strdup_printf(this_->filename_ex1,i++);
96 } while (file_exists(this_->filename_ex2));
97 #ifdef HAVE_API_ANDROID
98 pos[1]='i';
99 #endif
100 } else
101 this_->filename_ex2=g_strdup(this_->filename_ex1);
102 }
103
104 static void
105 log_set_last_flush(struct log *this_)
106 {
107 #ifdef HAVE_SYS_TIME_H
108 gettimeofday(&this_->last_flush, NULL);
109 #endif
110 }
111
112 static void
113 log_open(struct log *this_)
114 {
115 char *mode;
116 if (this_->overwrite)
117 mode="w";
118 else
119 mode="r+";
120 if (this_->mkdir)
121 file_mkdir(this_->filename_ex2, 2);
122 this_->f=fopen(this_->filename_ex2, mode);
123 if (! this_->f)
124 this_->f=fopen(this_->filename_ex2, "w");
125 if (! this_->f)
126 return;
127 if (!this_->overwrite)
128 fseek(this_->f, 0, SEEK_END);
129 this_->empty = !ftell(this_->f);
130 log_set_last_flush(this_);
131 }
132
133 static void
134 log_close(struct log *this_)
135 {
136 if (! this_->f)
137 return;
138 if (this_->trailer.len)
139 fwrite(this_->trailer.data, 1, this_->trailer.len, this_->f);
140 fflush(this_->f);
141 fclose(this_->f);
142 this_->f=NULL;
143 }
144
145 static void
146 log_flush(struct log *this_, enum log_flags flags)
147 {
148 long pos;
149 if (this_->lazy && !this_->f) {
150 if (!this_->data.len)
151 return;
152 log_open(this_);
153 }
154 if (! this_->f)
155 return;
156 if (this_->empty) {
157 if (this_->header.len)
158 fwrite(this_->header.data, 1, this_->header.len, this_->f);
159 if (this_->header.len || this_->data.len)
160 this_->empty=0;
161 }
162 fwrite(this_->data.data, 1, this_->data.len, this_->f);
163 #ifndef HAVE_API_WIN32_BASE
164 if (flags & log_flag_truncate) {
165 pos=ftell(this_->f);
166 ftruncate(fileno(this_->f), pos);
167 }
168 #endif
169 if (this_->trailer.len) {
170 pos=ftell(this_->f);
171 if (pos > 0) {
172 fwrite(this_->trailer.data, 1, this_->trailer.len, this_->f);
173 fseek(this_->f, pos, SEEK_SET);
174 }
175 }
176 if (flags & log_flag_keep_pointer)
177 fseek(this_->f, -this_->data.len, SEEK_CUR);
178 fflush(this_->f);
179 if (!(flags & log_flag_keep_buffer)) {
180 g_free(this_->data.data);
181 this_->data.data=NULL;
182 this_->data.max_len=this_->data.len=0;
183 }
184 log_set_last_flush(this_);
185 }
186
187 static int
188 log_flush_required(struct log *this_)
189 {
190 return this_->data.len > this_->flush_size;
191 }
192
193
194 static void
195 log_change(struct log *this_)
196 {
197 log_flush(this_,0);
198 log_close(this_);
199 expand_filenames(this_);
200 if (! this_->lazy)
201 log_open(this_);
202 }
203
204 static int
205 log_change_required(struct log *this_)
206 {
207 char buffer[4096];
208
209 strftime_localtime(buffer, 4096, this_->filename);
210 return (strcmp(this_->filename_ex1, buffer) != 0);
211 }
212
213 static void
214 log_timer(struct log *this_)
215 {
216 #ifdef HAVE_SYS_TIME_H
217 struct timeval tv;
218 int delta;
219 gettimeofday(&tv, NULL);
220 delta=(tv.tv_sec-this_->last_flush.tv_sec)*1000+(tv.tv_usec-this_->last_flush.tv_usec)/1000;
221 dbg(1,"delta=%d flush_time=%d\n", delta, this_->flush_time);
222 if (this_->flush_time && delta >= this_->flush_time*1000)
223 log_flush(this_,0);
224 #endif
225 }
226
227 int
228 log_get_attr(struct log *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
229 {
230 return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter);
231 }
232
233
234 struct log *
235 log_new(struct attr * parent,struct attr **attrs)
236 {
237 struct log *ret=g_new0(struct log, 1);
238 struct attr *data,*overwrite,*lazy,*mkdir,*flush_size,*flush_time;
239 struct file_wordexp *wexp;
240 char *filename, **wexp_data;
241
242 dbg(1,"enter\n");
243 data=attr_search(attrs, NULL, attr_data);
244 if (! data)
245 return NULL;
246 filename=data->u.str;
247 wexp=file_wordexp_new(filename);
248 if (wexp && file_wordexp_get_count(wexp) > 0) {
249 wexp_data=file_wordexp_get_array(wexp);
250 filename=wexp_data[0];
251 }
252 if (filename)
253 ret->filename=g_strdup(filename);
254 if (wexp)
255 file_wordexp_destroy(wexp);
256 overwrite=attr_search(attrs, NULL, attr_overwrite);
257 if (overwrite)
258 ret->overwrite=overwrite->u.num;
259 lazy=attr_search(attrs, NULL, attr_lazy);
260 if (lazy)
261 ret->lazy=lazy->u.num;
262 mkdir=attr_search(attrs, NULL, attr_mkdir);
263 if (mkdir)
264 ret->mkdir=mkdir->u.num;
265 flush_size=attr_search(attrs, NULL, attr_flush_size);
266 if (flush_size)
267 ret->flush_size=flush_size->u.num;
268 flush_time=attr_search(attrs, NULL, attr_flush_time);
269 if (flush_time)
270 ret->flush_time=flush_time->u.num;
271 if (ret->flush_time) {
272 dbg(1,"interval %d\n", ret->flush_time*1000);
273 ret->timer_callback=callback_new_1(callback_cast(log_timer), ret);
274 ret->timer=event_add_timeout(ret->flush_time*1000, 1, ret->timer_callback);
275 }
276 expand_filenames(ret);
277 if (ret->lazy)
278 log_set_last_flush(ret);
279 else
280 log_open(ret);
281 ret->attrs=attr_list_dup(attrs);
282 return ret;
283 }
284
285 void
286 log_set_header(struct log *this_, char *data, int len)
287 {
288 this_->header.data=g_malloc(len);
289 this_->header.max_len=this_->header.len=len;
290 memcpy(this_->header.data, data, len);
291 }
292
293 void
294 log_set_trailer(struct log *this_, char *data, int len)
295 {
296 this_->trailer.data=g_malloc(len);
297 this_->trailer.max_len=this_->trailer.len=len;
298 memcpy(this_->trailer.data, data, len);
299 }
300
301 void
302 log_write(struct log *this_, char *data, int len, enum log_flags flags)
303 {
304 dbg(1,"enter\n");
305 if (log_change_required(this_)) {
306 dbg(1,"log_change");
307 log_change(this_);
308 }
309 if (flags & log_flag_replace_buffer)
310 this_->data.len=0;
311 if (this_->data.len + len > this_->data.max_len) {
312 dbg(2,"overflow\n");
313 this_->data.max_len+=16384;
314 this_->data.data=g_realloc(this_->data.data,this_->data.max_len);
315 }
316 memcpy(this_->data.data+this_->data.len, data, len);
317 this_->data.len+=len;
318 if (log_flush_required(this_) || (flags & log_flag_force_flush))
319 log_flush(this_, flags);
320 }
321
322 void *
323 log_get_buffer(struct log *this_, int *len)
324 {
325 if (len)
326 *len=this_->data.len;
327 return this_->data.data;
328 }
329
330
331 void
332 log_printf(struct log *this_, char *fmt, ...)
333 {
334 char buffer[LOG_BUFFER_SIZE];
335 int size;
336 va_list ap;
337
338 va_start(ap, fmt);
339
340 // Format the string and write it to the log
341 size = g_vsnprintf(buffer, LOG_BUFFER_SIZE, fmt, ap);
342 log_write(this_, buffer, size, 0);
343
344 va_end(ap);
345 }
346
347 void
348 log_destroy(struct log *this_)
349 {
350 attr_list_free(this_->attrs);
351 callback_destroy(this_->timer_callback);
352 event_remove_timeout(this_->timer);
353 log_flush(this_,0);
354 log_close(this_);
355 g_free(this_);
356 }

   
Visit the ZANavi Wiki