--- ray/src/util/ranimate.c 1996/01/24 14:31:36 2.8 +++ ray/src/util/ranimate.c 1997/10/31 15:02:43 2.23 @@ -1,4 +1,4 @@ -/* Copyright (c) 1995 Regents of the University of California */ +/* Copyright (c) 1996 Regents of the University of California */ #ifndef lint static char SCCSid[] = "$SunId$ LBL"; @@ -15,6 +15,12 @@ static char SCCSid[] = "$SunId$ LBL"; #include "view.h" #include "vars.h" #include "netproc.h" + /* default remote shell */ +#ifdef _AUX_SOURCE +#define REMSH "remsh" +#else +#define REMSH "rsh" +#endif /* input variables */ #define HOST 0 /* rendering host machine */ #define RENDER 1 /* rendering options */ @@ -38,8 +44,9 @@ static char SCCSid[] = "$SunId$ LBL"; #define DISKSPACE 19 /* how much disk space to use */ #define RESOLUTION 20 /* desired final resolution */ #define EXPOSURE 21 /* how to compute exposure */ +#define RSH 22 /* remote shell script or program */ -int NVARS = 22; /* total number of variables */ +int NVARS = 23; /* total number of variables */ VARIABLE vv[] = { /* variable-value pairs */ {"host", 4, 0, NULL, NULL}, @@ -64,6 +71,7 @@ VARIABLE vv[] = { /* variable-value pairs */ {"DISKSPACE", 3, 0, NULL, fltvalue}, {"RESOLUTION", 3, 0, NULL, onevalue}, {"EXPOSURE", 3, 0, NULL, onevalue}, + {"RSH", 3, 0, NULL, onevalue}, }; #define SFNAME "STATUS" /* status file name */ @@ -84,7 +92,8 @@ int nowarn = 0; /* turn warnings off? */ int silent = 0; /* silent mode? */ int noaction = 0; /* take no action? */ -char rendopt[2048] = ""; /* rendering options */ +char *remsh; /* remote shell program/script */ +char rendopt[2048]; /* rendering options */ char rresopt[32]; /* rendering resolution options */ char fresopt[32]; /* filter resolution options */ int pfiltalways; /* always use pfilt? */ @@ -99,17 +108,18 @@ struct pslot { } *pslot; /* process slots */ int npslots; /* number of process slots */ -int lastpid; /* ID of last completed background process */ -PSERVER *lastpserver; /* last process server used */ - #define phostname(ps) ((ps)->hostname[0] ? (ps)->hostname : astat.host) struct pslot *findpslot(); +PSERVER *lastpserver; /* last process server with error */ + VIEW *getview(); char *getexp(); +extern time_t fdate(), time(); + main(argc, argv) int argc; char *argv[]; @@ -140,6 +150,8 @@ char *argv[]; cfname = argv[i]; /* load variables */ loadvars(cfname); + /* check variables */ + checkvalues(); /* did we get DIRECTORY? */ checkdir(); /* check status */ @@ -166,8 +178,11 @@ char *argv[]; argv[i] = vval(NEXTANIM); /* just change input file */ if (!silent) printargs(argc, argv, stdout); - execvp(progname, argv); /* pass to next */ - quit(1); /* shouldn't return */ + if ((argv[0] = getpath(progname,getenv("PATH"),X_OK)) == NULL) + fprintf(stderr, "%s: command not found\n", progname); + else + execv(progname, argv); + quit(1); } quit(0); userr: @@ -178,13 +193,13 @@ userr: getastat() /* check/set animation status */ { - char buf[256]; + char sfname[256]; FILE *fp; - sprintf(buf, "%s/%s", vval(DIRECTORY), SFNAME); - if ((fp = fopen(buf, "r")) == NULL) { + sprintf(sfname, "%s/%s", vval(DIRECTORY), SFNAME); + if ((fp = fopen(sfname, "r")) == NULL) { if (errno != ENOENT) { - perror(buf); + perror(sfname); return(-1); } astat.rnext = astat.fnext = astat.tnext = 0; @@ -204,8 +219,7 @@ getastat() /* check/set animation status */ goto fmterr; fclose(fp); if (astat.pid != 0) { /* thinks it's still running */ - gethostname(buf, sizeof(buf)); - if (strcmp(buf, astat.host)) { + if (strcmp(myhostname(), astat.host)) { fprintf(stderr, "%s: process %d may still be running on host %s\n", progname, astat.pid, astat.host); @@ -218,19 +232,24 @@ getastat() /* check/set animation status */ } /* assume it is dead */ } - if (strcmp(cfname, astat.cfname) && astat.tnext != 0) { /* other's */ + if (strcmp(cfname, astat.cfname) && astat.pid != 0) { /* other's */ fprintf(stderr, "%s: unfinished job \"%s\"\n", progname, astat.cfname); return(-1); } + /* check control file mods. */ + if (!nowarn && fdate(cfname) > fdate(sfname)) + fprintf(stderr, + "%s: warning - control file modified since last run\n", + progname); setours: /* set our values */ - gethostname(astat.host, sizeof(astat.host)); + strcpy(astat.host, myhostname()); astat.pid = getpid(); strcpy(astat.cfname, cfname); return(0); fmterr: fprintf(stderr, "%s: format error in status file \"%s\"\n", - progname, buf); + progname, sfname); fclose(fp); return(-1); } @@ -282,6 +301,8 @@ checkdir() /* make sure we have our directory */ setdefaults() /* set default values */ { + extern char *atos(); + int decades; char buf[256]; if (vdef(ANIMATE)) { @@ -315,7 +336,9 @@ setdefaults() /* set default values */ quit(1); } if (!vdef(BASENAME)) { - sprintf(buf, "%s/frame%%03d", vval(DIRECTORY)); + decades = (int)log10((double)vint(END)) + 1; + if (decades < 3) decades = 3; + sprintf(buf, "%s/frame%%0%dd", vval(DIRECTORY), decades); vval(BASENAME) = savqstr(buf); vdef(BASENAME)++; } @@ -347,6 +370,17 @@ setdefaults() /* set default values */ vval(DISKSPACE) = "100"; vdef(DISKSPACE)++; } + if (!vdef(RSH)) { + vval(RSH) = REMSH; + vdef(RSH)++; + } + /* locate remote shell program */ + atos(buf, sizeof(buf), vval(RSH)); + if ((remsh = getpath(buf, getenv("PATH"), X_OK)) != NULL) + remsh = savqstr(remsh); + else + remsh = vval(RSH); /* will generate error if used */ + /* append rendering options */ if (vdef(RENDER)) sprintf(rendopt+strlen(rendopt), " %s", vval(RENDER)); @@ -416,28 +450,39 @@ char *rfargs; char combuf[256]; register int i; register char *cp; + char *pippt; /* create rad command */ sprintf(rendopt, " @%s/render.opt", vval(DIRECTORY)); sprintf(combuf, "rad -v 0 -s -e -w %s OPTFILE=%s | egrep '^[ \t]*(NOMATCH", rfargs, rendopt+2); cp = combuf; - while (*cp) cp++; /* match unset variables */ + while (*cp) { + if (*cp == '|') pippt = cp; + cp++; + } /* match unset variables */ for (i = 0; mvar[i] >= 0; i++) if (!vdef(mvar[i])) { *cp++ = '|'; strcpy(cp, vnam(mvar[i])); while (*cp) cp++; + pippt = NULL; } - sprintf(cp, ")[ \t]*=' > %s/radset.var", vval(DIRECTORY)); - cp += 11; /* point to file name */ + if (pippt != NULL) + strcpy(pippt, "> /dev/null"); /* nothing to match */ + else { + sprintf(cp, ")[ \t]*=' > %s/radset.var", vval(DIRECTORY)); + cp += 11; /* point to file name */ + } if (system(combuf)) { fprintf(stderr, "%s: error executing rad command:\n\t%s\n", progname, combuf); quit(1); } - loadvars(cp); /* load variables and remove file */ - unlink(cp); + if (pippt == NULL) { /* load variables and remove file */ + loadvars(cp); + unlink(cp); + } } @@ -452,9 +497,9 @@ animate() /* run animation */ i = sscanf(vval(RESOLUTION), "%d %d %f", &xres, &yres, &pa); mult = vflt(OVERSAMP); if (i == 3) { - sprintf(rresopt, "-x %d -y %d -pa %f", (int)(mult*xres), + sprintf(rresopt, "-x %d -y %d -pa %.3f", (int)(mult*xres), (int)(mult*yres), pa); - sprintf(fresopt, "-x %d -y %d -pa %f", xres, yres, pa); + sprintf(fresopt, "-x %d -y %d -pa %.3f", xres, yres, pa); } else if (i) { if (i == 1) yres = xres; sprintf(rresopt, "-x %d -y %d", (int)(mult*xres), @@ -482,7 +527,7 @@ animate() /* run animation */ /* figure # frames per batch */ d1 = mult*xres*mult*yres*4; /* space for orig. picture */ if ((i=vint(INTERP)) || atoi(vval(MBLUR))) - d1 += mult*xres*mult*yres*4; /* space for z-buffer */ + d1 += mult*xres*mult*yres*sizeof(float); /* Z-buffer */ d2 = xres*yres*4; /* space for final picture */ frames_batch = (i+1)*(vflt(DISKSPACE)*1048576.-d1)/(d1+i*d2); if (frames_batch < i+2) { @@ -811,7 +856,7 @@ int rvr; while (*arcnext) arcnext++; strcpy(arcnext, ".unf"); arcnext += 4; - if (usepinterp || vint(INTERP)) { /* and z-buf */ + if (usepinterp || vint(INTERP)) { /* and Z-buf */ *arcnext++ = ' '; sprintf(arcnext, vval(BASENAME), frame-vint(INTERP)-1); @@ -869,7 +914,7 @@ int rvr; strcat(combuf, viewopt(vp)); if (vbool(RTRACE)) sprintf(combuf+strlen(combuf), " -ff -fr '%s -w0 %s'", - rendopt, vval(OCTREE)); + rendopt+1, vval(OCTREE)); if (vdef(PINTERP)) sprintf(combuf+strlen(combuf), " %s", vval(PINTERP)); if (usepfilt) @@ -957,7 +1002,7 @@ int n; } while (n > viewnum) { /* scan to desired view */ if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL) - return(viewnum==1 ? &curview : NULL); + return(viewnum==1 ? &curview : (VIEW *)NULL); if (isview(linebuf) && sscanview(&curview, linebuf) > 0) viewnum++; } @@ -990,10 +1035,12 @@ int n; if (n == 0) { /* signal to close file */ if (expfp != NULL) { fclose(expfp); + free((char *)exppos); expfp = NULL; } return(NULL); - } + } else if (n > vint(END)) /* request past end (error?) */ + return(NULL); if (!vdef(EXPOSURE)) /* no setting (auto) */ return(NULL); if (isflt(vval(EXPOSURE))) /* always the same */ @@ -1031,13 +1078,15 @@ int n; } curfrm++; cp = fskip(expval); /* check format */ - if (cp == NULL || *cp != '\n') { + if (cp != NULL) + while (isspace(*cp)) + *cp++ = '\0'; + if (cp == NULL || *cp) { fprintf(stderr, "%s: exposure format error on line %d\n", vval(EXPOSURE), curfrm); quit(1); } - *cp = '\0'; } return(expval); /* return value */ } @@ -1067,6 +1116,7 @@ int pn; int status; { register PROC *pp; + register struct pslot *psl; pp = ps->proc + pn; if (pp->elen) { /* pass errors */ @@ -1078,9 +1128,24 @@ int status; if (ps->hostname[0]) status = 1; /* because rsh doesn't return status */ } + lastpserver = NULL; + psl = findpslot(pp->pid); /* check for bruncom() slot */ + if (psl->pid) { + if (status) { + if (psl->rcvf != NULL) /* attempt recovery */ + status = (*psl->rcvf)(psl->fout); + if (status) { + fprintf(stderr, + "%s: error rendering frame %d\n", + progname, psl->fout); + quit(1); + } + lastpserver = ps; + } + psl->pid = 0; /* free process slot */ + } else if (status) + lastpserver = ps; freestr(pp->com); /* free command string */ - lastpid = pp->pid; /* record PID for bwait() */ - lastpserver = ps; /* record server for serverdown() */ return(status); } @@ -1088,6 +1153,8 @@ int status; int serverdown() /* check status of last process server */ { + if (lastpserver == NULL || !lastpserver->hostname[0]) + return(0); if (pserverOK(lastpserver)) /* server still up? */ return(0); delpserver(lastpserver); /* else delete it */ @@ -1114,8 +1181,8 @@ int (*rf)(); printf("\t%s\n", com); /* echo command */ return(0); } - /* else start it when we can */ - while ((pid = startjob(NULL, savestr(com), donecom)) == -1) + com = savestr(com); /* else start it when we can */ + while ((pid = startjob(NULL, com, donecom)) == -1) bwait(1); if (!silent) { /* echo command */ PSERVER *ps; @@ -1137,24 +1204,13 @@ bwait(ncoms) /* wait for batch job(s) to finish */ int ncoms; { int status; - register struct pslot *psl; if (noaction) return; while ((status = wait4job(NULL, -1)) != -1) { - psl = findpslot(lastpid); - if (status) { /* attempt recovery */ - serverdown(); /* check server */ - if (psl->rcvf == NULL || (*psl->rcvf)(psl->fout)) { - fprintf(stderr, - "%s: error rendering frame %d\n", - progname, psl->fout); - quit(1); - } - } - psl->pid = 0; /* free process slot */ - if (!--ncoms) - return; /* done enough */ + serverdown(); /* update server status */ + if (--ncoms == 0) + break; /* done enough */ } } @@ -1166,8 +1222,10 @@ int maxcopies; { int retstatus = 0; int hostcopies; - char com1buf[10240], *com1, *endcom1; + char buf[10240], *com1, *s; int status; + int pfd; + register int n; register PSERVER *ps; if (!silent) @@ -1179,25 +1237,23 @@ int maxcopies; for (ps = pslist; ps != NULL; ps = ps->next) { hostcopies = 0; if (maxcopies > 1 && ps->nprocs > 1 && ppins != NULL) { - strcpy(com1=com1buf, com); /* build -PP command */ + strcpy(com1=buf, com); /* build -PP command */ sprintf(com1+(ppins-com), " -PP %s/%s.persist", vval(DIRECTORY), phostname(ps)); strcat(com1, ppins); - endcom1 = com1 + strlen(com1); - sprintf(endcom1, "; kill `sed -n '1s/^[^ ]* //p' %s/%s.persist`", - vval(DIRECTORY), phostname(ps)); - } else { + } else com1 = com; - endcom1 = NULL; + while (maxcopies > 0) { + s = savestr(com1); + if (startjob(ps, s, donecom) != -1) { + sleep(20); + hostcopies++; + maxcopies--; + } else { + freestr(s); + break; + } } - while (maxcopies > 0 && - startjob(ps, savestr(com1), donecom) != -1) { - sleep(10); - hostcopies++; - maxcopies--; - if (endcom1 != NULL) - *endcom1 = '\0'; - } if (!silent && hostcopies) { if (hostcopies > 1) printf("\t%d duplicate processes", hostcopies); @@ -1209,8 +1265,21 @@ int maxcopies; } /* wait for jobs to finish */ while ((status = wait4job(NULL, -1)) != -1) - if (status) - retstatus += !serverdown(); /* check server */ + retstatus += status && !serverdown(); + /* terminate parallel rpict's */ + for (ps = pslist; ps != NULL; ps = ps->next) { + sprintf(buf, "%s/%s.persist", vval(DIRECTORY), phostname(ps)); + if ((pfd = open(buf, O_RDONLY)) >= 0) { + n = read(pfd, buf, sizeof(buf)-1); /* get PID */ + buf[n] = '\0'; + close(pfd); + for (n = 0; buf[n] && !isspace(buf[n]); n++) + ; + /* terminate */ + sprintf(buf, "kill -ALRM %d", atoi(buf+n)); + wait4job(ps, startjob(ps, buf, NULL)); + } + } return(retstatus); }