dlm/tests/scripts/dlm_seq_async.c

363 lines
6.9 KiB
C

/*
* Copyright (c) 2011 David Teigland
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License V2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/* gcc dlm_seq_async.c -ldlm -o dlm_seq_async */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#include <syslog.h>
#include <sys/time.h>
#include <asm/types.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include "libdlm.h"
#define DEFAULT_NUM_R 1000
#define DEFAULT_NUM_LPR 1
static dlm_lshandle_t *dh;
static int openclose = 0;
static int quiet = 0;
static int verbose = 0;
static int opt_convert = 0;
static int opt_unlock = 0;
static int opt_async = 0;
static int opt_delay = 0;
static unsigned int num_r = DEFAULT_NUM_R;
static unsigned int num_lpr = DEFAULT_NUM_LPR;
static unsigned int num_iter = 1;
static unsigned int iter = 0;
static uint32_t *lkids;
static struct dlm_lksb lksb;
static unsigned int cb_count;
static int libdlm_fd;
#define log_debug(fmt, args...) \
do { \
if (!quiet) \
printf(fmt "\n", ##args); \
} while (0)
#define log_error(fmt, args...) \
do { \
printf("ERROR " fmt "\n", ##args); \
exit(-1); \
} while (0)
static void astfn(void *arg)
{
int status = lksb.sb_status;
cb_count++;
printf("astfn %x status %d count %u\n", lksb.sb_lkid, status, cb_count);
if (!status)
return;
if (status == EUNLOCK)
return;
}
static void seq(int acquire, int convert, int unlock, int mode)
{
char name[DLM_RESNAME_MAXLEN];
uint32_t lkid;
int i, j, rv;
for (i = 0; i < num_r; i++) {
snprintf(name, sizeof(name), "seq.%08d", i);
for (j = 0; j < num_lpr; j++) {
memset(&lksb, 0, sizeof(lksb));
if (acquire) {
printf("acquire %s %d\n", name, mode);
rv = dlm_ls_lockx(dh, mode, &lksb, 0,
name, strlen(name), 0,
astfn, &lksb, NULL,
NULL, NULL);
}
if (convert) {
lksb.sb_lkid = lkids[(i * num_lpr) + j];
printf("convert %s %x %d\n", name, lksb.sb_lkid, mode);
rv = dlm_ls_lockx(dh, mode, &lksb, LKF_CONVERT,
name, strlen(name), 0,
astfn, &lksb, NULL,
NULL, NULL);
}
if (unlock) {
lkid = lkids[(i * num_lpr) + j];
printf("unlock %s %x\n", name, lkid);
rv = dlm_ls_unlock(dh, lkid, 0, &lksb, &lksb);
}
if (rv) {
log_error("dlm op %d %d %d %d,%d error %d",
acquire, convert, unlock, i, j, rv);
return;
}
if (acquire && lkids)
lkids[(i * num_lpr) + j] = lksb.sb_lkid;
}
}
cb_count = 0;
while (1) {
rv = dlm_dispatch(libdlm_fd);
if (rv < 0) {
printf("dlm_dispatch error %d %d\n", rv, errno);
}
if (cb_count == (num_r * num_lpr))
break;
}
}
static void print_usage(void)
{
printf("dlm_seq [options]\n");
printf("Options:\n");
printf("\n");
printf(" -i <n> Iterations (0 no limit), default 1)\n");
printf(" -r <n> The number of resources, default %d\n", DEFAULT_NUM_R);
printf(" -l <n> The number of locks per resource, default %d\n", DEFAULT_NUM_LPR);
printf(" -c Convert locks after acquiring them all\n");
printf(" -u Unlock locks after acquire/convert\n");
printf(" -s Same resource names in each iteration\n");
printf(" -d <us> Delay us between consecutive seq\n");
printf(" -o Open/close existing lockspace\n");
printf(" -v Verbose output\n");
printf(" -q Quiet output\n");
}
static void decode_arguments(int argc, char **argv)
{
int cont = 1;
int optchar;
while (cont) {
optchar = getopt(argc, argv, "i:r:l:cuvqohad:s");
switch (optchar) {
case 'i':
num_iter = atoi(optarg);
break;
case 'r':
num_r = atoi(optarg);
break;
case 'l':
num_lpr = atoi(optarg);
break;
case 'c':
opt_convert = 1;
break;
case 'u':
opt_unlock = 1;
break;
case 'd':
opt_delay = atoi(optarg);
break;
case 'o':
openclose = 1;
break;
case 'v':
verbose = 1;
break;
case 'q':
quiet = 1;
break;
case 'h':
print_usage();
exit(EXIT_SUCCESS);
break;
case 'V':
printf("%s (built %s %s)\n", argv[0], __DATE__, __TIME__);
exit(EXIT_SUCCESS);
break;
case ':':
case '?':
fprintf(stderr, "Please use '-h' for usage.\n");
exit(EXIT_FAILURE);
break;
case EOF:
cont = 0;
break;
default:
fprintf(stderr, "unknown option: %c\n", optchar);
exit(EXIT_FAILURE);
break;
};
}
}
void _acquire(int mode)
{
seq(1, 0, 0, mode);
if (opt_delay)
usleep(opt_delay);
}
void _convert(int mode)
{
seq(0, 1, 0, mode);
if (opt_delay)
usleep(opt_delay);
}
void _unlock(void)
{
seq(0, 0, 1, 0);
if (opt_delay)
usleep(opt_delay);
}
int main(int argc, char *argv[])
{
int rv, quit = 0;
decode_arguments(argc, argv);
printf("%d resources, %d locks per resource\n", num_r, num_lpr);
if (openclose) {
log_debug("dlm_open_lockspace...");
dh = dlm_open_lockspace("dlm_seq");
if (!dh) {
log_error("dlm_open_lockspace error %lu %d",
(unsigned long)dh, errno);
return -ENOTCONN;
}
} else {
log_debug("dlm_new_lockspace...");
dh = dlm_new_lockspace("dlm_seq", 0600, 0);
if (!dh) {
log_error("dlm_new_lockspace error %lu %d",
(unsigned long)dh, errno);
return -ENOTCONN;
}
}
libdlm_fd = dlm_ls_get_fd(dh);
if (libdlm_fd < 0) {
log_error("dlm_ls_get fd error %d %d", libdlm_fd, errno);
goto done;
}
lkids = malloc(sizeof(uint32_t) * (num_r * num_lpr));
if (!lkids) {
log_error("no mem");
goto done;
}
while (1) {
_acquire(LKM_EXMODE);
_convert(LKM_PRMODE);
_unlock();
_acquire(LKM_EXMODE);
_unlock();
_acquire(LKM_EXMODE);
_convert(LKM_NLMODE);
_convert(LKM_EXMODE);
_unlock();
_acquire(LKM_PRMODE);
_convert(LKM_EXMODE);
_unlock();
_acquire(LKM_PRMODE);
_unlock();
_acquire(LKM_PRMODE);
_convert(LKM_NLMODE);
_convert(LKM_PRMODE);
_unlock();
_acquire(LKM_NLMODE);
_convert(LKM_PRMODE);
_unlock();
_acquire(LKM_NLMODE);
_unlock();
_acquire(LKM_NLMODE);
_convert(LKM_EXMODE);
_convert(LKM_NLMODE);
_unlock();
iter++;
if (!num_iter)
continue;
if (iter == num_iter)
break;
}
free(lkids);
done:
if (openclose) {
log_debug("dlm_close_lockspace");
rv = dlm_close_lockspace(dh);
if (rv < 0)
log_error("dlm_close_lockspace error %d %d",
rv, errno);
} else {
log_debug("dlm_release_lockspace");
rv = dlm_release_lockspace("dlm_seq", dh, 1);
if (rv < 0)
log_error("dlm_release_lockspace error %d %d",
rv, errno);
}
return 0;
}