home *** CD-ROM | disk | FTP | other *** search
- /* 89-08-18 Jahns set _bufsp_ref_ct from 0 to 1 */
-
-
-
- /* (c) 1985, Phoenix Computer Products Corp. and Novum Organum, Inc. */
- /***
- * Name: BfSpIst - create an instance of a buffer space.
- * BfSpRls - release an instance of a buffer space
- * BfSpParms - return the specification of current buffer space.
- *
- * Synopsis: bfspist(nbufs, bufsiz)
- * f_exists = bfsppars(&nbufs, &bufsiz)
- * NBUFS The number of buffers in buffer space
- * BUFSIZ The size of buffers in bytes.
- * F_EXISTS Flag indicating if buffer space is allocated
- *
- * bfsprls()
- * Description: A buffer space consists of a header which points to a
- * ring of buffer headers. Each buffer header points to a buffer
- * and contains information about the buffer's contents.
- * Whenever a new page must be read into memory, the least
- * recently used buffer is selected for reading. If the selected
- * buffer contains a page whose contents were altered, then the
- * 'dirty' page is written before the new one is read. The
- * buffer containing the new page is moved to the head of the
- * ring so that it is the last buffer looked at the next time
- * a buffer is needed (The ring is searched from the end toward
- * the front.)
- *
- *
- * Returns: BfSpParms() returns non-zero if a buffer space currently
- * exists. If one does, then the number of buffers in the
- * space and their size are also returned indirectly.
- *
- * (C) Novum Organum, Inc. 1985
- *
- ***/
-
-
- #include "pdefs.h"
-
- #define DIRTY_PG 1
- #define HAS_NEWPG 2
- #define EMPTY -1
-
- #define PC_HI 3
- #define PC_LOW 1
- #define PC_MED 2
- #define PC_PROTCTD 127
-
- #define BUF struct _BUF
- #define H_BUF ((BUF *)h_buf)
-
- BUF {
- HDL h_nxt_buf,
- h_prv_buf;
- short pg_in_buf;
- HDL h_fl;
- short bflags;
- short priority;
- short bsiz;
- char *addr;
- };
-
- #define BUFSPACE struct _BUFSPACE
-
- BUFSPACE{
- short nbufs;
- short bbufsiz;
- short f_far_bufs;
- char *pool;
- HDL ring_head;
- };
-
- #define SEEKERR (-1L)
- #define ALLFILS ((HDL)(-1))
-
- #define _H_BUFSP ((BUFSPACE *)_h_bufsp)
-
- static HDL _h_bufsp = 0/*NULLHDL*/;
- static int _bufsp_ref_ct=1;
-
- bfspist(nbufs, bufsiz)
- int nbufs,bufsiz;
- {
- char *memgive(), *memgivetrap(), *p;
- HDL ring_head, dlrlink(), h_buf;
-
- if (nbufs < 4) /* At lease 4 buffers are always allocated. */
- nbufs = 4;
-
- _bufsp_ref_ct++; /* Keep creation request reference count */
- /* in case more than one process is */
- /* allocating and freeing buffer space*/
-
- if (_h_bufsp == NULLHDL) /* If buffer space already exist, do nothing*/
- {
- /* Create the buffer space header. */
- _h_bufsp =(HDL)memgive(sizeof(BUFSPACE));
- /* The buffer space is maintained as a ring of */
- /* doubly linked buffers. */
-
- ring_head = NULLHDL;
- /* Get memory area big enough to hold all NBUF buffers. */
- /* 64K is largest buffer pool available. */
- p = memgivetrap((int)((uint)nbufs*(uint)bufsiz));
- if (p==NULLPTR)
- {
- p = memgive(4*bufsiz);
- nbufs = 4;
- }
- _H_BUFSP->nbufs = nbufs;
- _H_BUFSP->pool = p;
- _H_BUFSP->bbufsiz = bufsiz;
-
- /* Allocate buffer headers which keep information on what */
- /* file's pages are in the buffer; buffer priority and processing*/
- /* bflags. */
- while (nbufs--)
- {
- h_buf = (HDL)memgive (sizeof(BUF));
- H_BUF->h_nxt_buf = H_BUF->h_prv_buf = h_buf;
- ring_head = dlrlink(ring_head, h_buf);
- H_BUF->pg_in_buf = EMPTY;
- H_BUF->h_fl = NULLHDL;
- H_BUF->bflags = NO;
- H_BUF->priority = PC_LOW;
- H_BUF->addr = p;
- H_BUF->bsiz = bufsiz;
- p += bufsiz; /* Advance pool pointer to begin of next buf*/
- }
- _H_BUFSP->ring_head = ring_head;/*Point to first buf in ring. */
- }
- return (RC_SUCCESS);
- }
-
- bfsprls()
- {
- if (_bufsp_ref_ct > 0) /* If buffer's allocated at lease once */
- _bufsp_ref_ct--; /* then decrement reference count. */
-
- /* if reference count reached zero and buf-space exits then free*/
- if ((_bufsp_ref_ct > 0) && (_h_bufsp))
- {
- bfflush(); /* Clean out buffer. */
- memtake(_H_BUFSP->pool);/* Free buffer pool */
- memtakering(0, (char *)_H_BUFSP->ring_head);/* Free buffer headers.*/
- memtake((char *)_h_bufsp); /* Free buffer space header. */
- _h_bufsp = NULLHDL; /* Bind Null handle as active */
- }
- return(RC_SUCCESS);
- }
-
- bfspparms (pnbufs, pbufsiz)
- int *pnbufs, *pbufsiz;
- {
- if (_h_bufsp)
- {
- *pnbufs = _H_BUFSP->nbufs;
- *pbufsiz = _H_BUFSP->bbufsiz;
- }
- else
- *pnbufs = *pbufsiz = 0;
-
- return (_h_bufsp != NULLHDL);
- }
-
- /* Return the memory address of this buffer */
-
- char *bfaddr(h_buf)
- FAST HDL h_buf;
- {
- return (H_BUF->addr);
- }
-
-
- /* Append a new page to a file */
-
- HDL bfapppg (h_fl, pg_num)
- HDL h_fl;
- int pg_num;
- {
- HDL h_buf;
-
- if (!bfsrch(h_fl, pg_num, &h_buf))
- {
- bfsetpg (h_buf, h_fl, pg_num);
- bfmrkdirty (h_buf);
- }
- return (h_buf);
- }
-
- bffilflush (h_fl)
- HDL h_fl;
- {
- FAST HDL h_buf;
- HDL phd, bfring();
- int attrs;
-
- attrs = HAS_NEWPG;
-
- /* first flush new pages (HAS_NEWPG) */
- /* then flush old dirty pages (DIRTY_PG) */
-
- FOREVER {
- phd = h_buf = bfring();
-
- do {
- if ((h_fl == ALLFILS)
- || (H_BUF->h_fl == h_fl))
- {
- if (H_BUF->bflags & attrs)
- bftodisk (h_buf);
- }
- h_buf = H_BUF->h_nxt_buf;
- }
- while (h_buf != phd);/* do until back at head */
-
- if (attrs == HAS_NEWPG)
- attrs = DIRTY_PG;
- else
- break;
- }
- }
-
- bffilzap(h_fl)
- HDL h_fl;
- {
- FAST HDL h_buf;
- HDL phd, bfring();
-
- phd = h_buf = bfring();
-
- do {
- if ((h_fl == ALLFILS)
- || (H_BUF->h_fl == h_fl))
- {
- H_BUF->pg_in_buf = EMPTY;
- H_BUF->h_fl = NULLHDL;
- H_BUF->priority = PC_LOW;
- }
- h_buf = H_BUF->h_nxt_buf;
- }
- while (h_buf != phd);
- }
-
- bfflush ()
- {
- bffilflush (ALLFILS);
- }
-
- #define FROMBEG 0
-
- bffromdisk (h_fl, pg_num, h_buf)
- HDL h_fl;
- int pg_num;
- FAST HDL h_buf;
- {
- long flseek();
-
- flseek (h_fl, (long) pg_num * (long) H_BUF->bsiz, FROMBEG);
- flget (H_BUF->addr, H_BUF->bsiz, h_fl);
-
- H_BUF->pg_in_buf = pg_num;
- H_BUF->h_fl = h_fl;
- H_BUF->bflags = NULLVAL;
- }
-
- /* Return the file handle for the page in this buffer. */
- HDL bffhdl (h_buf)
- FAST HDL h_buf;
- {
- return (H_BUF->h_fl);
- }
-
- /* Lock this page in memory. This buffer will never be */
- /* selected to have its page written out to disk and a new */
- /* page read in. */
- bflck (h_buf)
- FAST HDL h_buf;
- {
- int old_pri;
-
- old_pri = H_BUF->priority;
- H_BUF->priority = PC_PROTCTD;
-
- return (old_pri);
- }
-
- HDL bflku (h_fl, pg)
- HDL h_fl;
- int pg;
- {
- FAST HDL h_buf;
- HDL phd, inbuf, bfring();
-
- phd = h_buf = bfring();
- inbuf = NULLHDL;
-
- do {
- if ((H_BUF->h_fl == h_fl) && (H_BUF->pg_in_buf == pg))
- {
- bftohd (h_buf);
- inbuf = h_buf;
- break;
- }
- h_buf = H_BUF->h_nxt_buf;
- }
- while (h_buf != phd);
-
- return (inbuf);
- }
-
- /* Mark that the page in this buffer has been altered. */
- bfmrkdirty (h_buf)
- FAST HDL h_buf;
- {
- H_BUF->bflags |= DIRTY_PG;
- }
-
- /* Set a flag indicating that the buffer contains a page */
- /* which as never been writen to disk (An appended page). */
- bfmrknewpg (h_buf)
- FAST HDL h_buf;
- {
- H_BUF->bflags |= HAS_NEWPG;
- }
-
- /* Return the number of the page in the buffer. */
- bfpginbuf (h_buf)
- FAST HDL h_buf;
- {
- return (H_BUF->pg_in_buf);
- }
-
- /* Return the priority of the specified buffer. */
- bfpri (h_buf)
- FAST HDL h_buf;
- {
- return ((int) H_BUF->priority);
- }
-
- /* return the handle of the first buffer header in bufspace ring.*/
- HDL bfring()
- {
- return (_H_BUFSP->ring_head);
- }
-
- /* Set the page number and file handle to show contains of this buffer. */
-
- bfsetpg (h_buf, h_fl, pg_num)
- FAST HDL h_buf;
- int pg_num;
- HDL h_fl;
- {
- H_BUF->h_fl = h_fl;
- H_BUF->pg_in_buf = pg_num;
- }
-
- int bfsizof()
- {
- return (_H_BUFSP->bbufsiz);
- }
-
- #define H_FREE ((BUF *)h_free)
- #define H_HEAD ((BUF *)h_head)
-
- int bfsrch (h_fl, pg, ph_buf)
- HDL h_fl;
- int pg;
- HDL *ph_buf;
- {
- HDL bfring(), h_head, h_buf, h_free;
- int f_fnd;
-
- h_free = NULLHDL;
- h_head = h_buf = bfring();
- f_fnd = NO;
-
- do {
- if ((H_BUF->h_fl == h_fl) && (H_BUF->pg_in_buf == pg))
- {
- h_free = h_buf;
- f_fnd = YES;
- break;
- }
- else
- if (H_BUF->priority != PC_PROTCTD)
- h_free = h_buf;
- h_buf = H_BUF->h_nxt_buf;
- }
- while (h_buf != h_head);
-
- if (!h_free)
- /* all pages are protectd priority (help!) */
- sylongjmp(SE_NOFREEBUFS);
-
- if (!f_fnd)/* didn't find page already in a buffer */
- { /* clean chosen buffer so can read in desired page */
- if (H_FREE->bflags & DIRTY_PG)
- bftodisk (h_free);
- H_FREE->priority = PC_LOW;
- }
- bftohd (h_free);
- *ph_buf = h_free;
- return (f_fnd);
- }
-
- bftodisk (h_buf)
- FAST HDL h_buf;
- {
- long flseek();
- /* If this buffer is not empty, then write to disk. */
- if (H_BUF->pg_in_buf != EMPTY)
- {
- /* Move to proper place in file to write page. */
- flseek(H_BUF->h_fl,(long)H_BUF->pg_in_buf*(long)H_BUF->bsiz,FROMBEG);
- /* Write out the page. */
- flput(H_BUF->addr, H_BUF->bsiz, H_BUF->h_fl);
- }
- /* Reset bflags to zero. */
- H_BUF->bflags &= (~(HAS_NEWPG | DIRTY_PG));
- }
-
- /* Move a buffer to the head the ring. When a new buffer is needed, */
- /* the ring is searched from the tail toward the head. Thus the head */
- /* buffer is the least likely to be selected. */
-
- bftohd (h_buf)
- FAST HDL h_buf;
- {
- HDL dlrtohd();
- _H_BUFSP->ring_head = dlrtohd(_H_BUFSP->ring_head, h_buf);
- }
-
- /* Read a page from the disk into a buffer. */
-
- HDL bftomem (h_fl, pg_num)
- HDL h_fl;
- int pg_num;
- {
- HDL h_buf;
- /* If the requested page was not found already in the buffer */
- /* space, then read the page from disk. */
- if (bfsrch (h_fl, pg_num, &h_buf) == NO)
- bffromdisk (h_fl, pg_num, h_buf);
- return (h_buf);
- }
-
- /* Set a buffer's priority. */
-
- bfunlck (h_buf, priority)
- FAST HDL h_buf;
- int priority;
- {
- H_BUF->priority = priority;
- }
-
- /* Zap the buffers for all the files currently having pages in buf space */
- bfzap ()
- {
- bffilzap(ALLFILS);
- }
-