1 #include "libctdb_private.h"
6 #include <ctdb_protocol.h>
11 /* Remove type-safety macros. */
12 #undef ctdb_set_message_handler_send
13 #undef ctdb_set_message_handler_recv
14 #undef ctdb_remove_message_handler_send
16 struct message_handler_info {
17 struct message_handler_info *next, *prev;
20 ctdb_message_fn_t handler;
24 void deliver_message(struct ctdb_connection *ctdb, struct ctdb_req_header *hdr)
26 struct message_handler_info *i;
27 struct ctdb_req_message *msg = (struct ctdb_req_message *)hdr;
31 data.dptr = msg->data;
32 data.dsize = msg->datalen;
34 /* Note: we want to call *every* handler: there may be more than one */
35 for (i = ctdb->message_handlers; i; i = i->next) {
36 if (i->srvid == msg->srvid) {
37 i->handler(ctdb, msg->srvid, data, i->handler_data);
42 DEBUG(ctdb, LOG_WARNING,
43 "ctdb_service: messsage for unregistered srvid %llu",
48 void remove_message_handlers(struct ctdb_connection *ctdb)
50 struct message_handler_info *i;
52 /* ctdbd should unregister automatically when we close fd, so we don't
53 need to do that here. */
54 while ((i = ctdb->message_handlers) != NULL) {
55 DLIST_REMOVE(ctdb->message_handlers, i);
60 bool ctdb_set_message_handler_recv(struct ctdb_connection *ctdb,
61 struct ctdb_request *req)
63 struct message_handler_info *info = req->extra;
64 struct ctdb_reply_control *reply;
66 reply = unpack_reply_control(ctdb, req, CTDB_CONTROL_REGISTER_SRVID);
70 if (reply->status != 0) {
72 "ctdb_set_message_handler_recv: status %i",
77 /* Put ourselves in list of handlers. */
78 DLIST_ADD(ctdb->message_handlers, info);
79 /* Keep safe from destructor */
84 static void free_info(struct ctdb_connection *ctdb, struct ctdb_request *req)
90 ctdb_set_message_handler_send(struct ctdb_connection *ctdb, uint64_t srvid,
91 ctdb_message_fn_t handler, void *handler_data,
92 ctdb_callback_t callback, void *private_data)
94 struct message_handler_info *info;
95 struct ctdb_request *req;
97 info = malloc(sizeof(*info));
100 "ctdb_set_message_handler_send: allocating info");
104 req = new_ctdb_control_request(ctdb, CTDB_CONTROL_REGISTER_SRVID,
105 CTDB_CURRENT_NODE, NULL, 0,
106 callback, private_data);
109 "ctdb_set_message_handler_send: allocating request");
114 req->extra_destructor = free_info;
115 req->hdr.control->srvid = srvid;
118 info->handler = handler;
119 info->handler_data = handler_data;
121 DEBUG(ctdb, LOG_DEBUG,
122 "ctdb_set_message_handler_send: sending request %u for id %llx",
123 req->hdr.hdr->reqid, srvid);
127 struct ctdb_request *
128 ctdb_remove_message_handler_send(struct ctdb_connection *ctdb, uint64_t srvid,
129 ctdb_message_fn_t handler, void *hdata,
130 ctdb_callback_t callback, void *cbdata)
132 struct message_handler_info *i;
133 struct ctdb_request *req;
135 for (i = ctdb->message_handlers; i; i = i->next) {
136 if (i->srvid == srvid
137 && i->handler == handler && i->handler_data == hdata) {
142 DEBUG(ctdb, LOG_ALERT,
143 "ctdb_remove_message_handler_send: no such handler");
148 req = new_ctdb_control_request(ctdb, CTDB_CONTROL_DEREGISTER_SRVID,
149 CTDB_CURRENT_NODE, NULL, 0,
153 "ctdb_remove_message_handler_send: allocating request");
156 req->hdr.control->srvid = srvid;
159 DEBUG(ctdb, LOG_DEBUG,
160 "ctdb_set_remove_handler_send: sending request %u for id %llu",
161 req->hdr.hdr->reqid, srvid);
165 bool ctdb_remove_message_handler_recv(struct ctdb_connection *ctdb,
166 struct ctdb_request *req)
168 struct message_handler_info *handler = req->extra;
169 struct ctdb_reply_control *reply;
171 reply = unpack_reply_control(ctdb, req, CTDB_CONTROL_DEREGISTER_SRVID);
175 if (reply->status != 0) {
177 "ctdb_remove_message_handler_recv: status %i",
182 /* Remove ourselves from list of handlers. */
183 DLIST_REMOVE(ctdb->message_handlers, handler);
185 /* Crash if they call this again! */
190 bool ctdb_send_message(struct ctdb_connection *ctdb,
191 uint32_t pnn, uint64_t srvid,
194 struct ctdb_request *req;
195 struct ctdb_req_message *pkt;
197 /* We just discard it once it's finished: no reply. */
198 req = new_ctdb_request(offsetof(struct ctdb_req_message, data) + data.dsize,
199 ctdb_cancel_callback, NULL);
201 DEBUG(ctdb, LOG_ERR, "ctdb_set_message: allocating message");
205 io_elem_init_req_header(req->io,
206 CTDB_REQ_MESSAGE, pnn, new_reqid(ctdb));
208 pkt = req->hdr.message;
210 pkt->datalen = data.dsize;
211 memcpy(pkt->data, data.dptr, data.dsize);
212 DLIST_ADD_END(ctdb->outq, req, struct ctdb_request);