1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1997-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9#include <sys/types.h> 10 11#include <stdlib.h> 12#include <string.h> 13 14#ifdef _WIN32 15extern int getopt(int, char * const *, const char *); 16#else 17#include <unistd.h> 18#endif 19 20#include <db.h> 21 22int db_init __P((const char *, u_int32_t, int)); 23int main __P((int, char *[])); 24int usage __P((void)); 25 26DB_ENV *dbenv; 27const char 28 *progname = "ex_lock"; /* Program name. */ 29 30int 31main(argc, argv) 32 int argc; 33 char *argv[]; 34{ 35 extern char *optarg; 36 extern int optind; 37 DBT lock_dbt; 38 DB_LOCK lock; 39 DB_LOCK *locks; 40 db_lockmode_t lock_type; 41 long held; 42 size_t len; 43 u_int32_t locker, maxlocks; 44 int ch, do_unlink, did_get, i, lockid, lockcount, ret; 45 const char *home; 46 char opbuf[16], objbuf[1024], lockbuf[16]; 47 48 home = "TESTDIR"; 49 maxlocks = 0; 50 do_unlink = 0; 51 while ((ch = getopt(argc, argv, "h:m:u")) != EOF) 52 switch (ch) { 53 case 'h': 54 home = optarg; 55 break; 56 case 'm': 57 if ((i = atoi(optarg)) <= 0) 58 return (usage()); 59 maxlocks = (u_int32_t)i; /* XXX: possible overflow. */ 60 break; 61 case 'u': 62 do_unlink = 1; 63 break; 64 case '?': 65 default: 66 return (usage()); 67 } 68 argc -= optind; 69 argv += optind; 70 71 if (argc != 0) 72 return (usage()); 73 74 /* Initialize the database environment. */ 75 if ((ret = db_init(home, maxlocks, do_unlink)) != 0) 76 return (ret); 77 78 locks = 0; 79 lockcount = 0; 80 81 /* 82 * Accept lock requests. 83 */ 84 if ((ret = dbenv->lock_id(dbenv, &locker)) != 0) { 85 dbenv->err(dbenv, ret, "unable to get locker id"); 86 (void)dbenv->close(dbenv, 0); 87 return (EXIT_FAILURE); 88 } 89 lockid = -1; 90 91 memset(&lock_dbt, 0, sizeof(lock_dbt)); 92 for (held = 0, did_get = 0;;) { 93 printf("Operation get/release [get]> "); 94 fflush(stdout); 95 if (fgets(opbuf, sizeof(opbuf), stdin) == NULL) 96 break; 97 if ((len = strlen(opbuf)) <= 1 || strcmp(opbuf, "get\n") == 0) { 98 /* Acquire a lock. */ 99 printf("input object (text string) to lock> "); 100 fflush(stdout); 101 if (fgets(objbuf, sizeof(objbuf), stdin) == NULL) 102 break; 103 if ((len = strlen(objbuf)) <= 1) 104 continue; 105 106 do { 107 printf("lock type read/write [read]> "); 108 fflush(stdout); 109 if (fgets(lockbuf, 110 sizeof(lockbuf), stdin) == NULL) 111 break; 112 len = strlen(lockbuf); 113 } while (len > 1 && 114 strcmp(lockbuf, "read\n") != 0 && 115 strcmp(lockbuf, "write\n") != 0); 116 if (len == 1 || strcmp(lockbuf, "read\n") == 0) 117 lock_type = DB_LOCK_READ; 118 else 119 lock_type = DB_LOCK_WRITE; 120 121 lock_dbt.data = objbuf; 122 lock_dbt.size = (u_int32_t)strlen(objbuf); 123 ret = dbenv->lock_get(dbenv, locker, 124 DB_LOCK_NOWAIT, &lock_dbt, lock_type, &lock); 125 if (ret == 0) { 126 did_get = 1; 127 lockid = lockcount++; 128 if (locks == NULL) 129 locks = 130 (DB_LOCK *)malloc(sizeof(DB_LOCK)); 131 else 132 locks = (DB_LOCK *)realloc(locks, 133 lockcount * sizeof(DB_LOCK)); 134 locks[lockid] = lock; 135 } 136 } else { 137 /* Release a lock. */ 138 do { 139 printf("input lock to release> "); 140 fflush(stdout); 141 if (fgets(objbuf, 142 sizeof(objbuf), stdin) == NULL) 143 break; 144 } while ((len = strlen(objbuf)) <= 1); 145 lockid = strtol(objbuf, NULL, 16); 146 if (lockid < 0 || lockid >= lockcount) { 147 printf("Lock #%d out of range\n", lockid); 148 continue; 149 } 150 lock = locks[lockid]; 151 ret = dbenv->lock_put(dbenv, &lock); 152 did_get = 0; 153 } 154 switch (ret) { 155 case 0: 156 printf("Lock #%d %s\n", lockid, 157 did_get ? "granted" : "released"); 158 held += did_get ? 1 : -1; 159 break; 160 case DB_LOCK_NOTGRANTED: 161 dbenv->err(dbenv, ret, NULL); 162 break; 163 case DB_LOCK_DEADLOCK: 164 dbenv->err(dbenv, ret, 165 "lock_%s", did_get ? "get" : "put"); 166 break; 167 default: 168 dbenv->err(dbenv, ret, 169 "lock_%s", did_get ? "get" : "put"); 170 (void)dbenv->close(dbenv, 0); 171 return (EXIT_FAILURE); 172 } 173 } 174 175 printf("\nClosing lock region %ld locks held\n", held); 176 177 if (locks != NULL) 178 free(locks); 179 180 if ((ret = dbenv->close(dbenv, 0)) != 0) { 181 fprintf(stderr, 182 "%s: dbenv->close: %s\n", progname, db_strerror(ret)); 183 return (EXIT_FAILURE); 184 } 185 return (EXIT_SUCCESS); 186} 187 188/* 189 * db_init -- 190 * Initialize the environment. 191 */ 192int 193db_init(home, maxlocks, do_unlink) 194 const char *home; 195 u_int32_t maxlocks; 196 int do_unlink; 197{ 198 int ret; 199 200 if ((ret = db_env_create(&dbenv, 0)) != 0) { 201 fprintf(stderr, "%s: db_env_create: %s\n", 202 progname, db_strerror(ret)); 203 return (EXIT_FAILURE); 204 } 205 206 if (do_unlink) { 207 if ((ret = dbenv->remove(dbenv, home, DB_FORCE)) != 0) { 208 fprintf(stderr, "%s: dbenv->remove: %s\n", 209 progname, db_strerror(ret)); 210 return (EXIT_FAILURE); 211 } 212 if ((ret = db_env_create(&dbenv, 0)) != 0) { 213 fprintf(stderr, "%s: db_env_create: %s\n", 214 progname, db_strerror(ret)); 215 return (EXIT_FAILURE); 216 } 217 } 218 219 dbenv->set_errfile(dbenv, stderr); 220 dbenv->set_errpfx(dbenv, progname); 221 if (maxlocks != 0) 222 dbenv->set_lk_max_locks(dbenv, maxlocks); 223 224 if ((ret = 225 dbenv->open(dbenv, home, DB_CREATE | DB_INIT_LOCK, 0)) != 0) { 226 dbenv->err(dbenv, ret, NULL); 227 (void)dbenv->close(dbenv, 0); 228 return (EXIT_FAILURE); 229 } 230 return (0); 231} 232 233int 234usage() 235{ 236 (void)fprintf(stderr, 237 "usage: %s [-u] [-h home] [-m maxlocks]\n", progname); 238 return (EXIT_FAILURE); 239} 240