diff options
Diffstat (limited to 'source4/cluster/ctdb/tests/lockwait.c')
-rw-r--r-- | source4/cluster/ctdb/tests/lockwait.c | 244 |
1 files changed, 0 insertions, 244 deletions
diff --git a/source4/cluster/ctdb/tests/lockwait.c b/source4/cluster/ctdb/tests/lockwait.c deleted file mode 100644 index 6cefe5680a..0000000000 --- a/source4/cluster/ctdb/tests/lockwait.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - test a lock wait idea - - Copyright (C) Andrew Tridgell 2006 - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 3 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "lib/events/events.h" -#include "system/filesys.h" -#include "system/wait.h" -#include "popt.h" -#include "cmdline.h" - - -struct lockwait_handle { - struct fd_event *fde; - int fd[2]; - pid_t child; - void *private_data; - void (*callback)(void *); -}; - -static void lockwait_handler(struct event_context *ev, struct fd_event *fde, - uint16_t flags, void *private_data) -{ - struct lockwait_handle *h = talloc_get_type(private_data, - struct lockwait_handle); - void (*callback)(void *) = h->callback; - void *p = h->private_data; - talloc_set_destructor(h, NULL); - close(h->fd[0]); - talloc_free(h); - callback(p); - waitpid(h->child, NULL, 0); -} - -static int lockwait_destructor(struct lockwait_handle *h) -{ - close(h->fd[0]); - kill(h->child, SIGKILL); - waitpid(h->child, NULL, 0); - return 0; -} - - -static struct lockwait_handle *lockwait(struct event_context *ev, - TALLOC_CTX *mem_ctx, - int fd, off_t ofs, size_t len, - void (*callback)(void *), void *private_data) -{ - struct lockwait_handle *h; - int ret; - - h = talloc_zero(mem_ctx, struct lockwait_handle); - if (h == NULL) { - return NULL; - } - - ret = pipe(h->fd); - if (ret != 0) { - talloc_free(h); - return NULL; - } - - h->child = fork(); - if (h->child == (pid_t)-1) { - close(h->fd[0]); - close(h->fd[1]); - talloc_free(h); - return NULL; - } - - h->callback = callback; - h->private_data = private_data; - - if (h->child == 0) { - /* in child */ - struct flock lock; - close(h->fd[0]); - lock.l_type = F_WRLCK; - lock.l_whence = SEEK_SET; - lock.l_start = ofs; - lock.l_len = len; - lock.l_pid = 0; - fcntl(fd,F_SETLKW,&lock); - _exit(0); - } - - close(h->fd[1]); - talloc_set_destructor(h, lockwait_destructor); - - h->fde = event_add_fd(ev, h, h->fd[0], EVENT_FD_READ, lockwait_handler, h); - if (h->fde == NULL) { - talloc_free(h); - return NULL; - } - - return h; -} - - - - -static void fcntl_lock_callback(void *p) -{ - int *got_lock = (int *)p; - *got_lock = 1; -} - -/* - get an fcntl lock - waiting if necessary - */ -static int fcntl_lock(struct event_context *ev, - int fd, int op, off_t offset, off_t count, int type) -{ - struct flock lock; - int ret; - int use_lockwait = (op == F_SETLKW); - int got_lock = 0; - - lock.l_type = type; - lock.l_whence = SEEK_SET; - lock.l_start = offset; - lock.l_len = count; - lock.l_pid = 0; - - do { - ret = fcntl(fd,use_lockwait?F_SETLK:op,&lock); - if (ret == 0) { - return 0; - } - if (ret == -1 && - (errno == EACCES || errno == EAGAIN || errno == EDEADLK)) { - struct lockwait_handle *h; - h = lockwait(ev, ev, fd, offset, count, - fcntl_lock_callback, &got_lock); - if (h == NULL) { - errno = ENOLCK; - return -1; - } - /* in real code we would return to the event loop */ - while (!got_lock) { - event_loop_once(ev); - } - got_lock = 0; - } - } while (!got_lock); - - return ret; -} - -static void child(struct event_context *ev, int n) -{ - int fd; - int count=0; - struct timeval tv; - fd = open("test.dat", O_CREAT|O_RDWR, 0666); - if (fd == -1) { - perror("test.dat"); - exit(1); - } - - tv = timeval_current(); - - while (timeval_elapsed(&tv) < 10) { - int ret; - ret = fcntl_lock(ev, fd, F_SETLKW, 0, 1, F_WRLCK); - if (ret != 0) { - printf("Failed to get lock in child %d!\n", n); - break; - } - fcntl_lock(ev, fd, F_SETLK, 0, 1, F_UNLCK); - count++; - } - - printf("child %2d %.0f ops/sec\n", n, count/timeval_elapsed(&tv)); - _exit(0); -} - -static int timelimit = 10; - -/* - main program -*/ -int main(int argc, const char *argv[]) -{ - pid_t *pids; - int nprogs = 2; - int i; - struct event_context *ev; - struct poptOption popt_options[] = { - POPT_AUTOHELP - { "timelimit", 't', POPT_ARG_INT, &timelimit, 0, "timelimit", "integer" }, - { "num-progs", 'n', POPT_ARG_INT, &nprogs, 0, "num_progs", "integer" }, - POPT_TABLEEND - }; - poptContext pc; - int opt; - - pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST); - - while ((opt = poptGetNextOpt(pc)) != -1) { - switch (opt) { - default: - fprintf(stderr, "Invalid option %s: %s\n", - poptBadOption(pc, 0), poptStrerror(opt)); - exit(1); - } - } - - ev = event_context_init(NULL); - - pids = talloc_array(ev, pid_t, nprogs); - - /* create N processes fighting over the same lock */ - for (i=0;i<nprogs;i++) { - pids[i] = fork(); - if (pids[i] == 0) { - child(ev, i); - } - } - - printf("Waiting for %d children ...\n", nprogs); - - /* wait for our kids to finish playing */ - for (i=0;i<nprogs;i++) { - waitpid(pids[i], NULL, 0); - } - - return 0; -} |