2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
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.
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.
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.
50 struct event_timeout *timer;
51 struct callback *timer_callback;
52 struct timeval last_flush;
56 struct log_data header;
58 struct log_data trailer;
63 strftime_localtime(char *buffer, int size, char *fmt)
70 strftime(buffer, 4096, fmt, tm);
74 expand_filenames(struct log *this_)
76 char *pos,buffer[4096];
79 strftime_localtime(buffer, 4096, this_->filename);
80 this_->filename_ex1=g_strdup(buffer);
81 if ((pos=strstr(this_->filename_ex1,"%i"))) {
82 #ifdef HAVE_API_ANDROID
87 g_free(this_->filename_ex2);
88 this_->filename_ex2=g_strdup_printf(this_->filename_ex1,i++);
89 } while (file_exists(this_->filename_ex2));
90 #ifdef HAVE_API_ANDROID
94 this_->filename_ex2=g_strdup(this_->filename_ex1);
98 log_set_last_flush(struct log *this_)
100 gettimeofday(&this_->last_flush, NULL);
104 log_open(struct log *this_)
107 if (this_->overwrite)
112 file_mkdir(this_->filename_ex2, 2);
113 this_->f=fopen(this_->filename_ex2, mode);
115 this_->f=fopen(this_->filename_ex2, "w");
118 if (!this_->overwrite)
119 fseek(this_->f, 0, SEEK_END);
120 this_->empty = !ftell(this_->f);
121 log_set_last_flush(this_);
125 log_close(struct log *this_)
129 if (this_->trailer.len)
130 fwrite(this_->trailer.data, 1, this_->trailer.len, this_->f);
137 log_flush(struct log *this_, enum log_flags flags)
140 if (this_->lazy && !this_->f) {
141 if (!this_->data.len)
148 if (this_->header.len)
149 fwrite(this_->header.data, 1, this_->header.len, this_->f);
150 if (this_->header.len || this_->data.len)
153 fwrite(this_->data.data, 1, this_->data.len, this_->f);
154 #ifndef HAVE_API_WIN32_BASE
155 if (flags & log_flag_truncate) {
157 ftruncate(fileno(this_->f), pos);
160 if (this_->trailer.len) {
163 fwrite(this_->trailer.data, 1, this_->trailer.len, this_->f);
164 fseek(this_->f, pos, SEEK_SET);
167 if (flags & log_flag_keep_pointer)
168 fseek(this_->f, -this_->data.len, SEEK_CUR);
170 if (!(flags & log_flag_keep_buffer)) {
171 g_free(this_->data.data);
172 this_->data.data=NULL;
173 this_->data.max_len=this_->data.len=0;
175 log_set_last_flush(this_);
179 log_flush_required(struct log *this_)
181 return this_->data.len > this_->flush_size;
186 log_change(struct log *this_)
190 expand_filenames(this_);
196 log_change_required(struct log *this_)
200 strftime_localtime(buffer, 4096, this_->filename);
201 return (strcmp(this_->filename_ex1, buffer) != 0);
205 log_timer(struct log *this_)
209 gettimeofday(&tv, NULL);
210 delta=(tv.tv_sec-this_->last_flush.tv_sec)*1000+(tv.tv_usec-this_->last_flush.tv_usec)/1000;
211 dbg(1,"delta=%d flush_time=%d\n", delta, this_->flush_time);
212 if (this_->flush_time && delta >= this_->flush_time*1000)
217 log_get_attr(struct log *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
219 return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter);
224 log_new(struct attr * parent,struct attr **attrs)
226 struct log *ret=g_new0(struct log, 1);
227 struct attr *data,*overwrite,*lazy,*mkdir,*flush_size,*flush_time;
228 struct file_wordexp *wexp;
229 char *filename, **wexp_data;
232 data=attr_search(attrs, NULL, attr_data);
235 filename=data->u.str;
236 wexp=file_wordexp_new(filename);
237 if (wexp && file_wordexp_get_count(wexp) > 0) {
238 wexp_data=file_wordexp_get_array(wexp);
239 filename=wexp_data[0];
242 ret->filename=g_strdup(filename);
244 file_wordexp_destroy(wexp);
245 overwrite=attr_search(attrs, NULL, attr_overwrite);
247 ret->overwrite=overwrite->u.num;
248 lazy=attr_search(attrs, NULL, attr_lazy);
250 ret->lazy=lazy->u.num;
251 mkdir=attr_search(attrs, NULL, attr_mkdir);
253 ret->mkdir=mkdir->u.num;
254 flush_size=attr_search(attrs, NULL, attr_flush_size);
256 ret->flush_size=flush_size->u.num;
257 flush_time=attr_search(attrs, NULL, attr_flush_time);
259 ret->flush_time=flush_time->u.num;
260 if (ret->flush_time) {
261 dbg(1,"interval %d\n", ret->flush_time*1000);
262 ret->timer_callback=callback_new_1(callback_cast(log_timer), ret);
263 ret->timer=event_add_timeout(ret->flush_time*1000, 1, ret->timer_callback);
265 expand_filenames(ret);
267 log_set_last_flush(ret);
270 ret->attrs=attr_list_dup(attrs);
275 log_set_header(struct log *this_, char *data, int len)
277 this_->header.data=g_malloc(len);
278 this_->header.max_len=this_->header.len=len;
279 memcpy(this_->header.data, data, len);
283 log_set_trailer(struct log *this_, char *data, int len)
285 this_->trailer.data=g_malloc(len);
286 this_->trailer.max_len=this_->trailer.len=len;
287 memcpy(this_->trailer.data, data, len);
291 log_write(struct log *this_, char *data, int len, enum log_flags flags)
294 if (log_change_required(this_)) {
298 if (flags & log_flag_replace_buffer)
300 if (this_->data.len + len > this_->data.max_len) {
302 this_->data.max_len+=16384;
303 this_->data.data=g_realloc(this_->data.data,this_->data.max_len);
305 memcpy(this_->data.data+this_->data.len, data, len);
306 this_->data.len+=len;
307 if (log_flush_required(this_) || (flags & log_flag_force_flush))
308 log_flush(this_, flags);
312 log_get_buffer(struct log *this_, int *len)
315 *len=this_->data.len;
316 return this_->data.data;
321 log_printf(struct log *this_, char *fmt, ...)
323 char buffer[LOG_BUFFER_SIZE];
329 // Format the string and write it to the log
330 size = vsnprintf(buffer, LOG_BUFFER_SIZE, fmt, ap);
331 log_write(this_, buffer, size, 0);
337 log_destroy(struct log *this_)
339 callback_destroy(this_->timer_callback);
340 event_remove_timeout(this_->timer);