home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / storage / ipc / sinvaladt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  32.0 KB  |  1,122 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *     sinvaladt.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    POSTGRES shared cache invalidation segment definitions.
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *
  10.  *   NOTES
  11.  *
  12.  *   IDENTIFICATION
  13.  *    $Header: /private/postgres/src/storage/ipc/RCS/sinvaladt.c,v 1.26 1992/07/30 19:51:20 mer Exp $
  14.  * ----------------------------------------------------------------
  15.  */
  16.  
  17. /* ----------------
  18.  *    include files
  19.  *
  20.  *    XXX yucky order dependency
  21.  * ----------------
  22.  */
  23.  
  24. #include "storage/ipci.h"
  25. #include "storage/ipc.h"
  26. #include "storage/sinvaladt.h"
  27. #include "storage/lmgr.h"
  28. #include "utils/log.h"
  29.  
  30. /* ----------------
  31.  *    global variable notes
  32.  *
  33.  *    SharedInvalidationSemaphore
  34.  *
  35.  *    shmInvalBuffer
  36.  *        the shared buffer segment, set by SISegmentAttach()
  37.  *
  38.  *    MyBackendId
  39.  *        might be removed later, used only for
  40.  *         debugging in debug routines (end of file)
  41.  *
  42.  *    SIDbId
  43.  *        identification of buffer (disappears)
  44.  *
  45.  *    SIRelId        \ 
  46.  *    SIDummyOid     \  identification of buffer
  47.  *    SIXidData     /
  48.  *    SIXid        /
  49.  *
  50.  *  XXX This file really needs to be cleaned up.  We switched to using
  51.  *    spinlocks to protect critical sections (as opposed to using fake
  52.  *    relations and going through the lock manager) and some of the old
  53.  *    cruft was 'ifdef'ed out, while other parts (now unused) are still
  54.  *    compiled into the system. -mer 5/24/92
  55.  * ----------------
  56.  */
  57. #ifdef HAS_TEST_AND_SET
  58. int SharedInvalidationLockId;
  59. #else
  60. IpcSemaphoreId    SharedInvalidationSemaphore;
  61. #endif
  62. SISeg        *shmInvalBuffer;    
  63. extern BackendId MyBackendId;
  64.  
  65. OID         SIDbId = 0;        
  66. LRelId      SIRelId;            
  67. OID         SIDummyOid = InvalidObjectId;
  68.  
  69. #ifdef _FOO_BAR_BAZ_
  70. /*
  71.  * XXX this won't work now with 4 byte xid's it should probably be torched.
  72.  */
  73. TransactionIdData    SIXidData;
  74. TransactionId        SIXid = &SIXidData;
  75. #endif
  76.  
  77. /* ----------------
  78.  *    declarations
  79.  * ----------------
  80.  */
  81.  
  82. /*
  83.  * SISetActiveProcess --
  84.  */
  85. extern
  86. BackendId
  87. SIAssignBackendId ARGS((
  88.     SISeg         *segInOutP,
  89.     BackendTag    tag
  90. ));
  91.  
  92. /*
  93.  * CleanupInvalidationState --
  94.  * Note:
  95.  *    This is a temporary hack.  ExitBackend should call this instead
  96.  *    of exit (via on_exitpg).
  97.  */
  98. extern
  99. void
  100. CleanupInvalidationState ARGS((
  101.     int        status,    /* XXX */
  102.     SISeg        *segInOutP
  103. ));
  104.  
  105. /************************************************************************/
  106. /* SISetActiveProcess(segP, backendId)    set the backend status active    */
  107. /*      should be called only by the postmaster when creating a backend    */
  108. /************************************************************************/
  109. /* XXX I suspect that the segP parameter is extraneous. -hirohama */
  110. void
  111. SISetActiveProcess(segInOutP, backendId)
  112.     SISeg     *segInOutP;
  113.     BackendId     backendId;
  114. {
  115.     /* mark all messages as read */
  116.  
  117.     /* Assert(segP->procState[backendId - 1].tag == MyBackendTag); */
  118.  
  119.     segInOutP->procState[backendId - 1].resetState = false;
  120.     segInOutP->procState[backendId - 1].limit = SIGetNumEntries(segInOutP);
  121. }
  122.  
  123. /****************************************************************************/
  124. /* SIBackendInit()  initializes a backend to operate on the buffer          */
  125. /****************************************************************************/
  126. int
  127. SIBackendInit(segInOutP)
  128.     SISeg         *segInOutP;
  129. {
  130.     LRelId                  LtCreateRelId();
  131.     TransactionId           LMITransactionIdCopy();
  132.     
  133.     Assert(MyBackendTag > 0);
  134.  
  135.     MyBackendId = SIAssignBackendId(segInOutP, MyBackendTag);
  136.     if (MyBackendId == InvalidBackendTag)
  137.     return 0;
  138.  
  139. #ifdef    INVALIDDEBUG
  140.     elog(DEBUG, "SIBackendInit: backend tag %d; backend id %d.",
  141.      MyBackendTag, MyBackendId);
  142. #endif    INVALIDDEBUG
  143.  
  144.     SISetActiveProcess(segInOutP, MyBackendId);
  145.     on_exitpg(CleanupInvalidationState, segInOutP);
  146.     return 1;
  147. }
  148.  
  149. /* ----------------
  150.  *    SIAssignBackendId
  151.  * ----------------
  152.  */
  153. BackendId
  154. SIAssignBackendId(segInOutP, backendTag)
  155.     SISeg        *segInOutP;
  156.     BackendTag    backendTag;
  157. {
  158.     Index        index;
  159.     ProcState    *stateP;
  160.  
  161.     stateP = NULL;
  162.  
  163.     for (index = 0; index < MaxBackendId; index += 1) {
  164.     if (segInOutP->procState[index].tag == InvalidBackendTag ||
  165.         segInOutP->procState[index].tag == backendTag)
  166.         {
  167.         stateP = &segInOutP->procState[index];
  168.         break;
  169.         }
  170.  
  171.     if (!PointerIsValid(stateP) ||
  172.         (segInOutP->procState[index].resetState &&
  173.          (!stateP->resetState ||
  174.           stateP->tag < backendTag)) ||
  175.         (!stateP->resetState &&
  176.          (segInOutP->procState[index].limit <
  177.           stateP->limit ||
  178.           stateP->tag < backendTag)))
  179.         {
  180.         stateP = &segInOutP->procState[index];
  181.         }
  182.     }
  183.  
  184.     /* verify that all "procState" entries checked for matching tags */
  185.  
  186.     for (index += 1; index < MaxBackendId; index += 1) {
  187.     if (segInOutP->procState[index].tag == backendTag) {
  188.         elog (FATAL, "SIAssignBackendId: tag %d found twice",
  189.           backendTag);
  190.     }
  191.     }
  192.  
  193.     if (stateP->tag != InvalidBackendTag) {
  194.     if (stateP->tag == backendTag) {
  195.         elog(NOTICE, "SIAssignBackendId: reusing tag %d",
  196.          backendTag);
  197.     } else {
  198.         elog(NOTICE,
  199.          "SIAssignBackendId: discarding tag %d",
  200.          stateP->tag);
  201.         return InvalidBackendTag;
  202.     }
  203.     }
  204.  
  205.     stateP->tag = backendTag;
  206.  
  207.     return (1 + stateP - &segInOutP->procState[0]);
  208. }
  209.  
  210.  
  211. /************************************************************************/
  212. /* The following function should be called only by the postmaster !!    */
  213. /************************************************************************/
  214.  
  215. /************************************************************************/
  216. /* SISetDeadProcess(segP, backendId)  set the backend status DEAD       */
  217. /*      should be called only by the postmaster when a backend died     */
  218. /************************************************************************/
  219. void
  220. SISetDeadProcess(segP, backendId)
  221.     SISeg     *segP;
  222.     int     backendId;
  223. {
  224.     /* XXX call me.... */
  225.  
  226.     segP->procState[backendId - 1].resetState = false;
  227.     segP->procState[backendId - 1].limit = -1;
  228.     segP->procState[backendId - 1].tag = InvalidBackendTag;
  229. }
  230.  
  231. /* ----------------
  232.  *    CleanupInvalidationState
  233.  * ----------------
  234.  */
  235. void
  236. CleanupInvalidationState(status, segInOutP)
  237.     int        status;        /* XXX */
  238.     SISeg    *segInOutP;    /* XXX style */
  239. {
  240.     Assert(PointerIsValid(segInOutP));
  241.  
  242.     SISetDeadProcess(segInOutP, MyBackendId);
  243. }
  244.  
  245.  
  246. /************************************************************************/
  247. /* SIComputeSize()  - retuns the size of a buffer segment               */
  248. /************************************************************************/
  249. SISegOffsets *
  250. SIComputeSize(segSize)
  251.     int *segSize;
  252. {
  253.     int           A, B, a, b, totalSize;
  254.     SISegOffsets *oP;
  255.  
  256.     A = 0;
  257.     a = SizeSISeg;      /* offset to first data entry */
  258.     b = SizeOfOneSISegEntry * MAXNUMMESSAGES;
  259.     B = A + a + b;
  260.     totalSize = B - A;
  261.     *segSize = totalSize;
  262.     
  263.     oP = (SISegOffsets *) palloc(sizeof(SISegOffsets));
  264.     oP->startSegment = A;
  265.     oP->offsetToFirstEntry = a; /* relatiove to A */
  266.     oP->offsetToEndOfSegemnt = totalSize; /* relative to A */
  267.     return(oP);
  268. }
  269.  
  270.  
  271. /************************************************************************/
  272. /* SIGetSemaphoreId - returns the general semaphore Id                    */
  273. /************************************************************************/
  274. SIGetSemaphoreId(segP)
  275.     SISeg *segP;
  276. {
  277.     return(segP->generalSemaphoreId);
  278. }
  279.  
  280.  
  281. /************************************************************************/
  282. /* SISetSemaphoreId     - sets the general semaphore Id                    */
  283. /************************************************************************/
  284. void
  285. SISetSemaphoreId(segP, id)
  286.     SISeg *segP;
  287.     IpcSemaphoreId id;
  288. {
  289.     segP->generalSemaphoreId = id;
  290. }
  291.  
  292.  
  293. /************************************************************************/
  294. /* SISetStartEntrySection(segP, offset)     - sets the offset        */
  295. /************************************************************************/
  296. void
  297. SISetStartEntrySection(segP, offset)
  298.     SISeg *segP;
  299.     Offset offset;
  300. {
  301.     segP->startEntrySection = offset;
  302. }
  303.  
  304. /************************************************************************/
  305. /* SIGetStartEntrySection(segP)     - returnss the offset           */
  306. /************************************************************************/
  307. Offset
  308. SIGetStartEntrySection(segP)
  309. SISeg *segP;
  310. {
  311.     return(segP->startEntrySection);
  312. }
  313.  
  314.  
  315. /************************************************************************/
  316. /* SISetEndEntrySection(segP, offset)     - sets the offset           */
  317. /************************************************************************/
  318. void
  319. SISetEndEntrySection(segP, offset)
  320.     SISeg *segP;
  321.     Offset offset;
  322. {
  323.     segP->endEntrySection = offset;
  324. }
  325.  
  326. /************************************************************************/
  327. /* SIGetEndEntrySection(segP)     - returnss the offset                    */
  328. /************************************************************************/
  329. Offset
  330. SIGetEndEntrySection(segP)
  331.     SISeg *segP;
  332. {
  333.     return(segP->endEntrySection);
  334. }
  335.  
  336. /************************************************************************/
  337. /* SISetEndEntryChain(segP, offset)     - sets the offset               */
  338. /************************************************************************/
  339. void
  340. SISetEndEntryChain(segP, offset)
  341.     SISeg *segP;
  342.     Offset offset;
  343. {
  344.     segP->endEntryChain = offset;
  345. }
  346.  
  347. /************************************************************************/
  348. /* SIGetEndEntryChain(segP)     - returnss the offset                    */
  349. /************************************************************************/
  350. Offset
  351. SIGetEndEntryChain(segP)
  352.     SISeg *segP;
  353. {
  354.     return(segP->endEntryChain);
  355. }
  356.  
  357. /************************************************************************/
  358. /* SISetStartEntryChain(segP, offset)     - sets the offset               */
  359. /************************************************************************/
  360. void
  361. SISetStartEntryChain(segP, offset)
  362.     SISeg *segP;
  363.     Offset offset;
  364. {
  365.     segP->startEntryChain = offset;
  366. }
  367.  
  368. /************************************************************************/
  369. /* SIGetStartEntryChain(segP)     - returns  the offset                    */
  370. /************************************************************************/
  371. Offset
  372. SIGetStartEntryChain(segP)
  373.     SISeg *segP;
  374. {
  375.     return(segP->startEntryChain);
  376. }
  377.  
  378. /************************************************************************/
  379. /* SISetNumEntries(segP, num)    sets the current nuber of entries       */
  380. /************************************************************************/
  381. bool
  382. SISetNumEntries(segP, num)
  383.     SISeg *segP;
  384.     int   num;
  385. {
  386.     if ( num <= MAXNUMMESSAGES) {
  387.         segP->numEntries =  num;
  388.         return(true);
  389.     } else {
  390.         return(false);  /* table full */
  391.     }    
  392. }
  393.  
  394. /************************************************************************/
  395. /* SIGetNumEntries(segP)    - returns the current nuber of entries      */
  396. /************************************************************************/
  397. int
  398. SIGetNumEntries(segP)
  399.     SISeg *segP;
  400. {
  401.     return(segP->numEntries);
  402. }
  403.  
  404.  
  405. /************************************************************************/
  406. /* SISetMaxNumEntries(segP, num)    sets the maximal number of entries    */
  407. /************************************************************************/
  408. bool
  409. SISetMaxNumEntries(segP, num)
  410.     SISeg *segP;
  411.     int   num;
  412. {
  413.     if ( num <= MAXNUMMESSAGES) {
  414.         segP->maxNumEntries =  num;
  415.         return(true);
  416.     } else {
  417.         return(false);  /* wrong number */
  418.     }   
  419. }
  420.  
  421.  
  422. /************************************************************************/
  423. /* SIGetMaxNumEntries(segP)     returns the maximal number of entries    */
  424. /************************************************************************/
  425. int
  426. SIGetMaxNumEntries(segP)
  427.     SISeg *segP;
  428. {
  429.     return(segP->maxNumEntries);
  430. }
  431.  
  432. /************************************************************************/
  433. /* SIGetProcStateLimit(segP, i)    returns the limit of read messages      */
  434. /************************************************************************/
  435. int
  436. SIGetProcStateLimit(segP, i) 
  437.     SISeg     *segP;
  438.     int     i;
  439. {
  440.     return(segP->procState[i].limit);
  441. }
  442.  
  443. /************************************************************************/
  444. /* SIGetProcStateResetState(segP, i)  returns the limit of read messages*/
  445. /************************************************************************/
  446. bool
  447. SIGetProcStateResetState(segP, i) 
  448.     SISeg     *segP;
  449.     int     i;
  450. {
  451.     return((bool) segP->procState[i].resetState);
  452. }
  453.  
  454. /************************************************************************/
  455. /* SIIncNumEntries(segP, num)    increments the current nuber of entries    */
  456. /************************************************************************/
  457. bool
  458. SIIncNumEntries(segP, num)
  459.     SISeg *segP;
  460.     int   num;
  461. {
  462.     if ((segP->numEntries + num) <= MAXNUMMESSAGES) {
  463.         segP->numEntries = segP->numEntries + num;
  464.         return(true);
  465.     } else {
  466.         return(false);  /* table full */
  467.     }   
  468. }
  469.  
  470. /************************************************************************/
  471. /* SIDecNumEntries(segP, num)    decrements the current nuber of entries    */
  472. /************************************************************************/
  473. bool
  474. SIDecNumEntries(segP, num)
  475.     SISeg *segP;
  476.     int   num;
  477. {
  478.     if ((segP->numEntries - num) >=  0) {
  479.         segP->numEntries = segP->numEntries - num;
  480.         return(true);
  481.     } else {
  482.         return(false);  /* not enough entries in table */
  483.     }   
  484. }
  485.  
  486. /************************************************************************/
  487. /* SISetStartFreeSpace(segP, offset)  - sets the offset                    */
  488. /************************************************************************/
  489. void
  490. SISetStartFreeSpace(segP, offset)
  491.     SISeg *segP;
  492.     Offset offset;
  493. {
  494.     segP->startFreeSpace = offset;
  495. }
  496.  
  497. /************************************************************************/
  498. /* SIGetStartFreeSpace(segP)  - returns the offset                      */
  499. /************************************************************************/
  500. Offset
  501. SIGetStartFreeSpace(segP)
  502.     SISeg *segP;
  503. {
  504.     return(segP->startFreeSpace);
  505. }
  506.  
  507.  
  508.  
  509. /************************************************************************/
  510. /* SIGetFirstDataEntry(segP)  returns first data entry                    */
  511. /************************************************************************/
  512. SISegEntry *
  513. SIGetFirstDataEntry(segP)
  514.     SISeg *segP;
  515. {
  516.     SISegEntry  *eP;
  517.     Offset      startChain;
  518.     
  519.     startChain = SIGetStartEntryChain(segP);
  520.     
  521.     if (startChain == InvalidOffset)
  522.         return(NULL);
  523.          
  524.     eP = (SISegEntry  *) ((Pointer) segP + 
  525.                            SIGetStartEntrySection(segP) +
  526.                            startChain );
  527.     return(eP);
  528. }
  529.  
  530.  
  531. /************************************************************************/
  532. /* SIGetLastDataEntry(segP)  returns last data entry in the chain       */
  533. /************************************************************************/
  534. SISegEntry *
  535. SIGetLastDataEntry(segP)
  536.     SISeg *segP;
  537. {
  538.     SISegEntry  *eP;
  539.     Offset      endChain;
  540.     
  541.     endChain = SIGetEndEntryChain(segP);
  542.     
  543.     if (endChain == InvalidOffset)
  544.         return(NULL);
  545.          
  546.     eP = (SISegEntry  *) ((Pointer) segP + 
  547.                            SIGetStartEntrySection(segP) +
  548.                            endChain );
  549.     return(eP);
  550. }
  551.  
  552. /************************************************************************/
  553. /* SIGetNextDataEntry(segP, offset)  returns next data entry            */
  554. /************************************************************************/
  555. SISegEntry *
  556. SIGetNextDataEntry(segP, offset)
  557.     SISeg         *segP;
  558.     Offset       offset;
  559. {
  560.     SISegEntry  *eP;
  561.     
  562.     if (offset == InvalidOffset)
  563.         return(NULL);
  564.         
  565.     eP = (SISegEntry  *) ((Pointer) segP +
  566.                           SIGetStartEntrySection(segP) + 
  567.                           offset);
  568.     return(eP);
  569. }
  570.  
  571.  
  572. /************************************************************************/
  573. /* SIGetNthDataEntry(segP, n)    returns the n-th data entry in chain    */
  574. /************************************************************************/
  575. SISegEntry *
  576. SIGetNthDataEntry(segP, n)
  577.     SISeg     *segP;
  578.     int     n;      /* must range from 1 to MaxMessages */
  579. {
  580.     SISegEntry  *eP;
  581.     int            i;
  582.     
  583.     if (n <= 0) return(NULL);
  584.     
  585.     eP = SIGetFirstDataEntry(segP);
  586.     for (i = 1; i < n; i++) {
  587.         /* skip one and get the next    */
  588.         eP = SIGetNextDataEntry(segP, eP->next);
  589.     }
  590.     
  591.     return(eP);
  592. }
  593.  
  594. /************************************************************************/
  595. /* SIEntryOffset(segP, entryP)   returns the offset for an pointer      */
  596. /************************************************************************/
  597. Offset
  598. SIEntryOffset(segP, entryP)
  599.     SISeg      *segP;
  600.     SISegEntry *entryP;
  601. {
  602.     /* relative to B !! */
  603.     return ((Offset) ((Pointer) entryP -
  604.                       (Pointer) segP - 
  605.                       SIGetStartEntrySection(segP) ));
  606. }
  607.  
  608.  
  609. /************************************************************************/
  610. /* SISetDataEntry(segP, data)  - sets a message in the segemnt            */
  611. /************************************************************************/
  612. bool
  613. SISetDataEntry(segP, data)
  614.     SISeg *segP;
  615.     SharedInvalidData  *data;
  616. {
  617.     Offset          offsetToNewData;
  618.     SISegEntry         *eP, *lastP;
  619.     bool            SISegFull();
  620.     Offset          SIEntryOffset();
  621.     Offset          SIGetStartFreeSpace();
  622.     SISegEntry         *SIGetFirstDataEntry();
  623.     SISegEntry         *SIGetNextDataEntry();
  624.     SISegEntry         *SIGetLastDataEntry();
  625.  
  626.     if (!SIIncNumEntries(segP, 1)) 
  627.       return(false);  /* no space */
  628.     
  629.     /* get a free entry */
  630.     offsetToNewData = SIGetStartFreeSpace(segP);
  631.     eP = SIGetNextDataEntry(segP, offsetToNewData); /* it's a free one */
  632.     SISetStartFreeSpace(segP, eP->next);
  633.     /* fill it up */
  634.     eP->entryData = *data;
  635.     eP->isfree = false;
  636.     eP->next = InvalidOffset;
  637.     
  638.     /* handle insertion point at the end of the chain !!*/
  639.     lastP = SIGetLastDataEntry(segP);
  640.     if (lastP == NULL) {
  641.         /* there is no chain, insert the first entry */
  642.         SISetStartEntryChain(segP, SIEntryOffset(segP, eP));
  643.     } else {
  644.         /* there is a last entry in the chain */
  645.         lastP->next = SIEntryOffset(segP, eP);
  646.     }
  647.     SISetEndEntryChain(segP, SIEntryOffset(segP, eP));
  648.     return(true);
  649. }
  650.  
  651.  
  652. /************************************************************************/
  653. /* SIDecProcLimit(segP, num)  decrements all process limits             */
  654. /************************************************************************/
  655. void
  656. SIDecProcLimit(segP, num)
  657.     SISeg     *segP;
  658.     int     num;
  659. {
  660.     int i;
  661.     for (i=0; i < MaxBackendId; i++) {
  662.         /* decrement only, if there is a limit > 0  */
  663.         if (segP->procState[i].limit > 0) {
  664.             segP->procState[i].limit = segP->procState[i].limit - num;
  665.             if (segP->procState[i].limit < 0) {
  666.                 /* limit was not high enough, reset to zero */
  667.                 /* negative means it's a dead backend        */
  668.                 segP->procState[i].limit = 0;
  669.             }
  670.         }
  671.     }
  672. }
  673.  
  674.  
  675. /************************************************************************/
  676. /* SIDelDataEntry(segP)        - free the FIRST entry                       */
  677. /************************************************************************/
  678. bool
  679. SIDelDataEntry(segP)
  680.     SISeg     *segP;
  681. {
  682.     SISegEntry         *eP, *e1P;
  683.     SISegEntry         *SIGetFirstDataEntry();
  684.  
  685.     if (!SIDecNumEntries(segP, 1))  {
  686.         /* no entries in buffer */
  687.         return(false);
  688.     }
  689.     
  690.     e1P = SIGetFirstDataEntry(segP);
  691.     SISetStartEntryChain(segP, e1P->next);
  692.     if (SIGetStartEntryChain(segP) == InvalidOffset) {
  693.         /* it was the last entry */
  694.         SISetEndEntryChain(segP, InvalidOffset);
  695.     }
  696.     /* free the entry */
  697.     e1P->isfree = true;
  698.     e1P->next = SIGetStartFreeSpace(segP);
  699.     SISetStartFreeSpace(segP, SIEntryOffset(segP, e1P));
  700.     SIDecProcLimit(segP, 1);
  701.     return(true); 
  702. }
  703.  
  704.     
  705.  
  706. /************************************************************************/
  707. /* SISetProcStateInvalid(segP)    checks and marks a backends state as     */
  708. /*                                  invalid                             */
  709. /************************************************************************/
  710. void
  711. SISetProcStateInvalid(segP)
  712.     SISeg     *segP;
  713. {
  714.     int i;
  715.  
  716.     for (i=0; i < MaxBackendId; i++) {
  717.         if (segP->procState[i].limit == 0) {
  718.             /* backend i didn't read any message                        */
  719.             segP->procState[i].resetState = true;
  720.             /*XXX signal backend that it has to reset its internal cache ? */
  721.         }
  722.     }
  723. }
  724.  
  725. /************************************************************************/
  726. /* SIReadEntryData(segP, backendId, function)                            */
  727. /*                      - marks messages to be read by id               */
  728. /*                        and executes function                            */
  729. /************************************************************************/
  730. void
  731. SIReadEntryData(segP, backendId, invalFunction, resetFunction)
  732.     SISeg   *segP;
  733.     int     backendId;
  734.     void    (*invalFunction)();
  735.     void    (*resetFunction)();
  736. {
  737.     int i;
  738.     SISegEntry *data;
  739.  
  740.     Assert(segP->procState[backendId - 1].tag == MyBackendTag);
  741.  
  742.     if (!segP->procState[backendId - 1].resetState) {
  743.         /* invalidate data, but only those, you have not seen yet !!*/
  744.         /* therefore skip read messages */
  745.         i = 0;
  746.         data = SIGetNthDataEntry(segP, 
  747.                                  SIGetProcStateLimit(segP, backendId - 1) + 1);
  748.         while (data != NULL) {
  749.             i++;
  750.             segP->procState[backendId - 1].limit++;  /* one more message read */
  751.             invalFunction(data->entryData.cacheId, 
  752.                  data->entryData.hashIndex,
  753.                  &data->entryData.pointerData);
  754.             data = SIGetNextDataEntry(segP, data->next);
  755.         }
  756.         /* SIDelExpiredDataEntries(segP); */
  757.     } else {
  758.         /*backend must not read messages, its own state has to be reset        */
  759.         elog(NOTICE, "SIMarkEntryData: cache state reset");
  760.         resetFunction(); /* XXXX call it here, parameters? */
  761.  
  762.         /* new valid state--mark all messages "read" */
  763.         segP->procState[backendId - 1].resetState = false;
  764.         segP->procState[backendId - 1].limit = SIGetNumEntries(segP);
  765.     }
  766.     /* check whether we can remove dead messages                            */
  767.     if (i > MAXNUMMESSAGES) {
  768.         elog(FATAL, "SIReadEntryData: Invalid segment state");
  769.     }
  770. }
  771.  
  772. /************************************************************************/
  773. /* SIDelExpiredDataEntries  (segP)  - removes irrelevant messages       */
  774. /************************************************************************/
  775. void
  776. SIDelExpiredDataEntries(segP)
  777.     SISeg     *segP;
  778. {
  779.     int   min, i, h;
  780.     
  781.     min = 9999999;
  782.     for (i = 0; i < MaxBackendId; i++) {
  783.         h = SIGetProcStateLimit(segP, i);
  784.         if (h >= 0)  { /* backend active */
  785.             if (h < min ) min = h;
  786.         }
  787.     }
  788.     if (min != 9999999) {
  789.         /* we can remove min messages */
  790.         for (i = 1; i <= min; i++) {
  791.             /* this  adjusts also the state limits!*/
  792.             if (!SIDelDataEntry(segP)) { 
  793.                 elog(FATAL, "SIDelExpiredDataEntries: Invalid segment state");
  794.             }
  795.         }
  796.     }
  797. }
  798.  
  799.  
  800.  
  801. /************************************************************************/
  802. /* SISegInit(segP)  - initializes the segment                            */
  803. /************************************************************************/
  804. void
  805. SISegInit(segP)
  806.     SISeg *segP;
  807. {
  808.     SISegOffsets    *oP;
  809.     SISegOffsets    *SIComputeSize();
  810.     int                segSize, i;
  811.     SISegEntry      *eP;
  812.     
  813.     oP = SIComputeSize(&segSize);
  814.     /* set sempahore ids in the segment */
  815.     /* XXX */
  816.     SISetStartEntrySection(segP, oP->offsetToFirstEntry);
  817.     SISetEndEntrySection(segP, oP->offsetToEndOfSegemnt);
  818.     SISetStartFreeSpace(segP, 0);
  819.     SISetStartEntryChain(segP, InvalidOffset);
  820.     SISetEndEntryChain(segP, InvalidOffset);
  821.     (void) SISetNumEntries(segP, 0);
  822.     (void) SISetMaxNumEntries(segP, MAXNUMMESSAGES);
  823.     for (i = 0; i < MaxBackendId; i++) {
  824.         segP->procState[i].limit = -1;         /* no backend active  !!*/
  825.         segP->procState[i].resetState = false;
  826.         segP->procState[i].tag = InvalidBackendTag;
  827.     }
  828.     /* construct a chain of free entries                            */
  829.     for (i = 1; i < MAXNUMMESSAGES; i++)  {
  830.         eP = (SISegEntry  *) ((Pointer) segP +
  831.                              SIGetStartEntrySection(segP) +
  832.                              (i - 1) * sizeof(SISegEntry));
  833.         eP->isfree = true;
  834.         eP->next = i * sizeof(SISegEntry); /* relative to B */
  835.     }
  836.     /* handle the last free entry separate                          */
  837.     eP = (SISegEntry  *) ((Pointer) segP +
  838.                              SIGetStartEntrySection(segP) +
  839.                              (MAXNUMMESSAGES - 1) * sizeof(SISegEntry));
  840.     eP->isfree = true;
  841.     eP->next = InvalidOffset;  /* it's the end of the chain !! */
  842.     /*
  843.      * Be tidy
  844.      */
  845.     pfree(oP);
  846.                              
  847. }
  848.    
  849.  
  850.  
  851. /************************************************************************/
  852. /* SISegmentKill(key)   - kill any segment                              */
  853. /************************************************************************/
  854. void
  855. SISegmentKill(key)
  856.     int key;                    /* the corresponding key for the segment    */
  857. {   
  858.     IpcMemoryKill(key);
  859. }    
  860.  
  861.  
  862. /************************************************************************/
  863. /* SISegmentGet(key, size)  - get a shared segment of size <size>       */
  864. /*                returns a segment id                                  */
  865. /************************************************************************/
  866. IpcMemoryId
  867. SISegmentGet(key, size, create)
  868.     int     key;                /* the corresponding key for the segment    */
  869.     int     size;               /* size of segment in bytes                 */
  870.     bool    create;
  871. {
  872.     IpcMemoryId   shmid;
  873.  
  874.     if (create) {
  875.     shmid = IpcMemoryCreate(key, size, IPCProtection);
  876.     } else {
  877.     shmid = IpcMemoryIdGet(key, size);
  878.     }
  879.     return(shmid);
  880. }
  881.  
  882. /************************************************************************/
  883. /* SISegmentAttach(shmid)   - attach a shared segment with id shmid     */
  884. /************************************************************************/
  885. void
  886. SISegmentAttach(shmid)
  887.     IpcMemoryId   shmid;
  888. {
  889.     shmInvalBuffer = (struct SISeg *) IpcMemoryAttach(shmid);
  890.     if (shmInvalBuffer == IpcMemAttachFailed) {   
  891.     /* XXX use validity function */
  892.     elog(NOTICE, "SISegmentAttach: Could not attach segment");
  893.     elog(FATAL, "SISegmentAttach: %m");
  894.     }
  895. }
  896.  
  897.  
  898. /************************************************************************/
  899. /* SISegmentInit(killExistingSegment, key)  initialize segment            */
  900. /************************************************************************/
  901. int
  902. SISegmentInit(killExistingSegment, key)
  903.     bool    killExistingSegment;
  904.     IPCKey  key;
  905.     SISegOffsets    *oP;
  906.     int                 status, segSize;
  907.     IpcMemoryId            shmId;
  908.     bool                create;
  909.     
  910.     if (killExistingSegment) {
  911.         /* Kill existing segment */
  912.         /* set semaphore */
  913.         SISegmentKill(key);
  914.         
  915.         /* Get a shared segment */
  916.          
  917.         oP = SIComputeSize(&segSize);
  918.     /*
  919.      * Be tidy
  920.      */
  921.     pfree(oP);
  922.  
  923.         create = true;
  924.         shmId = SISegmentGet(key,segSize, create);
  925.         if (shmId < 0) {
  926.             perror("SISegmentGet: failed");
  927.             return(-1);                                     /* an error */
  928.         }
  929.  
  930.         /* Attach the shared cache invalidation  segment */
  931.         /* sets the global variable shmInvalBuffer */
  932.         SISegmentAttach(shmId);
  933.  
  934.         /* Init shared memory table */
  935.         SISegInit(shmInvalBuffer);  
  936.     } else {
  937.         /* use an existing segment */
  938.         create = false;
  939.         shmId = SISegmentGet(key, 0, create);
  940.         if (shmId < 0) {
  941.             perror("SISegmentGet: getting an existent segment failed");
  942.             return(-1);                                        /* an error */
  943.         }
  944.         /* Attach the shared cache invalidation segment */
  945.           SISegmentAttach(shmId);
  946.     }
  947.     return(1);
  948. }
  949.  
  950.  
  951. /* synchronization of the shared buffer access                */
  952.  
  953. void
  954. SISyncInit(key)
  955.     IPCKey    key;
  956. {
  957. #ifdef HAS_TEST_AND_SET
  958.     SharedInvalidationLockId = (int)SINVALLOCKID;  /* a fixed lock */
  959. #else /* HAS_TEST_AND_SET */
  960.     int status;
  961.     SharedInvalidationSemaphore =
  962.         IpcSemaphoreCreate(key, 1, IPCProtection, SI_LockStartValue,
  963.                            &status);
  964.     if(0) { /* XXX use validity function and check status */
  965.         elog(FATAL, "SISynchInit: %m");
  966.     }
  967. #endif /* HAS_TEST_AND_SET */
  968. }
  969.  
  970. void
  971. SISyncKill(key)
  972.     IPCKey    key;
  973. {
  974. #ifndef HAS_TEST_AND_SET
  975.     IpcSemaphoreKill(key);
  976. #endif
  977. }
  978.  
  979.  
  980. void
  981. SIReadLock()
  982. {
  983. #ifdef HAS_TEST_AND_SET
  984.     SharedLock(SharedInvalidationLockId);
  985. #else /* HAS_TEST_AND_SET */
  986.     IpcSemaphoreLock ( SharedInvalidationSemaphore ,
  987.                0 , 
  988.                SI_SharedLock );
  989. #endif /* HAS_TEST_AND_SET */
  990. }
  991.  
  992.  
  993. void
  994. SIWriteLock()
  995. {
  996. #ifdef HAS_TEST_AND_SET
  997.     ExclusiveLock(SharedInvalidationLockId);
  998. #else /* HAS_TEST_AND_SET */
  999.     IpcSemaphoreLock ( SharedInvalidationSemaphore,
  1000.                0 ,
  1001.               SI_ExclusiveLock );
  1002. #endif /* HAS_TEST_AND_SET */
  1003. }
  1004.  
  1005.  
  1006. void
  1007. SIReadUnlock()
  1008. {
  1009. #ifdef HAS_TEST_AND_SET
  1010.     SharedUnlock(SharedInvalidationLockId);
  1011. #else /* HAS_TEST_AND_SET */
  1012.     IpcSemaphoreLock ( SharedInvalidationSemaphore,
  1013.                0,
  1014.                (- SI_SharedLock) );
  1015. #endif /* HAS_TEST_AND_SET */
  1016. }
  1017.  
  1018.  
  1019. void
  1020. SIWriteUnlock()
  1021. {
  1022. #ifdef HAS_TEST_AND_SET
  1023.     ExclusiveUnlock(SharedInvalidationLockId);
  1024. #else /* HAS_TEST_AND_SET */
  1025.     IpcSemaphoreLock ( SharedInvalidationSemaphore,
  1026.                0,
  1027.                ( - SI_ExclusiveLock ) );
  1028. #endif /* HAS_TEST_AND_SET */
  1029. }
  1030.  
  1031.  
  1032.  
  1033. #ifdef _FOO_BAR_BAZ_
  1034. /************************************************************************
  1035. * debug routines
  1036. *
  1037. * This code tries to use the old lmgr setup and should not be called 
  1038. * unless you are willing to set up a spin lock for it as was done above
  1039. * to handle shared invaladation processing.
  1040. *************************************************************************/
  1041. void
  1042. SIBufferImage()
  1043. {
  1044.     int i, status;
  1045.     SISegEntry     *SIGetFirstDataEntry();
  1046.     SISegEntry     *eP;
  1047.     SISeg       *segP;
  1048.     
  1049.     /* READ LOCK buffer */
  1050.     status = LMLock(SILockTableId, LockWait, &SIRelId, &SIDummyOid, &SIDummyOid,
  1051.                     SIXid, MultiLevelLockRequest_ReadRelation);
  1052.     if (status == L_ERROR) {
  1053.             elog(FATAL, "InvalidateSharedInvalid: Could not lock buffer segment");
  1054.     }
  1055.     
  1056.     segP = shmInvalBuffer;
  1057.     fprintf(stderr, "\nDEBUG: current segment IMAGE");
  1058.     fprintf(stderr, "\n startEntrySection: %d", SIGetStartEntrySection(segP));
  1059.     fprintf(stderr, "\n endEntrySection: %d", SIGetEndEntrySection(segP));
  1060.     fprintf(stderr, "\n startFreeSpace: %d", SIGetStartFreeSpace(segP));
  1061.     fprintf(stderr, "\n startEntryChain: %d", SIGetStartEntryChain(segP));
  1062.     fprintf(stderr, "\n endEntryChain: %d", SIGetEndEntryChain(segP));
  1063.     fprintf(stderr, "\n numEntries: %d", SIGetNumEntries(segP));
  1064.     fprintf(stderr, "\n maxNumEntries: %d", SIGetMaxNumEntries(segP));
  1065.     for (i = 0; i < MaxBackendId; i++) {
  1066.         fprintf(stderr, "\n   Backend[%2d] - limit: %3d  reset: %s", 
  1067.                     i + 1,
  1068.                     SIGetProcStateLimit(segP, i),
  1069.                     SIGetProcStateResetState(segP, i) ? "true" : "false");
  1070.     }
  1071.     fprintf(stderr, "\n Message entries:");
  1072.     eP = SIGetFirstDataEntry(segP);
  1073.     while (eP != NULL) {
  1074.         fprintf(stderr, "\n  cacheId: %-7d", eP->entryData.cacheId);
  1075.         fprintf(stderr, "   free: %s", eP->isfree ? "true" : "false");
  1076.         fprintf(stderr, "   my offset: %-4d", SIEntryOffset(segP, eP));
  1077.         fprintf(stderr, "   next: %-4d", eP->next);
  1078.         eP = SIGetNextDataEntry(segP, eP->next);
  1079.     }
  1080.     fprintf(stderr, "\n No further entries");
  1081.     
  1082.     fprintf(stderr, "\n No. of free entries: %d", 
  1083.                     (SIGetMaxNumEntries(segP) - SIGetNumEntries(segP)));
  1084. /*  fprintf(stderr, "\n Free space chain:");
  1085.     eP = SIGetNextDataEntry(segP, SIGetStartFreeSpace(segP));
  1086.     while (eP != NULL) {
  1087.         fprintf(stderr, "\n  free: %s", eP->isfree ? "true" : "false");
  1088.         fprintf(stderr, "   my offset: %-4d", SIEntryOffset(segP, eP));
  1089.         fprintf(stderr, "   next: %-4d", eP->next);
  1090.         eP = SIGetNextDataEntry(segP, eP->next);
  1091.     }
  1092.     fprintf(stderr, "\n No further entries");
  1093. */  
  1094.     fprintf(stderr, "\n");
  1095.     
  1096.     /* UNLOCK buffer */
  1097.     status = LMLockReleaseAll(SILockTableId, SIXid);
  1098.     if (status == L_ERROR) {
  1099.             elog(FATAL, "InvalidateSharedInvalid: Could not unlock buffer segment");
  1100.     }
  1101. }
  1102. #endif _FOO_BAR_BAZ_
  1103.  
  1104. /****************************************************************************/
  1105. /*  Invalidation functions for testing cache invalidation                   */
  1106. /****************************************************************************/
  1107. void
  1108. SIinvalFunc(data)
  1109.     int data;
  1110. {   
  1111.     printf(" Backend: %d -- invalidating data (cacheId) %d\n",
  1112.             MyBackendId, data);
  1113. }
  1114.  
  1115. void
  1116. SIresetFunc()
  1117. {   
  1118.     printf("\n Backend: %d -- state reset done",
  1119.             MyBackendId);
  1120. }
  1121.