main.c

Go to the documentation of this file.
00001 /* Reincarnation Server.  This servers starts new system services and detects
00002  * they are exiting.   In case of errors, system services can be restarted.  
00003  * The RS server periodically checks the status of all registered services
00004  * services to see whether they are still alive.   The system services are 
00005  * expected to periodically send a heartbeat message. 
00006  * 
00007  * Created:
00008  *   Jul 22, 2005       by Jorrit N. Herder
00009  */
00010 #include "inc.h"
00011 #include <minix/dmap.h>
00012 #include <minix/endpoint.h>
00013 #include "../../kernel/const.h"
00014 #include "../../kernel/type.h"
00015 
00016 /* Declare some local functions. */
00017 FORWARD _PROTOTYPE(void init_server, (void)                             );
00018 FORWARD _PROTOTYPE(void sig_handler, (void)                             );
00019 FORWARD _PROTOTYPE(void get_work, (message *m)                          );
00020 FORWARD _PROTOTYPE(void reply, (int whom, int result)                   );
00021 
00022 /* Data buffers to retrieve info during initialization. */
00023 PRIVATE struct boot_image image[NR_BOOT_PROCS];
00024 PUBLIC struct dmap dmap[NR_DEVICES];
00025 
00026 /*===========================================================================*
00027  *                              main                                         *
00028  *===========================================================================*/
00029 PUBLIC int main(void)
00030 {
00031 /* This is the main routine of this service. The main loop consists of 
00032  * three major activities: getting new work, processing the work, and
00033  * sending the reply. The loop never terminates, unless a panic occurs.
00034  */
00035   message m;                                    /* request message */
00036   int call_nr, who_e,who_p;                     /* call number and caller */
00037   int result;                                   /* result to return */
00038   sigset_t sigset;                              /* system signal set */
00039   int s;
00040 
00041   /* Initialize the server, then go to work. */
00042   init_server();        
00043 
00044   /* Main loop - get work and do it, forever. */         
00045   while (TRUE) {              
00046 
00047       /* Wait for request message. */
00048       get_work(&m);
00049       who_e = m.m_source;
00050       who_p = _ENDPOINT_P(who_e);
00051       if(who_p < -NR_TASKS || who_p >= NR_PROCS)
00052         panic("RS","message from bogus source", who_e);
00053 
00054       call_nr = m.m_type;
00055 
00056       /* Now determine what to do.  Three types of requests are expected: 
00057        * - Heartbeat messages (notifications from registered system services)
00058        * - System notifications (POSIX signals or synchronous alarm)
00059        * - User requests (control messages to manage system services)
00060        */
00061 
00062       /* Notification messages are control messages and do not need a reply.
00063        * These include heartbeat messages and system notifications.
00064        */
00065       if (m.m_type & NOTIFY_MESSAGE) {
00066           switch (call_nr) {
00067           case SYN_ALARM:
00068               do_period(&m);                    /* check drivers status */
00069               continue;                         
00070           case PROC_EVENT:
00071               sig_handler();
00072               continue;                         
00073           default:                              /* heartbeat notification */
00074               if (rproc_ptr[who_p] != NULL)     /* mark heartbeat time */ 
00075                   rproc_ptr[who_p]->r_alive_tm = m.NOTIFY_TIMESTAMP;
00076           }
00077       }
00078 
00079       /* If this is not a notification message, it is a normal request. 
00080        * Handle the request and send a reply to the caller. 
00081        */
00082       else {    
00083           switch(call_nr) {
00084           case RS_UP:           result = do_up(&m);             break;
00085           case RS_DOWN:         result = do_down(&m);           break;
00086           case RS_REFRESH:      result = do_refresh(&m);        break;
00087           case RS_RESCUE:       result = do_rescue(&m);         break;
00088           case RS_SHUTDOWN:     result = do_shutdown(&m);       break;
00089           case GETSYSINFO:      result = do_getsysinfo(&m);     break;
00090           default: 
00091               printf("Warning, RS got unexpected request %d from %d\n",
00092                   m.m_type, m.m_source);
00093               result = EINVAL;
00094           }
00095 
00096           /* Finally send reply message, unless disabled. */
00097           if (result != EDONTREPLY) {
00098               reply(who_e, result);
00099           }
00100       }
00101   }
00102 }
00103 
00104 
00105 /*===========================================================================*
00106  *                              init_server                                  *
00107  *===========================================================================*/
00108 PRIVATE void init_server(void)
00109 {
00110 /* Initialize the reincarnation server. */
00111   struct sigaction sa;
00112   struct boot_image *ip;
00113   int s,t;
00114 
00115   /* Install signal handlers. Ask PM to transform signal into message. */
00116   sa.sa_handler = SIG_MESS;
00117   sigemptyset(&sa.sa_mask);
00118   sa.sa_flags = 0;
00119   if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno);
00120   if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno);
00121 
00122   /* Initialize the system process table. Use the boot image from the kernel
00123    * and the device map from the FS to gather all needed information.
00124    */
00125   if ((s = sys_getimage(image)) != OK) 
00126       panic("RS","warning: couldn't get copy of image table", s);
00127   if ((s = getsysinfo(FS_PROC_NR, SI_DMAP_TAB, dmap)) < 0)
00128       panic("RS","warning: couldn't get copy of dmap table", errno);
00129   
00130   /* Now initialize the table with the processes in the system image. 
00131    * Prepend /sbin/ to the binaries so that we can actually find them. 
00132    */
00133   for (s=0; s< NR_BOOT_PROCS; s++) {
00134       ip = &image[s];
00135       if (ip->proc_nr >= 0) {
00136           nr_in_use ++;
00137           rproc[s].r_flags = RS_IN_USE;
00138           rproc[s].r_proc_nr_e = ip->endpoint;
00139           rproc[s].r_pid = getnpid(ip->proc_nr);
00140           for(t=0; t< NR_DEVICES; t++)
00141               if (dmap[t].dmap_driver == ip->proc_nr)
00142                   rproc[s].r_dev_nr = t;
00143           strcpy(rproc[s].r_cmd, "/sbin/");
00144           strcpy(rproc[s].r_cmd+6, ip->proc_name);
00145           rproc[s].r_argc = 1;
00146           rproc[s].r_argv[0] = rproc[s].r_cmd;
00147           rproc[s].r_argv[1] = NULL;
00148       }
00149   }
00150 
00151   /* Set alarm to periodically check driver status. */
00152   if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
00153       panic("RS", "couldn't set alarm", s);
00154 
00155 }
00156 
00157 /*===========================================================================*
00158  *                              sig_handler                                  *
00159  *===========================================================================*/
00160 PRIVATE void sig_handler()
00161 {
00162   sigset_t sigset;
00163   int sig;
00164 
00165   /* Try to obtain signal set from PM. */
00166   if (getsigset(&sigset) != 0) return;
00167 
00168   /* Check for known signals. */
00169   if (sigismember(&sigset, SIGCHLD)) do_exit(NULL);
00170   if (sigismember(&sigset, SIGTERM)) do_shutdown(NULL);
00171 }
00172 
00173 /*===========================================================================*
00174  *                              get_work                                     *
00175  *===========================================================================*/
00176 PRIVATE void get_work(m_in)
00177 message *m_in;                          /* pointer to message */
00178 {
00179     int s;                              /* receive status */
00180     if (OK != (s=receive(ANY, m_in)))   /* wait for message */
00181         panic("RS","receive failed", s);
00182 }
00183 
00184 
00185 /*===========================================================================*
00186  *                              reply                                        *
00187  *===========================================================================*/
00188 PRIVATE void reply(who, result)
00189 int who;                                /* replyee */
00190 int result;                             /* report result */
00191 {
00192     message m_out;                      /* reply message */
00193     int s;                              /* send status */
00194 
00195     m_out.m_type = result;              /* build reply message */
00196     if (OK != (s=send(who, &m_out)))    /* send the message */
00197         panic("RS", "unable to send reply", s);
00198 }
00199 
00200 
00201 

Generated on Fri Apr 14 22:56:41 2006 for minix by  doxygen 1.4.6