nmdb: Add an option to save the pidfile
[nmdb.git] / nmdb / main.c
blobe7841451c38463fa0c4813717d4563fcb8d1c335
2 #include <stdio.h> /* printf() */
3 #include <unistd.h> /* malloc(), fork() and getopt() */
4 #include <stdlib.h> /* atoi() */
5 #include <sys/types.h> /* for pid_t */
6 #include <string.h> /* for strcpy() and strlen() */
7 #include <pthread.h> /* for pthread_t */
9 #include "cache.h"
10 #include "net.h"
11 #include "dbloop.h"
12 #include "common.h"
13 #include "net-const.h"
14 #include "log.h"
15 #include "stats.h"
16 #include "be.h"
18 #define DEFDBNAME "database"
21 /* Define the common structures that are used throughout the whole server. */
22 struct settings settings;
23 struct stats stats;
24 struct cache *cache_table;
25 struct queue *op_queue;
28 static void help(void) {
29 char h[] = \
30 "nmdb [options]\n"
31 "\n"
32 " -b backend backend to use (" DEFAULT_BE_NAME ")\n"
33 " -d dbpath database path ('database' by default)\n"
34 " -l lower TIPC lower port number (10)\n"
35 " -L upper TIPC upper port number (= lower)\n"
36 " -t port TCP listening port (26010)\n"
37 " -T addr TCP listening address (all local addresses)\n"
38 " -u port UDP listening port (26010)\n"
39 " -U addr UDP listening address (all local addresses)\n"
40 " -s port SCTP listening port (26010)\n"
41 " -S addr SCTP listening address (all local addresses)\n"
42 " -c nobj max. number of objects to be cached, in thousands (128)\n"
43 " -o fname log to the given file (stdout).\n"
44 " -i pidfile file to write the PID to (none).\n"
45 " -f don't fork and stay in the foreground\n"
46 " -p enable passive mode, for redundancy purposes (read docs.)\n"
47 " -r read-only mode\n"
48 " -h show this help\n"
49 "\n"
50 "Available backends: " SUPPORTED_BE "\n"
51 "\n"
52 "Please report bugs to Alberto Bertogli (albertito@blitiri.com.ar)\n"
53 "\n";
54 printf("%s", h);
58 static int load_settings(int argc, char **argv)
60 int c;
62 settings.tipc_lower = -1;
63 settings.tipc_upper = -1;
64 settings.tcp_addr = NULL;
65 settings.tcp_port = -1;
66 settings.udp_addr = NULL;
67 settings.udp_port = -1;
68 settings.sctp_addr = NULL;
69 settings.sctp_port = -1;
70 settings.numobjs = -1;
71 settings.foreground = 0;
72 settings.passive = 0;
73 settings.read_only = 0;
74 settings.logfname = "-";
75 settings.pidfile = NULL;
76 settings.backend = DEFAULT_BE;
78 settings.dbname = malloc(strlen(DEFDBNAME) + 1);
79 strcpy(settings.dbname, DEFDBNAME);
81 while ((c = getopt(argc, argv,
82 "b:d:l:L:t:T:u:U:s:S:c:o:i:fprh?")) != -1) {
83 switch(c) {
84 case 'b':
85 settings.backend = be_type_from_str(optarg);
86 break;
87 case 'd':
88 free(settings.dbname);
89 settings.dbname = malloc(strlen(optarg) + 1);
90 strcpy(settings.dbname, optarg);
91 break;
93 case 'l':
94 settings.tipc_lower = atoi(optarg);
95 break;
96 case 'L':
97 settings.tipc_upper = atoi(optarg);
98 break;
100 case 't':
101 settings.tcp_port = atoi(optarg);
102 break;
103 case 'T':
104 settings.tcp_addr = optarg;
105 break;
107 case 'u':
108 settings.udp_port = atoi(optarg);
109 break;
110 case 'U':
111 settings.udp_addr = optarg;
112 break;
114 case 's':
115 settings.sctp_port = atoi(optarg);
116 break;
117 case 'S':
118 settings.sctp_addr = optarg;
119 break;
121 case 'c':
122 settings.numobjs = atoi(optarg) * 1024;
123 break;
125 case 'o':
126 settings.logfname = malloc(strlen(optarg) + 1);
127 strcpy(settings.logfname, optarg);
128 break;
130 case 'i':
131 settings.pidfile = malloc(strlen(optarg) + 1);
132 strcpy(settings.pidfile, optarg);
133 break;
135 case 'f':
136 settings.foreground = 1;
137 break;
138 case 'p':
139 settings.passive = 1;
140 break;
141 case 'r':
142 settings.read_only = 1;
143 break;
145 case 'h':
146 case '?':
147 help();
148 return 0;
149 default:
150 printf("Unknown parameter '%c'\n", c);
151 return 0;
155 if (settings.tipc_lower == -1)
156 settings.tipc_lower = TIPC_SERVER_INST;
157 if (settings.tipc_upper == -1)
158 settings.tipc_upper = settings.tipc_lower;
159 if (settings.tcp_addr == NULL)
160 settings.tcp_addr = TCP_SERVER_ADDR;
161 if (settings.tcp_port == -1)
162 settings.tcp_port = TCP_SERVER_PORT;
163 if (settings.udp_addr == NULL)
164 settings.udp_addr = UDP_SERVER_ADDR;
165 if (settings.udp_port == -1)
166 settings.udp_port = UDP_SERVER_PORT;
167 if (settings.sctp_addr == NULL)
168 settings.sctp_addr = SCTP_SERVER_ADDR;
169 if (settings.sctp_port == -1)
170 settings.sctp_port = SCTP_SERVER_PORT;
171 if (settings.numobjs == -1)
172 settings.numobjs = 128 * 1024;
174 if (settings.backend == BE_UNKNOWN) {
175 printf("Error: unknown backend\n");
176 return 0;
177 } else if (settings.backend == BE_UNSUPPORTED) {
178 printf("Error: unsupported backend\n");
179 return 0;
182 return 1;
186 int main(int argc, char **argv)
188 struct cache *cd;
189 struct queue *q;
190 struct db_conn *db;
191 pid_t pid;
192 pthread_t *dbthread;
194 if (!load_settings(argc, argv))
195 return 1;
197 if (!log_init()) {
198 perror("Error opening log file");
199 return 1;
202 stats_init(&stats);
204 cd = cache_create(settings.numobjs, 0);
205 if (cd == NULL) {
206 errlog("Error creating cache");
207 return 1;
209 cache_table = cd;
211 q = queue_create();
212 if (q == NULL) {
213 errlog("Error creating queue");
214 return 1;
216 op_queue = q;
218 db = db_open(settings.backend, settings.dbname, 0);
219 if (db == NULL) {
220 errlog("Error opening DB");
221 return 1;
223 wlog("Opened database \"%s\" with %s backend\n", settings.dbname,
224 be_str_from_type(settings.backend));
226 if (!settings.foreground) {
227 pid = fork();
228 if (pid > 0) {
229 /* parent exits */
230 return 0;
231 } else if (pid < 0) {
232 errlog("Error in fork()");
233 return 1;
236 close(0);
237 setsid();
240 wlog("Starting nmdb\n");
242 write_pid();
244 dbthread = db_loop_start(db);
246 net_loop();
248 db_loop_stop(dbthread);
250 db->close(db);
252 queue_free(q);
254 cache_free(cd);
256 unlink(settings.pidfile);
258 return 0;