home *** CD-ROM | disk | FTP | other *** search
- #include "pt.h"
- #include "memory.h"
-
- #define hashFn(x,y,z) ((13*(x)+(int)((y)&0x7FFF))%(z))
-
- void pascal
- /* XTAG:unlink1 */
- unlink1(bp)
- register struct diskBuffer *bp;
- {
- extern struct diskBuffer *bufHash[];
-
- int h2;
-
- /* unlink it from its old hash chain */
- if( bp->forwardHash != NULL )
- bp->forwardHash->backwardHash = bp->backwardHash;
- if( bp->backwardHash != NULL )
- bp->backwardHash->forwardHash = bp->forwardHash;
- else { /* first in the hash chain */
- h2 = hashFn(bp->handle, bp->blockNumber, NBUFHASH);
- bufHash[h2] = bp->forwardHash;
- }
- }
-
- struct diskBuffer * pascal
- /* XTAG:getBuffer */
- getBuffer(handle, blockNumber)
- int handle;
- long blockNumber;
- {
- extern unsigned char msgBuffer[];
- extern struct diskBuffer *buffers;
- extern struct diskBuffer *bufHash[];
- extern int nextBuffer;
- extern struct openFile *files;
- extern int nBuffers;
- extern struct SREGS segRegs;
- extern int addHandle;
- extern int debug;
- extern int maxFiles;
- extern unsigned char *userMessages[];
-
- register int i;
- register struct diskBuffer *bp;
- int h;
- unsigned char far *fp;
- unsigned int bufferBits, fileBits;
-
-
- /* see if the block is already in a buffer */
- h = hashFn(handle, blockNumber, NBUFHASH);
- bp = bufHash[h];
-
- while( bp != NULL ) {
- if( bp->handle==handle && bp->blockNumber==blockNumber ) {
- break;
- }
- bp = bp->forwardHash;
- }
-
- if( bp == NULL ) {
-
- /* if not, assign it a buffer and fill it with data */
- /* LATER: use LRU buffer replacment instead of FIFO */
- if( ++nextBuffer >= nBuffers )
- nextBuffer = 0;
- bp = &buffers[nextBuffer];
-
- if( bp->handle != -1 ) { /* is the buffer in use? */
-
- /* unlink it from its old hash chain */
- unlink1(bp);
-
- /* Invalidate any possible buffer caches. */
- bufferBits = ((unsigned int)FP_OFF(bp->bufferAddress))
- >> BUFFERSHIFT;
- for(i = 0; i < maxFiles; i++) {
- /* get the high order bits of the offset */
- /* of the buffer address */
- fileBits =
- ((unsigned int)files[i].logBufOffset)
- >> BUFFERSHIFT;
- /* see if the offsets match */
- if( bufferBits == fileBits ) {
- /* if so invalidate the cache */
- files[i].hiLogBuffer = -1L;
- }
- }
-
- /* write the buffer out to disk */
- if( bp->written ) {
- lseekls(bp->handle,
- (bp->blockNumber)<<BUFFERSHIFT, 0);
- i = writeFar(bp->handle, bp->bufferAddress,
- BUFFERSIZE);
- if( i < BUFFERSIZE )
- msg(userMessages[FULLMSG], 3);
- }
- }
- bp->handle = handle;
- bp->blockNumber = blockNumber;
- bp->written = 0;
-
- /* read in the new buffer contents */
- lseekls(handle, blockNumber<<BUFFERSHIFT, 0);
- i = readFar(handle, bp->bufferAddress, BUFFERSIZE);
- /* read zeros for non-existing chararacters */
- /* this will occur in the add file only */
- if( i <= 0 ) {
- if( i < 0 ) {
- sprintf(msgBuffer,
- "getBuffer: read error, ret=%d, handle=%d", i, handle);
- msg(msgBuffer, 3);
- }
- /* zero out the buffer */
- fp = bp->bufferAddress;
- for(i = 0; i < BUFFERSIZE; ++i)
- *fp++ = '\0';
- }
-
- bp->backwardHash = NULL;
- bp->forwardHash = bufHash[h];
- if( bufHash[h] != NULL )
- bufHash[h]->backwardHash = bp;
- bufHash[h] = bp;
- }
- return bp;
- }
-
- void pascal
- /* XTAG:fidInvalid */
- fidInvalid(fid)
- int fid;
- {
- extern struct diskBuffer *buffers;
- extern int nBuffers;
- extern struct changeItem *change;
- extern int tailChange, nextChange;
-
- register int i;
-
- /* invalidate the buffer cache */
- for(i = 0; i < nBuffers; i++)
- if( buffers[i].handle == fid ) {
- unlink1(&buffers[i]);
- buffers[i].handle = -1;
- }
-
- /* invalidate and history changes that refer to this file */
- i = tailChange;
- if( i != nextChange ) { /* make sure the history is not empty */
- while( 1 ) {
- if( change[i].fileId==fid && change[i].type!=CNULL) {
- freePieces( change[i].firstPiece );
- change[i].type = CNULL;
- }
- if( i == nextChange )
- break;
- if( ++i >= NHISTORY )
- i = 0;
- }
- }
- }
-
- unsigned char pascal
- /* XTAG:readChar */
- readChar(fileId, logicalByte)
- int fileId;
- long logicalByte;
- {
- int n;
- unsigned char far *firstByte;
- unsigned char far *dummy;
-
- n = getSpan(fileId, logicalByte, &firstByte, &dummy, 0);
- if( n != 0 )
- return '\0';
- else
- return *firstByte;
- }
-
- int pascal
- /* XTAG:getSpan */
- getSpan(fileId, logicalByte, inFirstByte, inLastByte, reversed)
- int fileId, reversed;
- long logicalByte;
- unsigned char far * *inFirstByte;
- unsigned char far * *inLastByte;
- {
- extern unsigned char msgBuffer[];
- extern struct openFile *files;
- extern int debug;
- extern int addHandle;
- extern struct SREGS segRegs;
-
- register struct openFile *ff;
- struct diskBuffer *buf;
- long physicalByte, blockNumber, nn, bp;
- int handle;
- long offset;
- struct piece *pp;
- struct longPointer *firstByte;
- struct longPointer *lastByte;
-
- /* for efficiency, keep some addresses */
- ff = &files[fileId];
- firstByte = (struct longPointer *)inFirstByte;
- lastByte = (struct longPointer *)inLastByte;
-
- /* if file is not open print an error message */
- if( fileId == -1 || ff->origHandle == -1 ) {
- sprintf(msgBuffer, "getSpan: file %d is not open", fileId);
- msg(msgBuffer, 3);
- return 1;
- }
-
- /* see if the logical byte number is invalid */
- if( logicalByte < 0 || logicalByte >= ff->fileSize)
- return 1;
-
- /* check for optimized special cases */
- if( ff->loLogBuffer<=logicalByte && logicalByte<=ff->hiLogBuffer ) {
- /* if this logical byte is in the buffer cache then set up */
- /* the addresses using the saved segment and offset fields */
- firstByte->offset = ff->logBufOffset
- + (unsigned int)(logicalByte - ff->loLogBuffer);
- if( reversed ) {
- lastByte->offset = firstByte->offset;
- firstByte->offset = ff->logBufOffset;
- } else
- lastByte->offset = ff->logBufOffset
- + (unsigned int)(ff->hiLogBuffer - ff->loLogBuffer);
- firstByte->segment = ff->logBufSegment;
- lastByte->segment = ff->logBufSegment;
- return 0;
- }
-
- /* see if we already know what piece it is in */
- /* findPiece checks this but for speed we do it here anyway */
- /* since readChar is on the critical path of performance */
- if( ff->loLogPiece<=logicalByte && logicalByte<=ff->hiLogPiece ) {
- pp = ff->logPiece;
- physicalByte = pp->position + logicalByte - ff->loLogPiece;
- } else {
- pp = findPiece(logicalByte, ff, &nn);
- physicalByte = pp->position + logicalByte - nn;
- /* remember this piece as the cached piece */
- ff->logPiece = pp;
- ff->loLogPiece = nn;
- ff->hiLogPiece = nn + pp->length - 1;
- }
-
- /* get the physical file block containing this character */
- blockNumber = physicalByte>>BUFFERSHIFT;
-
- /* figure out the appropriate handle */
- if( pp->file == ORIGFILE )
- handle = ff->origHandle;
- else /* pp->file == ADDFILE */
- handle = addHandle;
-
- /* get the buffer that this character is in */
- buf = getBuffer(handle, blockNumber);
-
- /* figure out how many bytes into the buffer logicalByte is */
- offset = physicalByte - (blockNumber<<BUFFERSHIFT);
- firstByte->offset = (char *)FP_OFF(buf->bufferAddress) + offset;
- firstByte->segment = (char *)FP_SEG(buf->bufferAddress);
-
- /* Remember the logical byte limits in this buffer. */
-
- /* Is the beginning of the buffer still in this piece? */
- bp = logicalByte - offset;
-
- /* bp = logical byte number of the first physical byte in buffer */
- /* "buf" ASSUMING all of this buffer is in piece "pp". Now we */
- /* check this assumption and adjust things if it is false */
-
- if( bp >= ff->loLogPiece ) {
- /* the first byte in this buffer is still in the piece */
- ff->loLogBuffer = bp;
- ff->logBufSegment = (char *)FP_SEG(buf->bufferAddress);
- ff->logBufOffset = (char *)FP_OFF(buf->bufferAddress);
- } else {
- /* the piece begins inside the buffer */
- ff->loLogBuffer = ff->loLogPiece;
- ff->logBufSegment = (char *)FP_SEG(buf->bufferAddress);
- ff->logBufOffset = (char *)FP_OFF(buf->bufferAddress)
- + (ff->loLogPiece - bp);
- }
-
- /* Now check if the last physical byte in this buffer is still */
- /* in piece "pp" */
-
- /* bp: logical byte at the end of the buffer */
- bp += (BUFFERSIZE - 1);
- if( bp <= ff->hiLogPiece ) {
- /* the last byte of the buffer is in the piece */
- ff->hiLogBuffer = bp;
- } else {
- /* piece ends before the end of the buffer */
- ff->hiLogBuffer = ff->hiLogPiece;
- }
-
- /* handle the special case of reversed spans to support searching */
- /* backwards */
- lastByte->segment = firstByte->segment;
- if( reversed ) {
- /* lastByte points to the logical character argument */
- lastByte->offset = firstByte->offset;
- /* firstByte points to the beginning of the buffer */
- firstByte->offset = ff->logBufOffset;
- } else {
- lastByte->offset = firstByte->offset
- + (unsigned int)(ff->hiLogBuffer - logicalByte);
- }
-
- return 0;
- }
-
- void pascal
- /* XTAG:writeChar */
- writeChar(ch, physicalByte)
- unsigned char ch;
- long physicalByte;
- {
- extern unsigned char msgBuffer[];
- extern struct openFile *files;
- extern int addHandle;
- extern struct SREGS segRegs;
-
- struct diskBuffer *buf;
- long blockNumber;
- int offset;
-
- /* get the physical file block containing this character */
- blockNumber = physicalByte>>BUFFERSHIFT;
- buf = getBuffer(addHandle, blockNumber);
-
- /* mark this buffer as written so it will be flushed before */
- /* it is reused */
- buf->written = 1;
-
- /* figure out how many bytes into the buffer physicalByte is */
- offset = (int)( physicalByte - (blockNumber<<BUFFERSHIFT) );
-
- /* now store the byte */
- /*************************************
- movedata(segRegs.ds, (unsigned int)&ch, FP_SEG(buf->bufferAddress),
- FP_OFF(buf->bufferAddress) + offset, 1);
- *************************************/
- *(buf->bufferAddress+offset) = ch;
- }