summaryrefslogtreecommitdiff
path: root/source4/cluster/ctdb/tests/lockwait.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/cluster/ctdb/tests/lockwait.c')
-rw-r--r--source4/cluster/ctdb/tests/lockwait.c244
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;
-}