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>
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+
7177struct 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,
11991255static 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 );
0 commit comments