37
37
#include "../../evi/evi_transport.h"
38
38
#include "../../mem/shm_mem.h"
39
39
#include "../../locking.h"
40
+ #include "../../timer.h"
41
+ #include "../../ipc.h"
40
42
#include "../../ut.h"
41
43
42
44
static int mod_init (void );
@@ -52,6 +54,8 @@ mi_response_t *mi_rotate(const mi_params_t *params,
52
54
static int flat_raise (struct sip_msg * msg , str * ev_name , evi_reply_sock * sock ,
53
55
evi_params_t * params , evi_async_ctx_t * async_ctx );
54
56
57
+ static void event_flatstore_timer (unsigned int ticks , void * param );
58
+
55
59
static int * opened_fds ;
56
60
static int * rotate_version ;
57
61
@@ -70,6 +74,9 @@ static int initial_capacity = FLAT_DEFAULT_MAX_FD;
70
74
static int suppress_event_name = 0 ;
71
75
static str file_permissions ;
72
76
static mode_t file_permissions_oct ;
77
+ static int file_rotate_period ;
78
+ static str file_suffix ;
79
+ static pv_elem_p file_suffix_format ;
73
80
74
81
static const mi_export_t mi_cmds [] = {
75
82
{ "evi_flat_rotate" , "rotates the files the module dumps events into" , 0 ,0 ,{
@@ -84,6 +91,8 @@ static const param_export_t mod_params[] = {
84
91
{"delimiter" ,STR_PARAM , & delimiter .s },
85
92
{"file_permissions" , STR_PARAM , & file_permissions .s },
86
93
{"suppress_event_name" , INT_PARAM , & suppress_event_name },
94
+ {"rotate_period" , INT_PARAM , & file_rotate_period },
95
+ {"suffix" , STR_PARAM , & file_suffix .s },
87
96
{0 ,0 ,0 }
88
97
};
89
98
@@ -134,6 +143,20 @@ static int mod_init(void) {
134
143
135
144
LM_NOTICE ("initializing module ...\n" );
136
145
146
+ if (file_rotate_period && file_rotate_period < 0 ) {
147
+ LM_WARN ("\"rotate_period\" parameter needs to be a positive integer (%d)! "
148
+ "Disabling auto-rotate!\n" , file_rotate_period );
149
+ file_rotate_period = 0 ;
150
+ }
151
+
152
+ if (file_suffix .s ) {
153
+ file_suffix .len = strlen (file_suffix .s );
154
+ if (pv_parse_format (& file_suffix , & file_suffix_format ) < 0 ) {
155
+ LM_ERR ("could not parse file suffix format!\n" );
156
+ return -1 ;
157
+ }
158
+ }
159
+
137
160
if (register_event_mod (& trans_export_flat )) {
138
161
LM_ERR ("cannot register transport functions for SCRIPTROUTE\n" );
139
162
return -1 ;
@@ -220,6 +243,13 @@ static int mod_init(void) {
220
243
for (i = 0 ; i < initial_capacity ; i ++ )
221
244
opened_fds [i ] = -1 ;
222
245
246
+ if (file_rotate_period &&
247
+ register_timer ("event_flatstore" , event_flatstore_timer , 0 ,
248
+ 1 , TIMER_FLAG_DELAY_ON_DELAY ) < 0 ) {
249
+ LM_ERR ("could not add event flatstore routine\n" );
250
+ return -1 ;
251
+ }
252
+
223
253
return 0 ;
224
254
}
225
255
@@ -490,12 +520,67 @@ static evi_reply_sock* flat_parse(str socket){
490
520
return NULL ;
491
521
}
492
522
523
+ static char * get_file_path (struct flat_file * file )
524
+ {
525
+ str format ;
526
+ char * filepath ;
527
+ static struct sip_msg req ;
528
+
529
+ /* if suffix not used, the path is always the same */
530
+ if (!file_suffix_format ) {
531
+ file -> pathname = file -> path .s ;
532
+ goto end ;
533
+ }
534
+
535
+ req .first_line .u .request .method .s = "DUMMY" ;
536
+ req .first_line .u .request .method .len = 5 ;
537
+ req .
first_line .
u .
request .
uri .
s = "sip:[email protected] " ;
538
+ req .first_line .u .request .uri .len = 19 ;
539
+ req .rcv .src_ip .af = AF_INET ;
540
+ req .rcv .dst_ip .af = AF_INET ;
541
+
542
+ if (pv_printf_s (& req , file_suffix_format , & format ) < 0 ) {
543
+ LM_ERR ("could not print the file's format!\n" );
544
+ goto error ;
545
+ }
546
+
547
+ if (!file -> pathname ) {
548
+ filepath = shm_malloc (file -> path .len + format .len + 1 );
549
+ if (!filepath ) {
550
+ LM_ERR ("could not allocate new file's name!\n" );
551
+ goto error ;
552
+ }
553
+ /* the file path is always the same */
554
+ memcpy (filepath , file -> path .s , file -> path .len );
555
+ } else {
556
+ filepath = shm_realloc (file -> pathname , file -> path .len + format .len + 1 );
557
+ if (!filepath ) {
558
+ LM_ERR ("could not re-allocate new file's name!\n" );
559
+ goto error ;
560
+ }
561
+ }
562
+ memcpy (filepath + file -> path .len , format .s , format .len );
563
+ filepath [file -> path .len + format .len ] = '\0' ;
564
+ file -> pathname = filepath ;
565
+ goto end ;
566
+
567
+ error :
568
+ /* if there was a previous file, dump data in the same file
569
+ * otherwise, in the initial path, no suffix*/
570
+ if (!file -> pathname )
571
+ file -> pathname = file -> path .s ;
572
+ end :
573
+ LM_DBG ("filepath for socket [%s] is [%s]\n" , file -> path .s , file -> pathname );
574
+ return file -> pathname ;
575
+ }
576
+
493
577
/* check if the local 'version' of the file descriptor asociated with entry fs
494
578
is different from the global version, if it is different reopen the file
495
579
*/
496
580
static void rotating (struct flat_file * file ){
497
581
int index ;
498
582
int rc ;
583
+ char * filepath ;
499
584
500
585
if (!file )
501
586
return ;
@@ -505,7 +590,14 @@ static void rotating(struct flat_file *file){
505
590
index = file -> file_index_process ;
506
591
507
592
if (opened_fds [index ] == -1 ) {
508
- opened_fds [index ] = open (file -> path .s ,O_RDWR | O_APPEND | O_CREAT , file_permissions_oct );
593
+ /* fd not opened in this process */
594
+
595
+ if (!file -> pathname )
596
+ filepath = get_file_path (file );
597
+ else
598
+ /* different process already filled it in */
599
+ filepath = file -> pathname ;
600
+ opened_fds [index ] = open (filepath , O_RDWR | O_APPEND | O_CREAT , file_permissions_oct );
509
601
if (opened_fds [index ] < 0 ) {
510
602
LM_ERR ("Opening socket error\n" );
511
603
lock_release (global_lock );
@@ -517,9 +609,9 @@ static void rotating(struct flat_file *file){
517
609
518
610
lock_release (global_lock );
519
611
return ;
520
- }
521
612
522
- if (rotate_version [index ] != file -> rotate_version && opened_fds [index ] != -1 ) {
613
+ } else if (rotate_version [index ] != file -> rotate_version ) {
614
+ /* fd is opened in this process */
523
615
524
616
/* update version */
525
617
rotate_version [index ] = file -> rotate_version ;
@@ -532,7 +624,7 @@ static void rotating(struct flat_file *file){
532
624
return ;
533
625
}
534
626
535
- opened_fds [index ] = open (file -> path . s , O_RDWR | O_APPEND | O_CREAT , file_permissions_oct );
627
+ opened_fds [index ] = open (file -> pathname , O_RDWR | O_APPEND | O_CREAT , file_permissions_oct );
536
628
if (opened_fds [index ] < 0 ) {
537
629
LM_ERR ("Opening socket error\n" );
538
630
return ;
@@ -708,6 +800,44 @@ static str flat_print(evi_reply_sock *sock){
708
800
return fs -> file -> path ;
709
801
}
710
802
803
+ void event_flatstore_rotate (int sender , void * param )
804
+ {
805
+ /* we've been instructed to double check the versions of our sockets */
806
+ struct flat_file * file ;
807
+ int index ;
808
+
809
+ lock_get (global_lock );
810
+ for (file = * list_files ; file ; file = file -> next ) {
811
+ index = file -> file_index_process ;
812
+ if (opened_fds [index ] != -1 && rotate_version [index ] != file -> rotate_version ) {
813
+ close (opened_fds [index ]);
814
+ opened_fds [index ] = -1 ; /* open it next time we have an event */
815
+ file -> counter_open -- ;
816
+ }
817
+ }
818
+ lock_release (global_lock );
819
+ }
820
+
821
+ static void event_flatstore_timer (unsigned int ticks , void * param )
822
+ {
823
+ struct flat_file * file ;
824
+
825
+ /* we only run when ticks is multiple of file_rotate_period */
826
+ if (time (NULL ) % file_rotate_period != 0 )
827
+ return ;
828
+
829
+ lock_get (global_lock );
830
+ for (file = * list_files ; file ; file = file -> next ) {
831
+ file -> rotate_version ++ ;
832
+ file -> pathname = get_file_path (file );
833
+ LM_DBG ("File %s is being rotated at %u - new file is %s\n" ,
834
+ file -> path .s , ticks , file -> pathname );
835
+ }
836
+ /* inform everyone they need to rotate */
837
+ ipc_broadcast_rpc (event_flatstore_rotate , 0 );
838
+ lock_release (global_lock );
839
+ }
840
+
711
841
static void verify_delete (void ) {
712
842
struct flat_delete * del_it , * del_prev , * del_tmp ;
713
843
@@ -750,6 +880,10 @@ static void verify_delete(void) {
750
880
else
751
881
* list_delete = del_it -> next ;
752
882
883
+ if (del_it -> file -> pathname &&
884
+ del_it -> file -> pathname != del_it -> file -> path .s )
885
+ shm_free (del_it -> file -> pathname );
886
+
753
887
del_tmp = del_it ;
754
888
del_it = del_it -> next ;
755
889
shm_free (del_tmp );
0 commit comments