libctdb: implement ctdb_disconnect and ctdb_detachdb
authorRusty Russell <rusty@rustcorp.com.au>
Fri, 18 Jun 2010 06:05:52 +0000 (15:35 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 18 Jun 2010 06:05:52 +0000 (15:35 +0930)
These are important for testing, since we can easily tell if we
leak memory if there are outstanding allocations after calling
these.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
include/ctdb.h
libctdb/ctdb.c
libctdb/messages.c
libctdb/messages.h

index e4aff86723717d17c46d8ee18509f805527b2b80..a9ee63ff25a6489532600d21542cb81071ff21da 100644 (file)
@@ -72,7 +72,7 @@ typedef void (*ctdb_log_fn_t)(void *log_priv,
  * @log: the logging function
  * @log_priv: the private argument to the logging function.
  *
- * Returns a ctdb context if successful or NULL.  Use ctdb_free() to
+ * Returns a ctdb context if successful or NULL.  Use ctdb_disconnect() to
  * release the returned ctdb_connection when finished.
  *
  * See Also:
@@ -100,6 +100,14 @@ void ctdb_log_file(FILE *, int, const char *, va_list);
  */
 extern int ctdb_log_level;
 
+/**
+ * ctdb_disconnect - close down a connection to ctdbd.
+ * @ctdb: the ctdb connectio returned from ctdb_connect.
+ *
+ * The @ctdb arg will be freed by this call, and must not be used again.
+ */
+void ctdb_disconnect(struct ctdb_connection *ctdb);
+
 /***
  *
  *  Asynchronous API
@@ -185,7 +193,7 @@ typedef void (*ctdb_callback_t)(struct ctdb_connection *ctdb,
  * This represents a particular open database: you receive it from
  * ctdb_attachdb or ctdb_attachdb_recv to manipulate a database.
  *
- * You have to free the handle with ctdb_detach_db() when finished with it.
+ * You have to free the handle with ctdb_detachdb() when finished with it.
  */
 struct ctdb_db;
 
@@ -456,6 +464,15 @@ struct ctdb_db *ctdb_attachdb(struct ctdb_connection *ctdb,
                              const char *name, bool persistent,
                              uint32_t tdb_flags);
 
+/**
+ * ctdb_detachdb - close a clustered TDB.
+ * @ctdb: the ctdb_connection from ctdb_connect.
+ * @db: the database from ctdb_attachdb/ctdb_attachdb_send
+ *
+ * Closes a clustered tdb.
+ */
+void ctdb_detachdb(struct ctdb_connection *ctdb, struct ctdb_db *db);
+
 /**
  * ctdb_readrecordlock - read and lock a record (synchronous)
  * @ctdb_db: the database handle from ctdb_attachdb/ctdb_attachdb_recv.
index 1c16d36a7c18e2acbbcd3059014dbca3ab9413b2..096a9264f0a4e012bf46e53853732281dbe1b027 100644 (file)
@@ -50,6 +50,17 @@ struct ctdb_lock {
        ctdb_rrl_callback_t callback;
 };
 
+struct ctdb_db {
+       struct ctdb_connection *ctdb;
+       bool persistent;
+       uint32_t tdb_flags;
+       uint32_t id;
+       struct tdb_context *tdb;
+
+       ctdb_callback_t callback;
+       void *private_data;
+};
+
 static void remove_lock(struct ctdb_connection *ctdb, struct ctdb_lock *lock)
 {
        DLIST_REMOVE(ctdb->locks, lock);
@@ -67,6 +78,19 @@ static void add_lock(struct ctdb_connection *ctdb, struct ctdb_lock *lock)
        DLIST_ADD(ctdb->locks, lock);
 }
 
+static void cleanup_locks(struct ctdb_connection *ctdb, struct ctdb_db *db)
+{
+       struct ctdb_lock *i, *next;
+
+       for (i = ctdb->locks; i; i = next) {
+               /* Grab next pointer, as release_lock will free i */
+               next = i->next;
+               if (i->ctdb_db == db) {
+                       ctdb_release_lock(db, i);
+               }
+       }
+}
+
 /* FIXME: Could be in shared util code with rest of ctdb */
 static void close_noerr(int fd)
 {
@@ -165,6 +189,33 @@ fail:
        return NULL;
 }
 
+void ctdb_disconnect(struct ctdb_connection *ctdb)
+{
+       struct ctdb_request *i;
+
+       DEBUG(ctdb, LOG_DEBUG, "ctdb_disconnect");
+
+       while ((i = ctdb->outq) != NULL) {
+               DLIST_REMOVE(ctdb->outq, i);
+               ctdb_request_free(ctdb, i);
+       }
+
+       while ((i = ctdb->doneq) != NULL) {
+               DLIST_REMOVE(ctdb->doneq, i);
+               ctdb_request_free(ctdb, i);
+       }
+
+       if (ctdb->in)
+               free_io_elem(ctdb->in);
+
+       remove_message_handlers(ctdb);
+
+       close(ctdb->fd);
+       /* Just in case they try to reuse */
+       ctdb->fd = -1;
+       free(ctdb);
+}
+
 int ctdb_get_fd(struct ctdb_connection *ctdb)
 {
        return ctdb->fd;
@@ -478,16 +529,12 @@ void ctdb_cancel(struct ctdb_connection *ctdb, struct ctdb_request *req)
        req->callback = ctdb_cancel_callback;
 }
 
-struct ctdb_db {
-       struct ctdb_connection *ctdb;
-       bool persistent;
-       uint32_t tdb_flags;
-       uint32_t id;
-       struct tdb_context *tdb;
-
-       ctdb_callback_t callback;
-       void *private_data;
-};
+void ctdb_detachdb(struct ctdb_connection *ctdb, struct ctdb_db *db)
+{
+       cleanup_locks(ctdb, db);
+       tdb_close(db->tdb);
+       free(db);
+}
 
 static void attachdb_getdbpath_done(struct ctdb_connection *ctdb,
                                    struct ctdb_request *req,
index bab0e8c4cbdf56d103cc9c2633937c6bd5c2e468..7ad48d5dc834542fb6ce3edec2095057dbd229e6 100644 (file)
@@ -43,6 +43,18 @@ void deliver_message(struct ctdb_connection *ctdb, struct ctdb_req_header *hdr)
        }
 }
 
+void remove_message_handlers(struct ctdb_connection *ctdb)
+{
+       struct message_handler_info *i;
+
+       /* ctdbd should unregister automatically when we close fd, so we don't
+          need to do that here. */
+       while ((i = ctdb->message_handlers) != NULL) {
+               DLIST_REMOVE(ctdb->message_handlers, i);
+               free(i);
+       }
+}
+
 bool ctdb_set_message_handler_recv(struct ctdb_connection *ctdb,
                                   struct ctdb_request *req)
 {
index dcf19c8b6ca6b689bd1bcb1b71be996cd2a8897a..89a04608eca7bba9207eead4abb05ece2a6435e7 100644 (file)
@@ -5,4 +5,5 @@ struct ctdb_connection;
 struct ctdb_req_header;
 
 void deliver_message(struct ctdb_connection *ctdb, struct ctdb_req_header *hdr);
+void remove_message_handlers(struct ctdb_connection *ctdb);
 #endif /* _LIBCTDB_MESSAGE_H */