Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/logging.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1613 - (show annotations) (download) (as text)
Thu Oct 23 17:56:26 2014 UTC (10 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 12996 byte(s)
Comment fixes, tidy-up and one bug fixed.

1 /***************************************
2 Functions to handle logging functions.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2014 Andrew M. Bishop
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Affero General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ***************************************/
21
22
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <sys/time.h>
29
30 #include "logging.h"
31
32
33 /* Global variables */
34
35 /*+ The option to print the output in a way that allows logging to a file. +*/
36 int option_loggable=0;
37
38 /*+ The option to print elapsed time with the output. +*/
39 int option_logtime=0;
40
41 /*+ The option to print memory usage with the output. +*/
42 int option_logmemory=0;
43
44
45 /* Local data types */
46
47 /*+ A structure to contain the list of allocated memory. +*/
48 struct mallocinfo
49 {
50 void *address; /*+ The address of the allocated memory. +*/
51 size_t size; /*+ The size of the allocated memory. +*/
52 };
53
54
55 /* Local functions */
56
57 static void vfprintf_first(FILE *file,const char *format,va_list ap);
58 static void vfprintf_middle(FILE *file,const char *format,va_list ap);
59 static void vfprintf_last(FILE *file,const char *format,va_list ap);
60
61 static void fprintf_elapsed_time(FILE *file,struct timeval *start);
62 static void fprintf_max_memory(FILE *file,size_t max_alloc,size_t max_mmap);
63
64
65 /* Local variables */
66
67 /*+ The time that program_start() was called. +*/
68 static struct timeval program_start_time;
69
70 /*+ The time that printf_first() was called. +*/
71 static struct timeval function_start_time;
72
73 /*+ The list of allocated memory. +*/
74 static struct mallocinfo *mallocedmem;
75
76 /*+ The number of allocated memory blocks. +*/
77 static int nmallocedmem=0;
78
79 /*+ The length of the string printed out last time. +*/
80 static int printed_length=0;
81
82 /*+ The maximum amount of memory allocated and memory mapped since starting the program. +*/
83 static size_t program_max_alloc=0,program_max_mmap=0;
84
85 /*+ The maximum amount of memory allocated and memory mapped since starting the function. +*/
86 static size_t function_max_alloc=0,function_max_mmap=0;
87
88 /*+ The current amount of memory allocated and memory mapped. +*/
89 static size_t current_alloc=0,current_mmap=0;
90
91
92 /*++++++++++++++++++++++++++++++++++++++
93 Record the time that the program started.
94 ++++++++++++++++++++++++++++++++++++++*/
95
96 void printf_program_start(void)
97 {
98 gettimeofday(&program_start_time,NULL);
99
100 program_max_alloc=program_max_mmap=0;
101 }
102
103
104 /*++++++++++++++++++++++++++++++++++++++
105 Record the time that the program started.
106 ++++++++++++++++++++++++++++++++++++++*/
107
108 void printf_program_end(void)
109 {
110 if(option_logtime || option_logmemory)
111 {
112 if(option_logtime)
113 fprintf_elapsed_time(stdout,&program_start_time);
114
115 if(option_logmemory)
116 fprintf_max_memory(stdout,program_max_alloc,program_max_mmap);
117
118 printf("Finish Program\n");
119
120 if(option_logtime==2)
121 printf("[ m:ss.micros] ");
122 else if(option_logtime==1)
123 printf("[ m:ss.mil] ");
124
125 if(option_logmemory)
126 printf("[RAM,FILE MB] ");
127
128 if(option_logtime)
129 printf("elapsed time");
130
131 if(option_logmemory)
132 {
133 if(option_logtime)
134 printf(", ");
135 printf("maximum memory");
136 }
137
138 printf("\n");
139
140 fflush(stdout);
141 }
142 }
143
144
145 /*++++++++++++++++++++++++++++++++++++++
146 Print the first message in an overwriting sequence (to stdout).
147
148 const char *format The format string.
149
150 ... The other arguments.
151 ++++++++++++++++++++++++++++++++++++++*/
152
153 void printf_first(const char *format, ...)
154 {
155 va_list ap;
156
157 if(option_logtime)
158 gettimeofday(&function_start_time,NULL);
159
160 if(option_logmemory)
161 {
162 function_max_alloc=current_alloc;
163 function_max_mmap=current_mmap;
164 }
165
166 if(option_loggable)
167 return;
168
169 va_start(ap,format);
170
171 vfprintf_first(stdout,format,ap);
172
173 va_end(ap);
174 }
175
176
177 /*++++++++++++++++++++++++++++++++++++++
178 Print the middle message in an overwriting sequence (to stdout).
179
180 const char *format The format string.
181
182 ... The other arguments.
183 ++++++++++++++++++++++++++++++++++++++*/
184
185 void printf_middle(const char *format, ...)
186 {
187 va_list ap;
188
189 if(option_loggable)
190 return;
191
192 va_start(ap,format);
193
194 vfprintf_middle(stdout,format,ap);
195
196 va_end(ap);
197 }
198
199
200 /*++++++++++++++++++++++++++++++++++++++
201 Print the last message in an overwriting sequence (to stdout).
202
203 const char *format The format string.
204
205 ... The other arguments.
206 ++++++++++++++++++++++++++++++++++++++*/
207
208 void printf_last(const char *format, ...)
209 {
210 va_list ap;
211
212 va_start(ap,format);
213
214 vfprintf_last(stdout,format,ap);
215
216 va_end(ap);
217 }
218
219
220 /*++++++++++++++++++++++++++++++++++++++
221 Print the first message in an overwriting sequence to a specified file.
222
223 FILE *file The file to write to.
224
225 const char *format The format string.
226
227 ... The other arguments.
228 ++++++++++++++++++++++++++++++++++++++*/
229
230 void fprintf_first(FILE *file,const char *format, ...)
231 {
232 va_list ap;
233
234 if(option_logtime)
235 gettimeofday(&function_start_time,NULL);
236
237 if(option_logmemory)
238 {
239 function_max_alloc=current_alloc;
240 function_max_mmap=current_mmap;
241 }
242
243 if(option_loggable)
244 return;
245
246 va_start(ap,format);
247
248 vfprintf_first(file,format,ap);
249
250 va_end(ap);
251 }
252
253
254 /*++++++++++++++++++++++++++++++++++++++
255 Print the middle message in an overwriting sequence to a specified file.
256
257 FILE *file The file to write to.
258
259 const char *format The format string.
260
261 ... The other arguments.
262 ++++++++++++++++++++++++++++++++++++++*/
263
264 void fprintf_middle(FILE *file,const char *format, ...)
265 {
266 va_list ap;
267
268 if(option_loggable)
269 return;
270
271 va_start(ap,format);
272
273 vfprintf_middle(file,format,ap);
274
275 va_end(ap);
276 }
277
278
279 /*++++++++++++++++++++++++++++++++++++++
280 Print the last message in an overwriting sequence to a specified file.
281
282 FILE *file The file to write to.
283
284 const char *format The format string.
285
286 ... The other arguments.
287 ++++++++++++++++++++++++++++++++++++++*/
288
289 void fprintf_last(FILE *file,const char *format, ...)
290 {
291 va_list ap;
292
293 va_start(ap,format);
294
295 vfprintf_last(file,format,ap);
296
297 va_end(ap);
298 }
299
300
301 /*++++++++++++++++++++++++++++++++++++++
302 Record the memory allocations (record the amount in use).
303
304 void *address The address that has been allocated.
305
306 size_t size The size of the memory that has been allocated.
307 ++++++++++++++++++++++++++++++++++++++*/
308
309 void log_malloc(void *address,size_t size)
310 {
311 int i;
312
313 if(!option_logmemory)
314 return;
315
316 /* Store the information about the allocated memory */
317
318 for(i=0;i<nmallocedmem;i++)
319 if(mallocedmem[i].address==address)
320 {
321 size=size-mallocedmem[i].size;
322 mallocedmem[i].size+=size;
323 break;
324 }
325
326 if(i==nmallocedmem)
327 {
328 mallocedmem=(struct mallocinfo*)realloc((void*)mallocedmem,(nmallocedmem+1)*sizeof(struct mallocinfo));
329
330 mallocedmem[nmallocedmem].address=address;
331 mallocedmem[nmallocedmem].size=size;
332
333 nmallocedmem++;
334 }
335
336 /* Increase the sum of allocated memory */
337
338 current_alloc+=size;
339
340 if(current_alloc>function_max_alloc)
341 function_max_alloc=current_alloc;
342
343 if(current_alloc>program_max_alloc)
344 program_max_alloc=current_alloc;
345 }
346
347
348 /*++++++++++++++++++++++++++++++++++++++
349 Record the memory de-allocations.
350
351 void *address The address that has been freed.
352 ++++++++++++++++++++++++++++++++++++++*/
353
354 void log_free(void *address)
355 {
356 size_t size=0;
357 int i;
358
359 if(!option_logmemory)
360 return;
361
362 /* Remove the information about the allocated memory */
363
364 for(i=0;i<nmallocedmem;i++)
365 if(mallocedmem[i].address==address)
366 {
367 size=mallocedmem[i].size;
368 break;
369 }
370
371 logassert(i!=nmallocedmem,"Memory freed with log_free() was not allocated with log_[cm]alloc()");
372
373 nmallocedmem--;
374
375 if(nmallocedmem>i)
376 memmove(&mallocedmem[i],&mallocedmem[i+1],(nmallocedmem-i)*sizeof(struct mallocinfo));
377
378 /* Reduce the sum of allocated memory */
379
380 current_alloc-=size;
381 }
382
383
384 /*++++++++++++++++++++++++++++++++++++++
385 Record the amount of memory that has been mapped into files.
386
387 size_t size The size of the file that has been mapped.
388 ++++++++++++++++++++++++++++++++++++++*/
389
390 void log_mmap(size_t size)
391 {
392 if(!option_logmemory)
393 return;
394
395 current_mmap+=size;
396
397 if(current_mmap>function_max_mmap)
398 function_max_mmap=current_mmap;
399
400 if(current_mmap>program_max_mmap)
401 program_max_mmap=current_mmap;
402 }
403
404
405 /*++++++++++++++++++++++++++++++++++++++
406 Record the amount of memory that has been unmapped from files.
407
408 size_t size The size of the file that has been unmapped.
409 ++++++++++++++++++++++++++++++++++++++*/
410
411 void log_munmap(size_t size)
412 {
413 if(!option_logmemory)
414 return;
415
416 current_mmap-=size;
417 }
418
419
420 /*++++++++++++++++++++++++++++++++++++++
421 Do the work to print the first message in an overwriting sequence.
422
423 FILE *file The file to write to.
424
425 const char *format The format string.
426
427 va_list ap The other arguments.
428 ++++++++++++++++++++++++++++++++++++++*/
429
430 static void vfprintf_first(FILE *file,const char *format,va_list ap)
431 {
432 int retval;
433
434 if(option_logtime)
435 fprintf_elapsed_time(file,&function_start_time);
436
437 if(option_logmemory)
438 fprintf_max_memory(file,function_max_alloc,function_max_mmap);
439
440 retval=vfprintf(file,format,ap);
441 fflush(file);
442
443 if(retval>0)
444 printed_length=retval;
445 }
446
447
448 /*++++++++++++++++++++++++++++++++++++++
449 Do the work to print the middle message in an overwriting sequence.
450
451 FILE *file The file to write to.
452
453 const char *format The format string.
454
455 va_list ap The other arguments.
456 ++++++++++++++++++++++++++++++++++++++*/
457
458 static void vfprintf_middle(FILE *file,const char *format,va_list ap)
459 {
460 int retval;
461
462 fputc('\r',file);
463
464 if(option_logtime)
465 fprintf_elapsed_time(file,&function_start_time);
466
467 if(option_logmemory)
468 fprintf_max_memory(file,function_max_alloc,function_max_mmap);
469
470 retval=vfprintf(file,format,ap);
471 fflush(file);
472
473 if(retval>0)
474 {
475 int new_printed_length=retval;
476
477 while(retval++<printed_length)
478 fputc(' ',file);
479
480 printed_length=new_printed_length;
481 }
482 }
483
484
485 /*++++++++++++++++++++++++++++++++++++++
486 Do the work to print the last message in an overwriting sequence.
487
488 FILE *file The file to write to.
489
490 const char *format The format string.
491
492 va_list ap The other arguments.
493 ++++++++++++++++++++++++++++++++++++++*/
494
495 static void vfprintf_last(FILE *file,const char *format,va_list ap)
496 {
497 int retval;
498
499 if(!option_loggable)
500 fputc('\r',file);
501
502 if(option_logtime)
503 fprintf_elapsed_time(file,&function_start_time);
504
505 if(option_logmemory)
506 fprintf_max_memory(file,function_max_alloc,function_max_mmap);
507
508 retval=vfprintf(file,format,ap);
509
510 if(retval>0)
511 while(retval++<printed_length)
512 fputc(' ',file);
513
514 fputc('\n',file);
515 fflush(file);
516 }
517
518
519 /*++++++++++++++++++++++++++++++++++++++
520 Print the elapsed time without a following newline.
521
522 FILE *file The file to print to.
523
524 struct timeval *start The start time from which the elapsed time is to be printed.
525 ++++++++++++++++++++++++++++++++++++++*/
526
527 static void fprintf_elapsed_time(FILE *file,struct timeval *start)
528 {
529 struct timeval finish,elapsed;
530
531 gettimeofday(&finish,NULL);
532
533 elapsed.tv_sec =finish.tv_sec -start->tv_sec;
534 elapsed.tv_usec=finish.tv_usec-start->tv_usec;
535 if(elapsed.tv_usec<0)
536 {
537 elapsed.tv_sec -=1;
538 elapsed.tv_usec+=1000000;
539 }
540
541 if(option_logtime==2)
542 fprintf(file,"[%2ld:%02ld.%06ld] ",elapsed.tv_sec/60,elapsed.tv_sec%60,elapsed.tv_usec);
543 else
544 fprintf(file,"[%2ld:%02ld.%03ld] ",elapsed.tv_sec/60,elapsed.tv_sec%60,elapsed.tv_usec/1000);
545 }
546
547
548 /*++++++++++++++++++++++++++++++++++++++
549 Print the maximum used memory without a following newline.
550
551 FILE *file The file to print to.
552
553 size_t max_alloc The maximum amount of allocated memory.
554
555 size_t max_mmap The maximum amount of memory mapped memory.
556 ++++++++++++++++++++++++++++++++++++++*/
557
558 static void fprintf_max_memory(FILE *file,size_t max_alloc,size_t max_mmap)
559 {
560 fprintf(file,"[%3d, %3d MB] ",max_alloc/(1024*1024),max_mmap/(1024*1024));
561 }
562
563
564 /*++++++++++++++++++++++++++++++++++++++
565 Log a fatal error and exit
566
567 const char *message The error message.
568
569 const char *file The file in which the error occured.
570
571 int line The line number in the file at which the error occured.
572 ++++++++++++++++++++++++++++++++++++++*/
573
574 void _logassert(const char *message,const char *file,int line)
575 {
576 fprintf(stderr,"Routino Fatal Error (%s:%d): %s\n",file,line,message);
577
578 exit(EXIT_FAILURE);
579 }