/************************************************************/ /* Windows Write, Copyright 1985-1992 Microsoft Corporation */ /************************************************************/ #define NOCLIPBOARD #define NOGDICAPMASKS #define NOCTLMGR #define NOVIRTUALKEYCODES #define NOWINMESSAGES #define NOWINSTYLES #define NOSYSMETRICS #define NOMENUS #include #include "mw.h" #include "doslib.h" #include "cmddefs.h" #include "docdefs.h" #include "filedefs.h" #include "str.h" #include "debug.h" extern int vfnWriting; #define IibpHash(fn,pn) ((int) ((fn + 1) * (pn + 1)) & 077777) % iibpHashMax #define FcMin(a,b) CpMin(a,b) extern CHAR *rgibpHash; extern int vfSysFull; extern struct BPS *mpibpbps; extern struct FCB (**hpfnfcb)[]; extern typeTS tsMruBps; extern CHAR (*rgbp)[cbSector]; #ifdef CKSM #ifdef DEBUG extern unsigned (**hpibpcksm) []; #endif #endif /* WriteDirtyPages kicks out of memory as much of the previous files as it can in order to fill the page buffers with a new file. This is called on every transfer load of a file. */ WriteDirtyPages() {/* Description: Cleans the buffer pool of all dirty pages by writing them out to disk. If a disk full condition is reached, only pages which actually made it to disk are marked as non dirty. Returns: nothing. */ int ibp; struct BPS *pbps = &mpibpbps [0]; for (ibp = 0; ibp < ibpMax; ++ibp, ++pbps) { #ifdef CKSM #ifdef DEBUG if (pbps->fn != fnNil && !pbps->fDirty) Assert( (**hpibpcksm) [ibp] == CksmFromIbp( ibp ) ); #endif #endif if (pbps->fn != fnNil && pbps->fDirty) { FFlushFn(pbps->fn); /* keep on flushing if failure ? */ } } } ReadFilePages(fn) int fn; { /* Description: ReadFilePages tries to read in as much of a file as it can. The idea is to fill the page buffers in anticipation of much access. This is called on every Transfer Load of a file. If fn == fnNil or there are no characters in the file, ReadFilePages simply returns. Returns: nothing */ int ibp; int cfcRead; int cpnRead; int dfcMac; typeFC fcMac; int ibpReadMax; int cfcLastPage; int iibp; struct FCB *pfcb; typeTS ts; if (fn == fnNil) return; /* Write ALL dirty pages to disk */ WriteDirtyPages(); /* Just in case */ pfcb = &(**hpfnfcb)[fn]; /* we read as much of the file as will fit in the page buffers */ /* Note that we assume that fcMax is coercable to an integer. This is valid as long as ibpMax*cbSector < 32k */ dfcMac = (int) FcMin(pfcb->fcMac, (typeFC) (ibpMax * cbSector)); if (dfcMac == 0) return; if (vfSysFull) /* call to FFlushFn in WriteDirtyPages failed. the buffer algorithm assures us that the first cbpMustKeep ibp's do not contain scratch file information. Thus, there is no danger in overwriting these ibps. */ dfcMac = imin( dfcMac, (cbpMustKeep * cbSector) ); Assert( ((int)dfcMac) >= 0 ); /* Read pages from the file */ cfcRead = CchReadAtPage( fn, (typePN) 0, rgbp [0], (int) dfcMac, FALSE ); /* cfcRead contains a count of bytes read from the file */ ibpReadMax = ((cfcRead-1) / cbSector) + 1; cfcLastPage = cfcRead - (ibpReadMax-1)*cbSector; ts = ibpMax; /* order time stamps so the beginning slots have the greatest ts. Lru allocation will start at the end of the buffer table and work backward. Thus, the first page of the current file is considered the most recently used item. */ /* describe the newly filled pages */ for(ibp = 0; ibp < ibpReadMax; ++ibp) { struct BPS *pbps = &mpibpbps[ibp]; pbps->fn = fn; pbps->pn = ibp; pbps->ts = --ts; pbps->fDirty = false; pbps->cch = cbSector; pbps->ibpHashNext = ibpNil; } #ifdef CKSM #ifdef DEBUG { int ibpT; for ( ibpT = 0; ibpT < ibpReadMax; ibpT++ ) (**hpibpcksm) [ibpT] = CksmFromIbp( ibpT ); } #endif #endif /* fix some boundary conditions */ mpibpbps[ibpReadMax-1].cch = cfcLastPage; /* ?????? */ #ifdef CKSM #ifdef DEBUG (**hpibpcksm) [ibpReadMax - 1] = CksmFromIbp( ibpReadMax - 1 ); #endif #endif /* update descriptions of untouched page buffers */ for (ibp=ibpReadMax; ibp < ibpMax; ibp++) { struct BPS *pbps = &mpibpbps[ibp]; pbps->ts = --ts; pbps->fDirty = false; pbps->ibpHashNext = ibpNil; #ifdef CKSM #ifdef DEBUG if (pbps->fn != fnNil) (**hpibpcksm) [ibp] = CksmFromIbp( ibp ); #endif #endif } tsMruBps = ibpMax - 1; /* recalculate the hash table */ RehashRgibpHash(); } /* end of R e a d F i l e P a g e s */ RehashRgibpHash() { int iibp; register struct BPS *pbps; struct BPS *pbpsMax = &mpibpbps[ibpMax]; int iibpHash; int ibpT; int ibpPrev; int ibp; for (iibp = 0; iibp < iibpHashMax; iibp++) rgibpHash[iibp] = ibpNil; for (ibp = 0, pbps = &mpibpbps[0]; pbps < pbpsMax; pbps++, ibp++) { if (pbps->fn == fnNil) continue; iibpHash = IibpHash(pbps->fn, pbps->pn); ibpT = rgibpHash[iibpHash]; ibpPrev = ibpNil; while (ibpT != ibpNil) { ibpPrev = ibpT; ibpT = mpibpbps[ibpT].ibpHashNext; } if (ibpPrev == ibpNil) rgibpHash[iibpHash] = ibp; else mpibpbps[ibpPrev].ibpHashNext = ibp; } #ifdef DEBUG CheckIbp(); #endif } /* end of RehashRgibpHash */