r84429 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r84428‎ | r84429 | r84430 >
Date:22:18, 20 March 2011
Author:platonides
Status:fixme (Comments)
Tags:nodeploy 
Comment:
Basic stats
Modified paths:
  • /trunk/extensions/PoolCounter/daemon/Makefile (modified) (history)
  • /trunk/extensions/PoolCounter/daemon/client_data.c (modified) (history)
  • /trunk/extensions/PoolCounter/daemon/locks.c (modified) (history)
  • /trunk/extensions/PoolCounter/daemon/locks.h (modified) (history)
  • /trunk/extensions/PoolCounter/daemon/main.c (modified) (history)
  • /trunk/extensions/PoolCounter/daemon/stats.c (added) (history)
  • /trunk/extensions/PoolCounter/daemon/stats.h (added) (history)
  • /trunk/extensions/PoolCounter/daemon/stats.list (added) (history)

Diff [purge]

Index: trunk/extensions/PoolCounter/daemon/stats.c
@@ -0,0 +1,40 @@
 2+#include <stdio.h>
 3+#include <string.h>
 4+#include "stats.h"
 5+
 6+
 7+struct stats stats;
 8+
 9+#define COMMAND(item) + sizeof(#item) + 2 + MAX_COUNT_LEN
 10+static char stats_buffer[
 11+ sizeof("Uptime: 100000 days, 23h 59m 59s") + 2
 12+ #include "stats.list"
 13+];
 14+#undef COMMAND
 15+
 16+const char* provide_stats(const char* type)
 17+{
 18+ int seconds = time(NULL) - stats.start;
 19+ int minutes = seconds / 60;
 20+ seconds %= 60;
 21+ int hours = minutes / 60;
 22+ minutes %= 60;
 23+ unsigned int days = hours / 24;
 24+
 25+ int n;
 26+ n = sprintf( stats_buffer, "uptime: %u days, %dh %dm %ds\n", days, hours, minutes, seconds );
 27+
 28+ if ( !strcasecmp( type, "FULL" ) ) {
 29+ #define COMMAND(item) n += sprintf( stats_buffer + n, #item ": %" PRcount "\n", stats.item );
 30+ #include "stats.list"
 31+ #undef COMMAND
 32+ strcpy( stats_buffer + n, "\n" );
 33+ } else if ( strcasecmp( type, "UPTIME" ) ) {
 34+ #define COMMAND(item) if ( !strcasecmp( type, #item ) ) sprintf( stats_buffer, #item ": %" PRcount "\n", stats.item ); else
 35+ #include "stats.list"
 36+ #undef COMMAND
 37+
 38+ strcpy( stats_buffer, "ERROR WRONG_STAT" );
 39+ }
 40+ return stats_buffer;
 41+}
Property changes on: trunk/extensions/PoolCounter/daemon/stats.c
___________________________________________________________________
Added: svn:eol-style
142 + native
Index: trunk/extensions/PoolCounter/daemon/locks.h
@@ -39,7 +39,7 @@
4040 struct client_data;
4141 void init_lock(struct locks* l);
4242 void finish_lock(struct locks* l);
43 -char* process_line(struct client_data* cli_data, char* line, int line_len);
 43+const char* process_line(struct client_data* cli_data, char* line, int line_len);
4444 void process_timeout(struct locks* l);
4545 void remove_client_lock(struct locks* l, int wakeup_anyones);
4646 void send_client(struct locks* l, const char* msg);
Index: trunk/extensions/PoolCounter/daemon/stats.h
@@ -0,0 +1,23 @@
 2+
 3+#include <time.h>
 4+#include <stdint.h>
 5+#include <inttypes.h>
 6+
 7+typedef int64_t count_t;
 8+#define PRcount PRIi64
 9+#define MAX_COUNT_LEN sizeof("−9223372036854775808")
 10+
 11+struct stats {
 12+ time_t start;
 13+
 14+#define COMMAND(item) volatile count_t item;
 15+#include "stats.list"
 16+#undef COMMAND
 17+
 18+};
 19+
 20+extern struct stats stats;
 21+const char* provide_stats(const char* type);
 22+
 23+#define incr_stats(item) stats.item++
 24+#define decr_stats(item) stats.item--
Property changes on: trunk/extensions/PoolCounter/daemon/stats.h
___________________________________________________________________
Added: svn:eol-style
125 + native
Index: trunk/extensions/PoolCounter/daemon/main.c
@@ -12,6 +12,7 @@
1313 #include "client_data.h"
1414 #include "prototypes.h"
1515 #include "locks.h"
 16+#include "stats.h"
1617
1718 static int open_sockets = 1; /* Program will automatically close when this reaches 0 */
1819
@@ -38,6 +39,8 @@
3940 return 1;
4041 }
4142
 43+ stats.start = time( NULL );
 44+
4245 event_set( &listener_ev, listener, EV_READ | EV_PERSIST, on_connect, NULL );
4346
4447 event_add( &listener_ev, NULL );
@@ -91,6 +94,7 @@
9295 #endif
9396
9497 if ( fd == -1 ) {
 98+ incr_stats( connect_errors );
9599 perror( "Error accepting" );
96100 return;
97101 }
@@ -104,6 +108,7 @@
105109
106110 cli = new_client_data( fd );
107111 if ( !cli ) {
 112+ incr_stats( connect_errors );
108113 perror( "Couldn't allocate the client data! :(" );
109114 close( fd );
110115 return;
Index: trunk/extensions/PoolCounter/daemon/client_data.c
@@ -6,6 +6,7 @@
77 #include <malloc.h>
88 #include "client_data.h"
99 #include "locks.h"
 10+#include "stats.h"
1011
1112 struct client_data* new_client_data(int fd) {
1213 struct client_data* cd;
@@ -98,6 +99,7 @@
99100
100101 if ( send( cli_data->fd, msg, len, 0) != len ) {
101102 perror( "Something failed sending message" );
 103+ incr_stats( failed_sends );
102104 }
103105 /* Wait for answer */
104106 event_add( &cli_data->ev, NULL );
Index: trunk/extensions/PoolCounter/daemon/stats.list
@@ -0,0 +1,13 @@
 2+
 3+/* Preprocessor template for iterating the stats items */
 4+COMMAND(total_acquired) /* Total number of acquired locks */
 5+COMMAND(total_releases) /* Total number of released locks */
 6+COMMAND(hashtable_entries) /* Number of locks currently held */
 7+COMMAND(processing_workers) /* Number of workers currently doing work */
 8+COMMAND(waiting_workers) /* Number of workers currently waiting for a lock */
 9+COMMAND(connect_errors) /* Clients whose connection couldn't be served */
 10+COMMAND(failed_sends) /* Number of send() calls which didn't succeed */
 11+COMMAND(full_queues) /* Number of times locks were refused because the queue already had so many workers */
 12+COMMAND(lock_mismatch) /* Number of times a user tried to do a lock without a previous release */
 13+COMMAND(release_mismatch) /* Number of times a user tried to do a release without a previous lock */
 14+
Property changes on: trunk/extensions/PoolCounter/daemon/stats.list
___________________________________________________________________
Added: svn:eol-style
115 + native
Index: trunk/extensions/PoolCounter/daemon/locks.c
@@ -5,6 +5,7 @@
66 #include "locks.h"
77 #include "hash.h"
88 #include "client_data.h"
 9+#include "stats.h"
910
1011 void init_lock(struct locks* l) {
1112 l->state = UNLOCKED;
@@ -42,7 +43,7 @@
4344 return num;
4445 }
4546
46 -char* process_line(struct client_data* cli_data, char* line, int line_len) {
 47+const char* process_line(struct client_data* cli_data, char* line, int line_len) {
4748 struct locks* l = &cli_data->client_locks;
4849 if (line_len > 0 && line[line_len-1] == '\r') {
4950 line_len--;
@@ -51,6 +52,7 @@
5253
5354 if ( !strncmp( line, "ACQ4ME ", 7 ) || !strncmp( line, "ACQ4ANY ", 8 ) ) {
5455 if ( l->state != UNLOCKED ) {
 56+ incr_stats( lock_mismatch );
5557 return "LOCK_HELD\n";
5658 }
5759
@@ -71,7 +73,7 @@
7274 if ( !pCounter ) {
7375 pCounter = malloc( sizeof( *pCounter ) );
7476 if ( !pCounter ) {
75 - fprintf(stderr, "Out of memory\n");
 77+ fprintf( stderr, "Out of memory\n" );
7678 return "ERROR OUT_OF_MEMORY\n";
7779 }
7880 pCounter->htentry.key = strdup( key );
@@ -84,10 +86,13 @@
8587 DOUBLE_LLIST_INIT( pCounter->for_anyone );
8688
8789 hashtable_insert( primary_hashtable, (struct hashtable_entry *) pCounter );
 90+ incr_stats( hashtable_entries );
8891 }
8992
90 - if ( pCounter->count >= maxqueue )
 93+ if ( pCounter->count >= maxqueue ) {
 94+ incr_stats( full_queues );
9195 return "QUEUE_FULL\n";
 96+ }
9297
9398 l->parent = pCounter;
9499 pCounter->count++;
@@ -95,7 +100,9 @@
96101 if ( pCounter->processing < workers ) {
97102 l->state = PROCESSING;
98103 pCounter->processing++;
 104+ incr_stats( processing_workers );
99105 DOUBLE_LLIST_ADD( &pCounter->working, &l->siblings );
 106+ incr_stats( total_acquired );
100107 return "LOCKED\n";
101108 } else {
102109 struct timeval wait_time;
@@ -106,6 +113,7 @@
107114 l->state = WAITING;
108115 DOUBLE_LLIST_ADD( &pCounter->for_them, &l->siblings );
109116 }
 117+ incr_stats( waiting_workers );
110118
111119 wait_time.tv_sec = timeout;
112120 wait_time.tv_usec = 0;
@@ -115,11 +123,15 @@
116124 }
117125 } else if ( !strncmp(line, "RELEASE", 7) ) {
118126 if ( l->state == UNLOCKED ) {
 127+ incr_stats( release_mismatch );
119128 return "NOT_LOCKED\n";
120129 } else {
121130 remove_client_lock( l, 1 );
 131+ incr_stats( total_releases );
122132 return "RELEASED\n";
123133 }
 134+ } else if ( !strncmp( line, "STATS ", 6 ) ) {
 135+ return provide_stats( line + 6 );
124136 } else {
125137 return "ERROR BAD_COMMAND\n";
126138 }
@@ -128,6 +140,7 @@
129141 void process_timeout(struct locks* l) {
130142 if ( ( l->state == WAIT_ANY ) || ( l->state == WAITING ) ) {
131143 send_client( l, "TIMEOUT\n" );
 144+ decr_stats( waiting_workers );
132145 remove_client_lock( l, 0 );
133146 }
134147 }
@@ -139,6 +152,7 @@
140153 while ( l->parent->for_anyone.next != &l->parent->for_anyone ) {
141154 send_client( (void*)l->parent->for_anyone.next, "DONE\n" );
142155 remove_client_lock( (void*)l->parent->for_anyone.next, 0 );
 156+ decr_stats( waiting_workers );
143157 }
144158 }
145159
@@ -162,14 +176,18 @@
163177 DOUBLE_LLIST_ADD( &l->parent->working, &new_owner->siblings );
164178 send_client( new_owner, "LOCKED\n" );
165179 new_owner->state = PROCESSING;
 180+ incr_stats( total_acquired );
 181+ decr_stats( waiting_workers );
166182 } else {
167 - l->parent->processing--;
 183+ l->parent->processing--;
 184+ decr_stats( processing_workers );
168185 }
169186 }
170187
171188 l->state = UNLOCKED;
172189 l->parent->count--;
173190 if ( !l->parent->count ) {
 191+ decr_stats( hashtable_entries );
174192 hashtable_remove( l->parent->htentry.parent_hashtable, &l->parent->htentry );
175193 free( l->parent->htentry.key );
176194 free( l->parent );
Index: trunk/extensions/PoolCounter/daemon/Makefile
@@ -1,9 +1,9 @@
22 CC=gcc
33 DEFINES=-DENDIAN_BIG=0 -DENDIAN_LITTLE=1 -DHAVE_ACCEPT4=1
44 CFLAGS=-Wall $(DEFINES)
5 -OBJS=main.o client_data.o locks.o hash.o
 5+OBJS=main.o client_data.o locks.o hash.o stats.o
66 LINK=-levent
7 -HEADERS=prototypes.h client_data.h
 7+HEADERS=prototypes.h client_data.h stats.h stats.list
88 DESTDIR ?=
99
1010 poolcounterd: $(OBJS)

Sign-offs

UserFlagDate
Jeenxxxinspected20:42, 10 December 2013 (struck 20:43, 10 December 2013)
Jeenxxxinspected20:43, 10 December 2013

Comments

#Comment by Tim Starling (talk | contribs)   04:21, 21 March 2011

If you absolutely must use fixed-size output buffers, please use snprintf() instead of sprintf() and strcpy(), to avoid a buffer overflow.

Your assumption that a short non-blocking write to a TCP socket will always succeed is looking even more shaky now that you have the "STATS FULL". If you used bufferevent_write(), you wouldn't have to worry about either that or about accurate sizing of sprintf/snprintf buffers. Memory management would be handled by libevent.

#Comment by RobLa-WMF (talk | contribs)   22:18, 30 January 2012

This is "nodeploy" only because it doesn't automatically get deployed with the rest of 1.19, but needs to be packaged and pushed.

#Comment by Platonides (talk | contribs)   16:41, 31 January 2012

This is already running in the cluster. Looking at r85311 it seems to have been packaged, too. Maybe it's not in puppet , though.

Status & tagging log