git » nmdb » commit 6b1996e

Implement a REQ_STATS command in the server.

author Alberto Bertogli
2007-10-11 07:45:50 UTC
committer Alberto Bertogli
2007-10-11 07:45:50 UTC
parent 646fd0f95fe65d06b4e6bfa6e383ecd621dc8d3b

Implement a REQ_STATS command in the server.

This allows a client to query the stats from the server.

Signed-off-by: Alberto Bertogli <albertito@gmail.com>

nmdb/net-const.h +1 -0
nmdb/parse.c +79 -2
nmdb/stats.h +6 -4

diff --git a/nmdb/net-const.h b/nmdb/net-const.h
index b9e875a..4d8ecd9 100644
--- a/nmdb/net-const.h
+++ b/nmdb/net-const.h
@@ -39,6 +39,7 @@
 #define REQ_CAS			0x110
 #define REQ_CACHE_INCR		0x111
 #define REQ_INCR		0x112
+#define REQ_STATS		0x113
 
 /* Network replies (different namespace from requests) */
 #define REP_ERR			0x800
diff --git a/nmdb/parse.c b/nmdb/parse.c
index 29a9489..46c6877 100644
--- a/nmdb/parse.c
+++ b/nmdb/parse.c
@@ -17,6 +17,7 @@ static void parse_set(struct req_info *req, int impact_db, int async);
 static void parse_del(struct req_info *req, int impact_db, int async);
 static void parse_cas(struct req_info *req, int impact_db);
 static void parse_incr(struct req_info *req, int impact_db);
+static void parse_stats(struct req_info *req);
 
 
 /* Create a queue entry structure based on the parameters passed. Memory
@@ -195,6 +196,8 @@ int parse_message(struct req_info *req,
 	} else if (cmd == REQ_INCR) {
 		stats.db_incr++;
 		parse_incr(req, 1);
+	} else if (cmd == REQ_STATS) {
+		parse_stats(req);
 	} else {
 		stats.net_unk_req++;
 		req->reply_err(req, ERR_UNKREQ);
@@ -456,8 +459,8 @@ static void parse_cas(struct req_info *req, int impact_db)
 }
 
 
-/* ntohll() is not standard, so we define it using an UGLY trick because there
- * is no standard way to check for endianness at runtime! */
+/* ntohll() and htonll() are not standard, so we define it using an UGLY trick
+ * because there is no standard way to check for endianness at runtime! */
 static uint64_t ntohll(uint64_t x)
 {
 	static int endianness = 0;
@@ -481,6 +484,29 @@ static uint64_t ntohll(uint64_t x)
 			( (uint64_t) ntohl(x & 0xFFFFFFFF) ) << 32 );
 }
 
+static uint64_t htonll(uint64_t x)
+{
+	static int endianness = 0;
+
+	/* determine the endianness by checking how htonl() behaves; use -1
+	 * for little endian and 1 for big endian */
+	if (endianness == 0) {
+		if (htonl(1) == 1)
+			endianness = 1;
+		else
+			endianness = -1;
+	}
+
+	if (endianness == 1) {
+		/* big endian */
+		return x;
+	}
+
+	/* little endian */
+	return ( htonl( (x >> 32) & 0xFFFFFFFF ) | \
+			( (uint64_t) htonl(x & 0xFFFFFFFF) ) << 32 );
+}
+
 
 static void parse_incr(struct req_info *req, int impact_db)
 {
@@ -550,3 +576,54 @@ static void parse_incr(struct req_info *req, int impact_db)
 }
 
 
+static void parse_stats(struct req_info *req)
+{
+	int i;
+	uint64_t response[STATS_REPLY_SIZE];
+
+	/* The packet is just the request, there's no payload. We need to
+	 * reply with the stats structure.
+	 * The response structure is just several uint64_t packed together,
+	 * each one corresponds to a single value of the stats structure. */
+
+	/* We define a macro to do the assignment easily; it's not nice, but
+	 * it's more portable than using a packed struct */
+	i = 0;
+	#define fcpy(field) \
+		do { response[i] = htonll(stats.field); i++; } while(0)
+
+
+	fcpy(cache_get);
+	fcpy(cache_set);
+	fcpy(cache_del);
+	fcpy(cache_cas);
+	fcpy(cache_incr);
+
+	fcpy(db_get);
+	fcpy(db_set);
+	fcpy(db_del);
+	fcpy(db_cas);
+	fcpy(db_incr);
+
+	fcpy(cache_hits);
+	fcpy(cache_misses);
+
+	fcpy(db_hits);
+	fcpy(db_misses);
+
+	fcpy(msg_tipc);
+	fcpy(msg_tcp);
+	fcpy(msg_udp);
+	fcpy(msg_sctp);
+
+	fcpy(net_version_mismatch);
+	fcpy(net_broken_req);
+	fcpy(net_unk_req);
+
+	req->reply_long(req, REP_OK, (unsigned char *) response,
+			sizeof(response));
+
+	return;
+}
+
+
diff --git a/nmdb/stats.h b/nmdb/stats.h
index 5bf3e8b..8d85ff6 100644
--- a/nmdb/stats.h
+++ b/nmdb/stats.h
@@ -8,13 +8,13 @@ struct stats {
 	unsigned long cache_set;
 	unsigned long cache_del;
 	unsigned long cache_cas;
-	unsigned long cache_incr;
+	unsigned long cache_incr;	/* 5 */
 
 	unsigned long db_get;
 	unsigned long db_set;
 	unsigned long db_del;
 	unsigned long db_cas;
-	unsigned long db_incr;
+	unsigned long db_incr;		/* 10 */
 
 	unsigned long cache_hits;
 	unsigned long cache_misses;
@@ -23,16 +23,18 @@ struct stats {
 	unsigned long db_misses;
 
 
-	unsigned long msg_tipc;
+	unsigned long msg_tipc;		/* 15 */
 	unsigned long msg_tcp;
 	unsigned long msg_udp;
 	unsigned long msg_sctp;
 
 	unsigned long net_version_mismatch;
-	unsigned long net_broken_req;
+	unsigned long net_broken_req;	/* 20 */
 	unsigned long net_unk_req;
 };
 
+#define STATS_REPLY_SIZE 21
+
 void stats_init(struct stats *s);
 
 #endif