]> granicus.if.org Git - postgresql/commitdiff
Initial MVCC code.
authorVadim B. Mikheev <vadim4o@yahoo.com>
Tue, 15 Dec 1998 12:47:01 +0000 (12:47 +0000)
committerVadim B. Mikheev <vadim4o@yahoo.com>
Tue, 15 Dec 1998 12:47:01 +0000 (12:47 +0000)
New code for locking buffer' context.

65 files changed:
src/backend/access/gist/gist.c
src/backend/access/gist/gistscan.c
src/backend/access/hash/hashpage.c
src/backend/access/heap/heapam.c
src/backend/access/heap/hio.c
src/backend/access/heap/stats.c
src/backend/access/index/indexam.c
src/backend/access/nbtree/nbtinsert.c
src/backend/access/nbtree/nbtpage.c
src/backend/access/rtree/rtree.c
src/backend/access/rtree/rtscan.c
src/backend/access/transam/transam.c
src/backend/access/transam/transsup.c
src/backend/access/transam/xact.c
src/backend/catalog/aclchk.c
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/catalog/pg_operator.c
src/backend/catalog/pg_type.c
src/backend/commands/async.c
src/backend/commands/command.c
src/backend/commands/copy.c
src/backend/commands/dbcommands.c
src/backend/commands/defind.c
src/backend/commands/proclang.c
src/backend/commands/remove.c
src/backend/commands/rename.c
src/backend/commands/sequence.c
src/backend/commands/trigger.c
src/backend/commands/user.c
src/backend/commands/vacuum.c
src/backend/executor/execMain.c
src/backend/executor/execUtils.c
src/backend/executor/nodeHash.c
src/backend/parser/gram.c
src/backend/parser/parse_func.c
src/backend/rewrite/rewriteRemove.c
src/backend/rewrite/rewriteSupport.c
src/backend/storage/buffer/buf_init.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/buffer/s_lock.c
src/backend/storage/ipc/ipci.c
src/backend/storage/ipc/shmem.c
src/backend/storage/large_object/inv_api.c
src/backend/storage/lmgr/Makefile
src/backend/storage/lmgr/lmgr.c
src/backend/storage/lmgr/lock.c
src/backend/utils/adt/sets.c
src/backend/utils/cache/relcache.c
src/backend/utils/time/tqual.c
src/include/access/heapam.h
src/include/access/hio.h
src/include/access/htup.h
src/include/access/xact.h
src/include/catalog/pg_am.h
src/include/catalog/pg_class.h
src/include/commands/trigger.h
src/include/storage/buf_internals.h
src/include/storage/bufmgr.h
src/include/storage/ipc.h
src/include/storage/lmgr.h
src/include/storage/lock.h
src/include/storage/proc.h
src/include/storage/s_lock.h
src/include/utils/tqual.h

index a761784204290433a806952862b9fe6795551c21..ce9ef24c88ee1010acf1e2cd1f24320b892b612b 100644 (file)
@@ -104,8 +104,7 @@ gistbuild(Relation heap,
        Buffer          buffer = InvalidBuffer;
        bool       *compvec;
 
-       /* GiSTs only know how to do stupid locking now */
-       RelationSetLockForWrite(index);
+       /* no locking is needed */
 
        setheapoverride(true);          /* so we can see the new pg_index tuple */
        initGISTstate(&giststate, index);
@@ -269,7 +268,6 @@ gistbuild(Relation heap,
 
        /* okay, all heap tuples are indexed */
        heap_endscan(scan);
-       RelationUnsetLockForWrite(index);
 
        if (pred != NULL || oldPred != NULL)
        {
@@ -343,7 +341,12 @@ gistinsert(Relation r, Datum *datum, char *nulls, ItemPointer ht_ctid, Relation
        itup = index_formtuple(RelationGetDescr(r), datum, nulls);
        itup->t_tid = *ht_ctid;
 
+       /*
+        * Notes in ExecUtils:ExecOpenIndices()
+        *
        RelationSetLockForWrite(r);
+        */
+
        res = gistdoinsert(r, itup, &giststate);
        for (i = 0; i < r->rd_att->natts; i++)
                if (compvec[i] == TRUE)
@@ -351,7 +354,6 @@ gistinsert(Relation r, Datum *datum, char *nulls, ItemPointer ht_ctid, Relation
        pfree(itup);
        pfree(compvec);
 
-       /* XXX two-phase locking -- don't unlock the relation until EOT */
        return res;
 }
 
@@ -1103,8 +1105,12 @@ gistdelete(Relation r, ItemPointer tid)
        Buffer          buf;
        Page            page;
 
-       /* must write-lock on delete */
+       /*
+        * Notes in ExecUtils:ExecOpenIndices()
+        * Also note that only vacuum deletes index tuples now...
+        *
        RelationSetLockForWrite(r);
+        */
 
        blkno = ItemPointerGetBlockNumber(tid);
        offnum = ItemPointerGetOffsetNumber(tid);
@@ -1120,7 +1126,6 @@ gistdelete(Relation r, ItemPointer tid)
 
        WriteBuffer(buf);
 
-       /* XXX -- two-phase locking, don't release the write lock */
 }
 
 void
index f74316cb3314a995d3501b466f0f6317ca787f5c..3528fd30ce2d344d76f0e740ebff9ec54ed3618e 100644 (file)
@@ -65,7 +65,12 @@ gistbeginscan(Relation r,
 {
        IndexScanDesc s;
 
+       /*
+        * Let index_beginscan does its work...
+        *
        RelationSetLockForRead(r);
+        */
+
        s = RelationGetIndexScan(r, fromEnd, nkeys, key);
        gistregscan(s);
 
index dc3ad3727aaee1ded7467a0f283a8e74a3fcaf6b..208cda1bf7eb4a25c9754fea49d190952b1892a5 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.17 1998/09/01 03:20:58 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.18 1998/12/15 12:45:10 vadim Exp $
  *
  * NOTES
  *       Postgres hash pages look like ordinary relation pages.  The opaque
@@ -81,7 +81,7 @@ _hash_metapinit(Relation rel)
 
        /* can't be sharing this with anyone, now... */
        if (USELOCKING)
-               RelationSetLockForWrite(rel);
+               LockRelation(rel, AccessExclusiveLock);
 
        if ((nblocks = RelationGetNumberOfBlocks(rel)) != 0)
        {
@@ -169,7 +169,7 @@ _hash_metapinit(Relation rel)
        _hash_relbuf(rel, metabuf, HASH_WRITE);
 
        if (USELOCKING)
-               RelationUnsetLockForWrite(rel);
+               UnlockRelation(rel, AccessExclusiveLock);
 }
 
 /*
@@ -316,19 +316,16 @@ _hash_setpagelock(Relation rel,
                                  BlockNumber blkno,
                                  int access)
 {
-       ItemPointerData iptr;
 
        if (USELOCKING)
        {
-               ItemPointerSet(&iptr, blkno, 1);
-
                switch (access)
                {
                        case HASH_WRITE:
-                               RelationSetSingleWLockPage(rel, &iptr);
+                               LockPage(rel, blkno, ExclusiveLock);
                                break;
                        case HASH_READ:
-                               RelationSetSingleRLockPage(rel, &iptr);
+                               LockPage(rel, blkno, ShareLock);
                                break;
                        default:
                                elog(ERROR, "_hash_setpagelock: invalid access (%d) on blk %x: %s",
@@ -343,19 +340,16 @@ _hash_unsetpagelock(Relation rel,
                                        BlockNumber blkno,
                                        int access)
 {
-       ItemPointerData iptr;
 
        if (USELOCKING)
        {
-               ItemPointerSet(&iptr, blkno, 1);
-
                switch (access)
                {
                        case HASH_WRITE:
-                               RelationUnsetSingleWLockPage(rel, &iptr);
+                               UnlockPage(rel, blkno, ExclusiveLock);
                                break;
                        case HASH_READ:
-                               RelationUnsetSingleRLockPage(rel, &iptr);
+                               UnlockPage(rel, blkno, ShareLock);
                                break;
                        default:
                                elog(ERROR, "_hash_unsetpagelock: invalid access (%d) on blk %x: %s",
index 76fcfaf2c8210d506e79beb7d9ed3bd6e782c2b7..8ffd9d4192275242437fdf588ec8467c50bb0418 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.38 1998/11/27 19:51:36 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.39 1998/12/15 12:45:13 vadim Exp $
  *
  *
  * INTERFACE ROUTINES
 #include <utils/inval.h>
 #include <utils/memutils.h>
 
-
 #ifndef HAVE_MEMMOVE
 #include <regex/utils.h>
 #else
 #include <string.h>
 #endif
 
-static void doinsert(Relation relation, HeapTuple tup);
-
 /* ----------------------------------------------------------------
  *                                              heap support routines
  * ----------------------------------------------------------------
@@ -214,7 +211,7 @@ static void
 heapgettup(Relation relation,
                   HeapTuple tuple,
                   int dir,
-                  Buffer *buf,
+                  Buffer *buffer,
                   Snapshot snapshot,
                   int nkeys,
                   ScanKey key)
@@ -255,7 +252,7 @@ heapgettup(Relation relation,
                elog(DEBUG, "heapgettup(%s, tid=0x%x, dir=%d, ...)",
                         RelationGetRelationName(relation), tid, dir);
        }
-       elog(DEBUG, "heapgettup(..., b=0x%x, nkeys=%d, key=0x%x", buf, nkeys, key);
+       elog(DEBUG, "heapgettup(..., b=0x%x, nkeys=%d, key=0x%x", buffer, nkeys, key);
 
        elog(DEBUG, "heapgettup: relation(%c)=`%s', %p",
                 relation->rd_rel->relkind, &relation->rd_rel->relname,
@@ -288,25 +285,26 @@ heapgettup(Relation relation,
                /* assume it is a valid TID XXX */
                if (ItemPointerIsValid(tid) == false)
                {
-                       *buf = InvalidBuffer;
+                       *buffer = InvalidBuffer;
                        tuple->t_data = NULL;
                        return;
                }
-               *buf = RelationGetBufferWithBuffer(relation,
+               *buffer = RelationGetBufferWithBuffer(relation,
                                                                                   ItemPointerGetBlockNumber(tid),
-                                                                                  *buf);
+                                                                                  *buffer);
 
-#ifndef NO_BUFFERISVALID
-               if (!BufferIsValid(*buf))
+               if (!BufferIsValid(*buffer))
                        elog(ERROR, "heapgettup: failed ReadBuffer");
-#endif
 
-               dp = (Page) BufferGetPage(*buf);
+               LockBuffer(*buffer, BUFFER_LOCK_SHARE);
+
+               dp = (Page) BufferGetPage(*buffer);
                lineoff = ItemPointerGetOffsetNumber(tid);
                lpp = PageGetItemId(dp, lineoff);
 
                tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
                tuple->t_len = ItemIdGetLength(lpp);
+               LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
                return;
 
        }
@@ -328,18 +326,18 @@ heapgettup(Relation relation,
                }
                if (page < 0)
                {
-                       *buf = InvalidBuffer;
+                       *buffer = InvalidBuffer;
                        tuple->t_data = NULL;
                        return;
                }
 
-               *buf = RelationGetBufferWithBuffer(relation, page, *buf);
-#ifndef NO_BUFFERISVALID
-               if (!BufferIsValid(*buf))
+               *buffer = RelationGetBufferWithBuffer(relation, page, *buffer);
+               if (!BufferIsValid(*buffer))
                        elog(ERROR, "heapgettup: failed ReadBuffer");
-#endif
 
-               dp = (Page) BufferGetPage(*buf);
+               LockBuffer(*buffer, BUFFER_LOCK_SHARE);
+
+               dp = (Page) BufferGetPage(*buffer);
                lines = PageGetMaxOffsetNumber(dp);
                if (tid == NULL)
                {
@@ -373,19 +371,19 @@ heapgettup(Relation relation,
 
                if (page >= pages)
                {
-                       *buf = InvalidBuffer;
+                       *buffer = InvalidBuffer;
                        tuple->t_data = NULL;
                        return;
                }
                /* page and lineoff now reference the physically next tid */
 
-               *buf = RelationGetBufferWithBuffer(relation, page, *buf);
-#ifndef NO_BUFFERISVALID
-               if (!BufferIsValid(*buf))
+               *buffer = RelationGetBufferWithBuffer(relation, page, *buffer);
+               if (!BufferIsValid(*buffer))
                        elog(ERROR, "heapgettup: failed ReadBuffer");
-#endif
 
-               dp = (Page) BufferGetPage(*buf);
+               LockBuffer(*buffer, BUFFER_LOCK_SHARE);
+
+               dp = (Page) BufferGetPage(*buffer);
                lines = PageGetMaxOffsetNumber(dp);
        }
 
@@ -420,10 +418,13 @@ heapgettup(Relation relation,
                                 *      if current tuple qualifies, return it.
                                 * ----------------
                                 */
-                               HeapTupleSatisfies(tuple, relation, *buf, (PageHeader) dp,
+                               HeapTupleSatisfies(tuple, relation, *buffer, (PageHeader) dp,
                                                                   snapshot, nkeys, key);
                                if (tuple->t_data != NULL)
+                               {
+                                       LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
                                        return;
+                               }
                        }
 
                        /* ----------------
@@ -448,6 +449,7 @@ heapgettup(Relation relation,
                 *      this page and it's time to move to the next..
                 * ----------------
                 */
+               LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
                page = nextpage(page, dir);
 
                /* ----------------
@@ -456,20 +458,19 @@ heapgettup(Relation relation,
                 */
                if (page < 0 || page >= pages)
                {
-                       if (BufferIsValid(*buf))
-                               ReleaseBuffer(*buf);
-                       *buf = InvalidBuffer;
+                       if (BufferIsValid(*buffer))
+                               ReleaseBuffer(*buffer);
+                       *buffer = InvalidBuffer;
                        tuple->t_data = NULL;
                        return;
                }
 
-               *buf = ReleaseAndReadBuffer(*buf, relation, page);
+               *buffer = ReleaseAndReadBuffer(*buffer, relation, page);
 
-#ifndef NO_BUFFERISVALID
-               if (!BufferIsValid(*buf))
+               if (!BufferIsValid(*buffer))
                        elog(ERROR, "heapgettup: failed ReadBuffer");
-#endif
-               dp = (Page) BufferGetPage(*buf);
+               LockBuffer(*buffer, BUFFER_LOCK_SHARE);
+               dp = (Page) BufferGetPage(*buffer);
                lines = PageGetMaxOffsetNumber((Page) dp);
                linesleft = lines - 1;
                if (dir < 0)
@@ -485,13 +486,6 @@ heapgettup(Relation relation,
        }
 }
 
-static void
-doinsert(Relation relation, HeapTuple tup)
-{
-       RelationPutHeapTupleAtEnd(relation, tup);
-       return;
-}
-
 
 /* ----------------------------------------------------------------
  *                                      heap access method interface
@@ -599,11 +593,7 @@ heap_beginscan(Relation relation,
        if (RelationIsValid(relation) == false)
                elog(ERROR, "heap_beginscan: !RelationIsValid(relation)");
 
-       /* ----------------
-        * set relation level read lock
-        * ----------------
-        */
-       RelationSetLockForRead(relation);
+       LockRelation(relation, AccessShareLock);
 
        /* XXX someday assert SelfTimeQual if relkind == RELKIND_UNCATALOGED */
        if (relation->rd_rel->relkind == RELKIND_UNCATALOGED)
@@ -707,13 +697,7 @@ heap_endscan(HeapScanDesc scan)
         */
        RelationDecrementReferenceCount(scan->rs_rd);
 
-       /* ----------------
-        * Non 2-phase read locks on catalog relations
-        * ----------------
-        */
-       if (IsSystemRelationName(RelationGetRelationName(scan->rs_rd)->data))
-
-               RelationUnsetLockForRead(scan->rs_rd);
+       UnlockRelation(scan->rs_rd, AccessShareLock);
 
        pfree(scan);                            /* XXX */
 }
@@ -997,14 +981,6 @@ heap_fetch(Relation relation,
        IncrHeapAccessStat(local_fetch);
        IncrHeapAccessStat(global_fetch);
 
-       /*
-        * Note: This is collosally expensive - does two system calls per
-        * indexscan tuple fetch.  Not good, and since we should be doing page
-        * level locking by the scanner anyway, it is commented out.
-        */
-
-       /* RelationSetLockForTupleRead(relation, tid); */
-
        /* ----------------
         *      get the buffer from the relation descriptor
         *      Note that this does a buffer pin.
@@ -1013,13 +989,11 @@ heap_fetch(Relation relation,
 
        buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
 
-#ifndef NO_BUFFERISVALID
        if (!BufferIsValid(buffer))
-       {
                elog(ERROR, "heap_fetch: %s relation: ReadBuffer(%lx) failed",
                         &relation->rd_rel->relname, (long) tid);
-       }
-#endif
+
+       LockBuffer(buffer, BUFFER_LOCK_SHARE);
 
        /* ----------------
         *      get the item line pointer corresponding to the requested tid
@@ -1047,6 +1021,8 @@ heap_fetch(Relation relation,
        HeapTupleSatisfies(tuple, relation, buffer, dp,
                                           snapshot, 0, (ScanKey) NULL);
 
+       LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
        if (tuple->t_data == NULL)
        {
                ReleaseBuffer(buffer);
@@ -1090,14 +1066,6 @@ heap_insert(Relation relation, HeapTuple tup)
        IncrHeapAccessStat(local_insert);
        IncrHeapAccessStat(global_insert);
 
-       /* ----------------
-        *      set relation level write lock. If this is a "local" relation (not
-        *      visible to others), we don't need to set a write lock.
-        * ----------------
-        */
-       if (!relation->rd_islocal)
-               RelationSetLockForWrite(relation);
-
        /* ----------------
         *      If the object id of this tuple has already been assigned, trust
         *      the caller.  There are a couple of ways this can happen.  At initial
@@ -1122,228 +1090,178 @@ heap_insert(Relation relation, HeapTuple tup)
        tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
        tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
 
-       doinsert(relation, tup);
+       RelationPutHeapTupleAtEnd(relation, tup);
 
        if (IsSystemRelationName(RelationGetRelationName(relation)->data))
        {
-               RelationUnsetLockForWrite(relation);
-
-               /* ----------------
-                *              invalidate caches (only works for system relations)
-                * ----------------
-                */
                RelationInvalidateHeapTuple(relation, tup);
        }
 
        return tup->t_data->t_oid;
 }
 
-/* ----------------
- *             heap_delete             - delete a tuple
- *
- *             Must decide how to handle errors.
- * ----------------
+/*
+ *     heap_delete             - delete a tuple
  */
 int
-heap_delete(Relation relation, ItemPointer tid)
+heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid)
 {
        ItemId                  lp;
        HeapTupleData   tp;
        PageHeader              dp;
-       Buffer                  buf;
+       Buffer                  buffer;
+       int                             result;
 
-       /* ----------------
-        *      increment access statistics
-        * ----------------
-        */
+       /* increment access statistics */
        IncrHeapAccessStat(local_delete);
        IncrHeapAccessStat(global_delete);
 
-       /* ----------------
-        *      sanity check
-        * ----------------
-        */
        Assert(ItemPointerIsValid(tid));
 
-       /* ----------------
-        *      set relation level write lock
-        * ----------------
-        */
-       RelationSetLockForWrite(relation);
-
-       buf = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
+       buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
 
-#ifndef NO_BUFFERISVALID
-       if (!BufferIsValid(buf))
-       {                                                       /* XXX L_SH better ??? */
+       if (!BufferIsValid(buffer))
                elog(ERROR, "heap_delete: failed ReadBuffer");
-       }
-#endif  /* NO_BUFFERISVALID */
 
-       dp = (PageHeader) BufferGetPage(buf);
-       lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
+       LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
 
-       /*
-        * Just like test against non-functional updates we try to catch
-        * non-functional delete attempts.                      - vadim 05/05/97
-        */
+       dp = (PageHeader) BufferGetPage(buffer);
+       lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
        tp.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
        tp.t_len = ItemIdGetLength(lp);
        tp.t_self = *tid;
        
-       if (TupleUpdatedByCurXactAndCmd(&tp))
+l1:
+       result = HeapTupleSatisfiesUpdate(&tp);
+       
+       if (result == HeapTupleInvisible)
        {
-
-               /*
-                * Vadim says this is no longer needed 1998/6/15 elog(NOTICE,
-                * "Non-functional delete, tuple already deleted");
-                */
-               if (IsSystemRelationName(RelationGetRelationName(relation)->data))
-                       RelationUnsetLockForWrite(relation);
-               ReleaseBuffer(buf);
-               return 1;
+               LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+               ReleaseBuffer(buffer);
+               elog(ERROR, "heap_delete: (am)invalid tid");
        }
-       /* ----------------
-        *      check that we're deleteing a valid item
-        * ----------------
-        */
-       HeapTupleSatisfies((&tp), relation, buf, dp,
-                                          false, 0, (ScanKey) NULL);
-       if (!(tp.t_data))
+       else if (result == HeapTupleBeingUpdated)
        {
-
-               /* XXX call something else */
-               ReleaseBuffer(buf);
-
-               elog(ERROR, "heap_delete: (am)invalid tid");
+               TransactionId   xwait = tp.t_data->t_xmax;
+
+               /* sleep untill concurrent transaction ends */
+               LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+               XactLockTableWait(xwait);
+
+               LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+               if (TransactionIdDidAbort(xwait))
+                       goto l1;
+               /* concurrent xact committed */
+               Assert(tp.t_data->t_xmax == xwait);
+               if (!(tp.t_data->t_infomask & HEAP_XMAX_COMMITTED))
+               {
+                       tp.t_data->t_infomask |= HEAP_XMAX_COMMITTED;
+                       SetBufferCommitInfoNeedsSave(buffer);
+               }
+               /* if tuple was marked for update but not updated... */
+               if (tp.t_data->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                       result = HeapTupleMayBeUpdated;
+               else
+                       result = HeapTupleUpdated;
+       }
+       if (result != HeapTupleMayBeUpdated)
+       {
+               Assert(result == HeapTupleSelfUpdated || result == HeapTupleUpdated);
+               if (ctid != NULL)
+                       *ctid = tp.t_data->t_ctid;
+               LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+               ReleaseBuffer(buffer);
+               return result;
        }
 
-       /* ----------------
-        *      get the tuple and lock tell the buffer manager we want
-        *      exclusive access to the page
-        * ----------------
-        */
-
-       /* ----------------
-        *      store transaction information of xact deleting the tuple
-        * ----------------
-        */
+       /* store transaction information of xact deleting the tuple */
        TransactionIdStore(GetCurrentTransactionId(), &(tp.t_data->t_xmax));
        tp.t_data->t_cmax = GetCurrentCommandId();
-       tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID);
+       tp.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | 
+                                                          HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
 
-       /* ----------------
-        *      invalidate caches
-        * ----------------
-        */
+       LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+       /* invalidate caches */
        RelationInvalidateHeapTuple(relation, &tp);
 
-       WriteBuffer(buf);
-       if (IsSystemRelationName(RelationGetRelationName(relation)->data))
-               RelationUnsetLockForWrite(relation);
+       WriteBuffer(buffer);
 
-       return 0;
+       return HeapTupleMayBeUpdated;
 }
 
-/* ----------------
- *             heap_replace    - replace a tuple
- *
- *             Must decide how to handle errors.
- *
- *             Fix arguments, work with indexes.
- *
- *             12/30/93 - modified the return value to be 1 when
- *                                a non-functional update is detected. This
- *                                prevents the calling routine from updating
- *                                indices unnecessarily. -kw
- *
- * ----------------
+/*
+ *     heap_replace    - replace a tuple
  */
 int
-heap_replace(Relation relation, ItemPointer otid, HeapTuple newtup)
+heap_replace(Relation relation, ItemPointer otid, HeapTuple newtup, 
+                               ItemPointer ctid)
 {
        ItemId                  lp;
        HeapTupleData   oldtup;
-       Page                    dp;
+       PageHeader              dp;
        Buffer                  buffer;
+       int                             result;
 
-       /* ----------------
-        *      increment access statistics
-        * ----------------
-        */
+       /* increment access statistics */
        IncrHeapAccessStat(local_replace);
        IncrHeapAccessStat(global_replace);
 
-       /* ----------------
-        *      sanity checks
-        * ----------------
-        */
        Assert(ItemPointerIsValid(otid));
 
-       /* ----------------
-        *      set relation level write lock
-        * ----------------
-        */
-       if (!relation->rd_islocal)
-               RelationSetLockForWrite(relation);
-
        buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(otid));
        if (!BufferIsValid(buffer))
                elog(ERROR, "amreplace: failed ReadBuffer");
+       LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
 
-       dp = (Page) BufferGetPage(buffer);
+       dp = (PageHeader) BufferGetPage(buffer);
        lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(otid));
 
-       /* ----------------
-        *      logically delete old item
-        * ----------------
-        */
-
        oldtup.t_data = (HeapTupleHeader) PageGetItem(dp, lp);
        oldtup.t_len = ItemIdGetLength(lp);
        oldtup.t_self = *otid;
 
-       /* -----------------
-        *      the following test should be able to catch all non-functional
-        *      update attempts and shut out all ghost tuples.
-        *      XXX In the future, Spyros may need to update the rule lock on a tuple
-        *      more than once within the same command and same transaction.
-        *      He will have to introduce a new flag to override the following check.
-        *      -- Wei
-        *
-        * -----------------
-        */
-
-       if (TupleUpdatedByCurXactAndCmd(&oldtup))
+l2:
+       result = HeapTupleSatisfiesUpdate(&oldtup);
+       
+       if (result == HeapTupleInvisible)
        {
-               elog(NOTICE, "Non-functional update, only first update is performed");
-               if (IsSystemRelationName(RelationGetRelationName(relation)->data))
-                       RelationUnsetLockForWrite(relation);
+               LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
                ReleaseBuffer(buffer);
-               return 1;
+               elog(ERROR, "heap_replace: (am)invalid tid");
        }
-
-       /* ----------------
-        *      check that we're replacing a valid item -
-        *
-        *      NOTE that this check must follow the non-functional update test
-        *               above as it can happen that we try to 'replace' the same tuple
-        *               twice in a single transaction.  The second time around the
-        *               tuple will fail the NowTimeQual.  We don't want to abort the
-        *               xact, we only want to flag the 'non-functional' NOTICE. -mer
-        * ----------------
-        */
-       HeapTupleSatisfies((&oldtup),
-                                          relation,
-                                          buffer,
-                                          (PageHeader) dp,
-                                          false,
-                                          0,
-                                          (ScanKey) NULL);
-       if (!(oldtup.t_data))
+       else if (result == HeapTupleBeingUpdated)
        {
+               TransactionId   xwait = oldtup.t_data->t_xmax;
+
+               /* sleep untill concurrent transaction ends */
+               LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+               XactLockTableWait(xwait);
+
+               LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
+               if (TransactionIdDidAbort(xwait))
+                       goto l2;
+               /* concurrent xact committed */
+               Assert(oldtup.t_data->t_xmax == xwait);
+               if (!(oldtup.t_data->t_infomask & HEAP_XMAX_COMMITTED))
+               {
+                       oldtup.t_data->t_infomask |= HEAP_XMAX_COMMITTED;
+                       SetBufferCommitInfoNeedsSave(buffer);
+               }
+               /* if tuple was marked for update but not updated... */
+               if (oldtup.t_data->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                       result = HeapTupleMayBeUpdated;
+               else
+                       result = HeapTupleUpdated;
+       }
+       if (result != HeapTupleMayBeUpdated)
+       {
+               Assert(result == HeapTupleSelfUpdated || result == HeapTupleUpdated);
+               if (ctid != NULL)
+                       *ctid = oldtup.t_data->t_ctid;
+               LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
                ReleaseBuffer(buffer);
-               elog(ERROR, "heap_replace: (am)invalid otid");
+               return result;
        }
 
        /* XXX order problems if not atomic assignment ??? */
@@ -1354,42 +1272,122 @@ heap_replace(Relation relation, ItemPointer otid, HeapTuple newtup)
        newtup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
        newtup->t_data->t_infomask |= HEAP_XMAX_INVALID;
 
-       /* ----------------
-        *      insert new item
-        * ----------------
-        */
+       /* logically delete old item */
+       TransactionIdStore(GetCurrentTransactionId(), &(oldtup.t_data->t_xmax));
+       oldtup.t_data->t_cmax = GetCurrentCommandId();
+       oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | 
+                                                                  HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
+
+       /* insert new item */
        if ((unsigned) DOUBLEALIGN(newtup->t_len) <= PageGetFreeSpace((Page) dp))
-               RelationPutHeapTuple(relation, BufferGetBlockNumber(buffer), newtup);
+               RelationPutHeapTuple(relation, buffer, newtup);
        else
        {
-               /* ----------------
-                *      new item won't fit on same page as old item, have to look
-                *      for a new place to put it.
-                * ----------------
+               /*
+                * New item won't fit on same page as old item, have to look
+                * for a new place to put it. Note that we have to unlock
+                * current buffer context - not good but RelationPutHeapTupleAtEnd
+                * uses extend lock.
                 */
-               doinsert(relation, newtup);
+               LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+               RelationPutHeapTupleAtEnd(relation, newtup);
+               LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
        }
 
-       /* ----------------
-        *      new item in place, now record transaction information
-        * ----------------
+       /*
+        * New item in place, now record address of new tuple in
+        * t_ctid of old one.
         */
-       TransactionIdStore(GetCurrentTransactionId(), &(oldtup.t_data->t_xmax));
-       oldtup.t_data->t_cmax = GetCurrentCommandId();
-       oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID);
+       oldtup.t_data->t_ctid = newtup->t_self;
 
-       /* ----------------
-        *      invalidate caches
-        * ----------------
-        */
+       LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
+       /* invalidate caches */
        RelationInvalidateHeapTuple(relation, &oldtup);
 
        WriteBuffer(buffer);
 
-       if (IsSystemRelationName(RelationGetRelationName(relation)->data))
-               RelationUnsetLockForWrite(relation);
+       return HeapTupleMayBeUpdated;
+}
+
+/*
+ *     heap_mark4update                - mark a tuple for update
+ */
+int
+heap_mark4update(Relation relation, HeapTuple tuple, Buffer *buffer)
+{
+       ItemPointer             tid = &(tuple->t_self);
+       ItemId                  lp;
+       PageHeader              dp;
+       int                             result;
+
+       /* increment access statistics */
+       IncrHeapAccessStat(local_mark4update);
+       IncrHeapAccessStat(global_mark4update);
+
+       *buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
+
+       if (!BufferIsValid(*buffer))
+               elog(ERROR, "heap_mark4update: failed ReadBuffer");
+
+       LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
+
+       dp = (PageHeader) BufferGetPage(*buffer);
+       lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
+       tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
+       tuple->t_len = ItemIdGetLength(lp);
+       
+l3:
+       result = HeapTupleSatisfiesUpdate(tuple);
+       
+       if (result == HeapTupleInvisible)
+       {
+               LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
+               ReleaseBuffer(*buffer);
+               elog(ERROR, "heap_mark4update: (am)invalid tid");
+       }
+       else if (result == HeapTupleBeingUpdated)
+       {
+               TransactionId   xwait = tuple->t_data->t_xmax;
+
+               /* sleep untill concurrent transaction ends */
+               LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
+               XactLockTableWait(xwait);
+
+               LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
+               if (TransactionIdDidAbort(xwait))
+                       goto l3;
+               /* concurrent xact committed */
+               Assert(tuple->t_data->t_xmax == xwait);
+               if (!(tuple->t_data->t_infomask & HEAP_XMAX_COMMITTED))
+               {
+                       tuple->t_data->t_infomask |= HEAP_XMAX_COMMITTED;
+                       SetBufferCommitInfoNeedsSave(*buffer);
+               }
+               /* if tuple was marked for update but not updated... */
+               if (tuple->t_data->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                       result = HeapTupleMayBeUpdated;
+               else
+                       result = HeapTupleUpdated;
+       }
+       if (result != HeapTupleMayBeUpdated)
+       {
+               Assert(result == HeapTupleSelfUpdated || result == HeapTupleUpdated);
+               LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
+               return result;
+       }
+
+       /* store transaction information of xact marking the tuple */
+       TransactionIdStore(GetCurrentTransactionId(), &(tuple->t_data->t_xmax));
+       tuple->t_data->t_cmax = GetCurrentCommandId();
+       tuple->t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID);
+       tuple->t_data->t_infomask |= HEAP_MARKED_FOR_UPDATE;
+
+       LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
+
+       WriteNoReleaseBuffer(*buffer);
 
-       return 0;
+       return HeapTupleMayBeUpdated;
 }
 
 /* ----------------
index 5c727145f6f0a725c10334ce144c2f5989f27bda..462de54ccfdb5fb1a21d39d37f482ff976b020da 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Id: hio.c,v 1.14 1998/11/27 19:51:36 vadim Exp $
+ *       $Id: hio.c,v 1.15 1998/12/15 12:45:14 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -15,6 +15,7 @@
 #include <postgres.h>
 
 #include <storage/bufpage.h>
+#include <access/hio.h>
 #include <access/heapam.h>
 #include <storage/bufmgr.h>
 #include <utils/memutils.h>
  *      Probably needs to have an amdelunique to allow for
  *      internal index records to be deleted and reordered as needed.
  *      For the heap AM, this should never be needed.
+ *
+ *      Note - we assume that caller hold BUFFER_LOCK_EXCLUSIVE on the buffer.
+ *
  */
 void
 RelationPutHeapTuple(Relation relation,
-                                        BlockNumber blockIndex,
+                                        Buffer buffer,
                                         HeapTuple tuple)
 {
-       Buffer          buffer;
-       Page            pageHeader;
-       BlockNumber numberOfBlocks;
-       OffsetNumber offnum;
-       unsigned int len;
-       ItemId          itemId;
-       Item            item;
+       Page                    pageHeader;
+       OffsetNumber    offnum;
+       unsigned int    len;
+       ItemId                  itemId;
+       Item                    item;
 
        /* ----------------
         *      increment access statistics
@@ -50,21 +52,6 @@ RelationPutHeapTuple(Relation relation,
        IncrHeapAccessStat(local_RelationPutHeapTuple);
        IncrHeapAccessStat(global_RelationPutHeapTuple);
 
-       Assert(RelationIsValid(relation));
-       Assert(HeapTupleIsValid(tuple));
-
-       numberOfBlocks = RelationGetNumberOfBlocks(relation);
-       Assert(blockIndex < numberOfBlocks);
-
-       buffer = ReadBuffer(relation, blockIndex);
-#ifndef NO_BUFFERISVALID
-       if (!BufferIsValid(buffer))
-       {
-               elog(ERROR, "RelationPutHeapTuple: no buffer for %ld in %s",
-                        blockIndex, &relation->rd_rel->relname);
-       }
-#endif
-
        pageHeader = (Page) BufferGetPage(buffer);
        len = (unsigned) DOUBLEALIGN(tuple->t_len); /* be conservative */
        Assert((int) len <= PageGetFreeSpace(pageHeader));
@@ -75,11 +62,17 @@ RelationPutHeapTuple(Relation relation,
        itemId = PageGetItemId((Page) pageHeader, offnum);
        item = PageGetItem((Page) pageHeader, itemId);
 
-       ItemPointerSet(&((HeapTupleHeader) item)->t_ctid, blockIndex, offnum);
+       ItemPointerSet(&((HeapTupleHeader) item)->t_ctid, 
+                                       BufferGetBlockNumber(buffer), offnum);
 
+       /*
+        * Let the caller do this!
+        *
        WriteBuffer(buffer);
+        */
+
        /* return an accurate tuple */
-       ItemPointerSet(&tuple->t_self, blockIndex, offnum);
+       ItemPointerSet(&tuple->t_self, BufferGetBlockNumber(buffer), offnum);
 }
 
 /*
@@ -99,6 +92,7 @@ RelationPutHeapTuple(Relation relation,
  * RelationGetNumberOfBlocks to be useful.
  *
  * NOTE: This code presumes that we have a write lock on the relation.
+ * Not now - we use extend locking...
  *
  * Also note that this routine probably shouldn't have to exist, and does
  * screw up the call graph rather badly, but we are wasting so much time and
@@ -116,8 +110,8 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
        ItemId          itemId;
        Item            item;
 
-       Assert(RelationIsValid(relation));
-       Assert(HeapTupleIsValid(tuple));
+       if (!relation->rd_islocal)
+               LockRelation(relation, ExtendLock);
 
        /*
         * XXX This does an lseek - VERY expensive - but at the moment it is
@@ -132,16 +126,18 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
        {
                buffer = ReadBuffer(relation, lastblock);
                pageHeader = (Page) BufferGetPage(buffer);
-               if (PageIsNew((PageHeader) pageHeader))
-               {
-                       buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
-                       pageHeader = (Page) BufferGetPage(buffer);
-                       PageInit(pageHeader, BufferGetPageSize(buffer), 0);
-               }
+               /*
+                * There was IF instead of ASSERT here ?!
+                */
+               Assert(PageIsNew((PageHeader) pageHeader));
+               buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
+               pageHeader = (Page) BufferGetPage(buffer);
+               PageInit(pageHeader, BufferGetPageSize(buffer), 0);
        }
        else
                buffer = ReadBuffer(relation, lastblock - 1);
 
+       LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
        pageHeader = (Page) BufferGetPage(buffer);
        len = (unsigned) DOUBLEALIGN(tuple->t_len); /* be conservative */
 
@@ -152,7 +148,9 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
 
        if (len > PageGetFreeSpace(pageHeader))
        {
+               LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
                buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
+               LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
                pageHeader = (Page) BufferGetPage(buffer);
                PageInit(pageHeader, BufferGetPageSize(buffer), 0);
 
@@ -160,6 +158,9 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
                        elog(ERROR, "Tuple is too big: size %d", len);
        }
 
+       if (!relation->rd_islocal)
+               UnlockRelation(relation, ExtendLock);
+
        offnum = PageAddItem((Page) pageHeader, (Item) tuple->t_data,
                                                 tuple->t_len, InvalidOffsetNumber, LP_USED);
 
@@ -173,5 +174,7 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
        /* return an accurate tuple */
        ItemPointerSet(&tuple->t_self, lastblock, offnum);
 
+       LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
        WriteBuffer(buffer);
+
 }
index 2bebfd9b0befe07bcdee7ca9edf4300a9be6ef52..d630dedf815953c46675caf32e46659d6932ac2d 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/heap/Attic/stats.c,v 1.13 1997/09/08 02:20:31 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/heap/Attic/stats.c,v 1.14 1998/12/15 12:45:15 vadim Exp $
  *
  * NOTES
  *       initam should be moved someplace else.
@@ -73,6 +73,7 @@ InitHeapAccessStatistics()
        stats->global_insert = 0;
        stats->global_delete = 0;
        stats->global_replace = 0;
+       stats->global_mark4update = 0;
        stats->global_markpos = 0;
        stats->global_restrpos = 0;
        stats->global_BufferGetRelation = 0;
@@ -94,6 +95,7 @@ InitHeapAccessStatistics()
        stats->local_insert = 0;
        stats->local_delete = 0;
        stats->local_replace = 0;
+       stats->local_mark4update = 0;
        stats->local_markpos = 0;
        stats->local_restrpos = 0;
        stats->local_BufferGetRelation = 0;
@@ -157,6 +159,7 @@ ResetHeapAccessStatistics()
        stats->local_insert = 0;
        stats->local_delete = 0;
        stats->local_replace = 0;
+       stats->local_mark4update = 0;
        stats->local_markpos = 0;
        stats->local_restrpos = 0;
        stats->local_BufferGetRelation = 0;
@@ -274,6 +277,9 @@ PrintHeapAccessStatistics(HeapAccessStatistics stats)
        printf("local/global_replace:                     %6d/%6d\n",
                   stats->local_replace, stats->global_replace);
 
+       printf("local/global_mark4update:                     %6d/%6d\n",
+                  stats->local_mark4update, stats->global_mark4update);
+
        printf("local/global_markpos:                     %6d/%6d\n",
                   stats->local_markpos, stats->global_markpos);
 
index aa2d9446504ba74ec6e118c75f7175144e546708..f1516c669b3653429579f8282c05803477272264 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.28 1998/10/02 16:27:43 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.29 1998/12/15 12:45:15 vadim Exp $
  *
  * INTERFACE ROUTINES
  *             index_open              - open an index relation by relationId
@@ -225,7 +225,7 @@ index_beginscan(Relation relation,
        RELATION_CHECKS;
        GET_REL_PROCEDURE(beginscan, ambeginscan);
 
-       RelationSetRIntentLock(relation);
+       LockRelation(relation, AccessShareLock);
 
        scandesc = (IndexScanDesc)
                fmgr(procedure, relation, scanFromEnd, numberOfKeys, key);
@@ -262,7 +262,7 @@ index_endscan(IndexScanDesc scan)
 
        fmgr(procedure, scan);
 
-       RelationUnsetRIntentLock(scan->relation);
+       UnlockRelation(scan->relation, AccessShareLock);
 }
 
 /* ----------------
index 44349cfe3c7e847a228f2f31cf426112ad057d9c..54ea9ed8abd0e76230e5d650ae5e04403306ef70 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.31 1998/11/27 19:51:40 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.32 1998/12/15 12:45:20 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -18,6 +18,7 @@
 #include <storage/bufpage.h>
 #include <access/nbtree.h>
 #include <access/heapam.h>
+#include <access/xact.h>
 #include <storage/bufmgr.h>
 #include <fmgr.h>
 
@@ -67,6 +68,8 @@ _bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, Relation heapRel
 
        /* trade in our read lock for a write lock */
        _bt_relbuf(rel, buf, BT_READ);
+
+l1:
        buf = _bt_getbuf(rel, blkno, BT_WRITE);
 
        /*
@@ -120,9 +123,25 @@ _bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, Relation heapRel
                        {                                       /* they're equal */
                                btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offset));
                                htup.t_self = btitem->bti_itup.t_tid;
-                               heap_fetch(heapRel, SnapshotSelf, &htup, &buffer);
-                               if (htup.t_data != NULL)
-                               {                               /* it is a duplicate */
+                               heap_fetch(heapRel, SnapshotDirty, &htup, &buffer);
+                               if (htup.t_data != NULL)        /* it is a duplicate */
+                               {
+                                       TransactionId xwait = 
+                                               (TransactionIdIsValid(SnapshotDirty->xmin)) ? 
+                                               SnapshotDirty->xmin : SnapshotDirty->xmax;
+
+                                       /*
+                                        * If this tuple is being updated by other transaction
+                                        * then we have to wait for its commit/abort.
+                                        */
+                                       if (TransactionIdIsValid(xwait))
+                                       {
+                                               if (nbuf != InvalidBuffer)
+                                                       _bt_relbuf(rel, nbuf, BT_READ);
+                                               _bt_relbuf(rel, buf, BT_WRITE);
+                                               XactLockTableWait(xwait);
+                                               goto l1;        /* continue from the begin */
+                                       }
                                        elog(ERROR, "Cannot insert a duplicate key into a unique index");
                                }
                                /* htup null so no buffer to release */
index 223efc5c91e1c3fda2125fde3b636d9af693802a..306f4fa0e934a07a6affc3ca41b466b3c6dff19b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.16 1998/09/01 03:21:14 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtpage.c,v 1.17 1998/12/15 12:45:23 vadim Exp $
  *
  *     NOTES
  *        Postgres btree pages look like ordinary relation pages.      The opaque
@@ -93,7 +93,7 @@ _bt_metapinit(Relation rel)
 
        /* can't be sharing this with anyone, now... */
        if (USELOCKING)
-               RelationSetLockForWrite(rel);
+               LockRelation(rel, AccessExclusiveLock);
 
        if ((nblocks = RelationGetNumberOfBlocks(rel)) != 0)
        {
@@ -120,7 +120,7 @@ _bt_metapinit(Relation rel)
 
        /* all done */
        if (USELOCKING)
-               RelationUnsetLockForWrite(rel);
+               UnlockRelation(rel, AccessExclusiveLock);
 }
 
 #ifdef NOT_USED
@@ -571,32 +571,26 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
 static void
 _bt_setpagelock(Relation rel, BlockNumber blkno, int access)
 {
-       ItemPointerData iptr;
 
        if (USELOCKING)
        {
-               ItemPointerSet(&iptr, blkno, P_HIKEY);
-
                if (access == BT_WRITE)
-                       RelationSetSingleWLockPage(rel, &iptr);
+                       LockPage(rel, blkno, ExclusiveLock);
                else
-                       RelationSetSingleRLockPage(rel, &iptr);
+                       LockPage(rel, blkno, ShareLock);
        }
 }
 
 static void
 _bt_unsetpagelock(Relation rel, BlockNumber blkno, int access)
 {
-       ItemPointerData iptr;
 
        if (USELOCKING)
        {
-               ItemPointerSet(&iptr, blkno, P_HIKEY);
-
                if (access == BT_WRITE)
-                       RelationUnsetSingleWLockPage(rel, &iptr);
+                       UnlockPage(rel, blkno, ExclusiveLock);
                else
-                       RelationUnsetSingleRLockPage(rel, &iptr);
+                       UnlockPage(rel, blkno, ShareLock);
        }
 }
 
index 3a8feda536daba1cb6b7bb7e04df7af2b3daa5f7..9bf6d90dae11f4f30675f269bf6eeb2a50b9613f 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.29 1998/11/27 19:51:41 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.30 1998/12/15 12:45:25 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -107,9 +107,6 @@ rtbuild(Relation heap,
 
        initRtstate(&rtState, index);
 
-       /* rtrees only know how to do stupid locking now */
-       RelationSetLockForWrite(index);
-
        pred = predInfo->pred;
        oldPred = predInfo->oldPred;
 
@@ -250,7 +247,6 @@ rtbuild(Relation heap,
 
        /* okay, all heap tuples are indexed */
        heap_endscan(scan);
-       RelationUnsetLockForWrite(index);
 
        if (pred != NULL || oldPred != NULL)
        {
@@ -308,10 +304,14 @@ rtinsert(Relation r, Datum *datum, char *nulls, ItemPointer ht_ctid, Relation he
        itup->t_tid = *ht_ctid;
        initRtstate(&rtState, r);
 
+       /*
+        * Notes in ExecUtils:ExecOpenIndices()
+        *
        RelationSetLockForWrite(r);
+        */
+
        res = rtdoinsert(r, itup, &rtState);
 
-       /* XXX two-phase locking -- don't unlock the relation until EOT */
        return res;
 }
 
@@ -946,8 +946,12 @@ rtdelete(Relation r, ItemPointer tid)
        Buffer          buf;
        Page            page;
 
-       /* must write-lock on delete */
+       /*
+        * Notes in ExecUtils:ExecOpenIndices()
+        * Also note that only vacuum deletes index tuples now...
+        *
        RelationSetLockForWrite(r);
+        */
 
        blkno = ItemPointerGetBlockNumber(tid);
        offnum = ItemPointerGetOffsetNumber(tid);
@@ -963,7 +967,6 @@ rtdelete(Relation r, ItemPointer tid)
 
        WriteBuffer(buf);
 
-       /* XXX -- two-phase locking, don't release the write lock */
        return (char *) NULL;
 }
 
index 6d0bb632e7f2b94bac7855ccb6bf236c197dda27..f2c7927d27398b2ed1334b362dba50fdae7c355b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.19 1998/09/01 04:27:12 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.20 1998/12/15 12:45:29 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -66,7 +66,12 @@ rtbeginscan(Relation r,
 {
        IndexScanDesc s;
 
+       /*
+        * Let index_beginscan does its work...
+        *
        RelationSetLockForRead(r);
+        */
+
        s = RelationGetIndexScan(r, fromEnd, nkeys, key);
        rtregscan(s);
 
index 5bcce3c2d70cbd5a171343ff958687b19c928e6c..b68b6ab66911d0443c28faed63a03d47829b1b06 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.19 1998/09/01 04:27:15 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/transam/transam.c,v 1.20 1998/12/15 12:45:30 vadim Exp $
  *
  * NOTES
  *       This file contains the high level access-method interface to the
@@ -172,8 +172,12 @@ TransactionLogTest(TransactionId transactionId, /* transaction id to test */
 
        if (!fail)
        {
-               TransactionIdStore(transactionId, &cachedTestXid);
-               cachedTestXidStatus = xidstatus;
+               /* must not cache status of running xaction !!! */
+               if (xidstatus != XID_INPROGRESS)
+               {
+                       TransactionIdStore(transactionId, &cachedTestXid);
+                       cachedTestXidStatus = xidstatus;
+               }
                return (bool)
                        (status == xidstatus);
        }
@@ -219,11 +223,14 @@ TransactionLogUpdate(TransactionId transactionId,         /* trans id to update */
                                                                 status,
                                                                 &fail);
 
-       /* ----------------
-        *       update (invalidate) our single item TransactionLogTest cache.
-        * ----------------
-        */
+       /*
+        * update (invalidate) our single item TransactionLogTest cache.
+        *
        if (status != XID_COMMIT)
+        *
+        * What's the hell ?! Why != XID_COMMIT ?!
+        */
+       if (status != XID_INPROGRESS)
        {
                TransactionIdStore(transactionId, &cachedTestXid);
                cachedTestXidStatus = status;
index 6f1b09b577432e16b3eb643c67c2c024dbc896c4..edf953384f9380e3580a4d0b150ad7bd3c59e67e 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/transam/Attic/transsup.c,v 1.17 1998/09/01 04:27:16 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/transam/Attic/transsup.c,v 1.18 1998/12/15 12:45:33 vadim Exp $
  *
  * NOTES
  *       This file contains support functions for the high
@@ -289,18 +289,12 @@ TransBlockNumberGetXidStatus(Relation relation,
        XidStatus       xstatus;                /* recorded status of xid */
        bool            localfail;              /* bool used if failP = NULL */
 
-       /* ----------------
-        *      SOMEDAY place a read lock on the log relation
-        *      That someday is today 5 Aug 1991 -mer
-        * ----------------
-        */
-       RelationSetLockForRead(relation);
-
        /* ----------------
         *      get the page containing the transaction information
         * ----------------
         */
        buffer = ReadBuffer(relation, blockNumber);
+       LockBuffer(buffer, BUFFER_LOCK_SHARE);
        block = BufferGetBlock(buffer);
 
        /* ----------------
@@ -318,14 +312,9 @@ TransBlockNumberGetXidStatus(Relation relation,
         *      release the buffer and return the status
         * ----------------
         */
+       LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
        ReleaseBuffer(buffer);
 
-       /* ----------------
-        *      SOMEDAY release our lock on the log relation
-        * ----------------
-        */
-       RelationUnsetLockForRead(relation);
-
        return
                xstatus;
 }
@@ -345,19 +334,12 @@ TransBlockNumberSetXidStatus(Relation relation,
        Block           block;                  /* block containing xstatus */
        bool            localfail;              /* bool used if failP = NULL */
 
-       /* ----------------
-        *      SOMEDAY gain exclusive access to the log relation
-        *
-        *      That someday is today 5 Aug 1991 -mer
-        * ----------------
-        */
-       RelationSetLockForWrite(relation);
-
        /* ----------------
         *      get the block containing the transaction status
         * ----------------
         */
        buffer = ReadBuffer(relation, blockNumber);
+       LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
        block = BufferGetBlock(buffer);
 
        /* ----------------
@@ -372,16 +354,11 @@ TransBlockNumberSetXidStatus(Relation relation,
 
        TransBlockSetXidStatus(block, xid, xstatus);
 
+       LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
        if ((*failP) == false)
                WriteBuffer(buffer);
        else
                ReleaseBuffer(buffer);
-
-       /* ----------------
-        *      SOMEDAY release our lock on the log relation
-        * ----------------
-        */
-       RelationUnsetLockForWrite(relation);
 }
 
 /* --------------------------------
index 35bcbfed6a4aa59eb8d52561013572d0647d92fa..002b43cd040c098876305a082790bda1b149cb03 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.25 1998/10/08 18:29:15 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.26 1998/12/15 12:45:35 vadim Exp $
  *
  * NOTES
  *             Transaction aborts can now occur two ways:
@@ -194,6 +194,8 @@ TransactionStateData CurrentTransactionStateData = {
 TransactionState CurrentTransactionState =
 &CurrentTransactionStateData;
 
+int    XactIsoLevel = XACT_SERIALIZED;
+
 /* ----------------
  *             info returned when the system is disabled
  *
@@ -816,6 +818,8 @@ StartTransaction()
         */
        GetNewTransactionId(&(s->transactionIdData));
 
+       XactLockTableInsert(s->transactionIdData);
+
        /* ----------------
         *      initialize current transaction state fields
         * ----------------
@@ -966,6 +970,7 @@ AbortTransaction()
         *      do abort processing
         * ----------------
         */
+       UnlockBuffers();
        AtAbort_Notify();
        CloseSequences();
        AtEOXact_portals();
index 6c4fb244571bcf249def0efff7b8d62d55d01fd0..b905717630779f6e2579aec96de88a49bf693bb1 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.17 1998/11/27 19:51:46 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.18 1998/12/15 12:45:39 vadim Exp $
  *
  * NOTES
  *       See acl.h.
@@ -162,7 +162,7 @@ ChangeAcl(char *relname,
        tuple = heap_modifytuple(tuple, relation, values, nulls, replaces);
        /* XXX handle index on pg_class? */
        setheapoverride(true);
-       heap_replace(relation, &tuple->t_self, tuple);
+       heap_replace(relation, &tuple->t_self, tuple, NULL);
        setheapoverride(false);
 
        /* keep the catalog indices up to date */
index 3fbdcec4e3235b6178805ae18dffe0569f9fd7b7..bc897c5965c293804ccba25b44e442f721c66bd3 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.69 1998/12/14 05:18:37 scrappy Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.70 1998/12/15 12:45:40 vadim Exp $
  *
  * INTERFACE ROUTINES
  *             heap_create()                   - Create an uncataloged heap relation
@@ -929,7 +929,7 @@ RelationRemoveInheritance(Relation relation)
 
        while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
        {
-               heap_delete(catalogRelation, &tuple->t_self);
+               heap_delete(catalogRelation, &tuple->t_self, NULL);
                found = true;
        }
 
@@ -951,7 +951,7 @@ RelationRemoveInheritance(Relation relation)
                                                  &entry);
 
        while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
-               heap_delete(catalogRelation, &tuple->t_self);
+               heap_delete(catalogRelation, &tuple->t_self, NULL);
 
        heap_endscan(scan);
        heap_close(catalogRelation);
@@ -1020,7 +1020,7 @@ DeletePgRelationTuple(Relation rel)
         *      delete the relation tuple from pg_class, and finish up.
         * ----------------
         */
-       heap_delete(pg_class_desc, &tup->t_self);
+       heap_delete(pg_class_desc, &tup->t_self, NULL);
        pfree(tup);
 
        heap_close(pg_class_desc);
@@ -1048,7 +1048,7 @@ DeletePgAttributeTuples(Relation rel)
         * Get a write lock _before_ getting the read lock in the scan
         * ----------------
         */
-       RelationSetLockForWrite(pg_attribute_desc);
+       LockRelation(pg_attribute_desc, AccessExclusiveLock);
 
        for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
                 attnum <= rel->rd_att->natts;
@@ -1059,7 +1059,7 @@ DeletePgAttributeTuples(Relation rel)
                                                                                                   Int16GetDatum(attnum),
                                                                                                                   0, 0)))
                {
-                       heap_delete(pg_attribute_desc, &tup->t_self);
+                       heap_delete(pg_attribute_desc, &tup->t_self, NULL);
                        pfree(tup);
                }
        }
@@ -1068,7 +1068,7 @@ DeletePgAttributeTuples(Relation rel)
         * Release the write lock
         * ----------------
         */
-       RelationUnsetLockForWrite(pg_attribute_desc);
+       UnlockRelation(pg_attribute_desc, AccessExclusiveLock);
        heap_close(pg_attribute_desc);
 }
 
@@ -1183,7 +1183,7 @@ DeletePgTypeTuple(Relation rel)
         *      we release the read lock on pg_type.  -mer 13 Aug 1991
         * ----------------
         */
-       heap_delete(pg_type_desc, &tup->t_self);
+       heap_delete(pg_type_desc, &tup->t_self, NULL);
 
        heap_endscan(pg_type_scan);
        heap_close(pg_type_desc);
@@ -1209,7 +1209,7 @@ heap_destroy_with_catalog(char *relname)
        if (rel == NULL)
                elog(ERROR, "Relation %s Does Not Exist!", relname);
 
-       RelationSetLockForWrite(rel);
+       LockRelation(rel, AccessExclusiveLock);
        rid = rel->rd_id;
 
        /* ----------------
@@ -1288,7 +1288,7 @@ heap_destroy_with_catalog(char *relname)
 
        rel->rd_tmpunlinked = TRUE;
 
-       RelationUnsetLockForWrite(rel);
+       UnlockRelation(rel, AccessExclusiveLock);
 
        heap_close(rel);
 
@@ -1608,16 +1608,16 @@ RemoveAttrDefault(Relation rel)
        ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
                                                   F_OIDEQ, rel->rd_id);
 
-       RelationSetLockForWrite(adrel);
+       LockRelation(adrel, AccessExclusiveLock);
 
        adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
 
        while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
-               heap_delete(adrel, &tup->t_self);
+               heap_delete(adrel, &tup->t_self, NULL);
 
        heap_endscan(adscan);
 
-       RelationUnsetLockForWrite(adrel);
+       UnlockRelation(adrel, AccessExclusiveLock);
        heap_close(adrel);
 
 }
@@ -1635,16 +1635,16 @@ RemoveRelCheck(Relation rel)
        ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
                                                   F_OIDEQ, rel->rd_id);
 
-       RelationSetLockForWrite(rcrel);
+       LockRelation(rcrel, AccessExclusiveLock);
 
        rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
 
        while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
-               heap_delete(rcrel, &tup->t_self);
+               heap_delete(rcrel, &tup->t_self, NULL);
 
        heap_endscan(rcscan);
 
-       RelationUnsetLockForWrite(rcrel);
+       UnlockRelation(rcrel, AccessExclusiveLock);
        heap_close(rcrel);
 
 }
index 0c487bc2496b357a5536819db17d5353dd33416a..29565ba285e51572ca862a9071df30009cb025fa 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.65 1998/12/13 04:37:50 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.66 1998/12/15 12:45:43 vadim Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -913,7 +913,7 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate)
 
        newtup = heap_modifytuple(tuple, pg_index, values, nulls, replace);
 
-       heap_replace(pg_index, &newtup->t_self, newtup);
+       heap_replace(pg_index, &newtup->t_self, newtup, NULL);
 
        pfree(newtup);
        heap_close(pg_index);
@@ -1039,15 +1039,11 @@ index_create(char *heapRelationName,
 
        heapRelation = heap_open(heapoid);
 
-       /* ----------------
-        * write lock heap to guarantee exclusive access
-        * ----------------
-       RelationSetLockForWrite(heapRelation);
-        *                                ^^^^^
-        * Does it have any sense ?             - vadim 10/27/97
+       /*
+        * Only SELECT ... FOR UPDATE are allowed
         */
 
-       RelationSetLockForRead(heapRelation);
+       LockRelation(heapRelation, ShareLock);
 
        /* ----------------
         *        construct new tuple descriptor
@@ -1195,7 +1191,7 @@ index_destroy(Oid indexId)
 
        AssertState(HeapTupleIsValid(tuple));
 
-       heap_delete(relationRelation, &tuple->t_self);
+       heap_delete(relationRelation, &tuple->t_self, NULL);
        pfree(tuple);
        heap_close(relationRelation);
 
@@ -1212,7 +1208,7 @@ index_destroy(Oid indexId)
                                                                                                   Int16GetDatum(attnum),
                                                                                                                        0, 0)))
        {
-               heap_delete(attributeRelation, &tuple->t_self);
+               heap_delete(attributeRelation, &tuple->t_self, NULL);
                pfree(tuple);
                attnum++;
        }
@@ -1232,7 +1228,7 @@ index_destroy(Oid indexId)
 
        indexRelation = heap_openr(IndexRelationName);
 
-       heap_delete(indexRelation, &tuple->t_self);
+       heap_delete(indexRelation, &tuple->t_self, NULL);
        pfree(tuple);
        heap_close(indexRelation);
 
@@ -1424,7 +1420,7 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
                values[Anum_pg_class_relhasindex - 1] = CharGetDatum(hasindex);
 
                newtup = heap_modifytuple(tuple, pg_class, values, nulls, replace);
-               heap_replace(pg_class, &tuple->t_self, newtup);
+               heap_replace(pg_class, &tuple->t_self, newtup, NULL);
                CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
                CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, newtup);
                CatalogCloseIndices(Num_pg_class_indices, idescs);
index 96fb9ae35f6909377e9c2da6a4d2fb93c9e6908d..40a33fd5b55d24b896011bc52cb96d045a276909 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.30 1998/11/27 19:51:50 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.31 1998/12/15 12:45:45 vadim Exp $
  *
  * NOTES
  *       these routines moved here from commands/define.c and somewhat cleaned up.
@@ -711,7 +711,7 @@ OperatorDef(char *operatorName,
                                                                   replaces);
 
                        setheapoverride(true);
-                       heap_replace(pg_operator_desc, &tup->t_self, tup);
+                       heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
                        setheapoverride(false);
                }
                else
@@ -830,7 +830,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
                                                                           replaces);
 
                                setheapoverride(true);
-                               heap_replace(pg_operator_desc, &tup->t_self, tup);
+                               heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
                                setheapoverride(false);
 
                        }
@@ -855,7 +855,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
                                                           replaces);
 
                setheapoverride(true);
-               heap_replace(pg_operator_desc, &tup->t_self, tup);
+               heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
                setheapoverride(false);
 
                values[Anum_pg_operator_oprcom - 1] = (Datum) NULL;
@@ -884,7 +884,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
                                                           replaces);
 
                setheapoverride(true);
-               heap_replace(pg_operator_desc, &tup->t_self, tup);
+               heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
                setheapoverride(false);
        }
 
index f46bb8f3a2abf2a139f2bfd4249e294b79ed0f43..f67317defe05a42fdb01c193d14f6b118fcd6548 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.31 1998/11/27 19:51:51 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.32 1998/12/15 12:45:47 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -459,7 +459,7 @@ TypeCreate(char *typeName,
         * when the heap_insert() or heap_replace() is called.
         * -----------------
         */
-       RelationSetLockForWrite(pg_type_desc);
+       LockRelation(pg_type_desc, AccessExclusiveLock);
 
        typeKey[0].sk_argument = PointerGetDatum(typeName);
        pg_type_scan = heap_beginscan(pg_type_desc,
@@ -484,7 +484,7 @@ TypeCreate(char *typeName,
                                                           replaces);
 
                setheapoverride(true);
-               heap_replace(pg_type_desc, &tup->t_self, tup);
+               heap_replace(pg_type_desc, &tup->t_self, tup, NULL);
                setheapoverride(false);
 
                typeObjectId = tup->t_data->t_oid;
@@ -516,7 +516,7 @@ TypeCreate(char *typeName,
                CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup);
                CatalogCloseIndices(Num_pg_type_indices, idescs);
        }
-       RelationUnsetLockForWrite(pg_type_desc);
+       UnlockRelation(pg_type_desc, AccessExclusiveLock);
        heap_close(pg_type_desc);
 
        return typeObjectId;
@@ -561,7 +561,7 @@ TypeRename(char *oldTypeName, char *newTypeName)
        namestrcpy(&(((Form_pg_type) GETSTRUCT(oldtup))->typname), newTypeName);
 
        setheapoverride(true);
-       heap_replace(pg_type_desc, &oldtup->t_self, oldtup);
+       heap_replace(pg_type_desc, &oldtup->t_self, oldtup, NULL);
        setheapoverride(false);
 
        /* update the system catalog indices */
index 50d4f13cc09c01dd7f3622096824476dd1ab9c2f..b18941781d425b3a0380a5ca7e37ebd8b2fbd58e 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.42 1998/11/27 19:51:53 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.43 1998/12/15 12:45:50 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -218,7 +218,7 @@ Async_Listen(char *relname, int pid)
        TPRINTF(TRACE_NOTIFY, "Async_Listen: %s", relname);
 
        lRel = heap_openr(ListenerRelationName);
-       RelationSetLockForWrite(lRel);
+       LockRelation(lRel, AccessExclusiveLock);
        tdesc = RelationGetDescr(lRel);
 
        /* Detect whether we are already listening on this relname */
@@ -242,7 +242,7 @@ Async_Listen(char *relname, int pid)
        if (alreadyListener)
        {
                elog(NOTICE, "Async_Listen: We are already listening on %s", relname);
-               RelationUnsetLockForWrite(lRel);
+               UnlockRelation(lRel, AccessExclusiveLock);
                heap_close(lRel);
                return;
        }
@@ -267,7 +267,7 @@ Async_Listen(char *relname, int pid)
        heap_insert(lRel, newtup);
        pfree(newtup);
 
-       RelationUnsetLockForWrite(lRel);
+       UnlockRelation(lRel, AccessExclusiveLock);
        heap_close(lRel);
 
        /*
@@ -320,9 +320,9 @@ Async_Unlisten(char *relname, int pid)
        if (lTuple != NULL)
        {
                lRel = heap_openr(ListenerRelationName);
-               RelationSetLockForWrite(lRel);
-               heap_delete(lRel, &lTuple->t_self);
-               RelationUnsetLockForWrite(lRel);
+               LockRelation(lRel, AccessExclusiveLock);
+               heap_delete(lRel, &lTuple->t_self, NULL);
+               UnlockRelation(lRel, AccessExclusiveLock);
                heap_close(lRel);
        }
        /* We do not complain about unlistening something not being listened;
@@ -358,7 +358,7 @@ Async_UnlistenAll()
        TPRINTF(TRACE_NOTIFY, "Async_UnlistenAll");
 
        lRel = heap_openr(ListenerRelationName);
-       RelationSetLockForWrite(lRel);
+       LockRelation(lRel, AccessExclusiveLock);
        tdesc = RelationGetDescr(lRel);
 
        /* Find and delete all entries with my listenerPID */
@@ -369,10 +369,10 @@ Async_UnlistenAll()
        sRel = heap_beginscan(lRel, 0, SnapshotNow, 1, key);
 
        while (HeapTupleIsValid(lTuple = heap_getnext(sRel, 0)))
-               heap_delete(lRel, &lTuple->t_self);
+               heap_delete(lRel, &lTuple->t_self, NULL);
 
        heap_endscan(sRel);
-       RelationUnsetLockForWrite(lRel);
+       UnlockRelation(lRel, AccessExclusiveLock);
        heap_close(lRel);
 }
 
@@ -463,7 +463,7 @@ AtCommit_Notify()
        TPRINTF(TRACE_NOTIFY, "AtCommit_Notify");
 
        lRel = heap_openr(ListenerRelationName);
-       RelationSetLockForWrite(lRel);
+       LockRelation(lRel, AccessExclusiveLock);
        tdesc = RelationGetDescr(lRel);
        sRel = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
 
@@ -516,7 +516,7 @@ AtCommit_Notify()
                                         * but as far as I can see we should just do it for any
                                         * failure (certainly at least for EPERM too...)
                                         */
-                                       heap_delete(lRel, &lTuple->t_self);
+                                       heap_delete(lRel, &lTuple->t_self, NULL);
                                }
                                else
 #endif
@@ -527,7 +527,7 @@ AtCommit_Notify()
                                        {
                                                rTuple = heap_modifytuple(lTuple, lRel,
                                                                                                  value, nulls, repl);
-                                               heap_replace(lRel, &lTuple->t_self, rTuple);
+                                               heap_replace(lRel, &lTuple->t_self, rTuple, NULL);
                                        }
                                }
                        }
@@ -741,7 +741,7 @@ ProcessIncomingNotify(void)
        StartTransactionCommand();
 
        lRel = heap_openr(ListenerRelationName);
-       RelationSetLockForWrite(lRel);
+       LockRelation(lRel, AccessExclusiveLock);
        tdesc = RelationGetDescr(lRel);
 
        /* Scan only entries with my listenerPID */
@@ -772,7 +772,7 @@ ProcessIncomingNotify(void)
                        NotifyMyFrontEnd(relname, sourcePID);
                        /* Rewrite the tuple with 0 in notification column */
                        rTuple = heap_modifytuple(lTuple, lRel, value, nulls, repl);
-                       heap_replace(lRel, &lTuple->t_self, rTuple);
+                       heap_replace(lRel, &lTuple->t_self, rTuple, NULL);
                }
        }
        heap_endscan(sRel);
index 6cbf8b980cbe33842880953122e2a49c1821d77c..f1fc29f6f6eaf4a6e9c80868c28803283fb6eb72 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.33 1998/11/27 19:51:54 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.34 1998/12/15 12:45:52 vadim Exp $
  *
  * NOTES
  *       The PortalExecutorHeapMemory crap needs to be eliminated
@@ -482,7 +482,7 @@ PerformAddAttribute(char *relationName,
        heap_close(attrdesc);
 
        ((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts;
-       heap_replace(rel, &reltup->t_self, reltup);
+       heap_replace(rel, &reltup->t_self, reltup, NULL);
 
        /* keep catalog indices current */
        CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
index 419874e5d49d737b3b420a46567f7051037acebc..61151ef6aadbc5fb8f1d172ea8fae6163ba69f35 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.64 1998/11/27 19:51:54 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.65 1998/12/15 12:45:53 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -777,6 +777,20 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
                pfree(typmod);
        }
        pfree(byval);
+
+       /* comments in execUtils.c */
+       if (has_index)
+       {
+               for (i = 0; i < n_indices; i++)
+               {
+                       if (index_rels[i] == NULL)
+                               continue;
+                       if ((index_rels[i])->rd_rel->relam != BTREE_AM_OID && 
+                               (index_rels[i])->rd_rel->relam != HASH_AM_OID)
+                               UnlockRelation(index_rels[i], AccessExclusiveLock);
+                       index_close(index_rels[i]);
+               }
+       }
        heap_close(rel);
 }
 
@@ -914,7 +928,14 @@ GetIndexRelations(Oid main_relation_oid,
        *index_rels = (Relation *) palloc(*n_indices * sizeof(Relation));
 
        for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next)
+       {
                (*index_rels)[i] = index_open(scan->index_rel_oid);
+               /* comments in execUtils.c */
+               if ((*index_rels)[i] != NULL && 
+                       ((*index_rels)[i])->rd_rel->relam != BTREE_AM_OID &&
+                       ((*index_rels)[i])->rd_rel->relam != HASH_AM_OID)
+                       LockRelation((*index_rels)[i], AccessExclusiveLock);
+       }
 
        for (i = 0, scan = head; i < *n_indices + 1; i++)
        {
index d25d430c39cefdc1339f6babc893686e4049e46d..a774ca1deb148b42c591a90c15a12a912b08988b 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.27 1998/12/14 05:18:43 scrappy Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.28 1998/12/15 12:45:55 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -235,7 +235,7 @@ check_permissions(char *command,
         * delays when multiple 'createdb's or 'destroydb's are run simult.
         * -mer 7/3/91
         */
-       RelationSetLockForWrite(dbrel);
+       LockRelation(dbrel, AccessExclusiveLock);
        dbtup = get_pg_dbtup(command, dbname, dbrel);
        dbfound = HeapTupleIsValid(dbtup);
 
index c071c2d9fe829e07de9734d513f6a5e6c6731ff2..33d069e6517fa8968c6a4e92da6a73cff5598dbc 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/defind.c,v 1.28 1998/11/27 19:51:56 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/defind.c,v 1.29 1998/12/15 12:45:56 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -342,7 +342,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
        heapRelation = heap_open(relationId);
        indexRelation = index_open(indexId);
 
-       RelationSetLockForWrite(heapRelation);
+       LockRelation(heapRelation, ShareLock);
 
        InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId);
 
index c8b4e836f021eb9e755d071cedfb5a6394a35344..d95c4efdff7e1673bd8415baa4c005c39956e33e 100644 (file)
@@ -174,7 +174,7 @@ DropProceduralLanguage(DropPLangStmt *stmt)
        }
 
        rel = heap_openr(LanguageRelationName);
-       heap_delete(rel, &langTup->t_self);
+       heap_delete(rel, &langTup->t_self, NULL);
 
        pfree(langTup);
        heap_close(rel);
index e662e90ec56ad0f67c8b74d7ab2273935fc33df8..e11983ea8e9ac03ac04d66d5c4f544aeaeadd6da 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.30 1998/11/27 19:51:57 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.31 1998/12/15 12:45:57 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -102,7 +102,7 @@ RemoveOperator(char *operatorName,          /* operator name */
                        elog(ERROR, "RemoveOperator: operator '%s': permission denied",
                                 operatorName);
 #endif
-               heap_delete(relation, &tup->t_self);
+               heap_delete(relation, &tup->t_self, NULL);
        }
        else
        {
@@ -157,7 +157,7 @@ SingleOpOperatorRemove(Oid typeOid)
                key[0].sk_attno = attnums[i];
                scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
                while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
-                       heap_delete(rel, &tup->t_self);
+                       heap_delete(rel, &tup->t_self, NULL);
                heap_endscan(scan);
        }
        heap_close(rel);
@@ -268,7 +268,7 @@ RemoveType(char *typeName)          /* type name to be removed */
 
        relation = heap_openr(TypeRelationName);
        typeOid = tup->t_data->t_oid;
-       heap_delete(relation, &tup->t_self);
+       heap_delete(relation, &tup->t_self, NULL);
 
        /* Now, Delete the "array of" that type */
        shadow_type = makeArrayTypeName(typeName);
@@ -282,7 +282,7 @@ RemoveType(char *typeName)          /* type name to be removed */
        }
 
        typeOid = tup->t_data->t_oid;
-       heap_delete(relation, &tup->t_self);
+       heap_delete(relation, &tup->t_self, NULL);
 
        heap_close(relation);
 }
@@ -357,7 +357,7 @@ RemoveFunction(char *functionName,          /* function name to be removed */
                elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName);
        }
 
-       heap_delete(relation, &tup->t_self);
+       heap_delete(relation, &tup->t_self, NULL);
 
        heap_close(relation);
 }
@@ -428,7 +428,7 @@ RemoveAggregate(char *aggName, char *aggType)
                                 aggName);
                }
        }
-       heap_delete(relation, &tup->t_self);
+       heap_delete(relation, &tup->t_self, NULL);
 
        heap_close(relation);
 }
index c423da11963da24a977ca534402ff58a12a76b66..2977d9e79d061d60d8bddbe265f6c2a00e76c164 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.18 1998/11/27 19:51:57 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.19 1998/12/15 12:45:58 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -180,7 +180,7 @@ renameatt(char *relname,
                        newattname, NAMEDATALEN);
 
        attrelation = heap_openr(AttributeRelationName);
-       heap_replace(attrelation, &oldatttup->t_self, oldatttup);
+       heap_replace(attrelation, &oldatttup->t_self, oldatttup, NULL);
 
        /* keep system catalog indices current */
        CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, irelations);
@@ -248,7 +248,7 @@ renamerel(char *oldrelname, char *newrelname)
 
        /* insert fixed rel tuple */
        relrelation = heap_openr(RelationRelationName);
-       heap_replace(relrelation, &oldreltup->t_self, oldreltup);
+       heap_replace(relrelation, &oldreltup->t_self, oldreltup, NULL);
 
        /* keep the system catalog indices current */
        CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations);
index 9edec5a9dc65c48ef842ef1c9981c678d5de5efe..e391936cbf848d021df0f8206d3f2201e68d3c31 100644 (file)
@@ -162,7 +162,7 @@ DefineSequence(CreateSeqStmt *seq)
        rel = heap_openr(seq->seqname);
        Assert(RelationIsValid(rel));
 
-       RelationSetLockForWrite(rel);
+       LockRelation(rel, AccessExclusiveLock);
 
        tupDesc = RelationGetDescr(rel);
 
@@ -185,7 +185,7 @@ DefineSequence(CreateSeqStmt *seq)
        if (WriteBuffer(buf) == STATUS_ERROR)
                elog(ERROR, "DefineSequence: WriteBuffer failed");
 
-       RelationUnsetLockForWrite(rel);
+       UnlockRelation(rel, AccessExclusiveLock);
        heap_close(rel);
 
        return;
@@ -200,7 +200,6 @@ nextval(struct varlena * seqin)
        SeqTable        elm;
        Buffer          buf;
        Form_pg_sequence seq;
-       ItemPointerData iptr;
        int4            incby,
                                maxv,
                                minv,
@@ -209,7 +208,7 @@ nextval(struct varlena * seqin)
                                next,
                                rescnt = 0;
 
-       /* open and WIntentLock sequence */
+       /* open and AccessShareLock sequence */
        elm = init_sequence("nextval", seqname);
        pfree(seqname);
 
@@ -219,7 +218,7 @@ nextval(struct varlena * seqin)
                return elm->last;
        }
 
-       seq = read_info("nextval", elm, &buf);          /* lock page and read
+       seq = read_info("nextval", elm, &buf);          /* lock page' buffer and read
                                                                                                 * tuple */
 
        next = result = seq->last_value;
@@ -282,12 +281,11 @@ nextval(struct varlena * seqin)
        seq->last_value = next;         /* last fetched number */
        seq->is_called = 't';
 
+       LockBuffer(buf, BUFFER_LOCK_UNLOCK);
+
        if (WriteBuffer(buf) == STATUS_ERROR)
                elog(ERROR, "%s.nextval: WriteBuffer failed", elm->name);
 
-       ItemPointerSet(&iptr, 0, FirstOffsetNumber);
-       RelationUnsetSingleWLockPage(elm->rel, &iptr);
-
        return result;
 
 }
@@ -300,7 +298,7 @@ currval(struct varlena * seqin)
        SeqTable        elm;
        int4            result;
 
-       /* open and WIntentLock sequence */
+       /* open and AccessShareLock sequence */
        elm = init_sequence("currval", seqname);
        pfree(seqname);
 
@@ -320,7 +318,6 @@ setval(struct varlena * seqin, int4 next)
        SeqTable        elm;
        Buffer          buf;
        Form_pg_sequence seq;
-       ItemPointerData iptr;
 
 #ifndef NO_SECURITY
        if (pg_aclcheck(seqname, getpgusername(), ACL_WR) != ACLCHECK_OK)
@@ -328,9 +325,9 @@ setval(struct varlena * seqin, int4 next)
                         seqname, seqname);
 #endif
 
-       /* open and WIntentLock sequence */
+       /* open and AccessShareLock sequence */
        elm = init_sequence("setval", seqname);
-       seq = read_info("setval", elm, &buf);           /* lock page and read
+       seq = read_info("setval", elm, &buf);           /* lock page' buffer and read
                                                                                                 * tuple */
 
        if (seq->cache_value != 1)
@@ -353,27 +350,22 @@ setval(struct varlena * seqin, int4 next)
        seq->last_value = next;         /* last fetched number */
        seq->is_called = 't';
 
+       LockBuffer(buf, BUFFER_LOCK_UNLOCK);
+
        if (WriteBuffer(buf) == STATUS_ERROR)
                elog(ERROR, "%s.settval: WriteBuffer failed", seqname);
 
-       ItemPointerSet(&iptr, 0, FirstOffsetNumber);
-       RelationUnsetSingleWLockPage(elm->rel, &iptr);
-
        return next;
 }
 
 static Form_pg_sequence
 read_info(char *caller, SeqTable elm, Buffer *buf)
 {
-       ItemPointerData iptr;
-       PageHeader      page;
-       ItemId          lp;
+       PageHeader              page;
+       ItemId                  lp;
        HeapTupleData   tuple;
        sequence_magic *sm;
-       Form_pg_sequence seq;
-
-       ItemPointerSet(&iptr, 0, FirstOffsetNumber);
-       RelationSetSingleWLockPage(elm->rel, &iptr);
+       Form_pg_sequence        seq;
 
        if (RelationGetNumberOfBlocks(elm->rel) != 1)
                elog(ERROR, "%s.%s: invalid number of blocks in sequence",
@@ -383,6 +375,8 @@ read_info(char *caller, SeqTable elm, Buffer *buf)
        if (!BufferIsValid(*buf))
                elog(ERROR, "%s.%s: ReadBuffer failed", elm->name, caller);
 
+       LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);
+
        page = (PageHeader) BufferGetPage(*buf);
        sm = (sequence_magic *) PageGetSpecialPointer(page);
 
@@ -439,7 +433,7 @@ init_sequence(char *caller, char *name)
        if (!RelationIsValid(temp->rel))
                elog(ERROR, "%s.%s: sequence does not exist", name, caller);
 
-       RelationSetWIntentLock(temp->rel);
+       LockRelation(temp->rel, AccessShareLock);
 
        if (temp->rel->rd_rel->relkind != RELKIND_SEQUENCE)
                elog(ERROR, "%s.%s: %s is not sequence !", name, caller, name);
@@ -485,7 +479,7 @@ CloseSequences(void)
                {
                        rel = elm->rel;
                        elm->rel = (Relation) NULL;
-                       RelationUnsetWIntentLock(rel);
+                       UnlockRelation(rel, AccessShareLock);
                        heap_close(rel);
                }
                elm = elm->next;
index 431a70a6ff9e9037fe1975589462fd588a395356..60d0056930bf040edcf07a03630e5da05ffd9000 100644 (file)
@@ -40,7 +40,7 @@ void          RelationBuildTriggers(Relation relation);
 void           FreeTriggerDesc(Relation relation);
 
 static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
-static HeapTuple GetTupleForTrigger(Relation relation, ItemPointer tid,
+static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid,
                                   bool before);
 
 extern GlobalMemory CacheCxt;
@@ -77,7 +77,7 @@ CreateTrigger(CreateTrigStmt *stmt)
        if (!RelationIsValid(rel))
                elog(ERROR, "CreateTrigger: there is no relation %s", stmt->relname);
 
-       RelationSetLockForWrite(rel);
+       LockRelation(rel, AccessExclusiveLock);
 
        TRIGGER_CLEAR_TYPE(tgtype);
        if (stmt->before)
@@ -114,7 +114,7 @@ CreateTrigger(CreateTrigStmt *stmt)
 
        /* Scan pg_trigger */
        tgrel = heap_openr(TriggerRelationName);
-       RelationSetLockForWrite(tgrel);
+       LockRelation(tgrel, AccessExclusiveLock);
        ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
                                                   F_OIDEQ, RelationGetRelid(rel));
        tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
@@ -211,7 +211,7 @@ CreateTrigger(CreateTrigStmt *stmt)
        CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
        CatalogCloseIndices(Num_pg_trigger_indices, idescs);
        pfree(tuple);
-       RelationUnsetLockForWrite(tgrel);
+       UnlockRelation(tgrel, AccessExclusiveLock);
        heap_close(tgrel);
 
        pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
@@ -227,7 +227,7 @@ CreateTrigger(CreateTrigStmt *stmt)
        pgrel = heap_openr(RelationRelationName);
        ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
        RelationInvalidateHeapTuple(pgrel, tuple);
-       heap_replace(pgrel, &tuple->t_self, tuple);
+       heap_replace(pgrel, &tuple->t_self, tuple, NULL);
        CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
        CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
        CatalogCloseIndices(Num_pg_class_indices, ridescs);
@@ -267,10 +267,10 @@ DropTrigger(DropTrigStmt *stmt)
        if (!RelationIsValid(rel))
                elog(ERROR, "DropTrigger: there is no relation %s", stmt->relname);
 
-       RelationSetLockForWrite(rel);
+       LockRelation(rel, AccessExclusiveLock);
 
        tgrel = heap_openr(TriggerRelationName);
-       RelationSetLockForWrite(tgrel);
+       LockRelation(tgrel, AccessExclusiveLock);
        ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
                                                   F_OIDEQ, RelationGetRelid(rel));
        tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
@@ -280,7 +280,7 @@ DropTrigger(DropTrigStmt *stmt)
 
                if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
                {
-                       heap_delete(tgrel, &tuple->t_self);
+                       heap_delete(tgrel, &tuple->t_self, NULL);
                        tgfound++;
                }
                else
@@ -293,7 +293,7 @@ DropTrigger(DropTrigStmt *stmt)
                elog(NOTICE, "DropTrigger: found (and deleted) %d trigger %s on relation %s",
                         tgfound, stmt->trigname, stmt->relname);
        heap_endscan(tgscan);
-       RelationUnsetLockForWrite(tgrel);
+       UnlockRelation(tgrel, AccessExclusiveLock);
        heap_close(tgrel);
 
        tuple = SearchSysCacheTupleCopy(RELNAME,
@@ -306,7 +306,7 @@ DropTrigger(DropTrigStmt *stmt)
        pgrel = heap_openr(RelationRelationName);
        ((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
        RelationInvalidateHeapTuple(pgrel, tuple);
-       heap_replace(pgrel, &tuple->t_self, tuple);
+       heap_replace(pgrel, &tuple->t_self, tuple, NULL);
        CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
        CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
        CatalogCloseIndices(Num_pg_class_indices, ridescs);
@@ -333,17 +333,17 @@ RelationRemoveTriggers(Relation rel)
        HeapTuple       tup;
 
        tgrel = heap_openr(TriggerRelationName);
-       RelationSetLockForWrite(tgrel);
+       LockRelation(tgrel, AccessExclusiveLock);
        ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
                                                   F_OIDEQ, RelationGetRelid(rel));
 
        tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
 
        while (HeapTupleIsValid(tup = heap_getnext(tgscan, 0)))
-               heap_delete(tgrel, &tup->t_self);
+               heap_delete(tgrel, &tup->t_self, NULL);
 
        heap_endscan(tgscan);
-       RelationUnsetLockForWrite(tgrel);
+       UnlockRelation(tgrel, AccessExclusiveLock);
        heap_close(tgrel);
 
 }
@@ -376,7 +376,6 @@ RelationBuildTriggers(Relation relation)
                                                   ObjectIdGetDatum(RelationGetRelid(relation)));
 
        tgrel = heap_openr(TriggerRelationName);
-       RelationSetLockForRead(tgrel);
        irel = index_openr(TriggerRelidIndex);
        sd = index_beginscan(irel, false, 1, &skey);
 
@@ -450,7 +449,6 @@ RelationBuildTriggers(Relation relation)
        index_endscan(sd);
        pfree(sd);
        index_close(irel);
-       RelationUnsetLockForRead(tgrel);
        heap_close(tgrel);
 
        /* Build trigdesc */
@@ -657,16 +655,17 @@ ExecARInsertTriggers(Relation rel, HeapTuple trigtuple)
 }
 
 bool
-ExecBRDeleteTriggers(Relation rel, ItemPointer tupleid)
+ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
 {
-       TriggerData *SaveTriggerData;
-       int                     ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
-       Trigger   **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
-       HeapTuple       trigtuple;
-       HeapTuple       newtuple = NULL;
-       int                     i;
-
-       trigtuple = GetTupleForTrigger(rel, tupleid, true);
+       Relation                rel = estate->es_result_relation_info->ri_RelationDesc;
+       TriggerData        *SaveTriggerData;
+       int                             ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
+       Trigger           **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
+       HeapTuple               trigtuple;
+       HeapTuple               newtuple = NULL;
+       int                             i;
+
+       trigtuple = GetTupleForTrigger(estate, tupleid, true);
        if (trigtuple == NULL)
                return false;
 
@@ -692,15 +691,16 @@ ExecBRDeleteTriggers(Relation rel, ItemPointer tupleid)
 }
 
 void
-ExecARDeleteTriggers(Relation rel, ItemPointer tupleid)
+ExecARDeleteTriggers(EState *estate, ItemPointer tupleid)
 {
+       Relation                rel = estate->es_result_relation_info->ri_RelationDesc;
        TriggerData *SaveTriggerData;
        int                     ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE];
        Trigger   **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_DELETE];
        HeapTuple       trigtuple;
        int                     i;
 
-       trigtuple = GetTupleForTrigger(rel, tupleid, false);
+       trigtuple = GetTupleForTrigger(estate, tupleid, false);
        Assert(trigtuple != NULL);
 
        SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
@@ -722,17 +722,18 @@ ExecARDeleteTriggers(Relation rel, ItemPointer tupleid)
 }
 
 HeapTuple
-ExecBRUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
+ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
 {
-       TriggerData *SaveTriggerData;
-       int                     ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
-       Trigger   **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
-       HeapTuple       trigtuple;
-       HeapTuple       oldtuple;
-       HeapTuple       intuple = newtuple;
-       int                     i;
-
-       trigtuple = GetTupleForTrigger(rel, tupleid, true);
+       Relation                rel = estate->es_result_relation_info->ri_RelationDesc;
+       TriggerData        *SaveTriggerData;
+       int                             ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
+       Trigger           **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
+       HeapTuple               trigtuple;
+       HeapTuple               oldtuple;
+       HeapTuple               intuple = newtuple;
+       int                             i;
+
+       trigtuple = GetTupleForTrigger(estate, tupleid, true);
        if (trigtuple == NULL)
                return NULL;
 
@@ -759,15 +760,16 @@ ExecBRUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
 }
 
 void
-ExecARUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
+ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
 {
+       Relation                rel = estate->es_result_relation_info->ri_RelationDesc;
        TriggerData *SaveTriggerData;
        int                     ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE];
        Trigger   **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_UPDATE];
        HeapTuple       trigtuple;
        int                     i;
 
-       trigtuple = GetTupleForTrigger(rel, tupleid, false);
+       trigtuple = GetTupleForTrigger(estate, tupleid, false);
        Assert(trigtuple != NULL);
 
        SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
@@ -789,48 +791,67 @@ ExecARUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
 }
 
 static HeapTuple
-GetTupleForTrigger(Relation relation, ItemPointer tid, bool before)
+GetTupleForTrigger(EState *estate, ItemPointer tid, bool before)
 {
-       ItemId                  lp;
+       Relation                relation = estate->es_result_relation_info->ri_RelationDesc;
        HeapTupleData   tuple;
        HeapTuple               result;
-       PageHeader              dp;
-       Buffer                  b;
+       Buffer                  buffer;
 
-       b = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
+       if (before)
+       {
+               int             test;
+
+               /*
+                *      mark tuple for update
+                */
+               tuple.t_self = *tid;
+               test = heap_mark4update(relation, &tuple, &buffer);
+               switch (test)
+               {
+                       case HeapTupleSelfUpdated:
+                               ReleaseBuffer(buffer);
+                               return(NULL);
 
-       if (!BufferIsValid(b))
-               elog(ERROR, "GetTupleForTrigger: failed ReadBuffer");
+                       case HeapTupleMayBeUpdated:
+                               break;
 
-       dp = (PageHeader) BufferGetPage(b);
-       lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
+                       case HeapTupleUpdated:
+                               ReleaseBuffer(buffer);
+                               if (XactIsoLevel == XACT_SERIALIZED)
+                                       elog(ERROR, "Serialize access failed due to concurrent update");
+                               else
+                                       elog(ERROR, "Isolation level %u is not supported", XactIsoLevel);
+                               return(NULL);
 
-       Assert(ItemIdIsUsed(lp));
+                       default:
+                               ReleaseBuffer(buffer);
+                               elog(ERROR, "Unknown status %u from heap_mark4update", test);
+                               return(NULL);
+               }
+       }
+       else
+       {
+               PageHeader              dp;
+               ItemId                  lp;
 
-       tuple.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
-       tuple.t_len = ItemIdGetLength(lp);
-       tuple.t_self = *tid;
+               buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
 
-       if (before)
-       {
-               if (TupleUpdatedByCurXactAndCmd(&tuple))
-               {
-                       elog(NOTICE, "GetTupleForTrigger: Non-functional delete/update");
-                       ReleaseBuffer(b);
-                       return NULL;
-               }
+               if (!BufferIsValid(buffer))
+                       elog(ERROR, "GetTupleForTrigger: failed ReadBuffer");
 
-               HeapTupleSatisfies(&tuple, relation, b, dp,
-                                                  false, 0, (ScanKey) NULL);
-               if (!tuple.t_data)
-               {
-                       ReleaseBuffer(b);
-                       elog(ERROR, "GetTupleForTrigger: (am)invalid tid");
-               }
+               dp = (PageHeader) BufferGetPage(buffer);
+               lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
+
+               Assert(ItemIdIsUsed(lp));
+
+               tuple.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
+               tuple.t_len = ItemIdGetLength(lp);
+               tuple.t_self = *tid;
        }
 
        result = heap_copytuple(&tuple);
-       ReleaseBuffer(b);
+       ReleaseBuffer(buffer);
 
        return result;
 }
index e0c0e51ea13a3e6276c50847fa4a02fbe06f405e..7c4203528fae6c75f6f8c99daa47d20805fb98af 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: user.c,v 1.22 1998/12/14 08:11:00 scrappy Exp $
+ * $Id: user.c,v 1.23 1998/12/15 12:46:00 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -136,7 +136,7 @@ DefineUser(CreateUserStmt *stmt)
         * Secure a write lock on pg_shadow so we can be sure of what the next
         * usesysid should be.
         */
-       RelationSetLockForWrite(pg_shadow_rel);
+       LockRelation(pg_shadow_rel, AccessExclusiveLock);
 
        scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, NULL);
        while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
@@ -154,7 +154,7 @@ DefineUser(CreateUserStmt *stmt)
 
        if (exists)
        {
-               RelationUnsetLockForWrite(pg_shadow_rel);
+               UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
                heap_close(pg_shadow_rel);
                UserAbortTransactionBlock();
                elog(ERROR, 
@@ -187,7 +187,7 @@ DefineUser(CreateUserStmt *stmt)
         * This goes after the UpdatePgPwdFile to be certain that two backends
         * to not attempt to write to the pg_pwd file at the same time.
         */
-       RelationUnsetLockForWrite(pg_shadow_rel);
+       UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
        heap_close(pg_shadow_rel);
 
        if (IsTransactionBlock() && !inblock)
@@ -235,14 +235,14 @@ AlterUser(AlterUserStmt *stmt)
         * dump of the pg_pwd file is done, there is not another backend doing
         * the same.
         */
-       RelationSetLockForWrite(pg_shadow_rel);
+       LockRelation(pg_shadow_rel, AccessExclusiveLock);
 
        tuple = SearchSysCacheTuple(USENAME,
                                                                PointerGetDatum(stmt->user),
                                                                0, 0, 0);
        if (!HeapTupleIsValid(tuple))
        {
-               RelationUnsetLockForWrite(pg_shadow_rel);
+               UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
                heap_close(pg_shadow_rel);
                UserAbortTransactionBlock();    /* needed? */
                elog(ERROR, "alterUser: user \"%s\" does not exist", stmt->user);
@@ -288,7 +288,7 @@ AlterUser(AlterUserStmt *stmt)
 
        UpdatePgPwdFile(sql);
 
-       RelationUnsetLockForWrite(pg_shadow_rel);
+       UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
        heap_close(pg_shadow_rel);
 
        if (IsTransactionBlock() && !inblock)
@@ -342,14 +342,14 @@ RemoveUser(char *user)
         * dump of the pg_pwd file is done, there is not another backend doing
         * the same.
         */
-       RelationSetLockForWrite(pg_shadow_rel);
+       LockRelation(pg_shadow_rel, AccessExclusiveLock);
 
        tuple = SearchSysCacheTuple(USENAME,
                                                                PointerGetDatum(user),
                                                                0, 0, 0);
        if (!HeapTupleIsValid(tuple))
        {
-               RelationUnsetLockForWrite(pg_shadow_rel);
+               UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
                heap_close(pg_shadow_rel);
                UserAbortTransactionBlock();
                elog(ERROR, "removeUser: user \"%s\" does not exist", user);
@@ -422,7 +422,7 @@ RemoveUser(char *user)
 
        UpdatePgPwdFile(sql);
 
-       RelationUnsetLockForWrite(pg_shadow_rel);
+       UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
        heap_close(pg_shadow_rel);
 
        if (IsTransactionBlock() && !inblock)
index f7bed005add47272b50079d88787afcc85deeb2d..608dd729ffa6656debaf6183d1dc8ca15ce5e28a 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.91 1998/11/27 19:51:58 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.92 1998/12/15 12:46:01 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -497,7 +497,7 @@ vc_vacone(Oid relid, bool analyze, List *va_cols)
        }
 
        /* we require the relation to be locked until the indices are cleaned */
-       RelationSetLockForWrite(onerel);
+       LockRelation(onerel, AccessExclusiveLock);
 
        /* scan it */
        vacuum_pages.vpl_num_pages = fraged_pages.vpl_num_pages = 0;
@@ -1918,7 +1918,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums)
                        if (i >= attcnt)
                                continue;               /* don't delete it */
                }
-               heap_delete(pgstatistic, &tuple->t_self);
+               heap_delete(pgstatistic, &tuple->t_self, NULL);
        }
 
        heap_endscan(scan);
@@ -1928,11 +1928,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums)
 static void
 vc_setpagelock(Relation rel, BlockNumber blkno)
 {
-       ItemPointerData itm;
-
-       ItemPointerSet(&itm, blkno, 1);
-
-       RelationSetLockForWritePage(rel, &itm);
+       LockPage(rel, blkno, ExclusiveLock);
 }
 
 /*
index 45be159ae17c5a5166b2dcaaaf6dce2326f7d5dd..712f2285342e59a598e3c970082dd693b20f6ed3 100644 (file)
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.59 1998/11/27 19:51:59 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.60 1998/12/15 12:46:04 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -51,6 +51,7 @@
 /* #include "access/localam.h" */
 #include "optimizer/var.h"
 #include "access/heapam.h"
+#include "access/xact.h"
 #include "catalog/heap.h"
 #include "commands/trigger.h"
 
@@ -421,7 +422,6 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
        {
                /******************
                 *        if we have a result relation, open it and
-
                 *        initialize the result relation info stuff.
                 ******************
                 */
@@ -440,14 +440,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
                        elog(ERROR, "You can't change sequence relation %s",
                                 resultRelationDesc->rd_rel->relname.data);
 
-               /*
-                * Write-lock the result relation right away: if the relation is
-                * used in a subsequent scan, we won't have to elevate the
-                * read-lock set by heap_beginscan to a write-lock (needed by
-                * heap_insert, heap_delete and heap_replace). This will hopefully
-                * prevent some deadlocks.      - 01/24/94
-                */
-               RelationSetLockForWrite(resultRelationDesc);
+               LockRelation(resultRelationDesc, RowExclusiveLock);
 
                resultRelationInfo = makeNode(RelationInfo);
                resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
@@ -461,7 +454,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
                 *      in the result relation information..
                 ******************
                 */
-               ExecOpenIndices(resultRelationOid, resultRelationInfo);
+               if (operation != CMD_DELETE)
+                       ExecOpenIndices(resultRelationOid, resultRelationInfo);
 
                estate->es_result_relation_info = resultRelationInfo;
        }
@@ -1006,8 +1000,10 @@ ExecDelete(TupleTableSlot *slot,
                   ItemPointer tupleid,
                   EState *estate)
 {
-       RelationInfo *resultRelationInfo;
-       Relation        resultRelationDesc;
+       RelationInfo       *resultRelationInfo;
+       Relation                        resultRelationDesc;
+       ItemPointerData         ctid;
+       int                                     result;
 
        /******************
         *      get the result relation information
@@ -1022,19 +1018,35 @@ ExecDelete(TupleTableSlot *slot,
        {
                bool            dodelete;
 
-               dodelete = ExecBRDeleteTriggers(resultRelationDesc, tupleid);
+               dodelete = ExecBRDeleteTriggers(estate, tupleid);
 
                if (!dodelete)                  /* "do nothing" */
                        return;
        }
 
-       /******************
+       /*
         *      delete the tuple
-        ******************
         */
-       if (heap_delete(resultRelationDesc, /* relation desc */
-                                       tupleid))       /* item pointer to tuple */
-               return;
+       result = heap_delete(resultRelationDesc, tupleid, &ctid);
+       switch (result)
+       {
+               case HeapTupleSelfUpdated:
+                       return;
+
+               case HeapTupleMayBeUpdated:
+                       break;
+
+               case HeapTupleUpdated:
+                       if (XactIsoLevel == XACT_SERIALIZED)
+                               elog(ERROR, "Serialize access failed due to concurrent update");
+                       else
+                               elog(ERROR, "Isolation level %u is not supported", XactIsoLevel);
+                       return;
+
+               default:
+                       elog(ERROR, "Unknown status %u from heap_delete", result);
+                       return;
+       }
 
        IncrDeleted();
        (estate->es_processed)++;
@@ -1054,7 +1066,7 @@ ExecDelete(TupleTableSlot *slot,
        /* AFTER ROW DELETE Triggers */
        if (resultRelationDesc->trigdesc &&
         resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
-               ExecARDeleteTriggers(resultRelationDesc, tupleid);
+               ExecARDeleteTriggers(estate, tupleid);
 
 }
 
@@ -1075,10 +1087,12 @@ ExecReplace(TupleTableSlot *slot,
                        EState *estate,
                        Query *parseTree)
 {
-       HeapTuple       tuple;
-       RelationInfo *resultRelationInfo;
-       Relation        resultRelationDesc;
-       int                     numIndices;
+       HeapTuple                       tuple;
+       RelationInfo       *resultRelationInfo;
+       Relation                        resultRelationDesc;
+       ItemPointerData         ctid;
+       int                                     result;
+       int                                     numIndices;
 
        /******************
         *      abort the operation if not running transactions
@@ -1117,7 +1131,7 @@ ExecReplace(TupleTableSlot *slot,
        {
                HeapTuple       newtuple;
 
-               newtuple = ExecBRUpdateTriggers(resultRelationDesc, tupleid, tuple);
+               newtuple = ExecBRUpdateTriggers(estate, tupleid, tuple);
 
                if (newtuple == NULL)   /* "do nothing" */
                        return;
@@ -1140,19 +1154,28 @@ ExecReplace(TupleTableSlot *slot,
                ExecConstraints("ExecReplace", resultRelationDesc, tuple);
        }
 
-       /******************
+       /*
         *      replace the heap tuple
-        *
-        * Don't want to continue if our heap_replace didn't actually
-        * do a replace. This would be the case if heap_replace
-        * detected a non-functional update. -kw 12/30/93
-        ******************
         */
-       if (heap_replace(resultRelationDesc,            /* relation desc */
-                                        tupleid,       /* item ptr of tuple to replace */
-                                        tuple))
-       {                                                       /* replacement heap tuple */
-               return;
+       result = heap_replace(resultRelationDesc, tupleid, tuple, &ctid);
+       switch (result)
+       {
+               case HeapTupleSelfUpdated:
+                       return;
+
+               case HeapTupleMayBeUpdated:
+                       break;
+
+               case HeapTupleUpdated:
+                       if (XactIsoLevel == XACT_SERIALIZED)
+                               elog(ERROR, "Serialize access failed due to concurrent update");
+                       else
+                               elog(ERROR, "Isolation level %u is not supported", XactIsoLevel);
+                       return;
+
+               default:
+                       elog(ERROR, "Unknown status %u from heap_replace", result);
+                       return;
        }
 
        IncrReplaced();
@@ -1187,7 +1210,7 @@ ExecReplace(TupleTableSlot *slot,
        /* AFTER ROW UPDATE Triggers */
        if (resultRelationDesc->trigdesc &&
         resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
-               ExecARUpdateTriggers(resultRelationDesc, tupleid, tuple);
+               ExecARUpdateTriggers(estate, tupleid, tuple);
 }
 
 #if 0
index 1af4fcbc88a354faaf7f0d2e361f7b4c7f3bde11..58dbcd19efc5a90c40f514e580b7eb71b91f3359 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.40 1998/11/27 19:52:01 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.41 1998/12/15 12:46:05 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -868,7 +868,23 @@ ExecOpenIndices(Oid resultRelationOid,
                        indexOid = lfirsti(indexoid);
                        indexDesc = index_open(indexOid);
                        if (indexDesc != NULL)
+                       {
                                relationDescs[i++] = indexDesc;
+                               /*
+                                * Hack for not btree and hash indices: they use relation level
+                                * exclusive locking on updation (i.e. - they are not ready 
+                                * for MVCC) and so we have to exclusively lock indices here
+                                * to prevent deadlocks if we will scan them - index_beginscan
+                                * places AccessShareLock, indices update methods don't use 
+                                * locks at all. We release this lock in ExecCloseIndices.
+                                * Note, that hashes use page level locking - i.e. are not
+                                * deadlock-free, - let's them be on their way -:))
+                                *              vadim 03-12-1998
+                                */
+                               if (indexDesc->rd_rel->relam != BTREE_AM_OID && 
+                                               indexDesc->rd_rel->relam != HASH_AM_OID)
+                                       LockRelation(indexDesc, AccessExclusiveLock);
+                       }
                }
 
                /* ----------------
@@ -948,9 +964,18 @@ ExecCloseIndices(RelationInfo *resultRelationInfo)
        relationDescs = resultRelationInfo->ri_IndexRelationDescs;
 
        for (i = 0; i < numIndices; i++)
-               if (relationDescs[i] != NULL)
-                       index_close(relationDescs[i]);
+       {
+               if (relationDescs[i] == NULL)
+                       continue;
+               /*
+                * Notes in ExecOpenIndices.
+                */
+               if (relationDescs[i]->rd_rel->relam != BTREE_AM_OID && 
+                               relationDescs[i]->rd_rel->relam != HASH_AM_OID)
+                       UnlockRelation(relationDescs[i], AccessExclusiveLock);
 
+               index_close(relationDescs[i]);
+       }
        /*
         * XXX should free indexInfo array here too.
         */
index 5f528850ffac17b0ecd45c025abb28bd7a5b7d92..5ec45c7c795726528798942afa2d7be2b7a64907 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (c) 1994, Regents of the University of California
  *
  *
- *  $Id: nodeHash.c,v 1.27 1998/12/14 08:11:02 scrappy Exp $
+ *  $Id: nodeHash.c,v 1.28 1998/12/15 12:46:06 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -693,13 +693,13 @@ ExecScanHashBucket(HashJoinState *hjstate,
                else
                        heapTuple = (HeapTuple)
                                LONGALIGN(((char *) curtuple + curtuple->t_len + HEAPTUPLESIZE));
-               
-               heapTuple->t_data = (HeapTupleHeader) 
-                                                       ((char *) heapTuple + HEAPTUPLESIZE);
 
                while (heapTuple < (HeapTuple) ABSADDR(bucket->bottom))
                {
 
+                       heapTuple->t_data = (HeapTupleHeader) 
+                                                               ((char *) heapTuple + HEAPTUPLESIZE);
+
                        inntuple = ExecStoreTuple(heapTuple,            /* tuple to store */
                                                                          hjstate->hj_HashTupleSlot,            /* slot */
                                                                          InvalidBuffer,        /* tuple has no buffer */
@@ -713,8 +713,6 @@ ExecScanHashBucket(HashJoinState *hjstate,
 
                        heapTuple = (HeapTuple)
                                LONGALIGN(((char *) heapTuple + heapTuple->t_len + HEAPTUPLESIZE));
-                       heapTuple->t_data = (HeapTupleHeader) 
-                                                               ((char *) heapTuple + HEAPTUPLESIZE);
                }
 
                if (firstotuple == NULL)
index 6c484aecf18c447e7120569c20f0641b0127cb0b..0eb9d3eb137359f90c1b8af10e31d99b22db9d58 100644 (file)
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/Attic/gram.c,v 2.51 1998/12/14 05:18:57 scrappy Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/Attic/gram.c,v 2.52 1998/12/15 12:46:08 vadim Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
index c2066a43b12d8c60b773f1c99f7c930255687f83..bc9c9a738a4d7c668fc95a2f77bc3437f8cb823d 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.34 1998/12/13 23:54:40 thomas Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.35 1998/12/15 12:46:14 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1115,7 +1115,6 @@ find_inheritors(Oid relid, Oid **supervec)
 
 
        inhrel = heap_openr(InheritsRelationName);
-       RelationSetLockForRead(inhrel);
        inhtupdesc = RelationGetDescr(inhrel);
 
        /*
@@ -1182,7 +1181,6 @@ find_inheritors(Oid relid, Oid **supervec)
                }
        } while (qentry != (SuperQE *) NULL);
 
-       RelationUnsetLockForRead(inhrel);
        heap_close(inhrel);
 
        if (nvisited > 0)
index fd1472a93cf24045f517b9a20548576cfe7aeb18..8be2f413cfc248f1cd96fac1bc9e5b8500293e52 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.20 1998/12/14 00:02:17 thomas Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.21 1998/12/15 12:46:16 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -127,7 +127,7 @@ RemoveRewriteRule(char *ruleName)
        /*
         * Now delete the tuple...
         */
-       heap_delete(RewriteRelation, &tuple->t_self);
+       heap_delete(RewriteRelation, &tuple->t_self, NULL);
 
        pfree(tuple);
        heap_close(RewriteRelation);
@@ -164,7 +164,7 @@ RelationRemoveRules(Oid relid)
                                                          0, SnapshotNow, 1, &scanKeyData);
 
        while (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0)))
-               heap_delete(RewriteRelation, &tuple->t_self);
+               heap_delete(RewriteRelation, &tuple->t_self, NULL);
 
        heap_endscan(scanDesc);
        heap_close(RewriteRelation);
index 2b57e2771165e228c3b0a9e524a32711260931f6..15a9b18b906135c15da7b97812c032cf5faa5ca7 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.29 1998/11/27 19:52:18 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.30 1998/12/15 12:46:18 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -128,7 +128,7 @@ setRelhasrulesInRelation(Oid relationId, bool relhasrules)
 
        relationRelation = heap_openr(RelationRelationName);
        ((Form_pg_class) GETSTRUCT(tuple))->relhasrules = relhasrules;
-       heap_replace(relationRelation, &tuple->t_self, tuple);
+       heap_replace(relationRelation, &tuple->t_self, tuple, NULL);
 
        /* keep the catalog indices up to date */
        CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
index 975e999ec2b26e1871b0f4aaebcd4f71339af78a..620708aaae3834fc6c0d950d0f62fb847ba4e7d6 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.19 1998/09/01 04:31:39 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.20 1998/12/15 12:46:18 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,13 +62,13 @@ BufferBlock BufferBlocks;
 
 #ifndef HAS_TEST_AND_SET
 long      *NWaitIOBackendP;
-
 #endif
 
 extern IpcSemaphoreId WaitIOSemId;
 
 long      *PrivateRefCount;    /* also used in freelist.c */
 long      *LastRefCount;               /* refcounts of last ExecMain level */
+bits8     *BufferLocks;                /* */
 long      *CommitInfoNeedsSave;/* to write buffers where we have filled
                                                                 * in t_infomask */
 
@@ -146,21 +146,6 @@ InitBufferPool(IPCKey key)
                                foundDescs;
        int                     i;
 
-       /* check padding of BufferDesc and BufferHdr */
-
-       /*
-        * we need both checks because a sbufdesc_padded >
-        * PADDED_SBUFDESC_SIZE will shrink sbufdesc to the required size,
-        * which is bad
-        */
-       if (sizeof(struct sbufdesc) != PADDED_SBUFDESC_SIZE ||
-               sizeof(struct sbufdesc_unpadded) > PADDED_SBUFDESC_SIZE)
-               elog(ERROR, "Internal error:  sbufdesc does not have the proper size, "
-                        "contact the Postgres developers");
-       if (sizeof(struct sbufdesc_unpadded) <= PADDED_SBUFDESC_SIZE / 2)
-               elog(ERROR, "Internal error:  sbufdesc is greatly over-sized, "
-                        "contact the Postgres developers");
-
        Data_Descriptors = NBuffers;
        Free_List_Descriptor = Data_Descriptors;
        Lookup_List_Descriptor = Data_Descriptors + 1;
@@ -232,6 +217,7 @@ InitBufferPool(IPCKey key)
                        buf->buf_id = i;
 #ifdef HAS_TEST_AND_SET
                        S_INIT_LOCK(&(buf->io_in_progress_lock));
+                       S_INIT_LOCK(&(buf->cntx_lock));
 #endif
                }
 
@@ -252,10 +238,15 @@ InitBufferPool(IPCKey key)
 
                WaitIOSemId = IpcSemaphoreCreate(IPCKeyGetWaitIOSemaphoreKey(key),
                                                                                 1, IPCProtection, 0, 1, &status);
+               WaitCLSemId = IpcSemaphoreCreate(IPCKeyGetWaitCLSemaphoreKey(key),
+                                                                                1, IPCProtection, 
+                                                                                IpcSemaphoreDefaultStartValue, 
+                                                                                1, &status);
        }
 #endif
        PrivateRefCount = (long *) calloc(NBuffers, sizeof(long));
        LastRefCount = (long *) calloc(NBuffers, sizeof(long));
+       BufferLocks = (bits8*) calloc (NBuffers, sizeof(bits8));
        CommitInfoNeedsSave = (long *) calloc(NBuffers, sizeof(long));
 }
 
index cab1e8084e00b793b8f594695782b2455edab18c..d5fa26b6035a8b254c69545c211093914c8c30e0 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.44 1998/10/08 18:29:54 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.45 1998/12/15 12:46:19 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -86,7 +86,6 @@ static void WaitIO(BufferDesc *buf, SPINLOCK spinlock);
 #ifndef HAS_TEST_AND_SET
 static void SignalIO(BufferDesc *buf);
 extern long *NWaitIOBackendP;  /* defined in buf_init.c */
-
 #endif  /* HAS_TEST_AND_SET */
 
 static Buffer ReadBufferWithBufferLock(Relation relation, BlockNumber blockNum,
@@ -583,7 +582,6 @@ BufferAlloc(Relation reln,
                                        if (buf->refcount > 1)
                                                SignalIO(buf);
 #endif  /* !HAS_TEST_AND_SET */
-
                                        /* give up the buffer since we don't need it any more */
                                        buf->refcount--;
                                        PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 0;
@@ -1096,6 +1094,7 @@ WaitIO(BufferDesc *buf, SPINLOCK spinlock)
 
 #else                                                  /* HAS_TEST_AND_SET */
 IpcSemaphoreId WaitIOSemId;
+IpcSemaphoreId WaitCLSemId;
 
 static void
 WaitIO(BufferDesc *buf, SPINLOCK spinlock)
@@ -1933,3 +1932,147 @@ SetBufferCommitInfoNeedsSave(Buffer buffer)
        if (!BufferIsLocal(buffer))
                CommitInfoNeedsSave[buffer - 1]++;
 }
+
+void
+UnlockBuffers()
+{
+       BufferDesc *buf;
+       int                     i;
+
+       for (i = 0; i < NBuffers; i++)
+       {
+               if (BufferLocks[i] == 0)
+                       continue;
+               
+               Assert(BufferIsValid(i+1));
+               buf = &(BufferDescriptors[i]);
+
+#ifdef HAS_TEST_AND_SET
+               S_LOCK(&(buf->cntx_lock));
+#else
+               IpcSemaphoreLock(WaitCLSemId, 0, IpcExclusiveLock);
+#endif
+
+               if (BufferLocks[i] & BL_R_LOCK)
+               {
+                       Assert(buf->r_locks > 0);
+                       (buf->r_locks)--;
+               }
+               if (BufferLocks[i] & BL_RI_LOCK)
+               {
+                       Assert(buf->ri_lock);
+                       buf->ri_lock = false;
+               }
+               if (BufferLocks[i] & BL_W_LOCK)
+               {
+                       Assert(buf->w_lock);
+                       buf->w_lock = false;
+               }
+#ifdef HAS_TEST_AND_SET
+               S_UNLOCK(&(buf->cntx_lock));
+#else
+               IpcSemaphoreUnlock(WaitCLSemId, 0, IpcExclusiveLock);
+#endif
+               BufferLocks[i] = 0;
+       }
+}
+
+void
+LockBuffer (Buffer buffer, int mode)
+{
+       BufferDesc *buf;
+
+       Assert(BufferIsValid(buffer));
+       if (BufferIsLocal(buffer))
+               return;
+
+       buf = &(BufferDescriptors[buffer-1]);
+
+#ifdef HAS_TEST_AND_SET
+               S_LOCK(&(buf->cntx_lock));
+#else
+               IpcSemaphoreLock(WaitCLSemId, 0, IpcExclusiveLock);
+#endif
+
+       if (mode == BUFFER_LOCK_UNLOCK)
+       {
+               if (BufferLocks[buffer-1] & BL_R_LOCK)
+               {
+                       Assert(buf->r_locks > 0);
+                       Assert(!(buf->w_lock));
+                       Assert(!(BufferLocks[buffer-1] & (BL_W_LOCK | BL_RI_LOCK)))
+                       (buf->r_locks)--;
+                       BufferLocks[buffer-1] &= ~BL_R_LOCK;
+               }
+               else if (BufferLocks[buffer-1] & BL_W_LOCK)
+               {
+                       Assert(buf->w_lock);
+                       Assert(buf->r_locks == 0 && !buf->ri_lock);
+                       Assert(!(BufferLocks[buffer-1] & (BL_R_LOCK | BL_RI_LOCK)))
+                       buf->w_lock = false;
+                       BufferLocks[buffer-1] &= ~BL_W_LOCK;
+               }
+               else
+                       elog(ERROR, "UNLockBuffer: buffer %u is not locked", buffer);
+       }
+       else if (mode == BUFFER_LOCK_SHARE)
+       {
+               unsigned        i = 0;
+
+               Assert(!(BufferLocks[buffer-1] & (BL_R_LOCK | BL_W_LOCK | BL_RI_LOCK)));
+               while (buf->ri_lock || buf->w_lock)
+               {
+#ifdef HAS_TEST_AND_SET
+                       S_UNLOCK(&(buf->cntx_lock));
+                       s_lock_sleep(i++);
+                       S_LOCK(&(buf->cntx_lock));
+#else
+                       IpcSemaphoreUnlock(WaitCLSemId, 0, IpcExclusiveLock);
+                       s_lock_sleep(i++)
+                       IpcSemaphoreLock(WaitCLSemId, 0, IpcExclusiveLock);
+#endif
+               }
+               (buf->r_locks)++;
+               BufferLocks[buffer-1] |= BL_R_LOCK;
+       }
+       else if (mode == BUFFER_LOCK_EXCLUSIVE)
+       {
+               unsigned        i = 0;
+               
+               Assert(!(BufferLocks[buffer-1] & (BL_R_LOCK | BL_W_LOCK | BL_RI_LOCK)));
+               while (buf->r_locks > 0 || buf->w_lock)
+               {
+                       if (buf->r_locks > 3)
+                       {
+                               if (!(BufferLocks[buffer-1] & BL_RI_LOCK))
+                                       BufferLocks[buffer-1] |= BL_RI_LOCK;
+                               buf->ri_lock = true;
+                       }
+#ifdef HAS_TEST_AND_SET
+                       S_UNLOCK(&(buf->cntx_lock));
+                       s_lock_sleep(i++);
+                       S_LOCK(&(buf->cntx_lock));
+#else
+                       IpcSemaphoreUnlock(WaitCLSemId, 0, IpcExclusiveLock);
+                       s_lock_sleep(i++)
+                       IpcSemaphoreLock(WaitCLSemId, 0, IpcExclusiveLock);
+#endif
+               }
+               buf->w_lock = true;
+               BufferLocks[buffer-1] |= BL_W_LOCK;
+               if (BufferLocks[buffer-1] & BL_RI_LOCK)
+               {
+                       buf->ri_lock = false;
+                       BufferLocks[buffer-1] &= ~BL_RI_LOCK;
+               }
+       }
+       else
+               elog(ERROR, "LockBuffer: unknown lock mode %d", mode);
+
+#ifdef HAS_TEST_AND_SET
+               S_UNLOCK(&(buf->cntx_lock));
+#else
+               IpcSemaphoreUnlock(WaitCLSemId, 0, IpcExclusiveLock);
+#endif
+
+}
index a7b42bc479332f491066aa1cb5981b644cce57ae..439240a386fd540e0e70ae7720de8653f300ec03 100644 (file)
@@ -7,13 +7,14 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.12 1998/09/18 17:18:39 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.13 1998/12/15 12:46:21 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include <stdio.h>
 #include <sys/time.h>
+#include <unistd.h>
 
 #include "config.h"
 #include "c.h"
@@ -52,6 +53,16 @@ s_lock_stuck(volatile slock_t *lock, const char *file, const int line)
 }
 
 
+void
+s_lock_sleep(unsigned spin)
+{
+       struct timeval delay;
+
+       delay.tv_sec = 0;
+       delay.tv_usec = s_spincycle[spin % S_NSPINCYCLE];
+       (void) select(0, NULL, NULL, NULL, &delay);
+}
+
 
 /*
  * s_lock(lock) - take a spinlock with backoff
@@ -59,15 +70,11 @@ s_lock_stuck(volatile slock_t *lock, const char *file, const int line)
 void
 s_lock(volatile slock_t *lock, const char *file, const int line)
 {
-       int                     spins = 0;
+       unsigned        spins = 0;
 
        while (TAS(lock))
        {
-               struct timeval delay;
-
-               delay.tv_sec = 0;
-               delay.tv_usec = s_spincycle[spins % S_NSPINCYCLE];
-               (void) select(0, NULL, NULL, NULL, &delay);
+               s_lock_sleep(spins);
                if (++spins > S_MAX_BUSY)
                {
                        /* It's been over a minute...  */
index f6ce9eda241a6cbbc57a2e80de0e663db88741cb..47305f3f0875be2d2d8cf29ae5fdcdbbba5233f3 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.16 1998/09/01 03:25:10 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.17 1998/12/15 12:46:24 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,7 +17,6 @@
 #include "postgres.h"
 
 #include "storage/ipc.h"
-#include "storage/multilev.h"
 #include "storage/sinval.h"
 #include "storage/bufmgr.h"
 #include "storage/proc.h"
@@ -92,7 +91,7 @@ CreateSharedMemoryAndSemaphores(IPCKey key)
         * ----------------
         */
        InitLocks();
-       if (InitMultiLevelLocks() == INVALID_TABLEID)
+       if (InitLockTable() == INVALID_TABLEID)
                elog(FATAL, "Couldn't create the lock table");
 
        /* ----------------
@@ -145,7 +144,7 @@ AttachSharedMemoryAndSemaphores(IPCKey key)
         * ----------------
         */
        InitLocks();
-       if (InitMultiLevelLocks() == INVALID_TABLEID)
+       if (InitLockTable() == INVALID_TABLEID)
                elog(FATAL, "Couldn't attach to the lock table");
 
        AttachSharedInvalidationState(key);
index 18b8d718d67fb9a77790f53264def058465c321f..17416fc9eef8ecdb9c3a05aef08d16463c4e0de1 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.31 1998/09/01 04:31:49 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/shmem.c,v 1.32 1998/12/15 12:46:24 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -68,7 +68,8 @@
 #include "utils/dynahash.h"
 #include "utils/hsearch.h"
 #include "utils/memutils.h"
-#include "access/transam.h"
+#include "access/xact.h"
+#include "utils/tqual.h"
 
 /* shared memory global variables */
 
@@ -629,7 +630,6 @@ TransactionIdIsInProgress(TransactionId xid)
        return false;
 }
 
-#ifdef LowLevelLocking
 /*
  * GetSnapshotData -- returns information about running transactions.
  *
@@ -645,16 +645,15 @@ Snapshot
 GetSnapshotData(bool serialized)
 {
        Snapshot        snapshot = (Snapshot) malloc(sizeof(SnapshotData));
-       TransactionId snapshot->xip = (TransactionId *)
-       malloc(32 * sizeof(TransactionId));
        ShmemIndexEnt *result;
        PROC       *proc;
        TransactionId cid = GetCurrentTransactionId();
-       uint            count = 0;
-       unit            free = 31;
+       uint32          count = 0;
+       uint32          have = 31;
 
        Assert(ShmemIndex);
 
+       snapshot->xip = (TransactionId *) malloc(32 * sizeof(TransactionId));
        snapshot->xmax = cid;
        snapshot->xmin = cid;
 
@@ -676,20 +675,20 @@ GetSnapshotData(bool serialized)
                        continue;
                proc = (PROC *) MAKE_PTR(result->location);
                if (proc == MyProc || proc->xid < FirstTransactionId ||
-                       serialized && proc->xid >= cid)
+                       (serialized && proc->xid >= cid))
                        continue;
                if (proc->xid < snapshot->xmin)
                        snapshot->xmin = proc->xid;
                else if (proc->xid > snapshot->xmax)
                        snapshot->xmax = proc->xid;
-               if (free == 0)
+               if (have == 0)
                {
                        snapshot->xip = (TransactionId *) realloc(snapshot->xip,
                                                                   (count + 33) * sizeof(TransactionId));
-                       free = 32;
+                       have = 32;
                }
                snapshot->xip[count] = proc->xid;
-               free--;
+               have--;
                count++;
        }
 
@@ -699,5 +698,3 @@ GetSnapshotData(bool serialized)
        elog(ERROR, "GetSnapshotData: ShmemIndex corrupted");
        return NULL;
 }
-
-#endif
index 740a4132631489028b173cb2330f946efae64374..404604041972b8826b60a6880014cb0ba05ecc6e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.43 1998/12/13 05:07:50 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.44 1998/12/15 12:46:26 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -203,12 +203,12 @@ inv_create(int flags)
 
        if (flags & INV_WRITE)
        {
-               RelationSetLockForWrite(r);
+               LockRelation(r, ExclusiveLock);
                retval->flags = IFS_WRLOCK | IFS_RDLOCK;
        }
        else if (flags & INV_READ)
        {
-               RelationSetLockForRead(r);
+               LockRelation(r, ShareLock);
                retval->flags = IFS_RDLOCK;
        }
        retval->flags |= IFS_ATEOF;
@@ -254,12 +254,12 @@ inv_open(Oid lobjId, int flags)
 
        if (flags & INV_WRITE)
        {
-               RelationSetLockForWrite(r);
+               LockRelation(r, ExclusiveLock);
                retval->flags = IFS_WRLOCK | IFS_RDLOCK;
        }
        else if (flags & INV_READ)
        {
-               RelationSetLockForRead(r);
+               LockRelation(r, ShareLock);
                retval->flags = IFS_RDLOCK;
        }
 
@@ -328,7 +328,7 @@ inv_stat(LargeObjectDesc *obj_desc, struct pgstat * stbuf)
        /* need read lock for stat */
        if (!(obj_desc->flags & IFS_RDLOCK))
        {
-               RelationSetLockForRead(obj_desc->heap_r);
+               LockRelation(obj_desc->heap_r, ShareLock);
                obj_desc->flags |= IFS_RDLOCK;
        }
 
@@ -376,7 +376,7 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
                /* need read lock for getsize */
                if (!(obj_desc->flags & IFS_RDLOCK))
                {
-                       RelationSetLockForRead(obj_desc->heap_r);
+                       LockRelation(obj_desc->heap_r, ShareLock);
                        obj_desc->flags |= IFS_RDLOCK;
                }
                offset += _inv_getsize(obj_desc->heap_r,
@@ -458,7 +458,7 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
        /* make sure we obey two-phase locking */
        if (!(obj_desc->flags & IFS_RDLOCK))
        {
-               RelationSetLockForRead(obj_desc->heap_r);
+               LockRelation(obj_desc->heap_r, ShareLock);
                obj_desc->flags |= IFS_RDLOCK;
        }
 
@@ -516,7 +516,7 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
 
        if (!(obj_desc->flags & IFS_WRLOCK))
        {
-               RelationSetLockForRead(obj_desc->heap_r);
+               LockRelation(obj_desc->heap_r, ShareLock);
                obj_desc->flags |= (IFS_WRLOCK | IFS_RDLOCK);
        }
 
index 66fc25484a48231196a7e3fb9187671f6938719f..88cd9d060c4c7e67b6717f6d3399fefd473d19c5 100644 (file)
@@ -4,7 +4,7 @@
 #    Makefile for storage/lmgr
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/storage/lmgr/Makefile,v 1.8 1998/07/26 04:30:40 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/backend/storage/lmgr/Makefile,v 1.9 1998/12/15 12:46:29 vadim Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -16,7 +16,7 @@ ifdef MULTIBYTE
 CFLAGS+= $(MBFLAGS)
 endif
 
-OBJS = lmgr.o lock.o multi.o proc.o single.o
+OBJS = lmgr.o lock.o proc.o
 
 all: SUBSYS.o
 
index 13adb8c48f861fb4ac32079adb40f8be7a80758f..307c54e39e16173b423b25d88caaf32e74b61bc5 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.19 1998/09/01 04:31:58 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.20 1998/12/15 12:46:30 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 extern Oid     MyDatabaseId;
 
+static MASK LockConflicts[] = {
+       (int) NULL,
+
+/* AccessShareLock */
+       (1 << AccessExclusiveLock),
+
+/* RowShareLock */
+       (1 << ExclusiveLock) | (1 << AccessExclusiveLock),
+
+/* RowExclusiveLock */
+       (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) |
+       (1 << AccessExclusiveLock),
+
+/* ShareLock */
+       (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) |
+       (1 << RowExclusiveLock) | (1 << AccessExclusiveLock),
+
+/* ShareRowExclusiveLock */
+       (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) |
+       (1 << ShareLock) | (1 << RowExclusiveLock) | (1 << AccessExclusiveLock),
+
+/* ExclusiveLock */
+       (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) |
+       (1 << RowExclusiveLock) | (1 << RowShareLock) | (1 << AccessExclusiveLock),
+
+/* AccessExclusiveLock */
+       (1 << ExclusiveLock) | (1 << ShareRowExclusiveLock) | (1 << ShareLock) |
+       (1 << RowExclusiveLock) | (1 << RowShareLock) | (1 << AccessExclusiveLock) | 
+       (1 << AccessShareLock),
+
+/* ExtendLock */
+       (1 << ExtendLock)
+
+};
+
+static int     LockPrios[] = {
+       (int) NULL,
+       1,
+       2,
+       3,
+       4,
+       5,
+       6,
+       7,
+       1
+};
+
+LOCKMETHOD     LockTableId = (LOCKMETHOD) NULL;
+LOCKMETHOD     LongTermTableId = (LOCKMETHOD) NULL;
+
+/*
+ * Create the lock table described by LockConflicts and LockPrios.
+ */
+LOCKMETHOD
+InitLockTable()
+{
+       int                     lockmethod;
+
+       lockmethod = LockMethodTableInit("LockTable",
+                                                 LockConflicts, LockPrios, MAX_LOCKMODES - 1);
+       LockTableId = lockmethod;
+       if (!(LockTableId))
+               elog(ERROR, "InitLockTable: couldnt initialize lock table");
+
+#ifdef USER_LOCKS
+       /*
+        * Allocate another tableId for long-term locks
+        */
+       LongTermTableId = LockMethodTableRename(LockTableId);
+       if (!(LongTermTableId))
+       {
+               elog(ERROR,
+                        "InitLockTable: couldn't rename long-term lock table");
+       }
+#endif
+
+       return LockTableId;
+}
+
 /*
  * RelationInitLockInfo --
  *             Initializes the lock information in a relation descriptor.
@@ -82,130 +161,49 @@ RelationInitLockInfo(Relation relation)
        else
                info->lockRelId.dbId = MyDatabaseId;
 
-#ifdef LowLevelLocking
-       memset(info->lockHeld, 0, sizeof(info->lockHeld));
-#endif
-
        relation->lockInfo = (Pointer) info;
 }
 
 /*
- * RelationSetLockForDescriptorOpen --
- *             Sets read locks for a relation descriptor.
- */
-#ifdef LOCKDEBUGALL
-#define LOCKDEBUGALL_30 \
-elog(DEBUG, "RelationSetLockForDescriptorOpen(%s[%d,%d]) called", \
-        RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId)
-#else
-#define LOCKDEBUGALL_30
-#endif  /* LOCKDEBUGALL */
-
-void
-RelationSetLockForDescriptorOpen(Relation relation)
-{
-       /* ----------------
-        *      sanity checks
-        * ----------------
-        */
-       Assert(RelationIsValid(relation));
-       if (LockingDisabled())
-               return;
-
-       LOCKDEBUGALL_30;
-
-       /* ----------------
-        * read lock catalog tuples which compose the relation descriptor
-        * XXX race condition? XXX For now, do nothing.
-        * ----------------
-        */
-}
-
-/* ----------------
- *             RelationSetLockForRead
- * ----------------
- */
-#ifdef LOCKDEBUG
-#define LOCKDEBUG_40 \
-elog(DEBUG, "RelationSetLockForRead(%s[%d,%d]) called", \
-        RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId)
-#else
-#define LOCKDEBUG_40
-#endif  /* LOCKDEBUG */
-
-/*
- * RelationSetLockForRead --
- *             Sets relation level read lock.
+ *             LockRelation
  */
 void
-RelationSetLockForRead(Relation relation)
+LockRelation(Relation relation, LOCKMODE lockmode)
 {
        LockInfo        lockinfo;
+       LOCKTAG         tag;
 
-       /* ----------------
-        *      sanity checks
-        * ----------------
-        */
-       Assert(RelationIsValid(relation));
        if (LockingDisabled())
                return;
 
-       LOCKDEBUG_40;
-
-       /* ----------------
-        * If we don't have lock info on the reln just go ahead and
-        * lock it without trying to short circuit the lock manager.
-        * ----------------
-        */
        if (!LockInfoIsValid(relation->lockInfo))
-       {
                RelationInitLockInfo(relation);
-               lockinfo = (LockInfo) relation->lockInfo;
-               MultiLockReln(lockinfo, READ_LOCK);
-               return;
-       }
-       else
-               lockinfo = (LockInfo) relation->lockInfo;
 
-       MultiLockReln(lockinfo, READ_LOCK);
-}
+       lockinfo = (LockInfo) relation->lockInfo;
 
-/* ----------------
- *             RelationUnsetLockForRead
- * ----------------
- */
-#ifdef LOCKDEBUG
-#define LOCKDEBUG_50 \
-elog(DEBUG, "RelationUnsetLockForRead(%s[%d,%d]) called", \
-        RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId)
-#else
-#define LOCKDEBUG_50
-#endif  /* LOCKDEBUG */
+       MemSet(&tag, 0, sizeof(tag));
+       tag.relId = lockinfo->lockRelId.relId;
+       tag.dbId = lockinfo->lockRelId.dbId;
+       tag.objId.blkno = InvalidBlockNumber;
+
+       LockAcquire(LockTableId, &tag, lockmode);
+       return;
+}
 
 /*
- * RelationUnsetLockForRead --
- *             Unsets relation level read lock.
+ *             UnlockRelation
  */
 void
-RelationUnsetLockForRead(Relation relation)
+UnlockRelation(Relation relation, LOCKMODE lockmode)
 {
        LockInfo        lockinfo;
+       LOCKTAG         tag;
 
-       /* ----------------
-        *      sanity check
-        * ----------------
-        */
-       Assert(RelationIsValid(relation));
        if (LockingDisabled())
                return;
 
        lockinfo = (LockInfo) relation->lockInfo;
 
-       /* ----------------
-        * If we don't have lock info on the reln just go ahead and
-        * release it.
-        * ----------------
-        */
        if (!LockInfoIsValid(lockinfo))
        {
                elog(ERROR,
@@ -213,84 +211,50 @@ RelationUnsetLockForRead(Relation relation)
                         RelationGetRelationName(relation));
        }
 
-       MultiReleaseReln(lockinfo, READ_LOCK);
-}
+       MemSet(&tag, 0, sizeof(tag));
+       tag.relId = lockinfo->lockRelId.relId;
+       tag.dbId = lockinfo->lockRelId.dbId;
+       tag.objId.blkno = InvalidBlockNumber;
 
-/* ----------------
- *             RelationSetLockForWrite(relation)
- * ----------------
- */
-#ifdef LOCKDEBUG
-#define LOCKDEBUG_60 \
-elog(DEBUG, "RelationSetLockForWrite(%s[%d,%d]) called", \
-        RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId)
-#else
-#define LOCKDEBUG_60
-#endif  /* LOCKDEBUG */
+       LockRelease(LockTableId, &tag, lockmode);
+       return;
+}
 
 /*
- * RelationSetLockForWrite --
- *             Sets relation level write lock.
+ *             LockPage
  */
 void
-RelationSetLockForWrite(Relation relation)
+LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
 {
        LockInfo        lockinfo;
+       LOCKTAG         tag;
 
-       /* ----------------
-        *      sanity checks
-        * ----------------
-        */
-       Assert(RelationIsValid(relation));
        if (LockingDisabled())
                return;
 
-       LOCKDEBUG_60;
-
-       /* ----------------
-        * If we don't have lock info on the reln just go ahead and
-        * lock it without trying to short circuit the lock manager.
-        * ----------------
-        */
        if (!LockInfoIsValid(relation->lockInfo))
-       {
                RelationInitLockInfo(relation);
-               lockinfo = (LockInfo) relation->lockInfo;
-               MultiLockReln(lockinfo, WRITE_LOCK);
-               return;
-       }
-       else
-               lockinfo = (LockInfo) relation->lockInfo;
 
-       MultiLockReln(lockinfo, WRITE_LOCK);
-}
+       lockinfo = (LockInfo) relation->lockInfo;
 
-/* ----------------
- *             RelationUnsetLockForWrite
- * ----------------
- */
-#ifdef LOCKDEBUG
-#define LOCKDEBUG_70 \
-elog(DEBUG, "RelationUnsetLockForWrite(%s[%d,%d]) called", \
-        RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId)
-#else
-#define LOCKDEBUG_70
-#endif  /* LOCKDEBUG */
+       MemSet(&tag, 0, sizeof(tag));
+       tag.relId = lockinfo->lockRelId.relId;
+       tag.dbId = lockinfo->lockRelId.dbId;
+       tag.objId.blkno = blkno;
+
+       LockAcquire(LockTableId, &tag, lockmode);
+       return;
+}
 
 /*
- * RelationUnsetLockForWrite --
- *             Unsets relation level write lock.
+ *             UnlockPage
  */
 void
-RelationUnsetLockForWrite(Relation relation)
+UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
 {
        LockInfo        lockinfo;
+       LOCKTAG         tag;
 
-       /* ----------------
-        *      sanity checks
-        * ----------------
-        */
-       Assert(RelationIsValid(relation));
        if (LockingDisabled())
                return;
 
@@ -303,309 +267,71 @@ RelationUnsetLockForWrite(Relation relation)
                         RelationGetRelationName(relation));
        }
 
-       MultiReleaseReln(lockinfo, WRITE_LOCK);
-}
+       MemSet(&tag, 0, sizeof(tag));
+       tag.relId = lockinfo->lockRelId.relId;
+       tag.dbId = lockinfo->lockRelId.dbId;
+       tag.objId.blkno = blkno;
 
-/* ----------------
- *             RelationSetLockForReadPage
- * ----------------
- */
-#ifdef LOCKDEBUG
-#define LOCKDEBUG_90 \
-elog(DEBUG, "RelationSetLockForReadPage(%s[%d,%d], @%d) called", \
-        RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId, page)
-#else
-#define LOCKDEBUG_90
-#endif  /* LOCKDEBUG */
-
-/* ----------------
- *             RelationSetLockForWritePage
- * ----------------
- */
-#ifdef LOCKDEBUG
-#define LOCKDEBUG_100 \
-elog(DEBUG, "RelationSetLockForWritePage(%s[%d,%d], @%d) called", \
-        RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId, page)
-#else
-#define LOCKDEBUG_100
-#endif  /* LOCKDEBUG */
-
-/*
- * RelationSetLockForWritePage --
- *             Sets write lock on a page.
- */
-void
-RelationSetLockForWritePage(Relation relation,
-                                                       ItemPointer itemPointer)
-{
-       /* ----------------
-        *      sanity checks
-        * ----------------
-        */
-       Assert(RelationIsValid(relation));
-       if (LockingDisabled())
-               return;
-
-       /* ---------------
-        * Make sure lockinfo is initialized
-        * ---------------
-        */
-       if (!LockInfoIsValid(relation->lockInfo))
-               RelationInitLockInfo(relation);
-
-       /* ----------------
-        *      attempt to set lock
-        * ----------------
-        */
-       MultiLockPage((LockInfo) relation->lockInfo, itemPointer, WRITE_LOCK);
+       LockRelease(LockTableId, &tag, lockmode);
+       return;
 }
 
-/* ----------------
- *             RelationUnsetLockForReadPage
- * ----------------
- */
-#ifdef LOCKDEBUG
-#define LOCKDEBUG_110 \
-elog(DEBUG, "RelationUnsetLockForReadPage(%s[%d,%d], @%d) called", \
-        RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId, page)
-#else
-#define LOCKDEBUG_110
-#endif  /* LOCKDEBUG */
-
-/* ----------------
- *             RelationUnsetLockForWritePage
- * ----------------
- */
-#ifdef LOCKDEBUG
-#define LOCKDEBUG_120 \
-elog(DEBUG, "RelationUnsetLockForWritePage(%s[%d,%d], @%d) called", \
-        RelationGetRelationName(relation), lockRelId.dbId, lockRelId.relId, page)
-#else
-#define LOCKDEBUG_120
-#endif  /* LOCKDEBUG */
-
-/*
- * Set a single level write page lock. Assumes that you already
- * have a write intent lock on the relation.
- */
 void
-RelationSetSingleWLockPage(Relation relation,
-                                                  ItemPointer itemPointer)
+XactLockTableInsert(TransactionId xid)
 {
+       LOCKTAG         tag;
 
-       /* ----------------
-        *      sanity checks
-        * ----------------
-        */
-       Assert(RelationIsValid(relation));
        if (LockingDisabled())
                return;
 
-       if (!LockInfoIsValid(relation->lockInfo))
-               RelationInitLockInfo(relation);
+       MemSet(&tag, 0, sizeof(tag));
+       tag.relId = XactLockTableId;
+       tag.dbId = InvalidOid;
+       tag.objId.xid = xid;
 
-       SingleLockPage((LockInfo) relation->lockInfo, itemPointer, WRITE_LOCK, !UNLOCK);
+       LockAcquire(LockTableId, &tag, ExclusiveLock);
+       return;
 }
 
-/*
- * Unset a single level write page lock
- */
 void
-RelationUnsetSingleWLockPage(Relation relation,
-                                                        ItemPointer itemPointer)
+XactLockTableDelete(TransactionId xid)
 {
+       LOCKTAG         tag;
 
-       /* ----------------
-        *      sanity checks
-        * ----------------
-        */
-       Assert(RelationIsValid(relation));
        if (LockingDisabled())
                return;
 
-       if (!LockInfoIsValid(relation->lockInfo))
-               elog(ERROR,
-                        "Releasing a lock on %s with invalid lock information",
-                        RelationGetRelationName(relation));
-
-       SingleLockPage((LockInfo) relation->lockInfo, itemPointer, WRITE_LOCK, UNLOCK);
-}
-
-/*
- * Set a single level read page lock.  Assumes you already have a read
- * intent lock set on the relation.
- */
-void
-RelationSetSingleRLockPage(Relation relation,
-                                                  ItemPointer itemPointer)
-{
-
-       /* ----------------
-        *      sanity checks
-        * ----------------
-        */
-       Assert(RelationIsValid(relation));
-       if (LockingDisabled())
-               return;
-
-       if (!LockInfoIsValid(relation->lockInfo))
-               RelationInitLockInfo(relation);
-
-       SingleLockPage((LockInfo) relation->lockInfo, itemPointer, READ_LOCK, !UNLOCK);
-}
-
-/*
- * Unset a single level read page lock.
- */
-void
-RelationUnsetSingleRLockPage(Relation relation,
-                                                        ItemPointer itemPointer)
-{
-
-       /* ----------------
-        *      sanity checks
-        * ----------------
-        */
-       Assert(RelationIsValid(relation));
-       if (LockingDisabled())
-               return;
-
-       if (!LockInfoIsValid(relation->lockInfo))
-               elog(ERROR,
-                        "Releasing a lock on %s with invalid lock information",
-                        RelationGetRelationName(relation));
-
-       SingleLockPage((LockInfo) relation->lockInfo, itemPointer, READ_LOCK, UNLOCK);
-}
-
-/*
- * Set a read intent lock on a relation.
- *
- * Usually these are set in a multi-level table when you acquiring a
- * page level lock.  i.e. To acquire a lock on a page you first acquire
- * an intent lock on the entire relation.  Acquiring an intent lock along
- * allows one to use the single level locking routines later.  Good for
- * index scans that do a lot of page level locking.
- */
-void
-RelationSetRIntentLock(Relation relation)
-{
-       /* -----------------
-        * Sanity check
-        * -----------------
-        */
-       Assert(RelationIsValid(relation));
-       if (LockingDisabled())
-               return;
-
-       if (!LockInfoIsValid(relation->lockInfo))
-               RelationInitLockInfo(relation);
-
-       SingleLockReln((LockInfo) relation->lockInfo, READ_LOCK + INTENT, !UNLOCK);
-}
-
-/*
- * Unset a read intent lock on a relation
- */
-void
-RelationUnsetRIntentLock(Relation relation)
-{
-       /* -----------------
-        * Sanity check
-        * -----------------
-        */
-       Assert(RelationIsValid(relation));
-       if (LockingDisabled())
-               return;
-
-       if (!LockInfoIsValid(relation->lockInfo))
-               RelationInitLockInfo(relation);
+       MemSet(&tag, 0, sizeof(tag));
+       tag.relId = XactLockTableId;
+       tag.dbId = InvalidOid;
+       tag.objId.xid = xid;
 
-       SingleLockReln((LockInfo) relation->lockInfo, READ_LOCK + INTENT, UNLOCK);
+       LockRelease(LockTableId, &tag, ExclusiveLock);
+       return;
 }
 
-/*
- * Set a write intent lock on a relation. For a more complete explanation
- * see RelationSetRIntentLock()
- */
 void
-RelationSetWIntentLock(Relation relation)
+XactLockTableWait(TransactionId xid)
 {
-       /* -----------------
-        * Sanity check
-        * -----------------
-        */
-       Assert(RelationIsValid(relation));
-       if (LockingDisabled())
-               return;
-
-       if (!LockInfoIsValid(relation->lockInfo))
-               RelationInitLockInfo(relation);
+       LOCKTAG         tag;
 
-       SingleLockReln((LockInfo) relation->lockInfo, WRITE_LOCK + INTENT, !UNLOCK);
-}
-
-/*
- * Unset a write intent lock.
- */
-void
-RelationUnsetWIntentLock(Relation relation)
-{
-       /* -----------------
-        * Sanity check
-        * -----------------
-        */
-       Assert(RelationIsValid(relation));
        if (LockingDisabled())
                return;
 
-       if (!LockInfoIsValid(relation->lockInfo))
-               RelationInitLockInfo(relation);
+       MemSet(&tag, 0, sizeof(tag));
+       tag.relId = XactLockTableId;
+       tag.dbId = InvalidOid;
+       tag.objId.xid = xid;
 
-       SingleLockReln((LockInfo) relation->lockInfo, WRITE_LOCK + INTENT, UNLOCK);
-}
+       LockAcquire(LockTableId, &tag, ShareLock);
 
-/*
- * Extend locks are used primarily in tertiary storage devices such as
- * a WORM disk jukebox.  Sometimes need exclusive access to extend a
- * file by a block.
- */
-#ifdef NOT_USED
-void
-RelationSetLockForExtend(Relation relation)
-{
-       /* -----------------
-        * Sanity check
-        * -----------------
+       /*
+        * Transaction was committed/aborted/crashed - 
+        * we have to update pg_log if transaction is still
+        * marked as running.
         */
-       Assert(RelationIsValid(relation));
-       if (LockingDisabled())
-               return;
-
-       if (!LockInfoIsValid(relation->lockInfo))
-               RelationInitLockInfo(relation);
+       if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
+               TransactionIdAbort(xid);
 
-       MultiLockReln((LockInfo) relation->lockInfo, EXTEND_LOCK);
+       return;
 }
-
-#endif
-
-#ifdef NOT_USED
-void
-RelationUnsetLockForExtend(Relation relation)
-{
-       /* -----------------
-        * Sanity check
-        * -----------------
-        */
-       Assert(RelationIsValid(relation));
-       if (LockingDisabled())
-               return;
-
-       if (!LockInfoIsValid(relation->lockInfo))
-               RelationInitLockInfo(relation);
-
-       MultiReleaseReln((LockInfo) relation->lockInfo, EXTEND_LOCK);
-}
-
-#endif
index adc4d1a42eaae7497c3716722a293268c30a382b..7fdd8fec84362b523d997f15efababea3e9e550a 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.38 1998/10/08 18:29:57 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.39 1998/12/15 12:46:30 vadim Exp $
  *
  * NOTES
  *       Outside modules can create a lock table and acquire/release
@@ -84,7 +84,7 @@ static int WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode,
 
 #define LOCK_PRINT_AUX(where,lock,type) \
        TPRINTF(TRACE_ALL, \
-                "%s: lock(%x) tbl(%d) rel(%d) db(%d) tid(%d,%d) mask(%x) " \
+                "%s: lock(%x) tbl(%d) rel(%d) db(%d) obj(%u) mask(%x) " \
                 "hold(%d,%d,%d,%d,%d)=%d " \
                 "act(%d,%d,%d,%d,%d)=%d wait(%d) type(%s)", \
                 where, \
@@ -92,9 +92,7 @@ static int WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode,
                 lock->tag.lockmethod, \
                 lock->tag.relId, \
                 lock->tag.dbId, \
-                ((lock->tag.tupleId.ip_blkid.bi_hi<<16)+ \
-                 lock->tag.tupleId.ip_blkid.bi_lo), \
-                lock->tag.tupleId.ip_posid, \
+                lock->tag.objId.blkno, \
                 lock->mask, \
                 lock->holders[1], \
                 lock->holders[2], \
@@ -498,10 +496,8 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
        if (is_user_lock)
        {
 #ifdef USER_LOCKS_DEBUG
-               TPRINTF(TRACE_USERLOCKS, "LockAcquire: user lock [%u,%u] %s",
-                               locktag->tupleId.ip_posid,
-                               ((locktag->tupleId.ip_blkid.bi_hi << 16) +
-                                locktag->tupleId.ip_blkid.bi_lo),
+               TPRINTF(TRACE_USERLOCKS, "LockAcquire: user lock [%u] %s",
+                               locktag->objId.blkno,
                                lock_types[lockmode]);
 #endif
        }
@@ -550,8 +546,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
                MemSet((char *) lock->holders, 0, sizeof(int) * MAX_LOCKMODES);
                MemSet((char *) lock->activeHolders, 0, sizeof(int) * MAX_LOCKMODES);
                ProcQueueInit(&(lock->waitProcs));
-               Assert(BlockIdEquals(&(lock->tag.tupleId.ip_blkid),
-                                                        &(locktag->tupleId.ip_blkid)));
+               Assert(lock->tag.objId.blkno == locktag->objId.blkno);
                LOCK_PRINT("LockAcquire: new", lock, lockmode);
        }
        else
@@ -993,10 +988,8 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
        is_user_lock = (lockmethod == USER_LOCKMETHOD);
        if (is_user_lock)
        {
-               TPRINTF(TRACE_USERLOCKS, "LockRelease: user lock tag [%u,%u] %d",
-                               locktag->tupleId.ip_posid,
-                               ((locktag->tupleId.ip_blkid.bi_hi << 16) +
-                                locktag->tupleId.ip_blkid.bi_lo),
+               TPRINTF(TRACE_USERLOCKS, "LockRelease: user lock tag [%u] %d",
+                               locktag->objId.blkno,
                                lockmode);
        }
 #endif
@@ -1336,19 +1329,15 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
                        {
                                /* Should never happen */
                                elog(NOTICE,
-                                        "LockReleaseAll: INVALID PID: [%u,%u] [%d,%d,%d]",
-                                        lock->tag.tupleId.ip_posid,
-                                        ((lock->tag.tupleId.ip_blkid.bi_hi << 16) +
-                                         lock->tag.tupleId.ip_blkid.bi_lo),
+                                        "LockReleaseAll: INVALID PID: [%u] [%d,%d,%d]",
+                                        lock->tag.objId.blkno,
                                  xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
                                nleft++;
                                goto next_item;
                        }
                        TPRINTF(TRACE_USERLOCKS,
-                               "LockReleaseAll: releasing user lock [%u,%u] [%d,%d,%d]",
-                                       lock->tag.tupleId.ip_posid,
-                                       ((lock->tag.tupleId.ip_blkid.bi_hi << 16) +
-                                        lock->tag.tupleId.ip_blkid.bi_lo),
+                               "LockReleaseAll: releasing user lock [%u] [%d,%d,%d]",
+                                       lock->tag.objId.blkno,
                                  xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
                }
                else
@@ -1361,10 +1350,8 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
                        if (xidLook->tag.pid != 0)
                        {
                                TPRINTF(TRACE_LOCKS,
-                                 "LockReleaseAll: skiping user lock [%u,%u] [%d,%d,%d]",
-                                               lock->tag.tupleId.ip_posid,
-                                               ((lock->tag.tupleId.ip_blkid.bi_hi << 16) +
-                                                lock->tag.tupleId.ip_blkid.bi_lo),
+                                 "LockReleaseAll: skiping user lock [%u] [%d,%d,%d]",
+                                               lock->tag.objId.blkno,
                                  xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
                                nleft++;
                                goto next_item;
@@ -1649,7 +1636,7 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
                                         */
 
                                        Assert(skip_check);
-                                       Assert(MyProc->prio == 2);
+                                       Assert(MyProc->prio >= 2);
 
                                        lockMethodTable = LockMethodTable[1];
                                        xidTable = lockMethodTable->xidHash;
@@ -1747,10 +1734,8 @@ LockOwners(LOCKMETHOD lockmethod, LOCKTAG *locktag)
        is_user_lock = (lockmethod == USER_LOCKMETHOD);
        if (is_user_lock)
        {
-               TPRINTF(TRACE_USERLOCKS, "LockOwners: user lock tag [%u,%u]",
-                               locktag->tupleId.ip_posid,
-                               ((locktag->tupleId.ip_blkid.bi_hi << 16) +
-                                locktag->tupleId.ip_blkid.bi_lo));
+               TPRINTF(TRACE_USERLOCKS, "LockOwners: user lock tag [%u]",
+                               locktag->objId.blkno;,
        }
 #endif
 
index a9c669bc3aa51d5731e765c8968116e8b8edee6e..6553e73214c5f8eb9e4b3911e1f43444a9ddac01 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.19 1998/11/27 19:52:23 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.20 1998/12/15 12:46:34 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -109,7 +109,7 @@ SetDefine(char *querystr, char *typename)
 
                /* change the pg_proc tuple */
                procrel = heap_openr(ProcedureRelationName);
-               RelationSetLockForWrite(procrel);
+               LockRelation(procrel, AccessExclusiveLock);
 
                tup = SearchSysCacheTuple(PROOID,
                                                                  ObjectIdGetDatum(setoid),
@@ -123,7 +123,7 @@ SetDefine(char *querystr, char *typename)
                                                                          repl);
 
                        setheapoverride(true);
-                       heap_replace(procrel, &tup->t_self, newtup);
+                       heap_replace(procrel, &tup->t_self, newtup, NULL);
                        setheapoverride(false);
 
                        setoid = newtup->t_data->t_oid;
@@ -139,7 +139,7 @@ SetDefine(char *querystr, char *typename)
                        CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup);
                        CatalogCloseIndices(Num_pg_proc_indices, idescs);
                }
-               RelationUnsetLockForWrite(procrel);
+               UnlockRelation(procrel, AccessExclusiveLock);
                heap_close(procrel);
        }
        return setoid;
index 492eba6f6596a53b5f2092a819a58aef4a1a965c..99ee3d2fc54f7fa38af5eff937b0897d26855544 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.51 1998/11/27 19:52:28 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.52 1998/12/15 12:46:37 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -363,8 +363,6 @@ scan_pg_rel_seq(RelationBuildDescInfo buildinfo)
         * ----------------
         */
        pg_class_desc = heap_openr(RelationRelationName);
-       if (!IsInitProcessingMode())
-               RelationSetLockForRead(pg_class_desc);
        pg_class_scan = heap_beginscan(pg_class_desc, 0, SnapshotNow, 1, &key);
        pg_class_tuple = heap_getnext(pg_class_scan, 0);
 
@@ -388,8 +386,6 @@ scan_pg_rel_seq(RelationBuildDescInfo buildinfo)
 
        /* all done */
        heap_endscan(pg_class_scan);
-       if (!IsInitProcessingMode())
-               RelationUnsetLockForRead(pg_class_desc);
        heap_close(pg_class_desc);
 
        return return_tuple;
@@ -403,7 +399,7 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
 
        pg_class_desc = heap_openr(RelationRelationName);
        if (!IsInitProcessingMode())
-               RelationSetLockForRead(pg_class_desc);
+               LockRelation(pg_class_desc, AccessShareLock);
 
        switch (buildinfo.infotype)
        {
@@ -428,7 +424,7 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
 
        /* all done */
        if (!IsInitProcessingMode())
-               RelationUnsetLockForRead(pg_class_desc);
+               UnlockRelation(pg_class_desc, AccessShareLock);
        heap_close(pg_class_desc);
 
        return return_tuple;
@@ -1126,7 +1122,6 @@ RelationIdCacheGetRelation(Oid relationId)
                }
 
                RelationIncrementReferenceCount(rd);
-               RelationSetLockForDescriptorOpen(rd);
 
        }
 
@@ -1159,7 +1154,6 @@ RelationNameCacheGetRelation(char *relationName)
                }
 
                RelationIncrementReferenceCount(rd);
-               RelationSetLockForDescriptorOpen(rd);
 
        }
 
index c88646151a7bd925f582191b6c0ce4dbb546bb3e..f53fdd72720123c42e497e2981dcad8883dfc988 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.20 1998/11/27 19:52:36 vadim Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.21 1998/12/15 12:46:40 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,6 +26,9 @@
 
 extern bool PostgresIsInitialized;
 
+SnapshotData   SnapshotDirtyData;
+Snapshot               SnapshotDirty = &SnapshotDirtyData;
+
 /*
  * XXX Transaction system override hacks start here
  */
@@ -88,8 +91,9 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
                {
                        if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
                                return true;
-                       else
-                               return false;
+                       if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                               return true;
+                       return false;
                }
 
                if (!TransactionIdDidCommit(tuple->t_xmin))
@@ -107,10 +111,18 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
                return true;
 
        if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
-               return false;
+       {
+               if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                       return true;
+               return false;                                                   /* updated by other */
+       }
 
        if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
+       {
+               if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                       return true;
                return false;
+       }
 
        if (!TransactionIdDidCommit(tuple->t_xmax))
        {
@@ -122,6 +134,9 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
        /* by here, deleting transaction has committed */
        tuple->t_infomask |= HEAP_XMAX_COMMITTED;
 
+       if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+               return true;
+
        return false;
 }
 
@@ -152,13 +167,6 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
  *                     (Xmax is not committed &&                       the row was deleted by another transaction
  *                      Xmax != my-transaction))))                     that has not been committed
  *
- * XXX
- *             CommandId stuff didn't work properly if one used SQL-functions in
- *             UPDATE/INSERT(fromSELECT)/DELETE scans: SQL-funcs call
- *             CommandCounterIncrement and made tuples changed/inserted by
- *             current command visible to command itself (so we had multiple
- *             update of updated tuples, etc).                 - vadim 08/29/97
- *
  *             mao says 17 march 1993:  the tests in this routine are correct;
  *             if you think they're not, you're wrong, and you should think
  *             about it again.  i know, it happened to me.  we don't need to
@@ -203,6 +211,9 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
 
                        Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
 
+                       if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                               return true;
+
                        if (CommandIdGEScanCommandId(tuple->t_cmax))
                                return true;    /* deleted after scan started */
                        else
@@ -229,10 +240,16 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
                return true;
 
        if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
+       {
+               if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                       return true;
                return false;
+       }
 
        if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
        {
+               if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                       return true;
                if (CommandIdGEScanCommandId(tuple->t_cmax))
                        return true;            /* deleted after scan started */
                else
@@ -249,5 +266,173 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
        /* xmax transaction committed */
        tuple->t_infomask |= HEAP_XMAX_COMMITTED;
 
+       if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+               return true;
+
        return false;
 }
+
+int
+HeapTupleSatisfiesUpdate(HeapTuple tuple)
+{
+       HeapTupleHeader th = tuple->t_data;
+
+       if (AMI_OVERRIDE)
+               return HeapTupleMayBeUpdated;
+
+       if (!(th->t_infomask & HEAP_XMIN_COMMITTED))
+       {
+               if (th->t_infomask & HEAP_XMIN_INVALID) /* xid invalid or aborted */
+                       return HeapTupleInvisible;
+
+               if (TransactionIdIsCurrentTransactionId(th->t_xmin))
+               {
+                       if (CommandIdGEScanCommandId(th->t_cmin) && !heapisoverride())
+                               return HeapTupleInvisible;      /* inserted after scan started */
+
+                       if (th->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
+                               return HeapTupleMayBeUpdated;
+
+                       Assert(TransactionIdIsCurrentTransactionId(th->t_xmax));
+
+                       if (th->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                               return HeapTupleMayBeUpdated;
+
+                       if (CommandIdGEScanCommandId(th->t_cmax))
+                               return HeapTupleSelfUpdated;/* updated after scan started */
+                       else
+                               return HeapTupleInvisible;      /* updated before scan started */
+               }
+
+               /*
+                * This call is VERY expensive - requires a log table lookup.
+                * Actually, this should be done by query before...
+                */
+
+               if (!TransactionIdDidCommit(th->t_xmin))
+               {
+                       if (TransactionIdDidAbort(th->t_xmin))
+                               th->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
+                       return HeapTupleInvisible;
+               }
+
+               th->t_infomask |= HEAP_XMIN_COMMITTED;
+       }
+
+       /* by here, the inserting transaction has committed */
+
+       if (th->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
+               return HeapTupleMayBeUpdated;
+
+       if (th->t_infomask & HEAP_XMAX_COMMITTED)
+       {
+               if (th->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                       return HeapTupleMayBeUpdated;
+               return HeapTupleUpdated;                        /* updated by other */
+       }
+
+       if (TransactionIdIsCurrentTransactionId(th->t_xmax))
+       {
+               if (th->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                       return HeapTupleMayBeUpdated;
+               if (CommandIdGEScanCommandId(th->t_cmax))
+                       return HeapTupleSelfUpdated;/* updated after scan started */
+               else
+                       return HeapTupleInvisible;      /* updated before scan started */
+       }
+
+       if (!TransactionIdDidCommit(th->t_xmax))
+       {
+               if (TransactionIdDidAbort(th->t_xmax))
+               {
+                       th->t_infomask |= HEAP_XMAX_INVALID;            /* aborted */
+                       return HeapTupleMayBeUpdated;
+               }
+               /* running xact */
+               return HeapTupleBeingUpdated;   /* in updation by other */
+       }
+
+       /* xmax transaction committed */
+       th->t_infomask |= HEAP_XMAX_COMMITTED;
+
+       if (th->t_infomask & HEAP_MARKED_FOR_UPDATE)
+               return HeapTupleMayBeUpdated;
+
+       return HeapTupleUpdated;                        /* updated by other */
+}
+
+bool
+HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
+{
+       SnapshotDirty->xmin = SnapshotDirty->xmax = InvalidTransactionId;
+
+       if (AMI_OVERRIDE)
+               return true;
+
+       if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
+       {
+               if (tuple->t_infomask & HEAP_XMIN_INVALID)      /* xid invalid or aborted */
+                       return false;
+
+               if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
+               {
+                       if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
+                               return true;
+
+                       Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
+
+                       if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                               return true;
+
+                       return false;
+               }
+
+               if (!TransactionIdDidCommit(tuple->t_xmin))
+               {
+                       if (TransactionIdDidAbort(tuple->t_xmin))
+                       {
+                               tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
+                               return false;
+                       }
+                       SnapshotDirty->xmin = tuple->t_xmin;
+                       return true;                                            /* in insertion by other */
+               }
+
+               tuple->t_infomask |= HEAP_XMIN_COMMITTED;
+       }
+
+       /* by here, the inserting transaction has committed */
+
+       if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid or aborted */
+               return true;
+
+       if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
+       {
+               if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                       return true;
+               return false;                                                   /* updated by other */
+       }
+
+       if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
+               return false;
+
+       if (!TransactionIdDidCommit(tuple->t_xmax))
+       {
+               if (TransactionIdDidAbort(tuple->t_xmax))
+               {
+                       tuple->t_infomask |= HEAP_XMAX_INVALID;         /* aborted */
+                       return true;
+               }
+               /* running xact */
+               SnapshotDirty->xmax = tuple->t_xmax;
+               return true;                                                    /* in updation by other */
+       }
+
+       /* xmax transaction committed */
+       tuple->t_infomask |= HEAP_XMAX_COMMITTED;
+
+       if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+               return true;
+
+       return false;                                                           /* updated by other */
+}
index 0c756e0beba6ad0dfd14ae0d2983161e52be6bab..e883c7f0a50a8c3f0ab33e3fab1c4de84ebf7c25 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heapam.h,v 1.39 1998/11/27 19:33:31 vadim Exp $
+ * $Id: heapam.h,v 1.40 1998/12/15 12:46:44 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,6 +42,7 @@ typedef struct HeapAccessStatisticsData
        int                     global_insert;
        int                     global_delete;
        int                     global_replace;
+       int                     global_mark4update;
        int                     global_markpos;
        int                     global_restrpos;
        int                     global_BufferGetRelation;
@@ -64,6 +65,7 @@ typedef struct HeapAccessStatisticsData
        int                     local_insert;
        int                     local_delete;
        int                     local_replace;
+       int                     local_mark4update;
        int                     local_markpos;
        int                     local_restrpos;
        int                     local_BufferGetRelation;
@@ -253,9 +255,10 @@ extern void heap_endscan(HeapScanDesc scan);
 extern HeapTuple heap_getnext(HeapScanDesc scandesc, int backw);
 extern void heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tup, Buffer *userbuf);
 extern Oid     heap_insert(Relation relation, HeapTuple tup);
-extern int     heap_delete(Relation relation, ItemPointer tid);
-extern int heap_replace(Relation relation, ItemPointer otid,
-                        HeapTuple tup);
+extern int     heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid);
+extern int     heap_replace(Relation relation, ItemPointer otid, HeapTuple tup,
+                                                       ItemPointer ctid);
+extern int     heap_mark4update(Relation relation, HeapTuple tup, Buffer *userbuf);
 extern void heap_markpos(HeapScanDesc scan);
 extern void heap_restrpos(HeapScanDesc scan);
 
@@ -281,9 +284,4 @@ HeapTuple   heap_addheader(uint32 natts, int structlen, char *structure);
 extern void PrintHeapAccessStatistics(HeapAccessStatistics stats);
 extern void initam(void);
 
-/* hio.c */
-extern void RelationPutHeapTuple(Relation relation, BlockNumber blockIndex,
-                                        HeapTuple tuple);
-extern void RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple);
-
 #endif  /* HEAPAM_H */
index caa5380083df9f0a17f2b13c4ec755335de39475..eb8a955b4d063eec3354c218c9b7001c996997b2 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: hio.h,v 1.8 1998/09/01 04:34:13 momjian Exp $
+ * $Id: hio.h,v 1.9 1998/12/15 12:46:45 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,8 +17,8 @@
 #include <utils/rel.h>
 
 
-extern void RelationPutHeapTuple(Relation relation, BlockNumber blockIndex,
-                                        HeapTuple tuple);
+extern void RelationPutHeapTuple(Relation relation, Buffer buffer, 
+                                                                       HeapTuple tuple);
 extern void RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple);
 
 #endif  /* HIO_H */
index 56197048ba0cd5c4d25637573c49336cf86714e7..06c62a9a4d9318cde2ad74c333bd8f17d046b384 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: htup.h,v 1.11 1998/11/27 19:33:31 vadim Exp $
+ * $Id: htup.h,v 1.12 1998/12/15 12:46:46 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -116,6 +116,7 @@ typedef HeapTupleData *HeapTuple;
 #define HEAP_XMIN_INVALID              0x0200  /* t_xmin invalid/aborted */
 #define HEAP_XMAX_COMMITTED            0x0400  /* t_xmax committed */
 #define HEAP_XMAX_INVALID              0x0800  /* t_xmax invalid/aborted */
+#define HEAP_MARKED_FOR_UPDATE 0x1000  /* marked for UPDATE */
 
 #define HEAP_XACT_MASK                 0x0F00  /* */
 
index e4c1e0a88cec342e8a7c3fe7ef89c9a5cafb61cf..6b0aae443f01ee22d50b190979351cdbfa2f7a90 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: xact.h,v 1.17 1998/10/08 18:30:23 momjian Exp $
+ * $Id: xact.h,v 1.18 1998/12/15 12:46:47 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,6 +38,8 @@ typedef struct TransactionStateData
 #define XACT_REPEATABLE_READ   2               /* not implemented */
 #define XACT_SERIALIZED                        3
 
+extern int     XactIsoLevel;
+
 /* ----------------
  *             transaction states
  * ----------------
index 3106ffa7cc154cbc3650fdea841545999bc981b0..bc3b9da1def22d78c0e0fc7478482752b23a3f64 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_am.h,v 1.9 1998/09/01 04:34:47 momjian Exp $
+ * $Id: pg_am.h,v 1.10 1998/12/15 12:46:49 vadim Exp $
  *
  * NOTES
  *             the genbki.sh script reads this file and generates .bki
@@ -106,6 +106,7 @@ DESCR("");
 #define BTREE_AM_OID 403
 DATA(insert OID = 405 (  hash PGUID "o"  1 1 hashgettuple hashinsert hashdelete - - - - hashbeginscan hashrescan hashendscan hashmarkpos hashrestrpos - - hashbuild - - ));
 DESCR("");
+#define HASH_AM_OID 405
 DATA(insert OID = 783 (  gist PGUID "o" 100 7 gistgettuple gistinsert gistdelete - - - - gistbeginscan gistrescan gistendscan gistmarkpos gistrestrpos - - gistbuild - - ));
 DESCR("");
 
index c96e05e393987a2d0675f0f7823433b39fda185b..c657375241aab5d278d6c78e897c366dad53d151 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_class.h,v 1.25 1998/09/10 15:32:31 vadim Exp $
+ * $Id: pg_class.h,v 1.26 1998/12/15 12:46:50 vadim Exp $
  *
  * NOTES
  *       ``pg_relation'' is being replaced by ``pg_class''.  currently
@@ -144,6 +144,8 @@ DATA(insert OID = 1264 (  pg_variable 90      PGUID 0 0 0 f t s 2  0 0 0 0 0 f f _n
 DESCR("");
 DATA(insert OID = 1269 (  pg_log  99             PGUID 0 0 0 f t s 1  0 0 0 0 0 f f _null_ ));
 DESCR("");
+DATA(insert OID = 376  (  pg_xactlock  0         PGUID 0 0 0 f t s 1  0 0 0 0 0 f f _null_ ));
+DESCR("");
 DATA(insert OID = 1215 (  pg_attrdef 109         PGUID 0 0 0 t t r 4  0 0 0 0 0 f f _null_ ));
 DESCR("");
 DATA(insert OID = 1216 (  pg_relcheck 110        PGUID 0 0 0 t t r 4  0 0 0 0 0 f f _null_ ));
@@ -164,6 +166,9 @@ DESCR("");
 #define RelOid_pg_relcheck             1216
 #define RelOid_pg_trigger              1219
 
+/* Xact lock pseudo-table */
+#define XactLockTableId                        376
+
 #define                  RELKIND_INDEX                   'i'           /* secondary index */
 #define                  RELKIND_LOBJECT                 'l'           /* large objects */
 #define                  RELKIND_RELATION                'r'           /* cataloged heap */
index 3cc0fdcc066699f89e0f2860757fdaaf69a01a90..b52c81dc7260f9f4bb11120152dd15a9070dc9cd 100644 (file)
@@ -12,6 +12,7 @@
 #include "access/tupdesc.h"
 #include "access/htup.h"
 #include "nodes/parsenodes.h"
+#include "nodes/execnodes.h"
 #include "utils/rel.h"
 
 typedef uint32 TriggerEvent;
@@ -65,9 +66,9 @@ extern void RelationRemoveTriggers(Relation rel);
 
 extern HeapTuple ExecBRInsertTriggers(Relation rel, HeapTuple tuple);
 extern void ExecARInsertTriggers(Relation rel, HeapTuple tuple);
-extern bool ExecBRDeleteTriggers(Relation rel, ItemPointer tupleid);
-extern void ExecARDeleteTriggers(Relation rel, ItemPointer tupleid);
-extern HeapTuple ExecBRUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple tuple);
-extern void ExecARUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple tuple);
+extern bool ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid);
+extern void ExecARDeleteTriggers(EState *estate, ItemPointer tupleid);
+extern HeapTuple ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple tuple);
+extern void ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple tuple);
 
 #endif  /* TRIGGER_H */
index 61f567b6d3b18f2e21c7b7fb1df51836e59ffce1..383204c3f0f7f901969ad505256cd359a2c11ce2 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: buf_internals.h,v 1.26 1998/09/01 04:38:10 momjian Exp $
+ * $Id: buf_internals.h,v 1.27 1998/12/15 12:46:55 vadim Exp $
  *
  * NOTE
  *             If BUFFERPAGE0 is defined, then 0 will be used as a
@@ -83,32 +83,6 @@ struct buftag
  *             Dbname, relname, dbid, and relid are enough to determine where
  *             to put the buffer, for all storage managers.
  */
-
-#define PADDED_SBUFDESC_SIZE   128
-
-/* DO NOT CHANGE THIS NEXT STRUCTURE:
-   It is used only to get padding information for the real sbufdesc structure
-   It should match the sbufdesc structure exactly except for a missing sb_pad
-*/
-struct sbufdesc_unpadded
-{
-       Buffer          freeNext;
-       Buffer          freePrev;
-       SHMEM_OFFSET data;
-       BufferTag       tag;
-       int                     buf_id;
-       BufFlags        flags;
-       unsigned        refcount;
-#ifdef HAS_TEST_AND_SET
-       slock_t         io_in_progress_lock;
-#endif  /* HAS_TEST_AND_SET */
-       char            sb_dbname[NAMEDATALEN];
-
-       /* NOTE NO PADDING OF THE MEMBER HERE */
-       char            sb_relname[NAMEDATALEN];
-};
-
-/* THE REAL STRUCTURE - the structure above must match it, minus sb_pad */
 struct sbufdesc
 {
        Buffer          freeNext;               /* link for freelist chain */
@@ -125,31 +99,25 @@ struct sbufdesc
 #ifdef HAS_TEST_AND_SET
        /* can afford a dedicated lock if test-and-set locks are available */
        slock_t         io_in_progress_lock;
+       slock_t         cntx_lock;              /* to lock access to page context */
 #endif  /* HAS_TEST_AND_SET */
+       unsigned        r_locks;                /* # of shared locks */
+       bool            ri_lock;                /* read-intent lock */
+       bool            w_lock;                 /* context exclusively locked */
 
        char            sb_dbname[NAMEDATALEN]; /* name of db in which buf belongs */
-
-       /*
-        * I padded this structure to a power of 2 (PADDED_SBUFDESC_SIZE)
-        * because BufferDescriptorGetBuffer is called a billion times and it
-        * does an C pointer subtraction (i.e., "x - y" -> array index of x
-        * relative to y, which is calculated using division by struct size).
-        * Integer ".div" hits you for 35 cycles, as opposed to a 1-cycle
-        * "sra" ... this hack cut 10% off of the time to create the Wisconsin
-        * database! It eats up more shared memory, of course, but we're
-        * (allegedly) going to make some of these types bigger soon anyway...
-        * -pma 1/2/93
-        */
-
-       /*
-        * please, don't take the sizeof() this member and use it for
-        * something important
-        */
-
-       char            sb_relname[NAMEDATALEN +                /* name of reln */
-                               PADDED_SBUFDESC_SIZE - sizeof(struct sbufdesc_unpadded)];
+       char            sb_relname[NAMEDATALEN];/* name of reln */
 };
 
+/*
+ * Buffer lock infos in BufferLocks below.
+ * We have to free these locks in elog(ERROR)...
+ */
+#define        BL_IO_IN_PROGRESS       (1 << 0)        /* unimplemented */
+#define        BL_R_LOCK                       (1 << 1)
+#define        BL_RI_LOCK                      (1 << 2)
+#define        BL_W_LOCK                       (1 << 3)
+
 /*
  *     mao tracing buffer allocation
  */
@@ -201,6 +169,7 @@ extern BufferDesc *BufferDescriptors;
 extern BufferBlock BufferBlocks;
 extern long *PrivateRefCount;
 extern long *LastRefCount;
+extern bits8 *BufferLocks;
 extern long *CommitInfoNeedsSave;
 extern SPINLOCK BufMgrLock;
 
index 1948e813ee3254ad52800d16052c45cb105cc9ae..22f66c2295b72fb2dcfd6ae2a8646fb0b63d07e3 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: bufmgr.h,v 1.23 1998/10/08 18:30:43 momjian Exp $
+ * $Id: bufmgr.h,v 1.24 1998/12/15 12:46:56 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -73,6 +73,14 @@ extern int   ShowPinTrace;
 #define BUFFER_FLUSH_WRITE             0               /* immediate write */
 #define BUFFER_LATE_WRITE              1               /* delayed write: mark as DIRTY */
 
+/*
+ * Buffer context lock modes
+ */
+#define        BUFFER_LOCK_UNLOCK              0
+#define        BUFFER_LOCK_SHARE               1
+#define        BUFFER_LOCK_EXCLUSIVE   2
+
+
 /*
  * BufferIsValid --
  *             True iff the refcnt of the local buffer is > 0
@@ -155,4 +163,7 @@ extern void BufferRefCountRestore(int *refcountsave);
 extern int     SetBufferWriteMode(int mode);
 extern void SetBufferCommitInfoNeedsSave(Buffer buffer);
 
+extern void UnlockBuffers(void);
+extern void LockBuffer(Buffer buffer, int mode);
+
 #endif  /* !defined(BufMgrIncluded) */
index 4733b34bbc85143f62977b85d65337e8b13fb942..2163aa79d5914f8aec122a98779634ab00504bc6 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: ipc.h,v 1.30 1998/09/01 04:38:16 momjian Exp $
+ * $Id: ipc.h,v 1.31 1998/12/15 12:46:57 vadim Exp $
  *
  * NOTES
  *       This file is very architecture-specific.      This stuff should actually
@@ -186,6 +186,8 @@ typedef enum _LockId_
                ((key == PrivateIPCKey) ? key : 11 + (key))
 #define IPCKeyGetWaitIOSemaphoreKey(key) \
                ((key == PrivateIPCKey) ? key : 12 + (key))
+#define IPCKeyGetWaitCLSemaphoreKey(key) \
+               ((key == PrivateIPCKey) ? key : 13 + (key))
 
 /* --------------------------
  * NOTE: This macro must always give the highest numbered key as every backend
index 4082811bcc87aec06c20b9403c1233604fb11528..a85ba1e8ff7d625122c0ed95342fa1ed976e9c76 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lmgr.h,v 1.15 1998/09/01 04:38:23 momjian Exp $
+ * $Id: lmgr.h,v 1.16 1998/12/15 12:46:57 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <utils/rel.h>
 #include <catalog/catname.h>
 
-/*
- * This was moved from pladt.h for the new lock manager.  Want to obsolete
- * all of the old code.
- */
+#define AccessShareLock                        1               /* SELECT */
+#define RowShareLock                   2               /* SELECT FOR UPDATE */
+#define RowExclusiveLock               3               /* INSERT, UPDATE, DELETE */
+#define ShareLock                              4
+#define ShareRowExclusiveLock  5
+#define ExclusiveLock                  6
+#define AccessExclusiveLock            7
+
+#define ExtendLock                             8
+
+extern LOCKMETHOD LockTableId;
+
+
 typedef struct LockRelId
 {
        Oid                     relId;                  /* a relation identifier */
        Oid                     dbId;                   /* a database identifier */
 }                      LockRelId;
 
-#ifdef LowLevelLocking
 typedef struct LockInfoData
 {
        LockRelId       lockRelId;
-       bool            lockHeld[MAX_LOCKMODES];                /* on table level */
 } LockInfoData;
 
-#else
-typedef struct LockInfoData
-{
-       LockRelId       lockRelId;
-} LockInfoData;
-
-#endif
-
 typedef LockInfoData *LockInfo;
 
 #define LockInfoIsValid(lockinfo)      PointerIsValid(lockinfo)
 
+extern LOCKMETHOD InitLockTable(void);
 extern void RelationInitLockInfo(Relation relation);
-extern void RelationSetLockForDescriptorOpen(Relation relation);
-extern void RelationSetLockForRead(Relation relation);
-extern void RelationUnsetLockForRead(Relation relation);
-extern void RelationSetLockForWrite(Relation relation);
-extern void RelationUnsetLockForWrite(Relation relation);
 
-/* used in vaccum.c */
-extern void RelationSetLockForWritePage(Relation relation,
-                                                       ItemPointer itemPointer);
+extern void LockRelation(Relation relation, LOCKMODE lockmode);
+extern void UnlockRelation(Relation relation, LOCKMODE lockmode);
 
-/* used in nbtpage.c, hashpage.c */
-extern void RelationSetSingleWLockPage(Relation relation,
-                                                  ItemPointer itemPointer);
-extern void RelationUnsetSingleWLockPage(Relation relation,
-                                                        ItemPointer itemPointer);
-extern void RelationSetSingleRLockPage(Relation relation,
-                                                  ItemPointer itemPointer);
-extern void RelationUnsetSingleRLockPage(Relation relation,
-                                                        ItemPointer itemPointer);
-extern void RelationSetRIntentLock(Relation relation);
-extern void RelationUnsetRIntentLock(Relation relation);
-extern void RelationSetWIntentLock(Relation relation);
-extern void RelationUnsetWIntentLock(Relation relation);
+/* this is for indices */
+extern void LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
+extern void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
 
-/* single.c */
-extern bool SingleLockReln(LockInfo lockinfo, LOCKMODE lockmode, int action);
-extern bool SingleLockPage(LockInfo lockinfo, ItemPointer tidPtr,
-                          LOCKMODE lockmode, int action);
+/* and this is for transactions */
+extern void XactLockTableInsert(TransactionId xid);
+extern void XactLockTableDelete(TransactionId xid);
+extern void XactLockTableWait(TransactionId xid);
 
 /* proc.c */
 extern void InitProcGlobal(IPCKey key);
index 329aa758a7fd560c41f5f8b466f23454a1195423..9c803ef8a1273e77f3d30b1febb0c4227ee46473 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lock.h,v 1.19 1998/10/08 18:30:45 momjian Exp $
+ * $Id: lock.h,v 1.20 1998/12/15 12:46:58 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,11 +42,7 @@ typedef int LOCKMODE;
 typedef int LOCKMETHOD;
 
 /* MAX_LOCKMODES cannot be larger than the bits in MASK */
-#ifdef LowLevelLocking
 #define MAX_LOCKMODES  9
-#else
-#define MAX_LOCKMODES  6
-#endif
 
 /*
  * MAX_LOCK_METHODS corresponds to the number of spin locks allocated in
@@ -69,7 +65,11 @@ typedef struct LTAG
 {
        Oid                     relId;
        Oid                     dbId;
-       ItemPointerData tupleId;
+       union
+       {
+               BlockNumber             blkno;
+               TransactionId   xid;
+       }                       objId;
        uint16          lockmethod;             /* needed by user locks */
 } LOCKTAG;
 
index 4a62fac18ab72b60cb3284d83ca538cb60e3b14a..914d934524f54561ff9c9c6de7a72056a41c38e9 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: proc.h,v 1.15 1998/09/01 04:38:31 momjian Exp $
+ * $Id: proc.h,v 1.16 1998/12/15 12:46:59 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,11 +44,9 @@ typedef struct proc
        TransactionId xid;                      /* transaction currently being executed by
                                                                 * this proc */
 
-#ifdef LowLevelLocking
        TransactionId xmin;                     /* minimal running XID as it was when we
                                                                 * were starting our xact: vacuum must not
                                                                 * remove tuples deleted by xid >= xmin ! */
-#endif
 
        LOCK       *waitLock;           /* Lock we're sleeping on */
        int                     token;                  /* info for proc wakeup routines */
index d47f5ab53b9c4ebe30d0f5c89885ed3e8732faf6..aa20a328bdcc6d267315d5a3f4ad6a65baf23bca 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.56 1998/10/31 02:06:08 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.57 1998/12/15 12:46:59 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -68,6 +68,8 @@
 
 #include "storage/ipc.h"
 
+extern void s_lock_sleep(unsigned spin);
+
 #if defined(HAS_TEST_AND_SET)
 
 
index 3d2f8531f47070b29c52223f0d59dbb244225cdf..cb15a60ca0d561bbdf221e1ccb1423307181c05e 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tqual.h,v 1.15 1998/11/27 19:33:35 vadim Exp $
+ * $Id: tqual.h,v 1.16 1998/12/15 12:47:01 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 typedef struct SnapshotData
 {
-       TransactionId xmin;                     /* XID < xmin are visible to me */
-       TransactionId xmax;                     /* XID > xmax are invisible to me */
-       TransactionId *xip;                     /* array of xacts in progress */
+       TransactionId   xmin;                   /* XID < xmin are visible to me */
+       TransactionId   xmax;                   /* XID > xmax are invisible to me */
+       TransactionId  *xip;                    /* array of xacts in progress */
 }                      SnapshotData;
 
 typedef SnapshotData *Snapshot;
 
-#define IsSnapshotNow(snapshot)                ((Snapshot) snapshot == (Snapshot) 0x0)
-#define IsSnapshotSelf(snapshot)       ((Snapshot) snapshot == (Snapshot) 0x1)
 #define SnapshotNow                                    ((Snapshot) 0x0)
 #define SnapshotSelf                           ((Snapshot) 0x1)
+extern Snapshot                                        SnapshotDirty;
+
+#define IsSnapshotNow(snapshot)                ((Snapshot) snapshot == SnapshotNow)
+#define IsSnapshotSelf(snapshot)       ((Snapshot) snapshot == SnapshotSelf)
+#define IsSnapshotDirty(snapshot)      ((Snapshot) snapshot == SnapshotDirty)
 
 extern TransactionId HeapSpecialTransactionId;
 extern CommandId HeapSpecialCommandId;
@@ -49,7 +52,11 @@ extern CommandId HeapSpecialCommandId;
                (IsSnapshotSelf(snapshot) || heapisoverride()) ? \
                        HeapTupleSatisfiesItself((tuple)->t_data) \
                : \
-                       HeapTupleSatisfiesNow((tuple)->t_data) \
+                       ((IsSnapshotDirty(snapshot)) ? \
+                               HeapTupleSatisfiesDirty((tuple)->t_data) \
+                       : \
+                               HeapTupleSatisfiesNow((tuple)->t_data) \
+                       ) \
        ) \
 )
 
@@ -71,10 +78,18 @@ extern CommandId HeapSpecialCommandId;
        ) \
 )
 
-extern bool HeapTupleSatisfiesItself(HeapTupleHeader tuple);
-extern bool HeapTupleSatisfiesNow(HeapTupleHeader tuple);
+#define        HeapTupleMayBeUpdated           0
+#define        HeapTupleInvisible                      1
+#define HeapTupleSelfUpdated           2
+#define HeapTupleUpdated                       3
+#define HeapTupleBeingUpdated          4
 
-extern void setheapoverride(bool on);
+extern bool            HeapTupleSatisfiesItself(HeapTupleHeader tuple);
+extern bool            HeapTupleSatisfiesNow(HeapTupleHeader tuple);
+extern bool            HeapTupleSatisfiesDirty(HeapTupleHeader tuple);
+extern int             HeapTupleSatisfiesUpdate(HeapTuple tuple);
 
+extern void setheapoverride(bool on);
+extern Snapshot GetSnapshotData(bool serialized);
 
 #endif  /* TQUAL_H */