git » nmdb » master » tree

[master] / utils / nmdb-stats.c

/* nmdb-stats.c
 * Queries the stats of a nmdb server.
 * Alberto Bertogli (albertito@blitiri.com.ar)
 */

#include <stdio.h>		/* printf() */
#include <stdint.h>		/* uint64_t */
#include <string.h>		/* strcmp() */
#include <stdlib.h>		/* atoi() */
#include <arpa/inet.h>		/* htonl() and friends */

#include "nmdb.h"


/* ntohll() is not standard, so we define it using an UGLY trick because there
 * is no standard way to check for endianness at runtime! (this is the same as
 * the one in nmdb/parse.c, the infraestructure to keep these common is not
 * worth it)*/
static uint64_t ntohll(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 ( ntohl( (x >> 32) & 0xFFFFFFFF ) | \
			( (uint64_t) ntohl(x & 0xFFFFFFFF) ) << 32 );
}

#define MAX_STATS_SIZE 64

static void help(void)
{
	printf("Use: nmdb-stats [ tipc port | [tcp|udp|sctp] host port ]\n");
}

int main(int argc, char **argv)
{
	int i, j, k;
	int rv;
	uint64_t stats[MAX_STATS_SIZE];
	unsigned int nservers = 0, nstats = 0;
	nmdb_t *db;

	db = nmdb_init();

	if (argc < 3) {
		help();
		return 1;
	}

	if (strcmp("tipc", argv[1]) == 0) {
		rv = nmdb_add_tipc_server(db, atoi(argv[2]));
	} else {
		if (argc != 4) {
			help();
			return 1;
		}

		if (strcmp("tcp", argv[1]) == 0) {
			rv = nmdb_add_tcp_server(db, argv[2], atoi(argv[3]));
		} else if (strcmp("udp", argv[1]) == 0) {
			rv = nmdb_add_udp_server(db, argv[2], atoi(argv[3]));
		} else if  (strcmp("sctp", argv[1]) == 0) {
			rv = nmdb_add_sctp_server(db, argv[2], atoi(argv[3]));
		} else {
			help();
			return 1;
		}
	}

	if (!rv) {
		perror("Error adding server");
		return 1;
	}

	rv = nmdb_stats(db, (unsigned char *) stats, sizeof(stats),
			&nservers, &nstats);
	if (rv <= 0) {
		printf("Error %d\n", rv);
		return 1;
	}

	/* Macro to simplify showing the fields */
	#define shst(s, pos) \
		do { \
			printf("\t%ju\t%s\n", ntohll(stats[j + pos]), s); \
		} while(0)

	/* The following assumes it can be more than one server. This can
	 * never happen with the current code, but it can be useful as an
	 * example in the future. */
	for (i = 0; i < nservers; i++) {
		printf("stats for server %d:\n", i);

		j = nstats * i;

		/* note they are not necessarily in numerical order */
		shst("cache get", 0);
		shst("cache set", 1);
		shst("cache del", 2);
		shst("cache cas", 3);
		shst("cache incr", 4);

		shst("db get", 5);
		shst("db set", 6);
		shst("db del", 7);
		shst("db cas", 8);
		shst("db incr", 9);
		shst("db firstkey", 21);
		shst("db nextkey", 22);

		shst("cache hits", 10);
		shst("cache misses", 11);

		shst("db hits", 12);
		shst("db misses", 13);

		shst("msg tipc", 14);
		shst("msg tcp", 15);
		shst("msg udp", 16);
		shst("msg sctp", 17);

		shst("version mismatch", 18);
		shst("broken requests", 19);
		shst("unknown requests", 20);

		/* if there are any fields we don't know, show them anyway */
		for (k = 23; k < nstats; k++) {
			shst("unknown field", k);
		}

		printf("\n");
	}

	nmdb_free(db);

	return 0;
}