Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_nodup_log.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
27#ifndef _GNU_SOURCE
29#define _GNU_SOURCE
31#define _GNU_SOURCE_WAS_NOT_DEFINED
32#endif
33#include <stdio.h>
34#include <stdarg.h>
35#ifdef _GNU_SOURCE_WAS_NOT_DEFINED
36#undef _GNU_SOURCE
37#endif
38
39#include "nilorea/n_common.h"
40#include "nilorea/n_log.h"
41#include "nilorea/n_str.h"
42#include "nilorea/n_list.h"
43#include "nilorea/n_hash.h"
44
45#include "nilorea/n_nodup_log.h"
46
49
54int init_nodup_log(size_t max) {
55 if (_n_nodup_table != NULL) {
56 n_log(LOG_ERR, "Could not allocate the internal hash table because it's already done");
57 return FALSE;
58 }
59 if (max == 0)
60 max = 1024;
61
63
64 if (_n_nodup_table == NULL) {
65 n_log(LOG_ERR, "Could not allocate the internal hash with size %zu", max);
66 return FALSE;
67 } else {
68 n_log(LOG_DEBUG, "LOGGING: nodup system activated with a hash table of %zu cells", max);
69 }
70
71 return TRUE;
72} /* init_nodup_log() */
73
79 __n_assert(_n_nodup_table, return FALSE);
81} /* empty_nodup_table() */
82
88 __n_assert(_n_nodup_table, return FALSE);
90} /* close_nodup_log() */
91
99static char* get_nodup_key(const char* file, const char* func, int line) {
100 N_STR* nstr = NULL;
101 char* ptr = NULL;
102 nstrprintf(nstr, "%s%s%d", file, func, line);
103 __n_assert(nstr, return NULL);
104 ptr = nstr->data;
105 Free(nstr);
106 return ptr;
107} /* get_nodup_key */
108
117static char* get_nodup_indexed_key(const char* file, const char* func, const char* prefix, int line) {
118 N_STR* nstr = NULL;
119 char* ptr = NULL;
120 nstrprintf(nstr, "%s%s%s%d", file, func, prefix, line);
121 __n_assert(nstr, return NULL);
122 ptr = nstr->data;
123 Free(nstr);
124 return ptr;
125} /* get_nodup_indexed_key */
126
136int check_n_log_dup(const char* log, const char* file, const char* func, int line) {
137 const HASH_NODE* node = NULL;
138 char* key = NULL;
139
140 /* check if the nopdup session is on, else do a normal n_log */
141 if (!_n_nodup_table) {
142 return 3;
143 }
144
145 key = get_nodup_key(file, func, line);
146
147 __n_assert(key, return FALSE);
148
150
151 Free(key);
152
153 if (node) {
154 if (strcmp(log, node->data.string) == 0) {
155 return 1;
156 }
157 return 2;
158 }
159 return 0;
160
161} /* check_n_log_dup(...) */
162
173int check_n_log_dup_indexed(const char* log, const char* file, const char* func, int line, const char* prefix) {
174 const HASH_NODE* node = NULL;
175 char* key = NULL;
176
177 /* check if the nopdup session is on, else do a normal n_log */
178 if (!_n_nodup_table) {
179 return 3;
180 }
181
182 key = get_nodup_indexed_key(file, func, prefix, line);
183
184 __n_assert(key, return FALSE);
185
187
188 Free(key);
189
190 if (node) {
191 if (strcmp(log, node->data.string) == 0) {
192 return 1;
193 }
194 return 2;
195 }
196 return 0;
197} /* check_nolog_dup_indexed() */
198
207void _n_nodup_log(int LEVEL, const char* file, const char* func, int line, const char* format, ...) {
208 __n_assert(file, return);
209 __n_assert(func, return);
210 __n_assert(format, return);
211
212 HASH_NODE* node = NULL;
213 va_list args;
214
215 char* syslogbuffer = NULL;
216
217 va_start(args, format);
218 if (vasprintf(&syslogbuffer, format, args) == -1) {
219 int error = errno;
220 n_log(LOG_ERR, "=>%s:%s:%d unable to parse '%s', %s", file, func, line, format, strerror(error));
221 va_end(args);
222 syslogbuffer = NULL;
223 return;
224 }
225 va_end(args);
226
227 char* key = get_nodup_key(file, func, line);
228 int is_dup = check_n_log_dup(syslogbuffer, file, func, line);
229
230 switch (is_dup) {
231 /* new log entry for file,func,line */
232 case 0:
233 if (_n_nodup_table) {
234 ht_put_string(_n_nodup_table, key, syslogbuffer);
235 }
236 _n_log(LEVEL, file, func, line, "%s", syslogbuffer);
237 break;
238
239 /* exising and same log entry, do nothing (maybe latter we will add a timeout to repeat logging) */
240 case 1:
241 break;
242 /* existing but different entry. We have to refresh and log it one time*/
243 case 2:
245 if (node) {
246 Free(node->data.string);
247 node->data.string = syslogbuffer;
248 syslogbuffer = NULL;
249 }
250 _n_log(LEVEL, file, func, line, "%s", node ? node->data.string : "");
251 break;
252 /* no nodup session started, normal loggin */
253 case 3:
254 default:
255 _n_log(LEVEL, file, func, line, "%s", syslogbuffer);
256 break;
257 }
258
259 Free(syslogbuffer);
260 Free(key);
261
262} /* _n_nodup_log() */
263
273void _n_nodup_log_indexed(int LEVEL, const char* prefix, const char* file, const char* func, int line, const char* format, ...) {
274 HASH_NODE* node = NULL;
275 va_list args;
276
277 char* syslogbuffer = NULL;
278
279 va_start(args, format);
280 if (vasprintf(&syslogbuffer, format, args) == -1) {
281 int error = errno;
282 n_log(LOG_ERR, "=>%s:%s:%d unable to parse '%s:%s', %s", file, func, line, prefix, format, strerror(error));
283 va_end(args);
284 syslogbuffer = NULL;
285 return;
286 }
287 va_end(args);
288
289 char* key = get_nodup_indexed_key(file, func, prefix, line);
290 int is_dup = check_n_log_dup_indexed(syslogbuffer, file, func, line, prefix);
291
292 switch (is_dup) {
293 /* new log entry for file,func,line */
294 case 0:
295 if (_n_nodup_table) {
296 ht_put_string(_n_nodup_table, key, syslogbuffer);
297 }
298 _n_log(LEVEL, file, func, line, "%s", syslogbuffer);
299 break;
300
301 /* exising and same log entry, do nothing (maybe latter we will add a timeout to repeat logging) */
302 case 1:
303 break;
304 /* existing but different entry. We have to refresh and log it one time*/
305 case 2:
307 if (node) {
308 Free(node->data.string);
309 node->data.string = syslogbuffer;
310 syslogbuffer = NULL;
311 }
312 _n_log(LEVEL, file, func, line, "%s", node ? node->data.string : "");
313 break;
314 /* no nodup session started, normal loggin */
315 case 3:
316 default:
317 _n_log(LEVEL, file, func, line, "%s", syslogbuffer);
318 break;
319 }
320
321 Free(syslogbuffer);
322 Free(key);
323
324} /* _n_nodup_log_indexed() */
325
333int dump_nodup_log(char* file) {
334 FILE* out = NULL;
335 __n_assert(file, return FALSE);
336 __n_assert(_n_nodup_table, return FALSE);
337
338 char* tmpfile = NULL;
339 n_log(LOG_DEBUG, "outfile:%s", file);
340 strprintf(tmpfile, "%s.tmp", file);
341 if (!tmpfile) {
342 n_log(LOG_ERR, "could not create tmp file name from filename %s", _str(file));
343 return FALSE;
344 }
345
346 int fd = open(tmpfile, O_CREAT | O_WRONLY | O_TRUNC, 0600); // Only owner can read/write
347 if (fd < 0) {
348 n_log(LOG_ERR, "could not create file %s with 0600 permissions", _str(tmpfile));
349 Free(tmpfile);
350 return FALSE;
351 }
352
353 out = fdopen(fd, "wb");
354 __n_assert(out, close(fd); Free(tmpfile); return FALSE);
355
356 if (_n_nodup_table) {
357 for (unsigned long int it = 0; it < _n_nodup_table->size; it++) {
358 list_foreach(list_node, _n_nodup_table->hash_table[it]) {
359 const HASH_NODE* hash_node = (const HASH_NODE*)list_node->ptr;
360 fprintf(out, "%s\n", hash_node->data.string);
361 }
362 }
363 }
364 fclose(out);
365
366 if (rename(tmpfile, file) != 0) {
367 int error = errno;
368 n_log(LOG_ERR, "could not rename '%s' to '%s' , %s", tmpfile, file,
369 strerror(error));
370 }
371 Free(tmpfile);
372
373 return TRUE;
374
375} /* dump_nodup_log() */
char * key
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:278
#define _str(__PTR)
define true
Definition n_common.h:192
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:262
union HASH_DATA data
data inside the node
Definition n_hash.h:121
LIST ** hash_table
HASH_CLASSIC mode: preallocated hash table.
Definition n_hash.h:145
char * string
char *type
Definition n_hash.h:107
size_t size
size of the hash table
Definition n_hash.h:139
int destroy_ht(HASH_TABLE **table)
empty a table and destroy it
Definition n_hash.c:2234
HASH_TABLE * new_ht(size_t size)
Create a hash table with the given size.
Definition n_hash.c:2001
int empty_ht(HASH_TABLE *table)
empty a table
Definition n_hash.c:2224
int ht_put_string(HASH_TABLE *table, const char *key, char *string)
put a string value (copy/dup) with given key in the targeted hash table
Definition n_hash.c:2167
HASH_NODE * ht_get_node(HASH_TABLE *table, const char *key)
get node at 'key' from 'table'
Definition n_hash.c:2061
structure of a hash table node
Definition n_hash.h:111
structure of a hash table
Definition n_hash.h:137
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper, safe for node removal during iteration.
Definition n_list.h:88
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:88
#define LOG_DEBUG
debug-level messages
Definition n_log.h:83
#define LOG_ERR
error conditions
Definition n_log.h:75
void _n_log(int level, const char *file, const char *func, int line, const char *format,...)
Logging function.
Definition n_log.c:267
int init_nodup_log(size_t max)
initialize the no duplicate logging system
Definition n_nodup_log.c:54
int dump_nodup_log(char *file)
Dump the duplicate error log hash table in a file The table is first written to a temporary file whic...
int close_nodup_log()
Empty nodup logtable and close the no duplicate logging session.
Definition n_nodup_log.c:87
void _n_nodup_log(int LEVEL, const char *file, const char *func, int line, const char *format,...)
Logging function.
int empty_nodup_table()
Empty the nodup internal table.
Definition n_nodup_log.c:78
void _n_nodup_log_indexed(int LEVEL, const char *prefix, const char *file, const char *func, int line, const char *format,...)
Logging function.
char * data
the string
Definition n_str.h:62
#define strprintf(__n_var,...)
Macro to quickly allocate and sprintf to a char.
Definition n_str.h:93
#define nstrprintf(__nstr_var, __format,...)
Macro to quickly allocate and sprintf to N_STR.
Definition n_str.h:115
A box including a string and his lenght.
Definition n_str.h:60
Common headers and low-level functions & define.
Hash functions and table.
List structures and definitions.
int vasprintf(char **strp, const char *fmt, va_list ap)
snprintf from a va_list, helper for asprintf
Definition n_log.c:226
Generic log system.
int check_n_log_dup(const char *log, const char *file, const char *func, int line)
check if a log was already done or not at the given line, func, file
int check_n_log_dup_indexed(const char *log, const char *file, const char *func, int line, const char *prefix)
check if a log was already done or not at the given line, func, file
static char * get_nodup_key(const char *file, const char *func, int line)
internal, get a key for a log entry
Definition n_nodup_log.c:99
static HASH_TABLE * _n_nodup_table
internal: no dup hash_table log save
Definition n_nodup_log.c:48
static char * get_nodup_indexed_key(const char *file, const char *func, const char *prefix, int line)
internal, get a key for an indexed log entry
Generic No Dup Log system.
N_STR and string function declaration.