home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 13 / 13.iso / s / s001 / 1.ddi / PFC / SRC / BUF.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-18  |  10.5 KB  |  464 lines

  1. /* 89-08-18 Jahns    set _bufsp_ref_ct from 0 to 1            */
  2.  
  3.  
  4.  
  5. /* (c) 1985, Phoenix Computer Products Corp. and Novum Organum, Inc. */
  6. /***
  7. * Name:        BfSpIst    - create an instance of a buffer space.
  8. *        BfSpRls - release an instance of a buffer space
  9. *        BfSpParms - return the specification of current buffer space.
  10. *
  11. * Synopsis:    bfspist(nbufs, bufsiz)
  12. *        f_exists = bfsppars(&nbufs, &bufsiz)
  13. *            NBUFS    The number of buffers in buffer space
  14. *            BUFSIZ    The size of buffers in bytes.
  15. *            F_EXISTS Flag indicating if buffer space is allocated
  16. *
  17. *        bfsprls()
  18. * Description:    A buffer space consists of a header which points to a
  19. *        ring of buffer headers.  Each buffer header points to a buffer
  20. *        and contains information about the buffer's contents. 
  21. *        Whenever a new page must be read into memory, the least 
  22. *        recently used buffer is selected for reading.  If the selected
  23. *        buffer contains a page whose contents were altered, then the 
  24. *        'dirty' page is written before the new one is read.  The 
  25. *        buffer containing the new page is moved to the head of the 
  26. *        ring so that it is the last buffer looked at the next time 
  27. *        a buffer is needed (The ring is searched from the end toward 
  28. *        the front.)
  29. *        
  30. *
  31. * Returns:    BfSpParms() returns non-zero if a buffer space currently 
  32. *        exists. If one does, then the number of buffers in the 
  33. *        space and their size are also returned indirectly.
  34. *
  35. * (C) Novum Organum, Inc. 1985
  36. *
  37. ***/
  38.  
  39.  
  40. #include "pdefs.h"
  41.  
  42. #define    DIRTY_PG    1
  43. #define    HAS_NEWPG    2
  44. #define    EMPTY        -1
  45.  
  46. #define PC_HI        3
  47. #define PC_LOW        1
  48. #define PC_MED        2
  49. #define PC_PROTCTD    127
  50.  
  51. #define    BUF    struct _BUF
  52. #define    H_BUF    ((BUF *)h_buf)
  53.  
  54. BUF    { 
  55.     HDL    h_nxt_buf,
  56.         h_prv_buf;
  57.     short   pg_in_buf; 
  58.     HDL    h_fl;
  59.     short    bflags;
  60.     short     priority; 
  61.     short    bsiz;
  62.     char    *addr;
  63.     }; 
  64.  
  65. #define    BUFSPACE struct _BUFSPACE
  66.  
  67. BUFSPACE{
  68.     short    nbufs;
  69.     short    bbufsiz;
  70.     short    f_far_bufs;
  71.     char    *pool;
  72.     HDL    ring_head;
  73.     };
  74.  
  75. #define    SEEKERR    (-1L)
  76. #define    ALLFILS    ((HDL)(-1))
  77.  
  78. #define    _H_BUFSP ((BUFSPACE *)_h_bufsp)
  79.  
  80. static HDL      _h_bufsp = 0/*NULLHDL*/;
  81. static int    _bufsp_ref_ct=1;
  82.  
  83. bfspist(nbufs, bufsiz)
  84.         int    nbufs,bufsiz;
  85. {
  86.         char    *memgive(), *memgivetrap(), *p;
  87.         HDL    ring_head, dlrlink(), h_buf;
  88.  
  89.     if    (nbufs < 4)        /* At lease 4 buffers are always allocated. */
  90.         nbufs = 4;
  91.  
  92.     _bufsp_ref_ct++;        /* Keep creation request reference count */
  93.                 /*   in case more than one process is     */
  94.                 /*   allocating and freeing buffer space*/
  95.  
  96.     if  (_h_bufsp == NULLHDL)    /* If buffer space already exist, do nothing*/
  97.     {
  98.         /* Create the buffer space header.        */
  99.     _h_bufsp =(HDL)memgive(sizeof(BUFSPACE));
  100.         /* The buffer space is maintained as a ring of     */
  101.         /* doubly linked buffers.            */
  102.  
  103.         ring_head = NULLHDL;
  104.     /* Get memory area big enough to hold all NBUF buffers.    */
  105.     /* 64K is largest buffer pool available.        */
  106.     p = memgivetrap((int)((uint)nbufs*(uint)bufsiz));
  107.     if  (p==NULLPTR)
  108.         {
  109.         p = memgive(4*bufsiz);
  110.         nbufs = 4;
  111.         }
  112.     _H_BUFSP->nbufs = nbufs;
  113.     _H_BUFSP->pool = p;
  114.     _H_BUFSP->bbufsiz = bufsiz;
  115.  
  116.     /* Allocate buffer headers which keep information on what     */
  117.     /* file's pages are in the buffer; buffer priority and processing*/
  118.     /* bflags. */
  119.     while (nbufs--)
  120.         {
  121.         h_buf = (HDL)memgive (sizeof(BUF));
  122.         H_BUF->h_nxt_buf = H_BUF->h_prv_buf = h_buf;
  123.         ring_head = dlrlink(ring_head, h_buf);
  124.         H_BUF->pg_in_buf = EMPTY;
  125.         H_BUF->h_fl = NULLHDL;
  126.         H_BUF->bflags = NO;
  127.         H_BUF->priority = PC_LOW;
  128.         H_BUF->addr = p;
  129.         H_BUF->bsiz = bufsiz;
  130.         p += bufsiz;    /* Advance pool pointer to begin of next buf*/
  131.         }          
  132.     _H_BUFSP->ring_head = ring_head;/*Point to first buf in ring. */
  133.     }
  134.     return (RC_SUCCESS);
  135. }
  136.  
  137. bfsprls()
  138. {
  139.     if    (_bufsp_ref_ct > 0)    /* If buffer's allocated at lease once    */
  140.     _bufsp_ref_ct--;    /* then decrement reference count.    */
  141.  
  142.     /* if reference count reached zero and buf-space exits then free*/
  143.     if    ((_bufsp_ref_ct > 0) && (_h_bufsp))
  144.         {
  145.     bfflush();        /* Clean out buffer.    */
  146.         memtake(_H_BUFSP->pool);/* Free buffer pool    */
  147.         memtakering(0, (char *)_H_BUFSP->ring_head);/* Free buffer headers.*/
  148.         memtake((char *)_h_bufsp);    /* Free buffer space header.    */
  149.         _h_bufsp = NULLHDL;        /* Bind Null handle as active    */
  150.         }
  151.     return(RC_SUCCESS);
  152. }
  153.  
  154. bfspparms (pnbufs, pbufsiz)
  155.     int    *pnbufs, *pbufsiz;
  156. {
  157.     if  (_h_bufsp)
  158.     {
  159.     *pnbufs = _H_BUFSP->nbufs;
  160.     *pbufsiz = _H_BUFSP->bbufsiz;
  161.     }
  162.     else
  163.     *pnbufs = *pbufsiz = 0;
  164.  
  165.     return (_h_bufsp != NULLHDL);
  166. }
  167.  
  168. /* Return the memory address of this buffer            */
  169.  
  170. char *bfaddr(h_buf)
  171. FAST    HDL     h_buf;
  172. {
  173.     return (H_BUF->addr);
  174. }
  175.  
  176.  
  177. /* Append a new page to a file        */
  178.  
  179. HDL bfapppg (h_fl, pg_num)
  180.     HDL    h_fl;
  181.     int   pg_num;
  182. {
  183.     HDL    h_buf;
  184.  
  185.     if    (!bfsrch(h_fl, pg_num, &h_buf)) 
  186.     {
  187.         bfsetpg (h_buf, h_fl, pg_num);
  188.         bfmrkdirty (h_buf);
  189.         }
  190.     return (h_buf);
  191. }
  192.  
  193. bffilflush (h_fl)
  194.     HDL    h_fl;
  195. {
  196. FAST    HDL     h_buf;
  197.         HDL    phd, bfring();
  198.         int    attrs;
  199.  
  200.     attrs = HAS_NEWPG;
  201.  
  202.     /* first flush new pages (HAS_NEWPG) */
  203.     /* then flush old dirty pages (DIRTY_PG) */
  204.  
  205.     FOREVER {
  206.         phd = h_buf = bfring();
  207.  
  208.         do  {
  209.             if      ((h_fl == ALLFILS)
  210.                 || (H_BUF->h_fl == h_fl))
  211.                 {
  212.                 if  (H_BUF->bflags & attrs)
  213.                     bftodisk (h_buf);
  214.                 }
  215.             h_buf = H_BUF->h_nxt_buf;
  216.             }
  217.         while    (h_buf != phd);/* do until back at head */
  218.         
  219.         if  (attrs == HAS_NEWPG)
  220.         attrs = DIRTY_PG;
  221.     else
  222.         break;
  223.         }
  224. }
  225.  
  226. bffilzap(h_fl)
  227.         HDL    h_fl;   
  228. {
  229. FAST    HDL     h_buf;
  230.         HDL    phd, bfring();
  231.  
  232.     phd = h_buf = bfring();
  233.     
  234.     do     {
  235.         if    ((h_fl == ALLFILS)
  236.               || (H_BUF->h_fl == h_fl))
  237.             {    
  238.             H_BUF->pg_in_buf = EMPTY;
  239.             H_BUF->h_fl = NULLHDL;
  240.             H_BUF->priority = PC_LOW;
  241.             }
  242.         h_buf = H_BUF->h_nxt_buf;
  243.         }
  244.     while (h_buf != phd);
  245. }
  246.  
  247. bfflush ()
  248. {
  249.     bffilflush (ALLFILS);
  250. }
  251.  
  252. #define    FROMBEG    0
  253.  
  254. bffromdisk (h_fl, pg_num, h_buf)
  255.     HDL    h_fl;
  256.     int   pg_num;
  257. FAST    HDL     h_buf;
  258. {
  259.     long flseek();
  260.  
  261.     flseek (h_fl, (long) pg_num * (long) H_BUF->bsiz, FROMBEG);
  262.     flget (H_BUF->addr, H_BUF->bsiz, h_fl);
  263.  
  264.     H_BUF->pg_in_buf = pg_num;         
  265.     H_BUF->h_fl  = h_fl;
  266.     H_BUF->bflags = NULLVAL;
  267. }
  268.  
  269.     /* Return the file handle for the page in this buffer.    */
  270. HDL bffhdl (h_buf)
  271. FAST    HDL h_buf;
  272. {
  273.     return (H_BUF->h_fl);
  274. }
  275.  
  276.     /* Lock this page in memory.  This buffer will never be */
  277.     /* selected to have its page written out to disk and a new    */
  278.     /* page read in.                    */
  279. bflck (h_buf)
  280. FAST    HDL     h_buf;
  281. {
  282.     int   old_pri;
  283.  
  284.     old_pri = H_BUF->priority;
  285.     H_BUF->priority = PC_PROTCTD;
  286.     
  287.     return (old_pri);
  288. }
  289.  
  290. HDL bflku (h_fl, pg)
  291.         HDL    h_fl;
  292.         int   pg;
  293. {
  294. FAST    HDL     h_buf;
  295.         HDL    phd, inbuf, bfring();
  296.  
  297.     phd = h_buf = bfring();
  298.     inbuf = NULLHDL;
  299.     
  300.     do    {
  301.         if  ((H_BUF->h_fl == h_fl) && (H_BUF->pg_in_buf == pg))
  302.             {
  303.             bftohd (h_buf);
  304.             inbuf = h_buf;
  305.             break;
  306.             }
  307.         h_buf = H_BUF->h_nxt_buf;
  308.         }
  309.     while   (h_buf != phd);          
  310.  
  311.     return (inbuf);
  312. }
  313.  
  314.     /* Mark that the page in this buffer has been altered.    */
  315. bfmrkdirty (h_buf)
  316. FAST    HDL h_buf;
  317. {
  318.     H_BUF->bflags |= DIRTY_PG;
  319. }
  320.  
  321.     /* Set a flag indicating that the buffer contains a page    */
  322.     /* which as never been writen to disk (An appended page).    */
  323. bfmrknewpg (h_buf)
  324. FAST    HDL h_buf;
  325. {
  326.     H_BUF->bflags |= HAS_NEWPG;
  327. }
  328.  
  329.     /* Return the number of the page in the buffer.    */
  330. bfpginbuf (h_buf)
  331. FAST    HDL h_buf;
  332. {
  333.     return  (H_BUF->pg_in_buf);
  334. }
  335.  
  336.     /* Return the priority of the specified buffer.    */
  337. bfpri (h_buf)
  338. FAST    HDL h_buf;
  339. {
  340.     return ((int) H_BUF->priority);
  341. }
  342.  
  343.     /* return the handle of the first buffer header in bufspace ring.*/
  344. HDL bfring()
  345. {
  346.     return (_H_BUFSP->ring_head);
  347. }
  348.  
  349. /* Set the page number and file handle to show contains of this buffer.    */
  350.  
  351. bfsetpg (h_buf, h_fl, pg_num)
  352. FAST    HDL h_buf;
  353.     int   pg_num;
  354.     HDL    h_fl;
  355. {
  356.     H_BUF->h_fl = h_fl;
  357.     H_BUF->pg_in_buf = pg_num;
  358. }
  359.  
  360. int bfsizof()
  361. {
  362.     return  (_H_BUFSP->bbufsiz);
  363. }
  364.  
  365. #define    H_FREE    ((BUF *)h_free)
  366. #define    H_HEAD    ((BUF *)h_head)
  367.  
  368. int bfsrch (h_fl, pg, ph_buf)
  369.     HDL      h_fl;
  370.     int   pg;
  371.     HDL     *ph_buf;
  372. {
  373.     HDL    bfring(), h_head, h_buf, h_free;
  374.     int    f_fnd;
  375.     
  376.     h_free = NULLHDL;
  377.     h_head = h_buf = bfring();
  378.     f_fnd = NO;
  379.  
  380.     do    {
  381.         if  ((H_BUF->h_fl == h_fl) && (H_BUF->pg_in_buf == pg))
  382.             {
  383.             h_free = h_buf;
  384.             f_fnd = YES;
  385.             break;
  386.             }
  387.         else
  388.         if  (H_BUF->priority != PC_PROTCTD)
  389.             h_free = h_buf;
  390.         h_buf = H_BUF->h_nxt_buf;
  391.         }
  392.     while (h_buf != h_head);
  393.  
  394.     if    (!h_free)
  395.         /* all pages are protectd priority (help!) */
  396.         sylongjmp(SE_NOFREEBUFS);
  397.             
  398.     if    (!f_fnd)/* didn't find page already in a buffer */
  399.         {   /* clean chosen buffer so can read in desired page */
  400.         if  (H_FREE->bflags & DIRTY_PG)
  401.             bftodisk (h_free);
  402.         H_FREE->priority = PC_LOW;
  403.         }
  404.     bftohd (h_free);
  405.     *ph_buf = h_free;
  406.     return  (f_fnd);
  407. }
  408.  
  409. bftodisk (h_buf)
  410. FAST    HDL h_buf;
  411. {
  412.     long flseek();
  413.     /* If this buffer is not empty, then write to disk.        */
  414.     if    (H_BUF->pg_in_buf != EMPTY) 
  415.     {
  416.     /* Move to proper place in file to write page.            */
  417.     flseek(H_BUF->h_fl,(long)H_BUF->pg_in_buf*(long)H_BUF->bsiz,FROMBEG);
  418.     /* Write out the page.                        */
  419.     flput(H_BUF->addr, H_BUF->bsiz, H_BUF->h_fl);
  420.     }
  421.     /* Reset bflags to zero.    */
  422.     H_BUF->bflags &= (~(HAS_NEWPG | DIRTY_PG));
  423. }
  424.  
  425. /* Move a buffer to the head the ring.  When a new buffer is needed,    */
  426. /* the ring is searched from the tail toward the head.  Thus the head    */
  427. /* buffer is the least likely to be selected.                */
  428.  
  429. bftohd (h_buf)
  430. FAST    HDL h_buf;
  431. {
  432.     HDL    dlrtohd();
  433.     _H_BUFSP->ring_head = dlrtohd(_H_BUFSP->ring_head, h_buf);
  434. }
  435.  
  436. /* Read a page from the disk into a buffer.            */
  437.  
  438. HDL bftomem (h_fl, pg_num)
  439.     HDL        h_fl;
  440.     int       pg_num;
  441. {
  442.     HDL        h_buf;
  443.     /* If the requested page was not found already in the buffer    */
  444.     /* space, then read the page from disk.                */
  445.     if    (bfsrch (h_fl, pg_num, &h_buf) == NO)
  446.         bffromdisk (h_fl, pg_num, h_buf);
  447.     return (h_buf);
  448. }
  449.  
  450. /*    Set a buffer's priority.            */
  451.  
  452. bfunlck (h_buf, priority)
  453. FAST    HDL h_buf;
  454.         int   priority;
  455. {
  456.     H_BUF->priority = priority;
  457. }
  458.  
  459. /* Zap the buffers for all the files currently having pages in buf space */
  460. bfzap ()
  461. {
  462.     bffilzap(ALLFILS);
  463. }
  464.