1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996,2008 Oracle. All rights reserved. 5 * 6 * $Id: db_deadlock.c,v 12.22 2008/01/08 20:58:13 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12 13#ifndef lint 14static const char copyright[] = 15 "Copyright (c) 1996,2008 Oracle. All rights reserved.\n"; 16#endif 17 18int db_deadlock_main __P((int, char *[])); 19int db_deadlock_usage __P((void)); 20int db_deadlock_version_check __P((void)); 21 22const char *progname; 23 24int 25db_deadlock(args) 26 char *args; 27{ 28 int argc; 29 char **argv; 30 31 __db_util_arg("db_deadlock", args, &argc, &argv); 32 return (db_deadlock_main(argc, argv) ? EXIT_FAILURE : EXIT_SUCCESS); 33} 34 35#include <stdio.h> 36#define ERROR_RETURN ERROR 37 38int 39db_deadlock_main(argc, argv) 40 int argc; 41 char *argv[]; 42{ 43 extern char *optarg; 44 extern int optind, __db_getopt_reset; 45 DB_ENV *dbenv; 46 u_int32_t atype; 47 time_t now; 48 u_long secs, usecs; 49 int rejected, ch, exitval, ret, verbose; 50 char *home, *logfile, *passwd, *str, time_buf[CTIME_BUFLEN]; 51 52 if ((progname = __db_rpath(argv[0])) == NULL) 53 progname = argv[0]; 54 else 55 ++progname; 56 57 if ((ret = db_deadlock_version_check()) != 0) 58 return (ret); 59 60 dbenv = NULL; 61 atype = DB_LOCK_DEFAULT; 62 home = logfile = passwd = NULL; 63 secs = usecs = 0; 64 exitval = verbose = 0; 65 __db_getopt_reset = 1; 66 while ((ch = getopt(argc, argv, "a:h:L:P:t:Vv")) != EOF) 67 switch (ch) { 68 case 'a': 69 switch (optarg[0]) { 70 case 'e': 71 atype = DB_LOCK_EXPIRE; 72 break; 73 case 'm': 74 atype = DB_LOCK_MAXLOCKS; 75 break; 76 case 'n': 77 atype = DB_LOCK_MINLOCKS; 78 break; 79 case 'o': 80 atype = DB_LOCK_OLDEST; 81 break; 82 case 'W': 83 atype = DB_LOCK_MAXWRITE; 84 break; 85 case 'w': 86 atype = DB_LOCK_MINWRITE; 87 break; 88 case 'y': 89 atype = DB_LOCK_YOUNGEST; 90 break; 91 default: 92 return (db_deadlock_usage()); 93 /* NOTREACHED */ 94 } 95 if (optarg[1] != '\0') 96 return (db_deadlock_usage()); 97 break; 98 case 'h': 99 home = optarg; 100 break; 101 case 'L': 102 logfile = optarg; 103 break; 104 case 'P': 105 passwd = strdup(optarg); 106 memset(optarg, 0, strlen(optarg)); 107 if (passwd == NULL) { 108 fprintf(stderr, "%s: strdup: %s\n", 109 progname, strerror(errno)); 110 return (EXIT_FAILURE); 111 } 112 break; 113 case 't': 114 if ((str = strchr(optarg, '.')) != NULL) { 115 *str++ = '\0'; 116 if (*str != '\0' && __db_getulong( 117 NULL, progname, str, 0, LONG_MAX, &usecs)) 118 return (EXIT_FAILURE); 119 } 120 if (*optarg != '\0' && __db_getulong( 121 NULL, progname, optarg, 0, LONG_MAX, &secs)) 122 return (EXIT_FAILURE); 123 if (secs == 0 && usecs == 0) 124 return (db_deadlock_usage()); 125 126 break; 127 case 'V': 128 printf("%s\n", db_version(NULL, NULL, NULL)); 129 return (EXIT_SUCCESS); 130 case 'v': 131 verbose = 1; 132 break; 133 case '?': 134 default: 135 return (db_deadlock_usage()); 136 } 137 argc -= optind; 138 argv += optind; 139 140 if (argc != 0) 141 return (db_deadlock_usage()); 142 143 /* Handle possible interruptions. */ 144 __db_util_siginit(); 145 146 /* Log our process ID. */ 147 if (logfile != NULL && __db_util_logset(progname, logfile)) 148 goto shutdown; 149 150 /* 151 * Create an environment object and initialize it for error 152 * reporting. 153 */ 154 if ((ret = db_env_create(&dbenv, 0)) != 0) { 155 fprintf(stderr, 156 "%s: db_env_create: %s\n", progname, db_strerror(ret)); 157 goto shutdown; 158 } 159 160 dbenv->set_errfile(dbenv, stderr); 161 dbenv->set_errpfx(dbenv, progname); 162 163 if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv, 164 passwd, DB_ENCRYPT_AES)) != 0) { 165 dbenv->err(dbenv, ret, "set_passwd"); 166 goto shutdown; 167 } 168 169 if (verbose) { 170 (void)dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK, 1); 171 (void)dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR, 1); 172 } 173 174 /* An environment is required. */ 175 if ((ret = dbenv->open(dbenv, home, DB_USE_ENVIRON, 0)) != 0) { 176 dbenv->err(dbenv, ret, "open"); 177 goto shutdown; 178 } 179 180 while (!__db_util_interrupted()) { 181 if (verbose) { 182 (void)time(&now); 183 dbenv->errx(dbenv, 184 "running at %.24s", __os_ctime(&now, time_buf)); 185 } 186 187 if ((ret = 188 dbenv->lock_detect(dbenv, 0, atype, &rejected)) != 0) { 189 dbenv->err(dbenv, ret, "DB_ENV->lock_detect"); 190 goto shutdown; 191 } 192 if (verbose) 193 dbenv->errx(dbenv, "rejected %d locks", rejected); 194 195 /* Make a pass every "secs" secs and "usecs" usecs. */ 196 if (secs == 0 && usecs == 0) 197 break; 198 __os_yield(dbenv->env, secs, usecs); 199 } 200 201 if (0) { 202shutdown: exitval = 1; 203 } 204 205 /* Clean up the logfile. */ 206 if (logfile != NULL) 207 (void)remove(logfile); 208 209 /* Clean up the environment. */ 210 if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) { 211 exitval = 1; 212 fprintf(stderr, 213 "%s: dbenv->close: %s\n", progname, db_strerror(ret)); 214 } 215 216 if (passwd != NULL) 217 free(passwd); 218 219 /* Resend any caught signal. */ 220 __db_util_sigresend(); 221 222 return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 223} 224 225int 226db_deadlock_usage() 227{ 228 (void)fprintf(stderr, 229 "usage: %s [-Vv] [-a e | m | n | o | W | w | y]\n\t%s\n", progname, 230 "[-h home] [-L file] [-P password] [-t sec.usec]"); 231 return (EXIT_FAILURE); 232} 233 234int 235db_deadlock_version_check() 236{ 237 int v_major, v_minor, v_patch; 238 239 /* Make sure we're loaded with the right version of the DB library. */ 240 (void)db_version(&v_major, &v_minor, &v_patch); 241 if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) { 242 fprintf(stderr, 243 "%s: version %d.%d doesn't match library version %d.%d\n", 244 progname, DB_VERSION_MAJOR, DB_VERSION_MINOR, 245 v_major, v_minor); 246 return (EXIT_FAILURE); 247 } 248 return (0); 249} 250