00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <sys/types.h>
00011
00012 #include <stdlib.h>
00013 #include <string.h>
00014
00015 #ifdef _WIN32
00016 extern int getopt(int, char * const *, const char *);
00017 #else
00018 #include <unistd.h>
00019 #endif
00020
00021 #include <db.h>
00022
00023 int db_init __P((const char *, u_int32_t, int));
00024 int main __P((int, char *[]));
00025 int usage __P((void));
00026
00027 DB_ENV *dbenv;
00028 const char
00029 *progname = "ex_lock";
00030
00031 int
00032 main(argc, argv)
00033 int argc;
00034 char *argv[];
00035 {
00036 extern char *optarg;
00037 extern int optind;
00038 DBT lock_dbt;
00039 DB_LOCK lock;
00040 DB_LOCK *locks;
00041 db_lockmode_t lock_type;
00042 long held;
00043 size_t len;
00044 u_int32_t locker, maxlocks;
00045 int ch, do_unlink, did_get, i, lockid, lockcount, ret;
00046 const char *home;
00047 char opbuf[16], objbuf[1024], lockbuf[16];
00048
00049 home = "TESTDIR";
00050 maxlocks = 0;
00051 do_unlink = 0;
00052 while ((ch = getopt(argc, argv, "h:m:u")) != EOF)
00053 switch (ch) {
00054 case 'h':
00055 home = optarg;
00056 break;
00057 case 'm':
00058 if ((i = atoi(optarg)) <= 0)
00059 return (usage());
00060 maxlocks = (u_int32_t)i;
00061 break;
00062 case 'u':
00063 do_unlink = 1;
00064 break;
00065 case '?':
00066 default:
00067 return (usage());
00068 }
00069 argc -= optind;
00070 argv += optind;
00071
00072 if (argc != 0)
00073 return (usage());
00074
00075
00076 if ((ret = db_init(home, maxlocks, do_unlink)) != 0)
00077 return (ret);
00078
00079 locks = 0;
00080 lockcount = 0;
00081
00082
00083
00084
00085 if ((ret = dbenv->lock_id(dbenv, &locker)) != 0) {
00086 dbenv->err(dbenv, ret, "unable to get locker id");
00087 (void)dbenv->close(dbenv, 0);
00088 return (EXIT_FAILURE);
00089 }
00090 lockid = -1;
00091
00092 memset(&lock_dbt, 0, sizeof(lock_dbt));
00093 for (held = 0, did_get = 0;;) {
00094 printf("Operation get/release [get]> ");
00095 fflush(stdout);
00096 if (fgets(opbuf, sizeof(opbuf), stdin) == NULL)
00097 break;
00098 if ((len = strlen(opbuf)) <= 1 || strcmp(opbuf, "get\n") == 0) {
00099
00100 printf("input object (text string) to lock> ");
00101 fflush(stdout);
00102 if (fgets(objbuf, sizeof(objbuf), stdin) == NULL)
00103 break;
00104 if ((len = strlen(objbuf)) <= 1)
00105 continue;
00106
00107 do {
00108 printf("lock type read/write [read]> ");
00109 fflush(stdout);
00110 if (fgets(lockbuf,
00111 sizeof(lockbuf), stdin) == NULL)
00112 break;
00113 len = strlen(lockbuf);
00114 } while (len > 1 &&
00115 strcmp(lockbuf, "read\n") != 0 &&
00116 strcmp(lockbuf, "write\n") != 0);
00117 if (len == 1 || strcmp(lockbuf, "read\n") == 0)
00118 lock_type = DB_LOCK_READ;
00119 else
00120 lock_type = DB_LOCK_WRITE;
00121
00122 lock_dbt.data = objbuf;
00123 lock_dbt.size = (u_int32_t)strlen(objbuf);
00124 ret = dbenv->lock_get(dbenv, locker,
00125 DB_LOCK_NOWAIT, &lock_dbt, lock_type, &lock);
00126 if (ret == 0) {
00127 did_get = 1;
00128 lockid = lockcount++;
00129 if (locks == NULL)
00130 locks =
00131 (DB_LOCK *)malloc(sizeof(DB_LOCK));
00132 else
00133 locks = (DB_LOCK *)realloc(locks,
00134 lockcount * sizeof(DB_LOCK));
00135 locks[lockid] = lock;
00136 }
00137 } else {
00138
00139 do {
00140 printf("input lock to release> ");
00141 fflush(stdout);
00142 if (fgets(objbuf,
00143 sizeof(objbuf), stdin) == NULL)
00144 break;
00145 } while ((len = strlen(objbuf)) <= 1);
00146 lockid = strtol(objbuf, NULL, 16);
00147 if (lockid < 0 || lockid >= lockcount) {
00148 printf("Lock #%d out of range\n", lockid);
00149 continue;
00150 }
00151 lock = locks[lockid];
00152 ret = dbenv->lock_put(dbenv, &lock);
00153 did_get = 0;
00154 }
00155 switch (ret) {
00156 case 0:
00157 printf("Lock #%d %s\n", lockid,
00158 did_get ? "granted" : "released");
00159 held += did_get ? 1 : -1;
00160 break;
00161 case DB_LOCK_NOTGRANTED:
00162 dbenv->err(dbenv, ret, NULL);
00163 break;
00164 case DB_LOCK_DEADLOCK:
00165 dbenv->err(dbenv, ret,
00166 "lock_%s", did_get ? "get" : "put");
00167 break;
00168 default:
00169 dbenv->err(dbenv, ret,
00170 "lock_%s", did_get ? "get" : "put");
00171 (void)dbenv->close(dbenv, 0);
00172 return (EXIT_FAILURE);
00173 }
00174 }
00175
00176 printf("\nClosing lock region %ld locks held\n", held);
00177
00178 if (locks != NULL)
00179 free(locks);
00180
00181 if ((ret = dbenv->close(dbenv, 0)) != 0) {
00182 fprintf(stderr,
00183 "%s: dbenv->close: %s\n", progname, db_strerror(ret));
00184 return (EXIT_FAILURE);
00185 }
00186 return (EXIT_SUCCESS);
00187 }
00188
00189
00190
00191
00192
00193 int
00194 db_init(home, maxlocks, do_unlink)
00195 const char *home;
00196 u_int32_t maxlocks;
00197 int do_unlink;
00198 {
00199 int ret;
00200
00201 if ((ret = db_env_create(&dbenv, 0)) != 0) {
00202 fprintf(stderr, "%s: db_env_create: %s\n",
00203 progname, db_strerror(ret));
00204 return (EXIT_FAILURE);
00205 }
00206
00207 if (do_unlink) {
00208 if ((ret = dbenv->remove(dbenv, home, DB_FORCE)) != 0) {
00209 fprintf(stderr, "%s: dbenv->remove: %s\n",
00210 progname, db_strerror(ret));
00211 return (EXIT_FAILURE);
00212 }
00213 if ((ret = db_env_create(&dbenv, 0)) != 0) {
00214 fprintf(stderr, "%s: db_env_create: %s\n",
00215 progname, db_strerror(ret));
00216 return (EXIT_FAILURE);
00217 }
00218 }
00219
00220 dbenv->set_errfile(dbenv, stderr);
00221 dbenv->set_errpfx(dbenv, progname);
00222 if (maxlocks != 0)
00223 dbenv->set_lk_max_locks(dbenv, maxlocks);
00224
00225 if ((ret =
00226 dbenv->open(dbenv, home, DB_CREATE | DB_INIT_LOCK, 0)) != 0) {
00227 dbenv->err(dbenv, ret, NULL);
00228 (void)dbenv->close(dbenv, 0);
00229 return (EXIT_FAILURE);
00230 }
00231 return (0);
00232 }
00233
00234 int
00235 usage()
00236 {
00237 (void)fprintf(stderr,
00238 "usage: %s [-u] [-h home] [-m maxlocks]\n", progname);
00239 return (EXIT_FAILURE);
00240 }