From 7348a381a903eea67611fbce0782cf968b965ebf Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 2 Jul 2009 19:41:47 +0400 Subject: [PATCH] * Rework structure and API of statfiles functions to improve performance and avoid missusage of hash table * Correct url length calculation in urls command --- src/classifiers/winnow.c | 24 +++-- src/controller.c | 5 +- src/plugins/surbl.c | 2 +- src/statfile.c | 197 +++++++++++++++++---------------------- src/statfile.h | 24 ++--- 5 files changed, 112 insertions(+), 140 deletions(-) diff --git a/src/classifiers/winnow.c b/src/classifiers/winnow.c index 1b3904e67..edd929af0 100644 --- a/src/classifiers/winnow.c +++ b/src/classifiers/winnow.c @@ -34,7 +34,7 @@ struct winnow_callback_data { statfile_pool_t *pool; struct classifier_ctx *ctx; - char *filename; + stat_file_t *file; double sum; int count; int in_class; @@ -49,7 +49,7 @@ classify_callback (gpointer key, gpointer value, gpointer data) float v; /* Consider that not found blocks have value 1 */ - if ((v = statfile_pool_get_block (cd->pool, cd->filename, node->h1, node->h2, cd->now)) < 0.00001) { + if ((v = statfile_pool_get_block (cd->pool, cd->file, node->h1, node->h2, cd->now)) < 0.00001) { cd->sum += 1; } else { @@ -72,11 +72,11 @@ learn_callback (gpointer key, gpointer value, gpointer data) c = (cd->in_class) ? WINNOW_PROMOTION : WINNOW_DEMOTION; /* Consider that not found blocks have value 1 */ - if ((v = statfile_pool_get_block (cd->pool, cd->filename, node->h1, node->h2, cd->now)) < 0.00001) { - statfile_pool_set_block (cd->pool, cd->filename, node->h1, node->h2, cd->now, c); + if ((v = statfile_pool_get_block (cd->pool, cd->file, node->h1, node->h2, cd->now)) < 0.00001) { + statfile_pool_set_block (cd->pool, cd->file, node->h1, node->h2, cd->now, c); } else { - statfile_pool_set_block (cd->pool, cd->filename, node->h1, node->h2, cd->now, v * c); + statfile_pool_set_block (cd->pool, cd->file, node->h1, node->h2, cd->now, v * c); } cd->count ++; @@ -105,14 +105,13 @@ winnow_classify (struct classifier_ctx *ctx, statfile_pool_t *pool, char *statfi g_assert (ctx != NULL); data.pool = pool; - data.filename = statfile; data.sum = 0; data.count = 0; data.now = time (NULL); data.ctx = ctx; - if (!statfile_pool_is_open (pool, statfile)) { - if (statfile_pool_open (pool, statfile) == -1) { + if ((data.file = statfile_pool_is_open (pool, statfile)) == NULL) { + if ((data.file = statfile_pool_open (pool, statfile)) == NULL) { return; } } @@ -138,22 +137,21 @@ winnow_learn (struct classifier_ctx *ctx, statfile_pool_t *pool, char *statfile, g_assert (ctx != NULL); data.pool = pool; - data.filename = statfile; data.sum = 0; data.count = 0; data.in_class = in_class; data.now = time (NULL); data.ctx = ctx; - if (!statfile_pool_is_open (pool, statfile)) { - if (statfile_pool_open (pool, statfile) == -1) { + if ((data.file = statfile_pool_is_open (pool, statfile)) == NULL) { + if ((data.file = statfile_pool_open (pool, statfile)) == NULL) { return; } } - statfile_pool_lock_file (pool, statfile); + statfile_pool_lock_file (pool, data.file); g_tree_foreach (input, learn_callback, &data); - statfile_pool_unlock_file (pool, statfile); + statfile_pool_unlock_file (pool, data.file); } struct winnow_result_data { diff --git a/src/controller.c b/src/controller.c index 4b0f7ae63..87e7f1b0f 100644 --- a/src/controller.c +++ b/src/controller.c @@ -172,6 +172,7 @@ process_command (struct controller_command *cmd, char **cmd_args, struct control time_t uptime; unsigned long size = 0; struct statfile *statfile; + stat_file_t *file; struct metric *metric; memory_pool_stat_t mem_st; char *password = g_hash_table_lookup (session->worker->cf->params, "password"); @@ -357,7 +358,7 @@ process_command (struct controller_command *cmd, char **cmd_args, struct control } session->learn_filename = resolve_stat_filename (session->session_pool, statfile->pattern, session->learn_rcpt, session->learn_from); - if (statfile_pool_open (session->worker->srv->statfile_pool, session->learn_filename) == -1) { + if ((file = statfile_pool_open (session->worker->srv->statfile_pool, session->learn_filename)) == NULL) { /* Try to create statfile */ if (statfile_pool_create (session->worker->srv->statfile_pool, session->learn_filename, statfile->size / sizeof (struct stat_file_block)) == -1) { @@ -365,7 +366,7 @@ process_command (struct controller_command *cmd, char **cmd_args, struct control rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE); return; } - if (statfile_pool_open (session->worker->srv->statfile_pool, session->learn_filename) == -1) { + if ((file = statfile_pool_open (session->worker->srv->statfile_pool, session->learn_filename)) == NULL) { r = snprintf (out_buf, sizeof (out_buf), "cannot open statfile %s" CRLF, session->learn_filename); rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE); return; diff --git a/src/plugins/surbl.c b/src/plugins/surbl.c index a7ff5bb7a..f0347f550 100644 --- a/src/plugins/surbl.c +++ b/src/plugins/surbl.c @@ -799,7 +799,7 @@ urls_command_handler (struct worker_task *task) cur = g_list_next (cur); } - buflen += sizeof (RSPAMD_REPLY_BANNER " 0 OK" CRLF CRLF); + buflen += sizeof (RSPAMD_REPLY_BANNER " 0 OK" CRLF CRLF "URLs: "); outbuf = memory_pool_alloc (task->task_pool, buflen * sizeof (char)); diff --git a/src/statfile.c b/src/statfile.c index 008154194..ac0c3bfaa 100644 --- a/src/statfile.c +++ b/src/statfile.c @@ -27,6 +27,17 @@ #include "statfile.h" #include "main.h" +/* Maximum number of statistics files */ +#define STATFILES_MAX 255 + +static int +cmpstatfile (const void *a, const void *b) +{ + const stat_file_t *s1 = a, *s2 = b; + + return rspamd_strcase_equal (s1->filename, s2->filename); +} + /* Check whether specified file is statistic file and calculate its len in blocks */ static int statfile_pool_check (stat_file_t *file) @@ -67,34 +78,32 @@ struct expiration_data { char *filename; }; -static void -pool_expiration_callback (gpointer key, gpointer value, void *data) -{ - struct expiration_data *exp = data; - stat_file_t *file = (stat_file_t *)value; - - if ((uint64_t)file->access_time < exp->oldest) { - exp->oldest = file->access_time; - exp->filename = file->filename; - } -} static int statfile_pool_expire (statfile_pool_t *pool) { struct expiration_data exp; + stat_file_t *file; + int i; - if (rspamd_hash_size (pool->files) == 0) { + if (pool->opened == 0) { return -1; } exp.pool = pool; exp.oldest = ULLONG_MAX; exp.filename = NULL; - rspamd_hash_foreach (pool->files, pool_expiration_callback, &exp); + + for (i = 0; i < pool->opened; i++) { + file = &pool->files[i]; + if ((uint64_t)file->access_time < exp.oldest) { + exp.oldest = file->access_time; + exp.filename = file->filename; + } + } if (exp.filename) { - statfile_pool_close (pool, exp.filename, TRUE); + statfile_pool_close (pool, file, TRUE); } return 0; @@ -109,63 +118,66 @@ statfile_pool_new (size_t max_size) bzero (new, sizeof (statfile_pool_t)); new->pool = memory_pool_new (memory_pool_get_size ()); new->max = max_size; - new->files = rspamd_hash_new (new->pool, g_str_hash, g_str_equal); - new->maps = rspamd_hash_new_shared (new->pool, g_str_hash, g_str_equal, 64); + new->files = memory_pool_alloc_shared (new->pool, STATFILES_MAX * sizeof (stat_file_t)); return new; } -int +stat_file_t * statfile_pool_open (statfile_pool_t *pool, char *filename) { struct stat st; stat_file_t *new_file; - if (rspamd_hash_lookup (pool->files, filename) != NULL) { + if (statfile_pool_is_open (pool, filename) != NULL) { msg_info ("statfile_pool_open: file %s is already opened", filename); - return 0; + return NULL; + } + + if (pool->opened >= STATFILES_MAX - 1) { + msg_err ("sttafile_pool_open: reached hard coded limit of statfiles opened: %d", STATFILES_MAX); + return NULL; } if (stat (filename, &st) == -1) { msg_info ("statfile_pool_open: cannot stat file %s, error %s, %d", filename, strerror (errno), errno); - return -1; + return NULL; } if (st.st_size > pool->max) { msg_info ("statfile_pool_open: cannot attach file to pool, too large: %zd", (size_t)st.st_size); - return -1; + return NULL; } while (pool->max <= pool->occupied + st.st_size) { if (statfile_pool_expire (pool) == -1) { /* Failed to find any more free space in pool */ msg_info ("statfile_pool_open: expiration for pool failed, opening file %s failed", filename); - return -1; + return NULL; } } - new_file = memory_pool_alloc (pool->pool, sizeof (stat_file_t)); + new_file = &pool->files[pool->opened ++]; if ((new_file->fd = open (filename, O_RDWR)) == -1 ) { msg_info ("statfile_pool_open: cannot open file %s, error %d, %s", filename, errno, strerror (errno)); - return -1; + pool->opened --; + return NULL; } - /* First try to search mmapped area in already opened areas */ - if ((new_file->map = rspamd_hash_lookup (pool->maps, filename)) == NULL) { - if ((new_file->map = mmap (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, new_file->fd, 0)) == NULL) { - close (new_file->fd); - msg_info ("statfile_pool_open: cannot mmap file %s, error %d, %s", filename, errno, strerror (errno)); - return -1; - - } - rspamd_hash_insert (pool->maps, filename, new_file->map); + if ((new_file->map = mmap (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, new_file->fd, 0)) == NULL) { + close (new_file->fd); + msg_info ("statfile_pool_open: cannot mmap file %s, error %d, %s", filename, errno, strerror (errno)); + pool->opened --; + return NULL; + } /* XXX: this is temporary copy of name to avoid strdup early */ new_file->filename = filename; new_file->len = st.st_size; if (statfile_pool_check (new_file) == -1) { - return -1; + pool->opened --; + return NULL; } pool->occupied += st.st_size; @@ -173,18 +185,20 @@ statfile_pool_open (statfile_pool_t *pool, char *filename) new_file->open_time = time (NULL); new_file->access_time = new_file->open_time; new_file->lock = memory_pool_get_mutex (pool->pool); - rspamd_hash_insert (pool->files, new_file->filename, new_file); + + /* Keep sorted */ + qsort (pool->files, pool->opened, sizeof (stat_file_t), cmpstatfile); - return 0; + return new_file; } int -statfile_pool_close (statfile_pool_t *pool, char *filename, gboolean remove_hash) +statfile_pool_close (statfile_pool_t *pool, stat_file_t *file, gboolean keep_sorted) { - stat_file_t *file; - - if ((file = rspamd_hash_lookup (pool->files, filename)) == NULL) { - msg_info ("statfile_pool_open: file %s is not opened", filename); + stat_file_t *pos; + + if ((pos = statfile_pool_is_open (pool, file->filename)) == NULL) { + msg_info ("statfile_pool_open: file %s is not opened", file->filename); return -1; } @@ -194,14 +208,16 @@ statfile_pool_close (statfile_pool_t *pool, char *filename, gboolean remove_hash if (file->map) { munmap (file->map, file->len); - rspamd_hash_remove (pool->maps, filename); } if (file->fd != -1) { close (file->fd); } pool->occupied -= file->len; - if (remove_hash) { - rspamd_hash_remove (pool->files, file->filename); + + if (keep_sorted) { + memmove (pos, &pool->files[pool->opened--], sizeof (stat_file_t)); + /* Keep sorted */ + qsort (pool->files, pool->opened, sizeof (stat_file_t), cmpstatfile); } return 0; } @@ -220,8 +236,8 @@ statfile_pool_create (statfile_pool_t *pool, char *filename, size_t blocks) struct stat_file_block block = {0, 0, 0, 0}; int fd; - if (rspamd_hash_lookup (pool->files, filename) != NULL) { - msg_info ("statfile_pool_create: file %s is already opened", filename); + if (statfile_pool_is_open (pool, filename) != NULL) { + msg_info ("statfile_pool_open: file %s is already opened", filename); return 0; } @@ -257,61 +273,40 @@ statfile_pool_create (statfile_pool_t *pool, char *filename, size_t blocks) return 0; } -static void -pool_delete_callback (gpointer key, gpointer value, void *data) -{ - statfile_pool_t *pool = (statfile_pool_t *)data; - - statfile_pool_close (pool, (char *)key, FALSE); -} - void statfile_pool_delete (statfile_pool_t *pool) { - rspamd_hash_foreach (pool->files, pool_delete_callback, pool); + int i; + + for (i = 0; i < pool->opened; i ++) { + statfile_pool_close (pool, &pool->files[i], FALSE); + } memory_pool_delete (pool->pool); g_free (pool); } void -statfile_pool_lock_file (statfile_pool_t *pool, char *filename) +statfile_pool_lock_file (statfile_pool_t *pool, stat_file_t *file) { - stat_file_t *file; - - if ((file = rspamd_hash_lookup (pool->files, filename)) == NULL) { - msg_info ("statfile_pool_lock_file: file %s is not opened", filename); - return; - } memory_pool_lock_mutex (file->lock); } void -statfile_pool_unlock_file (statfile_pool_t *pool, char *filename) +statfile_pool_unlock_file (statfile_pool_t *pool, stat_file_t *file) { - stat_file_t *file; - - if ((file = rspamd_hash_lookup (pool->files, filename)) == NULL) { - msg_info ("statfile_pool_unlock_file: file %s is not opened", filename); - return; - } memory_pool_unlock_mutex (file->lock); } float -statfile_pool_get_block (statfile_pool_t *pool, char *filename, uint32_t h1, uint32_t h2, time_t now) +statfile_pool_get_block (statfile_pool_t *pool, stat_file_t *file, uint32_t h1, uint32_t h2, time_t now) { - stat_file_t *file; struct stat_file_block *block; struct stat_file_header *header; unsigned int i, blocknum; u_char *c; - if ((file = rspamd_hash_lookup (pool->files, filename)) == NULL) { - msg_info ("statfile_pool_get_block: file %s is not opened", filename); - return 0; - } file->access_time = now; if (!file->map) { @@ -340,18 +335,13 @@ statfile_pool_get_block (statfile_pool_t *pool, char *filename, uint32_t h1, uin } void -statfile_pool_set_block (statfile_pool_t *pool, char *filename, uint32_t h1, uint32_t h2, time_t now, float value) +statfile_pool_set_block (statfile_pool_t *pool, stat_file_t *file, uint32_t h1, uint32_t h2, time_t now, float value) { - stat_file_t *file; struct stat_file_block *block, *to_expire = NULL; struct stat_file_header *header; unsigned int i, blocknum, oldest = 0; u_char *c; - if ((file = rspamd_hash_lookup (pool->files, filename)) == NULL) { - msg_info ("statfile_pool_set_block: file %s is not opened", filename); - return; - } file->access_time = now; if (!file->map) { @@ -407,36 +397,27 @@ statfile_pool_set_block (statfile_pool_t *pool, char *filename, uint32_t h1, uin block->value = value; } -gboolean +stat_file_t * statfile_pool_is_open (statfile_pool_t *pool, char *filename) { - return (rspamd_hash_lookup (pool->files, filename) != NULL); + static stat_file_t f; + f.filename = filename; + return bsearch (&f, pool->files, pool->opened, sizeof (stat_file_t), cmpstatfile); } uint32_t -statfile_pool_get_section (statfile_pool_t *pool, char *filename) +statfile_pool_get_section (statfile_pool_t *pool, stat_file_t *file) { - stat_file_t *file; - if ((file = rspamd_hash_lookup (pool->files, filename)) == NULL) { - msg_info ("statfile_pool_get_section: file %s is not opened", filename); - return 0; - } - return file->cur_section.code; } gboolean -statfile_pool_set_section (statfile_pool_t *pool, char *filename, uint32_t code, gboolean from_begin) +statfile_pool_set_section (statfile_pool_t *pool, stat_file_t *file, uint32_t code, gboolean from_begin) { - stat_file_t *file; struct stat_file_section *sec; off_t cur_offset; - if ((file = rspamd_hash_lookup (pool->files, filename)) == NULL) { - msg_info ("statfile_pool_set_section: file %s is not opened", filename); - return FALSE; - } /* Try to find section */ if (from_begin) { @@ -460,19 +441,13 @@ statfile_pool_set_section (statfile_pool_t *pool, char *filename, uint32_t code, } gboolean -statfile_pool_add_section (statfile_pool_t *pool, char *filename, uint32_t code, uint64_t length) +statfile_pool_add_section (statfile_pool_t *pool, stat_file_t *file, uint32_t code, uint64_t length) { - stat_file_t *file; struct stat_file_section sect; struct stat_file_block block = {0, 0, 0, 0}; - if ((file = rspamd_hash_lookup (pool->files, filename)) == NULL) { - msg_info ("statfile_pool_add_section: file %s is not opened", filename); - return FALSE; - } - if (lseek (file->fd, 0, SEEK_END) == -1) { - msg_info ("statfile_pool_add_section: cannot lseek file %s, error %d, %s", filename, errno, strerror (errno)); + msg_info ("statfile_pool_add_section: cannot lseek file %s, error %d, %s", file->filename, errno, strerror (errno)); return FALSE; } @@ -480,20 +455,19 @@ statfile_pool_add_section (statfile_pool_t *pool, char *filename, uint32_t code, sect.length = length; if (write (file->fd, §, sizeof (sect)) == -1) { - msg_info ("statfile_pool_add_section: cannot write block to file %s, error %d, %s", filename, errno, strerror (errno)); + msg_info ("statfile_pool_add_section: cannot write block to file %s, error %d, %s", file->filename, errno, strerror (errno)); return FALSE; } while (length --) { if (write (file->fd, &block, sizeof (block)) == -1) { - msg_info ("statfile_pool_add_section: cannot write block to file %s, error %d, %s", filename, errno, strerror (errno)); + msg_info ("statfile_pool_add_section: cannot write block to file %s, error %d, %s", file->filename, errno, strerror (errno)); return FALSE; } } /* Lock statfile to remap memory */ - statfile_pool_lock_file (pool, filename); - rspamd_hash_remove (pool->maps, filename); + statfile_pool_lock_file (pool, file); munmap (file->map, file->len); fsync (file->fd); file->len += length; @@ -506,16 +480,15 @@ statfile_pool_add_section (statfile_pool_t *pool, char *filename, uint32_t code, while (pool->max <= pool->occupied + file->len) { if (statfile_pool_expire (pool) == -1) { /* Failed to find any more free space in pool */ - msg_info ("statfile_pool_open: expiration for pool failed, opening file %s failed", filename); + msg_info ("statfile_pool_open: expiration for pool failed, opening file %s failed", file->filename); return FALSE; } } if ((file->map = mmap (NULL, file->len, PROT_READ | PROT_WRITE, MAP_SHARED, file->fd, 0)) == NULL) { - msg_info ("statfile_pool_open: cannot mmap file %s, error %d, %s", filename, errno, strerror (errno)); + msg_info ("statfile_pool_open: cannot mmap file %s, error %d, %s", file->filename, errno, strerror (errno)); return FALSE; } - rspamd_hash_insert (pool->maps, filename, file->map); - statfile_pool_unlock_file (pool, filename); + statfile_pool_unlock_file (pool, file); return TRUE; diff --git a/src/statfile.h b/src/statfile.h index f2c5dbbf2..be5d15b71 100644 --- a/src/statfile.h +++ b/src/statfile.h @@ -74,8 +74,8 @@ typedef struct stat_file_s { * Statfiles pool */ typedef struct statfile_pool_s { - rspamd_hash_t *files; /**< hash table of opened files indexed by name */ - rspamd_hash_t *maps; /**< shared hash table of mmaped areas indexed by name */ + stat_file_t *files; /**< hash table of opened files indexed by name */ + void **maps; /**< shared hash table of mmaped areas indexed by name */ int opened; /**< number of opened files */ size_t max; /**< maximum size */ size_t occupied; /**< current size */ @@ -95,7 +95,7 @@ statfile_pool_t* statfile_pool_new (size_t max_size); * @param filename name of statfile to open * @return 0 if specified statfile is attached and -1 in case of error */ -int statfile_pool_open (statfile_pool_t *pool, char *filename); +stat_file_t* statfile_pool_open (statfile_pool_t *pool, char *filename); /** * Create new statfile but DOES NOT attach it to pool, use @see statfile_pool_open for attaching @@ -113,7 +113,7 @@ int statfile_pool_create (statfile_pool_t *pool, char *filename, size_t len); * @param remove_hash remove filename from opened files hash also * @return 0 if file was closed and -1 if statfile was not opened */ -int statfile_pool_close (statfile_pool_t *pool, char *filename, gboolean remove_hash); +int statfile_pool_close (statfile_pool_t *pool, stat_file_t *file, gboolean keep_sorted); /** * Delete statfile pool and close all attached statfiles @@ -126,14 +126,14 @@ void statfile_pool_delete (statfile_pool_t *pool); * @param pool statfile pool object * @param filename name of statfile */ -void statfile_pool_lock_file (statfile_pool_t *pool, char *filename); +void statfile_pool_lock_file (statfile_pool_t *pool, stat_file_t *file); /** * Unlock specified file * @param pool statfile pool object * @param filename name of statfile */ -void statfile_pool_unlock_file (statfile_pool_t *pool, char *filename); +void statfile_pool_unlock_file (statfile_pool_t *pool, stat_file_t *file); /** * Get block from statfile with h1 and h2 values, use time argument for current time @@ -144,7 +144,7 @@ void statfile_pool_unlock_file (statfile_pool_t *pool, char *filename); * @param now current time * @return block value or 0 if block is not found */ -float statfile_pool_get_block (statfile_pool_t *pool, char *filename, uint32_t h1, uint32_t h2, time_t now); +float statfile_pool_get_block (statfile_pool_t *pool, stat_file_t *file, uint32_t h1, uint32_t h2, time_t now); /** * Set specified block in statfile @@ -155,7 +155,7 @@ float statfile_pool_get_block (statfile_pool_t *pool, char *filename, uint32_t h * @param now current time * @param value value of block */ -void statfile_pool_set_block (statfile_pool_t *pool, char *filename, uint32_t h1, uint32_t h2, time_t now, float value); +void statfile_pool_set_block (statfile_pool_t *pool, stat_file_t *file, uint32_t h1, uint32_t h2, time_t now, float value); /** * Check whether statfile is opened @@ -163,7 +163,7 @@ void statfile_pool_set_block (statfile_pool_t *pool, char *filename, uint32_t h1 * @param filename name of statfile * @return TRUE if specified statfile is opened and FALSE otherwise */ -gboolean statfile_pool_is_open (statfile_pool_t *pool, char *filename); +stat_file_t* statfile_pool_is_open (statfile_pool_t *pool, char *filename); /** * Returns current statfile section @@ -171,7 +171,7 @@ gboolean statfile_pool_is_open (statfile_pool_t *pool, char *filename); * @param filename name of statfile * @return code of section or 0 if file is not opened */ -uint32_t statfile_pool_get_section (statfile_pool_t *pool, char *filename); +uint32_t statfile_pool_get_section (statfile_pool_t *pool, stat_file_t *file); /** * Go to other section of statfile @@ -181,7 +181,7 @@ uint32_t statfile_pool_get_section (statfile_pool_t *pool, char *filename); * @param from_begin search for section from begin of file if true * @return TRUE if section was set and FALSE otherwise */ -gboolean statfile_pool_set_section (statfile_pool_t *pool, char *filename, uint32_t code, gboolean from_begin); +gboolean statfile_pool_set_section (statfile_pool_t *pool, stat_file_t *file, uint32_t code, gboolean from_begin); /** * Add new section to statfile @@ -191,7 +191,7 @@ gboolean statfile_pool_set_section (statfile_pool_t *pool, char *filename, uint3 * @param length length in blocks of new section * @return TRUE if section was successfully added and FALSE in case of error */ -gboolean statfile_pool_add_section (statfile_pool_t *pool, char *filename, uint32_t code, uint64_t length); +gboolean statfile_pool_add_section (statfile_pool_t *pool, stat_file_t *file, uint32_t code, uint64_t length); /** -- 2.39.5