From 3727165f0d206999d2cfc2800ff8868640868c7c Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 24 May 2010 13:52:17 +0930 Subject: [PATCH] libctdb: tweak interface for readrecordlock Previously we could hang in poll with the callback pending (since we fake it): explicitly call it immediately. Note: I experienced corruption using DLIST_ADD_END (ctdb->pnn was blatted when adding to the message_handler list). I switched them all to DLIST_ADD, but maybe I'm using it wrong? --- include/ctdb.h | 11 ++++++++--- libctdb/ctdb.c | 33 +++++++++++++++------------------ libctdb/libctdb_private.h | 2 -- libctdb/messages.c | 3 +-- libctdb/tst.c | 9 +++++---- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/include/ctdb.h b/include/ctdb.h index 9aabc4e2..bd4fdc12 100644 --- a/include/ctdb.h +++ b/include/ctdb.h @@ -22,6 +22,7 @@ #define _CTDB_H #include #include +#include #include /* All *_send() functions are guaranteed to be non-blocking and fully @@ -97,9 +98,13 @@ struct ctdb_lock; * * When the lock is released, data is freed too, so make sure to copy the data * before that. + * + * This returns true on success, and req will be non-NULL if a request was + * actually sent, otherwise callback will have already been called. */ -struct ctdb_request * +bool ctdb_readrecordlock_send(struct ctdb_db *ctdb_db, TDB_DATA key, + struct ctdb_request **req, ctdb_callback_t callback, void *private_data); struct ctdb_lock *ctdb_readrecordlock_recv(struct ctdb_db *ctdb_db, struct ctdb_request *handle, @@ -215,8 +220,8 @@ int ctdb_cancel(struct ctdb_request *); ctdb_attachdb_send((ctdb), (name), (persistent), (tdb_flags), \ ctdb_sendcb((cb), (cbdata)), (cbdata)) -#define ctdb_readrecordlock_send(ctdb_db, key, cb, cbdata) \ - ctdb_readrecordlock_send((ctdb_db), (key), \ +#define ctdb_readrecordlock_send(ctdb_db, key, reqp, cb, cbdata) \ + ctdb_readrecordlock_send((ctdb_db), (key), (reqp), \ ctdb_sendcb((cb), (cbdata)), (cbdata)) #define ctdb_set_message_handler_send(ctdb, srvid, handler, cb, cbdata) \ diff --git a/libctdb/ctdb.c b/libctdb/ctdb.c index 5461d3c1..c9adfdaa 100644 --- a/libctdb/ctdb.c +++ b/libctdb/ctdb.c @@ -87,9 +87,10 @@ struct ctdb_connection *ctdb_connect(const char *addr) goto fail; ctdb->outq = NULL; ctdb->doneq = NULL; - ctdb->immediateq = NULL; ctdb->in = NULL; ctdb->message_handlers = NULL; + ctdb->next_id = 0; + ctdb->broken = false; memset(&sun, 0, sizeof(sun)); sun.sun_family = AF_UNIX; @@ -270,8 +271,9 @@ int ctdb_service(struct ctdb_connection *ctdb, int revents) if (io_elem_finished(ctdb->outq->io)) { struct ctdb_request *done = ctdb->outq; DLIST_REMOVE(ctdb->outq, done); - DLIST_ADD_END(ctdb->doneq, done, - struct ctdb_request); + /* We add at the head: any dead ones + * sit and end. */ + DLIST_ADD(ctdb->doneq, done); } } } @@ -303,12 +305,6 @@ int ctdb_service(struct ctdb_connection *ctdb, int revents) } } - while (ctdb->immediateq) { - struct ctdb_request *imm = ctdb->immediateq; - imm->callback(ctdb, imm, imm->priv_data); - DLIST_REMOVE(ctdb->immediateq, imm); - } - return 0; } @@ -363,7 +359,7 @@ struct ctdb_request *new_ctdb_control_request(struct ctdb_connection *ctdb, pkt->flags = 0; pkt->datalen = extra; memcpy(pkt->data, extra_data, extra); - DLIST_ADD_END(ctdb->outq, req, struct ctdb_request); + DLIST_ADD(ctdb->outq, req); return req; } @@ -610,12 +606,13 @@ static void readrecordlock_retry(struct ctdb_connection *ctdb, /* Retransmit the same request again (we lost race). */ io_elem_reset(req->io); - DLIST_ADD_END(ctdb->outq, req, struct ctdb_request); + DLIST_ADD(ctdb->outq, req); return; } -struct ctdb_request * +bool ctdb_readrecordlock_send(struct ctdb_db *ctdb_db, TDB_DATA key, + struct ctdb_request **reqp, ctdb_callback_t callback, void *cbdata) { struct ctdb_request *req; @@ -644,10 +641,9 @@ ctdb_readrecordlock_send(struct ctdb_db *ctdb_db, TDB_DATA key, req->extra_destructor = destroy_lock; if (try_readrecordlock(lock)) { - /* Already got it: prepare for immediate callback. */ - DLIST_ADD_END(ctdb_db->ctdb->immediateq, - req, struct ctdb_request); - return req; + *reqp = NULL; + callback(ctdb_db->ctdb, req, cbdata); + return true; } /* We store the original callback in the lock, and use our own. */ @@ -664,8 +660,9 @@ ctdb_readrecordlock_send(struct ctdb_db *ctdb_db, TDB_DATA key, req->hdr.call->keylen = key.dsize; req->hdr.call->calldatalen = 0; memcpy(req->hdr.call->data, key.dptr, key.dsize); - DLIST_ADD_END(ctdb_db->ctdb->outq, req, struct ctdb_request); - return req; + DLIST_ADD(ctdb_db->ctdb->outq, req); + *reqp = req; + return true; } int ctdb_writerecord(struct ctdb_lock *lock, TDB_DATA data) diff --git a/libctdb/libctdb_private.h b/libctdb/libctdb_private.h index 57270127..f016be0c 100644 --- a/libctdb/libctdb_private.h +++ b/libctdb/libctdb_private.h @@ -42,8 +42,6 @@ struct ctdb_connection { struct ctdb_request *outq; /* Finished outgoings (awaiting response) */ struct ctdb_request *doneq; - /* Successful sync requests, waiting for next service. */ - struct ctdb_request *immediateq; /* Current incoming. */ struct io_elem *in; /* Guess at a good reqid to try next. */ diff --git a/libctdb/messages.c b/libctdb/messages.c index 864ec3e7..26f90aa0 100644 --- a/libctdb/messages.c +++ b/libctdb/messages.c @@ -49,8 +49,7 @@ int ctdb_set_message_handler_recv(struct ctdb_connection *ctdb, } /* Put ourselves in list of handlers. */ - DLIST_ADD_END(ctdb->message_handlers, info, - struct message_handler_info); + DLIST_ADD(ctdb->message_handlers, info); /* Keep safe from destructor */ req->extra = NULL; return 0; diff --git a/libctdb/tst.c b/libctdb/tst.c index 2b0aa14a..8ab631dd 100644 --- a/libctdb/tst.c +++ b/libctdb/tst.c @@ -164,13 +164,14 @@ int main(int argc, char *argv[]) exit(10); } - handle = ctdb_readrecordlock_send(ctdb_db_context, key, rrl_cb, - ctdb_db_context); - if (handle == NULL) { + if (!ctdb_readrecordlock_send(ctdb_db_context, key, &handle, + rrl_cb, ctdb_db_context)) { printf("Failed to send READRECORDLOCK\n"); exit(10); } - + if (handle) { + printf("READRECORDLOCK is async\n"); + } for (;;) { pfd.events = ctdb_which_events(ctdb_connection); -- 2.34.1