home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / access / heap / rac.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  9.7 KB  |  375 lines

  1. /*
  2.  * rac.c --
  3.  *    POSTGRES rule lock access code.
  4.  */
  5.  
  6. #include "tmp/c.h"
  7.  
  8. RcsId("$Header: /private/postgres/src/access/heap/RCS/rac.c,v 1.15 1992/03/05 00:36:28 hong Exp $");
  9.  
  10. #include "access/htup.h"
  11.  
  12. #include "rules/rac.h"
  13. #include "rules/prs2locks.h"
  14. #include "rules/prs2.h"
  15.  
  16. #include "storage/block.h"
  17. #include "storage/buf.h"
  18. #include "storage/bufmgr.h"
  19. #include "storage/bufpage.h"
  20. #include "storage/item.h"
  21. #include "storage/itemid.h"
  22. #include "storage/itemptr.h"
  23. #include "storage/page.h"
  24.  
  25. #include "utils/inval.h"
  26. #include "utils/palloc.h"
  27. #include "utils/rel.h"
  28. #include "utils/log.h"
  29.  
  30. /*
  31.  * XXX direct structure accesses should be removed
  32.  */
  33.  
  34. /*-------------------------------------------------------------------
  35.  * HeapTupleFreeRuleLock
  36.  *
  37.  * Frees a lock, but only if it is a main memory lock.
  38.  *
  39.  */
  40. void
  41. HeapTupleFreeRuleLock(tuple)
  42. HeapTuple tuple;
  43. {
  44.         if (tuple->t_locktype == MEM_RULE_LOCK) {
  45.         prs2FreeLocks(tuple->t_lock.l_lock);
  46.     }
  47. }
  48.  
  49. /*-------------------------------------------------------------------
  50.  *
  51.  * HeapTupleGetRuleLock
  52.  *
  53.  * A rule lock can be either an ItemPointer to the actual data in a
  54.  * disk page or a RuleLock, i.e. a pointer to a main memory structure.
  55.  *
  56.  * This routine always return the main memory representation (if necessary
  57.  * it makes the conversion)
  58.  *
  59.  * NOTE #1: When we save the tuple on disk, if the rule lock is empty
  60.  * (i.e. a "(numOfLocks: 0)"::lock, which must not be confused with
  61.  * an 'InvalidRuleLock') then we store an InvalidItemPointer.
  62.  * So, if the disk representation of the tuple's lock is such an
  63.  * InvalidItemPointer we have to create & return an empty lock.
  64.  *
  65.  * NOTE #2: We ALWAYS return a COPY of the locks. That means we
  66.  * return a freshly palloced new lock, that can and probably MUST
  67.  * be pfreed by the caller (to avoid memory leaks).
  68.  */
  69. RuleLock
  70. HeapTupleGetRuleLock(tuple, buffer)
  71.     HeapTuple    tuple;
  72.     Buffer        buffer;
  73. {
  74.     register RuleLock l;
  75.     
  76.     BlockNumber    blockNumber;
  77.     Page        page;
  78.     ItemId        itemId;
  79.     Item        item;
  80.     Item        returnItem;
  81.  
  82.  
  83.     Assert(HeapTupleIsValid(tuple));
  84.  
  85.     /*
  86.      * sanity check
  87.      */
  88.         if (tuple->t_locktype != MEM_RULE_LOCK &&
  89.             tuple->t_locktype != DISK_RULE_LOCK) {
  90.             elog(WARN,"HeapTupleGetRuleLock: locktype = '%c',(%d)\n",
  91.                 tuple->t_locktype, tuple->t_locktype);
  92.         }
  93.  
  94.     /*
  95.      * if this is a main memory lock, then return it.
  96.      */
  97.         if (tuple->t_locktype == MEM_RULE_LOCK) {
  98.             l = tuple->t_lock.l_lock;
  99.         if (l==InvalidRuleLock) {
  100.         elog(WARN, "HeapTupleGetRuleLock: Invalid Rule Lock!");
  101.         } else {
  102.         return(prs2CopyLocks(l));
  103.         }
  104.         }
  105.  
  106.     /*
  107.      * no, it is a disk lock. Check if it the item pointer is
  108.      * invalid and if yes, return an empty lock.
  109.      */
  110.     if (!ItemPointerIsValid(&tuple->t_lock.l_ltid)) {
  111.         return (prs2MakeLocks());
  112.     }
  113.  
  114.     /*
  115.      * If this is a disk lock, then we *must* pass a valid
  116.      * buffer...
  117.      * Otherwise ... booooooom!
  118.      */
  119.         if (!BufferIsValid(buffer)) {
  120.             elog(WARN,"HeapTupleGetRuleLock: Invalid buffer");
  121.         }
  122.  
  123.     /* ----------------
  124.      *    Yow! raw page access! shouldn't this use the am code?
  125.      * ----------------
  126.      */
  127.     blockNumber = ItemPointerGetBlockNumber(&tuple->t_lock.l_ltid);
  128.     
  129.     buffer = ReadBuffer(BufferGetRelation(buffer), blockNumber);
  130.     
  131.     page = BufferSimpleGetPage(buffer);
  132.     itemId = PageGetItemId(page,
  133.         ItemPointerSimpleGetOffsetIndex(&tuple->t_lock.l_ltid));
  134.     item = PageGetItem(page, itemId);
  135.     
  136.     returnItem = (Item) palloc(itemId->lp_len);    /* XXX */
  137.     bcopy(item, returnItem, (int)itemId->lp_len);    /* XXX Clib-copy */
  138.     
  139.     ReleaseBuffer(buffer);
  140.     
  141.     /*
  142.      * `l' is a pointer to data in a buffer page.
  143.      * return a copy of it.
  144.      */
  145.     l = LintCast(RuleLock, returnItem);
  146.     
  147.     return(prs2CopyLocks(l));
  148. }
  149.  
  150. /*----------------------------------------------------------------------------
  151.  * HeapTupleHasEmptyRuleLock
  152.  *
  153.  * return true if the given tuple has an empty rule lock.
  154.  * We can always use 'HeapTupleGetRuleLock', test the locks, and then
  155.  * pfreed it, but this routine avoids the calls to 'palloc'
  156.  * and 'pfree' thus making postgres 153.34 % faster....
  157.  *----------------------------------------------------------------------------
  158.  */
  159. bool
  160. HeapTupleHasEmptyRuleLock(tuple, buffer)
  161.     HeapTuple    tuple;
  162.     Buffer        buffer;
  163. {
  164.     register RuleLock l;
  165.  
  166.     Assert(HeapTupleIsValid(tuple));
  167.  
  168.     /*
  169.      * sanity check
  170.      */
  171.         if (tuple->t_locktype != MEM_RULE_LOCK &&
  172.             tuple->t_locktype != DISK_RULE_LOCK) {
  173.             elog(WARN,"HeapTupleHasEmptyRuleLock: locktype = '%c',(%d)\n",
  174.                 tuple->t_locktype, tuple->t_locktype);
  175.         }
  176.  
  177.     /*
  178.      * is this is a main memory lock ?
  179.      */
  180.         if (tuple->t_locktype == MEM_RULE_LOCK) {
  181.             l = tuple->t_lock.l_lock;
  182.         if (l==InvalidRuleLock) {
  183.         elog(WARN, "HeapTupleHasEmptyRuleLock: Invalid Rule Lock!");
  184.         } else {
  185.         if (prs2RuleLockIsEmpty(l))
  186.             return(true);
  187.         else
  188.             return(false);
  189.         }
  190.         }
  191.  
  192.     /*
  193.      * no, it is a disk lock. Check if it the item pointer is
  194.      * invalid and if yes, return true (empty lock), otherwise
  195.      * return false.
  196.      */
  197.     if (!ItemPointerIsValid(&tuple->t_lock.l_ltid))
  198.         return (true);
  199.     else
  200.         return(false);
  201. }
  202.  
  203. /*------------------------------------------------------------
  204.  *
  205.  * HeapTupleSetRuleLock
  206.  *
  207.  * Set the rule lock of a tuple.
  208.  *
  209.  * NOTE: the old lock of the tuple is pfreed (if it is a main
  210.  *    memory pointer of course... If it is an item in a disk page
  211.  *    it is left intact)
  212.  *
  213.  * NOTE: No copies of the tuple or the lock are made any more (this
  214.  * routine used to -sometimes- make a copy of the tuple)
  215.  */
  216. void
  217. HeapTupleSetRuleLock(tuple, buffer, lock)
  218.     HeapTuple    tuple;
  219.     Buffer        buffer;
  220.     RuleLock    lock;
  221. {
  222.     RuleLock oldLock;
  223.     Assert(HeapTupleIsValid(tuple));
  224.  
  225.     /*
  226.      * sanity check...
  227.      */
  228.         if (tuple->t_locktype != MEM_RULE_LOCK &&
  229.             tuple->t_locktype != DISK_RULE_LOCK) {
  230.             elog(WARN,"HeapTupleGetRuleLock: locktype = '%c',(%d)\n",
  231.                 tuple->t_locktype, tuple->t_locktype);
  232.         }
  233.  
  234.     HeapTupleFreeRuleLock(tuple);
  235.  
  236.         tuple->t_locktype = MEM_RULE_LOCK;
  237.     tuple->t_lock.l_lock = lock;
  238.  
  239. }
  240.  
  241. /*------------------------------------------------------------
  242.  *
  243.  * HeapTupleStoreRuleLock
  244.  *
  245.  * Store a rule lock in a page.
  246.  * The 'tuple' has a lock which can be either a "disk" or "main memory"
  247.  * rule lock. In the first case we don't need to do anything because
  248.  * the lock is already there! In the second case, add the lock data
  249.  * somewhere in the disk page & update the tuple->t_lock stuff...
  250.  *
  251.  * NOTE: When we save the tuple on disk, if the rule lock is empty
  252.  * (i.e. a "(numOfLocks: 0)"::lock, which must not be confused with
  253.  * an 'InvalidRuleLock') then we store an InvalidItemPointer.
  254.  */
  255. void
  256. HeapTupleStoreRuleLock(tuple, buffer)
  257.     HeapTuple    tuple;
  258.     Buffer        buffer;
  259. {
  260.     Relation    relation;
  261.     Page        page;
  262.     BlockNumber    blockNumber;
  263.     OffsetNumber    offsetNumber;
  264.     RuleLock    lock;
  265.     Size        lockSize;
  266.  
  267.     Assert(HeapTupleIsValid(tuple));
  268.     Assert(BufferIsValid(buffer));
  269.  
  270.     /*
  271.      * If it is a disk lock, then there is nothing to do...
  272.      */
  273.     if (tuple->t_locktype == DISK_RULE_LOCK) {
  274.         return;
  275.     }
  276.  
  277.     /*
  278.      * sanity check
  279.      */
  280.         if (tuple->t_locktype != MEM_RULE_LOCK) {
  281.             elog(WARN,"HeapTupleGetRuleLock: locktype = '%c',(%d)\n",
  282.                 tuple->t_locktype, tuple->t_locktype);
  283.         }
  284.  
  285.     lock = tuple->t_lock.l_lock;
  286.  
  287.     /*
  288.      * if it is an empty lock, treat the trivial case..
  289.      */
  290.         if (prs2RuleLockIsEmpty(lock)) {
  291.         /*
  292.          * change it to an empty  disk lock 
  293.          */
  294.                 tuple->t_locktype = DISK_RULE_LOCK;
  295.         ItemPointerSetInvalid(&tuple->t_lock.l_ltid);
  296.         return;
  297.     }
  298.  
  299.     relation = BufferGetRelation(buffer);
  300.  
  301.     /* Assert(0); */
  302.     /* XXX START HERE */
  303.     /*
  304.      * need to check if sufficient space.  If so, then place it.
  305.      * Otherwise, allocate a new page.  Etc.  Look at util/access.c
  306.      * for ideas and to have amputtup and amputnew call this funciton.
  307.      *
  308.      * XXX this should be rewritten to use the am code rather than
  309.      *    using the buffer and page code directly.
  310.      */
  311.  
  312.     page = BufferSimpleGetPage(buffer);
  313.  
  314.     lockSize = prs2LockSize(prs2GetNumberOfLocks(lock));
  315.  
  316.     if (PageGetFreeSpace(page) >= lockSize) {
  317.  
  318.         blockNumber = BufferGetBlockNumber(buffer);
  319.         offsetNumber = PageAddItem(page, (Item) lock, lockSize,
  320.             InvalidOffsetNumber, LP_USED | LP_LOCK);
  321.     } else {
  322.         Assert(lockSize < BLCKSZ); /* XXX cannot handle this yet */
  323.  
  324.         buffer = ReadBuffer(relation, P_NEW);
  325.         
  326. #ifndef NO_BUFFERISVALID
  327.         if (!BufferIsValid(buffer)) {
  328.             elog(WARN,
  329.              "HeapTupleStoreRuleLock: cannot get new buffer");
  330.         }
  331. #endif NO_BUFFERISVALID
  332.         
  333.         BufferSimpleInitPage(buffer);
  334.         blockNumber = BufferGetBlockNumber(buffer);
  335.         offsetNumber = PageAddItem(BufferSimpleGetPage(buffer),
  336.             (Item) lock, lockSize, InvalidOffsetNumber,
  337.             LP_USED | LP_LOCK);
  338.         WriteBuffer(buffer);
  339.     }
  340.     tuple->t_locktype = DISK_RULE_LOCK;
  341.     ItemPointerSimpleSet(&tuple->t_lock.l_ltid, blockNumber, offsetNumber);
  342.  
  343.     /*
  344.      * And now the tricky & funny part... (not submitted to
  345.      * Rec.puzzles yet...)
  346.      *
  347.      * Shall we free the old memory locks or not ????
  348.      * "I say yes! It is safe to pfree them..." (Spyros said, just before
  349.      * the lights went out...)
  350.      *
  351.      * ---
  352.      * The lights went out, so DO NOT FREE the locks! I think the
  353.      * problem is that when 'RelationPutHeapTuple' calls this routine
  354.      * it passes to it an item pointer, i.e. a "disk" tuple, and
  355.      * not the main memory tuple. So finally when the executor does
  356.      * its cleanup, it ends up freeing this lock twice!
  357.      */
  358.     /* prs2FreeLocks(lock); */
  359.  
  360.     /*
  361.      * And our last question for $200!
  362.      * the following call to "RelationInvalidateHeapTuple()"
  363.      * invalidates the cache...  Do we really need it ???
  364.      * 
  365.      * The correct answer is NO! "HeapTupleStoreRuleLock()"
  366.      * in only called by "RelationPutHeapTuple()"
  367.      * and "RelationPutLongHeapTuple()", which are called
  368.      * by "amreplace()", "aminsert()" and company, which
  369.      * invalidate the cache anyway...
  370.      */
  371.  
  372.     /* RelationInvalidateHeapTuple(relation, tuple); */
  373.  
  374. }
  375.