/* fetch the current record */
ret = ctdb_ltdb_lock_fetch_requeue(ctdb_db, key, &header, hdr, &data2,
- ctdb_recv_raw_pkt, ctdb);
+ ctdb_recv_raw_pkt, ctdb, False);
if (ret == -1) {
ctdb_fatal(ctdb, "ctdb_req_dmaster failed to fetch record");
return;
if the call will be answered locally */
ret = ctdb_ltdb_lock_fetch_requeue(ctdb_db, call.key, &header, hdr, &data,
- ctdb_recv_raw_pkt, ctdb);
+ ctdb_recv_raw_pkt, ctdb, False);
if (ret == -1) {
ctdb_send_error(ctdb, hdr, ret, "ltdb fetch failed in ctdb_request_call");
return;
data.dsize = c->datalen;
ret = ctdb_ltdb_lock_requeue(ctdb_db, key, hdr,
- ctdb_recv_raw_pkt, ctdb);
+ ctdb_recv_raw_pkt, ctdb, False);
if (ret == -2) {
return;
}
ret = ctdb_ltdb_lock_fetch_requeue(ctdb_db, key, &header,
(struct ctdb_req_header *)c, &data,
- daemon_incoming_packet, client);
+ daemon_incoming_packet, client, True);
if (ret == -2) {
/* will retry later */
ctdb->status.pending_calls--;
void (*recv_pkt)(void *, uint8_t *, uint32_t);
void *recv_context;
struct ctdb_req_header *hdr;
+ uint32_t generation;
+ bool ignore_generation;
};
/*
static void lock_fetch_callback(void *p)
{
struct lock_fetch_state *state = talloc_get_type(p, struct lock_fetch_state);
+ if (!state->ignore_generation &&
+ state->generation != state->ctdb->vnn_map->generation) {
+ DEBUG(0,("Discarding previous generation lockwait packet\n"));
+ talloc_free(state->hdr);
+ return;
+ }
state->recv_pkt(state->recv_context, (uint8_t *)state->hdr, state->hdr->length);
DEBUG(2,(__location__ " PACKET REQUEUED\n"));
}
int ctdb_ltdb_lock_requeue(struct ctdb_db_context *ctdb_db,
TDB_DATA key, struct ctdb_req_header *hdr,
void (*recv_pkt)(void *, uint8_t *, uint32_t ),
- void *recv_context)
+ void *recv_context, bool ignore_generation)
{
int ret;
struct tdb_context *tdb = ctdb_db->ltdb->tdb;
state->hdr = hdr;
state->recv_pkt = recv_pkt;
state->recv_context = recv_context;
+ state->generation = ctdb_db->ctdb->vnn_map->generation;
+ state->ignore_generation = ignore_generation;
/* now the contended path */
h = ctdb_lockwait(ctdb_db, key, lock_fetch_callback, state);
TDB_DATA key, struct ctdb_ltdb_header *header,
struct ctdb_req_header *hdr, TDB_DATA *data,
void (*recv_pkt)(void *, uint8_t *, uint32_t ),
- void *recv_context)
+ void *recv_context, bool ignore_generation)
{
int ret;
- ret = ctdb_ltdb_lock_requeue(ctdb_db, key, hdr, recv_pkt, recv_context);
+ ret = ctdb_ltdb_lock_requeue(ctdb_db, key, hdr, recv_pkt,
+ recv_context, ignore_generation);
if (ret == 0) {
ret = ctdb_ltdb_fetch(ctdb_db, key, header, hdr, data);
if (ret != 0) {
DEBUG(0, (__location__ " Unable to fetch record\n"));
goto failed;
}
- if (header.rsn < hdr->rsn) {
+ /* the <= is to cope with just-created records, which
+ have a rsn of zero */
+ if (header.rsn <= hdr->rsn) {
ret = ctdb_ltdb_store(ctdb_db, key, hdr, data);
if (ret != 0) {
DEBUG(0, (__location__ " Unable to store record\n"));
int ctdb_ltdb_lock_requeue(struct ctdb_db_context *ctdb_db,
TDB_DATA key, struct ctdb_req_header *hdr,
void (*recv_pkt)(void *, uint8_t *, uint32_t ),
- void *recv_context);
+ void *recv_context, bool ignore_generation);
int ctdb_ltdb_lock_fetch_requeue(struct ctdb_db_context *ctdb_db,
TDB_DATA key, struct ctdb_ltdb_header *header,
struct ctdb_req_header *hdr, TDB_DATA *data,
void (*recv_pkt)(void *, uint8_t *, uint32_t ),
- void *recv_context);
+ void *recv_context, bool ignore_generation);
void ctdb_recv_pkt(struct ctdb_context *ctdb, uint8_t *data, uint32_t length);
struct ctdb_call_state *ctdb_call_local_send(struct ctdb_db_context *ctdb_db,