aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/gist/gist.c17
-rw-r--r--src/backend/access/gist/gistscan.c5
-rw-r--r--src/backend/access/hash/hashpage.c20
-rw-r--r--src/backend/access/heap/heapam.c496
-rw-r--r--src/backend/access/heap/hio.c71
-rw-r--r--src/backend/access/heap/stats.c8
-rw-r--r--src/backend/access/index/indexam.c6
-rw-r--r--src/backend/access/nbtree/nbtinsert.c27
-rw-r--r--src/backend/access/nbtree/nbtpage.c20
-rw-r--r--src/backend/access/rtree/rtree.c19
-rw-r--r--src/backend/access/rtree/rtscan.c7
-rw-r--r--src/backend/access/transam/transam.c21
-rw-r--r--src/backend/access/transam/transsup.c33
-rw-r--r--src/backend/access/transam/xact.c7
-rw-r--r--src/backend/catalog/aclchk.c4
-rw-r--r--src/backend/catalog/heap.c32
-rw-r--r--src/backend/catalog/index.c22
-rw-r--r--src/backend/catalog/pg_operator.c10
-rw-r--r--src/backend/catalog/pg_type.c10
-rw-r--r--src/backend/commands/async.c30
-rw-r--r--src/backend/commands/command.c4
-rw-r--r--src/backend/commands/copy.c23
-rw-r--r--src/backend/commands/dbcommands.c4
-rw-r--r--src/backend/commands/defind.c4
-rw-r--r--src/backend/commands/proclang.c2
-rw-r--r--src/backend/commands/remove.c14
-rw-r--r--src/backend/commands/rename.c6
-rw-r--r--src/backend/commands/sequence.c42
-rw-r--r--src/backend/commands/trigger.c155
-rw-r--r--src/backend/commands/user.c20
-rw-r--r--src/backend/commands/vacuum.c12
-rw-r--r--src/backend/executor/execMain.c97
-rw-r--r--src/backend/executor/execUtils.c31
-rw-r--r--src/backend/executor/nodeHash.c10
-rw-r--r--src/backend/parser/gram.c2
-rw-r--r--src/backend/parser/parse_func.c4
-rw-r--r--src/backend/rewrite/rewriteRemove.c6
-rw-r--r--src/backend/rewrite/rewriteSupport.c4
-rw-r--r--src/backend/storage/buffer/buf_init.c25
-rw-r--r--src/backend/storage/buffer/bufmgr.c149
-rw-r--r--src/backend/storage/buffer/s_lock.c21
-rw-r--r--src/backend/storage/ipc/ipci.c7
-rw-r--r--src/backend/storage/ipc/shmem.c23
-rw-r--r--src/backend/storage/large_object/inv_api.c18
-rw-r--r--src/backend/storage/lmgr/Makefile4
-rw-r--r--src/backend/storage/lmgr/lmgr.c580
-rw-r--r--src/backend/storage/lmgr/lock.c49
-rw-r--r--src/backend/utils/adt/sets.c8
-rw-r--r--src/backend/utils/cache/relcache.c12
-rw-r--r--src/backend/utils/time/tqual.c207
-rw-r--r--src/include/access/heapam.h16
-rw-r--r--src/include/access/hio.h6
-rw-r--r--src/include/access/htup.h3
-rw-r--r--src/include/access/xact.h4
-rw-r--r--src/include/catalog/pg_am.h3
-rw-r--r--src/include/catalog/pg_class.h7
-rw-r--r--src/include/commands/trigger.h9
-rw-r--r--src/include/storage/buf_internals.h63
-rw-r--r--src/include/storage/bufmgr.h13
-rw-r--r--src/include/storage/ipc.h4
-rw-r--r--src/include/storage/lmgr.h64
-rw-r--r--src/include/storage/lock.h12
-rw-r--r--src/include/storage/proc.h4
-rw-r--r--src/include/storage/s_lock.h4
-rw-r--r--src/include/utils/tqual.h35
65 files changed, 1382 insertions, 1273 deletions
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index a7617842042..ce9ef24c88e 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -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
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index f74316cb331..3528fd30ce2 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -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);
diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c
index dc3ad3727aa..208cda1bf7e 100644
--- a/src/backend/access/hash/hashpage.c
+++ b/src/backend/access/hash/hashpage.c
@@ -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",
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 76fcfaf2c82..8ffd9d41922 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -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
@@ -89,15 +89,12 @@
#include <utils/inval.h>
#include <utils/memutils.h>
-
#ifndef HAVE_MEMMOVE
#include <regex/utils.h>
#else
#include <string.h>
#endif
-static void doinsert(Relation relation, HeapTuple tup);
-
/* ----------------------------------------------------------------
* heap support routines
* ----------------------------------------------------------------
@@ -214,7 +211,7 @@ static void
heapgettup(Relation relation,
HeapTuple tuple,
int dir,
- Buffer *buf,
+ Buffer *buffer,
Snapshot snapshot,
int nkeys,
ScanKey key)
@@ -255,7 +252,7 @@ heapgettup(Relation relation,
elog(DEBUG, "heapgettup(%s, tid=0x%x, dir=%d, ...)",
RelationGetRelationName(relation), tid, dir);
}
- elog(DEBUG, "heapgettup(..., b=0x%x, nkeys=%d, key=0x%x", buf, nkeys, key);
+ elog(DEBUG, "heapgettup(..., b=0x%x, nkeys=%d, key=0x%x", buffer, nkeys, key);
elog(DEBUG, "heapgettup: relation(%c)=`%s', %p",
relation->rd_rel->relkind, &relation->rd_rel->relname,
@@ -288,25 +285,26 @@ heapgettup(Relation relation,
/* assume it is a valid TID XXX */
if (ItemPointerIsValid(tid) == false)
{
- *buf = InvalidBuffer;
+ *buffer = InvalidBuffer;
tuple->t_data = NULL;
return;
}
- *buf = RelationGetBufferWithBuffer(relation,
+ *buffer = RelationGetBufferWithBuffer(relation,
ItemPointerGetBlockNumber(tid),
- *buf);
+ *buffer);
-#ifndef NO_BUFFERISVALID
- if (!BufferIsValid(*buf))
+ if (!BufferIsValid(*buffer))
elog(ERROR, "heapgettup: failed ReadBuffer");
-#endif
- dp = (Page) BufferGetPage(*buf);
+ LockBuffer(*buffer, BUFFER_LOCK_SHARE);
+
+ dp = (Page) BufferGetPage(*buffer);
lineoff = ItemPointerGetOffsetNumber(tid);
lpp = PageGetItemId(dp, lineoff);
tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
tuple->t_len = ItemIdGetLength(lpp);
+ LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
return;
}
@@ -328,18 +326,18 @@ heapgettup(Relation relation,
}
if (page < 0)
{
- *buf = InvalidBuffer;
+ *buffer = InvalidBuffer;
tuple->t_data = NULL;
return;
}
- *buf = RelationGetBufferWithBuffer(relation, page, *buf);
-#ifndef NO_BUFFERISVALID
- if (!BufferIsValid(*buf))
+ *buffer = RelationGetBufferWithBuffer(relation, page, *buffer);
+ if (!BufferIsValid(*buffer))
elog(ERROR, "heapgettup: failed ReadBuffer");
-#endif
- dp = (Page) BufferGetPage(*buf);
+ LockBuffer(*buffer, BUFFER_LOCK_SHARE);
+
+ dp = (Page) BufferGetPage(*buffer);
lines = PageGetMaxOffsetNumber(dp);
if (tid == NULL)
{
@@ -373,19 +371,19 @@ heapgettup(Relation relation,
if (page >= pages)
{
- *buf = InvalidBuffer;
+ *buffer = InvalidBuffer;
tuple->t_data = NULL;
return;
}
/* page and lineoff now reference the physically next tid */
- *buf = RelationGetBufferWithBuffer(relation, page, *buf);
-#ifndef NO_BUFFERISVALID
- if (!BufferIsValid(*buf))
+ *buffer = RelationGetBufferWithBuffer(relation, page, *buffer);
+ if (!BufferIsValid(*buffer))
elog(ERROR, "heapgettup: failed ReadBuffer");
-#endif
- dp = (Page) BufferGetPage(*buf);
+ LockBuffer(*buffer, BUFFER_LOCK_SHARE);
+
+ dp = (Page) BufferGetPage(*buffer);
lines = PageGetMaxOffsetNumber(dp);
}
@@ -420,10 +418,13 @@ heapgettup(Relation relation,
* if current tuple qualifies, return it.
* ----------------
*/
- HeapTupleSatisfies(tuple, relation, *buf, (PageHeader) dp,
+ HeapTupleSatisfies(tuple, relation, *buffer, (PageHeader) dp,
snapshot, nkeys, key);
if (tuple->t_data != NULL)
+ {
+ LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
return;
+ }
}
/* ----------------
@@ -448,6 +449,7 @@ heapgettup(Relation relation,
* this page and it's time to move to the next..
* ----------------
*/
+ LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
page = nextpage(page, dir);
/* ----------------
@@ -456,20 +458,19 @@ heapgettup(Relation relation,
*/
if (page < 0 || page >= pages)
{
- if (BufferIsValid(*buf))
- ReleaseBuffer(*buf);
- *buf = InvalidBuffer;
+ if (BufferIsValid(*buffer))
+ ReleaseBuffer(*buffer);
+ *buffer = InvalidBuffer;
tuple->t_data = NULL;
return;
}
- *buf = ReleaseAndReadBuffer(*buf, relation, page);
+ *buffer = ReleaseAndReadBuffer(*buffer, relation, page);
-#ifndef NO_BUFFERISVALID
- if (!BufferIsValid(*buf))
+ if (!BufferIsValid(*buffer))
elog(ERROR, "heapgettup: failed ReadBuffer");
-#endif
- dp = (Page) BufferGetPage(*buf);
+ LockBuffer(*buffer, BUFFER_LOCK_SHARE);
+ dp = (Page) BufferGetPage(*buffer);
lines = PageGetMaxOffsetNumber((Page) dp);
linesleft = lines - 1;
if (dir < 0)
@@ -485,13 +486,6 @@ heapgettup(Relation relation,
}
}
-static void
-doinsert(Relation relation, HeapTuple tup)
-{
- RelationPutHeapTupleAtEnd(relation, tup);
- return;
-}
-
/* ----------------------------------------------------------------
* heap access method interface
@@ -599,11 +593,7 @@ heap_beginscan(Relation relation,
if (RelationIsValid(relation) == false)
elog(ERROR, "heap_beginscan: !RelationIsValid(relation)");
- /* ----------------
- * set relation level read lock
- * ----------------
- */
- RelationSetLockForRead(relation);
+ LockRelation(relation, AccessShareLock);
/* XXX someday assert SelfTimeQual if relkind == RELKIND_UNCATALOGED */
if (relation->rd_rel->relkind == RELKIND_UNCATALOGED)
@@ -707,13 +697,7 @@ heap_endscan(HeapScanDesc scan)
*/
RelationDecrementReferenceCount(scan->rs_rd);
- /* ----------------
- * Non 2-phase read locks on catalog relations
- * ----------------
- */
- if (IsSystemRelationName(RelationGetRelationName(scan->rs_rd)->data))
-
- RelationUnsetLockForRead(scan->rs_rd);
+ UnlockRelation(scan->rs_rd, AccessShareLock);
pfree(scan); /* XXX */
}
@@ -997,14 +981,6 @@ heap_fetch(Relation relation,
IncrHeapAccessStat(local_fetch);
IncrHeapAccessStat(global_fetch);
- /*
- * Note: This is collosally expensive - does two system calls per
- * indexscan tuple fetch. Not good, and since we should be doing page
- * level locking by the scanner anyway, it is commented out.
- */
-
- /* RelationSetLockForTupleRead(relation, tid); */
-
/* ----------------
* get the buffer from the relation descriptor
* Note that this does a buffer pin.
@@ -1013,13 +989,11 @@ heap_fetch(Relation relation,
buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
-#ifndef NO_BUFFERISVALID
if (!BufferIsValid(buffer))
- {
elog(ERROR, "heap_fetch: %s relation: ReadBuffer(%lx) failed",
&relation->rd_rel->relname, (long) tid);
- }
-#endif
+
+ LockBuffer(buffer, BUFFER_LOCK_SHARE);
/* ----------------
* get the item line pointer corresponding to the requested tid
@@ -1047,6 +1021,8 @@ heap_fetch(Relation relation,
HeapTupleSatisfies(tuple, relation, buffer, dp,
snapshot, 0, (ScanKey) NULL);
+ LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
+
if (tuple->t_data == NULL)
{
ReleaseBuffer(buffer);
@@ -1091,14 +1067,6 @@ heap_insert(Relation relation, HeapTuple tup)
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
* db creation, the backend program sets oids for tuples. When we
@@ -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;
}
/* ----------------
diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c
index 5c727145f6f..462de54ccfd 100644
--- a/src/backend/access/heap/hio.c
+++ b/src/backend/access/heap/hio.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Id: hio.c,v 1.14 1998/11/27 19:51:36 vadim Exp $
+ * $Id: hio.c,v 1.15 1998/12/15 12:45:14 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -15,6 +15,7 @@
#include <postgres.h>
#include <storage/bufpage.h>
+#include <access/hio.h>
#include <access/heapam.h>
#include <storage/bufmgr.h>
#include <utils/memutils.h>
@@ -29,19 +30,20 @@
* 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);
+
}
diff --git a/src/backend/access/heap/stats.c b/src/backend/access/heap/stats.c
index 2bebfd9b0be..d630dedf815 100644
--- a/src/backend/access/heap/stats.c
+++ b/src/backend/access/heap/stats.c
@@ -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);
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index aa2d9446504..f1516c669b3 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -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);
}
/* ----------------
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index 44349cfe3c7..54ea9ed8abd 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.31 1998/11/27 19:51:40 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.32 1998/12/15 12:45:20 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,6 +18,7 @@
#include <storage/bufpage.h>
#include <access/nbtree.h>
#include <access/heapam.h>
+#include <access/xact.h>
#include <storage/bufmgr.h>
#include <fmgr.h>
@@ -67,6 +68,8 @@ _bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, Relation heapRel
/* trade in our read lock for a write lock */
_bt_relbuf(rel, buf, BT_READ);
+
+l1:
buf = _bt_getbuf(rel, blkno, BT_WRITE);
/*
@@ -120,9 +123,25 @@ _bt_doinsert(Relation rel, BTItem btitem, bool index_is_unique, Relation heapRel
{ /* they're equal */
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offset));
htup.t_self = btitem->bti_itup.t_tid;
- heap_fetch(heapRel, SnapshotSelf, &htup, &buffer);
- if (htup.t_data != NULL)
- { /* it is a duplicate */
+ heap_fetch(heapRel, SnapshotDirty, &htup, &buffer);
+ if (htup.t_data != NULL) /* it is a duplicate */
+ {
+ TransactionId xwait =
+ (TransactionIdIsValid(SnapshotDirty->xmin)) ?
+ SnapshotDirty->xmin : SnapshotDirty->xmax;
+
+ /*
+ * If this tuple is being updated by other transaction
+ * then we have to wait for its commit/abort.
+ */
+ if (TransactionIdIsValid(xwait))
+ {
+ if (nbuf != InvalidBuffer)
+ _bt_relbuf(rel, nbuf, BT_READ);
+ _bt_relbuf(rel, buf, BT_WRITE);
+ XactLockTableWait(xwait);
+ goto l1; /* continue from the begin */
+ }
elog(ERROR, "Cannot insert a duplicate key into a unique index");
}
/* htup null so no buffer to release */
diff --git a/src/backend/access/nbtree/nbtpage.c b/src/backend/access/nbtree/nbtpage.c
index 223efc5c91e..306f4fa0e93 100644
--- a/src/backend/access/nbtree/nbtpage.c
+++ b/src/backend/access/nbtree/nbtpage.c
@@ -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);
}
}
diff --git a/src/backend/access/rtree/rtree.c b/src/backend/access/rtree/rtree.c
index 3a8feda536d..9bf6d90dae1 100644
--- a/src/backend/access/rtree/rtree.c
+++ b/src/backend/access/rtree/rtree.c
@@ -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;
}
diff --git a/src/backend/access/rtree/rtscan.c b/src/backend/access/rtree/rtscan.c
index 6d0bb632e7f..f2c7927d273 100644
--- a/src/backend/access/rtree/rtscan.c
+++ b/src/backend/access/rtree/rtscan.c
@@ -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);
diff --git a/src/backend/access/transam/transam.c b/src/backend/access/transam/transam.c
index 5bcce3c2d70..b68b6ab6691 100644
--- a/src/backend/access/transam/transam.c
+++ b/src/backend/access/transam/transam.c
@@ -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;
diff --git a/src/backend/access/transam/transsup.c b/src/backend/access/transam/transsup.c
index 6f1b09b5774..edf953384f9 100644
--- a/src/backend/access/transam/transsup.c
+++ b/src/backend/access/transam/transsup.c
@@ -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
@@ -290,17 +290,11 @@ TransBlockNumberGetXidStatus(Relation relation,
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;
}
@@ -346,18 +335,11 @@ TransBlockNumberSetXidStatus(Relation relation,
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);
}
/* --------------------------------
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 35bcbfed6a4..002b43cd040 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -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();
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 6c4fb244571..b9057176307 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -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 */
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 3fbdcec4e32..bc897c5965c 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -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);
}
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 0c487bc2496..29565ba285e 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -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);
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 96fb9ae35f6..40a33fd5b55 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -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);
}
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index f46bb8f3a2a..f67317defe0 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -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 */
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 50d4f13cc09..b18941781d4 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -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);
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c
index 6cbf8b980cb..f1fc29f6f6e 100644
--- a/src/backend/commands/command.c
+++ b/src/backend/commands/command.c
@@ -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);
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 419874e5d49..61151ef6aad 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -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++)
{
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index d25d430c39c..a774ca1deb1 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -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);
diff --git a/src/backend/commands/defind.c b/src/backend/commands/defind.c
index c071c2d9fe8..33d069e6517 100644
--- a/src/backend/commands/defind.c
+++ b/src/backend/commands/defind.c
@@ -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);
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index c8b4e836f02..d95c4efdff7 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -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);
diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c
index e662e90ec56..e11983ea8e9 100644
--- a/src/backend/commands/remove.c
+++ b/src/backend/commands/remove.c
@@ -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);
}
diff --git a/src/backend/commands/rename.c b/src/backend/commands/rename.c
index c423da11963..2977d9e79d0 100644
--- a/src/backend/commands/rename.c
+++ b/src/backend/commands/rename.c
@@ -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);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 9edec5a9dc6..e391936cbf8 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -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;
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 431a70a6ff9..60d0056930b 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -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;
}
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index e0c0e51ea13..7c4203528fa 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -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)
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index f7bed005add..608dd729ffa 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -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);
}
/*
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 45be159ae17..712f2285342 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -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
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 1af4fcbc88a..58dbcd19efc 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -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.
*/
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index 5f528850ffa..5ec45c7c795 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -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)
diff --git a/src/backend/parser/gram.c b/src/backend/parser/gram.c
index 6c484aecf18..0eb9d3eb137 100644
--- a/src/backend/parser/gram.c
+++ b/src/backend/parser/gram.c
@@ -235,7 +235,7 @@
*
*
* 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
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index c2066a43b12..bc9c9a738a4 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -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)
diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c
index fd1472a93cf..8be2f413cfc 100644
--- a/src/backend/rewrite/rewriteRemove.c
+++ b/src/backend/rewrite/rewriteRemove.c
@@ -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);
diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c
index 2b57e277116..15a9b18b906 100644
--- a/src/backend/rewrite/rewriteSupport.c
+++ b/src/backend/rewrite/rewriteSupport.c
@@ -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);
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c
index 975e999ec2b..620708aaae3 100644
--- a/src/backend/storage/buffer/buf_init.c
+++ b/src/backend/storage/buffer/buf_init.c
@@ -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));
}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index cab1e8084e0..d5fa26b6035 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -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
+
+}
diff --git a/src/backend/storage/buffer/s_lock.c b/src/backend/storage/buffer/s_lock.c
index a7b42bc4793..439240a386f 100644
--- a/src/backend/storage/buffer/s_lock.c
+++ b/src/backend/storage/buffer/s_lock.c
@@ -7,13 +7,14 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.12 1998/09/18 17:18:39 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/Attic/s_lock.c,v 1.13 1998/12/15 12:46:21 vadim Exp $
*
*-------------------------------------------------------------------------
*/
#include <stdio.h>
#include <sys/time.h>
+#include <unistd.h>
#include "config.h"
#include "c.h"
@@ -52,6 +53,16 @@ s_lock_stuck(volatile slock_t *lock, const char *file, const int line)
}
+void
+s_lock_sleep(unsigned spin)
+{
+ struct timeval delay;
+
+ delay.tv_sec = 0;
+ delay.tv_usec = s_spincycle[spin % S_NSPINCYCLE];
+ (void) select(0, NULL, NULL, NULL, &delay);
+}
+
/*
* s_lock(lock) - take a spinlock with backoff
@@ -59,15 +70,11 @@ s_lock_stuck(volatile slock_t *lock, const char *file, const int line)
void
s_lock(volatile slock_t *lock, const char *file, const int line)
{
- int spins = 0;
+ unsigned spins = 0;
while (TAS(lock))
{
- struct timeval delay;
-
- delay.tv_sec = 0;
- delay.tv_usec = s_spincycle[spins % S_NSPINCYCLE];
- (void) select(0, NULL, NULL, NULL, &delay);
+ s_lock_sleep(spins);
if (++spins > S_MAX_BUSY)
{
/* It's been over a minute... */
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index f6ce9eda241..47305f3f087 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -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);
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 18b8d718d67..17416fc9eef 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -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
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index 740a4132631..40460404197 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -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);
}
diff --git a/src/backend/storage/lmgr/Makefile b/src/backend/storage/lmgr/Makefile
index 66fc25484a4..88cd9d060c4 100644
--- a/src/backend/storage/lmgr/Makefile
+++ b/src/backend/storage/lmgr/Makefile
@@ -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
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c
index 13adb8c48f8..307c54e39e1 100644
--- a/src/backend/storage/lmgr/lmgr.c
+++ b/src/backend/storage/lmgr/lmgr.c
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -49,6 +49,85 @@
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
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index adc4d1a42ea..7fdd8fec843 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -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
diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c
index a9c669bc3aa..6553e73214c 100644
--- a/src/backend/utils/adt/sets.c
+++ b/src/backend/utils/adt/sets.c
@@ -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;
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 492eba6f659..99ee3d2fc54 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -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);
}
diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index c88646151a7..f53fdd72720 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -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 */
+}
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 0c756e0beba..e883c7f0a50 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -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 */
diff --git a/src/include/access/hio.h b/src/include/access/hio.h
index caa5380083d..eb8a955b4d0 100644
--- a/src/include/access/hio.h
+++ b/src/include/access/hio.h
@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: hio.h,v 1.8 1998/09/01 04:34:13 momjian Exp $
+ * $Id: hio.h,v 1.9 1998/12/15 12:46:45 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,8 +17,8 @@
#include <utils/rel.h>
-extern void RelationPutHeapTuple(Relation relation, BlockNumber blockIndex,
- HeapTuple tuple);
+extern void RelationPutHeapTuple(Relation relation, Buffer buffer,
+ HeapTuple tuple);
extern void RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple);
#endif /* HIO_H */
diff --git a/src/include/access/htup.h b/src/include/access/htup.h
index 56197048ba0..06c62a9a4d9 100644
--- a/src/include/access/htup.h
+++ b/src/include/access/htup.h
@@ -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 /* */
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index e4c1e0a88ce..6b0aae443f0 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -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
* ----------------
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index 3106ffa7cc1..bc3b9da1def 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -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("");
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index c96e05e3939..c657375241a 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -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 */
diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h
index 3cc0fdcc066..b52c81dc726 100644
--- a/src/include/commands/trigger.h
+++ b/src/include/commands/trigger.h
@@ -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 */
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index 61f567b6d3b..383204c3f0f 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -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,32 +99,26 @@ 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;
diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h
index 1948e813ee3..22f66c2295b 100644
--- a/src/include/storage/bufmgr.h
+++ b/src/include/storage/bufmgr.h
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -74,6 +74,14 @@ extern int ShowPinTrace;
#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
* Note:
@@ -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) */
diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h
index 4733b34bbc8..2163aa79d59 100644
--- a/src/include/storage/ipc.h
+++ b/src/include/storage/ipc.h
@@ -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
diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h
index 4082811bcc8..a85ba1e8ff7 100644
--- a/src/include/storage/lmgr.h
+++ b/src/include/storage/lmgr.h
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -17,64 +17,48 @@
#include <utils/rel.h>
#include <catalog/catname.h>
-/*
- * This was moved from pladt.h for the new lock manager. Want to obsolete
- * all of the old code.
- */
+#define AccessShareLock 1 /* SELECT */
+#define RowShareLock 2 /* SELECT FOR UPDATE */
+#define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */
+#define ShareLock 4
+#define ShareRowExclusiveLock 5
+#define ExclusiveLock 6
+#define AccessExclusiveLock 7
+
+#define ExtendLock 8
+
+extern LOCKMETHOD LockTableId;
+
+
typedef struct LockRelId
{
Oid relId; /* a relation identifier */
Oid dbId; /* a database identifier */
} LockRelId;
-#ifdef LowLevelLocking
typedef struct LockInfoData
{
LockRelId lockRelId;
- bool lockHeld[MAX_LOCKMODES]; /* on table level */
} LockInfoData;
-#else
-typedef struct LockInfoData
-{
- LockRelId lockRelId;
-} LockInfoData;
-
-#endif
-
typedef LockInfoData *LockInfo;
#define LockInfoIsValid(lockinfo) PointerIsValid(lockinfo)
+extern LOCKMETHOD InitLockTable(void);
extern void RelationInitLockInfo(Relation relation);
-extern void RelationSetLockForDescriptorOpen(Relation relation);
-extern void RelationSetLockForRead(Relation relation);
-extern void RelationUnsetLockForRead(Relation relation);
-extern void RelationSetLockForWrite(Relation relation);
-extern void RelationUnsetLockForWrite(Relation relation);
-/* used in vaccum.c */
-extern void RelationSetLockForWritePage(Relation relation,
- ItemPointer itemPointer);
+extern void LockRelation(Relation relation, LOCKMODE lockmode);
+extern void UnlockRelation(Relation relation, LOCKMODE lockmode);
-/* used in nbtpage.c, hashpage.c */
-extern void RelationSetSingleWLockPage(Relation relation,
- ItemPointer itemPointer);
-extern void RelationUnsetSingleWLockPage(Relation relation,
- ItemPointer itemPointer);
-extern void RelationSetSingleRLockPage(Relation relation,
- ItemPointer itemPointer);
-extern void RelationUnsetSingleRLockPage(Relation relation,
- ItemPointer itemPointer);
-extern void RelationSetRIntentLock(Relation relation);
-extern void RelationUnsetRIntentLock(Relation relation);
-extern void RelationSetWIntentLock(Relation relation);
-extern void RelationUnsetWIntentLock(Relation relation);
+/* this is for indices */
+extern void LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
+extern void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
-/* single.c */
-extern bool SingleLockReln(LockInfo lockinfo, LOCKMODE lockmode, int action);
-extern bool SingleLockPage(LockInfo lockinfo, ItemPointer tidPtr,
- LOCKMODE lockmode, int action);
+/* and this is for transactions */
+extern void XactLockTableInsert(TransactionId xid);
+extern void XactLockTableDelete(TransactionId xid);
+extern void XactLockTableWait(TransactionId xid);
/* proc.c */
extern void InitProcGlobal(IPCKey key);
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
index 329aa758a7f..9c803ef8a12 100644
--- a/src/include/storage/lock.h
+++ b/src/include/storage/lock.h
@@ -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;
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 4a62fac18ab..914d934524f 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -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 */
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index d47f5ab53b9..aa20a328bdc 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -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)
diff --git a/src/include/utils/tqual.h b/src/include/utils/tqual.h
index 3d2f8531f47..cb15a60ca0d 100644
--- a/src/include/utils/tqual.h
+++ b/src/include/utils/tqual.h
@@ -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 $
*
*-------------------------------------------------------------------------
*/
@@ -18,17 +18,20 @@
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 */