mirror of
https://github.com/samba-team/samba.git
synced 2025-01-10 01:18:15 +03:00
remaning code to finish lock_fetch/store_unlock clientside helpers
(This used to be ctdb commit edf1e1fea8500461a08cd2795251a5cc0bd10229)
This commit is contained in:
commit
45660a3c48
@ -545,19 +545,33 @@ struct ctdb_record_handle *ctdb_client_fetch_lock(struct ctdb_db_context *ctdb_d
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ctdb_ltdb_fetch(ctdb_db, key, &header, ctdb_db, &data);
|
||||
ret = ctdb_ltdb_fetch(ctdb_db, key, &header, ctdb_db, data);
|
||||
if (ret != 0) {
|
||||
ctdb_ltdb_unlock(ctdb_db, key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (header.dmaster != ctdb->vnn) {
|
||||
if (header.dmaster != ctdb_db->ctdb->vnn) {
|
||||
state = ctdb_client_fetch_lock_send(ctdb_db, mem_ctx, key);
|
||||
rec = ctdb_client_fetch_lock_recv(state, mem_ctx, key, data);
|
||||
return rec;
|
||||
}
|
||||
|
||||
rec = talloc(mem_ctx, struct ctdb_record_handle);
|
||||
CTDB_NO_MEMORY_NULL(ctdb_db->ctdb, rec);
|
||||
|
||||
rec->ctdb_db = state->ctdb_db;
|
||||
rec->key = key;
|
||||
rec->key.dptr = talloc_memdup(rec, key.dptr, key.dsize);
|
||||
rec->data = talloc(rec, TDB_DATA);
|
||||
rec->data->dsize = state->call.reply_data.dsize;
|
||||
rec->data->dptr = talloc_memdup(rec, state->call.reply_data.dptr, rec->data->dsize);
|
||||
|
||||
if (data) {
|
||||
*data = *rec->data;
|
||||
}
|
||||
return rec;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -186,6 +186,24 @@ static void daemon_request_fetch_lock(struct ctdb_client *client,
|
||||
struct client_fetch_lock_data *fl_data;
|
||||
|
||||
ctdb_db = find_ctdb_db(client->ctdb, f->db_id);
|
||||
if (ctdb_db == NULL) {
|
||||
struct ctdb_reply_fetch_lock r;
|
||||
|
||||
ZERO_STRUCT(r);
|
||||
r.hdr.length = sizeof(r);
|
||||
r.hdr.ctdb_magic = CTDB_MAGIC;
|
||||
r.hdr.ctdb_version = CTDB_VERSION;
|
||||
r.hdr.operation = CTDB_REPLY_FETCH_LOCK;
|
||||
r.hdr.reqid = f->hdr.reqid;
|
||||
r.state = -1;
|
||||
|
||||
/*
|
||||
* Ignore the result, there's not much we can do anyway.
|
||||
*/
|
||||
ctdb_queue_send(client->queue, (uint8_t *)&r.hdr,
|
||||
r.hdr.length);
|
||||
return;
|
||||
}
|
||||
|
||||
key.dsize = f->keylen;
|
||||
key.dptr = &f->key[0];
|
||||
|
@ -71,48 +71,54 @@ static int lockwait_destructor(struct lockwait_handle *h)
|
||||
*/
|
||||
struct lockwait_handle *ctdb_lockwait(struct ctdb_db_context *ctdb_db,
|
||||
TDB_DATA key,
|
||||
void (*callback)(void *), void *private_data)
|
||||
void (*callback)(void *private_data),
|
||||
void *private_data)
|
||||
{
|
||||
struct lockwait_handle *h;
|
||||
struct lockwait_handle *result;
|
||||
int ret;
|
||||
|
||||
h = talloc_zero(ctdb_db, struct lockwait_handle);
|
||||
if (h == NULL) {
|
||||
if (!(result = talloc_zero(ctdb_db, struct lockwait_handle))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = pipe(h->fd);
|
||||
ret = pipe(result->fd);
|
||||
|
||||
if (ret != 0) {
|
||||
talloc_free(h);
|
||||
talloc_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
h->child = fork();
|
||||
if (h->child == (pid_t)-1) {
|
||||
close(h->fd[0]);
|
||||
close(h->fd[1]);
|
||||
talloc_free(h);
|
||||
result->child = fork();
|
||||
|
||||
if (result->child == (pid_t)-1) {
|
||||
close(result->fd[0]);
|
||||
close(result->fd[1]);
|
||||
talloc_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
h->callback = callback;
|
||||
h->private_data = private_data;
|
||||
result->callback = callback;
|
||||
result->private_data = private_data;
|
||||
|
||||
if (h->child == 0) {
|
||||
struct tdb_context *tdb = ctdb_db->ltdb->tdb;
|
||||
/* in child */
|
||||
tdb_chainlock(tdb, key);
|
||||
_exit(0);
|
||||
if (result->child == 0) {
|
||||
close(result->fd[0]);
|
||||
/*
|
||||
* Do we need a tdb_reopen here?
|
||||
*/
|
||||
tdb_chainlock(ctdb_db->ltdb->tdb, key);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
close(h->fd[1]);
|
||||
talloc_set_destructor(h, lockwait_destructor);
|
||||
close(result->fd[1]);
|
||||
talloc_set_destructor(result, lockwait_destructor);
|
||||
|
||||
h->fde = event_add_fd(ctdb_db->ctdb->ev, h, h->fd[0], EVENT_FD_READ, lockwait_handler, h);
|
||||
if (h->fde == NULL) {
|
||||
talloc_free(h);
|
||||
result->fde = event_add_fd(ctdb_db->ctdb->ev, result, result->fd[0],
|
||||
EVENT_FD_READ, lockwait_handler,
|
||||
(void *)result);
|
||||
if (result->fde == NULL) {
|
||||
talloc_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return h;
|
||||
return result;
|
||||
}
|
||||
|
@ -244,6 +244,12 @@ static void lock_fetch_callback(void *p)
|
||||
immediately satisfied until it can get the lock. This means that
|
||||
the main ctdb daemon will not block waiting for a chainlock held by
|
||||
a client
|
||||
|
||||
There are 3 possible return values:
|
||||
|
||||
0: means that it got the lock immediately.
|
||||
-1: means that it failed to get the lock, and won't retry
|
||||
-2: means that it failed to get the lock immediately, but will retry
|
||||
*/
|
||||
int ctdb_ltdb_lock_fetch_requeue(struct ctdb_db_context *ctdb_db,
|
||||
TDB_DATA key, struct ctdb_ltdb_header *header,
|
||||
@ -255,6 +261,12 @@ int ctdb_ltdb_lock_fetch_requeue(struct ctdb_db_context *ctdb_db,
|
||||
|
||||
ret = tdb_chainlock_nonblock(tdb, key);
|
||||
|
||||
if (ret != 0 &&
|
||||
!(errno == EACCES || errno == EAGAIN || errno == EDEADLK)) {
|
||||
/* a hard failure - don't try again */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* first the non-contended path */
|
||||
if (ret == 0) {
|
||||
ret = ctdb_ltdb_fetch(ctdb_db, key, header, hdr, data);
|
||||
@ -273,6 +285,11 @@ int ctdb_ltdb_lock_fetch_requeue(struct ctdb_db_context *ctdb_db,
|
||||
|
||||
/* we get an extra reference to the packet here, to
|
||||
stop it being freed in the top level packet handler */
|
||||
(void)talloc_reference(ctdb_db, hdr);
|
||||
return 0;
|
||||
if (talloc_reference(ctdb_db, hdr) == NULL) {
|
||||
talloc_free(h);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* now tell the caller than we will retry asynchronously */
|
||||
return -2;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user