]> rtime.felk.cvut.cz Git - frescor/forb.git/blob - src/forbrun/forbrun.c
forb: Split forb_port_destroy() to stop and destroy phases
[frescor/forb.git] / src / forbrun / forbrun.c
1 #define WITH_C99                /* For ul_gsa.h iterators */
2 #include <getopt.h>
3 #include <forb.h>
4 #include <error.h>
5 #include <errno.h>
6 #include <stdio.h>
7 #include <ul_log.h>
8 #include <ul_logreg.h>
9 #include <stdbool.h>
10 #include <dlfcn.h>
11 #include <forb/forb-internal.h>
12 #include <pthread.h>
13 #include <forb/server_id.h>
14
15 static struct option long_opts[] = {
16     { "daemon",   optional_argument, NULL, 'd' },
17     { "id",       required_argument, NULL, 'i' },
18     { "loglevel", required_argument, NULL, 'l' },
19     { "port",     required_argument, NULL, 'p' },
20     { "serverid", required_argument, NULL, 's' },
21     { 0, 0, 0, 0}
22 };
23
24 static void
25 usage(void)
26 {
27         printf("usage: forbrun [ options ] -- <forb-server>.so [ options for forb_main() ] [-- ...]\n");
28         printf("  -d, --daemon [pid-file]   go to background after initialization of servers\n");
29         printf("  -i, --id <textual orb id>\n");
30         printf("  -l, --loglevel <number>|<domain>=<number>,...\n");
31         printf("  -p, --port <number>       listen on a fixed port number\n");
32         printf("  -s, --serverid <serverid> fixed server id of this server\n");
33 }
34
35 int print_log_domain(ul_log_domain_t *domain, void *context)
36 {
37         printf("%s = %d\n", domain->name, domain->level);
38         return 0;
39 }
40
41 struct forb_main_data {
42         char *filename;
43         forb_orb orb;
44         int (*forb_main)(forb_orb orb, int argc, char *argv[]);
45         int argc;
46         char **argv;
47 };
48
49 void *forb_main_thread(void *arg)
50 {
51         struct forb_main_data *data = arg;
52         int ret;
53         optind = 1;
54         ret = data->forb_main(data->orb, data->argc, data->argv);
55         free(data);
56         exit(ret);
57         return NULL;
58 }
59
60 int main(int argc, char *argv[])
61 {
62         unsigned libs_loaded_cnt = 0;
63         forb_orb orb;
64         bool opt_daemon = false;
65         char *opt_pidfile = NULL;
66         int i, ret;
67         forb_server_id *server_id;
68         forb_init_attr_t attr = {
69                 .orb_id = "",
70                 .peer_discovery_callback = NULL, /* TODO */
71                 .peer_dead_callback = NULL,      /* TODO */
72                 .fixed_tcp_port = 0,
73 #ifdef CONFIG_FORB_PROTO_INET_DEFAULT           
74                 .fixed_server_id = 0, /* TODO */
75                 .redistribute_hellos = false , /* TODO */
76 #endif
77         };
78         int  opt;
79
80         while ((opt = getopt_long(argc, argv, "d::hi:l:p:s:", &long_opts[0], NULL)) != EOF) {
81                 switch (opt) {
82                         case 'l':
83                                 if (*optarg == '?') {
84                                         ul_logreg_for_each_domain(print_log_domain, NULL);
85                                         exit(0);
86                                 }
87                                 {
88                                         ret = ul_log_domain_arg2levels(optarg);
89                                         if (ret) 
90                                                 error(1, EINVAL, "Error parsing -l argument at char %d\n", ret);
91                                 }
92                                 break;
93                         case 'd':
94                                 opt_daemon = true;
95                                 opt_pidfile = optarg;
96                                 break;
97                         case 'i':
98                                 attr.orb_id = optarg;
99                                 break;
100                         case 'h':
101                         /*default:*/
102                                 usage();
103                                 exit(opt == 'h' ? 0 : 1);
104                                 break;
105                         case 'p':
106                                 attr.fixed_tcp_port = atol(optarg);
107                                 break;
108                         case 's':
109                                 server_id = forb_server_id_from_string(&attr.fixed_server_id, optarg);
110                                 if (!server_id)
111                                         error(1, 0, "Invalid server id: '%s'\n", optarg);
112                                 break;
113                 }
114         }
115
116         if (opt_daemon)
117                 forb_daemon_prepare(opt_pidfile); /* == fork() */
118
119         orb = forb_init(&argc, &argv, &attr);
120         if (!orb) error(1, errno, "FORB initialization failed");
121
122
123 #if CONFIG_FCB_INET && !CONFIG_FORB_PROTO_INET_DEFAULT
124         ret = register_inet_port(orb);
125         if (ret) error(0, errno, "INET port registration failed");
126 #endif
127
128         for (i = optind; i < argc; i++) {
129                 void *handle;
130                 fosa_thread_id_t tid;
131                 struct forb_main_data *data = malloc(sizeof(*data));
132
133                 data->filename = argv[i];
134                 handle = dlopen(data->filename, RTLD_LOCAL|RTLD_LAZY);
135                 if (!handle)
136                         error(1, errno, "dlopen(\"%s\") failed", data->filename);
137                 data->forb_main = dlsym(handle, "forb_main");
138                 if (!data->forb_main)
139                         error(1, errno, "Cannot find forb_main() in %s", data->filename);
140
141                 data->orb = orb;
142                 
143                 // prepare forb_main() parameters
144                 data->argc = 0;
145                 data->argv = &argv[i];
146                 while (i < argc && strcmp(argv[i], "--")) {
147                         i++;
148                         data->argc++;
149                 }
150                 
151                 fosa_thread_create(&tid, NULL, forb_main_thread, data);
152                 libs_loaded_cnt++;
153
154                 ret = forb_wait_for_server_ready(orb);
155                 if (ret)
156                         error(1, errno, "forb_wait_for_server_ready");
157         }
158
159         if (opt_daemon)
160                 forb_daemon_ready();
161
162         /* Allow other threads to continue execution, but exit
163          * ourselves (without exit()ing the whole process. */
164         if (libs_loaded_cnt > 0)
165                 pthread_exit(NULL);     
166
167         return 0;
168 }