Update.
[glibc.git] / db2 / progs / db_deadlock / db_deadlock.c
blobec2b53dee7aa791add80906ab2a7cb4a560c09b6
1 /*-
2 * See the file LICENSE for redistribution information.
4 * Copyright (c) 1996, 1997
5 * Sleepycat Software. All rights reserved.
6 */
8 #include "config.h"
10 #ifndef lint
11 static const char copyright[] =
12 "@(#) Copyright (c) 1997\n\
13 Sleepycat Software Inc. All rights reserved.\n";
14 static const char sccsid[] = "@(#)db_deadlock.c 10.15 (Sleepycat) 9/4/97";
15 #endif
17 #ifndef NO_SYSTEM_INCLUDES
18 #include <sys/types.h>
20 #include <errno.h>
21 #include <limits.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <time.h>
26 #include <unistd.h>
27 #endif
29 #include "db_int.h"
30 #include "clib_ext.h"
31 #include "common_ext.h"
33 #define BAD_KILLID 0xffffffff
35 DB_ENV *db_init __P((char *, int));
36 int logpid __P((char *, int));
37 int main __P((int, char *[]));
38 void onint __P((int));
39 void siginit __P((void));
40 void usage __P((void));
42 int interrupted;
43 const char
44 *progname = "db_deadlock"; /* Program name. */
46 int
47 main(argc, argv)
48 int argc;
49 char *argv[];
51 extern char *optarg;
52 extern int optind;
53 DB_ENV *dbenv;
54 u_int32_t atype;
55 time_t now;
56 long seconds;
57 int ch, flags, verbose;
58 char *home, *logfile;
60 atype = DB_LOCK_DEFAULT;
61 home = logfile = NULL;
62 seconds = 0;
63 flags = verbose = 0;
64 while ((ch = getopt(argc, argv, "a:h:L:t:vw")) != EOF)
65 switch (ch) {
66 case 'a':
67 switch (optarg[0]) {
68 case 'o':
69 atype = DB_LOCK_OLDEST;
70 break;
71 case 'y':
72 atype = DB_LOCK_YOUNGEST;
73 break;
74 default:
75 usage();
76 /* NOTREACHED */
78 if (optarg[1] != '\0')
79 usage();
80 break;
81 case 'h':
82 home = optarg;
83 break;
84 case 'L':
85 logfile = optarg;
86 break;
87 case 't':
88 get_long(optarg, 1, LONG_MAX, &seconds);
89 break;
90 case 'v':
91 verbose = 1;
92 break;
93 case 'w':
94 LF_SET(DB_LOCK_CONFLICT);
95 break;
96 case '?':
97 default:
98 usage();
100 argc -= optind;
101 argv += optind;
103 if (argc != 0)
104 usage();
106 if (seconds == 0 && !LF_ISSET(DB_LOCK_CONFLICT)) {
107 warnx("at least one of -t and -w must be specified");
108 usage();
112 * We detect every second when we're running in DB_LOCK_CONFLICT mode.
114 if (seconds == 0)
115 seconds = 1;
117 /* Initialize the deadlock detector by opening the lock manager. */
118 dbenv = db_init(home, verbose);
120 if (logfile != NULL && logpid(logfile, 1)) {
121 (void)db_appexit(dbenv);
122 return (1);
125 while (!interrupted) {
126 if (dbenv->db_verbose != 0) {
127 time(&now);
128 __db_err(dbenv, "Running at %s", ctime(&now));
131 if ((errno = lock_detect(dbenv->lk_info, flags, atype)) != 0)
132 break;
134 /* Make a pass every "seconds" seconds. */
135 (void)__db_sleep(seconds, 0);
138 if (logfile != NULL)
139 (void)logpid(logfile, 0);
141 if (interrupted) {
142 (void)signal(interrupted, SIG_DFL);
143 (void)raise(interrupted);
144 /* NOTREACHED */
147 return (db_appexit(dbenv));
150 DB_ENV *
151 db_init(home, verbose)
152 char *home;
153 int verbose;
155 DB_ENV *dbenv;
157 if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
158 errno = ENOMEM;
159 err(1, NULL);
161 dbenv->db_errfile = stderr;
162 dbenv->db_errpfx = progname;
163 dbenv->db_verbose = verbose;
165 if ((errno = db_appinit(home,
166 NULL, dbenv, DB_INIT_LOCK | DB_USE_ENVIRON)) != 0)
167 err(1, "db_appinit");
169 siginit();
171 return (dbenv);
175 * logpid --
176 * Log that we're running.
179 logpid(fname, is_open)
180 char *fname;
181 int is_open;
183 FILE *fp;
184 time_t now;
186 if (is_open) {
187 if ((fp = fopen(fname, "w")) == NULL) {
188 warn("%s", fname);
189 return (1);
191 (void)time(&now);
192 fprintf(fp,
193 "%s: %lu %s", progname, (u_long)getpid(), ctime(&now));
194 fclose(fp);
195 } else
196 (void)remove(fname);
197 return (0);
201 * siginit --
202 * Initialize the set of signals for which we want to clean up.
203 * Generally, we try not to leave the shared regions locked if
204 * we can.
206 void
207 siginit()
209 #ifdef SIGHUP
210 (void)signal(SIGHUP, onint);
211 #endif
212 (void)signal(SIGINT, onint);
213 #ifdef SIGKILL
214 (void)signal(SIGKILL, onint);
215 #endif
216 (void)signal(SIGTERM, onint);
220 * oninit --
221 * Interrupt signal handler.
223 void
224 onint(signo)
225 int signo;
227 if ((interrupted = signo) == 0)
228 interrupted = SIGINT;
231 void
232 usage()
234 (void)fprintf(stderr,
235 "usage: db_deadlock [-vw] [-a m | o | y] [-h home] [-L file] [-t sec]\n");
236 exit(1);