3 * Performs database maintenance tasks
4 * + Transaction checkpoints
6 * + Transaction log removal
11 #include "portable/setproctitle.h"
12 #include "portable/wait.h"
17 #include "inn/innconf.h"
18 #include "inn/messages.h"
22 #include "../storage/ovdb/ovdb.h"
23 #include "../storage/ovdb/ovdb-private.h"
25 #ifndef USE_BERKELEY_DB
27 int main(int argc UNUSED, char **argv UNUSED)
32 #else /* USE_BERKELEY_DB */
34 static int signalled = 0;
35 static void sigfunc(int sig UNUSED)
41 static pid_t deadlockpid = 0;
42 static pid_t checkpointpid = 0;
43 static pid_t logremoverpid = 0;
45 static int putpid(const char *path)
48 int fd = open(path, O_WRONLY|O_TRUNC|O_CREAT, 0664);
50 syswarn("cannot open %s", path);
53 snprintf(buf, sizeof(buf), "%d\n", getpid());
54 if(write(fd, buf, strlen(buf)) < 0) {
55 syswarn("cannot write to %s", path);
63 static void deadlock(void)
66 u_int32_t atype = DB_LOCK_YOUNGEST;
68 if(ovdb_open_berkeleydb(OV_WRITE, 0))
71 setproctitle("deadlock");
74 #if DB_VERSION_MAJOR == 2
75 ret = lock_detect(OVDBenv->lk_info, 0, atype);
76 #elif DB_VERSION_MAJOR == 3
77 ret = lock_detect(OVDBenv, 0, atype, NULL);
79 ret = OVDBenv->lock_detect(OVDBenv, 0, atype, NULL);
82 warn("OVDB: lock_detect: %s", db_strerror(ret));
89 ovdb_close_berkeleydb();
93 static void checkpoint(void)
97 #if DB_VERSION_MAJOR == 2
101 if(ovdb_open_berkeleydb(OV_WRITE, 0))
104 setproctitle("checkpoint");
106 /* Open a database and close it. This is so a necessary initialization
107 gets performed (by the db->open function). */
109 #if DB_VERSION_MAJOR == 2
110 memset(&dbinfo, 0, sizeof dbinfo);
111 ret = db_open("version", DB_BTREE, DB_CREATE, 0666, OVDBenv, &dbinfo, &db);
113 warn("OVDB: checkpoint: db_open failed: %s", db_strerror(ret));
117 ret = db_create(&db, OVDBenv, 0);
119 warn("OVDB: checkpoint: db_create: %s", db_strerror(ret));
122 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
123 ret = db->open(db, NULL, "version", NULL, DB_BTREE, DB_CREATE, 0666);
125 ret = db->open(db, "version", NULL, DB_BTREE, DB_CREATE, 0666);
129 warn("OVDB: checkpoint: version open: %s", db_strerror(ret));
137 #if DB_VERSION_MAJOR == 2
138 ret = txn_checkpoint(OVDBenv->tx_info, 2048, 1);
139 #elif DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0
140 ret = txn_checkpoint(OVDBenv, 2048, 1);
141 #elif DB_VERSION_MAJOR == 3
142 ret = txn_checkpoint(OVDBenv, 2048, 1, 0);
143 #elif DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 1
144 ret = OVDBenv->txn_checkpoint(OVDBenv, 2048, 1, 0);
146 OVDBenv->txn_checkpoint(OVDBenv, 2048, 1, 0);
148 #if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
151 if(ret != 0 && ret != DB_INCOMPLETE) {
152 warn("OVDB: txn_checkpoint: %s", db_strerror(ret));
156 if(ret == DB_INCOMPLETE)
163 ovdb_close_berkeleydb();
167 static void logremover(void)
172 if(ovdb_open_berkeleydb(OV_WRITE, 0))
175 setproctitle("logremover");
178 #if DB_VERSION_MAJOR == 2
179 ret = log_archive(OVDBenv->lg_info, &listp, DB_ARCH_ABS, malloc);
180 #elif DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR <= 2
181 ret = log_archive(OVDBenv, &listp, DB_ARCH_ABS, malloc);
182 #elif DB_VERSION_MAJOR == 3
183 ret = log_archive(OVDBenv, &listp, DB_ARCH_ABS);
185 ret = OVDBenv->log_archive(OVDBenv, &listp, DB_ARCH_ABS);
188 warn("OVDB: log_archive: %s", db_strerror(ret));
193 for(p = listp; *p; p++)
200 ovdb_close_berkeleydb();
204 static int start_process(pid_t *pid, void (*func)(void))
208 switch(child = fork()) {
213 syswarn("cannot fork");
222 static void cleanup(int status)
227 kill(deadlockpid, SIGTERM);
229 kill(checkpointpid, SIGTERM);
231 kill(logremoverpid, SIGTERM);
233 xsignal(SIGINT, SIG_DFL);
234 xsignal(SIGTERM, SIG_DFL);
235 xsignal(SIGHUP, SIG_DFL);
238 waitpid(deadlockpid, &cs, 0);
240 waitpid(checkpointpid, &cs, 0);
242 waitpid(logremoverpid, &cs, 0);
244 unlink(concatpath(innconf->pathrun, OVDB_MONITOR_PIDFILE));
248 static void monitorloop(void)
254 child = waitpid(-1, &cs, WNOHANG);
256 if(WIFSIGNALED(cs)) {
259 if(WEXITSTATUS(cs) == 0)
264 if(child == deadlockpid) {
266 if(restartit && start_process(&deadlockpid, deadlock))
268 } else if(child == checkpointpid) {
270 if(restartit && start_process(&checkpointpid, checkpoint))
272 } else if(child == logremoverpid) {
274 if(restartit && start_process(&logremoverpid, logremover))
286 int main(int argc, char **argv)
290 setproctitle_init(argc, argv);
292 openlog("ovdb_monitor", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG);
293 message_program_name = "ovdb_monitor";
295 if(argc != 2 || strcmp(argv[1], SPACES))
296 die("should be started by ovdb_init");
297 message_handlers_warn(1, message_log_syslog_err);
298 message_handlers_die(1, message_log_syslog_err);
300 if (!innconf_read(NULL))
303 if(strcmp(innconf->ovmethod, "ovdb"))
304 die("ovmethod not set to ovdb in inn.conf");
305 if(!ovdb_check_user())
306 die("command must be run as user " NEWSUSER);
307 if(!ovdb_getlock(OVDB_LOCK_ADMIN))
308 die("cannot lock database");
310 xsignal(SIGINT, sigfunc);
311 xsignal(SIGTERM, sigfunc);
312 xsignal(SIGHUP, sigfunc);
314 pidfile = concatpath(innconf->pathrun, OVDB_MONITOR_PIDFILE);
317 if(start_process(&deadlockpid, deadlock))
319 if(start_process(&checkpointpid, checkpoint))
321 if(start_process(&logremoverpid, logremover))
330 #endif /* USE_BERKELEY_DB */