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 <sys/socket.h>
21 #include "libctdb_private.h"
26 #include <ctdb_protocol.h>
31 /* Remove type-safety macros. */
32 #undef ctdb_set_message_handler_send
33 #undef ctdb_set_message_handler_recv
34 #undef ctdb_remove_message_handler_send
36 struct message_handler_info
{
37 struct message_handler_info
*next
, *prev
;
40 ctdb_message_fn_t handler
;
44 void deliver_message(struct ctdb_connection
*ctdb
, struct ctdb_req_header
*hdr
)
46 struct message_handler_info
*i
;
47 struct ctdb_req_message
*msg
= (struct ctdb_req_message
*)hdr
;
51 data
.dptr
= msg
->data
;
52 data
.dsize
= msg
->datalen
;
54 /* Note: we want to call *every* handler: there may be more than one */
55 for (i
= ctdb
->message_handlers
; i
; i
= i
->next
) {
56 if (i
->srvid
== msg
->srvid
) {
57 i
->handler(ctdb
, msg
->srvid
, data
, i
->handler_data
);
62 DEBUG(ctdb
, LOG_WARNING
,
63 "ctdb_service: messsage for unregistered srvid %llu",
64 (unsigned long long)msg
->srvid
);
68 void remove_message_handlers(struct ctdb_connection
*ctdb
)
70 struct message_handler_info
*i
;
72 /* ctdbd should unregister automatically when we close fd, so we don't
73 need to do that here. */
74 while ((i
= ctdb
->message_handlers
) != NULL
) {
75 DLIST_REMOVE(ctdb
->message_handlers
, i
);
80 static void free_info(struct ctdb_connection
*ctdb
, struct ctdb_request
*req
);
83 ctdb_set_message_handler_send(struct ctdb_connection
*ctdb
, uint64_t srvid
,
84 ctdb_message_fn_t handler
, void *handler_data
,
85 ctdb_callback_t callback
, void *private_data
)
87 struct message_handler_info
*info
;
88 struct ctdb_request
*req
;
90 info
= malloc(sizeof(*info
));
93 "ctdb_set_message_handler_send: allocating info");
97 req
= new_ctdb_control_request(ctdb
, CTDB_CONTROL_REGISTER_SRVID
,
98 CTDB_CURRENT_NODE
, NULL
, 0,
99 callback
, private_data
);
102 "ctdb_set_message_handler_send: allocating request");
107 req
->extra_destructor
= free_info
;
108 req
->hdr
.control
->srvid
= srvid
;
111 info
->handler
= handler
;
112 info
->handler_data
= handler_data
;
114 DEBUG(ctdb
, LOG_DEBUG
,
115 "ctdb_set_message_handler_send: sending request %u for id %llx",
116 req
->hdr
.hdr
->reqid
, (unsigned long long)srvid
);
120 static void free_info(struct ctdb_connection
*ctdb
, struct ctdb_request
*req
)
125 bool ctdb_set_message_handler_recv(struct ctdb_connection
*ctdb
,
126 struct ctdb_request
*req
)
128 struct message_handler_info
*info
= req
->extra
;
129 struct ctdb_reply_control
*reply
;
131 reply
= unpack_reply_control(req
, CTDB_CONTROL_REGISTER_SRVID
);
135 if (reply
->status
!= 0) {
137 "ctdb_set_message_handler_recv: status %i",
142 /* Put ourselves in list of handlers. */
143 DLIST_ADD(ctdb
->message_handlers
, info
);
144 /* Keep safe from destructor */
149 struct ctdb_request
*
150 ctdb_remove_message_handler_send(struct ctdb_connection
*ctdb
, uint64_t srvid
,
151 ctdb_message_fn_t handler
, void *hdata
,
152 ctdb_callback_t callback
, void *cbdata
)
154 struct message_handler_info
*i
;
155 struct ctdb_request
*req
;
157 for (i
= ctdb
->message_handlers
; i
; i
= i
->next
) {
158 if (i
->srvid
== srvid
159 && i
->handler
== handler
&& i
->handler_data
== hdata
) {
164 DEBUG(ctdb
, LOG_ALERT
,
165 "ctdb_remove_message_handler_send: no such handler");
170 req
= new_ctdb_control_request(ctdb
, CTDB_CONTROL_DEREGISTER_SRVID
,
171 CTDB_CURRENT_NODE
, NULL
, 0,
175 "ctdb_remove_message_handler_send: allocating request");
178 req
->hdr
.control
->srvid
= srvid
;
181 DEBUG(ctdb
, LOG_DEBUG
,
182 "ctdb_set_remove_handler_send: sending request %u for id %llu",
183 req
->hdr
.hdr
->reqid
, (unsigned long long)srvid
);
187 bool ctdb_remove_message_handler_recv(struct ctdb_connection
*ctdb
,
188 struct ctdb_request
*req
)
190 struct message_handler_info
*handler
= req
->extra
;
191 struct ctdb_reply_control
*reply
;
193 reply
= unpack_reply_control(req
, CTDB_CONTROL_DEREGISTER_SRVID
);
197 if (reply
->status
!= 0) {
199 "ctdb_remove_message_handler_recv: status %i",
204 /* Remove ourselves from list of handlers. */
205 DLIST_REMOVE(ctdb
->message_handlers
, handler
);
207 /* Crash if they call this again! */
212 bool ctdb_send_message(struct ctdb_connection
*ctdb
,
213 uint32_t pnn
, uint64_t srvid
,
216 struct ctdb_request
*req
;
217 struct ctdb_req_message
*pkt
;
219 /* We just discard it once it's finished: no reply. */
220 req
= new_ctdb_request(
221 ctdb
, offsetof(struct ctdb_req_message
, data
) + data
.dsize
,
222 ctdb_cancel_callback
, NULL
);
224 DEBUG(ctdb
, LOG_ERR
, "ctdb_set_message: allocating message");
228 io_elem_init_req_header(req
->io
,
229 CTDB_REQ_MESSAGE
, pnn
, new_reqid(ctdb
));
231 pkt
= req
->hdr
.message
;
233 pkt
->datalen
= data
.dsize
;
234 memcpy(pkt
->data
, data
.dptr
, data
.dsize
);
235 DLIST_ADD_END(ctdb
->outq
, req
, struct ctdb_request
);