[SCM] CTDB repository - branch master updated - ctdb-1.12-192-g751ed46

Ronnie Sahlberg sahlberg at samba.org
Tue Feb 7 22:57:47 MST 2012


The branch, master has been updated
       via  751ed46197661eb841042ab6a02855a51dd0b17c (commit)
       via  b098bcf8007be63889aaed640a951b0eeaa9d191 (commit)
      from  3e5d2b61fcb4d0062d2573d99724f630a4fc4622 (commit)

http://gitweb.samba.org/?p=ctdb.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 751ed46197661eb841042ab6a02855a51dd0b17c
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Wed Feb 8 15:29:27 2012 +1100

    ReadOnly: add per-database statistics to view how much delegations/revokes we have

commit b098bcf8007be63889aaed640a951b0eeaa9d191
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Wed Feb 8 13:42:30 2012 +1100

    STATISTICS: add total counts for number of delegations and number of revokes
    
    Everytime we give a delegation to another node we count this as one delegation.
    If the same record is delegated to several nodes we count one for each node.
    
    Everytime a record has all its delegations revoked we count this as one revoke.

-----------------------------------------------------------------------

Summary of changes:
 include/ctdb.h            |   57 +++++++++++++++++++++++++++++++++++++++++++++
 include/ctdb_private.h    |   11 ++++++++
 include/ctdb_protocol.h   |   11 ++++++++
 libctdb/control.c         |   51 ++++++++++++++++++++++++++++++++++++++++
 libctdb/sync.c            |   18 ++++++++++++++
 server/ctdb_call.c        |    4 +++
 server/ctdb_control.c     |    4 +++
 server/ctdb_daemon.c      |    2 +
 server/ctdb_ltdb_server.c |   17 +++++++++++++
 tests/src/libctdb_test.c  |   17 +++++++++++++
 tools/ctdb.c              |   52 +++++++++++++++++++++++++++++++++++++++++
 11 files changed, 244 insertions(+), 0 deletions(-)


Changeset truncated at 500 lines:

diff --git a/include/ctdb.h b/include/ctdb.h
index 8dbdd47..93224cb 100644
--- a/include/ctdb.h
+++ b/include/ctdb.h
@@ -510,6 +510,39 @@ bool ctdb_getpnn_recv(struct ctdb_connection *ctdb,
 
 
 /**
+ * ctdb_getdbstat_send - read statistics for a db
+ * @ctdb: the ctdb_connection from ctdb_connect.
+ * @destnode: the destination node (see below)
+ * @db_id:    the database to collect the statistics from
+ * @callback: the callback when ctdb replies to our message (typesafe)
+ * @cbdata: the argument to callback()
+ *
+ * There are several special values for destnode, detailed in
+ * ctdb_protocol.h, particularly CTDB_CURRENT_NODE which means the
+ * local ctdbd.
+ */
+struct ctdb_request *
+ctdb_getdbstat_send(struct ctdb_connection *ctdb,
+		     uint32_t destnode,
+		     uint32_t db_id,
+		     ctdb_callback_t callback,
+		     void *cbdata);
+/**
+ * ctdb_getdbstat_recv - read an ctdb_getdbstat reply from ctdbd
+ * @ctdb: the ctdb_connection from ctdb_connect.
+ * @req: the completed request.
+ * @stat: a pointer to the *stat to fill in
+ *
+ * This returns false if something went wrong, or otherwise fills in **stats
+ * stats must be freed later by calling ctdb_free_dbstat();
+ */
+bool ctdb_getdbstat_recv(struct ctdb_connection *ctdb,
+			 struct ctdb_request *req,
+			 struct ctdb_db_statistics **stat);
+
+void ctdb_free_dbstat(struct ctdb_db_statistics *stat);
+
+/**
  * ctdb_check_message_handlers_send - check a list of message_handlers
  * if they are registered
  * message_handlers are registered on the daemon using the
@@ -876,6 +909,26 @@ bool ctdb_getpnn(struct ctdb_connection *ctdb,
 		 uint32_t *pnn);
 
 /**
+ * ctdb_getdbstat - read the db stat of a node (synchronous)
+ * @ctdb: the ctdb_connection from ctdb_connect.
+ * @destnode: the destination node (see below)
+ * @db_id:    the database to collect the statistics from
+ * @stat: a pointer to the *stat to fill in
+ *
+ * There are several special values for destnode, detailed in
+ * ctdb_protocol.h, particularly CTDB_CURRENT_NODE which means the
+ * local ctdbd.
+ *
+ * This returns false if something went wrong, or otherwise fills in **stat
+ * stat must be freed later by calling ctdb_free_dbstat();
+ */
+bool ctdb_getdbstat(struct ctdb_connection *ctdb,
+		    uint32_t destnode,
+		    uint32_t db_id,
+		    struct ctdb_db_statistics **stat);
+
+
+/**
  * ctdb_check_message_handlers - check a list of message_handlers (synchronous)
  * @ctdb: the ctdb_connection from ctdb_connect.
  * @destnode: the destination node (see below)
@@ -1092,6 +1145,10 @@ void ctdb_free_vnnmap(struct ctdb_vnn_map *vnnmap);
 	ctdb_getpnn_send((ctdb), (destnode),				\
 			 ctdb_sendcb((cb), (cbdata)), (cbdata))
 
+#define ctdb_getdbstat_send(ctdb, destnode, db_id, cb, cbdata)		\
+	ctdb_getdbstat_send((ctdb), (destnode), (db_id),		\
+			    ctdb_sendcb((cb), (cbdata)), (cbdata))
+
 #define ctdb_check_message_handlers_send(ctdb, destnode, num, mhs,	\
 			 cb, cbdata)					\
 	ctdb_check_message_handlers_send((ctdb), (destnode), (num), 	\
diff --git a/include/ctdb_private.h b/include/ctdb_private.h
index f58356f..f420e6c 100644
--- a/include/ctdb_private.h
+++ b/include/ctdb_private.h
@@ -300,6 +300,11 @@ struct ctdb_daemon_data {
 		ctdb->statistics_current.counter++;					\
 	}
 
+#define CTDB_INCREMENT_DB_STAT(ctdb_db, counter) \
+	{										\
+		ctdb_db->statistics.counter++;						\
+	}
+
 #define CTDB_DECREMENT_STAT(ctdb, counter) \
 	{										\
 		if (ctdb->statistics.counter > 0)					\
@@ -513,6 +518,8 @@ struct ctdb_db_context {
 	   so we can avoid sending duplicate fetch requests
 	*/
 	struct trbt_tree *deferred_fetch;
+
+	struct ctdb_db_statistics statistics;
 };
 
 
@@ -1440,4 +1447,8 @@ int ctdb_fetch_func(struct ctdb_call_info *call);
 
 int ctdb_fetch_with_header_func(struct ctdb_call_info *call);
 
+int32_t ctdb_control_get_db_statistics(struct ctdb_context *ctdb,
+				uint32_t db_id,
+				TDB_DATA *outdata);
+
 #endif
diff --git a/include/ctdb_protocol.h b/include/ctdb_protocol.h
index 0b3245d..4cf2789 100644
--- a/include/ctdb_protocol.h
+++ b/include/ctdb_protocol.h
@@ -377,6 +377,7 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS          = 0,
 		    CTDB_CONTROL_SET_DB_READONLY	 = 129,
 		    CTDB_CONTROL_CHECK_SRVIDS		 = 130,
 		    CTDB_CONTROL_TRAVERSE_START_EXT	 = 131,
+		    CTDB_CONTROL_GET_DB_STATISTICS	 = 132,
 };
 
 /*
@@ -646,6 +647,8 @@ struct ctdb_statistics {
 	uint32_t num_recoveries;
 	struct timeval statistics_start_time;
 	struct timeval statistics_current_time;
+	uint32_t total_ro_delegations;
+	uint32_t total_ro_revokes;
 };
 
 /*
@@ -657,6 +660,14 @@ struct ctdb_statistics_wire {
 };
 
 /*
+ * db statistics
+ */
+struct ctdb_db_statistics {
+	uint32_t db_ro_delegations;
+	uint32_t db_ro_revokes;
+};
+
+/*
  * wire format for interface list
  */
 #ifdef IFNAMSIZ
diff --git a/libctdb/control.c b/libctdb/control.c
index ba22444..8741ad9 100644
--- a/libctdb/control.c
+++ b/libctdb/control.c
@@ -25,6 +25,7 @@
 #undef ctdb_getrecmaster_send
 #undef ctdb_getrecmode_send
 #undef ctdb_getpnn_send
+#undef ctdb_getdbstat_send
 #undef ctdb_check_message_handlers_send
 #undef ctdb_getnodemap_send
 #undef ctdb_getpublicips_send
@@ -112,6 +113,56 @@ struct ctdb_request *ctdb_getpnn_send(struct ctdb_connection *ctdb,
 					NULL, 0, callback, private_data);
 }
 
+bool ctdb_getdbstat_recv(struct ctdb_connection *ctdb,
+			 struct ctdb_request *req,
+			 struct ctdb_db_statistics **stat)
+{
+	struct ctdb_reply_control *reply;
+	struct ctdb_db_statistics *s;
+
+	reply = unpack_reply_control(req, CTDB_CONTROL_GET_DB_STATISTICS);
+	if (!reply) {
+		return false;
+	}
+	if (reply->status == -1) {
+		DEBUG(ctdb, LOG_ERR, "ctdb_getpnn_recv: status -1");
+		return false;
+	}
+	if (reply->datalen != sizeof(struct ctdb_db_statistics)) {
+		DEBUG(ctdb, LOG_ERR, "ctdb_getdbstat_recv: returned data is %d bytes but should be %d", reply->datalen, (int)sizeof(struct ctdb_db_statistics));
+		return false;
+	}
+
+	s = malloc(sizeof(struct ctdb_db_statistics));
+	if (!s) {
+		return false;
+	}
+	memcpy(s, reply->data, sizeof(struct ctdb_db_statistics));
+	*stat = s;
+
+	return true;
+}
+
+struct ctdb_request *ctdb_getdbstat_send(struct ctdb_connection *ctdb,
+				      uint32_t destnode,
+				      uint32_t db_id,
+				      ctdb_callback_t callback,
+				      void *private_data)
+{
+	uint32_t indata = db_id;
+
+	return new_ctdb_control_request(ctdb, CTDB_CONTROL_GET_DB_STATISTICS, destnode,
+					&indata, sizeof(indata), callback, private_data);
+}
+
+void ctdb_free_dbstat(struct ctdb_db_statistics *stat)
+{
+	if (stat == NULL) {
+		return;
+	}
+	free(stat);
+}
+
 bool ctdb_getnodemap_recv(struct ctdb_connection *ctdb,
 		      struct ctdb_request *req, struct ctdb_node_map **nodemap)
 {
diff --git a/libctdb/sync.c b/libctdb/sync.c
index f2b6957..4b68cd1 100644
--- a/libctdb/sync.c
+++ b/libctdb/sync.c
@@ -136,6 +136,24 @@ bool ctdb_getpnn(struct ctdb_connection *ctdb,
 	return ret;
 }
 
+bool ctdb_getdbstat(struct ctdb_connection *ctdb,
+		    uint32_t destnode, uint32_t db_id,
+		    struct ctdb_db_statistics **stat)
+{
+	struct ctdb_request *req;
+	bool done = false;
+	bool ret = false;
+
+	req = synchronous(ctdb,
+			  ctdb_getdbstat_send(ctdb, destnode, db_id, set, &done),
+			  &done);
+	if (req != NULL) {
+		ret = ctdb_getdbstat_recv(ctdb, req, stat);
+		ctdb_request_free(req);
+	}
+	return ret;
+}
+
 bool ctdb_check_message_handlers(struct ctdb_connection *ctdb,
 		      uint32_t destnode, uint32_t num,
 		      uint64_t *mhs, uint8_t *result)
diff --git a/server/ctdb_call.c b/server/ctdb_call.c
index 654fff4..9922233 100644
--- a/server/ctdb_call.c
+++ b/server/ctdb_call.c
@@ -513,6 +513,8 @@ void ctdb_request_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
 
 	if (header.flags & CTDB_REC_RO_REVOKE_COMPLETE) {
 		header.flags &= ~(CTDB_REC_RO_HAVE_DELEGATIONS|CTDB_REC_RO_HAVE_READONLY|CTDB_REC_RO_REVOKING_READONLY|CTDB_REC_RO_REVOKE_COMPLETE);
+		CTDB_INCREMENT_STAT(ctdb, total_ro_revokes);
+		CTDB_INCREMENT_DB_STAT(ctdb_db, db_ro_revokes);
 		if (ctdb_ltdb_store(ctdb_db, call->key, &header, data) != 0) {
 			ctdb_fatal(ctdb, "Failed to write header with cleared REVOKE flag");
 		}
@@ -619,6 +621,8 @@ void ctdb_request_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
 		}
 
 		ctdb_queue_packet(ctdb, &r->hdr);
+		CTDB_INCREMENT_STAT(ctdb, total_ro_delegations);
+		CTDB_INCREMENT_DB_STAT(ctdb_db, db_ro_delegations);
 
 		talloc_free(r);
 		return;
diff --git a/server/ctdb_control.c b/server/ctdb_control.c
index 060f2c5..c734588 100644
--- a/server/ctdb_control.c
+++ b/server/ctdb_control.c
@@ -630,6 +630,10 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
 		CHECK_CONTROL_DATA_SIZE(size);
 		return ctdb_control_schedule_for_deletion(ctdb, indata);
 	}
+	case CTDB_CONTROL_GET_DB_STATISTICS:
+		CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
+		return ctdb_control_get_db_statistics(ctdb, *(uint32_t *)indata.dptr, outdata);
+
 	default:
 		DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode));
 		return -1;
diff --git a/server/ctdb_daemon.c b/server/ctdb_daemon.c
index 53f47d6..2436997 100644
--- a/server/ctdb_daemon.c
+++ b/server/ctdb_daemon.c
@@ -690,6 +690,8 @@ static void daemon_request_call_from_client(struct ctdb_client *client,
 
 	if (header.flags & CTDB_REC_RO_REVOKE_COMPLETE) {
 		header.flags &= ~(CTDB_REC_RO_HAVE_DELEGATIONS|CTDB_REC_RO_HAVE_READONLY|CTDB_REC_RO_REVOKING_READONLY|CTDB_REC_RO_REVOKE_COMPLETE);
+		CTDB_INCREMENT_STAT(ctdb, total_ro_revokes);
+		CTDB_INCREMENT_DB_STAT(ctdb_db, db_ro_revokes);
 		if (ctdb_ltdb_store(ctdb_db, key, &header, data) != 0) {
 			ctdb_fatal(ctdb, "Failed to write header with cleared REVOKE flag");
 		}
diff --git a/server/ctdb_ltdb_server.c b/server/ctdb_ltdb_server.c
index 9a0132a..e5437b9 100644
--- a/server/ctdb_ltdb_server.c
+++ b/server/ctdb_ltdb_server.c
@@ -1464,3 +1464,20 @@ int32_t ctdb_control_set_db_priority(struct ctdb_context *ctdb, TDB_DATA indata)
 	return 0;
 }
 
+int32_t ctdb_control_get_db_statistics(struct ctdb_context *ctdb,
+				uint32_t db_id,
+				TDB_DATA *outdata)
+{
+	struct ctdb_db_context *ctdb_db;
+
+	ctdb_db = find_ctdb_db(ctdb, db_id);
+	if (!ctdb_db) {
+		DEBUG(DEBUG_ERR,("Unknown db_id 0x%x in get_db_statistics\n", db_id));
+		return -1;
+	}
+
+	outdata->dptr  = (uint8_t *)&(ctdb_db->statistics);
+	outdata->dsize = sizeof(ctdb_db->statistics);
+
+	return 0;
+}
diff --git a/tests/src/libctdb_test.c b/tests/src/libctdb_test.c
index 73ba155..56c007e 100644
--- a/tests/src/libctdb_test.c
+++ b/tests/src/libctdb_test.c
@@ -487,3 +487,20 @@ void ctdb_disconnect(struct ctdb_connection *ctdb)
 	free(ctdb);
 }
 
+bool ctdb_getdbstat(struct ctdb_connection *ctdb,
+		    uint32_t destnode,
+		    uint32_t db_id,
+		    struct ctdb_db_statistics **dbstatistics)
+{
+	if (!current_node_is_connected(ctdb)) {
+		return false;
+	}
+
+	*dbstatistics = malloc(sizeof(struct ctdb_db_statistics));
+	return true;
+}
+
+void ctdb_free_dbstat(struct ctdb_db_statistics *dbstatistics)
+{
+	free(dbstatistics);
+}
diff --git a/tools/ctdb.c b/tools/ctdb.c
index e852ca2..051a270 100644
--- a/tools/ctdb.c
+++ b/tools/ctdb.c
@@ -343,6 +343,8 @@ static void show_statistics(struct ctdb_statistics *s, int show_header)
 		STATISTICS_FIELD(pending_childwrite_calls),
 		STATISTICS_FIELD(memory_used),
 		STATISTICS_FIELD(max_hop_count),
+		STATISTICS_FIELD(total_ro_delegations),
+		STATISTICS_FIELD(total_ro_revokes),
 	};
 	tmp = s->statistics_current_time.tv_sec - s->statistics_start_time.tv_sec;
 	seconds = tmp%60;
@@ -564,6 +566,55 @@ static int control_stats(struct ctdb_context *ctdb, int argc, const char **argv)
 
 
 /*
+  display remote ctdb db statistics
+ */
+static int control_dbstatistics(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+	TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
+	struct ctdb_db_statistics *dbstatistics;
+	struct ctdb_dbid_map *dbmap=NULL;
+	int i, ret;
+
+	if (argc < 1) {
+		usage();
+	}
+
+	ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
+	if (ret != 0) {
+		DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
+		return ret;
+	}
+	for(i=0;i<dbmap->num;i++){
+		const char *name;
+
+		ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
+		if(!strcmp(argv[0], name)){
+			talloc_free(discard_const(name));
+			break;
+		}
+		talloc_free(discard_const(name));
+	}
+	if (i == dbmap->num) {
+		DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
+		talloc_free(tmp_ctx);
+		return -1;
+	}
+
+	if (!ctdb_getdbstat(ctdb_connection, options.pnn, dbmap->dbs[i].dbid, &dbstatistics)) {
+		DEBUG(DEBUG_ERR,("Failed to read db statistics from node\n"));
+		talloc_free(tmp_ctx);
+		return -1;
+	}
+
+	printf("DB Statistics:\n");
+	printf("RO Delegations: %d\n", dbstatistics->db_ro_delegations);
+	printf("RO Revokes:     %d\n", dbstatistics->db_ro_revokes);
+
+	ctdb_free_dbstat(dbstatistics);
+	return 0;
+}
+
+/*
   display uptime of remote node
  */
 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
@@ -5432,6 +5483,7 @@ static const struct {
 	{ "checktcpport",    control_chktcpport,      	false,	true,  "check if a service is bound to a specific tcp port or not", "<port>" },
 	{ "getdbseqnum",     control_getdbseqnum,       false,	false, "get the sequence number off a database", "<dbid>" },
 	{ "nodestatus",      control_nodestatus,        true,   false,  "show and return node status" },
+	{ "dbstatistics",    control_dbstatistics,      false,	false, "show db statistics", "<db>" },
 };
 
 /*


-- 
CTDB repository


More information about the samba-cvs mailing list