1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00
samba-mirror/ctdb/libctdb/messages.c
Volker Lendecke 85bc1ccb7e libctdb: "unpack_reply_control" does not need the ctdb_connection parameter
Signed-off-by: Michael Adam <obnox@samba.org>

(This used to be ctdb commit bb8f68f0256c43fe0671fe45023d1c88e340ad96)
2011-08-22 17:11:07 +02:00

237 lines
6.2 KiB
C

/*
core of libctdb
Copyright (C) Rusty Russell 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "libctdb_private.h"
#include "messages.h"
#include "io_elem.h"
#include <ctdb.h>
#include <tdb.h>
#include <ctdb_protocol.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* Remove type-safety macros. */
#undef ctdb_set_message_handler_send
#undef ctdb_set_message_handler_recv
#undef ctdb_remove_message_handler_send
struct message_handler_info {
struct message_handler_info *next, *prev;
uint64_t srvid;
ctdb_message_fn_t handler;
void *handler_data;
};
void deliver_message(struct ctdb_connection *ctdb, struct ctdb_req_header *hdr)
{
struct message_handler_info *i;
struct ctdb_req_message *msg = (struct ctdb_req_message *)hdr;
TDB_DATA data;
bool found;
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->handler_data);
found = true;
}
}
if (!found) {
DEBUG(ctdb, LOG_WARNING,
"ctdb_service: messsage for unregistered srvid %llu",
(unsigned long long)msg->srvid);
}
}
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);
}
}
static void free_info(struct ctdb_connection *ctdb, struct ctdb_request *req);
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 *private_data)
{
struct message_handler_info *info;
struct ctdb_request *req;
info = malloc(sizeof(*info));
if (!info) {
DEBUG(ctdb, LOG_ERR,
"ctdb_set_message_handler_send: allocating info");
return NULL;
}
req = new_ctdb_control_request(ctdb, CTDB_CONTROL_REGISTER_SRVID,
CTDB_CURRENT_NODE, NULL, 0,
callback, private_data);
if (!req) {
DEBUG(ctdb, LOG_ERR,
"ctdb_set_message_handler_send: allocating request");
free(info);
return NULL;
}
req->extra = info;
req->extra_destructor = free_info;
req->hdr.control->srvid = srvid;
info->srvid = srvid;
info->handler = handler;
info->handler_data = handler_data;
DEBUG(ctdb, LOG_DEBUG,
"ctdb_set_message_handler_send: sending request %u for id %llx",
req->hdr.hdr->reqid, (unsigned long long)srvid);
return req;
}
static void free_info(struct ctdb_connection *ctdb, struct ctdb_request *req)
{
free(req->extra);
}
bool ctdb_set_message_handler_recv(struct ctdb_connection *ctdb,
struct ctdb_request *req)
{
struct message_handler_info *info = req->extra;
struct ctdb_reply_control *reply;
reply = unpack_reply_control(req, CTDB_CONTROL_REGISTER_SRVID);
if (!reply) {
return false;
}
if (reply->status != 0) {
DEBUG(ctdb, LOG_ERR,
"ctdb_set_message_handler_recv: status %i",
reply->status);
return false;
}
/* Put ourselves in list of handlers. */
DLIST_ADD(ctdb->message_handlers, info);
/* Keep safe from destructor */
req->extra = NULL;
return true;
}
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, (unsigned long long)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(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)
{
struct ctdb_request *req;
struct ctdb_req_message *pkt;
/* We just discard it once it's finished: no reply. */
req = new_ctdb_request(
ctdb, offsetof(struct ctdb_req_message, data) + data.dsize,
ctdb_cancel_callback, NULL);
if (!req) {
DEBUG(ctdb, LOG_ERR, "ctdb_set_message: allocating message");
return false;
}
io_elem_init_req_header(req->io,
CTDB_REQ_MESSAGE, pnn, new_reqid(ctdb));
pkt = req->hdr.message;
pkt->srvid = srvid;
pkt->datalen = data.dsize;
memcpy(pkt->data, data.dptr, data.dsize);
DLIST_ADD_END(ctdb->outq, req, struct ctdb_request);
return true;
}