1010#include <stdlib.h>
1111#include <fcntl.h>
1212
13- #define LOG_PER_TIMER 500
1413#define LOG_LENGTH 400
1514#define IP_LENGTH 16
1615#define KEY_LENGTH 256
1716
18- typedef enum cmd_in_second_state {
17+ typedef enum cmd_in_second_state {
1918 NOT_STARTED ,
2019 ON_LOGGING ,
2120 ON_FLUSHING
22- }state ;
21+ } state ;
2322
24- typedef struct cmd_in_second_log {
23+ typedef struct cmd_in_second_log {
2524 char key [KEY_LENGTH ];
2625 char client_ip [IP_LENGTH ];
27- int32_t timer_idx ;
28- }logtype ;
26+ } logtype ;
2927
3028typedef struct cmd_in_second_buffer {
3129 logtype * ring ;
3230 int32_t front ;
3331 int32_t rear ;
3432 int32_t capacity ;
35- }buffertype ;
33+ } buffertype ;
3634
37- typedef struct cmd_in_second_timer {
38- struct timeval * times ;
39- int32_t size ;
40- int32_t counter ;
41- }timertype ;
35+ typedef struct cmd_in_second_timer {
36+ struct timeval * ring ;
37+ int32_t front ;
38+ int32_t rear ;
39+ int32_t capacity ;
40+ int32_t circular_counter ;
41+ } timertype ;
4242
4343struct cmd_in_second {
44- char cmd [10 ];
45- char collection_name [4 ];
44+ char cmd [20 ];
45+ char collection_name [10 ];
4646 struct cmd_in_second_buffer buffer ;
47- int32_t bulk_limit ;
4847 timertype timer ;
48+ int32_t bulk_limit ;
49+ int32_t log_per_timer ;
4950 state cur_state ;
5051};
5152
52- static EXTENSION_LOGGER_DESCRIPTOR * mc_logger ;
5353static struct cmd_in_second this ;
5454
5555static bool is_bulk_cmd ()
5656{
57- const logtype * front = & this .buffer .ring [this .buffer .front ];
58- const logtype * rear = & this .buffer .ring [this .buffer .rear ];
57+ const bool timer_empty = this .timer .front == this .timer .rear ;
5958
60- struct timeval front_time = this .timer .times [front -> timer_idx ];
61- struct timeval rear_time = this .timer .times [rear -> timer_idx ];
59+ if (timer_empty ) {
60+ return false;
61+ }
62+
63+ struct timeval front_time = this .timer .ring [this .timer .front ];
64+ struct timeval rear_time = this .timer .ring [this .timer .rear ];
6265
6366 return rear_time .tv_sec - front_time .tv_sec <= 1 ;
6467}
6568
6669static void get_whole_cmd (char * whole_cmd )
6770{
6871 if (strlen (this .collection_name )) {
69- sprintf (whole_cmd , "%s %s" , this .collection_name , this .cmd );
72+ snprintf (whole_cmd , 20 , "%s %s" , this .collection_name , this .cmd );
7073 return ;
7174 }
72- sprintf (whole_cmd , "%s" , this .cmd );
75+ snprintf (whole_cmd , 15 , "%s" , this .cmd );
7376}
7477
7578static bool buffer_empty ()
@@ -79,64 +82,74 @@ static bool buffer_empty()
7982
8083static void * buffer_flush_thread ()
8184{
82- int32_t fd = open ("cmd_in_second.log" , O_CREAT | O_WRONLY | O_TRUNC , 0644 );
85+ const int32_t fd = open ("cmd_in_second.log" , O_CREAT | O_WRONLY | O_TRUNC , 0644 );
8386
8487 if (fd < 0 ) {
85- mc_logger -> log (EXTENSION_LOG_WARNING , NULL ,
86- "Can't open cmd_in_second log file: %s\n" , "cmd_in_second.log" );
88+ perror ("Can't open cmd_in_second log file: cmd_in_second.log" );
8789 return NULL ;
8890 }
8991
90- char whole_cmd [20 ] = "" ;
91- get_whole_cmd (whole_cmd );
92-
9392 buffertype * buffer = & this .buffer ;
9493 timertype * timer = & this .timer ;
9594
96- int32_t timer_idx = -1 ;
97-
9895 char * log_str = (char * )malloc (LOG_LENGTH * this .bulk_limit * sizeof (char ));
9996
10097 if (log_str == NULL ) {
101- mc_logger -> log ( EXTENSION_LOG_WARNING , NULL , "Can't allocate memory" );
98+ perror ( "Can't allocate memory" );
10299 return NULL ;
103100 }
104101
102+ char whole_cmd [20 ] = "" ;
103+ get_whole_cmd (whole_cmd );
104+
105+ const size_t whole_cmd_len = strlen (whole_cmd );
106+ const size_t whitespaces = 3 ;
107+
105108 int32_t expected_write_length = 0 ;
109+ int32_t circular_log_counter = 0 ;
106110
107111 while (!buffer_empty ()) {
108112
109- logtype front = buffer -> ring [buffer -> front ++ ];
113+ const logtype front = buffer -> ring [buffer -> front ];
114+ buffer -> front = (buffer -> front + 1 ) % buffer -> capacity ;
110115
111116 char time_str [50 ] = "" ;
112117
113- if (front . timer_idx != timer_idx ) {
118+ if (circular_log_counter == 0 ) {
114119
115- const struct timeval * front_time = & timer -> times [ front . timer_idx ];
120+ const struct timeval * front_time = & timer -> ring [ timer -> front ];
116121 const struct tm * lt = localtime ((time_t * )& front_time -> tv_sec );
117122
118- sprintf (time_str , "%04d-%02d-%02d %02d:%02d:%02d.%06d\n" , lt -> tm_year + 1900 , lt -> tm_mon + 1 , lt -> tm_mday , lt -> tm_hour , lt -> tm_min , lt -> tm_sec , (int32_t )front_time -> tv_usec );
119- timer_idx = front .timer_idx ;
123+ timer -> front = (timer -> front + 1 ) % timer -> capacity ;
120124
125+ if (lt == NULL ) {
126+ perror ("localtime failed" );
127+ continue ;
128+ }
129+
130+ sprintf (time_str , "%04d-%02d-%02d %02d:%02d:%02d.%06d\n" , lt -> tm_year + 1900 , lt -> tm_mon + 1 , lt -> tm_mday ,
131+ lt -> tm_hour , lt -> tm_min , lt -> tm_sec , (int32_t )front_time -> tv_usec );
121132 expected_write_length += 27 ;
122133 }
134+
123135 char log [LOG_LENGTH ] = "" ;
124- sprintf (log , "%s%s %s %s\n" , time_str , whole_cmd , front .key , front .client_ip );
136+ snprintf (log , LOG_LENGTH , "%s%s %s %s\n" , time_str , whole_cmd , front .key , front .client_ip );
125137 strncat (log_str , log , LOG_LENGTH );
126138
127- expected_write_length += LOG_LENGTH ;
139+ expected_write_length += whole_cmd_len + strlen (front .key ) + strlen (front .client_ip ) + whitespaces ;
140+ circular_log_counter = (circular_log_counter + 1 ) % this .log_per_timer ;
128141 }
129142
130143 if (write (fd , log_str , expected_write_length ) != expected_write_length ) {
131- mc_logger -> log ( EXTENSION_LOG_WARNING , NULL , "write length is difference to expectation." );
144+ perror ( "write length is difference to expectation." );
132145 }
133146
134147 close (fd );
135148
136149 free (log_str );
137150
138- free (this .timer .times );
139- this .timer .times = NULL ;
151+ free (this .timer .ring );
152+ this .timer .ring = NULL ;
140153
141154 free (this .buffer .ring );
142155 this .buffer .ring = NULL ;
@@ -148,7 +161,6 @@ static void* buffer_flush_thread()
148161
149162static int32_t buffer_flush ()
150163{
151-
152164 this .cur_state = ON_FLUSHING ;
153165
154166 int32_t ret = 0 ;
@@ -159,8 +171,8 @@ static int32_t buffer_flush()
159171 pthread_attr_setdetachstate (& attr , PTHREAD_CREATE_DETACHED ) != 0 ||
160172 (ret = pthread_create (& tid , & attr , buffer_flush_thread , NULL )) != 0 )
161173 {
162- mc_logger -> log ( EXTENSION_LOG_WARNING , NULL ,
163- "Can't create buffer flush thread: %s\n" , strerror ( ret )) ;
174+ perror ( "Can't create buffer flush thread" );
175+ ret = -1 ;
164176 }
165177
166178 return ret ;
@@ -171,6 +183,9 @@ static void buffer_add(const logtype* log)
171183
172184 struct cmd_in_second_buffer * buffer = & this .buffer ;
173185
186+ buffer -> ring [buffer -> rear ] = * log ;
187+ buffer -> rear = (buffer -> rear + 1 ) % buffer -> capacity ;
188+
174189 const bool buffer_full = (buffer -> rear + 1 ) % buffer -> capacity == buffer -> front ;
175190
176191 if (buffer_full ) {
@@ -181,41 +196,55 @@ static void buffer_add(const logtype* log)
181196 buffer -> front = (buffer -> front + 1 ) % buffer -> capacity ;
182197 }
183198
184- buffer -> ring [buffer -> rear ] = * log ;
185- buffer -> rear = (buffer -> rear + 1 ) % buffer -> capacity ;
199+ }
200+
201+ static void timer_add ()
202+ {
203+ struct cmd_in_second_timer * timer = & this .timer ;
204+
205+ const bool timer_full = (timer -> rear + 1 ) % timer -> capacity == timer -> front ;
206+
207+ if (timer_full ) {
208+ timer -> front = (timer -> front + 1 ) % timer -> capacity ;
209+ }
210+
211+ if (gettimeofday (& timer -> ring [timer -> rear ], NULL ) == -1 ) {
212+ perror ("gettimeofday failed" );
213+ return ;
214+ };
215+
216+ timer -> rear = (timer -> rear + 1 ) % timer -> capacity ;
186217}
187218
188219static bool is_cmd_to_log (const char * collection_name , const char * cmd )
189220{
190- return strcmp (this .collection_name , collection_name ) == 0 && strcmp (this .cmd , cmd ) == 0 ;
221+ return strcmp (this .collection_name , collection_name ) == 0 &&
222+ strcmp (this .cmd , cmd ) == 0 ;
191223}
192224
193- bool cmd_in_second_write (const char * collection_name , const char * cmd , const char * key , const char * client_ip )
225+ bool cmd_in_second_write (const char * collection_name , const char * cmd ,
226+ const char * key , const char * client_ip )
194227{
195228 if (this .cur_state != ON_LOGGING || !is_cmd_to_log (collection_name , cmd )) {
196229 return false;
197230 }
198231
199- timertype * timer = & this .timer ;
200-
201- logtype log = {"" , "" , 0 };
232+ logtype log = {"" , "" };
202233 snprintf (log .client_ip , IP_LENGTH , "%s" , client_ip );
203234 snprintf (log .key , KEY_LENGTH , "%s" , key );
204235
205- if (timer -> counter == 0 ) {
206- timer -> size ++ ;
207- gettimeofday (& timer -> times [timer -> size - 1 ], NULL );
236+ if (this .timer .circular_counter == 0 ) {
237+ timer_add ();
208238 }
209239
210- log .timer_idx = timer -> size - 1 ;
211-
212240 buffer_add (& log );
213- timer -> counter = (timer -> counter + 1 ) % LOG_PER_TIMER ;
241+ this . timer . circular_counter = (this . timer . circular_counter + 1 ) % this . log_per_timer ;
214242
215243 return true;
216244}
217245
218- int32_t cmd_in_second_start (const char * collection_name , const char * cmd , const int32_t bulk_limit )
246+ int32_t cmd_in_second_start (const char * collection_name , const char * cmd ,
247+ const int32_t bulk_limit )
219248{
220249
221250 if (this .cur_state != NOT_STARTED ) {
@@ -233,17 +262,21 @@ int32_t cmd_in_second_start(const char* collection_name, const char* cmd, const
233262 return CMD_IN_SECOND_NO_MEM ;
234263 }
235264
236- this .timer .size = 0 ;
237- this .timer .counter = 0 ;
238- this .timer .times = (struct timeval * )malloc (bulk_limit * sizeof (struct timeval ));
265+ this .log_per_timer = bulk_limit / 10 + (bulk_limit % 10 != 0 );
266+ this .timer .capacity = this .log_per_timer + 1 ;
267+ this .timer .front = 0 ;
268+ this .timer .rear = 0 ;
269+ this .timer .circular_counter = 0 ;
270+
271+ this .timer .ring = (struct timeval * )malloc (this .timer .capacity * sizeof (struct timeval ));
239272
240- if (this .timer .times == NULL ) {
273+ if (this .timer .ring == NULL ) {
241274 free (this .buffer .ring );
242275 return CMD_IN_SECOND_NO_MEM ;
243276 }
244277
245- sprintf (this .collection_name , "%s" , collection_name );
246- sprintf (this .cmd , "%s" , cmd );
278+ snprintf (this .collection_name , 5 , "%s" , collection_name );
279+ snprintf (this .cmd , 15 , "%s" , cmd );
247280
248281 this .cur_state = ON_LOGGING ;
249282
0 commit comments