Back to index

radiance  4R0+20100331
rholo4.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: rholo4.c,v 3.36 2004/01/01 11:21:55 schorsch Exp $";
00003 #endif
00004 /*
00005  * Holodeck display process communication
00006  */
00007 
00008 #include "rholo.h"
00009 #include "rhdisp.h"
00010 #include "rtprocess.h"
00011 #include <sys/uio.h>
00012 #include <string.h>
00013 
00014 #ifndef HDSUF
00015 #define HDSUF        ".hdi"
00016 #endif
00017 #ifndef SLAVENAME
00018 #define SLAVENAME    "slave"
00019 #endif
00020 
00021 #ifndef FNONBLK
00022 #define FNONBLK             O_NONBLOCK
00023 #endif
00024 
00025 static int    inp_flags;
00026 static SUBPROC       dpd;
00027 static FILE   *dpout;
00028 
00029 static void disp_flush(void);
00030 static void disp_result(int type, int nbytes, char *p);
00031 
00032 
00033 extern void
00034 disp_open(           /* open the named display driver */
00035        char   *dname
00036 )
00037 {
00038        char   buf[sizeof(HDGRID)+512], fd0[8], fd1[8], *cmd[5], *sfn;
00039        int    i, n, len;
00040 
00041        if (!strcmp(dname, SLAVENAME)) {
00042               dpd.r = 0;           /* read from stdin */
00043               dpout = stdout;             /* write to stdout */
00044               dpd.running = 0; /* we're the slave procees */
00045        } else {
00046                                    /* get full display program name */
00047 #ifdef DEVPATH
00048               sprintf(buf, "%s/%s%s", DEVPATH, dname, HDSUF);
00049 #else
00050               sprintf(buf, "dev/%s%s", dname, HDSUF);
00051 #endif
00052                                    /* dup stdin and stdout */
00053               if (readinp)
00054                      sprintf(fd0, "%d", dup(0));
00055               else
00056                      strcpy(fd0, "-1");
00057               sprintf(fd1, "%d", dup(1));
00058                                    /* start the display process */
00059               cmd[0] = buf;
00060               cmd[1] = froot; cmd[2] = fd1; cmd[3] = fd0;
00061               cmd[4] = NULL;
00062               i = open_process(&dpd, cmd);
00063               if (i <= 0)
00064                      error(USER, "cannot start display process");
00065               if ((dpout = fdopen(dpd.w, "w")) == NULL)
00066                      error(SYSTEM, "problem opening display pipe");
00067                                    /* close dup'ed stdin and stdout */
00068               if (readinp)
00069                      close(atoi(fd0));
00070               close(atoi(fd1));
00071        }
00072        dpd.w = -1;          /* causes ignored error in close_process() */
00073        inp_flags = 0;
00074                             /* check if outside */
00075        if (vdef(OBSTRUCTIONS) && vbool(OBSTRUCTIONS))
00076               disp_result(DS_OUTSECT, 0, NULL);
00077                             /* send eye separation if specified */
00078        if (vdef(EYESEP)) {
00079               sprintf(buf, "%.9e", vflt(EYESEP));
00080               disp_result(DS_EYESEP, strlen(buf)+1, buf);
00081        }
00082                             /* write out hologram grids & octrees */
00083        for (i = 0; hdlist[i] != NULL; i++) {
00084               memcpy(buf, (void *)hdlist[i], sizeof(HDGRID));
00085               len = sizeof(HDGRID);
00086               n = vdef(GEOMETRY);
00087               sfn = i<n ? nvalue(GEOMETRY,i) :
00088                             n ? nvalue(GEOMETRY,n-1) : vval(OCTREE);
00089               strcpy(buf+len, sfn);
00090               len += strlen(sfn) + 1;
00091               n = vdef(PORTS);
00092               sfn = i<n ? nvalue(PORTS,i) : n ? nvalue(PORTS,n-1) : "";
00093               strcpy(buf+len, sfn);
00094               len += strlen(sfn) + 1;
00095               disp_result(DS_ADDHOLO, len, buf);
00096        }
00097        disp_flush();
00098 }
00099 
00100 
00101 extern void
00102 disp_packet(                /* display a packet */
00103        register PACKHEAD    *p
00104 )
00105 {
00106        disp_result(DS_BUNDLE, packsiz(p->nr), (char *)p);
00107 }
00108 
00109 
00110 extern int
00111 disp_check(          /* check display process */
00112        int    block
00113 )
00114 {
00115        MSGHEAD       msg;
00116        int    n;
00117        char   *buf = NULL;
00118 
00119        if (dpout == NULL)
00120               return(-1);
00121                                    /* flush display output */
00122        disp_flush();
00123                                    /* check read blocking */
00124        if (block != (inp_flags == 0)) {
00125               inp_flags = block ? 0 : FNONBLK;
00126               if (fcntl(dpd.r, F_SETFL, inp_flags) < 0)
00127                      goto fcntlerr;
00128        }
00129                                    /* read message header */
00130        n = read(dpd.r, (char *)&msg, sizeof(MSGHEAD));
00131        if (n != sizeof(MSGHEAD)) {
00132               if (n >= 0) {
00133                      dpout = NULL;
00134                      error(USER, "display process died");
00135               }
00136               if ((errno != EAGAIN) & (errno != EINTR))
00137                      goto readerr;
00138               return(2);           /* acceptable failure */
00139        }
00140        if (msg.nbytes) {           /* get the message body */
00141               if (msg.nbytes < 0)
00142                      error(INTERNAL, "anti-message from display process");
00143               buf = (char *)malloc(msg.nbytes);
00144               if (buf == NULL)
00145                      error(SYSTEM, "out of memory in disp_check");
00146               if (inp_flags != 0 && fcntl(dpd.r, F_SETFL, inp_flags=0) < 0)
00147                      goto fcntlerr;
00148               if (readbuf(dpd.r, buf, msg.nbytes) != msg.nbytes)
00149                      goto readerr;
00150        }
00151        switch (msg.type) {         /* take appropriate action */
00152        case DR_BUNDLE:             /* new bundle to calculate */
00153               if (msg.nbytes != sizeof(PACKHEAD))
00154                      error(INTERNAL, "bad DR_BUNDLE from display process");
00155               bundle_set(BS_ADD, (PACKHEAD *)buf, 1);
00156               break;
00157        case DR_NEWSET:             /* new calculation set */
00158               if (msg.nbytes % sizeof(PACKHEAD))
00159                      error(INTERNAL, "bad DR_NEWSET from display process");
00160               if (msg.nbytes)
00161                      disp_result(DS_STARTIMM, 0, NULL);
00162               bundle_set(BS_NEW, (PACKHEAD *)buf, msg.nbytes/sizeof(PACKHEAD));
00163               if (msg.nbytes) {
00164                      disp_result(DS_ENDIMM, 0, NULL);
00165                      disp_flush();
00166               }
00167               break;
00168        case DR_ADDSET:             /* add to calculation set */
00169               if (!msg.nbytes)
00170                      break;
00171               if (msg.nbytes % sizeof(PACKHEAD))
00172                      error(INTERNAL, "bad DR_ADDSET from display process");
00173               disp_result(DS_STARTIMM, 0, NULL);
00174               bundle_set(BS_ADD, (PACKHEAD *)buf, msg.nbytes/sizeof(PACKHEAD));
00175               disp_result(DS_ENDIMM, 0, NULL);
00176               disp_flush();
00177               break;
00178        case DR_ADJSET:             /* adjust calculation set members */
00179               if (!msg.nbytes)
00180                      break;
00181               if (msg.nbytes % sizeof(PACKHEAD))
00182                      error(INTERNAL, "bad DR_ADJSET from display process");
00183               disp_result(DS_STARTIMM, 0, NULL);
00184               bundle_set(BS_ADJ, (PACKHEAD *)buf, msg.nbytes/sizeof(PACKHEAD));
00185               disp_result(DS_ENDIMM, 0, NULL);
00186               disp_flush();
00187               break;
00188        case DR_DELSET:             /* delete from calculation set */
00189               if (!msg.nbytes)
00190                      break;
00191               if (msg.nbytes % sizeof(PACKHEAD))
00192                      error(INTERNAL, "bad DR_DELSET from display process");
00193               bundle_set(BS_DEL, (PACKHEAD *)buf, msg.nbytes/sizeof(PACKHEAD));
00194               break;
00195        case DR_VIEWPOINT:   /* set target eye position */
00196               if (msg.nbytes != sizeof(VIEWPOINT))
00197                      error(INTERNAL, "bad DR_VIEWPOINT from display process");
00198               myeye = *((VIEWPOINT *)buf);
00199               break;
00200        case DR_ATTEN:              /* block for priority request */
00201               if (msg.nbytes)
00202                      error(INTERNAL, "bad DR_ATTEN from display process");
00203                                    /* send acknowledgement */
00204               disp_result(DS_ACKNOW, 0, NULL);
00205               return(disp_check(1));      /* block on following request */
00206        case DR_KILL:        /* kill computation process(es) */
00207               if (msg.nbytes)
00208                      error(INTERNAL, "bad DR_KILL from display process");
00209               if (nprocs > 0)
00210                      done_rtrace();
00211               else
00212                      error(WARNING, "no rtrace process to kill");
00213               break;
00214        case DR_RESTART:     /* restart computation process(es) */
00215               if (msg.nbytes)
00216                      error(INTERNAL, "bad DR_RESTART from display process");
00217               if (ncprocs > nprocs)
00218                      new_rtrace();
00219               else if (nprocs > 0)
00220                      error(WARNING, "rtrace already runnning");
00221               else
00222                      error(WARNING, "holodeck not open for writing");
00223               break;
00224        case DR_CLOBBER:     /* clobber holodeck */
00225               if (msg.nbytes)
00226                      error(INTERNAL, "bad DR_CLOBBER from display process");
00227               if ((force <= 0) | (ncprocs <= 0))
00228                      error(WARNING, "request to clobber holodeck denied");
00229               else {
00230                      error(WARNING, "clobbering holodeck contents");
00231                      hdclobber(NULL);
00232               }
00233               break;
00234        case DR_SHUTDOWN:    /* shut down program */
00235               if (msg.nbytes)
00236                      error(INTERNAL, "bad DR_SHUTDOWN from display process");
00237               return(0);           /* zero return signals shutdown */
00238        case DR_NOOP:        /* do nothing */
00239               break;
00240        default:
00241               error(INTERNAL, "unrecognized request from display process");
00242        }
00243        if (msg.nbytes)                    /* clean up */
00244               free(buf);
00245        return(1);                  /* normal return value */
00246 fcntlerr:
00247        error(SYSTEM, "cannot change display blocking mode");
00248 readerr:
00249        error(SYSTEM, "error reading from display process");
00250        return -1; /* pro forma return */
00251 }
00252 
00253 
00254 extern int
00255 disp_close(void)                   /* close our display process */
00256 {
00257        if (dpout == NULL)
00258               return(-1);
00259        myeye.rng = 0;
00260        disp_result(DS_SHUTDOWN, 0, NULL);
00261        fclose(dpout);
00262        dpout = NULL;
00263        return(dpd.running ? close_process(&dpd) : 0);
00264 
00265 }
00266 
00267 
00268 static void
00269 disp_result(  /* queue result message to display process */
00270        int    type,
00271        int    nbytes,
00272        char   *p
00273 )
00274 {
00275        MSGHEAD       msg;
00276                                    /* consistency checks */
00277 #ifdef DEBUG
00278        if (nbytes < 0 || nbytes > 0 & p == NULL)
00279               error(CONSISTENCY, "bad buffer handed to disp_result");
00280 #endif
00281        if (dpout == NULL)
00282               return;
00283        msg.type = type;
00284        msg.nbytes = nbytes;
00285        fwrite((char *)&msg, sizeof(MSGHEAD), 1, dpout);
00286        if (nbytes > 0)
00287               fwrite(p, 1, nbytes, dpout);
00288 }
00289 
00290 
00291 static void
00292 disp_flush(void)                   /* flush output to display */
00293 {
00294        if (fflush(dpout) < 0)
00295               error(SYSTEM, "error writing to the display process");
00296 }