4 Copyright (C) Rusty Russell 2010
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "libctdb_private.h"
25 #include <ctdb_protocol.h>
30 /* Remove type-safety macros. */
31 #undef ctdb_set_message_handler_send
32 #undef ctdb_set_message_handler_recv
33 #undef ctdb_remove_message_handler_send
35 struct message_handler_info {
36 struct message_handler_info *next, *prev;
39 ctdb_message_fn_t handler;
43 void deliver_message(struct ctdb_connection *ctdb, struct ctdb_req_header *hdr)
45 struct message_handler_info *i;
46 struct ctdb_req_message *msg = (struct ctdb_req_message *)hdr;
50 data.dptr = msg->data;
51 data.dsize = msg->datalen;
53 /* Note: we want to call *every* handler: there may be more than one */
54 for (i = ctdb->message_handlers; i; i = i->next) {
55 if (i->srvid == msg->srvid) {
56 i->handler(ctdb, msg->srvid, data, i->handler_data);
61 DEBUG(ctdb, LOG_WARNING,
62 "ctdb_service: messsage for unregistered srvid %llu",
63 (unsigned long long)msg->srvid);
67 void remove_message_handlers(struct ctdb_connection *ctdb)
69 struct message_handler_info *i;
71 /* ctdbd should unregister automatically when we close fd, so we don't
72 need to do that here. */
73 while ((i = ctdb->message_handlers) != NULL) {
74 DLIST_REMOVE(ctdb->message_handlers, i);
79 static void free_info(struct ctdb_connection *ctdb, struct ctdb_request *req);
82 ctdb_set_message_handler_send(struct ctdb_connection *ctdb, uint64_t srvid,
83 ctdb_message_fn_t handler, void *handler_data,
84 ctdb_callback_t callback, void *private_data)
86 struct message_handler_info *info;
87 struct ctdb_request *req;
89 info = malloc(sizeof(*info));
92 "ctdb_set_message_handler_send: allocating info");
96 req = new_ctdb_control_request(ctdb, CTDB_CONTROL_REGISTER_SRVID,
97 CTDB_CURRENT_NODE, NULL, 0,
98 callback, private_data);
101 "ctdb_set_message_handler_send: allocating request");
106 req->extra_destructor = free_info;
107 req->hdr.control->srvid = srvid;
110 info->handler = handler;
111 info->handler_data = handler_data;
113 DEBUG(ctdb, LOG_DEBUG,
114 "ctdb_set_message_handler_send: sending request %u for id %llx",
115 req->hdr.hdr->reqid, (unsigned long long)srvid);
119 static void free_info(struct ctdb_connection *ctdb, struct ctdb_request *req)
124 bool ctdb_set_message_handler_recv(struct ctdb_connection *ctdb,
125 struct ctdb_request *req)
127 struct message_handler_info *info = req->extra;
128 struct ctdb_reply_control *reply;
130 reply = unpack_reply_control(req, CTDB_CONTROL_REGISTER_SRVID);
134 if (reply->status != 0) {
136 "ctdb_set_message_handler_recv: status %i",
141 /* Put ourselves in list of handlers. */
142 DLIST_ADD(ctdb->message_handlers, info);
143 /* Keep safe from destructor */
148 struct ctdb_request *
149 ctdb_remove_message_handler_send(struct ctdb_connection *ctdb, uint64_t srvid,
150 ctdb_message_fn_t handler, void *hdata,
151 ctdb_callback_t callback, void *cbdata)
153 struct message_handler_info *i;
154 struct ctdb_request *req;
156 for (i = ctdb->message_handlers; i; i = i->next) {
157 if (i->srvid == srvid
158 && i->handler == handler && i->handler_data == hdata) {
163 DEBUG(ctdb, LOG_ALERT,
164 "ctdb_remove_message_handler_send: no such handler");
169 req = new_ctdb_control_request(ctdb, CTDB_CONTROL_DEREGISTER_SRVID,
170 CTDB_CURRENT_NODE, NULL, 0,
174 "ctdb_remove_message_handler_send: allocating request");
177 req->hdr.control->srvid = srvid;
180 DEBUG(ctdb, LOG_DEBUG,
181 "ctdb_set_remove_handler_send: sending request %u for id %llu",
182 req->hdr.hdr->reqid, (unsigned long long)srvid);
186 bool ctdb_remove_message_handler_recv(struct ctdb_connection *ctdb,
187 struct ctdb_request *req)
189 struct message_handler_info *handler = req->extra;
190 struct ctdb_reply_control *reply;
192 reply = unpack_reply_control(req, CTDB_CONTROL_DEREGISTER_SRVID);
196 if (reply->status != 0) {
198 "ctdb_remove_message_handler_recv: status %i",
203 /* Remove ourselves from list of handlers. */
204 DLIST_REMOVE(ctdb->message_handlers, handler);
206 /* Crash if they call this again! */
211 bool ctdb_send_message(struct ctdb_connection *ctdb,
212 uint32_t pnn, uint64_t srvid,
215 struct ctdb_request *req;
216 struct ctdb_req_message *pkt;
218 /* We just discard it once it's finished: no reply. */
219 req = new_ctdb_request(
220 ctdb, offsetof(struct ctdb_req_message, data) + data.dsize,
221 ctdb_cancel_callback, NULL);
223 DEBUG(ctdb, LOG_ERR, "ctdb_set_message: allocating message");
227 io_elem_init_req_header(req->io,
228 CTDB_REQ_MESSAGE, pnn, new_reqid(ctdb));
230 pkt = req->hdr.message;
232 pkt->datalen = data.dsize;
233 memcpy(pkt->data, data.dptr, data.dsize);
234 DLIST_ADD_END(ctdb->outq, req, struct ctdb_request);