* @ctdb: the ctdb_connection from ctdb_connect.
* @srvid: the 64 bit identifier for our messages.
* @handler: the callback when we receive such a message (typesafe)
+ * @handler_data: the argument to handler()
* @callback: the callback when ctdb replies to our message (typesafe)
- * @cbdata: the argument to callback() and handler()
+ * @cbdata: the argument to callback()
*
* Note: our callback will always be called before handler.
*
struct ctdb_request *
ctdb_set_message_handler_send(struct ctdb_connection *ctdb, uint64_t srvid,
ctdb_message_fn_t handler,
+ void *handler_data,
ctdb_callback_t callback,
void *cbdata);
* ctdb_remove_message_handler_send - unregister for messages to a srvid
* @ctdb: the ctdb_connection from ctdb_connect.
* @srvid: the 64 bit identifier for our messages.
+ * @handler: the callback when we receive such a message (typesafe)
+ * @handler_data: the argument to handler()
* @callback: the callback when ctdb replies to our message (typesafe)
* @cbdata: the argument to callback()
*
*/
struct ctdb_request *
ctdb_remove_message_handler_send(struct ctdb_connection *ctdb, uint64_t srvid,
+ ctdb_message_fn_t handler, void *handler_data,
ctdb_callback_t callback, void *cbdata);
/**
* After this returns true, the registered handler will no longer be called.
* If this returns false, the de-registration failed.
*/
-bool ctdb_remove_message_handler_recv(struct ctdb_request *handle);
+bool ctdb_remove_message_handler_recv(struct ctdb_connection *ctdb,
+ struct ctdb_request *req);
/**
* failed.
*/
bool ctdb_set_message_handler(struct ctdb_connection *ctdb, uint64_t srvid,
- ctdb_message_fn_t handler, void *cbdata);
+ ctdb_message_fn_t handler, void *cbdata);
/**
* ctdb_remove_message_handler - deregister for messages (synchronous)
* @ctdb: the ctdb_connection from ctdb_connect.
* @srvid: the 64 bit identifier for our messages.
+ * @handler: the callback when we receive such a message (typesafe)
+ * @handler_data: the argument to handler()
*
* If this returns true, the message handler will no longer be called.
* If this returns false, the deregistration failed.
*/
-bool ctdb_remove_message_handler(struct ctdb_connection *ctdb, uint64_t srvid);
+bool ctdb_remove_message_handler(struct ctdb_connection *ctdb, uint64_t srvid,
+ ctdb_message_fn_t handler, void *handler_data);
/**
* ctdb_getpnn - read the pnn number of a node (synchronous)
typesafe_cb_preargs(void, (cb), (cbdata), \
struct ctdb_connection *, struct ctdb_request *)
+#define ctdb_msgcb(cb, cbdata) \
+ typesafe_cb_preargs(void, (cb), (cbdata), \
+ struct ctdb_connection *, uint64_t, TDB_DATA)
+
#define ctdb_connect(addr, log, logpriv) \
ctdb_connect((addr), \
typesafe_cb_postargs(void, (log), (logpriv), \
int, const char *, va_list), \
(logpriv))
+#define ctdb_set_message_handler(ctdb, srvid, handler, hdata) \
+ ctdb_set_message_handler((ctdb), (srvid), \
+ ctdb_msgcb((handler), (hdata)), (hdata))
+
+#define ctdb_remove_message_handler(ctdb, srvid, handler, hdata) \
+ ctdb_remove_message_handler((ctdb), (srvid), \
+ ctdb_msgcb((handler), (hdata)), (hdata))
#define ctdb_attachdb_send(ctdb, name, persistent, tdb_flags, cb, cbdata) \
ctdb_attachdb_send((ctdb), (name), (persistent), (tdb_flags), \
struct ctdb_db *, struct ctdb_lock *, \
TDB_DATA), (cbdata))
-#define ctdb_set_message_handler_send(ctdb, srvid, handler, cb, cbdata) \
- ctdb_set_message_handler_send((ctdb), (srvid), (handler), \
- ctdb_sendcb((cb), (cbdata)), (cbdata))
+#define ctdb_set_message_handler_send(ctdb, srvid, handler, hdata, cb, cbdata) \
+ ctdb_set_message_handler_send((ctdb), (srvid), \
+ ctdb_msgcb((handler), (hdata)), (hdata), \
+ ctdb_sendcb((cb), (cbdata)), (cbdata))
-#define ctdb_remove_message_handler_send(ctdb, srvid, cb, cbdata) \
+#define ctdb_remove_message_handler_send(ctdb, srvid, handler, hdata, cb, cbdata) \
ctdb_remove_message_handler_send((ctdb), (srvid), \
+ ctdb_msgcb((handler), (hdata)), (hdata), \
ctdb_sendcb((cb), (cbdata)), (cbdata))
#define ctdb_getpnn_send(ctdb, destnode, cb, cbdata) \
#include <ctdb_protocol.h>
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
/* Remove type-safety macros. */
#undef ctdb_set_message_handler_send
uint64_t srvid;
ctdb_message_fn_t handler;
- void *private_data;
+ void *handler_data;
};
void deliver_message(struct ctdb_connection *ctdb, struct ctdb_req_header *hdr)
data.dptr = msg->data;
data.dsize = msg->datalen;
+ /* Note: we want to call *every* handler: there may be more than one */
for (i = ctdb->message_handlers; i; i = i->next) {
if (i->srvid == msg->srvid) {
- i->handler(ctdb, msg->srvid, data, i->private_data);
+ i->handler(ctdb, msg->srvid, data, i->handler_data);
found = true;
}
}
struct ctdb_request *
ctdb_set_message_handler_send(struct ctdb_connection *ctdb, uint64_t srvid,
- ctdb_message_fn_t handler,
+ ctdb_message_fn_t handler, void *handler_data,
ctdb_callback_t callback, void *private_data)
{
struct message_handler_info *info;
info->srvid = srvid;
info->handler = handler;
- info->private_data = private_data;
+ info->handler_data = handler_data;
DEBUG(ctdb, LOG_DEBUG,
"ctdb_set_message_handler_send: sending request %u for id %llu",
return req;
}
+struct ctdb_request *
+ctdb_remove_message_handler_send(struct ctdb_connection *ctdb, uint64_t srvid,
+ ctdb_message_fn_t handler, void *hdata,
+ ctdb_callback_t callback, void *cbdata)
+{
+ struct message_handler_info *i;
+ struct ctdb_request *req;
+
+ for (i = ctdb->message_handlers; i; i = i->next) {
+ if (i->srvid == srvid
+ && i->handler == handler && i->handler_data == hdata) {
+ break;
+ }
+ }
+ if (!i) {
+ DEBUG(ctdb, LOG_ALERT,
+ "ctdb_remove_message_handler_send: no such handler");
+ errno = ENOENT;
+ return NULL;
+ }
+
+ req = new_ctdb_control_request(ctdb, CTDB_CONTROL_DEREGISTER_SRVID,
+ CTDB_CURRENT_NODE, NULL, 0,
+ callback, cbdata);
+ if (!req) {
+ DEBUG(ctdb, LOG_ERR,
+ "ctdb_remove_message_handler_send: allocating request");
+ return NULL;
+ }
+ req->hdr.control->srvid = srvid;
+ req->extra = i;
+
+ DEBUG(ctdb, LOG_DEBUG,
+ "ctdb_set_remove_handler_send: sending request %u for id %llu",
+ req->hdr.hdr->reqid, srvid);
+ return req;
+}
+
+bool ctdb_remove_message_handler_recv(struct ctdb_connection *ctdb,
+ struct ctdb_request *req)
+{
+ struct message_handler_info *handler = req->extra;
+ struct ctdb_reply_control *reply;
+
+ reply = unpack_reply_control(ctdb, req, CTDB_CONTROL_DEREGISTER_SRVID);
+ if (!reply) {
+ return false;
+ }
+ if (reply->status != 0) {
+ DEBUG(ctdb, LOG_ERR,
+ "ctdb_remove_message_handler_recv: status %i",
+ reply->status);
+ return false;
+ }
+
+ /* Remove ourselves from list of handlers. */
+ DLIST_REMOVE(ctdb->message_handlers, handler);
+ free(handler);
+ /* Crash if they call this again! */
+ req->extra = NULL;
+ return true;
+}
+
bool ctdb_send_message(struct ctdb_connection *ctdb,
uint32_t pnn, uint64_t srvid,
TDB_DATA data)