Initial MVCC code.
authorVadim B. Mikheev
Tue, 15 Dec 1998 12:47:01 +0000 (12:47 +0000)
committerVadim B. Mikheev
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 
 #include 
 
-
 #ifndef HAVE_MEMMOVE
 #include 
 #else
 #include 
 #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 
 
 #include 
+#include 
 #include 
 #include 
 #include 
  *  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 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -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 
 #include 
+#include 
 
 #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 
 
 
-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 
 #include 
 
-/*
- * 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 */