4f9b79a7bab84ae0ae3b539c460f5849ad85edb7
[kopensolaris-gnu/glibc.git] / db2 / progs / db_checkpoint / db_checkpoint.c
1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1996, 1997
5  *      Sleepycat Software.  All rights reserved.
6  */
7
8 #include "config.h"
9
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_checkpoint.c       10.11 (Sleepycat) 8/27/97";
15 #endif
16
17 #ifndef NO_SYSTEM_INCLUDES
18 #include <sys/types.h>
19
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
28
29 #include "db_int.h"
30 #include "shqueue.h"
31 #include "db_page.h"
32 #include "log.h"
33 #include "btree.h"
34 #include "hash.h"
35 #include "clib_ext.h"
36 #include "common_ext.h"
37
38 char    *check __P((DB_ENV *, long, long));
39 int      checkpoint __P((DB_ENV *, char *, int));
40 DB_ENV  *db_init __P((char *));
41 int      logpid __P((char *, int));
42 int      main __P((int, char *[]));
43 void     onint __P((int));
44 void     siginit __P((void));
45 void     usage __P((void));
46
47 int      interrupted;
48 time_t   now;                                   /* Checkpoint time. */
49 const char
50         *progname = "db_checkpoint";            /* Program name. */
51
52 int
53 main(argc, argv)
54         int argc;
55         char *argv[];
56 {
57         extern char *optarg;
58         extern int optind;
59         DB_ENV *dbenv;
60         time_t now;
61         long kbytes, minutes, seconds;
62         int ch, rval, verbose;
63         char *home, *logfile;
64
65         home = logfile = NULL;
66         kbytes = minutes = 0;
67         verbose = 0;
68         while ((ch = getopt(argc, argv, "h:k:L:p:v")) != EOF)
69                 switch (ch) {
70                 case 'h':
71                         home = optarg;
72                         break;
73                 case 'k':
74                         get_long(optarg, 1, LONG_MAX, &kbytes);
75                         break;
76                 case 'L':
77                         logfile = optarg;
78                         break;
79                 case 'p':
80                         get_long(optarg, 1, LONG_MAX, &minutes);
81                         break;
82                 case 'v':
83                         verbose = 1;
84                         break;
85                 case '?':
86                 default:
87                         usage();
88                 }
89         argc -= optind;
90         argv += optind;
91
92         if (argc != 0)
93                 usage();
94
95         if (kbytes == 0 && minutes == 0) {
96                 warnx("at least one of -k and -p must be specified");
97                 usage();
98         }
99
100         /* Initialize the environment. */
101         dbenv = db_init(home);
102
103         if (logfile != NULL && logpid(logfile, 1)) {
104                 (void)db_appexit(dbenv);
105                 return (1);
106         }
107
108         /*
109          * If we have only a time delay, then we'll sleep the right amount
110          * to wake up when a checkpoint is necessary.  If we have a "kbytes"
111          * field set, then we'll check every 30 seconds.
112          */
113         rval = 0;
114         seconds = kbytes != 0 ? 30 : minutes * 60;
115         while (!interrupted) {
116                 (void)__db_sleep(seconds, 0);
117
118                 if (verbose) {
119                         (void)time(&now);
120                         printf("checkpoint: %s", ctime(&now));
121                 }
122                 rval = txn_checkpoint(dbenv->tx_info, kbytes, minutes);
123                 if (rval < 0)
124                         break;
125
126                 while (rval > 0) {
127                         if (verbose)
128                                 __db_err(dbenv,
129                                     "checkpoint did not finish, retrying");
130                         (void)__db_sleep(2, 0);
131                         rval = txn_checkpoint(dbenv->tx_info, 0, 0);
132                 }
133                 if (rval < 0)
134                         break;
135         }
136
137         if (logfile != NULL && logpid(logfile, 0))
138                 rval = 1;
139
140         if (interrupted) {
141                 (void)signal(interrupted, SIG_DFL);
142                 (void)raise(interrupted);
143                 /* NOTREACHED */
144         }
145
146         return (db_appexit(dbenv) || rval ? 1 : 0);
147 }
148
149 /*
150  * db_init --
151  *      Initialize the environment.
152  */
153 DB_ENV *
154 db_init(home)
155         char *home;
156 {
157         DB_ENV *dbenv;
158
159         if ((dbenv = (DB_ENV *)calloc(sizeof(DB_ENV), 1)) == NULL) {
160                 errno = ENOMEM;
161                 err(1, NULL);
162         }
163         dbenv->db_errfile = stderr;
164         dbenv->db_errpfx = progname;
165
166         if ((errno = db_appinit(home, NULL, dbenv,
167            DB_INIT_LOG | DB_INIT_TXN | DB_INIT_MPOOL | DB_USE_ENVIRON)) != 0)
168                 err(1, "db_appinit");
169
170         if (memp_register(dbenv->mp_info,
171             DB_FTYPE_BTREE, __bam_pgin, __bam_pgout) ||
172             memp_register(dbenv->mp_info,
173             DB_FTYPE_HASH, __ham_pgin, __ham_pgout)) {
174                 (void)db_appexit(dbenv);
175                 errx(1,
176                     "db_appinit: failed to register access method functions");
177         }
178
179         siginit();
180
181         return (dbenv);
182 }
183
184 /*
185  * logpid --
186  *      Log that we're running.
187  */
188 int
189 logpid(fname, is_open)
190         char *fname;
191         int is_open;
192 {
193         FILE *fp;
194         time_t now;
195
196         if (is_open) {
197                 if ((fp = fopen(fname, "w")) == NULL) {
198                         warn("%s", fname);
199                         return (1);
200                 }
201                 (void)time(&now);
202                 fprintf(fp,
203                     "%s: %lu %s", progname, (u_long)getpid(), ctime(&now));
204                 fclose(fp);
205         } else
206                 (void)remove(fname);
207         return (0);
208 }
209
210 /*
211  * siginit --
212  *      Initialize the set of signals for which we want to clean up.
213  *      Generally, we try not to leave the shared regions locked if
214  *      we can.
215  */
216 void
217 siginit()
218 {
219 #ifdef SIGHUP
220         (void)signal(SIGHUP, onint);
221 #endif
222         (void)signal(SIGINT, onint);
223 #ifdef SIGKILL
224         (void)signal(SIGKILL, onint);
225 #endif
226         (void)signal(SIGTERM, onint);
227 }
228
229 /*
230  * oninit --
231  *      Interrupt signal handler.
232  */
233 void
234 onint(signo)
235         int signo;
236 {
237         if ((interrupted = signo) == 0)
238                 interrupted = SIGINT;
239 }
240
241 void
242 usage()
243 {
244         (void)fprintf(stderr,
245     "usage: db_checkpoint [-v] [-h home] [-k kbytes] [-L file] [-p min]\n");
246         exit(1);
247 }