* @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:
*/
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
* 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;
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.
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);
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)
{
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;
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,
}
}
+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)
{