2 * $Id: main.c,v 1.1.4.1 2003-09-09 16:42:20 didg Exp $
4 * Copyright (C) Joerg Lenneis 2003
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
14 #endif /* HAVE_UNISTD_H */
22 #ifdef HAVE_SYS_TYPES_H
23 #include <sys/types.h>
24 #endif /* HAVE_SYS_TYPES_H */
25 #include <sys/param.h>
26 #ifdef HAVE_SYS_STAT_H
28 #endif /* HAVE_SYS_STAT_H */
31 #include <netatalk/endian.h>
32 #include <atalk/cnid_dbd_private.h>
33 #include <atalk/logger.h>
41 #define LOCKFILENAME "lock"
43 static int exit_sig = 0;
46 static void sig_exit(int signo)
53 The dbd_XXX and comm_XXX functions all obey the same protocol for return values:
55 1: Success, if transactions are used commit.
56 0: Failure, but we continue to serve requests. If transactions are used abort/rollback.
57 -1: Fatal error, either from the database or from the socket. Abort the transaction if applicable
58 (which might fail as well) and then exit.
60 We always try to notify the client process about the outcome, the result field
61 of the cnid_dbd_rply structure contains further details.
65 static void block_sigs_onoff(int block)
70 sigaddset(&set, SIGINT);
71 sigaddset(&set, SIGTERM);
73 sigprocmask(SIG_BLOCK, &set, NULL);
75 sigprocmask(SIG_UNBLOCK, &set, NULL);
80 static int loop(struct db_param *dbp)
82 struct cnid_dbd_rqst rqst;
83 struct cnid_dbd_rply rply;
85 time_t now, time_next_flush, time_last_rqst;
87 static char namebuf[MAXPATHLEN + 1];
88 u_int32_t checkp_flags;
92 time_next_flush = now + dbp->flush_interval;
95 checkp_flags = DB_FORCE;
102 if ((cret = comm_rcv(&rqst)) < 0)
107 if (count > dbp->flush_frequency || now > time_next_flush) {
108 #ifdef CNID_BACKEND_DBD_TXN
109 if (dbif_txn_checkpoint(0, 0, checkp_flags) < 0)
116 time_next_flush = now + dbp->flush_interval;
124 if (dbp->idle_timeout && comm_nbe() <= 0 && (now - time_last_rqst) > dbp->idle_timeout)
128 /* We got a request */
129 time_last_rqst = now;
132 #ifdef CNID_BACKEND_DBD_TXN
133 if (dbif_txn_begin() < 0)
135 #endif /* CNID_BACKEND_DBD_TXN */
137 memset(&rply, 0, sizeof(rply));
139 /* ret gets set here */
140 case CNID_DBD_OP_OPEN:
141 case CNID_DBD_OP_CLOSE:
142 /* open/close are noops for now. */
146 case CNID_DBD_OP_ADD:
147 ret = dbd_add(&rqst, &rply);
149 case CNID_DBD_OP_GET:
150 ret = dbd_get(&rqst, &rply);
152 case CNID_DBD_OP_RESOLVE:
153 ret = dbd_resolve(&rqst, &rply);
155 case CNID_DBD_OP_LOOKUP:
156 ret = dbd_lookup(&rqst, &rply);
158 case CNID_DBD_OP_UPDATE:
159 ret = dbd_update(&rqst, &rply);
161 case CNID_DBD_OP_DELETE:
162 ret = dbd_delete(&rqst, &rply);
165 LOG(log_error, logtype_cnid, "loop: unknow op %d", rqst.op);
169 if ((cret = comm_snd(&rply)) < 0 || ret < 0) {
170 #ifdef CNID_BACKEND_DBD_TXN
172 #endif /* CNID_BACKEND_DBD_TXN */
175 #ifdef CNID_BACKEND_DBD_TXN
176 if (ret == 0 || cret == 0) {
177 if (dbif_txn_abort() < 0)
180 if (dbif_txn_commit() < 0)
183 #endif /* CNID_BACKEND_DBD_TXN */
188 int main(int argc, char *argv[])
191 struct db_param *dbp;
198 LOG(log_error, logtype_cnid, "main: not enough arguments");
202 if (chdir(dir) < 0) {
203 LOG(log_error, logtype_cnid, "chdir to %s failed: %s", dir, strerror(errno));
206 if (stat(".", &st) < 0) {
207 LOG(log_error, logtype_cnid, "error in stat for %s: %s", dir, strerror(errno));
211 LOG(log_info, logtype_cnid, "Setting uid/gid to %i/%i", st.st_uid, st.st_gid);
212 if (setegid(st.st_gid) < 0 || seteuid(st.st_uid) < 0) {
213 LOG(log_error, logtype_cnid, "uid/gid: %s", strerror(errno));
217 /* Before we do anything else, check if there is an instance of cnid_dbd
218 running already and silently exit if yes. */
219 if ((lockfd = open(LOCKFILENAME, O_RDONLY | O_CREAT, 0644)) < 0) {
220 LOG(log_error, logtype_cnid, "main: error opening lockfile: %s", strerror(errno));
223 if (flock(lockfd, LOCK_EX | LOCK_NB) < 0) {
224 if (errno == EWOULDBLOCK) {
227 LOG(log_error, logtype_cnid, "main: error in flock: %s", strerror(errno));
231 LOG(log_info, logtype_cnid, "Startup, DB dir %s", dir);
233 sv.sa_handler = sig_exit;
235 sigemptyset(&sv.sa_mask);
236 sigaddset(&sv.sa_mask, SIGINT);
237 sigaddset(&sv.sa_mask, SIGTERM);
238 if (sigaction(SIGINT, &sv, NULL) < 0 || sigaction(SIGTERM, &sv, NULL) < 0) {
239 LOG(log_error, logtype_cnid, "main: sigaction: %s", strerror(errno));
242 sv.sa_handler = SIG_IGN;
243 sigemptyset(&sv.sa_mask);
244 if (sigaction(SIGPIPE, &sv, NULL) < 0) {
245 LOG(log_error, logtype_cnid, "main: sigaction: %s", strerror(errno));
248 /* SIGINT and SIGTERM are always off, unless we get a return code of 0 from
249 comm_rcv (no requests for one second, see above in loop()). That means we
250 only shut down after one second of inactivity. */
252 if ((dbp = db_param_read(dir)) == NULL)
255 if (dbif_open(dbp) < 0) {
259 if (dbd_stamp() < 0) {
263 if (comm_init(dbp) < 0) {
273 if (dbif_close() < 0)
276 flock(lockfd, LOCK_UN);
283 LOG(log_info, logtype_cnid, "main: Exiting on signal %i", exit_sig);
285 LOG(log_info, logtype_cnid, "main: Idle timeout, exiting");