removed or optionalized verbose/debugging messages
[minix3.git] / servers / rs / main.c
blob07b1d72249ef5bf003514e55b41d8ad01d561ee5
1 /* Reincarnation Server. This servers starts new system services and detects
2 * they are exiting. In case of errors, system services can be restarted.
3 * The RS server periodically checks the status of all registered services
4 * services to see whether they are still alive. The system services are
5 * expected to periodically send a heartbeat message.
6 *
7 * Created:
8 * Jul 22, 2005 by Jorrit N. Herder
9 */
10 #include "inc.h"
11 #include <minix/dmap.h>
12 #include <minix/endpoint.h>
13 #include "../../kernel/const.h"
14 #include "../../kernel/type.h"
16 /* Declare some local functions. */
17 FORWARD _PROTOTYPE(void init_server, (void) );
18 FORWARD _PROTOTYPE(void sig_handler, (void) );
19 FORWARD _PROTOTYPE(void get_work, (message *m) );
20 FORWARD _PROTOTYPE(void reply, (int whom, message *m_out) );
22 /* Data buffers to retrieve info during initialization. */
23 PRIVATE struct boot_image image[NR_BOOT_PROCS];
24 PUBLIC struct dmap dmap[NR_DEVICES];
26 int rs_verbose = 0;
28 /*===========================================================================*
29 * main *
30 *===========================================================================*/
31 PUBLIC int main(void)
33 /* This is the main routine of this service. The main loop consists of
34 * three major activities: getting new work, processing the work, and
35 * sending the reply. The loop never terminates, unless a panic occurs.
37 message m; /* request message */
38 int call_nr, who_e,who_p; /* call number and caller */
39 int result; /* result to return */
40 sigset_t sigset; /* system signal set */
41 int s;
43 /* Initialize the server, then go to work. */
44 init_server();
46 /* Main loop - get work and do it, forever. */
47 while (TRUE) {
49 /* Wait for request message. */
50 get_work(&m);
51 who_e = m.m_source;
52 who_p = _ENDPOINT_P(who_e);
53 if(who_p < -NR_TASKS || who_p >= NR_PROCS)
54 panic("RS","message from bogus source", who_e);
56 call_nr = m.m_type;
58 /* Now determine what to do. Three types of requests are expected:
59 * - Heartbeat messages (notifications from registered system services)
60 * - System notifications (POSIX signals or synchronous alarm)
61 * - User requests (control messages to manage system services)
64 /* Notification messages are control messages and do not need a reply.
65 * These include heartbeat messages and system notifications.
67 if (m.m_type & NOTIFY_MESSAGE) {
68 switch (call_nr) {
69 case SYN_ALARM:
70 do_period(&m); /* check drivers status */
71 continue;
72 case PROC_EVENT:
73 sig_handler();
74 continue;
75 default: /* heartbeat notification */
76 if (rproc_ptr[who_p] != NULL) /* mark heartbeat time */
77 rproc_ptr[who_p]->r_alive_tm = m.NOTIFY_TIMESTAMP;
81 /* If this is not a notification message, it is a normal request.
82 * Handle the request and send a reply to the caller.
84 else {
85 switch(call_nr) {
86 case RS_UP: result = do_up(&m, FALSE, 0); break;
87 case RS_UP_COPY: result = do_up(&m, TRUE, 0); break;
88 case RS_START: result = do_start(&m); break;
89 case RS_DOWN: result = do_down(&m); break;
90 case RS_REFRESH: result = do_refresh(&m); break;
91 case RS_RESTART: result = do_restart(&m); break;
92 case RS_SHUTDOWN: result = do_shutdown(&m); break;
93 case GETSYSINFO: result = do_getsysinfo(&m); break;
94 default:
95 printf("Warning, RS got unexpected request %d from %d\n",
96 m.m_type, m.m_source);
97 result = EINVAL;
100 /* Finally send reply message, unless disabled. */
101 if (result != EDONTREPLY) {
102 m.m_type = result;
103 reply(who_e, &m);
110 /*===========================================================================*
111 * init_server *
112 *===========================================================================*/
113 PRIVATE void init_server(void)
115 /* Initialize the reincarnation server. */
116 struct sigaction sa;
117 struct boot_image *ip;
118 int s,t;
120 /* Install signal handlers. Ask PM to transform signal into message. */
121 sa.sa_handler = SIG_MESS;
122 sigemptyset(&sa.sa_mask);
123 sa.sa_flags = 0;
124 if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno);
125 if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno);
127 /* Initialize the system process table. Use the boot image from the kernel
128 * and the device map from the FS to gather all needed information.
130 if ((s = sys_getimage(image)) != OK)
131 panic("RS","warning: couldn't get copy of image table", s);
132 if ((s = getsysinfo(FS_PROC_NR, SI_DMAP_TAB, dmap)) < 0)
133 panic("RS","warning: couldn't get copy of dmap table", errno);
135 #if 0
136 /* Now initialize the table with the processes in the system image.
137 * Prepend /sbin/ to the binaries so that we can actually find them.
139 for (s=0; s< NR_BOOT_PROCS; s++) {
140 ip = &image[s];
141 if (ip->proc_nr >= 0) {
142 rproc[s].r_flags = RS_IN_USE;
143 rproc[s].r_proc_nr_e = ip->endpoint;
144 rproc[s].r_pid = getnpid(ip->proc_nr);
145 for(t=0; t< NR_DEVICES; t++)
146 if (dmap[t].dmap_driver == ip->proc_nr)
147 rproc[s].r_dev_nr = t;
148 strcpy(rproc[s].r_cmd, "/sbin/");
149 strcpy(rproc[s].r_cmd+6, ip->proc_name);
150 rproc[s].r_argc = 1;
151 rproc[s].r_argv[0] = rproc[s].r_cmd;
152 rproc[s].r_argv[1] = NULL;
155 #endif
157 /* Set alarm to periodically check driver status. */
158 if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
159 panic("RS", "couldn't set alarm", s);
161 /* See if we run in verbose mode. */
162 env_parse("rs_verbose", "d", 0, &rs_verbose, 0, 1);
165 /*===========================================================================*
166 * sig_handler *
167 *===========================================================================*/
168 PRIVATE void sig_handler()
170 sigset_t sigset;
171 int sig;
173 /* Try to obtain signal set from PM. */
174 if (getsigset(&sigset) != 0) return;
176 /* Check for known signals. */
177 if (sigismember(&sigset, SIGCHLD)) do_exit(NULL);
178 if (sigismember(&sigset, SIGTERM)) do_shutdown(NULL);
181 /*===========================================================================*
182 * get_work *
183 *===========================================================================*/
184 PRIVATE void get_work(m_in)
185 message *m_in; /* pointer to message */
187 int s; /* receive status */
188 if (OK != (s=receive(ANY, m_in))) /* wait for message */
189 panic("RS","receive failed", s);
193 /*===========================================================================*
194 * reply *
195 *===========================================================================*/
196 PRIVATE void reply(who, m_out)
197 int who; /* replyee */
198 message *m_out; /* reply message */
200 /*message m_out;*/ /* reply message */
201 int s; /* send status */
203 /*m_out.m_type = result;*/ /* build reply message */
204 if (OK != (s=send(who, m_out))) /* send the message */
205 panic("RS", "unable to send reply", s);