Skip to content

Commit 277aea3

Browse files
committed
out_logrotate: refactor file size management to use linked list instead of hash table
This change replaces the hash table with a linked list for storing file sizes, improving memory management and simplifying the code. Additionally, helper functions for managing file size entries have been added, enhancing the overall structure and readability of the logrotate plugin. Signed-off-by: SagiROosto <sagi.rosenthal@oosto.com>
1 parent aa6eaa2 commit 277aea3

File tree

2 files changed

+119
-54
lines changed

2 files changed

+119
-54
lines changed

plugins/out_logrotate/logrotate.c

Lines changed: 118 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include <fluent-bit/flb_log_event_decoder.h>
2727
#include <fluent-bit/flb_gzip.h>
2828
#include <fluent-bit/flb_str.h>
29-
#include <fluent-bit/flb_hash_table.h>
29+
#include <fluent-bit/flb_info.h>
3030
#include <msgpack.h>
3131

3232
#include <stdio.h>
@@ -68,6 +68,12 @@
6868
#define GZIP_HEADER_SIZE 10
6969
#define GZIP_FOOTER_SIZE 8
7070

71+
struct logrotate_file_size {
72+
flb_sds_t filename;
73+
size_t size;
74+
struct mk_list _head;
75+
};
76+
7177
struct flb_logrotate_conf {
7278
const char *out_path;
7379
const char *out_file;
@@ -80,7 +86,7 @@ struct flb_logrotate_conf {
8086
size_t max_size; /* Max file size */
8187
int max_files; /* Maximum number of rotated files to keep */
8288
int gzip; /* Whether to gzip rotated files */
83-
struct flb_hash_table *file_sizes; /* Hash table to store file size per filename */
89+
struct mk_list file_sizes; /* Linked list to store file size per filename */
8490
struct flb_output_instance *ins;
8591
};
8692

@@ -125,19 +131,11 @@ static int cb_logrotate_init(struct flb_output_instance *ins,
125131
ctx->label_delimiter = NULL;
126132
ctx->template = NULL;
127133

128-
/* Initialize hash table to store file sizes per filename */
129-
ctx->file_sizes = flb_hash_table_create(FLB_HASH_TABLE_EVICT_NONE, 64, 0);
130-
if (!ctx->file_sizes) {
131-
flb_errno();
132-
flb_free(ctx);
133-
return -1;
134-
}
134+
/* Initialize linked list to store file sizes per filename */
135+
mk_list_init(&ctx->file_sizes);
135136

136137
ret = flb_output_config_map_set(ins, (void *) ctx);
137138
if (ret == -1) {
138-
if (ctx->file_sizes) {
139-
flb_hash_table_destroy(ctx->file_sizes);
140-
}
141139
flb_free(ctx);
142140
return -1;
143141
}
@@ -173,9 +171,6 @@ static int cb_logrotate_init(struct flb_output_instance *ins,
173171
}
174172
else {
175173
flb_plg_error(ctx->ins, "unknown format %s. abort.", tmp);
176-
if (ctx->file_sizes) {
177-
flb_hash_table_destroy(ctx->file_sizes);
178-
}
179174
flb_free(ctx);
180175
return -1;
181176
}
@@ -529,28 +524,97 @@ static int mkpath(struct flb_output_instance *ins, const char *dir)
529524
#endif
530525
}
531526

532-
/* Function to check if file size exceeds max size for a specific file */
533-
static int should_rotate_file(struct flb_logrotate_conf *ctx, const char *filename)
527+
/* Helper function to find a file size entry by filename */
528+
static struct logrotate_file_size *find_file_size_entry(struct flb_logrotate_conf *ctx,
529+
const char *filename)
534530
{
535-
size_t file_size = 0;
536-
void *out_buf;
537-
size_t out_size;
538-
int ret;
531+
struct mk_list *head;
532+
struct logrotate_file_size *entry;
533+
534+
mk_list_foreach(head, &ctx->file_sizes) {
535+
entry = mk_list_entry(head, struct logrotate_file_size, _head);
536+
if (entry->filename && strcmp(entry->filename, filename) == 0) {
537+
return entry;
538+
}
539+
}
540+
return NULL;
541+
}
542+
543+
/* Helper function to get file size from list or stat */
544+
static size_t get_file_size(struct flb_logrotate_conf *ctx, const char *filename)
545+
{
546+
struct logrotate_file_size *entry;
539547
struct stat st;
540548

541-
/* Get file size from hash table */
542-
ret = flb_hash_table_get(ctx->file_sizes, filename, strlen(filename),
543-
&out_buf, &out_size);
544-
if (ret == 0 && out_size == sizeof(size_t)) {
545-
file_size = *(size_t *)out_buf;
549+
entry = find_file_size_entry(ctx, filename);
550+
if (entry != NULL) {
551+
return entry->size;
546552
}
547-
else {
548-
/* If not in hash table, check actual file size as fallback */
549-
if (stat(filename, &st) == 0 && st.st_size >= 0) {
550-
file_size = (size_t) st.st_size;
551-
flb_plg_debug(ctx->ins, "file size not in hash table, using stat: %zu", file_size);
553+
554+
/* Fallback to stat if not in list */
555+
if (stat(filename, &st) == 0 && st.st_size >= 0) {
556+
return (size_t) st.st_size;
557+
}
558+
559+
return 0;
560+
}
561+
562+
/* Helper function to update or create file size entry */
563+
static int update_file_size(struct flb_logrotate_conf *ctx, const char *filename, size_t size)
564+
{
565+
struct logrotate_file_size *entry;
566+
flb_sds_t filename_copy;
567+
568+
entry = find_file_size_entry(ctx, filename);
569+
if (entry != NULL) {
570+
/* Update existing entry */
571+
entry->size = size;
572+
return 0;
573+
}
574+
575+
/* Create new entry */
576+
entry = flb_calloc(1, sizeof(struct logrotate_file_size));
577+
if (!entry) {
578+
flb_errno();
579+
return -1;
580+
}
581+
582+
filename_copy = flb_sds_create(filename);
583+
if (!filename_copy) {
584+
flb_free(entry);
585+
flb_errno();
586+
return -1;
587+
}
588+
589+
entry->filename = filename_copy;
590+
entry->size = size;
591+
mk_list_add(&entry->_head, &ctx->file_sizes);
592+
593+
return 0;
594+
}
595+
596+
/* Helper function to remove file size entry */
597+
static void remove_file_size(struct flb_logrotate_conf *ctx, const char *filename)
598+
{
599+
struct logrotate_file_size *entry;
600+
601+
entry = find_file_size_entry(ctx, filename);
602+
if (entry != NULL) {
603+
mk_list_del(&entry->_head);
604+
if (entry->filename) {
605+
flb_sds_destroy(entry->filename);
552606
}
607+
flb_free(entry);
553608
}
609+
}
610+
611+
/* Function to check if file size exceeds max size for a specific file */
612+
static int should_rotate_file(struct flb_logrotate_conf *ctx, const char *filename)
613+
{
614+
size_t file_size;
615+
616+
/* Get file size from list or stat fallback */
617+
file_size = get_file_size(ctx, filename);
554618

555619
if (file_size >= ctx->max_size) {
556620
flb_plg_info(ctx->ins, "going to rotate file %s: current size=%zu max size=%zu",
@@ -575,11 +639,8 @@ static void update_file_size_counter(struct flb_logrotate_conf *ctx,
575639
if (fstat(fileno(fp), &st) == 0 && st.st_size >= 0) {
576640
file_size = (size_t) st.st_size;
577641

578-
/* Delete existing entry if it exists to ensure we can update the value */
579-
flb_hash_table_del(ctx->file_sizes, filename);
580-
/* Store or update file size in hash table */
581-
ret = flb_hash_table_add(ctx->file_sizes, filename, strlen(filename),
582-
&file_size, sizeof(size_t));
642+
/* Update or create file size entry in list */
643+
ret = update_file_size(ctx, filename, file_size);
583644
if (ret == -1) {
584645
flb_plg_warn(ctx->ins, "failed to update file size for %s", filename);
585646
}
@@ -762,15 +823,13 @@ static int rotate_file(struct flb_logrotate_conf *ctx, const char *filename)
762823
char rotated_filename[PATH_MAX];
763824
char gzip_filename[PATH_MAX];
764825
size_t file_size = 0;
765-
void *out_buf;
766-
size_t out_size;
826+
struct logrotate_file_size *entry;
767827
int ret = 0;
768828

769-
/* Get file size from hash table for logging */
770-
ret = flb_hash_table_get(ctx->file_sizes, filename, strlen(filename),
771-
&out_buf, &out_size);
772-
if (ret == 0 && out_size == sizeof(size_t)) {
773-
file_size = *(size_t *)out_buf;
829+
/* Get file size from list for logging */
830+
entry = find_file_size_entry(ctx, filename);
831+
if (entry != NULL) {
832+
file_size = entry->size;
774833
}
775834

776835
/* Log rotation event */
@@ -1031,8 +1090,8 @@ static void cb_logrotate_flush(struct flb_event_chunk *event_chunk,
10311090

10321091
/* Rotate the file */
10331092
if (rotate_file(ctx, out_file) == 0) {
1034-
/* Remove file size entry from hash table after rotation */
1035-
flb_hash_table_del(ctx->file_sizes, out_file);
1093+
/* Remove file size entry from list after rotation */
1094+
remove_file_size(ctx, out_file);
10361095
/* Clean up old rotated files */
10371096
if (have_directory) {
10381097
cleanup_old_files(ctx, directory, base_filename);
@@ -1065,12 +1124,9 @@ static void cb_logrotate_flush(struct flb_event_chunk *event_chunk,
10651124

10661125
/* Initialize file size counter if this is a new file */
10671126
{
1068-
void *out_buf;
1069-
size_t out_size;
1070-
int ret = flb_hash_table_get(ctx->file_sizes, out_file, strlen(out_file),
1071-
&out_buf, &out_size);
1072-
if (ret != 0) {
1073-
/* File not in hash table, initialize it */
1127+
struct logrotate_file_size *entry = find_file_size_entry(ctx, out_file);
1128+
if (entry == NULL) {
1129+
/* File not in list, initialize it */
10741130
update_file_size_counter(ctx, out_file, fp);
10751131
}
10761132
}
@@ -1199,14 +1255,22 @@ static void cb_logrotate_flush(struct flb_event_chunk *event_chunk,
11991255
static int cb_logrotate_exit(void *data, struct flb_config *config)
12001256
{
12011257
struct flb_logrotate_conf *ctx = data;
1258+
struct mk_list *head;
1259+
struct mk_list *tmp;
1260+
struct logrotate_file_size *entry;
12021261

12031262
if (!ctx) {
12041263
return 0;
12051264
}
12061265

1207-
/* Destroy hash table */
1208-
if (ctx->file_sizes) {
1209-
flb_hash_table_destroy(ctx->file_sizes);
1266+
/* Free all file size entries from linked list */
1267+
mk_list_foreach_safe(head, tmp, &ctx->file_sizes) {
1268+
entry = mk_list_entry(head, struct logrotate_file_size, _head);
1269+
mk_list_del(&entry->_head);
1270+
if (entry->filename) {
1271+
flb_sds_destroy(entry->filename);
1272+
}
1273+
flb_free(entry);
12101274
}
12111275

12121276
flb_free(ctx);

tests/runtime/out_logrotate.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <fluent-bit.h>
44
#include <fluent-bit/flb_sds.h>
55
#include <fluent-bit/flb_engine.h>
6+
#include <fluent-bit/flb_time.h>
67
#include "flb_tests_runtime.h"
78
#include <sys/stat.h>
89
#include <sys/types.h>

0 commit comments

Comments
 (0)