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 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
28#ifndef _GNU_SOURCE
30#define _GNU_SOURCE
32#define _GNU_SOURCE_WAS_NOT_DEFINED
33#endif
34#include <stdio.h>
35#include <stdarg.h>
36#ifdef _GNU_SOURCE_WAS_NOT_DEFINED
37#undef _GNU_SOURCE
38#endif
39
40#include "nilorea/n_common.h"
41#include "nilorea/n_log.h"
42#include "nilorea/n_str.h"
43#include "nilorea/n_list.h"
44#include "nilorea/n_hash.h"
45
46#include "nilorea/n_nodup_log.h"
47
50
55int init_nodup_log(size_t max) {
56 if (_n_nodup_table != NULL) {
57 n_log(LOG_ERR, "Could not allocate the internal hash table because it's already done");
58 return FALSE;
59 }
60 if (max == 0)
61 max = 1024;
62
64
65 if (_n_nodup_table == NULL) {
66 n_log(LOG_ERR, "Could not allocate the internal hash with size %zu", max);
67 return FALSE;
68 } else {
69 n_log(LOG_DEBUG, "LOGGING: nodup system activated with a hash table of %zu cells", max);
70 }
71
72 return TRUE;
73} /* init_nodup_log() */
74
80 __n_assert(_n_nodup_table, return FALSE);
82} /* empty_nodup_table() */
83
89 __n_assert(_n_nodup_table, return FALSE);
91} /* close_nodup_log() */
92
100static char* get_nodup_key(const char* file, const char* func, int line) {
101 N_STR* nstr = NULL;
102 char* ptr = NULL;
103 nstrprintf(nstr, "%s%s%d", file, func, line);
104 __n_assert(nstr, return NULL);
105 ptr = nstr->data;
106 Free(nstr);
107 return ptr;
108} /* get_nodup_key */
109
118static char* get_nodup_indexed_key(const char* file, const char* func, const char* prefix, int line) {
119 N_STR* nstr = NULL;
120 char* ptr = NULL;
121 nstrprintf(nstr, "%s%s%s%d", file, func, prefix, line);
122 __n_assert(nstr, return NULL);
123 ptr = nstr->data;
124 Free(nstr);
125 return ptr;
126} /* get_nodup_indexed_key */
127
137int check_n_log_dup(const char* log, const char* file, const char* func, int line) {
138 const HASH_NODE* node = NULL;
139 char* key = NULL;
140
141 /* check if the nopdup session is on, else do a normal n_log */
142 if (!_n_nodup_table) {
143 return 3;
144 }
145
146 key = get_nodup_key(file, func, line);
147
148 __n_assert(key, return FALSE);
149
151
152 Free(key);
153
154 if (node) {
155 if (strcmp(log, node->data.string) == 0) {
156 return 1;
157 }
158 return 2;
159 }
160 return 0;
161
162} /* check_n_log_dup(...) */
163
174int check_n_log_dup_indexed(const char* log, const char* file, const char* func, int line, const char* prefix) {
175 const HASH_NODE* node = NULL;
176 char* key = NULL;
177
178 /* check if the nopdup session is on, else do a normal n_log */
179 if (!_n_nodup_table) {
180 return 3;
181 }
182
183 key = get_nodup_indexed_key(file, func, prefix, line);
184
185 __n_assert(key, return FALSE);
186
188
189 Free(key);
190
191 if (node) {
192 if (strcmp(log, node->data.string) == 0) {
193 return 1;
194 }
195 return 2;
196 }
197 return 0;
198} /* check_nolog_dup_indexed() */
199
208void _n_nodup_log(int LEVEL, const char* file, const char* func, int line, const char* format, ...) {
209 __n_assert(file, return);
210 __n_assert(func, return);
211 __n_assert(format, return);
212
213 HASH_NODE* node = NULL;
214 va_list args;
215
216 char* syslogbuffer = NULL;
217
218 va_start(args, format);
219 if (vasprintf(&syslogbuffer, format, args) == -1) {
220 int error = errno;
221 n_log(LOG_ERR, "=>%s:%s:%d unable to parse '%s', %s", file, func, line, format, strerror(error));
222 va_end(args);
223 syslogbuffer = NULL;
224 return;
225 }
226 va_end(args);
227
228 char* key = get_nodup_key(file, func, line);
229 int is_dup = check_n_log_dup(syslogbuffer, file, func, line);
230
231 switch (is_dup) {
232 /* new log entry for file,func,line */
233 case 0:
234 if (_n_nodup_table) {
235 ht_put_string(_n_nodup_table, key, syslogbuffer);
236 }
237 _n_log(LEVEL, file, func, line, "%s", syslogbuffer);
238 break;
239
240 /* exising and same log entry, do nothing (maybe latter we will add a timeout to repeat logging) */
241 case 1:
242 break;
243 /* existing but different entry. We have to refresh and log it one time*/
244 case 2:
246 if (node) {
247 Free(node->data.string);
248 node->data.string = syslogbuffer;
249 syslogbuffer = NULL;
250 }
251 _n_log(LEVEL, file, func, line, "%s", node ? node->data.string : "");
252 break;
253 /* no nodup session started, normal loggin */
254 case 3:
255 default:
256 _n_log(LEVEL, file, func, line, "%s", syslogbuffer);
257 break;
258 }
259
260 Free(syslogbuffer);
261 Free(key);
262
263} /* _n_nodup_log() */
264
274void _n_nodup_log_indexed(int LEVEL, const char* prefix, const char* file, const char* func, int line, const char* format, ...) {
275 HASH_NODE* node = NULL;
276 va_list args;
277
278 char* syslogbuffer = NULL;
279
280 va_start(args, format);
281 if (vasprintf(&syslogbuffer, format, args) == -1) {
282 int error = errno;
283 n_log(LOG_ERR, "=>%s:%s:%d unable to parse '%s:%s', %s", file, func, line, prefix, format, strerror(error));
284 va_end(args);
285 syslogbuffer = NULL;
286 return;
287 }
288 va_end(args);
289
290 char* key = get_nodup_indexed_key(file, func, prefix, line);
291 int is_dup = check_n_log_dup_indexed(syslogbuffer, file, func, line, prefix);
292
293 switch (is_dup) {
294 /* new log entry for file,func,line */
295 case 0:
296 if (_n_nodup_table) {
297 ht_put_string(_n_nodup_table, key, syslogbuffer);
298 }
299 _n_log(LEVEL, file, func, line, "%s", syslogbuffer);
300 break;
301
302 /* exising and same log entry, do nothing (maybe latter we will add a timeout to repeat logging) */
303 case 1:
304 break;
305 /* existing but different entry. We have to refresh and log it one time*/
306 case 2:
308 if (node) {
309 Free(node->data.string);
310 node->data.string = syslogbuffer;
311 syslogbuffer = NULL;
312 }
313 _n_log(LEVEL, file, func, line, "%s", node ? node->data.string : "");
314 break;
315 /* no nodup session started, normal loggin */
316 case 3:
317 default:
318 _n_log(LEVEL, file, func, line, "%s", syslogbuffer);
319 break;
320 }
321
322 Free(syslogbuffer);
323 Free(key);
324
325} /* _n_nodup_log_indexed() */
326
334int dump_nodup_log(char* file) {
335 FILE* out = NULL;
336 __n_assert(file, return FALSE);
337 __n_assert(_n_nodup_table, return FALSE);
338
339 char* tmpfile = NULL;
340 n_log(LOG_DEBUG, "outfile:%s", file);
341 strprintf(tmpfile, "%s.tmp", file);
342 if (!tmpfile) {
343 n_log(LOG_ERR, "could not create tmp file name from filename %s", _str(file));
344 return FALSE;
345 }
346
347 int fd = open(tmpfile, O_CREAT | O_WRONLY | O_TRUNC, 0600); // Only owner can read/write
348 if (fd < 0) {
349 n_log(LOG_ERR, "could not create file %s with 0600 permissions", _str(tmpfile));
350 Free(tmpfile);
351 return FALSE;
352 }
353
354 out = fdopen(fd, "wb");
355 __n_assert(out, close(fd); Free(tmpfile); return FALSE);
356
357 if (_n_nodup_table) {
358 for (unsigned long int it = 0; it < _n_nodup_table->size; it++) {
359 list_foreach(list_node, _n_nodup_table->hash_table[it]) {
360 const HASH_NODE* hash_node = (const HASH_NODE*)list_node->ptr;
361 fprintf(out, "%s\n", hash_node->data.string);
362 }
363 }
364 }
365 fclose(out);
366
367 if (rename(tmpfile, file) != 0) {
368 int error = errno;
369 n_log(LOG_ERR, "could not rename '%s' to '%s' , %s", tmpfile, file,
370 strerror(error));
371 }
372 Free(tmpfile);
373
374 return TRUE;
375
376} /* dump_nodup_log() */
char * key
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:279
#define _str(__PTR)
define true
Definition n_common.h:193
#define Free(__ptr)
Free Handler to get errors.
Definition n_common.h:263
union HASH_DATA data
data inside the node
Definition n_hash.h:122
LIST ** hash_table
HASH_CLASSIC mode: preallocated hash table.
Definition n_hash.h:146
char * string
char *type
Definition n_hash.h:108
size_t size
size of the hash table
Definition n_hash.h:140
int destroy_ht(HASH_TABLE **table)
empty a table and destroy it
Definition n_hash.c:2244
HASH_TABLE * new_ht(size_t size)
Create a hash table with the given size.
Definition n_hash.c:2011
int empty_ht(HASH_TABLE *table)
empty a table
Definition n_hash.c:2234
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:2177
HASH_NODE * ht_get_node(HASH_TABLE *table, const char *key)
get node at 'key' from 'table'
Definition n_hash.c:2071
structure of a hash table node
Definition n_hash.h:112
structure of a hash table
Definition n_hash.h:138
#define list_foreach(__ITEM_, __LIST_)
ForEach macro helper, safe for node removal during iteration.
Definition n_list.h:89
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:89
#define LOG_DEBUG
debug-level messages
Definition n_log.h:84
#define LOG_ERR
error conditions
Definition n_log.h:76
void _n_log(int level, const char *file, const char *func, int line, const char *format,...)
Logging function.
Definition n_log.c:268
int init_nodup_log(size_t max)
initialize the no duplicate logging system
Definition n_nodup_log.c:55
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:88
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:79
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:63
#define strprintf(__n_var,...)
Macro to quickly allocate and sprintf to a char.
Definition n_str.h:95
#define nstrprintf(__nstr_var, __format,...)
Macro to quickly allocate and sprintf to N_STR.
Definition n_str.h:117
A box including a string and his lenght.
Definition n_str.h:61
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:227
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
static HASH_TABLE * _n_nodup_table
internal: no dup hash_table log save
Definition n_nodup_log.c:49
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.