147147 /* misc */ \
148148 HANDLER (AUTH , UNIMPL ) \
149149 HANDLER (ECHO , UNIMPL ) \
150- HANDLER (PING , PROXY ) \
151- HANDLER (INFO , PROXY ) \
150+ HANDLER (PING , EXTRA ) \
151+ HANDLER (INFO , EXTRA ) \
152+ HANDLER (PROXY , EXTRA ) \
152153 HANDLER (QUIT , UNIMPL ) \
153154 HANDLER (SELECT , UNIMPL )
154155
156+ #define CMD_INCREF (cmd ) \
157+ do { \
158+ (cmd)->rep_buf[0].buf->refcount++; \
159+ if ((cmd)->rep_buf[1].buf != (cmd)->rep_buf[0].buf) { \
160+ (cmd)->rep_buf[1].buf->refcount++; \
161+ } \
162+ } while (0)
163+
155164enum {
156165 CMD_DO (CMD_DEFINE )
157166};
@@ -160,7 +169,7 @@ enum {
160169 CMD_UNIMPL ,
161170 CMD_BASIC ,
162171 CMD_COMPLEX ,
163- CMD_PROXY ,
172+ CMD_EXTRA ,
164173};
165174
166175struct cmd_item {
@@ -223,13 +232,15 @@ static void cmd_init(struct context *ctx, struct command *cmd)
223232
224233static void cmd_recycle (struct context * ctx , struct command * cmd )
225234{
226- ctx -> stats .cmds -- ;
235+ ATOMIC_DEC (ctx -> mstats .cmds , 1 );
236+
227237 STAILQ_NEXT (cmd , cmd_next ) = NULL ;
228238 STAILQ_NEXT (cmd , ready_next ) = NULL ;
229239 STAILQ_NEXT (cmd , waiting_next ) = NULL ;
230240 STAILQ_NEXT (cmd , sub_cmd_next ) = NULL ;
231241 STAILQ_INSERT_HEAD (& ctx -> free_cmdq , cmd , cmd_next );
232- ctx -> nfree_cmdq ++ ;
242+
243+ ATOMIC_INC (ctx -> mstats .free_cmds , 1 );
233244}
234245
235246static int cmd_in_queue (struct command * cmd , struct connection * server )
@@ -287,30 +298,14 @@ static int cmd_format_stats(char *dest, size_t n, struct stats *stats, char *lat
287298 "remote_latency:%.6f\r\n"
288299 "total_latency:%.6f\r\n"
289300 "last_command_latency:%s\r\n"
290- "in_use_buffers:%lld\r\n"
291- "free_buffers:%lld\r\n"
292- "in_use_cmds:%lld\r\n"
293- "free_cmds:%lld\r\n"
294- "in_use_conns:%lld\r\n"
295- "free_conns:%lld\r\n"
296- "in_use_conn_info:%lld\r\n"
297- "free_conn_info:%lld\r\n"
298301 "remotes:%s\r\n" ,
299302 config .cluster , VERSION , stats -> pid , stats -> threads ,
300303 stats -> used_cpu_sys , stats -> used_cpu_user ,
301304 stats -> basic .connected_clients ,
302305 stats -> basic .completed_commands ,
303306 stats -> basic .recv_bytes , stats -> basic .send_bytes ,
304- stats -> basic .remote_latency ,
305- stats -> basic .total_latency , latency ,
306- stats -> basic .buffers ,
307- stats -> free_buffers ,
308- stats -> basic .cmds ,
309- stats -> free_cmds ,
310- stats -> basic .conns ,
311- stats -> free_conns ,
312- stats -> basic .conn_info ,
313- stats -> free_conn_info ,
307+ stats -> basic .remote_latency / 1000000.0 ,
308+ stats -> basic .total_latency / 1000000.0 , latency ,
314309 stats -> remote_nodes );
315310}
316311
@@ -484,11 +479,7 @@ int cmd_ping(struct command *cmd)
484479{
485480 conn_add_data (cmd -> client , (uint8_t * )rep_ping , 7 ,
486481 & cmd -> rep_buf [0 ], & cmd -> rep_buf [1 ]);
487-
488- cmd -> rep_buf [0 ].buf -> refcount ++ ;
489- if (cmd -> rep_buf [1 ].buf != cmd -> rep_buf [0 ].buf ) {
490- cmd -> rep_buf [1 ].buf -> refcount ++ ;
491- }
482+ CMD_INCREF (cmd );
492483
493484 cmd_mark_done (cmd );
494485 return CORVUS_OK ;
@@ -505,7 +496,7 @@ int cmd_info(struct command *cmd)
505496 memset (latency , 0 , sizeof (latency ));
506497
507498 for (i = 0 ; i < stats .threads ; i ++ ) {
508- n = snprintf (latency + size , 16 , "%.6f" , stats .last_command_latency [i ]);
499+ n = snprintf (latency + size , 16 , "%.6f" , stats .last_command_latency [i ] / 1000000.0 );
509500 size += n ;
510501 if (i < stats .threads - 1 ) {
511502 latency [size ] = ',' ;
@@ -522,23 +513,75 @@ int cmd_info(struct command *cmd)
522513 snprintf (head , sizeof (head ), fmt , n );
523514
524515 conn_add_data (cmd -> client , (uint8_t * )head , size , & cmd -> rep_buf [0 ], NULL );
525- cmd -> rep_buf [0 ].buf -> refcount ++ ;
526516 conn_add_data (cmd -> client , (uint8_t * )info , n , NULL , NULL );
527517 conn_add_data (cmd -> client , (uint8_t * )"\r\n" , 2 , NULL , & cmd -> rep_buf [1 ]);
528- if (cmd -> rep_buf [1 ].buf != cmd -> rep_buf [0 ].buf ) {
529- cmd -> rep_buf [1 ].buf -> refcount ++ ;
530- }
518+ CMD_INCREF (cmd );
519+
520+ cmd_mark_done (cmd );
521+ return CORVUS_OK ;
522+ }
523+
524+ int cmd_proxy_info (struct command * cmd )
525+ {
526+ struct memory_stats stats ;
527+ memset (& stats , 0 , sizeof (stats ));
528+ stats_get_memory (& stats );
529+
530+ int n = 1024 ;
531+ char data [n + 1 ];
532+ snprintf (data , n ,
533+ "+"
534+ "in_use_buffers:%lld\n"
535+ "free_buffers:%lld\n"
536+ "in_use_cmds:%lld\n"
537+ "free_cmds:%lld\n"
538+ "in_use_conns:%lld\n"
539+ "free_conns:%lld\n"
540+ "in_use_conn_info:%lld\n"
541+ "free_conn_info:%lld"
542+ "\r\n" ,
543+ stats .buffers , stats .free_buffers , stats .cmds , stats .free_cmds ,
544+ stats .conns , stats .free_conns , stats .conn_info , stats .free_conn_info );
545+
546+ conn_add_data (cmd -> client , (uint8_t * )data , strlen (data ),
547+ & cmd -> rep_buf [0 ], & cmd -> rep_buf [1 ]);
548+ CMD_INCREF (cmd );
549+
531550 cmd_mark_done (cmd );
532551 return CORVUS_OK ;
533552}
534553
535- int cmd_proxy (struct command * cmd )
554+ int cmd_proxy (struct command * cmd , struct redis_data * data )
555+ {
556+ ASSERT_TYPE (data , REP_ARRAY );
557+ ASSERT_ELEMENTS (data -> elements >= 2 , data );
558+
559+ struct redis_data * op = & data -> element [1 ];
560+ ASSERT_TYPE (op , REP_STRING );
561+
562+ char type [op -> pos .str_len + 1 ];
563+ if (pos_to_str (& op -> pos , type ) == CORVUS_ERR ) {
564+ LOG (ERROR , "cmd_proxy: parse error" );
565+ return CORVUS_ERR ;
566+ }
567+
568+ if (strcasecmp (type , "INFO" ) == 0 ) {
569+ return cmd_proxy_info (cmd );
570+ } else {
571+ cmd_mark_fail (cmd , rep_err );
572+ }
573+ return CORVUS_OK ;
574+ }
575+
576+ int cmd_extra (struct command * cmd , struct redis_data * data )
536577{
537578 switch (cmd -> cmd_type ) {
538579 case CMD_PING :
539580 return cmd_ping (cmd );
540581 case CMD_INFO :
541582 return cmd_info (cmd );
583+ case CMD_PROXY :
584+ return cmd_proxy (cmd , data );
542585 default :
543586 LOG (ERROR , "%s: unknown command type %d" , __func__ , cmd -> cmd_type );
544587 return CORVUS_ERR ;
@@ -555,8 +598,8 @@ int cmd_forward(struct command *cmd, struct redis_data *data)
555598 return cmd_forward_basic (cmd );
556599 case CMD_COMPLEX :
557600 return cmd_forward_complex (cmd , data );
558- case CMD_PROXY :
559- return cmd_proxy (cmd );
601+ case CMD_EXTRA :
602+ return cmd_extra (cmd , data );
560603 case CMD_UNIMPL :
561604 return CORVUS_ERR ;
562605 }
@@ -786,13 +829,13 @@ struct command *cmd_create(struct context *ctx)
786829 LOG (DEBUG , "cmd get cache" );
787830 cmd = STAILQ_FIRST (& ctx -> free_cmdq );
788831 STAILQ_REMOVE_HEAD (& ctx -> free_cmdq , cmd_next );
789- ctx -> nfree_cmdq -- ;
832+ ATOMIC_DEC ( ctx -> mstats . free_cmds , 1 ) ;
790833 STAILQ_NEXT (cmd , cmd_next ) = NULL ;
791834 } else {
792835 cmd = malloc (sizeof (struct command ));
793836 }
794837 cmd_init (ctx , cmd );
795- ctx -> stats .cmds ++ ;
838+ ATOMIC_INC ( ctx -> mstats .cmds , 1 ) ;
796839 return cmd ;
797840}
798841
@@ -923,22 +966,23 @@ void cmd_stats(struct command *cmd)
923966{
924967 struct context * ctx = cmd -> ctx ;
925968 struct command * last , * first ;
926- double latency ;
969+ long long latency ;
970+
971+ ATOMIC_INC (ctx -> stats .completed_commands , 1 );
927972
928- ctx -> stats . completed_commands ++ ;
973+ latency = cmd -> req_time [ 1 ] - cmd -> req_time [ 0 ] ;
929974
930- latency = (cmd -> req_time [1 ] - cmd -> req_time [0 ]) / 1000000.0 ;
931- ctx -> stats .total_latency += latency ;
932- ctx -> last_command_latency = latency ;
975+ ATOMIC_INC (ctx -> stats .total_latency , latency );
976+ ATOMIC_SET (ctx -> last_command_latency , latency );
933977
934978 if (!STAILQ_EMPTY (& cmd -> sub_cmds )) {
935979 first = STAILQ_FIRST (& cmd -> sub_cmds );
936980 last = STAILQ_LAST (& cmd -> sub_cmds , command , sub_cmd_next );
937- latency = ( last -> rep_time [1 ] - first -> rep_time [0 ]) / 1000000.0 ;
981+ latency = last -> rep_time [1 ] - first -> rep_time [0 ];
938982 } else {
939- latency = ( cmd -> rep_time [1 ] - cmd -> rep_time [0 ]) / 1000000.0 ;
983+ latency = cmd -> rep_time [1 ] - cmd -> rep_time [0 ];
940984 }
941- ctx -> stats .remote_latency += latency ;
985+ ATOMIC_INC ( ctx -> stats .remote_latency , latency ) ;
942986}
943987
944988void cmd_set_stale (struct command * cmd )
0 commit comments