/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 Iterations (0 no limit), default 1)\n"); printf(" -r The number of resources, default %d\n", DEFAULT_NUM_R); printf(" -l 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 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; }