]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
added ctdb_status tool
authorAndrew Tridgell <tridge@samba.org>
Fri, 20 Apr 2007 10:07:47 +0000 (20:07 +1000)
committerAndrew Tridgell <tridge@samba.org>
Fri, 20 Apr 2007 10:07:47 +0000 (20:07 +1000)
(This used to be ctdb commit 908d6c6a936e21f70f05827ce302e966cca0132a)

ctdb/Makefile.in
ctdb/common/cmdline.c
ctdb/common/ctdb.c
ctdb/common/ctdb_client.c
ctdb/common/ctdb_daemon.c
ctdb/common/ctdb_lockwait.c
ctdb/common/ctdb_util.c
ctdb/include/ctdb.h
ctdb/include/ctdb_private.h
ctdb/tools/ctdb_status.c [new file with mode: 0644]

index 7729875f4e3494aa8c4b167855b65fa58126b53e..adc1f92d0a925b2cfa9b76b63a851b16df510e14 100644 (file)
@@ -30,7 +30,7 @@ CTDB_OBJ = $(CTDB_COMMON_OBJ) $(CTDB_TCP_OBJ)
 
 OBJS = @TDBOBJ@ @TALLOCOBJ@ @LIBREPLACEOBJ@ @INFINIBAND_WRAPPER_OBJ@ $(EXTRA_OBJ) $(EVENTS_OBJ) $(CTDB_OBJ)
 
-BINS = bin/ctdbd bin/ctdbd_test bin/ctdb_test bin/ctdb_bench bin/ctdb_messaging bin/ctdb_fetch bin/ctdb_fetch1 bin/lockwait @INFINIBAND_BINS@
+BINS = bin/ctdbd bin/ctdbd_test bin/ctdb_test bin/ctdb_bench bin/ctdb_messaging bin/ctdb_fetch bin/ctdb_fetch1 bin/lockwait bin/ctdb_status @INFINIBAND_BINS@
 
 DIRS = lib bin
 
@@ -57,6 +57,10 @@ bin/ctdbd: $(OBJS) direct/ctdbd.o
        @echo Linking $@
        @$(CC) $(CFLAGS) -o $@ direct/ctdbd.o $(OBJS) $(LIB_FLAGS)
 
+bin/ctdb_status: $(OBJS) tools/ctdb_status.o 
+       @echo Linking $@
+       @$(CC) $(CFLAGS) -o $@ tools/ctdb_status.o $(OBJS) $(LIB_FLAGS)
+
 bin/ctdbd_test: $(OBJS) direct/ctdbd_test.o
        @echo Linking $@
        @$(CC) $(CFLAGS) -o $@ direct/ctdbd_test.o 
index e319d4635e37f32c1488547965f6d0511b1eb7d5..699cb8fb2201159251f49e1f6f64a6af44c34d0a 100644 (file)
@@ -22,6 +22,8 @@
 #include "lib/events/events.h"
 #include "system/filesys.h"
 #include "popt.h"
+#include "../include/ctdb.h"
+#include "../include/ctdb_private.h"
 
 /* Handle common command line options for ctdb test progs
  */
@@ -110,3 +112,31 @@ struct ctdb_context *ctdb_cmdline_init(struct event_context *ev)
 
        return ctdb;
 }
+
+
+/*
+  startup a client only ctdb context
+ */
+struct ctdb_context *ctdb_cmdline_client(struct event_context *ev, const char *ctdb_socket)
+{
+       struct ctdb_context *ctdb;
+       int ret;
+
+       /* initialise ctdb */
+       ctdb = ctdb_init(ev);
+       if (ctdb == NULL) {
+               printf("Failed to init ctdb\n");
+               exit(1);
+       }
+
+       ctdb->daemon.name = talloc_strdup(ctdb, ctdb_socket);
+
+       ret = ctdb_socket_connect(ctdb);
+       if (ret != 0) {
+               DEBUG(0,(__location__ " Failed to connect to daemon\n"));
+               talloc_free(ctdb);
+               return NULL;
+       }
+
+       return ctdb;
+}
index ac3dc6d345fb582ac08fc79d9d23319966e40740..ed96df91021fea30cc0b7fdf05decf2b5c6428a3 100644 (file)
@@ -211,6 +211,8 @@ void ctdb_recv_pkt(struct ctdb_context *ctdb, uint8_t *data, uint32_t length)
        struct ctdb_req_header *hdr = (struct ctdb_req_header *)data;
        TALLOC_CTX *tmp_ctx;
 
+       ctdb->status.node_packets_recv++;
+
        /* place the packet as a child of the tmp_ctx. We then use
           talloc_free() below to free it. If any of the calls want
           to keep it, then they will steal it somewhere else, and the
@@ -375,6 +377,7 @@ static void ctdb_defer_packet(struct ctdb_context *ctdb, struct ctdb_req_header
 void ctdb_queue_packet(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
 {
        struct ctdb_node *node;
+       ctdb->status.node_packets_sent++;
        node = ctdb->nodes[hdr->destnode];
        if (hdr->destnode == ctdb->vnn && !(ctdb->flags & CTDB_FLAG_SELF_CONNECT)) {
                ctdb_defer_packet(ctdb, hdr);
index f09894b55550729e9e3b01895d61c2a83c6b69c6..dbed8d35851d72a224b9ad7cee372c2504617b4e 100644 (file)
@@ -84,6 +84,8 @@ static void ctdb_client_reply_call(struct ctdb_context *ctdb, struct ctdb_req_he
        state->state = CTDB_CALL_DONE;
 }
 
+static void ctdb_reply_status(struct ctdb_context *ctdb, struct ctdb_req_header *hdr);
+
 /*
   this is called in the client, when data comes in from the daemon
  */
@@ -138,6 +140,10 @@ static void ctdb_client_read_cb(uint8_t *data, size_t cnt, void *args)
                ctdb_reply_connect_wait(ctdb, hdr);
                break;
 
+       case CTDB_REPLY_STATUS:
+               ctdb_reply_status(ctdb, hdr);
+               break;
+
        default:
                DEBUG(0,("bogus operation code:%d\n",hdr->operation));
        }
@@ -149,7 +155,7 @@ done:
 /*
   connect to a unix domain socket
 */
-static int ux_socket_connect(struct ctdb_context *ctdb)
+int ctdb_socket_connect(struct ctdb_context *ctdb)
 {
        struct sockaddr_un addr;
 
@@ -276,7 +282,7 @@ struct ctdb_client_call_state *ctdb_call_send(struct ctdb_db_context *ctdb_db,
 
        /* if the domain socket is not yet open, open it */
        if (ctdb->daemon.sd==-1) {
-               ux_socket_connect(ctdb);
+               ctdb_socket_connect(ctdb);
        }
 
        ret = ctdb_ltdb_lock(ctdb_db, call->key);
@@ -373,7 +379,7 @@ int ctdb_set_message_handler(struct ctdb_context *ctdb, uint32_t srvid,
 
        /* if the domain socket is not yet open, open it */
        if (ctdb->daemon.sd==-1) {
-               ux_socket_connect(ctdb);
+               ctdb_socket_connect(ctdb);
        }
 
        ZERO_STRUCT(c);
@@ -447,7 +453,7 @@ void ctdb_connect_wait(struct ctdb_context *ctdb)
 
        /* if the domain socket is not yet open, open it */
        if (ctdb->daemon.sd==-1) {
-               ux_socket_connect(ctdb);
+               ctdb_socket_connect(ctdb);
        }
        
        res = ctdb_queue_send(ctdb->daemon.queue, (uint8_t *)&r.hdr, r.hdr.length);
@@ -585,7 +591,7 @@ void ctdb_shutdown(struct ctdb_context *ctdb)
 
        /* if the domain socket is not yet open, open it */
        if (ctdb->daemon.sd==-1) {
-               ux_socket_connect(ctdb);
+               ctdb_socket_connect(ctdb);
        }
 
        len = sizeof(struct ctdb_req_shutdown);
@@ -604,4 +610,73 @@ void ctdb_shutdown(struct ctdb_context *ctdb)
        }
 }
 
+enum ctdb_status_states {CTDB_STATUS_WAIT, CTDB_STATUS_DONE};
+
+struct ctdb_status_state {
+       uint32_t reqid;
+       struct ctdb_status *status;
+       enum ctdb_status_states state;
+};
+
+/*
+  handle a ctdb_reply_status reply
+ */
+static void ctdb_reply_status(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
+{
+       struct ctdb_reply_status *r = (struct ctdb_reply_status *)hdr;
+       struct ctdb_status_state *state;
+
+       state = idr_find_type(ctdb->idr, hdr->reqid, struct ctdb_status_state);
+       if (state == NULL) {
+               DEBUG(0, ("reqid %d not found\n", hdr->reqid));
+               return;
+       }
+
+       *state->status = r->status;
+       state->state = CTDB_STATUS_DONE;
+}
+
+/*
+  wait until we're the only node left.
+  this function never returns
+*/
+int ctdb_status(struct ctdb_context *ctdb, struct ctdb_status *status)
+{
+       struct ctdb_req_status r;
+       int ret;
+       struct ctdb_status_state *state;
+
+       /* if the domain socket is not yet open, open it */
+       if (ctdb->daemon.sd==-1) {
+               ctdb_socket_connect(ctdb);
+       }
+
+       state = talloc(ctdb, struct ctdb_status_state);
+       CTDB_NO_MEMORY(ctdb, state);
+
+       state->reqid = idr_get_new(ctdb->idr, state, 0xFFFF);
+       state->status = status;
+       state->state = CTDB_STATUS_WAIT;
+       
+       ZERO_STRUCT(r);
+       r.hdr.length       = sizeof(r);
+       r.hdr.ctdb_magic   = CTDB_MAGIC;
+       r.hdr.ctdb_version = CTDB_VERSION;
+       r.hdr.operation    = CTDB_REQ_STATUS;
+       r.hdr.reqid        = state->reqid;
+
+       ret = ctdb_client_queue_pkt(ctdb, &(r.hdr));
+       if (ret != 0) {
+               talloc_free(state);
+               return -1;
+       }
+       
+       while (state->state == CTDB_STATUS_WAIT) {
+               event_loop_once(ctdb->ev);
+       }
+
+       talloc_free(state);
+
+       return 0;
+}
 
index be535ef5ed03deff21f496e1141ea6e2b96814c0..3189a8a31c6ad3955fc13f4c95950a2f2c3f04d8 100644 (file)
@@ -74,6 +74,15 @@ static void block_signal(int signum)
 }
 
 
+/*
+  send a packet to a client
+ */
+static int daemon_queue_send(struct ctdb_client *client, struct ctdb_req_header *hdr)
+{
+       client->ctdb->status.client_packets_sent++;
+       return ctdb_queue_send(client->queue, (uint8_t *)hdr, hdr->length);
+}
+
 /*
   message handler for when we are in daemon mode. This redirects the message
   to the right client
@@ -101,7 +110,7 @@ static void daemon_message_handler(struct ctdb_context *ctdb, uint32_t srvid,
        r->datalen       = data.dsize;
        memcpy(&r->data[0], data.dptr, data.dsize);
 
-       ctdb_queue_send(client->queue, (uint8_t *)&r->hdr, len);
+       daemon_queue_send(client, &r->hdr);
 
        talloc_free(r);
 }
@@ -205,7 +214,34 @@ static void daemon_request_connect_wait(struct ctdb_client *client,
        r.vnn           = ctdb_get_vnn(client->ctdb);
        r.num_connected = client->ctdb->num_connected;
        
-       res = ctdb_queue_send(client->queue, (uint8_t *)&r.hdr, r.hdr.length);
+       res = daemon_queue_send(client, &r.hdr);
+       if (res != 0) {
+               DEBUG(0,(__location__ " Failed to queue a connect wait response\n"));
+               return;
+       }
+}
+
+
+/*
+  called when the daemon gets a status request from a client
+ */
+static void daemon_request_status(struct ctdb_client *client, 
+                                 struct ctdb_req_status *c)
+{
+       struct ctdb_reply_status r;
+       int res;
+
+       /* now send the reply */
+       ZERO_STRUCT(r);
+
+       r.hdr.length     = sizeof(r);
+       r.hdr.ctdb_magic = CTDB_MAGIC;
+       r.hdr.ctdb_version = CTDB_VERSION;
+       r.hdr.operation = CTDB_REPLY_STATUS;
+       r.hdr.reqid = c->hdr.reqid;
+       r.status = client->ctdb->status;
+       
+       res = daemon_queue_send(client, &r.hdr);
        if (res != 0) {
                DEBUG(0,(__location__ " Failed to queue a connect wait response\n"));
                return;
@@ -255,6 +291,7 @@ struct daemon_call_state {
        struct ctdb_client *client;
        uint32_t reqid;
        struct ctdb_call *call;
+       struct timeval start_time;
 };
 
 /* 
@@ -275,6 +312,8 @@ static void daemon_call_from_client_callback(struct ctdb_call_state *state)
        res = ctdb_daemon_call_recv(state, dstate->call);
        if (res != 0) {
                DEBUG(0, (__location__ " ctdbd_call_recv() returned error\n"));
+               client->ctdb->status.pending_calls--;
+               ctdb_latency(&client->ctdb->status.max_call_latency, dstate->start_time);
                return;
        }
 
@@ -282,6 +321,8 @@ static void daemon_call_from_client_callback(struct ctdb_call_state *state)
        r = ctdbd_allocate_pkt(dstate, length);
        if (r == NULL) {
                DEBUG(0, (__location__ " Failed to allocate reply_call in ctdb daemon\n"));
+               client->ctdb->status.pending_calls--;
+               ctdb_latency(&client->ctdb->status.max_call_latency, dstate->start_time);
                return;
        }
        memset(r, 0, offsetof(struct ctdb_reply_call, data));
@@ -293,11 +334,13 @@ static void daemon_call_from_client_callback(struct ctdb_call_state *state)
        r->datalen          = dstate->call->reply_data.dsize;
        memcpy(&r->data[0], dstate->call->reply_data.dptr, r->datalen);
 
-       res = ctdb_queue_send(client->queue, (uint8_t *)&r->hdr, r->hdr.length);
+       res = daemon_queue_send(client, &r->hdr);
        if (res != 0) {
                DEBUG(0, (__location__ "Failed to queue packet from daemon to client\n"));
        }
        talloc_free(dstate);
+       client->ctdb->status.pending_calls--;
+       ctdb_latency(&client->ctdb->status.max_call_latency, dstate->start_time);
 }
 
 
@@ -317,10 +360,14 @@ static void daemon_request_call_from_client(struct ctdb_client *client,
        int ret;
        struct ctdb_context *ctdb = client->ctdb;
 
+       ctdb->status.total_calls++;
+       ctdb->status.pending_calls++;
+
        ctdb_db = find_ctdb_db(client->ctdb, c->db_id);
        if (!ctdb_db) {
                DEBUG(0, (__location__ " Unknown database in request. db_id==0x%08x",
                          c->db_id));
+               ctdb->status.pending_calls--;
                return;
        }
 
@@ -332,11 +379,13 @@ static void daemon_request_call_from_client(struct ctdb_client *client,
                                           daemon_incoming_packet, client);
        if (ret == -2) {
                /* will retry later */
+               ctdb->status.pending_calls--;
                return;
        }
 
        if (ret != 0) {
                DEBUG(0,(__location__ " Unable to fetch record\n"));
+               ctdb->status.pending_calls--;
                return;
        }
 
@@ -344,8 +393,10 @@ static void daemon_request_call_from_client(struct ctdb_client *client,
        if (dstate == NULL) {
                ctdb_ltdb_unlock(ctdb_db, key);
                DEBUG(0,(__location__ " Unable to allocate dstate\n"));
+               ctdb->status.pending_calls--;
                return;
        }
+       dstate->start_time = timeval_current();
        dstate->client = client;
        dstate->reqid  = c->hdr.reqid;
        talloc_steal(dstate, data.dptr);
@@ -354,6 +405,8 @@ static void daemon_request_call_from_client(struct ctdb_client *client,
        if (call == NULL) {
                ctdb_ltdb_unlock(ctdb_db, key);
                DEBUG(0,(__location__ " Unable to allocate call\n"));
+               ctdb->status.pending_calls--;
+               ctdb_latency(&ctdb->status.max_call_latency, dstate->start_time);
                return;
        }
 
@@ -373,6 +426,8 @@ static void daemon_request_call_from_client(struct ctdb_client *client,
 
        if (state == NULL) {
                DEBUG(0,(__location__ " Unable to setup call send\n"));
+               ctdb->status.pending_calls--;
+               ctdb_latency(&ctdb->status.max_call_latency, dstate->start_time);
                return;
        }
        talloc_steal(state, dstate);
@@ -427,6 +482,10 @@ static void daemon_incoming_packet(void *p, uint8_t *data, uint32_t nread)
                daemon_request_shutdown(client, (struct ctdb_req_shutdown *)hdr);
                break;
 
+       case CTDB_REQ_STATUS:
+               daemon_request_status(client, (struct ctdb_req_status *)hdr);
+               break;
+
        default:
                DEBUG(0,(__location__ " daemon: unrecognized operation %d\n",
                         hdr->operation));
@@ -436,7 +495,9 @@ done:
        talloc_free(tmp_ctx);
 }
 
-
+/*
+  called when the daemon gets a incoming packet
+ */
 static void ctdb_daemon_read_cb(uint8_t *data, size_t cnt, void *args)
 {
        struct ctdb_client *client = talloc_get_type(args, struct ctdb_client);
@@ -447,6 +508,8 @@ static void ctdb_daemon_read_cb(uint8_t *data, size_t cnt, void *args)
                return;
        }
 
+       client->ctdb->status.client_packets_recv++;
+
        if (cnt < sizeof(*hdr)) {
                ctdb_set_error(client->ctdb, "Bad packet length %d in daemon\n", cnt);
                return;
@@ -468,6 +531,10 @@ static void ctdb_daemon_read_cb(uint8_t *data, size_t cnt, void *args)
                return;
        }
 
+       DEBUG(3,(__location__ " client request %d of type %d length %d from "
+                "node %d to %d\n", hdr->reqid, hdr->operation, hdr->length,
+                hdr->srcnode, hdr->destnode));
+
        /* it is the responsibility of the incoming packet function to free 'data' */
        daemon_incoming_packet(client, data, cnt);
 }
index d5cea7c695c82fa34b5fe397fd7afddb9c6cd9d3..1ed6e3ab8962f5631de6de9476d1404bc8c7c4ce 100644 (file)
@@ -29,6 +29,7 @@
 
 
 struct lockwait_handle {
+       struct ctdb_context *ctdb;
        struct fd_event *fde;
        int fd[2];
        pid_t child;
@@ -48,6 +49,7 @@ static void lockwait_handler(struct event_context *ev, struct fd_event *fde,
        talloc_set_destructor(h, NULL);
        close(h->fd[0]);
        DEBUG(3,(__location__ " lockwait took %.6f seconds\n", timeval_elapsed(&h->t)));
+       h->ctdb->status.pending_lockwait_calls--;
        talloc_free(h); 
        callback(p);
        waitpid(child, NULL, 0);
@@ -55,6 +57,7 @@ static void lockwait_handler(struct event_context *ev, struct fd_event *fde,
 
 static int lockwait_destructor(struct lockwait_handle *h)
 {
+       h->ctdb->status.pending_lockwait_calls--;
        close(h->fd[0]);
        kill(h->child, SIGKILL);
        waitpid(h->child, NULL, 0);
@@ -79,7 +82,11 @@ struct lockwait_handle *ctdb_lockwait(struct ctdb_db_context *ctdb_db,
        struct lockwait_handle *result;
        int ret;
 
+       ctdb_db->ctdb->status.lockwait_calls++;
+       ctdb_db->ctdb->status.pending_lockwait_calls++;
+
        if (!(result = talloc_zero(ctdb_db, struct lockwait_handle))) {
+               ctdb_db->ctdb->status.pending_lockwait_calls--;
                return NULL;
        }
 
@@ -87,6 +94,7 @@ struct lockwait_handle *ctdb_lockwait(struct ctdb_db_context *ctdb_db,
 
        if (ret != 0) {
                talloc_free(result);
+               ctdb_db->ctdb->status.pending_lockwait_calls--;
                return NULL;
        }
 
@@ -96,11 +104,13 @@ struct lockwait_handle *ctdb_lockwait(struct ctdb_db_context *ctdb_db,
                close(result->fd[0]);
                close(result->fd[1]);
                talloc_free(result);
+               ctdb_db->ctdb->status.pending_lockwait_calls--;
                return NULL;
        }
 
        result->callback = callback;
        result->private_data = private_data;
+       result->ctdb = ctdb_db->ctdb;
 
        if (result->child == 0) {
                close(result->fd[0]);
@@ -119,6 +129,7 @@ struct lockwait_handle *ctdb_lockwait(struct ctdb_db_context *ctdb_db,
                                   (void *)result);
        if (result->fde == NULL) {
                talloc_free(result);
+               ctdb_db->ctdb->status.pending_lockwait_calls--;
                return NULL;
        }
 
index c5215c27a5d5f429664e8725d11f3a51b51ac545..9a5e51bfa0bedfd60dd8a89a6540e962161621a4 100644 (file)
@@ -117,3 +117,14 @@ void *_idr_find_type(struct idr_context *idp, int id, const char *type, const ch
        return p;
 }
 
+
+/*
+  update a max latency number
+ */
+void ctdb_latency(double *latency, struct timeval t)
+{
+       double l = timeval_elapsed(&t);
+       if (l > *latency) {
+               *latency = l;
+       }
+}
index 997bdc6e13f326740f80f47f15517cc6b979e141..cb765884b6cceefefb556d1a91a5b7983f3e5810 100644 (file)
@@ -208,4 +208,9 @@ int ctdb_register_message_handler(struct ctdb_context *ctdb,
 struct ctdb_db_context *find_ctdb_db(struct ctdb_context *ctdb, uint32_t id);
 
 
+struct ctdb_context *ctdb_cmdline_client(struct event_context *ev, const char *ctdb_socket);
+
+struct ctdb_status;
+int ctdb_status(struct ctdb_context *ctdb, struct ctdb_status *status);
+
 #endif
index 2f42cfb88a07d1413e761ef79c469e2741a24936..c46a2c025060b94e99cde739d4fa375aa0037ae0 100644 (file)
@@ -114,6 +114,22 @@ struct ctdb_daemon_data {
        struct ctdb_queue *queue;
 };
 
+/*
+  ctdb status information
+ */
+struct ctdb_status {
+       uint32_t client_packets_sent;
+       uint32_t client_packets_recv;
+       uint32_t node_packets_sent;
+       uint32_t node_packets_recv;
+       uint32_t total_calls;
+       uint32_t pending_calls;
+       uint32_t lockwait_calls;
+       uint32_t pending_lockwait_calls;
+       double max_call_latency;
+       double max_lockwait_latency;
+};
+
 /* main state of the ctdb daemon */
 struct ctdb_context {
        struct event_context *ev;
@@ -135,6 +151,7 @@ struct ctdb_context {
        struct ctdb_db_context *db_list;
        struct ctdb_message_list *message_list;
        struct ctdb_daemon_data daemon;
+       struct ctdb_status status;
 };
 
 struct ctdb_db_context {
@@ -225,7 +242,9 @@ enum ctdb_operation {
        CTDB_REQ_REGISTER       = 1000,     
        CTDB_REQ_CONNECT_WAIT   = 1001,
        CTDB_REPLY_CONNECT_WAIT = 1002,
-       CTDB_REQ_SHUTDOWN       = 1003
+       CTDB_REQ_SHUTDOWN       = 1003,
+       CTDB_REQ_STATUS         = 1004,
+       CTDB_REPLY_STATUS       = 1005
 };
 
 #define CTDB_MAGIC 0x43544442 /* CTDB */
@@ -318,6 +337,15 @@ struct ctdb_reply_connect_wait {
        uint32_t num_connected;
 };
 
+struct ctdb_req_status {
+       struct ctdb_req_header hdr;
+};
+
+struct ctdb_reply_status {
+       struct ctdb_req_header hdr;
+       struct ctdb_status status;
+};
+
 /* internal prototypes */
 void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
 void ctdb_fatal(struct ctdb_context *ctdb, const char *msg);
@@ -459,4 +487,8 @@ void *_idr_find_type(struct idr_context *idp, int id, const char *type, const ch
 
 void ctdb_recv_raw_pkt(void *p, uint8_t *data, uint32_t length);
 
+int ctdb_socket_connect(struct ctdb_context *ctdb);
+
+void ctdb_latency(double *latency, struct timeval t);
+
 #endif
diff --git a/ctdb/tools/ctdb_status.c b/ctdb/tools/ctdb_status.c
new file mode 100644 (file)
index 0000000..266fb0a
--- /dev/null
@@ -0,0 +1,117 @@
+/* 
+   ctdb status tool
+
+   Copyright (C) Andrew Tridgell  2007
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "includes.h"
+#include "lib/events/events.h"
+#include "system/filesys.h"
+#include "popt.h"
+#include "cmdline.h"
+#include "../include/ctdb_private.h"
+
+
+/*
+  display status structure
+ */
+static void show_status(struct ctdb_status *s)
+{
+       printf(" client_packets_sent     %u\n", s->client_packets_sent);
+       printf(" client_packets_recv     %u\n", s->client_packets_recv);
+       printf(" node_packets_sent       %u\n", s->node_packets_sent);
+       printf(" node_packets_recv       %u\n", s->node_packets_recv);
+       printf(" total_calls             %u\n", s->total_calls);
+       printf(" pending_calls           %u\n", s->pending_calls);
+       printf(" lockwait_calls          %u\n", s->lockwait_calls);
+       printf(" pending_lockwait_calls  %u\n", s->pending_lockwait_calls);
+       printf(" max_call_latency        %.6f seconds\n", s->max_call_latency);
+       printf(" max_lockwait_latency    %.6f seconds\n", s->max_lockwait_latency);
+}
+
+/*
+  show usage message
+ */
+static void usage(void)
+{
+       printf("Usage: ctdb_status <socketpath>\n");
+       exit(1);
+}
+
+/*
+  main program
+*/
+int main(int argc, const char *argv[])
+{
+       struct ctdb_context *ctdb;
+       struct poptOption popt_options[] = {
+               POPT_AUTOHELP
+               POPT_CTDB_CMDLINE
+               POPT_TABLEEND
+       };
+       int opt;
+       const char **extra_argv;
+       int extra_argc = 0;
+       int ret;
+       poptContext pc;
+       struct event_context *ev;
+       const char *ctdb_socket;
+       struct ctdb_status status;
+
+       pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
+
+       while ((opt = poptGetNextOpt(pc)) != -1) {
+               switch (opt) {
+               default:
+                       fprintf(stderr, "Invalid option %s: %s\n", 
+                               poptBadOption(pc, 0), poptStrerror(opt));
+                       exit(1);
+               }
+       }
+
+       /* setup the remaining options for the main program to use */
+       extra_argv = poptGetArgs(pc);
+       if (extra_argv) {
+               extra_argv++;
+               while (extra_argv[extra_argc]) extra_argc++;
+       }
+
+       if (extra_argc < 1) {
+               usage();
+       }
+
+       ctdb_socket = extra_argv[0];
+
+       ev = event_context_init(NULL);
+
+       /* initialise ctdb */
+       ctdb = ctdb_cmdline_client(ev, ctdb_socket);
+       if (ctdb == NULL) {
+               printf("Failed to init ctdb\n");
+               exit(1);
+       }
+
+       ret = ctdb_status(ctdb, &status);
+       if (ret != 0) {
+               printf("Failed to get ctdb status\n");
+               exit(1);
+       }
+
+       show_status(&status);
+
+       return 0;
+}