| 73 |  | hdrelease(fd)           /* stop tracking file fragments for some section */ | 
| 74 |  | register int    fd; | 
| 75 |  | { | 
| 76 | < | if (fd >= nhdfrags || !hdfrag[fd].nlinks) | 
| 76 | > | if (fd < 0 | fd >= nhdfrags || !hdfrag[fd].nlinks) | 
| 77 |  | return; | 
| 78 |  | if (!--hdfrag[fd].nlinks && hdfrag[fd].nfrags) { | 
| 79 |  | free((char *)hdfrag[fd].fi); | 
| 157 |  |  | 
| 158 |  |  | 
| 159 |  | int | 
| 160 | < | hdsync(hp)                      /* update directory on disk if necessary */ | 
| 160 | > | hdsync(hp, all)                 /* update beams and directory on disk */ | 
| 161 |  | register HOLO   *hp; | 
| 162 | + | int     all; | 
| 163 |  | { | 
| 164 |  | register int    j, n; | 
| 165 |  |  | 
| 166 | < | if (hp == NULL) {               /* do all */ | 
| 166 | > | if (hp == NULL) {               /* do all holodecks */ | 
| 167 |  | n = 0; | 
| 168 |  | for (j = 0; hdlist[j] != NULL; j++) | 
| 169 | < | n += hdsync(hdlist[j]); | 
| 169 | > | n += hdsync(hdlist[j], all); | 
| 170 |  | return(n); | 
| 171 |  | } | 
| 172 | < | if (!hp->dirty)                 /* check first */ | 
| 172 | > | /* sync the beams */ | 
| 173 | > | for (j = all ? nbeams(hp) : 0; j > 0; j--) | 
| 174 | > | if (hp->bl[j] != NULL) | 
| 175 | > | hdsyncbeam(hp, j); | 
| 176 | > | if (!hp->dirty)                 /* directory dirty? */ | 
| 177 |  | return(0); | 
| 178 |  | errno = 0; | 
| 179 |  | if (lseek(hp->fd, biglob(hp)->fo, 0) < 0) | 
| 216 |  |  | 
| 217 |  |  | 
| 218 |  | long | 
| 219 | + | hdfilen(fd)             /* return file length for fd */ | 
| 220 | + | int     fd; | 
| 221 | + | { | 
| 222 | + | long    fpos, flen; | 
| 223 | + |  | 
| 224 | + | if (fd < 0) | 
| 225 | + | return(-1); | 
| 226 | + | if (fd >= nhdfrags || !hdfrag[fd].nlinks) { | 
| 227 | + | if ((fpos = lseek(fd, 0L, 1)) < 0) | 
| 228 | + | return(-1); | 
| 229 | + | flen = lseek(fd, 0L, 2); | 
| 230 | + | lseek(fd, fpos, 0); | 
| 231 | + | return(flen); | 
| 232 | + | } | 
| 233 | + | return(hdfrag[fd].flen); | 
| 234 | + | } | 
| 235 | + |  | 
| 236 | + |  | 
| 237 | + | long | 
| 238 |  | hdfiluse(fd, all)       /* compute file usage (in bytes) */ | 
| 239 |  | int     fd;                     /* open file descriptor to check */ | 
| 240 |  | int     all;                    /* include overhead and unflushed data */ | 
| 340 |  |  | 
| 341 |  |  | 
| 342 |  | int | 
| 343 | < | hdgetbi(hp, i)                  /* allocate a file fragment */ | 
| 343 | > | hdsyncbeam(hp, i)               /* sync beam in memory with beam on disk */ | 
| 344 |  | register HOLO   *hp; | 
| 345 |  | register int    i; | 
| 346 |  | { | 
| 347 | < | int     nrays = hp->bl[i]->nrm; | 
| 348 | < |  | 
| 349 | < | if (hp->bi[i].nrd == nrays)     /* current one will do? */ | 
| 347 | > | unsigned int    nrays; | 
| 348 | > | long    nfo; | 
| 349 | > | unsigned int    n; | 
| 350 | > | #ifdef DEBUG | 
| 351 | > | if (i < 1 | i > nbeams(hp)) | 
| 352 | > | error(CONSISTENCY, "bad beam index in hdsyncbeam"); | 
| 353 | > | #endif | 
| 354 | > | /* is current fragment OK? */ | 
| 355 | > | if (hp->bl[i] == NULL || (nrays = hp->bl[i]->nrm) == hp->bi[i].nrd) | 
| 356 |  | return(0); | 
| 357 | + | /* check file status */ | 
| 358 | + | if (hp->dirty < 0) | 
| 359 | + | return(-1); | 
| 360 |  |  | 
| 361 |  | if (hp->fd >= nhdfrags || !hdfrag[hp->fd].nlinks) /* untracked */ | 
| 362 |  | hp->bi[i].fo = lseek(hp->fd, 0L, 2); | 
| 363 |  |  | 
| 364 |  | else if (hp->bi[i].fo + hp->bi[i].nrd*sizeof(RAYVAL) == | 
| 365 |  | hdfrag[hp->fd].flen)            /* EOF special case */ | 
| 366 | < | hdfrag[hp->fd].flen = hp->bi[i].fo + nrays*sizeof(RAYVAL); | 
| 366 | > | hdfrag[hp->fd].flen = (nfo=hp->bi[i].fo) + nrays*sizeof(RAYVAL); | 
| 367 |  |  | 
| 368 |  | else {                                          /* general case */ | 
| 369 |  | register struct fragment        *f = &hdfrag[hp->fd]; | 
| 384 |  | (j+FRAGBLK)*sizeof(BEAMI)); | 
| 385 |  | if (f->fi == NULL) | 
| 386 |  | error(SYSTEM, | 
| 387 | < | "out of memory in hdgetbi"); | 
| 387 | > | "out of memory in hdsyncbeam"); | 
| 388 |  | } | 
| 389 |  | for ( ; ; j--) {        /* insert in descending list */ | 
| 390 |  | if (!j || hp->bi[i].fo < f->fi[j-1].fo) { | 
| 409 |  | f->nfrags = j; | 
| 410 |  | } | 
| 411 |  | k = -1;                 /* find closest-sized fragment */ | 
| 412 | < | for (j = f->nfrags; j-- > 0; ) | 
| 412 | > | for (j = nrays ? f->nfrags : 0; j-- > 0; ) | 
| 413 |  | if (f->fi[j].nrd >= nrays && | 
| 414 |  | (k < 0 || f->fi[j].nrd < f->fi[k].nrd)) | 
| 415 |  | if (f->fi[k=j].nrd == nrays) | 
| 416 |  | break; | 
| 417 |  | if (k < 0) {            /* no fragment -- extend file */ | 
| 418 | < | hp->bi[i].fo = f->flen; | 
| 418 | > | nfo = f->flen; | 
| 419 |  | f->flen += nrays*sizeof(RAYVAL); | 
| 420 |  | } else {                /* else use fragment */ | 
| 421 | < | hp->bi[i].fo = f->fi[k].fo; | 
| 421 | > | nfo = f->fi[k].fo; | 
| 422 |  | if (f->fi[k].nrd == nrays) {    /* delete fragment */ | 
| 423 |  | f->nfrags--; | 
| 424 |  | for (j = k; j < f->nfrags; j++) | 
| 429 |  | } | 
| 430 |  | } | 
| 431 |  | } | 
| 432 | + | if (nrays) {            /* write the new fragment */ | 
| 433 | + | errno = 0; | 
| 434 | + | if (lseek(hp->fd, nfo, 0) < 0) | 
| 435 | + | error(SYSTEM, "cannot seek on holodeck file"); | 
| 436 | + | n = hp->bl[i]->nrm * sizeof(RAYVAL); | 
| 437 | + | if (write(hp->fd, (char *)hdbray(hp->bl[i]), n) != n) { | 
| 438 | + | hp->dirty = -1;         /* avoid recursive error */ | 
| 439 | + | error(SYSTEM, "write error in hdsyncbeam"); | 
| 440 | + | } | 
| 441 | + | } | 
| 442 |  | biglob(hp)->nrd += nrays - hp->bi[i].nrd; | 
| 443 |  | hp->bi[i].nrd = nrays; | 
| 444 | + | hp->bi[i].fo = nfo; | 
| 445 |  | markdirty(hp);          /* section directory now out of date */ | 
| 446 |  | return(1); | 
| 447 |  | } | 
| 452 |  | register HOLO   *hp; | 
| 453 |  | register int    i; | 
| 454 |  | { | 
| 455 | < | int     nchanged, n; | 
| 455 | > | int     nchanged; | 
| 456 |  |  | 
| 457 |  | if (hp == NULL) {               /* clear all holodecks */ | 
| 458 |  | nchanged = 0; | 
| 462 |  | } | 
| 463 |  | if (i == 0) {                   /* clear entire holodeck */ | 
| 464 |  | nchanged = 0; | 
| 465 | < | for (i = 1; i <= nbeams(hp); i++) | 
| 466 | < | nchanged += hdfreebeam(hp, i); | 
| 465 | > | for (i = nbeams(hp); i > 0; i--) | 
| 466 | > | if (hp->bl[i] != NULL) | 
| 467 | > | nchanged += hdfreebeam(hp, i); | 
| 468 |  | return(nchanged); | 
| 469 |  | } | 
| 470 | + | #ifdef DEBUG | 
| 471 |  | if (i < 1 | i > nbeams(hp)) | 
| 472 |  | error(CONSISTENCY, "bad beam index to hdfreebeam"); | 
| 473 | + | #endif | 
| 474 |  | if (hp->bl[i] == NULL) | 
| 475 |  | return(0); | 
| 476 |  | /* check for additions */ | 
| 477 |  | nchanged = hp->bl[i]->nrm - hp->bi[i].nrd; | 
| 478 | < | if (nchanged) { | 
| 479 | < | hdgetbi(hp, i);                 /* allocate a file position */ | 
| 433 | < | errno = 0; | 
| 434 | < | if (lseek(hp->fd, hp->bi[i].fo, 0) < 0) | 
| 435 | < | error(SYSTEM, "cannot seek on holodeck file"); | 
| 436 | < | n = hp->bl[i]->nrm * sizeof(RAYVAL); | 
| 437 | < | if (write(hp->fd, (char *)hdbray(hp->bl[i]), n) != n) | 
| 438 | < | error(SYSTEM, "write error in hdfreebeam"); | 
| 439 | < | } | 
| 478 | > | if (nchanged) | 
| 479 | > | hdsyncbeam(hp, i);              /* write new fragment */ | 
| 480 |  | blglob(hp)->nrm -= hp->bl[i]->nrm; | 
| 481 |  | free((char *)hp->bl[i]);                /* free memory */ | 
| 482 |  | hp->bl[i] = NULL; | 
| 484 |  | } | 
| 485 |  |  | 
| 486 |  |  | 
| 487 | + | int | 
| 488 | + | hdkillbeam(hp, i)               /* delete beam from holodeck */ | 
| 489 | + | register HOLO   *hp; | 
| 490 | + | register int    i; | 
| 491 | + | { | 
| 492 | + | static BEAM     emptybeam; | 
| 493 | + | int     nchanged; | 
| 494 | + |  | 
| 495 | + | if (hp == NULL) {               /* clobber all holodecks */ | 
| 496 | + | nchanged = 0; | 
| 497 | + | for (i = 0; hdlist[i] != NULL; i++) | 
| 498 | + | nchanged += hdkillbeam(hdlist[i], 0); | 
| 499 | + | return(nchanged); | 
| 500 | + | } | 
| 501 | + | if (i == 0) {                   /* clobber entire holodeck */ | 
| 502 | + | nchanged = 0; | 
| 503 | + | for (i = nbeams(hp); i > 0; i--) | 
| 504 | + | if (hp->bi[i].nrd > 0 || hp->bl[i] != NULL) | 
| 505 | + | nchanged += hdkillbeam(hp, i); | 
| 506 | + | #ifdef DEBUG | 
| 507 | + | if (biglob(hp)->nrd != 0 | blglob(hp)->nrm != 0) | 
| 508 | + | error(CONSISTENCY, "bad beam count in hdkillbeam"); | 
| 509 | + | #endif | 
| 510 | + | return(nchanged); | 
| 511 | + | } | 
| 512 | + | #ifdef DEBUG | 
| 513 | + | if (i < 1 | i > nbeams(hp)) | 
| 514 | + | error(CONSISTENCY, "bad beam index to hdkillbeam"); | 
| 515 | + | #endif | 
| 516 | + | if (hp->bl[i] != NULL) {        /* free memory */ | 
| 517 | + | blglob(hp)->nrm -= nchanged = hp->bl[i]->nrm; | 
| 518 | + | free((char *)hp->bl[i]); | 
| 519 | + | } else | 
| 520 | + | nchanged = hp->bi[i].nrd; | 
| 521 | + | if (hp->bi[i].nrd) {            /* free file fragment */ | 
| 522 | + | hp->bl[i] = &emptybeam; | 
| 523 | + | hdsyncbeam(hp, i); | 
| 524 | + | } | 
| 525 | + | hp->bl[i] = NULL; | 
| 526 | + | return(nchanged); | 
| 527 | + | } | 
| 528 | + |  | 
| 529 | + |  | 
| 530 |  | hdlrulist(ha, ba, n, hp)        /* add beams from holodeck to LRU list */ | 
| 531 |  | register HOLO   *ha[];                  /* section list (NULL terminated) */ | 
| 532 |  | register int    ba[];                   /* beam index to go with section */ | 
| 540 |  | ; | 
| 541 |  | nents = j; | 
| 542 |  | /* insert each beam from hp */ | 
| 543 | < | for (i = nbeams(hp); i > 0; i-- ) { | 
| 543 | > | for (i = nbeams(hp); i > 0; i--) { | 
| 544 |  | if (hp->bl[i] == NULL)          /* check if loaded */ | 
| 545 |  | continue; | 
| 546 |  | if ((j = ++nents) > n)          /* grow list if we can */ | 
| 587 |  | if ((freetarget -= hp[i]->bi[bn[i]].nrd) <= 0) | 
| 588 |  | break; | 
| 589 |  | } | 
| 590 | < | hdsync(honly);          /* synchronize directories as necessary */ | 
| 590 | > | hdsync(honly, 0);       /* synchronize directories as necessary */ | 
| 591 |  | } | 
| 592 |  |  | 
| 593 |  |  |