Clean-up compiler warnings about ignoring return values
[sliver-openvswitch.git] / ovsdb / ovsdb-server.c
1 /* Copyright (c) 2009 Nicira Networks
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <config.h>
17
18 #include "ovsdb.h"
19
20 #include <errno.h>
21 #include <getopt.h>
22 #include <signal.h>
23 #include <unistd.h>
24
25 #include "command-line.h"
26 #include "daemon.h"
27 #include "fault.h"
28 #include "file.h"
29 #include "json.h"
30 #include "jsonrpc.h"
31 #include "jsonrpc-server.h"
32 #include "leak-checker.h"
33 #include "list.h"
34 #include "ovsdb-error.h"
35 #include "poll-loop.h"
36 #include "process.h"
37 #include "stream.h"
38 #include "svec.h"
39 #include "timeval.h"
40 #include "trigger.h"
41 #include "util.h"
42 #include "unixctl.h"
43
44 #include "vlog.h"
45 #define THIS_MODULE VLM_ovsdb_server
46
47 static unixctl_cb_func ovsdb_server_exit;
48
49 static void parse_options(int argc, char *argv[], char **file_namep,
50                           struct svec *active, struct svec *passive,
51                           char **unixctl_pathp);
52 static void usage(void) NO_RETURN;
53
54 int
55 main(int argc, char *argv[])
56 {
57     char *unixctl_path = NULL;
58     struct unixctl_server *unixctl;
59     struct ovsdb_jsonrpc_server *jsonrpc;
60     struct svec active, passive;
61     struct pstream **listeners;
62     struct ovsdb_error *error;
63     struct ovsdb *db;
64     const char *name;
65     char *file_name;
66     bool do_chdir;
67     bool exiting;
68     int retval;
69     size_t i;
70
71     set_program_name(argv[0]);
72     register_fault_handlers();
73     time_init();
74     vlog_init();
75     signal(SIGPIPE, SIG_IGN);
76     process_init();
77
78     parse_options(argc, argv, &file_name, &active, &passive, &unixctl_path);
79
80     /* Open all the passive sockets before detaching, to avoid race with
81      * processes that start up later. */
82     listeners = xmalloc(passive.n * sizeof *listeners);
83     for (i = 0; i < passive.n; i++) {
84         int error;
85
86         error = pstream_open(passive.names[i], &listeners[i]);
87         if (error) {
88             ovs_fatal(error, "failed to listen on \"%s\"", passive.names[i]);
89         }
90     }
91
92     if (get_detach() && is_chdir_enabled()) {
93         /* We need to skip chdir("/") in daemonize() and do it later, because
94          * we need to open the database and possible set up up Unix domain
95          * sockets in the current working directory after we daemonize.  We
96          * can't open the database before we daemonize because file locks
97          * aren't inherited by child processes.  */
98         do_chdir = true;
99         set_no_chdir();
100     } else {
101         do_chdir = false;
102     }
103     die_if_already_running();
104     daemonize();
105
106     error = ovsdb_file_open(file_name, false, &db);
107     if (error) {
108         ovs_fatal(0, "%s", ovsdb_error_to_string(error));
109     }
110
111     jsonrpc = ovsdb_jsonrpc_server_create(db);
112     SVEC_FOR_EACH (i, name, &active) {
113         ovsdb_jsonrpc_server_connect(jsonrpc, name);
114     }
115     for (i = 0; i < passive.n; i++) {
116         ovsdb_jsonrpc_server_listen(jsonrpc, listeners[i]);
117     }
118     svec_destroy(&active);
119     svec_destroy(&passive);
120
121     retval = unixctl_server_create(unixctl_path, &unixctl);
122     if (retval) {
123         ovs_fatal(retval, "could not listen for control connections");
124     }
125
126     unixctl_command_register("exit", ovsdb_server_exit, &exiting);
127
128     if (do_chdir) {
129         ignore(chdir("/"));
130     }
131
132     exiting = false;
133     while (!exiting) {
134         ovsdb_jsonrpc_server_run(jsonrpc);
135         unixctl_server_run(unixctl);
136         ovsdb_trigger_run(db, time_msec());
137
138         ovsdb_jsonrpc_server_wait(jsonrpc);
139         unixctl_server_wait(unixctl);
140         ovsdb_trigger_wait(db, time_msec());
141         poll_block();
142     }
143
144     return 0;
145 }
146
147 static void
148 ovsdb_server_exit(struct unixctl_conn *conn, const char *args UNUSED,
149                   void *exiting_)
150 {
151     bool *exiting = exiting_;
152     *exiting = true;
153     unixctl_command_reply(conn, 200, NULL);
154 }
155
156 static void
157 parse_options(int argc, char *argv[], char **file_namep,
158               struct svec *active, struct svec *passive,
159               char **unixctl_pathp)
160 {
161     enum {
162         OPT_DUMMY = UCHAR_MAX + 1,
163         OPT_CONNECT,
164         OPT_LISTEN,
165         OPT_UNIXCTL,
166         VLOG_OPTION_ENUMS,
167         LEAK_CHECKER_OPTION_ENUMS
168     };
169     static struct option long_options[] = {
170         {"connect",     required_argument, 0, OPT_CONNECT},
171         {"listen",      required_argument, 0, OPT_LISTEN},
172         {"unixctl",     required_argument, 0, OPT_UNIXCTL},
173         {"help",        no_argument, 0, 'h'},
174         {"version",     no_argument, 0, 'V'},
175         DAEMON_LONG_OPTIONS,
176         VLOG_LONG_OPTIONS,
177         LEAK_CHECKER_LONG_OPTIONS,
178         {0, 0, 0, 0},
179     };
180     char *short_options = long_options_to_short_options(long_options);
181
182     svec_init(active);
183     svec_init(passive);
184     for (;;) {
185         int c;
186
187         c = getopt_long(argc, argv, short_options, long_options, NULL);
188         if (c == -1) {
189             break;
190         }
191
192         switch (c) {
193         case OPT_CONNECT:
194             svec_add(active, optarg);
195             break;
196
197         case OPT_LISTEN:
198             svec_add(passive, optarg);
199             break;
200
201         case OPT_UNIXCTL:
202             *unixctl_pathp = optarg;
203             break;
204
205         case 'h':
206             usage();
207
208         case 'V':
209             OVS_PRINT_VERSION(0, 0);
210             exit(EXIT_SUCCESS);
211
212         VLOG_OPTION_HANDLERS
213         DAEMON_OPTION_HANDLERS
214         LEAK_CHECKER_OPTION_HANDLERS
215
216         case '?':
217             exit(EXIT_FAILURE);
218
219         default:
220             abort();
221         }
222     }
223     free(short_options);
224
225     argc -= optind;
226     argv += optind;
227
228     if (argc != 1) {
229         ovs_fatal(0, "database file is only non-option argument; "
230                 "use --help for usage");
231     }
232
233     *file_namep = argv[0];
234 }
235
236 static void
237 usage(void)
238 {
239     printf("%s: Open vSwitch database server\n"
240            "usage: %s [OPTIONS] DATABASE\n"
241            "where DATABASE is a database file in ovsdb format.\n",
242            program_name, program_name);
243     printf("\nJSON-RPC options (may be specified any number of times):\n"
244            "  --connect=REMOTE        make active connection to REMOTE\n"
245            "  --listen=LOCAL          passively listen on LOCAL\n");
246     stream_usage("JSON-RPC", true, true);
247     daemon_usage();
248     vlog_usage();
249     printf("\nOther options:\n"
250            "  -h, --help              display this help message\n"
251            "  -V, --version           display version information\n");
252     leak_checker_usage();
253     exit(EXIT_SUCCESS);
254 }