mirror of
https://github.com/samba-team/samba.git
synced 2025-02-26 21:57:41 +03:00
added ctdb_status tool
(This used to be ctdb commit 908d6c6a936e21f70f05827ce302e966cca0132a)
This commit is contained in:
parent
00c706c2b8
commit
2e5aae04de
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
117
ctdb/tools/ctdb_status.c
Normal file
117
ctdb/tools/ctdb_status.c
Normal file
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user