| 1 |
#ifndef lint
|
| 2 |
static const char RCSid[] = "$Id: rhoptimize.c,v 3.23 2019/10/21 18:19:32 greg Exp $";
|
| 3 |
#endif
|
| 4 |
/*
|
| 5 |
* Optimize holodeck for quick access.
|
| 6 |
*
|
| 7 |
* 11/4/98 Greg Ward Larson
|
| 8 |
*/
|
| 9 |
|
| 10 |
#include <signal.h>
|
| 11 |
#include <string.h>
|
| 12 |
#include <stdio.h>
|
| 13 |
|
| 14 |
#include "platform.h"
|
| 15 |
#include "rterror.h"
|
| 16 |
#include "resolu.h"
|
| 17 |
#include "rtprocess.h" /* getpid() */
|
| 18 |
#include "holo.h"
|
| 19 |
|
| 20 |
#ifndef BKBSIZE
|
| 21 |
#define BKBSIZE 256 /* beam clump size (kilobytes) */
|
| 22 |
#endif
|
| 23 |
|
| 24 |
char *progname;
|
| 25 |
char tempfile[128];
|
| 26 |
int dupchecking = 0;
|
| 27 |
|
| 28 |
static long rhinitcopy(int hfd[2], char *infn, char *outfn);
|
| 29 |
static int nuniq(RAYVAL *rva, int n);
|
| 30 |
static int bpcmp(const void *b1p, const void *b2p);
|
| 31 |
static int xferclump(HOLO *hp, int *bq, int nb);
|
| 32 |
static void copysect(int ifd, int ofd);
|
| 33 |
|
| 34 |
|
| 35 |
int
|
| 36 |
main(
|
| 37 |
int argc,
|
| 38 |
char *argv[]
|
| 39 |
)
|
| 40 |
{
|
| 41 |
char *inpname, *outname;
|
| 42 |
int hdfd[2];
|
| 43 |
off_t nextipos, lastopos, thisopos;
|
| 44 |
|
| 45 |
progname = argv[0];
|
| 46 |
argv++; argc--; /* duplicate checking flag? */
|
| 47 |
if (argc > 1 && !strcmp(argv[0], "-u")) {
|
| 48 |
dupchecking++;
|
| 49 |
argv++; argc--;
|
| 50 |
}
|
| 51 |
if ((argc < 1) | (argc > 2)) {
|
| 52 |
fprintf(stderr, "Usage: %s [-u] input.hdk [output.hdk]\n",
|
| 53 |
progname);
|
| 54 |
exit(1);
|
| 55 |
}
|
| 56 |
inpname = argv[0]; /* get input file */
|
| 57 |
argv++; argc--;
|
| 58 |
if (argc == 1) /* use given output file */
|
| 59 |
outname = argv[0];
|
| 60 |
else { /* else use temporary file */
|
| 61 |
if (access(inpname, R_OK|W_OK) < 0) { /* check permissions */
|
| 62 |
sprintf(errmsg, "cannot access \"%s\"", inpname);
|
| 63 |
error(SYSTEM, errmsg);
|
| 64 |
}
|
| 65 |
strcpy(tempfile, inpname);
|
| 66 |
if ((outname = strrchr(tempfile, '/')) != NULL)
|
| 67 |
outname++;
|
| 68 |
else
|
| 69 |
outname = tempfile;
|
| 70 |
sprintf(outname, "rho%d.hdk", getpid());
|
| 71 |
outname = tempfile;
|
| 72 |
}
|
| 73 |
/* copy holodeck file header */
|
| 74 |
nextipos = rhinitcopy(hdfd, inpname, outname);
|
| 75 |
lastopos = 0; /* copy sections one by one */
|
| 76 |
while (nextipos != 0L) {
|
| 77 |
/* set input position; get next */
|
| 78 |
lseek(hdfd[0], nextipos, SEEK_SET);
|
| 79 |
read(hdfd[0], (char *)&nextipos, sizeof(nextipos));
|
| 80 |
/* get output position; set last */
|
| 81 |
thisopos = lseek(hdfd[1], (off_t)0, SEEK_END);
|
| 82 |
if (lastopos > 0) {
|
| 83 |
lseek(hdfd[1], lastopos, SEEK_SET);
|
| 84 |
write(hdfd[1], (char *)&thisopos, sizeof(thisopos));
|
| 85 |
lseek(hdfd[1], (off_t)0, SEEK_END);
|
| 86 |
}
|
| 87 |
lastopos = thisopos;
|
| 88 |
thisopos = 0; /* write place holder */
|
| 89 |
write(hdfd[1], (char *)&thisopos, sizeof(thisopos));
|
| 90 |
/* copy holodeck section */
|
| 91 |
copysect(hdfd[0], hdfd[1]);
|
| 92 |
}
|
| 93 |
/* clean up */
|
| 94 |
close(hdfd[0]);
|
| 95 |
close(hdfd[1]);
|
| 96 |
if (outname == tempfile && rename(outname, inpname) < 0) {
|
| 97 |
sprintf(errmsg, "cannot rename \"%s\" to \"%s\"",
|
| 98 |
outname, inpname);
|
| 99 |
error(SYSTEM, errmsg);
|
| 100 |
}
|
| 101 |
return(0);
|
| 102 |
}
|
| 103 |
|
| 104 |
|
| 105 |
static long
|
| 106 |
rhinitcopy( /* open files and copy header */
|
| 107 |
int hfd[2], /* returned file descriptors */
|
| 108 |
char *infn,
|
| 109 |
char *outfn
|
| 110 |
)
|
| 111 |
{
|
| 112 |
FILE *infp, *outfp;
|
| 113 |
long ifpos;
|
| 114 |
/* open files for i/o */
|
| 115 |
if ((infp = fopen(infn, "rb")) == NULL) {
|
| 116 |
sprintf(errmsg, "cannot open \"%s\" for reading", infn);
|
| 117 |
error(SYSTEM, errmsg);
|
| 118 |
}
|
| 119 |
if (access(outfn, F_OK) == 0) {
|
| 120 |
sprintf(errmsg, "output file \"%s\" already exists!", outfn);
|
| 121 |
error(USER, errmsg);
|
| 122 |
}
|
| 123 |
if ((outfp = fopen(outfn, "wb+")) == NULL) {
|
| 124 |
sprintf(errmsg, "cannot open \"%s\" for writing", outfn);
|
| 125 |
error(SYSTEM, errmsg);
|
| 126 |
}
|
| 127 |
/* set up signal handling */
|
| 128 |
#ifdef SIGINT
|
| 129 |
if (signal(SIGINT, quit) == SIG_IGN) signal(SIGINT, SIG_IGN);
|
| 130 |
#endif
|
| 131 |
#ifdef SIGHUP
|
| 132 |
if (signal(SIGHUP, quit) == SIG_IGN) signal(SIGHUP, SIG_IGN);
|
| 133 |
#endif
|
| 134 |
#ifdef SIGTERM
|
| 135 |
if (signal(SIGTERM, quit) == SIG_IGN) signal(SIGTERM, SIG_IGN);
|
| 136 |
#endif
|
| 137 |
#ifdef SIGXCPU
|
| 138 |
if (signal(SIGXCPU, quit) == SIG_IGN) signal(SIGXCPU, SIG_IGN);
|
| 139 |
if (signal(SIGXFSZ, quit) == SIG_IGN) signal(SIGXFSZ, SIG_IGN);
|
| 140 |
#endif
|
| 141 |
/* copy and verify header */
|
| 142 |
if (checkheader(infp, HOLOFMT, outfp) < 0 || getw(infp) != HOLOMAGIC)
|
| 143 |
error(USER, "input not in holodeck format");
|
| 144 |
fputformat(HOLOFMT, outfp);
|
| 145 |
fputc('\n', outfp);
|
| 146 |
putw(HOLOMAGIC, outfp);
|
| 147 |
/* get descriptors and free stdio */
|
| 148 |
if ((hfd[0] = dup(fileno(infp))) < 0 ||
|
| 149 |
(hfd[1] = dup(fileno(outfp))) < 0)
|
| 150 |
error(SYSTEM, "dup call failed in rhinitcopy");
|
| 151 |
ifpos = ftell(infp);
|
| 152 |
fclose(infp);
|
| 153 |
if (fclose(outfp) == EOF)
|
| 154 |
error(SYSTEM, "file flushing error in rhinitcopy");
|
| 155 |
/* check cache size */
|
| 156 |
if (BKBSIZE*1024*1.5 > hdcachesize)
|
| 157 |
hdcachesize = BKBSIZE*1024*1.5;
|
| 158 |
/* return input position */
|
| 159 |
return(ifpos);
|
| 160 |
}
|
| 161 |
|
| 162 |
|
| 163 |
static int
|
| 164 |
nuniq( /* sort unique rays to front of beam list */
|
| 165 |
RAYVAL *rva,
|
| 166 |
int n
|
| 167 |
)
|
| 168 |
{
|
| 169 |
int i, j;
|
| 170 |
RAYVAL rtmp;
|
| 171 |
|
| 172 |
for (j = 0; j < n; j++)
|
| 173 |
for (i = j+1; i < n; i++)
|
| 174 |
if ( rva[i].d == rva[j].d &&
|
| 175 |
rva[i].r[0][0]==rva[j].r[0][0] &&
|
| 176 |
rva[i].r[0][1]==rva[j].r[0][1] &&
|
| 177 |
rva[i].r[1][0]==rva[j].r[1][0] &&
|
| 178 |
rva[i].r[1][1]==rva[j].r[1][1] ) {
|
| 179 |
n--; /* swap duplicate with end */
|
| 180 |
rtmp = *(rva+n);
|
| 181 |
*(rva+n) = *(rva+i);
|
| 182 |
*(rva+i) = rtmp;
|
| 183 |
i--; /* recheck one we swapped */
|
| 184 |
}
|
| 185 |
return(n);
|
| 186 |
}
|
| 187 |
|
| 188 |
|
| 189 |
static BEAMI *beamdir;
|
| 190 |
|
| 191 |
static int
|
| 192 |
bpcmp( /* compare beam positions on disk */
|
| 193 |
const void *b1p,
|
| 194 |
const void *b2p
|
| 195 |
)
|
| 196 |
{
|
| 197 |
off_t pdif = beamdir[*(int*)b1p].fo - beamdir[*(int*)b2p].fo;
|
| 198 |
|
| 199 |
if (pdif < 0L) return(-1);
|
| 200 |
return(pdif > 0L);
|
| 201 |
}
|
| 202 |
|
| 203 |
static HOLO *hout;
|
| 204 |
|
| 205 |
static int
|
| 206 |
xferclump( /* transfer the given clump to hout and free */
|
| 207 |
HOLO *hp,
|
| 208 |
int *bq,
|
| 209 |
int nb
|
| 210 |
)
|
| 211 |
{
|
| 212 |
int i;
|
| 213 |
BEAM *bp;
|
| 214 |
int n;
|
| 215 |
|
| 216 |
beamdir = hp->bi; /* sort based on file position */
|
| 217 |
qsort((void *)bq, nb, sizeof(*bq), bpcmp);
|
| 218 |
/* transfer and free each beam */
|
| 219 |
for (i = 0; i < nb; i++) {
|
| 220 |
bp = hdgetbeam(hp, bq[i]);
|
| 221 |
DCHECK(bp==NULL, CONSISTENCY, "empty beam in xferclump");
|
| 222 |
n = dupchecking ? nuniq(hdbray(bp),bp->nrm) : bp->nrm;
|
| 223 |
memcpy((void *)hdnewrays(hout,bq[i],n),(void *)hdbray(bp),
|
| 224 |
n*sizeof(RAYVAL));
|
| 225 |
hdfreebeam(hp, bq[i]);
|
| 226 |
}
|
| 227 |
hdfreebeam(hout, 0); /* write & free clump */
|
| 228 |
return(0);
|
| 229 |
}
|
| 230 |
|
| 231 |
static void
|
| 232 |
copysect( /* copy holodeck section from ifd to ofd */
|
| 233 |
int ifd,
|
| 234 |
int ofd
|
| 235 |
)
|
| 236 |
{
|
| 237 |
HOLO *hinp;
|
| 238 |
/* load input section directory */
|
| 239 |
hinp = hdinit(ifd, NULL);
|
| 240 |
/* create output section directory */
|
| 241 |
hout = hdinit(ofd, (HDGRID *)hinp);
|
| 242 |
/* clump the beams */
|
| 243 |
clumpbeams(hinp, 0, BKBSIZE*1024, xferclump);
|
| 244 |
/* clean up */
|
| 245 |
hddone(hinp);
|
| 246 |
hddone(hout);
|
| 247 |
}
|
| 248 |
|
| 249 |
|
| 250 |
void
|
| 251 |
eputs(const char *s) /* put error message to stderr */
|
| 252 |
{
|
| 253 |
static int midline = 0;
|
| 254 |
|
| 255 |
if (!*s)
|
| 256 |
return;
|
| 257 |
if (!midline++) { /* prepend line with program name */
|
| 258 |
fputs(progname, stderr);
|
| 259 |
fputs(": ", stderr);
|
| 260 |
}
|
| 261 |
fputs(s, stderr);
|
| 262 |
if (s[strlen(s)-1] == '\n') {
|
| 263 |
fflush(stderr);
|
| 264 |
midline = 0;
|
| 265 |
}
|
| 266 |
}
|
| 267 |
|
| 268 |
|
| 269 |
void
|
| 270 |
quit(code) /* exit the program gracefully */
|
| 271 |
int code;
|
| 272 |
{
|
| 273 |
if (tempfile[0])
|
| 274 |
unlink(tempfile);
|
| 275 |
exit(code);
|
| 276 |
}
|