mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +03:00
Initial MVCC code.
New code for locking buffer' context.
This commit is contained in:
@ -104,8 +104,7 @@ gistbuild(Relation heap,
|
|||||||
Buffer buffer = InvalidBuffer;
|
Buffer buffer = InvalidBuffer;
|
||||||
bool *compvec;
|
bool *compvec;
|
||||||
|
|
||||||
/* GiSTs only know how to do stupid locking now */
|
/* no locking is needed */
|
||||||
RelationSetLockForWrite(index);
|
|
||||||
|
|
||||||
setheapoverride(true); /* so we can see the new pg_index tuple */
|
setheapoverride(true); /* so we can see the new pg_index tuple */
|
||||||
initGISTstate(&giststate, index);
|
initGISTstate(&giststate, index);
|
||||||
@ -269,7 +268,6 @@ gistbuild(Relation heap,
|
|||||||
|
|
||||||
/* okay, all heap tuples are indexed */
|
/* okay, all heap tuples are indexed */
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
RelationUnsetLockForWrite(index);
|
|
||||||
|
|
||||||
if (pred != NULL || oldPred != NULL)
|
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 = index_formtuple(RelationGetDescr(r), datum, nulls);
|
||||||
itup->t_tid = *ht_ctid;
|
itup->t_tid = *ht_ctid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notes in ExecUtils:ExecOpenIndices()
|
||||||
|
*
|
||||||
RelationSetLockForWrite(r);
|
RelationSetLockForWrite(r);
|
||||||
|
*/
|
||||||
|
|
||||||
res = gistdoinsert(r, itup, &giststate);
|
res = gistdoinsert(r, itup, &giststate);
|
||||||
for (i = 0; i < r->rd_att->natts; i++)
|
for (i = 0; i < r->rd_att->natts; i++)
|
||||||
if (compvec[i] == TRUE)
|
if (compvec[i] == TRUE)
|
||||||
@ -351,7 +354,6 @@ gistinsert(Relation r, Datum *datum, char *nulls, ItemPointer ht_ctid, Relation
|
|||||||
pfree(itup);
|
pfree(itup);
|
||||||
pfree(compvec);
|
pfree(compvec);
|
||||||
|
|
||||||
/* XXX two-phase locking -- don't unlock the relation until EOT */
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1103,8 +1105,12 @@ gistdelete(Relation r, ItemPointer tid)
|
|||||||
Buffer buf;
|
Buffer buf;
|
||||||
Page page;
|
Page page;
|
||||||
|
|
||||||
/* must write-lock on delete */
|
/*
|
||||||
|
* Notes in ExecUtils:ExecOpenIndices()
|
||||||
|
* Also note that only vacuum deletes index tuples now...
|
||||||
|
*
|
||||||
RelationSetLockForWrite(r);
|
RelationSetLockForWrite(r);
|
||||||
|
*/
|
||||||
|
|
||||||
blkno = ItemPointerGetBlockNumber(tid);
|
blkno = ItemPointerGetBlockNumber(tid);
|
||||||
offnum = ItemPointerGetOffsetNumber(tid);
|
offnum = ItemPointerGetOffsetNumber(tid);
|
||||||
@ -1120,7 +1126,6 @@ gistdelete(Relation r, ItemPointer tid)
|
|||||||
|
|
||||||
WriteBuffer(buf);
|
WriteBuffer(buf);
|
||||||
|
|
||||||
/* XXX -- two-phase locking, don't release the write lock */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -65,7 +65,12 @@ gistbeginscan(Relation r,
|
|||||||
{
|
{
|
||||||
IndexScanDesc s;
|
IndexScanDesc s;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let index_beginscan does its work...
|
||||||
|
*
|
||||||
RelationSetLockForRead(r);
|
RelationSetLockForRead(r);
|
||||||
|
*/
|
||||||
|
|
||||||
s = RelationGetIndexScan(r, fromEnd, nkeys, key);
|
s = RelationGetIndexScan(r, fromEnd, nkeys, key);
|
||||||
gistregscan(s);
|
gistregscan(s);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Postgres hash pages look like ordinary relation pages. The opaque
|
* 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... */
|
/* can't be sharing this with anyone, now... */
|
||||||
if (USELOCKING)
|
if (USELOCKING)
|
||||||
RelationSetLockForWrite(rel);
|
LockRelation(rel, AccessExclusiveLock);
|
||||||
|
|
||||||
if ((nblocks = RelationGetNumberOfBlocks(rel)) != 0)
|
if ((nblocks = RelationGetNumberOfBlocks(rel)) != 0)
|
||||||
{
|
{
|
||||||
@ -169,7 +169,7 @@ _hash_metapinit(Relation rel)
|
|||||||
_hash_relbuf(rel, metabuf, HASH_WRITE);
|
_hash_relbuf(rel, metabuf, HASH_WRITE);
|
||||||
|
|
||||||
if (USELOCKING)
|
if (USELOCKING)
|
||||||
RelationUnsetLockForWrite(rel);
|
UnlockRelation(rel, AccessExclusiveLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -316,19 +316,16 @@ _hash_setpagelock(Relation rel,
|
|||||||
BlockNumber blkno,
|
BlockNumber blkno,
|
||||||
int access)
|
int access)
|
||||||
{
|
{
|
||||||
ItemPointerData iptr;
|
|
||||||
|
|
||||||
if (USELOCKING)
|
if (USELOCKING)
|
||||||
{
|
{
|
||||||
ItemPointerSet(&iptr, blkno, 1);
|
|
||||||
|
|
||||||
switch (access)
|
switch (access)
|
||||||
{
|
{
|
||||||
case HASH_WRITE:
|
case HASH_WRITE:
|
||||||
RelationSetSingleWLockPage(rel, &iptr);
|
LockPage(rel, blkno, ExclusiveLock);
|
||||||
break;
|
break;
|
||||||
case HASH_READ:
|
case HASH_READ:
|
||||||
RelationSetSingleRLockPage(rel, &iptr);
|
LockPage(rel, blkno, ShareLock);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
elog(ERROR, "_hash_setpagelock: invalid access (%d) on blk %x: %s",
|
elog(ERROR, "_hash_setpagelock: invalid access (%d) on blk %x: %s",
|
||||||
@ -343,19 +340,16 @@ _hash_unsetpagelock(Relation rel,
|
|||||||
BlockNumber blkno,
|
BlockNumber blkno,
|
||||||
int access)
|
int access)
|
||||||
{
|
{
|
||||||
ItemPointerData iptr;
|
|
||||||
|
|
||||||
if (USELOCKING)
|
if (USELOCKING)
|
||||||
{
|
{
|
||||||
ItemPointerSet(&iptr, blkno, 1);
|
|
||||||
|
|
||||||
switch (access)
|
switch (access)
|
||||||
{
|
{
|
||||||
case HASH_WRITE:
|
case HASH_WRITE:
|
||||||
RelationUnsetSingleWLockPage(rel, &iptr);
|
UnlockPage(rel, blkno, ExclusiveLock);
|
||||||
break;
|
break;
|
||||||
case HASH_READ:
|
case HASH_READ:
|
||||||
RelationUnsetSingleRLockPage(rel, &iptr);
|
UnlockPage(rel, blkno, ShareLock);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
elog(ERROR, "_hash_unsetpagelock: invalid access (%d) on blk %x: %s",
|
elog(ERROR, "_hash_unsetpagelock: invalid access (%d) on blk %x: %s",
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* INTERFACE ROUTINES
|
||||||
@ -89,15 +89,12 @@
|
|||||||
#include <utils/inval.h>
|
#include <utils/inval.h>
|
||||||
#include <utils/memutils.h>
|
#include <utils/memutils.h>
|
||||||
|
|
||||||
|
|
||||||
#ifndef HAVE_MEMMOVE
|
#ifndef HAVE_MEMMOVE
|
||||||
#include <regex/utils.h>
|
#include <regex/utils.h>
|
||||||
#else
|
#else
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void doinsert(Relation relation, HeapTuple tup);
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------
|
/* ----------------------------------------------------------------
|
||||||
* heap support routines
|
* heap support routines
|
||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
@ -214,7 +211,7 @@ static void
|
|||||||
heapgettup(Relation relation,
|
heapgettup(Relation relation,
|
||||||
HeapTuple tuple,
|
HeapTuple tuple,
|
||||||
int dir,
|
int dir,
|
||||||
Buffer *buf,
|
Buffer *buffer,
|
||||||
Snapshot snapshot,
|
Snapshot snapshot,
|
||||||
int nkeys,
|
int nkeys,
|
||||||
ScanKey key)
|
ScanKey key)
|
||||||
@ -255,7 +252,7 @@ heapgettup(Relation relation,
|
|||||||
elog(DEBUG, "heapgettup(%s, tid=0x%x, dir=%d, ...)",
|
elog(DEBUG, "heapgettup(%s, tid=0x%x, dir=%d, ...)",
|
||||||
RelationGetRelationName(relation), tid, dir);
|
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",
|
elog(DEBUG, "heapgettup: relation(%c)=`%s', %p",
|
||||||
relation->rd_rel->relkind, &relation->rd_rel->relname,
|
relation->rd_rel->relkind, &relation->rd_rel->relname,
|
||||||
@ -288,25 +285,26 @@ heapgettup(Relation relation,
|
|||||||
/* assume it is a valid TID XXX */
|
/* assume it is a valid TID XXX */
|
||||||
if (ItemPointerIsValid(tid) == false)
|
if (ItemPointerIsValid(tid) == false)
|
||||||
{
|
{
|
||||||
*buf = InvalidBuffer;
|
*buffer = InvalidBuffer;
|
||||||
tuple->t_data = NULL;
|
tuple->t_data = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*buf = RelationGetBufferWithBuffer(relation,
|
*buffer = RelationGetBufferWithBuffer(relation,
|
||||||
ItemPointerGetBlockNumber(tid),
|
ItemPointerGetBlockNumber(tid),
|
||||||
*buf);
|
*buffer);
|
||||||
|
|
||||||
#ifndef NO_BUFFERISVALID
|
if (!BufferIsValid(*buffer))
|
||||||
if (!BufferIsValid(*buf))
|
|
||||||
elog(ERROR, "heapgettup: failed ReadBuffer");
|
elog(ERROR, "heapgettup: failed ReadBuffer");
|
||||||
#endif
|
|
||||||
|
|
||||||
dp = (Page) BufferGetPage(*buf);
|
LockBuffer(*buffer, BUFFER_LOCK_SHARE);
|
||||||
|
|
||||||
|
dp = (Page) BufferGetPage(*buffer);
|
||||||
lineoff = ItemPointerGetOffsetNumber(tid);
|
lineoff = ItemPointerGetOffsetNumber(tid);
|
||||||
lpp = PageGetItemId(dp, lineoff);
|
lpp = PageGetItemId(dp, lineoff);
|
||||||
|
|
||||||
tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
|
tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
|
||||||
tuple->t_len = ItemIdGetLength(lpp);
|
tuple->t_len = ItemIdGetLength(lpp);
|
||||||
|
LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -328,18 +326,18 @@ heapgettup(Relation relation,
|
|||||||
}
|
}
|
||||||
if (page < 0)
|
if (page < 0)
|
||||||
{
|
{
|
||||||
*buf = InvalidBuffer;
|
*buffer = InvalidBuffer;
|
||||||
tuple->t_data = NULL;
|
tuple->t_data = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*buf = RelationGetBufferWithBuffer(relation, page, *buf);
|
*buffer = RelationGetBufferWithBuffer(relation, page, *buffer);
|
||||||
#ifndef NO_BUFFERISVALID
|
if (!BufferIsValid(*buffer))
|
||||||
if (!BufferIsValid(*buf))
|
|
||||||
elog(ERROR, "heapgettup: failed ReadBuffer");
|
elog(ERROR, "heapgettup: failed ReadBuffer");
|
||||||
#endif
|
|
||||||
|
|
||||||
dp = (Page) BufferGetPage(*buf);
|
LockBuffer(*buffer, BUFFER_LOCK_SHARE);
|
||||||
|
|
||||||
|
dp = (Page) BufferGetPage(*buffer);
|
||||||
lines = PageGetMaxOffsetNumber(dp);
|
lines = PageGetMaxOffsetNumber(dp);
|
||||||
if (tid == NULL)
|
if (tid == NULL)
|
||||||
{
|
{
|
||||||
@ -373,19 +371,19 @@ heapgettup(Relation relation,
|
|||||||
|
|
||||||
if (page >= pages)
|
if (page >= pages)
|
||||||
{
|
{
|
||||||
*buf = InvalidBuffer;
|
*buffer = InvalidBuffer;
|
||||||
tuple->t_data = NULL;
|
tuple->t_data = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* page and lineoff now reference the physically next tid */
|
/* page and lineoff now reference the physically next tid */
|
||||||
|
|
||||||
*buf = RelationGetBufferWithBuffer(relation, page, *buf);
|
*buffer = RelationGetBufferWithBuffer(relation, page, *buffer);
|
||||||
#ifndef NO_BUFFERISVALID
|
if (!BufferIsValid(*buffer))
|
||||||
if (!BufferIsValid(*buf))
|
|
||||||
elog(ERROR, "heapgettup: failed ReadBuffer");
|
elog(ERROR, "heapgettup: failed ReadBuffer");
|
||||||
#endif
|
|
||||||
|
|
||||||
dp = (Page) BufferGetPage(*buf);
|
LockBuffer(*buffer, BUFFER_LOCK_SHARE);
|
||||||
|
|
||||||
|
dp = (Page) BufferGetPage(*buffer);
|
||||||
lines = PageGetMaxOffsetNumber(dp);
|
lines = PageGetMaxOffsetNumber(dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,10 +418,13 @@ heapgettup(Relation relation,
|
|||||||
* if current tuple qualifies, return it.
|
* if current tuple qualifies, return it.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
HeapTupleSatisfies(tuple, relation, *buf, (PageHeader) dp,
|
HeapTupleSatisfies(tuple, relation, *buffer, (PageHeader) dp,
|
||||||
snapshot, nkeys, key);
|
snapshot, nkeys, key);
|
||||||
if (tuple->t_data != NULL)
|
if (tuple->t_data != NULL)
|
||||||
|
{
|
||||||
|
LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
@ -448,6 +449,7 @@ heapgettup(Relation relation,
|
|||||||
* this page and it's time to move to the next..
|
* this page and it's time to move to the next..
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
|
||||||
page = nextpage(page, dir);
|
page = nextpage(page, dir);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
@ -456,20 +458,19 @@ heapgettup(Relation relation,
|
|||||||
*/
|
*/
|
||||||
if (page < 0 || page >= pages)
|
if (page < 0 || page >= pages)
|
||||||
{
|
{
|
||||||
if (BufferIsValid(*buf))
|
if (BufferIsValid(*buffer))
|
||||||
ReleaseBuffer(*buf);
|
ReleaseBuffer(*buffer);
|
||||||
*buf = InvalidBuffer;
|
*buffer = InvalidBuffer;
|
||||||
tuple->t_data = NULL;
|
tuple->t_data = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*buf = ReleaseAndReadBuffer(*buf, relation, page);
|
*buffer = ReleaseAndReadBuffer(*buffer, relation, page);
|
||||||
|
|
||||||
#ifndef NO_BUFFERISVALID
|
if (!BufferIsValid(*buffer))
|
||||||
if (!BufferIsValid(*buf))
|
|
||||||
elog(ERROR, "heapgettup: failed ReadBuffer");
|
elog(ERROR, "heapgettup: failed ReadBuffer");
|
||||||
#endif
|
LockBuffer(*buffer, BUFFER_LOCK_SHARE);
|
||||||
dp = (Page) BufferGetPage(*buf);
|
dp = (Page) BufferGetPage(*buffer);
|
||||||
lines = PageGetMaxOffsetNumber((Page) dp);
|
lines = PageGetMaxOffsetNumber((Page) dp);
|
||||||
linesleft = lines - 1;
|
linesleft = lines - 1;
|
||||||
if (dir < 0)
|
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
|
* heap access method interface
|
||||||
@ -599,11 +593,7 @@ heap_beginscan(Relation relation,
|
|||||||
if (RelationIsValid(relation) == false)
|
if (RelationIsValid(relation) == false)
|
||||||
elog(ERROR, "heap_beginscan: !RelationIsValid(relation)");
|
elog(ERROR, "heap_beginscan: !RelationIsValid(relation)");
|
||||||
|
|
||||||
/* ----------------
|
LockRelation(relation, AccessShareLock);
|
||||||
* set relation level read lock
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
RelationSetLockForRead(relation);
|
|
||||||
|
|
||||||
/* XXX someday assert SelfTimeQual if relkind == RELKIND_UNCATALOGED */
|
/* XXX someday assert SelfTimeQual if relkind == RELKIND_UNCATALOGED */
|
||||||
if (relation->rd_rel->relkind == RELKIND_UNCATALOGED)
|
if (relation->rd_rel->relkind == RELKIND_UNCATALOGED)
|
||||||
@ -707,13 +697,7 @@ heap_endscan(HeapScanDesc scan)
|
|||||||
*/
|
*/
|
||||||
RelationDecrementReferenceCount(scan->rs_rd);
|
RelationDecrementReferenceCount(scan->rs_rd);
|
||||||
|
|
||||||
/* ----------------
|
UnlockRelation(scan->rs_rd, AccessShareLock);
|
||||||
* Non 2-phase read locks on catalog relations
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
if (IsSystemRelationName(RelationGetRelationName(scan->rs_rd)->data))
|
|
||||||
|
|
||||||
RelationUnsetLockForRead(scan->rs_rd);
|
|
||||||
|
|
||||||
pfree(scan); /* XXX */
|
pfree(scan); /* XXX */
|
||||||
}
|
}
|
||||||
@ -997,14 +981,6 @@ heap_fetch(Relation relation,
|
|||||||
IncrHeapAccessStat(local_fetch);
|
IncrHeapAccessStat(local_fetch);
|
||||||
IncrHeapAccessStat(global_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
|
* get the buffer from the relation descriptor
|
||||||
* Note that this does a buffer pin.
|
* Note that this does a buffer pin.
|
||||||
@ -1013,13 +989,11 @@ heap_fetch(Relation relation,
|
|||||||
|
|
||||||
buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
|
buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
|
||||||
|
|
||||||
#ifndef NO_BUFFERISVALID
|
|
||||||
if (!BufferIsValid(buffer))
|
if (!BufferIsValid(buffer))
|
||||||
{
|
|
||||||
elog(ERROR, "heap_fetch: %s relation: ReadBuffer(%lx) failed",
|
elog(ERROR, "heap_fetch: %s relation: ReadBuffer(%lx) failed",
|
||||||
&relation->rd_rel->relname, (long) tid);
|
&relation->rd_rel->relname, (long) tid);
|
||||||
}
|
|
||||||
#endif
|
LockBuffer(buffer, BUFFER_LOCK_SHARE);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* get the item line pointer corresponding to the requested tid
|
* get the item line pointer corresponding to the requested tid
|
||||||
@ -1047,6 +1021,8 @@ heap_fetch(Relation relation,
|
|||||||
HeapTupleSatisfies(tuple, relation, buffer, dp,
|
HeapTupleSatisfies(tuple, relation, buffer, dp,
|
||||||
snapshot, 0, (ScanKey) NULL);
|
snapshot, 0, (ScanKey) NULL);
|
||||||
|
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
|
|
||||||
if (tuple->t_data == NULL)
|
if (tuple->t_data == NULL)
|
||||||
{
|
{
|
||||||
ReleaseBuffer(buffer);
|
ReleaseBuffer(buffer);
|
||||||
@ -1090,14 +1066,6 @@ heap_insert(Relation relation, HeapTuple tup)
|
|||||||
IncrHeapAccessStat(local_insert);
|
IncrHeapAccessStat(local_insert);
|
||||||
IncrHeapAccessStat(global_insert);
|
IncrHeapAccessStat(global_insert);
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* set relation level write lock. If this is a "local" relation (not
|
|
||||||
* visible to others), we don't need to set a write lock.
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
if (!relation->rd_islocal)
|
|
||||||
RelationSetLockForWrite(relation);
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* If the object id of this tuple has already been assigned, trust
|
* 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
|
* the caller. There are a couple of ways this can happen. At initial
|
||||||
@ -1122,228 +1090,178 @@ heap_insert(Relation relation, HeapTuple tup)
|
|||||||
tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
|
tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
|
||||||
tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
|
tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
|
||||||
doinsert(relation, tup);
|
RelationPutHeapTupleAtEnd(relation, tup);
|
||||||
|
|
||||||
if (IsSystemRelationName(RelationGetRelationName(relation)->data))
|
if (IsSystemRelationName(RelationGetRelationName(relation)->data))
|
||||||
{
|
{
|
||||||
RelationUnsetLockForWrite(relation);
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* invalidate caches (only works for system relations)
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
RelationInvalidateHeapTuple(relation, tup);
|
RelationInvalidateHeapTuple(relation, tup);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tup->t_data->t_oid;
|
return tup->t_data->t_oid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/*
|
||||||
* heap_delete - delete a tuple
|
* heap_delete - delete a tuple
|
||||||
*
|
|
||||||
* Must decide how to handle errors.
|
|
||||||
* ----------------
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
heap_delete(Relation relation, ItemPointer tid)
|
heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid)
|
||||||
{
|
{
|
||||||
ItemId lp;
|
ItemId lp;
|
||||||
HeapTupleData tp;
|
HeapTupleData tp;
|
||||||
PageHeader dp;
|
PageHeader dp;
|
||||||
Buffer buf;
|
Buffer buffer;
|
||||||
|
int result;
|
||||||
|
|
||||||
/* ----------------
|
/* increment access statistics */
|
||||||
* increment access statistics
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
IncrHeapAccessStat(local_delete);
|
IncrHeapAccessStat(local_delete);
|
||||||
IncrHeapAccessStat(global_delete);
|
IncrHeapAccessStat(global_delete);
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* sanity check
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
Assert(ItemPointerIsValid(tid));
|
Assert(ItemPointerIsValid(tid));
|
||||||
|
|
||||||
/* ----------------
|
buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
|
||||||
* set relation level write lock
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
RelationSetLockForWrite(relation);
|
|
||||||
|
|
||||||
buf = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
|
if (!BufferIsValid(buffer))
|
||||||
|
|
||||||
#ifndef NO_BUFFERISVALID
|
|
||||||
if (!BufferIsValid(buf))
|
|
||||||
{ /* XXX L_SH better ??? */
|
|
||||||
elog(ERROR, "heap_delete: failed ReadBuffer");
|
elog(ERROR, "heap_delete: failed ReadBuffer");
|
||||||
}
|
|
||||||
#endif /* NO_BUFFERISVALID */
|
|
||||||
|
|
||||||
dp = (PageHeader) BufferGetPage(buf);
|
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
||||||
|
|
||||||
|
dp = (PageHeader) BufferGetPage(buffer);
|
||||||
lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
|
lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
|
||||||
|
|
||||||
/*
|
|
||||||
* Just like test against non-functional updates we try to catch
|
|
||||||
* non-functional delete attempts. - vadim 05/05/97
|
|
||||||
*/
|
|
||||||
tp.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
|
tp.t_data = (HeapTupleHeader) PageGetItem((Page) dp, lp);
|
||||||
tp.t_len = ItemIdGetLength(lp);
|
tp.t_len = ItemIdGetLength(lp);
|
||||||
tp.t_self = *tid;
|
tp.t_self = *tid;
|
||||||
|
|
||||||
if (TupleUpdatedByCurXactAndCmd(&tp))
|
l1:
|
||||||
|
result = HeapTupleSatisfiesUpdate(&tp);
|
||||||
|
|
||||||
|
if (result == HeapTupleInvisible)
|
||||||
{
|
{
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
/*
|
ReleaseBuffer(buffer);
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
/* ----------------
|
|
||||||
* check that we're deleteing a valid item
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
HeapTupleSatisfies((&tp), relation, buf, dp,
|
|
||||||
false, 0, (ScanKey) NULL);
|
|
||||||
if (!(tp.t_data))
|
|
||||||
{
|
|
||||||
|
|
||||||
/* XXX call something else */
|
|
||||||
ReleaseBuffer(buf);
|
|
||||||
|
|
||||||
elog(ERROR, "heap_delete: (am)invalid tid");
|
elog(ERROR, "heap_delete: (am)invalid tid");
|
||||||
}
|
}
|
||||||
|
else if (result == HeapTupleBeingUpdated)
|
||||||
|
{
|
||||||
|
TransactionId xwait = tp.t_data->t_xmax;
|
||||||
|
|
||||||
/* ----------------
|
/* sleep untill concurrent transaction ends */
|
||||||
* get the tuple and lock tell the buffer manager we want
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
* exclusive access to the page
|
XactLockTableWait(xwait);
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ----------------
|
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
||||||
* store transaction information of xact deleting the tuple
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store transaction information of xact deleting the tuple */
|
||||||
TransactionIdStore(GetCurrentTransactionId(), &(tp.t_data->t_xmax));
|
TransactionIdStore(GetCurrentTransactionId(), &(tp.t_data->t_xmax));
|
||||||
tp.t_data->t_cmax = GetCurrentCommandId();
|
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);
|
||||||
|
|
||||||
/* ----------------
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
* invalidate caches
|
|
||||||
* ----------------
|
/* invalidate caches */
|
||||||
*/
|
|
||||||
RelationInvalidateHeapTuple(relation, &tp);
|
RelationInvalidateHeapTuple(relation, &tp);
|
||||||
|
|
||||||
WriteBuffer(buf);
|
WriteBuffer(buffer);
|
||||||
if (IsSystemRelationName(RelationGetRelationName(relation)->data))
|
|
||||||
RelationUnsetLockForWrite(relation);
|
|
||||||
|
|
||||||
return 0;
|
return HeapTupleMayBeUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/*
|
||||||
* heap_replace - replace a tuple
|
* 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
|
|
||||||
*
|
|
||||||
* ----------------
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
heap_replace(Relation relation, ItemPointer otid, HeapTuple newtup)
|
heap_replace(Relation relation, ItemPointer otid, HeapTuple newtup,
|
||||||
|
ItemPointer ctid)
|
||||||
{
|
{
|
||||||
ItemId lp;
|
ItemId lp;
|
||||||
HeapTupleData oldtup;
|
HeapTupleData oldtup;
|
||||||
Page dp;
|
PageHeader dp;
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
|
int result;
|
||||||
|
|
||||||
/* ----------------
|
/* increment access statistics */
|
||||||
* increment access statistics
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
IncrHeapAccessStat(local_replace);
|
IncrHeapAccessStat(local_replace);
|
||||||
IncrHeapAccessStat(global_replace);
|
IncrHeapAccessStat(global_replace);
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* sanity checks
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
Assert(ItemPointerIsValid(otid));
|
Assert(ItemPointerIsValid(otid));
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* set relation level write lock
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
if (!relation->rd_islocal)
|
|
||||||
RelationSetLockForWrite(relation);
|
|
||||||
|
|
||||||
buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(otid));
|
buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(otid));
|
||||||
if (!BufferIsValid(buffer))
|
if (!BufferIsValid(buffer))
|
||||||
elog(ERROR, "amreplace: failed ReadBuffer");
|
elog(ERROR, "amreplace: failed ReadBuffer");
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
||||||
|
|
||||||
dp = (Page) BufferGetPage(buffer);
|
dp = (PageHeader) BufferGetPage(buffer);
|
||||||
lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(otid));
|
lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(otid));
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* logically delete old item
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
oldtup.t_data = (HeapTupleHeader) PageGetItem(dp, lp);
|
oldtup.t_data = (HeapTupleHeader) PageGetItem(dp, lp);
|
||||||
oldtup.t_len = ItemIdGetLength(lp);
|
oldtup.t_len = ItemIdGetLength(lp);
|
||||||
oldtup.t_self = *otid;
|
oldtup.t_self = *otid;
|
||||||
|
|
||||||
/* -----------------
|
l2:
|
||||||
* the following test should be able to catch all non-functional
|
result = HeapTupleSatisfiesUpdate(&oldtup);
|
||||||
* update attempts and shut out all ghost tuples.
|
|
||||||
* XXX In the future, Spyros may need to update the rule lock on a tuple
|
if (result == HeapTupleInvisible)
|
||||||
* 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))
|
|
||||||
{
|
{
|
||||||
elog(NOTICE, "Non-functional update, only first update is performed");
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
if (IsSystemRelationName(RelationGetRelationName(relation)->data))
|
|
||||||
RelationUnsetLockForWrite(relation);
|
|
||||||
ReleaseBuffer(buffer);
|
ReleaseBuffer(buffer);
|
||||||
return 1;
|
elog(ERROR, "heap_replace: (am)invalid tid");
|
||||||
}
|
}
|
||||||
|
else if (result == HeapTupleBeingUpdated)
|
||||||
/* ----------------
|
|
||||||
* 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))
|
|
||||||
{
|
{
|
||||||
|
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);
|
ReleaseBuffer(buffer);
|
||||||
elog(ERROR, "heap_replace: (am)invalid otid");
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX order problems if not atomic assignment ??? */
|
/* 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_XACT_MASK);
|
||||||
newtup->t_data->t_infomask |= HEAP_XMAX_INVALID;
|
newtup->t_data->t_infomask |= HEAP_XMAX_INVALID;
|
||||||
|
|
||||||
/* ----------------
|
/* logically delete old item */
|
||||||
* insert new item
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
if ((unsigned) DOUBLEALIGN(newtup->t_len) <= PageGetFreeSpace((Page) dp))
|
|
||||||
RelationPutHeapTuple(relation, BufferGetBlockNumber(buffer), newtup);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* ----------------
|
|
||||||
* new item won't fit on same page as old item, have to look
|
|
||||||
* for a new place to put it.
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
doinsert(relation, newtup);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* new item in place, now record transaction information
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
TransactionIdStore(GetCurrentTransactionId(), &(oldtup.t_data->t_xmax));
|
TransactionIdStore(GetCurrentTransactionId(), &(oldtup.t_data->t_xmax));
|
||||||
oldtup.t_data->t_cmax = GetCurrentCommandId();
|
oldtup.t_data->t_cmax = GetCurrentCommandId();
|
||||||
oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED | HEAP_XMAX_INVALID);
|
oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
|
||||||
|
HEAP_XMAX_INVALID | HEAP_MARKED_FOR_UPDATE);
|
||||||
|
|
||||||
/* ----------------
|
/* insert new item */
|
||||||
* invalidate caches
|
if ((unsigned) DOUBLEALIGN(newtup->t_len) <= PageGetFreeSpace((Page) dp))
|
||||||
* ----------------
|
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. Note that we have to unlock
|
||||||
|
* current buffer context - not good but RelationPutHeapTupleAtEnd
|
||||||
|
* uses extend lock.
|
||||||
|
*/
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
|
RelationPutHeapTupleAtEnd(relation, newtup);
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* New item in place, now record address of new tuple in
|
||||||
|
* t_ctid of old one.
|
||||||
*/
|
*/
|
||||||
|
oldtup.t_data->t_ctid = newtup->t_self;
|
||||||
|
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
|
|
||||||
|
/* invalidate caches */
|
||||||
RelationInvalidateHeapTuple(relation, &oldtup);
|
RelationInvalidateHeapTuple(relation, &oldtup);
|
||||||
|
|
||||||
WriteBuffer(buffer);
|
WriteBuffer(buffer);
|
||||||
|
|
||||||
if (IsSystemRelationName(RelationGetRelationName(relation)->data))
|
return HeapTupleMayBeUpdated;
|
||||||
RelationUnsetLockForWrite(relation);
|
}
|
||||||
|
|
||||||
return 0;
|
/*
|
||||||
|
* 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 HeapTupleMayBeUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 <postgres.h>
|
||||||
|
|
||||||
#include <storage/bufpage.h>
|
#include <storage/bufpage.h>
|
||||||
|
#include <access/hio.h>
|
||||||
#include <access/heapam.h>
|
#include <access/heapam.h>
|
||||||
#include <storage/bufmgr.h>
|
#include <storage/bufmgr.h>
|
||||||
#include <utils/memutils.h>
|
#include <utils/memutils.h>
|
||||||
@ -29,19 +30,20 @@
|
|||||||
* Probably needs to have an amdelunique to allow for
|
* Probably needs to have an amdelunique to allow for
|
||||||
* internal index records to be deleted and reordered as needed.
|
* internal index records to be deleted and reordered as needed.
|
||||||
* For the heap AM, this should never be needed.
|
* For the heap AM, this should never be needed.
|
||||||
|
*
|
||||||
|
* Note - we assume that caller hold BUFFER_LOCK_EXCLUSIVE on the buffer.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
RelationPutHeapTuple(Relation relation,
|
RelationPutHeapTuple(Relation relation,
|
||||||
BlockNumber blockIndex,
|
Buffer buffer,
|
||||||
HeapTuple tuple)
|
HeapTuple tuple)
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Page pageHeader;
|
||||||
Page pageHeader;
|
OffsetNumber offnum;
|
||||||
BlockNumber numberOfBlocks;
|
unsigned int len;
|
||||||
OffsetNumber offnum;
|
ItemId itemId;
|
||||||
unsigned int len;
|
Item item;
|
||||||
ItemId itemId;
|
|
||||||
Item item;
|
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* increment access statistics
|
* increment access statistics
|
||||||
@ -50,21 +52,6 @@ RelationPutHeapTuple(Relation relation,
|
|||||||
IncrHeapAccessStat(local_RelationPutHeapTuple);
|
IncrHeapAccessStat(local_RelationPutHeapTuple);
|
||||||
IncrHeapAccessStat(global_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);
|
pageHeader = (Page) BufferGetPage(buffer);
|
||||||
len = (unsigned) DOUBLEALIGN(tuple->t_len); /* be conservative */
|
len = (unsigned) DOUBLEALIGN(tuple->t_len); /* be conservative */
|
||||||
Assert((int) len <= PageGetFreeSpace(pageHeader));
|
Assert((int) len <= PageGetFreeSpace(pageHeader));
|
||||||
@ -75,11 +62,17 @@ RelationPutHeapTuple(Relation relation,
|
|||||||
itemId = PageGetItemId((Page) pageHeader, offnum);
|
itemId = PageGetItemId((Page) pageHeader, offnum);
|
||||||
item = PageGetItem((Page) pageHeader, itemId);
|
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);
|
WriteBuffer(buffer);
|
||||||
|
*/
|
||||||
|
|
||||||
/* return an accurate tuple */
|
/* 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.
|
* RelationGetNumberOfBlocks to be useful.
|
||||||
*
|
*
|
||||||
* NOTE: This code presumes that we have a write lock on the relation.
|
* 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
|
* 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
|
* 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;
|
ItemId itemId;
|
||||||
Item item;
|
Item item;
|
||||||
|
|
||||||
Assert(RelationIsValid(relation));
|
if (!relation->rd_islocal)
|
||||||
Assert(HeapTupleIsValid(tuple));
|
LockRelation(relation, ExtendLock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX This does an lseek - VERY expensive - but at the moment it is
|
* 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);
|
buffer = ReadBuffer(relation, lastblock);
|
||||||
pageHeader = (Page) BufferGetPage(buffer);
|
pageHeader = (Page) BufferGetPage(buffer);
|
||||||
if (PageIsNew((PageHeader) pageHeader))
|
/*
|
||||||
{
|
* There was IF instead of ASSERT here ?!
|
||||||
buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
|
*/
|
||||||
pageHeader = (Page) BufferGetPage(buffer);
|
Assert(PageIsNew((PageHeader) pageHeader));
|
||||||
PageInit(pageHeader, BufferGetPageSize(buffer), 0);
|
buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
|
||||||
}
|
pageHeader = (Page) BufferGetPage(buffer);
|
||||||
|
PageInit(pageHeader, BufferGetPageSize(buffer), 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
buffer = ReadBuffer(relation, lastblock - 1);
|
buffer = ReadBuffer(relation, lastblock - 1);
|
||||||
|
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
||||||
pageHeader = (Page) BufferGetPage(buffer);
|
pageHeader = (Page) BufferGetPage(buffer);
|
||||||
len = (unsigned) DOUBLEALIGN(tuple->t_len); /* be conservative */
|
len = (unsigned) DOUBLEALIGN(tuple->t_len); /* be conservative */
|
||||||
|
|
||||||
@ -152,7 +148,9 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
|
|||||||
|
|
||||||
if (len > PageGetFreeSpace(pageHeader))
|
if (len > PageGetFreeSpace(pageHeader))
|
||||||
{
|
{
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
|
buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
||||||
pageHeader = (Page) BufferGetPage(buffer);
|
pageHeader = (Page) BufferGetPage(buffer);
|
||||||
PageInit(pageHeader, BufferGetPageSize(buffer), 0);
|
PageInit(pageHeader, BufferGetPageSize(buffer), 0);
|
||||||
|
|
||||||
@ -160,6 +158,9 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
|
|||||||
elog(ERROR, "Tuple is too big: size %d", len);
|
elog(ERROR, "Tuple is too big: size %d", len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!relation->rd_islocal)
|
||||||
|
UnlockRelation(relation, ExtendLock);
|
||||||
|
|
||||||
offnum = PageAddItem((Page) pageHeader, (Item) tuple->t_data,
|
offnum = PageAddItem((Page) pageHeader, (Item) tuple->t_data,
|
||||||
tuple->t_len, InvalidOffsetNumber, LP_USED);
|
tuple->t_len, InvalidOffsetNumber, LP_USED);
|
||||||
|
|
||||||
@ -173,5 +174,7 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
|
|||||||
/* return an accurate tuple */
|
/* return an accurate tuple */
|
||||||
ItemPointerSet(&tuple->t_self, lastblock, offnum);
|
ItemPointerSet(&tuple->t_self, lastblock, offnum);
|
||||||
|
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
WriteBuffer(buffer);
|
WriteBuffer(buffer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* initam should be moved someplace else.
|
* initam should be moved someplace else.
|
||||||
@ -73,6 +73,7 @@ InitHeapAccessStatistics()
|
|||||||
stats->global_insert = 0;
|
stats->global_insert = 0;
|
||||||
stats->global_delete = 0;
|
stats->global_delete = 0;
|
||||||
stats->global_replace = 0;
|
stats->global_replace = 0;
|
||||||
|
stats->global_mark4update = 0;
|
||||||
stats->global_markpos = 0;
|
stats->global_markpos = 0;
|
||||||
stats->global_restrpos = 0;
|
stats->global_restrpos = 0;
|
||||||
stats->global_BufferGetRelation = 0;
|
stats->global_BufferGetRelation = 0;
|
||||||
@ -94,6 +95,7 @@ InitHeapAccessStatistics()
|
|||||||
stats->local_insert = 0;
|
stats->local_insert = 0;
|
||||||
stats->local_delete = 0;
|
stats->local_delete = 0;
|
||||||
stats->local_replace = 0;
|
stats->local_replace = 0;
|
||||||
|
stats->local_mark4update = 0;
|
||||||
stats->local_markpos = 0;
|
stats->local_markpos = 0;
|
||||||
stats->local_restrpos = 0;
|
stats->local_restrpos = 0;
|
||||||
stats->local_BufferGetRelation = 0;
|
stats->local_BufferGetRelation = 0;
|
||||||
@ -157,6 +159,7 @@ ResetHeapAccessStatistics()
|
|||||||
stats->local_insert = 0;
|
stats->local_insert = 0;
|
||||||
stats->local_delete = 0;
|
stats->local_delete = 0;
|
||||||
stats->local_replace = 0;
|
stats->local_replace = 0;
|
||||||
|
stats->local_mark4update = 0;
|
||||||
stats->local_markpos = 0;
|
stats->local_markpos = 0;
|
||||||
stats->local_restrpos = 0;
|
stats->local_restrpos = 0;
|
||||||
stats->local_BufferGetRelation = 0;
|
stats->local_BufferGetRelation = 0;
|
||||||
@ -274,6 +277,9 @@ PrintHeapAccessStatistics(HeapAccessStatistics stats)
|
|||||||
printf("local/global_replace: %6d/%6d\n",
|
printf("local/global_replace: %6d/%6d\n",
|
||||||
stats->local_replace, stats->global_replace);
|
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",
|
printf("local/global_markpos: %6d/%6d\n",
|
||||||
stats->local_markpos, stats->global_markpos);
|
stats->local_markpos, stats->global_markpos);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* INTERFACE ROUTINES
|
||||||
* index_open - open an index relation by relationId
|
* index_open - open an index relation by relationId
|
||||||
@ -225,7 +225,7 @@ index_beginscan(Relation relation,
|
|||||||
RELATION_CHECKS;
|
RELATION_CHECKS;
|
||||||
GET_REL_PROCEDURE(beginscan, ambeginscan);
|
GET_REL_PROCEDURE(beginscan, ambeginscan);
|
||||||
|
|
||||||
RelationSetRIntentLock(relation);
|
LockRelation(relation, AccessShareLock);
|
||||||
|
|
||||||
scandesc = (IndexScanDesc)
|
scandesc = (IndexScanDesc)
|
||||||
fmgr(procedure, relation, scanFromEnd, numberOfKeys, key);
|
fmgr(procedure, relation, scanFromEnd, numberOfKeys, key);
|
||||||
@ -262,7 +262,7 @@ index_endscan(IndexScanDesc scan)
|
|||||||
|
|
||||||
fmgr(procedure, scan);
|
fmgr(procedure, scan);
|
||||||
|
|
||||||
RelationUnsetRIntentLock(scan->relation);
|
UnlockRelation(scan->relation, AccessShareLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 <storage/bufpage.h>
|
||||||
#include <access/nbtree.h>
|
#include <access/nbtree.h>
|
||||||
#include <access/heapam.h>
|
#include <access/heapam.h>
|
||||||
|
#include <access/xact.h>
|
||||||
#include <storage/bufmgr.h>
|
#include <storage/bufmgr.h>
|
||||||
#include <fmgr.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 */
|
/* trade in our read lock for a write lock */
|
||||||
_bt_relbuf(rel, buf, BT_READ);
|
_bt_relbuf(rel, buf, BT_READ);
|
||||||
|
|
||||||
|
l1:
|
||||||
buf = _bt_getbuf(rel, blkno, BT_WRITE);
|
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 */
|
{ /* they're equal */
|
||||||
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offset));
|
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offset));
|
||||||
htup.t_self = btitem->bti_itup.t_tid;
|
htup.t_self = btitem->bti_itup.t_tid;
|
||||||
heap_fetch(heapRel, SnapshotSelf, &htup, &buffer);
|
heap_fetch(heapRel, SnapshotDirty, &htup, &buffer);
|
||||||
if (htup.t_data != NULL)
|
if (htup.t_data != NULL) /* it is a duplicate */
|
||||||
{ /* 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");
|
elog(ERROR, "Cannot insert a duplicate key into a unique index");
|
||||||
}
|
}
|
||||||
/* htup null so no buffer to release */
|
/* htup null so no buffer to release */
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Postgres btree pages look like ordinary relation pages. The opaque
|
* 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... */
|
/* can't be sharing this with anyone, now... */
|
||||||
if (USELOCKING)
|
if (USELOCKING)
|
||||||
RelationSetLockForWrite(rel);
|
LockRelation(rel, AccessExclusiveLock);
|
||||||
|
|
||||||
if ((nblocks = RelationGetNumberOfBlocks(rel)) != 0)
|
if ((nblocks = RelationGetNumberOfBlocks(rel)) != 0)
|
||||||
{
|
{
|
||||||
@ -120,7 +120,7 @@ _bt_metapinit(Relation rel)
|
|||||||
|
|
||||||
/* all done */
|
/* all done */
|
||||||
if (USELOCKING)
|
if (USELOCKING)
|
||||||
RelationUnsetLockForWrite(rel);
|
UnlockRelation(rel, AccessExclusiveLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NOT_USED
|
#ifdef NOT_USED
|
||||||
@ -571,32 +571,26 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
|
|||||||
static void
|
static void
|
||||||
_bt_setpagelock(Relation rel, BlockNumber blkno, int access)
|
_bt_setpagelock(Relation rel, BlockNumber blkno, int access)
|
||||||
{
|
{
|
||||||
ItemPointerData iptr;
|
|
||||||
|
|
||||||
if (USELOCKING)
|
if (USELOCKING)
|
||||||
{
|
{
|
||||||
ItemPointerSet(&iptr, blkno, P_HIKEY);
|
|
||||||
|
|
||||||
if (access == BT_WRITE)
|
if (access == BT_WRITE)
|
||||||
RelationSetSingleWLockPage(rel, &iptr);
|
LockPage(rel, blkno, ExclusiveLock);
|
||||||
else
|
else
|
||||||
RelationSetSingleRLockPage(rel, &iptr);
|
LockPage(rel, blkno, ShareLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_bt_unsetpagelock(Relation rel, BlockNumber blkno, int access)
|
_bt_unsetpagelock(Relation rel, BlockNumber blkno, int access)
|
||||||
{
|
{
|
||||||
ItemPointerData iptr;
|
|
||||||
|
|
||||||
if (USELOCKING)
|
if (USELOCKING)
|
||||||
{
|
{
|
||||||
ItemPointerSet(&iptr, blkno, P_HIKEY);
|
|
||||||
|
|
||||||
if (access == BT_WRITE)
|
if (access == BT_WRITE)
|
||||||
RelationUnsetSingleWLockPage(rel, &iptr);
|
UnlockPage(rel, blkno, ExclusiveLock);
|
||||||
else
|
else
|
||||||
RelationUnsetSingleRLockPage(rel, &iptr);
|
UnlockPage(rel, blkno, ShareLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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);
|
initRtstate(&rtState, index);
|
||||||
|
|
||||||
/* rtrees only know how to do stupid locking now */
|
|
||||||
RelationSetLockForWrite(index);
|
|
||||||
|
|
||||||
pred = predInfo->pred;
|
pred = predInfo->pred;
|
||||||
oldPred = predInfo->oldPred;
|
oldPred = predInfo->oldPred;
|
||||||
|
|
||||||
@ -250,7 +247,6 @@ rtbuild(Relation heap,
|
|||||||
|
|
||||||
/* okay, all heap tuples are indexed */
|
/* okay, all heap tuples are indexed */
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
RelationUnsetLockForWrite(index);
|
|
||||||
|
|
||||||
if (pred != NULL || oldPred != NULL)
|
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;
|
itup->t_tid = *ht_ctid;
|
||||||
initRtstate(&rtState, r);
|
initRtstate(&rtState, r);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notes in ExecUtils:ExecOpenIndices()
|
||||||
|
*
|
||||||
RelationSetLockForWrite(r);
|
RelationSetLockForWrite(r);
|
||||||
|
*/
|
||||||
|
|
||||||
res = rtdoinsert(r, itup, &rtState);
|
res = rtdoinsert(r, itup, &rtState);
|
||||||
|
|
||||||
/* XXX two-phase locking -- don't unlock the relation until EOT */
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -946,8 +946,12 @@ rtdelete(Relation r, ItemPointer tid)
|
|||||||
Buffer buf;
|
Buffer buf;
|
||||||
Page page;
|
Page page;
|
||||||
|
|
||||||
/* must write-lock on delete */
|
/*
|
||||||
|
* Notes in ExecUtils:ExecOpenIndices()
|
||||||
|
* Also note that only vacuum deletes index tuples now...
|
||||||
|
*
|
||||||
RelationSetLockForWrite(r);
|
RelationSetLockForWrite(r);
|
||||||
|
*/
|
||||||
|
|
||||||
blkno = ItemPointerGetBlockNumber(tid);
|
blkno = ItemPointerGetBlockNumber(tid);
|
||||||
offnum = ItemPointerGetOffsetNumber(tid);
|
offnum = ItemPointerGetOffsetNumber(tid);
|
||||||
@ -963,7 +967,6 @@ rtdelete(Relation r, ItemPointer tid)
|
|||||||
|
|
||||||
WriteBuffer(buf);
|
WriteBuffer(buf);
|
||||||
|
|
||||||
/* XXX -- two-phase locking, don't release the write lock */
|
|
||||||
return (char *) NULL;
|
return (char *) NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
IndexScanDesc s;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let index_beginscan does its work...
|
||||||
|
*
|
||||||
RelationSetLockForRead(r);
|
RelationSetLockForRead(r);
|
||||||
|
*/
|
||||||
|
|
||||||
s = RelationGetIndexScan(r, fromEnd, nkeys, key);
|
s = RelationGetIndexScan(r, fromEnd, nkeys, key);
|
||||||
rtregscan(s);
|
rtregscan(s);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* This file contains the high level access-method interface to the
|
* This file contains the high level access-method interface to the
|
||||||
@ -172,8 +172,12 @@ TransactionLogTest(TransactionId transactionId, /* transaction id to test */
|
|||||||
|
|
||||||
if (!fail)
|
if (!fail)
|
||||||
{
|
{
|
||||||
TransactionIdStore(transactionId, &cachedTestXid);
|
/* must not cache status of running xaction !!! */
|
||||||
cachedTestXidStatus = xidstatus;
|
if (xidstatus != XID_INPROGRESS)
|
||||||
|
{
|
||||||
|
TransactionIdStore(transactionId, &cachedTestXid);
|
||||||
|
cachedTestXidStatus = xidstatus;
|
||||||
|
}
|
||||||
return (bool)
|
return (bool)
|
||||||
(status == xidstatus);
|
(status == xidstatus);
|
||||||
}
|
}
|
||||||
@ -219,11 +223,14 @@ TransactionLogUpdate(TransactionId transactionId, /* trans id to update */
|
|||||||
status,
|
status,
|
||||||
&fail);
|
&fail);
|
||||||
|
|
||||||
/* ----------------
|
/*
|
||||||
* update (invalidate) our single item TransactionLogTest cache.
|
* update (invalidate) our single item TransactionLogTest cache.
|
||||||
* ----------------
|
*
|
||||||
*/
|
|
||||||
if (status != XID_COMMIT)
|
if (status != XID_COMMIT)
|
||||||
|
*
|
||||||
|
* What's the hell ?! Why != XID_COMMIT ?!
|
||||||
|
*/
|
||||||
|
if (status != XID_INPROGRESS)
|
||||||
{
|
{
|
||||||
TransactionIdStore(transactionId, &cachedTestXid);
|
TransactionIdStore(transactionId, &cachedTestXid);
|
||||||
cachedTestXidStatus = status;
|
cachedTestXidStatus = status;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* This file contains support functions for the high
|
* This file contains support functions for the high
|
||||||
@ -289,18 +289,12 @@ TransBlockNumberGetXidStatus(Relation relation,
|
|||||||
XidStatus xstatus; /* recorded status of xid */
|
XidStatus xstatus; /* recorded status of xid */
|
||||||
bool localfail; /* bool used if failP = NULL */
|
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
|
* get the page containing the transaction information
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
buffer = ReadBuffer(relation, blockNumber);
|
buffer = ReadBuffer(relation, blockNumber);
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_SHARE);
|
||||||
block = BufferGetBlock(buffer);
|
block = BufferGetBlock(buffer);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
@ -318,14 +312,9 @@ TransBlockNumberGetXidStatus(Relation relation,
|
|||||||
* release the buffer and return the status
|
* release the buffer and return the status
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
ReleaseBuffer(buffer);
|
ReleaseBuffer(buffer);
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* SOMEDAY release our lock on the log relation
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
RelationUnsetLockForRead(relation);
|
|
||||||
|
|
||||||
return
|
return
|
||||||
xstatus;
|
xstatus;
|
||||||
}
|
}
|
||||||
@ -345,19 +334,12 @@ TransBlockNumberSetXidStatus(Relation relation,
|
|||||||
Block block; /* block containing xstatus */
|
Block block; /* block containing xstatus */
|
||||||
bool localfail; /* bool used if failP = NULL */
|
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
|
* get the block containing the transaction status
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
buffer = ReadBuffer(relation, blockNumber);
|
buffer = ReadBuffer(relation, blockNumber);
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
||||||
block = BufferGetBlock(buffer);
|
block = BufferGetBlock(buffer);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
@ -372,16 +354,11 @@ TransBlockNumberSetXidStatus(Relation relation,
|
|||||||
|
|
||||||
TransBlockSetXidStatus(block, xid, xstatus);
|
TransBlockSetXidStatus(block, xid, xstatus);
|
||||||
|
|
||||||
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
if ((*failP) == false)
|
if ((*failP) == false)
|
||||||
WriteBuffer(buffer);
|
WriteBuffer(buffer);
|
||||||
else
|
else
|
||||||
ReleaseBuffer(buffer);
|
ReleaseBuffer(buffer);
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* SOMEDAY release our lock on the log relation
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
RelationUnsetLockForWrite(relation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------
|
/* --------------------------------
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Transaction aborts can now occur two ways:
|
* Transaction aborts can now occur two ways:
|
||||||
@ -194,6 +194,8 @@ TransactionStateData CurrentTransactionStateData = {
|
|||||||
TransactionState CurrentTransactionState =
|
TransactionState CurrentTransactionState =
|
||||||
&CurrentTransactionStateData;
|
&CurrentTransactionStateData;
|
||||||
|
|
||||||
|
int XactIsoLevel = XACT_SERIALIZED;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* info returned when the system is disabled
|
* info returned when the system is disabled
|
||||||
*
|
*
|
||||||
@ -816,6 +818,8 @@ StartTransaction()
|
|||||||
*/
|
*/
|
||||||
GetNewTransactionId(&(s->transactionIdData));
|
GetNewTransactionId(&(s->transactionIdData));
|
||||||
|
|
||||||
|
XactLockTableInsert(s->transactionIdData);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* initialize current transaction state fields
|
* initialize current transaction state fields
|
||||||
* ----------------
|
* ----------------
|
||||||
@ -966,6 +970,7 @@ AbortTransaction()
|
|||||||
* do abort processing
|
* do abort processing
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
UnlockBuffers();
|
||||||
AtAbort_Notify();
|
AtAbort_Notify();
|
||||||
CloseSequences();
|
CloseSequences();
|
||||||
AtEOXact_portals();
|
AtEOXact_portals();
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* See acl.h.
|
* See acl.h.
|
||||||
@ -162,7 +162,7 @@ ChangeAcl(char *relname,
|
|||||||
tuple = heap_modifytuple(tuple, relation, values, nulls, replaces);
|
tuple = heap_modifytuple(tuple, relation, values, nulls, replaces);
|
||||||
/* XXX handle index on pg_class? */
|
/* XXX handle index on pg_class? */
|
||||||
setheapoverride(true);
|
setheapoverride(true);
|
||||||
heap_replace(relation, &tuple->t_self, tuple);
|
heap_replace(relation, &tuple->t_self, tuple, NULL);
|
||||||
setheapoverride(false);
|
setheapoverride(false);
|
||||||
|
|
||||||
/* keep the catalog indices up to date */
|
/* keep the catalog indices up to date */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* INTERFACE ROUTINES
|
||||||
* heap_create() - Create an uncataloged heap relation
|
* heap_create() - Create an uncataloged heap relation
|
||||||
@ -929,7 +929,7 @@ RelationRemoveInheritance(Relation relation)
|
|||||||
|
|
||||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||||
{
|
{
|
||||||
heap_delete(catalogRelation, &tuple->t_self);
|
heap_delete(catalogRelation, &tuple->t_self, NULL);
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -951,7 +951,7 @@ RelationRemoveInheritance(Relation relation)
|
|||||||
&entry);
|
&entry);
|
||||||
|
|
||||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||||
heap_delete(catalogRelation, &tuple->t_self);
|
heap_delete(catalogRelation, &tuple->t_self, NULL);
|
||||||
|
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
heap_close(catalogRelation);
|
heap_close(catalogRelation);
|
||||||
@ -1020,7 +1020,7 @@ DeletePgRelationTuple(Relation rel)
|
|||||||
* delete the relation tuple from pg_class, and finish up.
|
* 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);
|
pfree(tup);
|
||||||
|
|
||||||
heap_close(pg_class_desc);
|
heap_close(pg_class_desc);
|
||||||
@ -1048,7 +1048,7 @@ DeletePgAttributeTuples(Relation rel)
|
|||||||
* Get a write lock _before_ getting the read lock in the scan
|
* 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;
|
for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
|
||||||
attnum <= rel->rd_att->natts;
|
attnum <= rel->rd_att->natts;
|
||||||
@ -1059,7 +1059,7 @@ DeletePgAttributeTuples(Relation rel)
|
|||||||
Int16GetDatum(attnum),
|
Int16GetDatum(attnum),
|
||||||
0, 0)))
|
0, 0)))
|
||||||
{
|
{
|
||||||
heap_delete(pg_attribute_desc, &tup->t_self);
|
heap_delete(pg_attribute_desc, &tup->t_self, NULL);
|
||||||
pfree(tup);
|
pfree(tup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1068,7 +1068,7 @@ DeletePgAttributeTuples(Relation rel)
|
|||||||
* Release the write lock
|
* Release the write lock
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
RelationUnsetLockForWrite(pg_attribute_desc);
|
UnlockRelation(pg_attribute_desc, AccessExclusiveLock);
|
||||||
heap_close(pg_attribute_desc);
|
heap_close(pg_attribute_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1183,7 +1183,7 @@ DeletePgTypeTuple(Relation rel)
|
|||||||
* we release the read lock on pg_type. -mer 13 Aug 1991
|
* 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_endscan(pg_type_scan);
|
||||||
heap_close(pg_type_desc);
|
heap_close(pg_type_desc);
|
||||||
@ -1209,7 +1209,7 @@ heap_destroy_with_catalog(char *relname)
|
|||||||
if (rel == NULL)
|
if (rel == NULL)
|
||||||
elog(ERROR, "Relation %s Does Not Exist!", relname);
|
elog(ERROR, "Relation %s Does Not Exist!", relname);
|
||||||
|
|
||||||
RelationSetLockForWrite(rel);
|
LockRelation(rel, AccessExclusiveLock);
|
||||||
rid = rel->rd_id;
|
rid = rel->rd_id;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
@ -1288,7 +1288,7 @@ heap_destroy_with_catalog(char *relname)
|
|||||||
|
|
||||||
rel->rd_tmpunlinked = TRUE;
|
rel->rd_tmpunlinked = TRUE;
|
||||||
|
|
||||||
RelationUnsetLockForWrite(rel);
|
UnlockRelation(rel, AccessExclusiveLock);
|
||||||
|
|
||||||
heap_close(rel);
|
heap_close(rel);
|
||||||
|
|
||||||
@ -1608,16 +1608,16 @@ RemoveAttrDefault(Relation rel)
|
|||||||
ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
|
ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
|
||||||
F_OIDEQ, rel->rd_id);
|
F_OIDEQ, rel->rd_id);
|
||||||
|
|
||||||
RelationSetLockForWrite(adrel);
|
LockRelation(adrel, AccessExclusiveLock);
|
||||||
|
|
||||||
adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
|
adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
|
||||||
|
|
||||||
while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
|
while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
|
||||||
heap_delete(adrel, &tup->t_self);
|
heap_delete(adrel, &tup->t_self, NULL);
|
||||||
|
|
||||||
heap_endscan(adscan);
|
heap_endscan(adscan);
|
||||||
|
|
||||||
RelationUnsetLockForWrite(adrel);
|
UnlockRelation(adrel, AccessExclusiveLock);
|
||||||
heap_close(adrel);
|
heap_close(adrel);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1635,16 +1635,16 @@ RemoveRelCheck(Relation rel)
|
|||||||
ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
|
ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
|
||||||
F_OIDEQ, rel->rd_id);
|
F_OIDEQ, rel->rd_id);
|
||||||
|
|
||||||
RelationSetLockForWrite(rcrel);
|
LockRelation(rcrel, AccessExclusiveLock);
|
||||||
|
|
||||||
rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
|
rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
|
||||||
|
|
||||||
while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
|
while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
|
||||||
heap_delete(rcrel, &tup->t_self);
|
heap_delete(rcrel, &tup->t_self, NULL);
|
||||||
|
|
||||||
heap_endscan(rcscan);
|
heap_endscan(rcscan);
|
||||||
|
|
||||||
RelationUnsetLockForWrite(rcrel);
|
UnlockRelation(rcrel, AccessExclusiveLock);
|
||||||
heap_close(rcrel);
|
heap_close(rcrel);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* INTERFACE ROUTINES
|
||||||
@ -913,7 +913,7 @@ UpdateIndexPredicate(Oid indexoid, Node *oldPred, Node *predicate)
|
|||||||
|
|
||||||
newtup = heap_modifytuple(tuple, pg_index, values, nulls, replace);
|
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);
|
pfree(newtup);
|
||||||
heap_close(pg_index);
|
heap_close(pg_index);
|
||||||
@ -1039,15 +1039,11 @@ index_create(char *heapRelationName,
|
|||||||
|
|
||||||
heapRelation = heap_open(heapoid);
|
heapRelation = heap_open(heapoid);
|
||||||
|
|
||||||
/* ----------------
|
/*
|
||||||
* write lock heap to guarantee exclusive access
|
* Only SELECT ... FOR UPDATE are allowed
|
||||||
* ----------------
|
|
||||||
RelationSetLockForWrite(heapRelation);
|
|
||||||
* ^^^^^
|
|
||||||
* Does it have any sense ? - vadim 10/27/97
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
RelationSetLockForRead(heapRelation);
|
LockRelation(heapRelation, ShareLock);
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* construct new tuple descriptor
|
* construct new tuple descriptor
|
||||||
@ -1195,7 +1191,7 @@ index_destroy(Oid indexId)
|
|||||||
|
|
||||||
AssertState(HeapTupleIsValid(tuple));
|
AssertState(HeapTupleIsValid(tuple));
|
||||||
|
|
||||||
heap_delete(relationRelation, &tuple->t_self);
|
heap_delete(relationRelation, &tuple->t_self, NULL);
|
||||||
pfree(tuple);
|
pfree(tuple);
|
||||||
heap_close(relationRelation);
|
heap_close(relationRelation);
|
||||||
|
|
||||||
@ -1212,7 +1208,7 @@ index_destroy(Oid indexId)
|
|||||||
Int16GetDatum(attnum),
|
Int16GetDatum(attnum),
|
||||||
0, 0)))
|
0, 0)))
|
||||||
{
|
{
|
||||||
heap_delete(attributeRelation, &tuple->t_self);
|
heap_delete(attributeRelation, &tuple->t_self, NULL);
|
||||||
pfree(tuple);
|
pfree(tuple);
|
||||||
attnum++;
|
attnum++;
|
||||||
}
|
}
|
||||||
@ -1232,7 +1228,7 @@ index_destroy(Oid indexId)
|
|||||||
|
|
||||||
indexRelation = heap_openr(IndexRelationName);
|
indexRelation = heap_openr(IndexRelationName);
|
||||||
|
|
||||||
heap_delete(indexRelation, &tuple->t_self);
|
heap_delete(indexRelation, &tuple->t_self, NULL);
|
||||||
pfree(tuple);
|
pfree(tuple);
|
||||||
heap_close(indexRelation);
|
heap_close(indexRelation);
|
||||||
|
|
||||||
@ -1424,7 +1420,7 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
|||||||
values[Anum_pg_class_relhasindex - 1] = CharGetDatum(hasindex);
|
values[Anum_pg_class_relhasindex - 1] = CharGetDatum(hasindex);
|
||||||
|
|
||||||
newtup = heap_modifytuple(tuple, pg_class, values, nulls, replace);
|
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);
|
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
|
||||||
CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, newtup);
|
CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class, newtup);
|
||||||
CatalogCloseIndices(Num_pg_class_indices, idescs);
|
CatalogCloseIndices(Num_pg_class_indices, idescs);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* these routines moved here from commands/define.c and somewhat cleaned up.
|
* these routines moved here from commands/define.c and somewhat cleaned up.
|
||||||
@ -711,7 +711,7 @@ OperatorDef(char *operatorName,
|
|||||||
replaces);
|
replaces);
|
||||||
|
|
||||||
setheapoverride(true);
|
setheapoverride(true);
|
||||||
heap_replace(pg_operator_desc, &tup->t_self, tup);
|
heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
|
||||||
setheapoverride(false);
|
setheapoverride(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -830,7 +830,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
|
|||||||
replaces);
|
replaces);
|
||||||
|
|
||||||
setheapoverride(true);
|
setheapoverride(true);
|
||||||
heap_replace(pg_operator_desc, &tup->t_self, tup);
|
heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
|
||||||
setheapoverride(false);
|
setheapoverride(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -855,7 +855,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
|
|||||||
replaces);
|
replaces);
|
||||||
|
|
||||||
setheapoverride(true);
|
setheapoverride(true);
|
||||||
heap_replace(pg_operator_desc, &tup->t_self, tup);
|
heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
|
||||||
setheapoverride(false);
|
setheapoverride(false);
|
||||||
|
|
||||||
values[Anum_pg_operator_oprcom - 1] = (Datum) NULL;
|
values[Anum_pg_operator_oprcom - 1] = (Datum) NULL;
|
||||||
@ -884,7 +884,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
|
|||||||
replaces);
|
replaces);
|
||||||
|
|
||||||
setheapoverride(true);
|
setheapoverride(true);
|
||||||
heap_replace(pg_operator_desc, &tup->t_self, tup);
|
heap_replace(pg_operator_desc, &tup->t_self, tup, NULL);
|
||||||
setheapoverride(false);
|
setheapoverride(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* when the heap_insert() or heap_replace() is called.
|
||||||
* -----------------
|
* -----------------
|
||||||
*/
|
*/
|
||||||
RelationSetLockForWrite(pg_type_desc);
|
LockRelation(pg_type_desc, AccessExclusiveLock);
|
||||||
|
|
||||||
typeKey[0].sk_argument = PointerGetDatum(typeName);
|
typeKey[0].sk_argument = PointerGetDatum(typeName);
|
||||||
pg_type_scan = heap_beginscan(pg_type_desc,
|
pg_type_scan = heap_beginscan(pg_type_desc,
|
||||||
@ -484,7 +484,7 @@ TypeCreate(char *typeName,
|
|||||||
replaces);
|
replaces);
|
||||||
|
|
||||||
setheapoverride(true);
|
setheapoverride(true);
|
||||||
heap_replace(pg_type_desc, &tup->t_self, tup);
|
heap_replace(pg_type_desc, &tup->t_self, tup, NULL);
|
||||||
setheapoverride(false);
|
setheapoverride(false);
|
||||||
|
|
||||||
typeObjectId = tup->t_data->t_oid;
|
typeObjectId = tup->t_data->t_oid;
|
||||||
@ -516,7 +516,7 @@ TypeCreate(char *typeName,
|
|||||||
CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup);
|
CatalogIndexInsert(idescs, Num_pg_type_indices, pg_type_desc, tup);
|
||||||
CatalogCloseIndices(Num_pg_type_indices, idescs);
|
CatalogCloseIndices(Num_pg_type_indices, idescs);
|
||||||
}
|
}
|
||||||
RelationUnsetLockForWrite(pg_type_desc);
|
UnlockRelation(pg_type_desc, AccessExclusiveLock);
|
||||||
heap_close(pg_type_desc);
|
heap_close(pg_type_desc);
|
||||||
|
|
||||||
return typeObjectId;
|
return typeObjectId;
|
||||||
@ -561,7 +561,7 @@ TypeRename(char *oldTypeName, char *newTypeName)
|
|||||||
namestrcpy(&(((Form_pg_type) GETSTRUCT(oldtup))->typname), newTypeName);
|
namestrcpy(&(((Form_pg_type) GETSTRUCT(oldtup))->typname), newTypeName);
|
||||||
|
|
||||||
setheapoverride(true);
|
setheapoverride(true);
|
||||||
heap_replace(pg_type_desc, &oldtup->t_self, oldtup);
|
heap_replace(pg_type_desc, &oldtup->t_self, oldtup, NULL);
|
||||||
setheapoverride(false);
|
setheapoverride(false);
|
||||||
|
|
||||||
/* update the system catalog indices */
|
/* update the system catalog indices */
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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);
|
TPRINTF(TRACE_NOTIFY, "Async_Listen: %s", relname);
|
||||||
|
|
||||||
lRel = heap_openr(ListenerRelationName);
|
lRel = heap_openr(ListenerRelationName);
|
||||||
RelationSetLockForWrite(lRel);
|
LockRelation(lRel, AccessExclusiveLock);
|
||||||
tdesc = RelationGetDescr(lRel);
|
tdesc = RelationGetDescr(lRel);
|
||||||
|
|
||||||
/* Detect whether we are already listening on this relname */
|
/* Detect whether we are already listening on this relname */
|
||||||
@ -242,7 +242,7 @@ Async_Listen(char *relname, int pid)
|
|||||||
if (alreadyListener)
|
if (alreadyListener)
|
||||||
{
|
{
|
||||||
elog(NOTICE, "Async_Listen: We are already listening on %s", relname);
|
elog(NOTICE, "Async_Listen: We are already listening on %s", relname);
|
||||||
RelationUnsetLockForWrite(lRel);
|
UnlockRelation(lRel, AccessExclusiveLock);
|
||||||
heap_close(lRel);
|
heap_close(lRel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -267,7 +267,7 @@ Async_Listen(char *relname, int pid)
|
|||||||
heap_insert(lRel, newtup);
|
heap_insert(lRel, newtup);
|
||||||
pfree(newtup);
|
pfree(newtup);
|
||||||
|
|
||||||
RelationUnsetLockForWrite(lRel);
|
UnlockRelation(lRel, AccessExclusiveLock);
|
||||||
heap_close(lRel);
|
heap_close(lRel);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -320,9 +320,9 @@ Async_Unlisten(char *relname, int pid)
|
|||||||
if (lTuple != NULL)
|
if (lTuple != NULL)
|
||||||
{
|
{
|
||||||
lRel = heap_openr(ListenerRelationName);
|
lRel = heap_openr(ListenerRelationName);
|
||||||
RelationSetLockForWrite(lRel);
|
LockRelation(lRel, AccessExclusiveLock);
|
||||||
heap_delete(lRel, &lTuple->t_self);
|
heap_delete(lRel, &lTuple->t_self, NULL);
|
||||||
RelationUnsetLockForWrite(lRel);
|
UnlockRelation(lRel, AccessExclusiveLock);
|
||||||
heap_close(lRel);
|
heap_close(lRel);
|
||||||
}
|
}
|
||||||
/* We do not complain about unlistening something not being listened;
|
/* We do not complain about unlistening something not being listened;
|
||||||
@ -358,7 +358,7 @@ Async_UnlistenAll()
|
|||||||
TPRINTF(TRACE_NOTIFY, "Async_UnlistenAll");
|
TPRINTF(TRACE_NOTIFY, "Async_UnlistenAll");
|
||||||
|
|
||||||
lRel = heap_openr(ListenerRelationName);
|
lRel = heap_openr(ListenerRelationName);
|
||||||
RelationSetLockForWrite(lRel);
|
LockRelation(lRel, AccessExclusiveLock);
|
||||||
tdesc = RelationGetDescr(lRel);
|
tdesc = RelationGetDescr(lRel);
|
||||||
|
|
||||||
/* Find and delete all entries with my listenerPID */
|
/* Find and delete all entries with my listenerPID */
|
||||||
@ -369,10 +369,10 @@ Async_UnlistenAll()
|
|||||||
sRel = heap_beginscan(lRel, 0, SnapshotNow, 1, key);
|
sRel = heap_beginscan(lRel, 0, SnapshotNow, 1, key);
|
||||||
|
|
||||||
while (HeapTupleIsValid(lTuple = heap_getnext(sRel, 0)))
|
while (HeapTupleIsValid(lTuple = heap_getnext(sRel, 0)))
|
||||||
heap_delete(lRel, &lTuple->t_self);
|
heap_delete(lRel, &lTuple->t_self, NULL);
|
||||||
|
|
||||||
heap_endscan(sRel);
|
heap_endscan(sRel);
|
||||||
RelationUnsetLockForWrite(lRel);
|
UnlockRelation(lRel, AccessExclusiveLock);
|
||||||
heap_close(lRel);
|
heap_close(lRel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,7 +463,7 @@ AtCommit_Notify()
|
|||||||
TPRINTF(TRACE_NOTIFY, "AtCommit_Notify");
|
TPRINTF(TRACE_NOTIFY, "AtCommit_Notify");
|
||||||
|
|
||||||
lRel = heap_openr(ListenerRelationName);
|
lRel = heap_openr(ListenerRelationName);
|
||||||
RelationSetLockForWrite(lRel);
|
LockRelation(lRel, AccessExclusiveLock);
|
||||||
tdesc = RelationGetDescr(lRel);
|
tdesc = RelationGetDescr(lRel);
|
||||||
sRel = heap_beginscan(lRel, 0, SnapshotNow, 0, (ScanKey) NULL);
|
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
|
* but as far as I can see we should just do it for any
|
||||||
* failure (certainly at least for EPERM too...)
|
* failure (certainly at least for EPERM too...)
|
||||||
*/
|
*/
|
||||||
heap_delete(lRel, &lTuple->t_self);
|
heap_delete(lRel, &lTuple->t_self, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -527,7 +527,7 @@ AtCommit_Notify()
|
|||||||
{
|
{
|
||||||
rTuple = heap_modifytuple(lTuple, lRel,
|
rTuple = heap_modifytuple(lTuple, lRel,
|
||||||
value, nulls, repl);
|
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();
|
StartTransactionCommand();
|
||||||
|
|
||||||
lRel = heap_openr(ListenerRelationName);
|
lRel = heap_openr(ListenerRelationName);
|
||||||
RelationSetLockForWrite(lRel);
|
LockRelation(lRel, AccessExclusiveLock);
|
||||||
tdesc = RelationGetDescr(lRel);
|
tdesc = RelationGetDescr(lRel);
|
||||||
|
|
||||||
/* Scan only entries with my listenerPID */
|
/* Scan only entries with my listenerPID */
|
||||||
@ -772,7 +772,7 @@ ProcessIncomingNotify(void)
|
|||||||
NotifyMyFrontEnd(relname, sourcePID);
|
NotifyMyFrontEnd(relname, sourcePID);
|
||||||
/* Rewrite the tuple with 0 in notification column */
|
/* Rewrite the tuple with 0 in notification column */
|
||||||
rTuple = heap_modifytuple(lTuple, lRel, value, nulls, repl);
|
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);
|
heap_endscan(sRel);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* The PortalExecutorHeapMemory crap needs to be eliminated
|
* The PortalExecutorHeapMemory crap needs to be eliminated
|
||||||
@ -482,7 +482,7 @@ PerformAddAttribute(char *relationName,
|
|||||||
heap_close(attrdesc);
|
heap_close(attrdesc);
|
||||||
|
|
||||||
((Form_pg_class) GETSTRUCT(reltup))->relnatts = maxatts;
|
((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 */
|
/* keep catalog indices current */
|
||||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
|
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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(typmod);
|
||||||
}
|
}
|
||||||
pfree(byval);
|
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);
|
heap_close(rel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -914,7 +928,14 @@ GetIndexRelations(Oid main_relation_oid,
|
|||||||
*index_rels = (Relation *) palloc(*n_indices * sizeof(Relation));
|
*index_rels = (Relation *) palloc(*n_indices * sizeof(Relation));
|
||||||
|
|
||||||
for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next)
|
for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next)
|
||||||
|
{
|
||||||
(*index_rels)[i] = index_open(scan->index_rel_oid);
|
(*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++)
|
for (i = 0, scan = head; i < *n_indices + 1; i++)
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* delays when multiple 'createdb's or 'destroydb's are run simult.
|
||||||
* -mer 7/3/91
|
* -mer 7/3/91
|
||||||
*/
|
*/
|
||||||
RelationSetLockForWrite(dbrel);
|
LockRelation(dbrel, AccessExclusiveLock);
|
||||||
dbtup = get_pg_dbtup(command, dbname, dbrel);
|
dbtup = get_pg_dbtup(command, dbname, dbrel);
|
||||||
dbfound = HeapTupleIsValid(dbtup);
|
dbfound = HeapTupleIsValid(dbtup);
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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);
|
heapRelation = heap_open(relationId);
|
||||||
indexRelation = index_open(indexId);
|
indexRelation = index_open(indexId);
|
||||||
|
|
||||||
RelationSetLockForWrite(heapRelation);
|
LockRelation(heapRelation, ShareLock);
|
||||||
|
|
||||||
InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId);
|
InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId);
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ DropProceduralLanguage(DropPLangStmt *stmt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rel = heap_openr(LanguageRelationName);
|
rel = heap_openr(LanguageRelationName);
|
||||||
heap_delete(rel, &langTup->t_self);
|
heap_delete(rel, &langTup->t_self, NULL);
|
||||||
|
|
||||||
pfree(langTup);
|
pfree(langTup);
|
||||||
heap_close(rel);
|
heap_close(rel);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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",
|
elog(ERROR, "RemoveOperator: operator '%s': permission denied",
|
||||||
operatorName);
|
operatorName);
|
||||||
#endif
|
#endif
|
||||||
heap_delete(relation, &tup->t_self);
|
heap_delete(relation, &tup->t_self, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -157,7 +157,7 @@ SingleOpOperatorRemove(Oid typeOid)
|
|||||||
key[0].sk_attno = attnums[i];
|
key[0].sk_attno = attnums[i];
|
||||||
scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
|
scan = heap_beginscan(rel, 0, SnapshotNow, 1, key);
|
||||||
while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
|
while (HeapTupleIsValid(tup = heap_getnext(scan, 0)))
|
||||||
heap_delete(rel, &tup->t_self);
|
heap_delete(rel, &tup->t_self, NULL);
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
}
|
}
|
||||||
heap_close(rel);
|
heap_close(rel);
|
||||||
@ -268,7 +268,7 @@ RemoveType(char *typeName) /* type name to be removed */
|
|||||||
|
|
||||||
relation = heap_openr(TypeRelationName);
|
relation = heap_openr(TypeRelationName);
|
||||||
typeOid = tup->t_data->t_oid;
|
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 */
|
/* Now, Delete the "array of" that type */
|
||||||
shadow_type = makeArrayTypeName(typeName);
|
shadow_type = makeArrayTypeName(typeName);
|
||||||
@ -282,7 +282,7 @@ RemoveType(char *typeName) /* type name to be removed */
|
|||||||
}
|
}
|
||||||
|
|
||||||
typeOid = tup->t_data->t_oid;
|
typeOid = tup->t_data->t_oid;
|
||||||
heap_delete(relation, &tup->t_self);
|
heap_delete(relation, &tup->t_self, NULL);
|
||||||
|
|
||||||
heap_close(relation);
|
heap_close(relation);
|
||||||
}
|
}
|
||||||
@ -357,7 +357,7 @@ RemoveFunction(char *functionName, /* function name to be removed */
|
|||||||
elog(ERROR, "RemoveFunction: function \"%s\" is built-in", functionName);
|
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);
|
heap_close(relation);
|
||||||
}
|
}
|
||||||
@ -428,7 +428,7 @@ RemoveAggregate(char *aggName, char *aggType)
|
|||||||
aggName);
|
aggName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
heap_delete(relation, &tup->t_self);
|
heap_delete(relation, &tup->t_self, NULL);
|
||||||
|
|
||||||
heap_close(relation);
|
heap_close(relation);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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);
|
newattname, NAMEDATALEN);
|
||||||
|
|
||||||
attrelation = heap_openr(AttributeRelationName);
|
attrelation = heap_openr(AttributeRelationName);
|
||||||
heap_replace(attrelation, &oldatttup->t_self, oldatttup);
|
heap_replace(attrelation, &oldatttup->t_self, oldatttup, NULL);
|
||||||
|
|
||||||
/* keep system catalog indices current */
|
/* keep system catalog indices current */
|
||||||
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, irelations);
|
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, irelations);
|
||||||
@ -248,7 +248,7 @@ renamerel(char *oldrelname, char *newrelname)
|
|||||||
|
|
||||||
/* insert fixed rel tuple */
|
/* insert fixed rel tuple */
|
||||||
relrelation = heap_openr(RelationRelationName);
|
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 */
|
/* keep the system catalog indices current */
|
||||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations);
|
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations);
|
||||||
|
@ -162,7 +162,7 @@ DefineSequence(CreateSeqStmt *seq)
|
|||||||
rel = heap_openr(seq->seqname);
|
rel = heap_openr(seq->seqname);
|
||||||
Assert(RelationIsValid(rel));
|
Assert(RelationIsValid(rel));
|
||||||
|
|
||||||
RelationSetLockForWrite(rel);
|
LockRelation(rel, AccessExclusiveLock);
|
||||||
|
|
||||||
tupDesc = RelationGetDescr(rel);
|
tupDesc = RelationGetDescr(rel);
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ DefineSequence(CreateSeqStmt *seq)
|
|||||||
if (WriteBuffer(buf) == STATUS_ERROR)
|
if (WriteBuffer(buf) == STATUS_ERROR)
|
||||||
elog(ERROR, "DefineSequence: WriteBuffer failed");
|
elog(ERROR, "DefineSequence: WriteBuffer failed");
|
||||||
|
|
||||||
RelationUnsetLockForWrite(rel);
|
UnlockRelation(rel, AccessExclusiveLock);
|
||||||
heap_close(rel);
|
heap_close(rel);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -200,7 +200,6 @@ nextval(struct varlena * seqin)
|
|||||||
SeqTable elm;
|
SeqTable elm;
|
||||||
Buffer buf;
|
Buffer buf;
|
||||||
Form_pg_sequence seq;
|
Form_pg_sequence seq;
|
||||||
ItemPointerData iptr;
|
|
||||||
int4 incby,
|
int4 incby,
|
||||||
maxv,
|
maxv,
|
||||||
minv,
|
minv,
|
||||||
@ -209,7 +208,7 @@ nextval(struct varlena * seqin)
|
|||||||
next,
|
next,
|
||||||
rescnt = 0;
|
rescnt = 0;
|
||||||
|
|
||||||
/* open and WIntentLock sequence */
|
/* open and AccessShareLock sequence */
|
||||||
elm = init_sequence("nextval", seqname);
|
elm = init_sequence("nextval", seqname);
|
||||||
pfree(seqname);
|
pfree(seqname);
|
||||||
|
|
||||||
@ -219,7 +218,7 @@ nextval(struct varlena * seqin)
|
|||||||
return elm->last;
|
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 */
|
* tuple */
|
||||||
|
|
||||||
next = result = seq->last_value;
|
next = result = seq->last_value;
|
||||||
@ -282,12 +281,11 @@ nextval(struct varlena * seqin)
|
|||||||
seq->last_value = next; /* last fetched number */
|
seq->last_value = next; /* last fetched number */
|
||||||
seq->is_called = 't';
|
seq->is_called = 't';
|
||||||
|
|
||||||
|
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
||||||
|
|
||||||
if (WriteBuffer(buf) == STATUS_ERROR)
|
if (WriteBuffer(buf) == STATUS_ERROR)
|
||||||
elog(ERROR, "%s.nextval: WriteBuffer failed", elm->name);
|
elog(ERROR, "%s.nextval: WriteBuffer failed", elm->name);
|
||||||
|
|
||||||
ItemPointerSet(&iptr, 0, FirstOffsetNumber);
|
|
||||||
RelationUnsetSingleWLockPage(elm->rel, &iptr);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -300,7 +298,7 @@ currval(struct varlena * seqin)
|
|||||||
SeqTable elm;
|
SeqTable elm;
|
||||||
int4 result;
|
int4 result;
|
||||||
|
|
||||||
/* open and WIntentLock sequence */
|
/* open and AccessShareLock sequence */
|
||||||
elm = init_sequence("currval", seqname);
|
elm = init_sequence("currval", seqname);
|
||||||
pfree(seqname);
|
pfree(seqname);
|
||||||
|
|
||||||
@ -320,7 +318,6 @@ setval(struct varlena * seqin, int4 next)
|
|||||||
SeqTable elm;
|
SeqTable elm;
|
||||||
Buffer buf;
|
Buffer buf;
|
||||||
Form_pg_sequence seq;
|
Form_pg_sequence seq;
|
||||||
ItemPointerData iptr;
|
|
||||||
|
|
||||||
#ifndef NO_SECURITY
|
#ifndef NO_SECURITY
|
||||||
if (pg_aclcheck(seqname, getpgusername(), ACL_WR) != ACLCHECK_OK)
|
if (pg_aclcheck(seqname, getpgusername(), ACL_WR) != ACLCHECK_OK)
|
||||||
@ -328,9 +325,9 @@ setval(struct varlena * seqin, int4 next)
|
|||||||
seqname, seqname);
|
seqname, seqname);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* open and WIntentLock sequence */
|
/* open and AccessShareLock sequence */
|
||||||
elm = init_sequence("setval", seqname);
|
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 */
|
* tuple */
|
||||||
|
|
||||||
if (seq->cache_value != 1)
|
if (seq->cache_value != 1)
|
||||||
@ -353,27 +350,22 @@ setval(struct varlena * seqin, int4 next)
|
|||||||
seq->last_value = next; /* last fetched number */
|
seq->last_value = next; /* last fetched number */
|
||||||
seq->is_called = 't';
|
seq->is_called = 't';
|
||||||
|
|
||||||
|
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
|
||||||
|
|
||||||
if (WriteBuffer(buf) == STATUS_ERROR)
|
if (WriteBuffer(buf) == STATUS_ERROR)
|
||||||
elog(ERROR, "%s.settval: WriteBuffer failed", seqname);
|
elog(ERROR, "%s.settval: WriteBuffer failed", seqname);
|
||||||
|
|
||||||
ItemPointerSet(&iptr, 0, FirstOffsetNumber);
|
|
||||||
RelationUnsetSingleWLockPage(elm->rel, &iptr);
|
|
||||||
|
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Form_pg_sequence
|
static Form_pg_sequence
|
||||||
read_info(char *caller, SeqTable elm, Buffer *buf)
|
read_info(char *caller, SeqTable elm, Buffer *buf)
|
||||||
{
|
{
|
||||||
ItemPointerData iptr;
|
PageHeader page;
|
||||||
PageHeader page;
|
ItemId lp;
|
||||||
ItemId lp;
|
|
||||||
HeapTupleData tuple;
|
HeapTupleData tuple;
|
||||||
sequence_magic *sm;
|
sequence_magic *sm;
|
||||||
Form_pg_sequence seq;
|
Form_pg_sequence seq;
|
||||||
|
|
||||||
ItemPointerSet(&iptr, 0, FirstOffsetNumber);
|
|
||||||
RelationSetSingleWLockPage(elm->rel, &iptr);
|
|
||||||
|
|
||||||
if (RelationGetNumberOfBlocks(elm->rel) != 1)
|
if (RelationGetNumberOfBlocks(elm->rel) != 1)
|
||||||
elog(ERROR, "%s.%s: invalid number of blocks in sequence",
|
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))
|
if (!BufferIsValid(*buf))
|
||||||
elog(ERROR, "%s.%s: ReadBuffer failed", elm->name, caller);
|
elog(ERROR, "%s.%s: ReadBuffer failed", elm->name, caller);
|
||||||
|
|
||||||
|
LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);
|
||||||
|
|
||||||
page = (PageHeader) BufferGetPage(*buf);
|
page = (PageHeader) BufferGetPage(*buf);
|
||||||
sm = (sequence_magic *) PageGetSpecialPointer(page);
|
sm = (sequence_magic *) PageGetSpecialPointer(page);
|
||||||
|
|
||||||
@ -439,7 +433,7 @@ init_sequence(char *caller, char *name)
|
|||||||
if (!RelationIsValid(temp->rel))
|
if (!RelationIsValid(temp->rel))
|
||||||
elog(ERROR, "%s.%s: sequence does not exist", name, caller);
|
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)
|
if (temp->rel->rd_rel->relkind != RELKIND_SEQUENCE)
|
||||||
elog(ERROR, "%s.%s: %s is not sequence !", name, caller, name);
|
elog(ERROR, "%s.%s: %s is not sequence !", name, caller, name);
|
||||||
@ -485,7 +479,7 @@ CloseSequences(void)
|
|||||||
{
|
{
|
||||||
rel = elm->rel;
|
rel = elm->rel;
|
||||||
elm->rel = (Relation) NULL;
|
elm->rel = (Relation) NULL;
|
||||||
RelationUnsetWIntentLock(rel);
|
UnlockRelation(rel, AccessShareLock);
|
||||||
heap_close(rel);
|
heap_close(rel);
|
||||||
}
|
}
|
||||||
elm = elm->next;
|
elm = elm->next;
|
||||||
|
@ -40,7 +40,7 @@ void RelationBuildTriggers(Relation relation);
|
|||||||
void FreeTriggerDesc(Relation relation);
|
void FreeTriggerDesc(Relation relation);
|
||||||
|
|
||||||
static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
|
static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
|
||||||
static HeapTuple GetTupleForTrigger(Relation relation, ItemPointer tid,
|
static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid,
|
||||||
bool before);
|
bool before);
|
||||||
|
|
||||||
extern GlobalMemory CacheCxt;
|
extern GlobalMemory CacheCxt;
|
||||||
@ -77,7 +77,7 @@ CreateTrigger(CreateTrigStmt *stmt)
|
|||||||
if (!RelationIsValid(rel))
|
if (!RelationIsValid(rel))
|
||||||
elog(ERROR, "CreateTrigger: there is no relation %s", stmt->relname);
|
elog(ERROR, "CreateTrigger: there is no relation %s", stmt->relname);
|
||||||
|
|
||||||
RelationSetLockForWrite(rel);
|
LockRelation(rel, AccessExclusiveLock);
|
||||||
|
|
||||||
TRIGGER_CLEAR_TYPE(tgtype);
|
TRIGGER_CLEAR_TYPE(tgtype);
|
||||||
if (stmt->before)
|
if (stmt->before)
|
||||||
@ -114,7 +114,7 @@ CreateTrigger(CreateTrigStmt *stmt)
|
|||||||
|
|
||||||
/* Scan pg_trigger */
|
/* Scan pg_trigger */
|
||||||
tgrel = heap_openr(TriggerRelationName);
|
tgrel = heap_openr(TriggerRelationName);
|
||||||
RelationSetLockForWrite(tgrel);
|
LockRelation(tgrel, AccessExclusiveLock);
|
||||||
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
|
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
|
||||||
F_OIDEQ, RelationGetRelid(rel));
|
F_OIDEQ, RelationGetRelid(rel));
|
||||||
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
|
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
|
||||||
@ -211,7 +211,7 @@ CreateTrigger(CreateTrigStmt *stmt)
|
|||||||
CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
|
CatalogIndexInsert(idescs, Num_pg_trigger_indices, tgrel, tuple);
|
||||||
CatalogCloseIndices(Num_pg_trigger_indices, idescs);
|
CatalogCloseIndices(Num_pg_trigger_indices, idescs);
|
||||||
pfree(tuple);
|
pfree(tuple);
|
||||||
RelationUnsetLockForWrite(tgrel);
|
UnlockRelation(tgrel, AccessExclusiveLock);
|
||||||
heap_close(tgrel);
|
heap_close(tgrel);
|
||||||
|
|
||||||
pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
|
pfree(DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
|
||||||
@ -227,7 +227,7 @@ CreateTrigger(CreateTrigStmt *stmt)
|
|||||||
pgrel = heap_openr(RelationRelationName);
|
pgrel = heap_openr(RelationRelationName);
|
||||||
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
|
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
|
||||||
RelationInvalidateHeapTuple(pgrel, tuple);
|
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);
|
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
|
||||||
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
|
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
|
||||||
CatalogCloseIndices(Num_pg_class_indices, ridescs);
|
CatalogCloseIndices(Num_pg_class_indices, ridescs);
|
||||||
@ -267,10 +267,10 @@ DropTrigger(DropTrigStmt *stmt)
|
|||||||
if (!RelationIsValid(rel))
|
if (!RelationIsValid(rel))
|
||||||
elog(ERROR, "DropTrigger: there is no relation %s", stmt->relname);
|
elog(ERROR, "DropTrigger: there is no relation %s", stmt->relname);
|
||||||
|
|
||||||
RelationSetLockForWrite(rel);
|
LockRelation(rel, AccessExclusiveLock);
|
||||||
|
|
||||||
tgrel = heap_openr(TriggerRelationName);
|
tgrel = heap_openr(TriggerRelationName);
|
||||||
RelationSetLockForWrite(tgrel);
|
LockRelation(tgrel, AccessExclusiveLock);
|
||||||
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
|
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
|
||||||
F_OIDEQ, RelationGetRelid(rel));
|
F_OIDEQ, RelationGetRelid(rel));
|
||||||
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
|
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
|
||||||
@ -280,7 +280,7 @@ DropTrigger(DropTrigStmt *stmt)
|
|||||||
|
|
||||||
if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
|
if (namestrcmp(&(pg_trigger->tgname), stmt->trigname) == 0)
|
||||||
{
|
{
|
||||||
heap_delete(tgrel, &tuple->t_self);
|
heap_delete(tgrel, &tuple->t_self, NULL);
|
||||||
tgfound++;
|
tgfound++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -293,7 +293,7 @@ DropTrigger(DropTrigStmt *stmt)
|
|||||||
elog(NOTICE, "DropTrigger: found (and deleted) %d trigger %s on relation %s",
|
elog(NOTICE, "DropTrigger: found (and deleted) %d trigger %s on relation %s",
|
||||||
tgfound, stmt->trigname, stmt->relname);
|
tgfound, stmt->trigname, stmt->relname);
|
||||||
heap_endscan(tgscan);
|
heap_endscan(tgscan);
|
||||||
RelationUnsetLockForWrite(tgrel);
|
UnlockRelation(tgrel, AccessExclusiveLock);
|
||||||
heap_close(tgrel);
|
heap_close(tgrel);
|
||||||
|
|
||||||
tuple = SearchSysCacheTupleCopy(RELNAME,
|
tuple = SearchSysCacheTupleCopy(RELNAME,
|
||||||
@ -306,7 +306,7 @@ DropTrigger(DropTrigStmt *stmt)
|
|||||||
pgrel = heap_openr(RelationRelationName);
|
pgrel = heap_openr(RelationRelationName);
|
||||||
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
|
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
|
||||||
RelationInvalidateHeapTuple(pgrel, tuple);
|
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);
|
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
|
||||||
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
|
CatalogIndexInsert(ridescs, Num_pg_class_indices, pgrel, tuple);
|
||||||
CatalogCloseIndices(Num_pg_class_indices, ridescs);
|
CatalogCloseIndices(Num_pg_class_indices, ridescs);
|
||||||
@ -333,17 +333,17 @@ RelationRemoveTriggers(Relation rel)
|
|||||||
HeapTuple tup;
|
HeapTuple tup;
|
||||||
|
|
||||||
tgrel = heap_openr(TriggerRelationName);
|
tgrel = heap_openr(TriggerRelationName);
|
||||||
RelationSetLockForWrite(tgrel);
|
LockRelation(tgrel, AccessExclusiveLock);
|
||||||
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
|
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
|
||||||
F_OIDEQ, RelationGetRelid(rel));
|
F_OIDEQ, RelationGetRelid(rel));
|
||||||
|
|
||||||
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
|
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
|
||||||
|
|
||||||
while (HeapTupleIsValid(tup = heap_getnext(tgscan, 0)))
|
while (HeapTupleIsValid(tup = heap_getnext(tgscan, 0)))
|
||||||
heap_delete(tgrel, &tup->t_self);
|
heap_delete(tgrel, &tup->t_self, NULL);
|
||||||
|
|
||||||
heap_endscan(tgscan);
|
heap_endscan(tgscan);
|
||||||
RelationUnsetLockForWrite(tgrel);
|
UnlockRelation(tgrel, AccessExclusiveLock);
|
||||||
heap_close(tgrel);
|
heap_close(tgrel);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -376,7 +376,6 @@ RelationBuildTriggers(Relation relation)
|
|||||||
ObjectIdGetDatum(RelationGetRelid(relation)));
|
ObjectIdGetDatum(RelationGetRelid(relation)));
|
||||||
|
|
||||||
tgrel = heap_openr(TriggerRelationName);
|
tgrel = heap_openr(TriggerRelationName);
|
||||||
RelationSetLockForRead(tgrel);
|
|
||||||
irel = index_openr(TriggerRelidIndex);
|
irel = index_openr(TriggerRelidIndex);
|
||||||
sd = index_beginscan(irel, false, 1, &skey);
|
sd = index_beginscan(irel, false, 1, &skey);
|
||||||
|
|
||||||
@ -450,7 +449,6 @@ RelationBuildTriggers(Relation relation)
|
|||||||
index_endscan(sd);
|
index_endscan(sd);
|
||||||
pfree(sd);
|
pfree(sd);
|
||||||
index_close(irel);
|
index_close(irel);
|
||||||
RelationUnsetLockForRead(tgrel);
|
|
||||||
heap_close(tgrel);
|
heap_close(tgrel);
|
||||||
|
|
||||||
/* Build trigdesc */
|
/* Build trigdesc */
|
||||||
@ -657,16 +655,17 @@ ExecARInsertTriggers(Relation rel, HeapTuple trigtuple)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ExecBRDeleteTriggers(Relation rel, ItemPointer tupleid)
|
ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
|
||||||
{
|
{
|
||||||
TriggerData *SaveTriggerData;
|
Relation rel = estate->es_result_relation_info->ri_RelationDesc;
|
||||||
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
|
TriggerData *SaveTriggerData;
|
||||||
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
|
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
|
||||||
HeapTuple trigtuple;
|
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
|
||||||
HeapTuple newtuple = NULL;
|
HeapTuple trigtuple;
|
||||||
int i;
|
HeapTuple newtuple = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
trigtuple = GetTupleForTrigger(rel, tupleid, true);
|
trigtuple = GetTupleForTrigger(estate, tupleid, true);
|
||||||
if (trigtuple == NULL)
|
if (trigtuple == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -692,15 +691,16 @@ ExecBRDeleteTriggers(Relation rel, ItemPointer tupleid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ExecARDeleteTriggers(Relation rel, ItemPointer tupleid)
|
ExecARDeleteTriggers(EState *estate, ItemPointer tupleid)
|
||||||
{
|
{
|
||||||
|
Relation rel = estate->es_result_relation_info->ri_RelationDesc;
|
||||||
TriggerData *SaveTriggerData;
|
TriggerData *SaveTriggerData;
|
||||||
int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE];
|
int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE];
|
||||||
Trigger **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_DELETE];
|
Trigger **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_DELETE];
|
||||||
HeapTuple trigtuple;
|
HeapTuple trigtuple;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
trigtuple = GetTupleForTrigger(rel, tupleid, false);
|
trigtuple = GetTupleForTrigger(estate, tupleid, false);
|
||||||
Assert(trigtuple != NULL);
|
Assert(trigtuple != NULL);
|
||||||
|
|
||||||
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
|
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
|
||||||
@ -722,17 +722,18 @@ ExecARDeleteTriggers(Relation rel, ItemPointer tupleid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
HeapTuple
|
HeapTuple
|
||||||
ExecBRUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
|
ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
|
||||||
{
|
{
|
||||||
TriggerData *SaveTriggerData;
|
Relation rel = estate->es_result_relation_info->ri_RelationDesc;
|
||||||
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
|
TriggerData *SaveTriggerData;
|
||||||
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
|
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
|
||||||
HeapTuple trigtuple;
|
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
|
||||||
HeapTuple oldtuple;
|
HeapTuple trigtuple;
|
||||||
HeapTuple intuple = newtuple;
|
HeapTuple oldtuple;
|
||||||
int i;
|
HeapTuple intuple = newtuple;
|
||||||
|
int i;
|
||||||
|
|
||||||
trigtuple = GetTupleForTrigger(rel, tupleid, true);
|
trigtuple = GetTupleForTrigger(estate, tupleid, true);
|
||||||
if (trigtuple == NULL)
|
if (trigtuple == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -759,15 +760,16 @@ ExecBRUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
TriggerData *SaveTriggerData;
|
||||||
int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE];
|
int ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE];
|
||||||
Trigger **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_UPDATE];
|
Trigger **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_UPDATE];
|
||||||
HeapTuple trigtuple;
|
HeapTuple trigtuple;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
trigtuple = GetTupleForTrigger(rel, tupleid, false);
|
trigtuple = GetTupleForTrigger(estate, tupleid, false);
|
||||||
Assert(trigtuple != NULL);
|
Assert(trigtuple != NULL);
|
||||||
|
|
||||||
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
|
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
|
||||||
@ -789,48 +791,67 @@ ExecARUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static HeapTuple
|
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;
|
HeapTupleData tuple;
|
||||||
HeapTuple result;
|
HeapTuple result;
|
||||||
PageHeader dp;
|
Buffer buffer;
|
||||||
Buffer b;
|
|
||||||
|
|
||||||
b = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
|
|
||||||
|
|
||||||
if (!BufferIsValid(b))
|
|
||||||
elog(ERROR, "GetTupleForTrigger: failed ReadBuffer");
|
|
||||||
|
|
||||||
dp = (PageHeader) BufferGetPage(b);
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (before)
|
if (before)
|
||||||
{
|
{
|
||||||
if (TupleUpdatedByCurXactAndCmd(&tuple))
|
int test;
|
||||||
{
|
|
||||||
elog(NOTICE, "GetTupleForTrigger: Non-functional delete/update");
|
|
||||||
ReleaseBuffer(b);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
HeapTupleSatisfies(&tuple, relation, b, dp,
|
/*
|
||||||
false, 0, (ScanKey) NULL);
|
* mark tuple for update
|
||||||
if (!tuple.t_data)
|
*/
|
||||||
|
tuple.t_self = *tid;
|
||||||
|
test = heap_mark4update(relation, &tuple, &buffer);
|
||||||
|
switch (test)
|
||||||
{
|
{
|
||||||
ReleaseBuffer(b);
|
case HeapTupleSelfUpdated:
|
||||||
elog(ERROR, "GetTupleForTrigger: (am)invalid tid");
|
ReleaseBuffer(buffer);
|
||||||
|
return(NULL);
|
||||||
|
|
||||||
|
case HeapTupleMayBeUpdated:
|
||||||
|
break;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
default:
|
||||||
|
ReleaseBuffer(buffer);
|
||||||
|
elog(ERROR, "Unknown status %u from heap_mark4update", test);
|
||||||
|
return(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PageHeader dp;
|
||||||
|
ItemId lp;
|
||||||
|
|
||||||
|
buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
|
||||||
|
|
||||||
|
if (!BufferIsValid(buffer))
|
||||||
|
elog(ERROR, "GetTupleForTrigger: failed ReadBuffer");
|
||||||
|
|
||||||
|
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);
|
result = heap_copytuple(&tuple);
|
||||||
ReleaseBuffer(b);
|
ReleaseBuffer(buffer);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
* Secure a write lock on pg_shadow so we can be sure of what the next
|
||||||
* usesysid should be.
|
* usesysid should be.
|
||||||
*/
|
*/
|
||||||
RelationSetLockForWrite(pg_shadow_rel);
|
LockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||||
|
|
||||||
scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, NULL);
|
scan = heap_beginscan(pg_shadow_rel, false, SnapshotNow, 0, NULL);
|
||||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||||
@ -154,7 +154,7 @@ DefineUser(CreateUserStmt *stmt)
|
|||||||
|
|
||||||
if (exists)
|
if (exists)
|
||||||
{
|
{
|
||||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||||
heap_close(pg_shadow_rel);
|
heap_close(pg_shadow_rel);
|
||||||
UserAbortTransactionBlock();
|
UserAbortTransactionBlock();
|
||||||
elog(ERROR,
|
elog(ERROR,
|
||||||
@ -187,7 +187,7 @@ DefineUser(CreateUserStmt *stmt)
|
|||||||
* This goes after the UpdatePgPwdFile to be certain that two backends
|
* 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.
|
* 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);
|
heap_close(pg_shadow_rel);
|
||||||
|
|
||||||
if (IsTransactionBlock() && !inblock)
|
if (IsTransactionBlock() && !inblock)
|
||||||
@ -235,14 +235,14 @@ AlterUser(AlterUserStmt *stmt)
|
|||||||
* dump of the pg_pwd file is done, there is not another backend doing
|
* dump of the pg_pwd file is done, there is not another backend doing
|
||||||
* the same.
|
* the same.
|
||||||
*/
|
*/
|
||||||
RelationSetLockForWrite(pg_shadow_rel);
|
LockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||||
|
|
||||||
tuple = SearchSysCacheTuple(USENAME,
|
tuple = SearchSysCacheTuple(USENAME,
|
||||||
PointerGetDatum(stmt->user),
|
PointerGetDatum(stmt->user),
|
||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
{
|
{
|
||||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||||
heap_close(pg_shadow_rel);
|
heap_close(pg_shadow_rel);
|
||||||
UserAbortTransactionBlock(); /* needed? */
|
UserAbortTransactionBlock(); /* needed? */
|
||||||
elog(ERROR, "alterUser: user \"%s\" does not exist", stmt->user);
|
elog(ERROR, "alterUser: user \"%s\" does not exist", stmt->user);
|
||||||
@ -288,7 +288,7 @@ AlterUser(AlterUserStmt *stmt)
|
|||||||
|
|
||||||
UpdatePgPwdFile(sql);
|
UpdatePgPwdFile(sql);
|
||||||
|
|
||||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||||
heap_close(pg_shadow_rel);
|
heap_close(pg_shadow_rel);
|
||||||
|
|
||||||
if (IsTransactionBlock() && !inblock)
|
if (IsTransactionBlock() && !inblock)
|
||||||
@ -342,14 +342,14 @@ RemoveUser(char *user)
|
|||||||
* dump of the pg_pwd file is done, there is not another backend doing
|
* dump of the pg_pwd file is done, there is not another backend doing
|
||||||
* the same.
|
* the same.
|
||||||
*/
|
*/
|
||||||
RelationSetLockForWrite(pg_shadow_rel);
|
LockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||||
|
|
||||||
tuple = SearchSysCacheTuple(USENAME,
|
tuple = SearchSysCacheTuple(USENAME,
|
||||||
PointerGetDatum(user),
|
PointerGetDatum(user),
|
||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
if (!HeapTupleIsValid(tuple))
|
if (!HeapTupleIsValid(tuple))
|
||||||
{
|
{
|
||||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||||
heap_close(pg_shadow_rel);
|
heap_close(pg_shadow_rel);
|
||||||
UserAbortTransactionBlock();
|
UserAbortTransactionBlock();
|
||||||
elog(ERROR, "removeUser: user \"%s\" does not exist", user);
|
elog(ERROR, "removeUser: user \"%s\" does not exist", user);
|
||||||
@ -422,7 +422,7 @@ RemoveUser(char *user)
|
|||||||
|
|
||||||
UpdatePgPwdFile(sql);
|
UpdatePgPwdFile(sql);
|
||||||
|
|
||||||
RelationUnsetLockForWrite(pg_shadow_rel);
|
UnlockRelation(pg_shadow_rel, AccessExclusiveLock);
|
||||||
heap_close(pg_shadow_rel);
|
heap_close(pg_shadow_rel);
|
||||||
|
|
||||||
if (IsTransactionBlock() && !inblock)
|
if (IsTransactionBlock() && !inblock)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 */
|
/* we require the relation to be locked until the indices are cleaned */
|
||||||
RelationSetLockForWrite(onerel);
|
LockRelation(onerel, AccessExclusiveLock);
|
||||||
|
|
||||||
/* scan it */
|
/* scan it */
|
||||||
vacuum_pages.vpl_num_pages = fraged_pages.vpl_num_pages = 0;
|
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)
|
if (i >= attcnt)
|
||||||
continue; /* don't delete it */
|
continue; /* don't delete it */
|
||||||
}
|
}
|
||||||
heap_delete(pgstatistic, &tuple->t_self);
|
heap_delete(pgstatistic, &tuple->t_self, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
@ -1928,11 +1928,7 @@ vc_delhilowstats(Oid relid, int attcnt, int *attnums)
|
|||||||
static void
|
static void
|
||||||
vc_setpagelock(Relation rel, BlockNumber blkno)
|
vc_setpagelock(Relation rel, BlockNumber blkno)
|
||||||
{
|
{
|
||||||
ItemPointerData itm;
|
LockPage(rel, blkno, ExclusiveLock);
|
||||||
|
|
||||||
ItemPointerSet(&itm, blkno, 1);
|
|
||||||
|
|
||||||
RelationSetLockForWritePage(rel, &itm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 "access/localam.h" */
|
||||||
#include "optimizer/var.h"
|
#include "optimizer/var.h"
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
|
#include "access/xact.h"
|
||||||
#include "catalog/heap.h"
|
#include "catalog/heap.h"
|
||||||
#include "commands/trigger.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
|
* if we have a result relation, open it and
|
||||||
|
|
||||||
* initialize the result relation info stuff.
|
* 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",
|
elog(ERROR, "You can't change sequence relation %s",
|
||||||
resultRelationDesc->rd_rel->relname.data);
|
resultRelationDesc->rd_rel->relname.data);
|
||||||
|
|
||||||
/*
|
LockRelation(resultRelationDesc, RowExclusiveLock);
|
||||||
* 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);
|
|
||||||
|
|
||||||
resultRelationInfo = makeNode(RelationInfo);
|
resultRelationInfo = makeNode(RelationInfo);
|
||||||
resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
|
resultRelationInfo->ri_RangeTableIndex = resultRelationIndex;
|
||||||
@ -461,7 +454,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
|
|||||||
* in the result relation information..
|
* in the result relation information..
|
||||||
******************
|
******************
|
||||||
*/
|
*/
|
||||||
ExecOpenIndices(resultRelationOid, resultRelationInfo);
|
if (operation != CMD_DELETE)
|
||||||
|
ExecOpenIndices(resultRelationOid, resultRelationInfo);
|
||||||
|
|
||||||
estate->es_result_relation_info = resultRelationInfo;
|
estate->es_result_relation_info = resultRelationInfo;
|
||||||
}
|
}
|
||||||
@ -1006,8 +1000,10 @@ ExecDelete(TupleTableSlot *slot,
|
|||||||
ItemPointer tupleid,
|
ItemPointer tupleid,
|
||||||
EState *estate)
|
EState *estate)
|
||||||
{
|
{
|
||||||
RelationInfo *resultRelationInfo;
|
RelationInfo *resultRelationInfo;
|
||||||
Relation resultRelationDesc;
|
Relation resultRelationDesc;
|
||||||
|
ItemPointerData ctid;
|
||||||
|
int result;
|
||||||
|
|
||||||
/******************
|
/******************
|
||||||
* get the result relation information
|
* get the result relation information
|
||||||
@ -1022,19 +1018,35 @@ ExecDelete(TupleTableSlot *slot,
|
|||||||
{
|
{
|
||||||
bool dodelete;
|
bool dodelete;
|
||||||
|
|
||||||
dodelete = ExecBRDeleteTriggers(resultRelationDesc, tupleid);
|
dodelete = ExecBRDeleteTriggers(estate, tupleid);
|
||||||
|
|
||||||
if (!dodelete) /* "do nothing" */
|
if (!dodelete) /* "do nothing" */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************
|
/*
|
||||||
* delete the tuple
|
* delete the tuple
|
||||||
******************
|
|
||||||
*/
|
*/
|
||||||
if (heap_delete(resultRelationDesc, /* relation desc */
|
result = heap_delete(resultRelationDesc, tupleid, &ctid);
|
||||||
tupleid)) /* item pointer to tuple */
|
switch (result)
|
||||||
return;
|
{
|
||||||
|
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();
|
IncrDeleted();
|
||||||
(estate->es_processed)++;
|
(estate->es_processed)++;
|
||||||
@ -1054,7 +1066,7 @@ ExecDelete(TupleTableSlot *slot,
|
|||||||
/* AFTER ROW DELETE Triggers */
|
/* AFTER ROW DELETE Triggers */
|
||||||
if (resultRelationDesc->trigdesc &&
|
if (resultRelationDesc->trigdesc &&
|
||||||
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
|
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_DELETE] > 0)
|
||||||
ExecARDeleteTriggers(resultRelationDesc, tupleid);
|
ExecARDeleteTriggers(estate, tupleid);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1075,10 +1087,12 @@ ExecReplace(TupleTableSlot *slot,
|
|||||||
EState *estate,
|
EState *estate,
|
||||||
Query *parseTree)
|
Query *parseTree)
|
||||||
{
|
{
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
RelationInfo *resultRelationInfo;
|
RelationInfo *resultRelationInfo;
|
||||||
Relation resultRelationDesc;
|
Relation resultRelationDesc;
|
||||||
int numIndices;
|
ItemPointerData ctid;
|
||||||
|
int result;
|
||||||
|
int numIndices;
|
||||||
|
|
||||||
/******************
|
/******************
|
||||||
* abort the operation if not running transactions
|
* abort the operation if not running transactions
|
||||||
@ -1117,7 +1131,7 @@ ExecReplace(TupleTableSlot *slot,
|
|||||||
{
|
{
|
||||||
HeapTuple newtuple;
|
HeapTuple newtuple;
|
||||||
|
|
||||||
newtuple = ExecBRUpdateTriggers(resultRelationDesc, tupleid, tuple);
|
newtuple = ExecBRUpdateTriggers(estate, tupleid, tuple);
|
||||||
|
|
||||||
if (newtuple == NULL) /* "do nothing" */
|
if (newtuple == NULL) /* "do nothing" */
|
||||||
return;
|
return;
|
||||||
@ -1140,19 +1154,28 @@ ExecReplace(TupleTableSlot *slot,
|
|||||||
ExecConstraints("ExecReplace", resultRelationDesc, tuple);
|
ExecConstraints("ExecReplace", resultRelationDesc, tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************
|
/*
|
||||||
* replace the heap 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 */
|
result = heap_replace(resultRelationDesc, tupleid, tuple, &ctid);
|
||||||
tupleid, /* item ptr of tuple to replace */
|
switch (result)
|
||||||
tuple))
|
{
|
||||||
{ /* replacement heap tuple */
|
case HeapTupleSelfUpdated:
|
||||||
return;
|
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();
|
IncrReplaced();
|
||||||
@ -1187,7 +1210,7 @@ ExecReplace(TupleTableSlot *slot,
|
|||||||
/* AFTER ROW UPDATE Triggers */
|
/* AFTER ROW UPDATE Triggers */
|
||||||
if (resultRelationDesc->trigdesc &&
|
if (resultRelationDesc->trigdesc &&
|
||||||
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
|
resultRelationDesc->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE] > 0)
|
||||||
ExecARUpdateTriggers(resultRelationDesc, tupleid, tuple);
|
ExecARUpdateTriggers(estate, tupleid, tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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);
|
indexOid = lfirsti(indexoid);
|
||||||
indexDesc = index_open(indexOid);
|
indexDesc = index_open(indexOid);
|
||||||
if (indexDesc != NULL)
|
if (indexDesc != NULL)
|
||||||
|
{
|
||||||
relationDescs[i++] = indexDesc;
|
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;
|
relationDescs = resultRelationInfo->ri_IndexRelationDescs;
|
||||||
|
|
||||||
for (i = 0; i < numIndices; i++)
|
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.
|
* XXX should free indexInfo array here too.
|
||||||
*/
|
*/
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
else
|
||||||
heapTuple = (HeapTuple)
|
heapTuple = (HeapTuple)
|
||||||
LONGALIGN(((char *) curtuple + curtuple->t_len + HEAPTUPLESIZE));
|
LONGALIGN(((char *) curtuple + curtuple->t_len + HEAPTUPLESIZE));
|
||||||
|
|
||||||
heapTuple->t_data = (HeapTupleHeader)
|
|
||||||
((char *) heapTuple + HEAPTUPLESIZE);
|
|
||||||
|
|
||||||
while (heapTuple < (HeapTuple) ABSADDR(bucket->bottom))
|
while (heapTuple < (HeapTuple) ABSADDR(bucket->bottom))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
heapTuple->t_data = (HeapTupleHeader)
|
||||||
|
((char *) heapTuple + HEAPTUPLESIZE);
|
||||||
|
|
||||||
inntuple = ExecStoreTuple(heapTuple, /* tuple to store */
|
inntuple = ExecStoreTuple(heapTuple, /* tuple to store */
|
||||||
hjstate->hj_HashTupleSlot, /* slot */
|
hjstate->hj_HashTupleSlot, /* slot */
|
||||||
InvalidBuffer, /* tuple has no buffer */
|
InvalidBuffer, /* tuple has no buffer */
|
||||||
@ -713,8 +713,6 @@ ExecScanHashBucket(HashJoinState *hjstate,
|
|||||||
|
|
||||||
heapTuple = (HeapTuple)
|
heapTuple = (HeapTuple)
|
||||||
LONGALIGN(((char *) heapTuple + heapTuple->t_len + HEAPTUPLESIZE));
|
LONGALIGN(((char *) heapTuple + heapTuple->t_len + HEAPTUPLESIZE));
|
||||||
heapTuple->t_data = (HeapTupleHeader)
|
|
||||||
((char *) heapTuple + HEAPTUPLESIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstotuple == NULL)
|
if (firstotuple == NULL)
|
||||||
|
@ -235,7 +235,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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);
|
inhrel = heap_openr(InheritsRelationName);
|
||||||
RelationSetLockForRead(inhrel);
|
|
||||||
inhtupdesc = RelationGetDescr(inhrel);
|
inhtupdesc = RelationGetDescr(inhrel);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1182,7 +1181,6 @@ find_inheritors(Oid relid, Oid **supervec)
|
|||||||
}
|
}
|
||||||
} while (qentry != (SuperQE *) NULL);
|
} while (qentry != (SuperQE *) NULL);
|
||||||
|
|
||||||
RelationUnsetLockForRead(inhrel);
|
|
||||||
heap_close(inhrel);
|
heap_close(inhrel);
|
||||||
|
|
||||||
if (nvisited > 0)
|
if (nvisited > 0)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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...
|
* Now delete the tuple...
|
||||||
*/
|
*/
|
||||||
heap_delete(RewriteRelation, &tuple->t_self);
|
heap_delete(RewriteRelation, &tuple->t_self, NULL);
|
||||||
|
|
||||||
pfree(tuple);
|
pfree(tuple);
|
||||||
heap_close(RewriteRelation);
|
heap_close(RewriteRelation);
|
||||||
@ -164,7 +164,7 @@ RelationRemoveRules(Oid relid)
|
|||||||
0, SnapshotNow, 1, &scanKeyData);
|
0, SnapshotNow, 1, &scanKeyData);
|
||||||
|
|
||||||
while (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0)))
|
while (HeapTupleIsValid(tuple = heap_getnext(scanDesc, 0)))
|
||||||
heap_delete(RewriteRelation, &tuple->t_self);
|
heap_delete(RewriteRelation, &tuple->t_self, NULL);
|
||||||
|
|
||||||
heap_endscan(scanDesc);
|
heap_endscan(scanDesc);
|
||||||
heap_close(RewriteRelation);
|
heap_close(RewriteRelation);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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);
|
relationRelation = heap_openr(RelationRelationName);
|
||||||
((Form_pg_class) GETSTRUCT(tuple))->relhasrules = relhasrules;
|
((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 */
|
/* keep the catalog indices up to date */
|
||||||
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
|
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
#ifndef HAS_TEST_AND_SET
|
||||||
long *NWaitIOBackendP;
|
long *NWaitIOBackendP;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern IpcSemaphoreId WaitIOSemId;
|
extern IpcSemaphoreId WaitIOSemId;
|
||||||
|
|
||||||
long *PrivateRefCount; /* also used in freelist.c */
|
long *PrivateRefCount; /* also used in freelist.c */
|
||||||
long *LastRefCount; /* refcounts of last ExecMain level */
|
long *LastRefCount; /* refcounts of last ExecMain level */
|
||||||
|
bits8 *BufferLocks; /* */
|
||||||
long *CommitInfoNeedsSave;/* to write buffers where we have filled
|
long *CommitInfoNeedsSave;/* to write buffers where we have filled
|
||||||
* in t_infomask */
|
* in t_infomask */
|
||||||
|
|
||||||
@ -146,21 +146,6 @@ InitBufferPool(IPCKey key)
|
|||||||
foundDescs;
|
foundDescs;
|
||||||
int i;
|
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;
|
Data_Descriptors = NBuffers;
|
||||||
Free_List_Descriptor = Data_Descriptors;
|
Free_List_Descriptor = Data_Descriptors;
|
||||||
Lookup_List_Descriptor = Data_Descriptors + 1;
|
Lookup_List_Descriptor = Data_Descriptors + 1;
|
||||||
@ -232,6 +217,7 @@ InitBufferPool(IPCKey key)
|
|||||||
buf->buf_id = i;
|
buf->buf_id = i;
|
||||||
#ifdef HAS_TEST_AND_SET
|
#ifdef HAS_TEST_AND_SET
|
||||||
S_INIT_LOCK(&(buf->io_in_progress_lock));
|
S_INIT_LOCK(&(buf->io_in_progress_lock));
|
||||||
|
S_INIT_LOCK(&(buf->cntx_lock));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,10 +238,15 @@ InitBufferPool(IPCKey key)
|
|||||||
|
|
||||||
WaitIOSemId = IpcSemaphoreCreate(IPCKeyGetWaitIOSemaphoreKey(key),
|
WaitIOSemId = IpcSemaphoreCreate(IPCKeyGetWaitIOSemaphoreKey(key),
|
||||||
1, IPCProtection, 0, 1, &status);
|
1, IPCProtection, 0, 1, &status);
|
||||||
|
WaitCLSemId = IpcSemaphoreCreate(IPCKeyGetWaitCLSemaphoreKey(key),
|
||||||
|
1, IPCProtection,
|
||||||
|
IpcSemaphoreDefaultStartValue,
|
||||||
|
1, &status);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
PrivateRefCount = (long *) calloc(NBuffers, sizeof(long));
|
PrivateRefCount = (long *) calloc(NBuffers, sizeof(long));
|
||||||
LastRefCount = (long *) calloc(NBuffers, sizeof(long));
|
LastRefCount = (long *) calloc(NBuffers, sizeof(long));
|
||||||
|
BufferLocks = (bits8*) calloc (NBuffers, sizeof(bits8));
|
||||||
CommitInfoNeedsSave = (long *) calloc(NBuffers, sizeof(long));
|
CommitInfoNeedsSave = (long *) calloc(NBuffers, sizeof(long));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
#ifndef HAS_TEST_AND_SET
|
||||||
static void SignalIO(BufferDesc *buf);
|
static void SignalIO(BufferDesc *buf);
|
||||||
extern long *NWaitIOBackendP; /* defined in buf_init.c */
|
extern long *NWaitIOBackendP; /* defined in buf_init.c */
|
||||||
|
|
||||||
#endif /* HAS_TEST_AND_SET */
|
#endif /* HAS_TEST_AND_SET */
|
||||||
|
|
||||||
static Buffer ReadBufferWithBufferLock(Relation relation, BlockNumber blockNum,
|
static Buffer ReadBufferWithBufferLock(Relation relation, BlockNumber blockNum,
|
||||||
@ -583,7 +582,6 @@ BufferAlloc(Relation reln,
|
|||||||
if (buf->refcount > 1)
|
if (buf->refcount > 1)
|
||||||
SignalIO(buf);
|
SignalIO(buf);
|
||||||
#endif /* !HAS_TEST_AND_SET */
|
#endif /* !HAS_TEST_AND_SET */
|
||||||
|
|
||||||
/* give up the buffer since we don't need it any more */
|
/* give up the buffer since we don't need it any more */
|
||||||
buf->refcount--;
|
buf->refcount--;
|
||||||
PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 0;
|
PrivateRefCount[BufferDescriptorGetBuffer(buf) - 1] = 0;
|
||||||
@ -1096,6 +1094,7 @@ WaitIO(BufferDesc *buf, SPINLOCK spinlock)
|
|||||||
|
|
||||||
#else /* HAS_TEST_AND_SET */
|
#else /* HAS_TEST_AND_SET */
|
||||||
IpcSemaphoreId WaitIOSemId;
|
IpcSemaphoreId WaitIOSemId;
|
||||||
|
IpcSemaphoreId WaitCLSemId;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
WaitIO(BufferDesc *buf, SPINLOCK spinlock)
|
WaitIO(BufferDesc *buf, SPINLOCK spinlock)
|
||||||
@ -1933,3 +1932,147 @@ SetBufferCommitInfoNeedsSave(Buffer buffer)
|
|||||||
if (!BufferIsLocal(buffer))
|
if (!BufferIsLocal(buffer))
|
||||||
CommitInfoNeedsSave[buffer - 1]++;
|
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
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -7,13 +7,14 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 <stdio.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "c.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
|
* 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
|
void
|
||||||
s_lock(volatile slock_t *lock, const char *file, const int line)
|
s_lock(volatile slock_t *lock, const char *file, const int line)
|
||||||
{
|
{
|
||||||
int spins = 0;
|
unsigned spins = 0;
|
||||||
|
|
||||||
while (TAS(lock))
|
while (TAS(lock))
|
||||||
{
|
{
|
||||||
struct timeval delay;
|
s_lock_sleep(spins);
|
||||||
|
|
||||||
delay.tv_sec = 0;
|
|
||||||
delay.tv_usec = s_spincycle[spins % S_NSPINCYCLE];
|
|
||||||
(void) select(0, NULL, NULL, NULL, &delay);
|
|
||||||
if (++spins > S_MAX_BUSY)
|
if (++spins > S_MAX_BUSY)
|
||||||
{
|
{
|
||||||
/* It's been over a minute... */
|
/* It's been over a minute... */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 "postgres.h"
|
||||||
|
|
||||||
#include "storage/ipc.h"
|
#include "storage/ipc.h"
|
||||||
#include "storage/multilev.h"
|
|
||||||
#include "storage/sinval.h"
|
#include "storage/sinval.h"
|
||||||
#include "storage/bufmgr.h"
|
#include "storage/bufmgr.h"
|
||||||
#include "storage/proc.h"
|
#include "storage/proc.h"
|
||||||
@ -92,7 +91,7 @@ CreateSharedMemoryAndSemaphores(IPCKey key)
|
|||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
InitLocks();
|
InitLocks();
|
||||||
if (InitMultiLevelLocks() == INVALID_TABLEID)
|
if (InitLockTable() == INVALID_TABLEID)
|
||||||
elog(FATAL, "Couldn't create the lock table");
|
elog(FATAL, "Couldn't create the lock table");
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
@ -145,7 +144,7 @@ AttachSharedMemoryAndSemaphores(IPCKey key)
|
|||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
InitLocks();
|
InitLocks();
|
||||||
if (InitMultiLevelLocks() == INVALID_TABLEID)
|
if (InitLockTable() == INVALID_TABLEID)
|
||||||
elog(FATAL, "Couldn't attach to the lock table");
|
elog(FATAL, "Couldn't attach to the lock table");
|
||||||
|
|
||||||
AttachSharedInvalidationState(key);
|
AttachSharedInvalidationState(key);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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/dynahash.h"
|
||||||
#include "utils/hsearch.h"
|
#include "utils/hsearch.h"
|
||||||
#include "utils/memutils.h"
|
#include "utils/memutils.h"
|
||||||
#include "access/transam.h"
|
#include "access/xact.h"
|
||||||
|
#include "utils/tqual.h"
|
||||||
|
|
||||||
/* shared memory global variables */
|
/* shared memory global variables */
|
||||||
|
|
||||||
@ -629,7 +630,6 @@ TransactionIdIsInProgress(TransactionId xid)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LowLevelLocking
|
|
||||||
/*
|
/*
|
||||||
* GetSnapshotData -- returns information about running transactions.
|
* GetSnapshotData -- returns information about running transactions.
|
||||||
*
|
*
|
||||||
@ -645,16 +645,15 @@ Snapshot
|
|||||||
GetSnapshotData(bool serialized)
|
GetSnapshotData(bool serialized)
|
||||||
{
|
{
|
||||||
Snapshot snapshot = (Snapshot) malloc(sizeof(SnapshotData));
|
Snapshot snapshot = (Snapshot) malloc(sizeof(SnapshotData));
|
||||||
TransactionId snapshot->xip = (TransactionId *)
|
|
||||||
malloc(32 * sizeof(TransactionId));
|
|
||||||
ShmemIndexEnt *result;
|
ShmemIndexEnt *result;
|
||||||
PROC *proc;
|
PROC *proc;
|
||||||
TransactionId cid = GetCurrentTransactionId();
|
TransactionId cid = GetCurrentTransactionId();
|
||||||
uint count = 0;
|
uint32 count = 0;
|
||||||
unit free = 31;
|
uint32 have = 31;
|
||||||
|
|
||||||
Assert(ShmemIndex);
|
Assert(ShmemIndex);
|
||||||
|
|
||||||
|
snapshot->xip = (TransactionId *) malloc(32 * sizeof(TransactionId));
|
||||||
snapshot->xmax = cid;
|
snapshot->xmax = cid;
|
||||||
snapshot->xmin = cid;
|
snapshot->xmin = cid;
|
||||||
|
|
||||||
@ -676,20 +675,20 @@ GetSnapshotData(bool serialized)
|
|||||||
continue;
|
continue;
|
||||||
proc = (PROC *) MAKE_PTR(result->location);
|
proc = (PROC *) MAKE_PTR(result->location);
|
||||||
if (proc == MyProc || proc->xid < FirstTransactionId ||
|
if (proc == MyProc || proc->xid < FirstTransactionId ||
|
||||||
serialized && proc->xid >= cid)
|
(serialized && proc->xid >= cid))
|
||||||
continue;
|
continue;
|
||||||
if (proc->xid < snapshot->xmin)
|
if (proc->xid < snapshot->xmin)
|
||||||
snapshot->xmin = proc->xid;
|
snapshot->xmin = proc->xid;
|
||||||
else if (proc->xid > snapshot->xmax)
|
else if (proc->xid > snapshot->xmax)
|
||||||
snapshot->xmax = proc->xid;
|
snapshot->xmax = proc->xid;
|
||||||
if (free == 0)
|
if (have == 0)
|
||||||
{
|
{
|
||||||
snapshot->xip = (TransactionId *) realloc(snapshot->xip,
|
snapshot->xip = (TransactionId *) realloc(snapshot->xip,
|
||||||
(count + 33) * sizeof(TransactionId));
|
(count + 33) * sizeof(TransactionId));
|
||||||
free = 32;
|
have = 32;
|
||||||
}
|
}
|
||||||
snapshot->xip[count] = proc->xid;
|
snapshot->xip[count] = proc->xid;
|
||||||
free--;
|
have--;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,5 +698,3 @@ GetSnapshotData(bool serialized)
|
|||||||
elog(ERROR, "GetSnapshotData: ShmemIndex corrupted");
|
elog(ERROR, "GetSnapshotData: ShmemIndex corrupted");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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)
|
if (flags & INV_WRITE)
|
||||||
{
|
{
|
||||||
RelationSetLockForWrite(r);
|
LockRelation(r, ExclusiveLock);
|
||||||
retval->flags = IFS_WRLOCK | IFS_RDLOCK;
|
retval->flags = IFS_WRLOCK | IFS_RDLOCK;
|
||||||
}
|
}
|
||||||
else if (flags & INV_READ)
|
else if (flags & INV_READ)
|
||||||
{
|
{
|
||||||
RelationSetLockForRead(r);
|
LockRelation(r, ShareLock);
|
||||||
retval->flags = IFS_RDLOCK;
|
retval->flags = IFS_RDLOCK;
|
||||||
}
|
}
|
||||||
retval->flags |= IFS_ATEOF;
|
retval->flags |= IFS_ATEOF;
|
||||||
@ -254,12 +254,12 @@ inv_open(Oid lobjId, int flags)
|
|||||||
|
|
||||||
if (flags & INV_WRITE)
|
if (flags & INV_WRITE)
|
||||||
{
|
{
|
||||||
RelationSetLockForWrite(r);
|
LockRelation(r, ExclusiveLock);
|
||||||
retval->flags = IFS_WRLOCK | IFS_RDLOCK;
|
retval->flags = IFS_WRLOCK | IFS_RDLOCK;
|
||||||
}
|
}
|
||||||
else if (flags & INV_READ)
|
else if (flags & INV_READ)
|
||||||
{
|
{
|
||||||
RelationSetLockForRead(r);
|
LockRelation(r, ShareLock);
|
||||||
retval->flags = IFS_RDLOCK;
|
retval->flags = IFS_RDLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +328,7 @@ inv_stat(LargeObjectDesc *obj_desc, struct pgstat * stbuf)
|
|||||||
/* need read lock for stat */
|
/* need read lock for stat */
|
||||||
if (!(obj_desc->flags & IFS_RDLOCK))
|
if (!(obj_desc->flags & IFS_RDLOCK))
|
||||||
{
|
{
|
||||||
RelationSetLockForRead(obj_desc->heap_r);
|
LockRelation(obj_desc->heap_r, ShareLock);
|
||||||
obj_desc->flags |= IFS_RDLOCK;
|
obj_desc->flags |= IFS_RDLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,7 +376,7 @@ inv_seek(LargeObjectDesc *obj_desc, int offset, int whence)
|
|||||||
/* need read lock for getsize */
|
/* need read lock for getsize */
|
||||||
if (!(obj_desc->flags & IFS_RDLOCK))
|
if (!(obj_desc->flags & IFS_RDLOCK))
|
||||||
{
|
{
|
||||||
RelationSetLockForRead(obj_desc->heap_r);
|
LockRelation(obj_desc->heap_r, ShareLock);
|
||||||
obj_desc->flags |= IFS_RDLOCK;
|
obj_desc->flags |= IFS_RDLOCK;
|
||||||
}
|
}
|
||||||
offset += _inv_getsize(obj_desc->heap_r,
|
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 */
|
/* make sure we obey two-phase locking */
|
||||||
if (!(obj_desc->flags & IFS_RDLOCK))
|
if (!(obj_desc->flags & IFS_RDLOCK))
|
||||||
{
|
{
|
||||||
RelationSetLockForRead(obj_desc->heap_r);
|
LockRelation(obj_desc->heap_r, ShareLock);
|
||||||
obj_desc->flags |= IFS_RDLOCK;
|
obj_desc->flags |= IFS_RDLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,7 +516,7 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
|
|||||||
|
|
||||||
if (!(obj_desc->flags & IFS_WRLOCK))
|
if (!(obj_desc->flags & IFS_WRLOCK))
|
||||||
{
|
{
|
||||||
RelationSetLockForRead(obj_desc->heap_r);
|
LockRelation(obj_desc->heap_r, ShareLock);
|
||||||
obj_desc->flags |= (IFS_WRLOCK | IFS_RDLOCK);
|
obj_desc->flags |= (IFS_WRLOCK | IFS_RDLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# Makefile for storage/lmgr
|
# Makefile for storage/lmgr
|
||||||
#
|
#
|
||||||
# IDENTIFICATION
|
# 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)
|
CFLAGS+= $(MBFLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
OBJS = lmgr.o lock.o multi.o proc.o single.o
|
OBJS = lmgr.o lock.o proc.o
|
||||||
|
|
||||||
all: SUBSYS.o
|
all: SUBSYS.o
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
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 --
|
* RelationInitLockInfo --
|
||||||
* Initializes the lock information in a relation descriptor.
|
* Initializes the lock information in a relation descriptor.
|
||||||
@ -82,215 +161,44 @@ RelationInitLockInfo(Relation relation)
|
|||||||
else
|
else
|
||||||
info->lockRelId.dbId = MyDatabaseId;
|
info->lockRelId.dbId = MyDatabaseId;
|
||||||
|
|
||||||
#ifdef LowLevelLocking
|
|
||||||
memset(info->lockHeld, 0, sizeof(info->lockHeld));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
relation->lockInfo = (Pointer) info;
|
relation->lockInfo = (Pointer) info;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RelationSetLockForDescriptorOpen --
|
* LockRelation
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
RelationSetLockForRead(Relation relation)
|
LockRelation(Relation relation, LOCKMODE lockmode)
|
||||||
{
|
{
|
||||||
LockInfo lockinfo;
|
LockInfo lockinfo;
|
||||||
|
LOCKTAG tag;
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* sanity checks
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
Assert(RelationIsValid(relation));
|
|
||||||
if (LockingDisabled())
|
if (LockingDisabled())
|
||||||
return;
|
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))
|
if (!LockInfoIsValid(relation->lockInfo))
|
||||||
{
|
|
||||||
RelationInitLockInfo(relation);
|
RelationInitLockInfo(relation);
|
||||||
lockinfo = (LockInfo) relation->lockInfo;
|
|
||||||
MultiLockReln(lockinfo, READ_LOCK);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
lockinfo = (LockInfo) relation->lockInfo;
|
|
||||||
|
|
||||||
MultiLockReln(lockinfo, READ_LOCK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* 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 */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* RelationUnsetLockForRead --
|
|
||||||
* Unsets relation level read lock.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
RelationUnsetLockForRead(Relation relation)
|
|
||||||
{
|
|
||||||
LockInfo lockinfo;
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* sanity check
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
Assert(RelationIsValid(relation));
|
|
||||||
if (LockingDisabled())
|
|
||||||
return;
|
|
||||||
|
|
||||||
lockinfo = (LockInfo) relation->lockInfo;
|
lockinfo = (LockInfo) relation->lockInfo;
|
||||||
|
|
||||||
/* ----------------
|
MemSet(&tag, 0, sizeof(tag));
|
||||||
* If we don't have lock info on the reln just go ahead and
|
tag.relId = lockinfo->lockRelId.relId;
|
||||||
* release it.
|
tag.dbId = lockinfo->lockRelId.dbId;
|
||||||
* ----------------
|
tag.objId.blkno = InvalidBlockNumber;
|
||||||
*/
|
|
||||||
if (!LockInfoIsValid(lockinfo))
|
|
||||||
{
|
|
||||||
elog(ERROR,
|
|
||||||
"Releasing a lock on %s with invalid lock information",
|
|
||||||
RelationGetRelationName(relation));
|
|
||||||
}
|
|
||||||
|
|
||||||
MultiReleaseReln(lockinfo, READ_LOCK);
|
LockAcquire(LockTableId, &tag, lockmode);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* 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 */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RelationSetLockForWrite --
|
* UnlockRelation
|
||||||
* Sets relation level write lock.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
RelationSetLockForWrite(Relation relation)
|
UnlockRelation(Relation relation, LOCKMODE lockmode)
|
||||||
{
|
{
|
||||||
LockInfo lockinfo;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* 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 */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* RelationUnsetLockForWrite --
|
|
||||||
* Unsets relation level write lock.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
RelationUnsetLockForWrite(Relation relation)
|
|
||||||
{
|
|
||||||
LockInfo lockinfo;
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* sanity checks
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
Assert(RelationIsValid(relation));
|
|
||||||
if (LockingDisabled())
|
if (LockingDisabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -303,309 +211,127 @@ RelationUnsetLockForWrite(Relation relation)
|
|||||||
RelationGetRelationName(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 = InvalidBlockNumber;
|
||||||
|
|
||||||
|
LockRelease(LockTableId, &tag, lockmode);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* 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 --
|
* LockPage
|
||||||
* Sets write lock on a page.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
RelationSetLockForWritePage(Relation relation,
|
LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
|
||||||
ItemPointer itemPointer)
|
|
||||||
{
|
{
|
||||||
/* ----------------
|
LockInfo lockinfo;
|
||||||
* sanity checks
|
LOCKTAG tag;
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* sanity checks
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
Assert(RelationIsValid(relation));
|
|
||||||
if (LockingDisabled())
|
if (LockingDisabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!LockInfoIsValid(relation->lockInfo))
|
if (!LockInfoIsValid(relation->lockInfo))
|
||||||
RelationInitLockInfo(relation);
|
RelationInitLockInfo(relation);
|
||||||
|
|
||||||
SingleLockPage((LockInfo) relation->lockInfo, itemPointer, WRITE_LOCK, !UNLOCK);
|
lockinfo = (LockInfo) relation->lockInfo;
|
||||||
|
|
||||||
|
MemSet(&tag, 0, sizeof(tag));
|
||||||
|
tag.relId = lockinfo->lockRelId.relId;
|
||||||
|
tag.dbId = lockinfo->lockRelId.dbId;
|
||||||
|
tag.objId.blkno = blkno;
|
||||||
|
|
||||||
|
LockAcquire(LockTableId, &tag, lockmode);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unset a single level write page lock
|
* UnlockPage
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
RelationUnsetSingleWLockPage(Relation relation,
|
UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
|
||||||
ItemPointer itemPointer)
|
|
||||||
{
|
{
|
||||||
|
LockInfo lockinfo;
|
||||||
|
LOCKTAG tag;
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* sanity checks
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
Assert(RelationIsValid(relation));
|
|
||||||
if (LockingDisabled())
|
if (LockingDisabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!LockInfoIsValid(relation->lockInfo))
|
lockinfo = (LockInfo) relation->lockInfo;
|
||||||
|
|
||||||
|
if (!LockInfoIsValid(lockinfo))
|
||||||
|
{
|
||||||
elog(ERROR,
|
elog(ERROR,
|
||||||
"Releasing a lock on %s with invalid lock information",
|
"Releasing a lock on %s with invalid lock information",
|
||||||
RelationGetRelationName(relation));
|
RelationGetRelationName(relation));
|
||||||
|
}
|
||||||
|
|
||||||
SingleLockPage((LockInfo) relation->lockInfo, itemPointer, WRITE_LOCK, UNLOCK);
|
MemSet(&tag, 0, sizeof(tag));
|
||||||
|
tag.relId = lockinfo->lockRelId.relId;
|
||||||
|
tag.dbId = lockinfo->lockRelId.dbId;
|
||||||
|
tag.objId.blkno = blkno;
|
||||||
|
|
||||||
|
LockRelease(LockTableId, &tag, lockmode);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Set a single level read page lock. Assumes you already have a read
|
|
||||||
* intent lock set on the relation.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
RelationSetSingleRLockPage(Relation relation,
|
XactLockTableInsert(TransactionId xid)
|
||||||
ItemPointer itemPointer)
|
|
||||||
{
|
{
|
||||||
|
LOCKTAG tag;
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* sanity checks
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
Assert(RelationIsValid(relation));
|
|
||||||
if (LockingDisabled())
|
if (LockingDisabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!LockInfoIsValid(relation->lockInfo))
|
MemSet(&tag, 0, sizeof(tag));
|
||||||
RelationInitLockInfo(relation);
|
tag.relId = XactLockTableId;
|
||||||
|
tag.dbId = InvalidOid;
|
||||||
|
tag.objId.xid = xid;
|
||||||
|
|
||||||
SingleLockPage((LockInfo) relation->lockInfo, itemPointer, READ_LOCK, !UNLOCK);
|
LockAcquire(LockTableId, &tag, ExclusiveLock);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Unset a single level read page lock.
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
RelationUnsetSingleRLockPage(Relation relation,
|
XactLockTableDelete(TransactionId xid)
|
||||||
ItemPointer itemPointer)
|
|
||||||
{
|
{
|
||||||
|
LOCKTAG tag;
|
||||||
|
|
||||||
/* ----------------
|
|
||||||
* sanity checks
|
|
||||||
* ----------------
|
|
||||||
*/
|
|
||||||
Assert(RelationIsValid(relation));
|
|
||||||
if (LockingDisabled())
|
if (LockingDisabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!LockInfoIsValid(relation->lockInfo))
|
MemSet(&tag, 0, sizeof(tag));
|
||||||
elog(ERROR,
|
tag.relId = XactLockTableId;
|
||||||
"Releasing a lock on %s with invalid lock information",
|
tag.dbId = InvalidOid;
|
||||||
RelationGetRelationName(relation));
|
tag.objId.xid = xid;
|
||||||
|
|
||||||
SingleLockPage((LockInfo) relation->lockInfo, itemPointer, READ_LOCK, UNLOCK);
|
LockRelease(LockTableId, &tag, ExclusiveLock);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
void
|
||||||
RelationSetRIntentLock(Relation relation)
|
XactLockTableWait(TransactionId xid)
|
||||||
{
|
{
|
||||||
/* -----------------
|
LOCKTAG tag;
|
||||||
* Sanity check
|
|
||||||
* -----------------
|
|
||||||
*/
|
|
||||||
Assert(RelationIsValid(relation));
|
|
||||||
if (LockingDisabled())
|
if (LockingDisabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!LockInfoIsValid(relation->lockInfo))
|
MemSet(&tag, 0, sizeof(tag));
|
||||||
RelationInitLockInfo(relation);
|
tag.relId = XactLockTableId;
|
||||||
|
tag.dbId = InvalidOid;
|
||||||
|
tag.objId.xid = xid;
|
||||||
|
|
||||||
SingleLockReln((LockInfo) relation->lockInfo, READ_LOCK + INTENT, !UNLOCK);
|
LockAcquire(LockTableId, &tag, ShareLock);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unset a read intent lock on a relation
|
* Transaction was committed/aborted/crashed -
|
||||||
*/
|
* we have to update pg_log if transaction is still
|
||||||
void
|
* marked as running.
|
||||||
RelationUnsetRIntentLock(Relation relation)
|
|
||||||
{
|
|
||||||
/* -----------------
|
|
||||||
* Sanity check
|
|
||||||
* -----------------
|
|
||||||
*/
|
*/
|
||||||
Assert(RelationIsValid(relation));
|
if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
|
||||||
if (LockingDisabled())
|
TransactionIdAbort(xid);
|
||||||
return;
|
|
||||||
|
|
||||||
if (!LockInfoIsValid(relation->lockInfo))
|
return;
|
||||||
RelationInitLockInfo(relation);
|
|
||||||
|
|
||||||
SingleLockReln((LockInfo) relation->lockInfo, READ_LOCK + INTENT, UNLOCK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Set a write intent lock on a relation. For a more complete explanation
|
|
||||||
* see RelationSetRIntentLock()
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
RelationSetWIntentLock(Relation relation)
|
|
||||||
{
|
|
||||||
/* -----------------
|
|
||||||
* Sanity check
|
|
||||||
* -----------------
|
|
||||||
*/
|
|
||||||
Assert(RelationIsValid(relation));
|
|
||||||
if (LockingDisabled())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!LockInfoIsValid(relation->lockInfo))
|
|
||||||
RelationInitLockInfo(relation);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
SingleLockReln((LockInfo) relation->lockInfo, WRITE_LOCK + INTENT, UNLOCK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
* -----------------
|
|
||||||
*/
|
|
||||||
Assert(RelationIsValid(relation));
|
|
||||||
if (LockingDisabled())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!LockInfoIsValid(relation->lockInfo))
|
|
||||||
RelationInitLockInfo(relation);
|
|
||||||
|
|
||||||
MultiLockReln((LockInfo) relation->lockInfo, EXTEND_LOCK);
|
|
||||||
}
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* NOTES
|
||||||
* Outside modules can create a lock table and acquire/release
|
* 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) \
|
#define LOCK_PRINT_AUX(where,lock,type) \
|
||||||
TPRINTF(TRACE_ALL, \
|
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 " \
|
"hold(%d,%d,%d,%d,%d)=%d " \
|
||||||
"act(%d,%d,%d,%d,%d)=%d wait(%d) type(%s)", \
|
"act(%d,%d,%d,%d,%d)=%d wait(%d) type(%s)", \
|
||||||
where, \
|
where, \
|
||||||
@ -92,9 +92,7 @@ static int WaitOnLock(LOCKMETHOD lockmethod, LOCK *lock, LOCKMODE lockmode,
|
|||||||
lock->tag.lockmethod, \
|
lock->tag.lockmethod, \
|
||||||
lock->tag.relId, \
|
lock->tag.relId, \
|
||||||
lock->tag.dbId, \
|
lock->tag.dbId, \
|
||||||
((lock->tag.tupleId.ip_blkid.bi_hi<<16)+ \
|
lock->tag.objId.blkno, \
|
||||||
lock->tag.tupleId.ip_blkid.bi_lo), \
|
|
||||||
lock->tag.tupleId.ip_posid, \
|
|
||||||
lock->mask, \
|
lock->mask, \
|
||||||
lock->holders[1], \
|
lock->holders[1], \
|
||||||
lock->holders[2], \
|
lock->holders[2], \
|
||||||
@ -498,10 +496,8 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
|||||||
if (is_user_lock)
|
if (is_user_lock)
|
||||||
{
|
{
|
||||||
#ifdef USER_LOCKS_DEBUG
|
#ifdef USER_LOCKS_DEBUG
|
||||||
TPRINTF(TRACE_USERLOCKS, "LockAcquire: user lock [%u,%u] %s",
|
TPRINTF(TRACE_USERLOCKS, "LockAcquire: user lock [%u] %s",
|
||||||
locktag->tupleId.ip_posid,
|
locktag->objId.blkno,
|
||||||
((locktag->tupleId.ip_blkid.bi_hi << 16) +
|
|
||||||
locktag->tupleId.ip_blkid.bi_lo),
|
|
||||||
lock_types[lockmode]);
|
lock_types[lockmode]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -550,8 +546,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
|||||||
MemSet((char *) lock->holders, 0, sizeof(int) * MAX_LOCKMODES);
|
MemSet((char *) lock->holders, 0, sizeof(int) * MAX_LOCKMODES);
|
||||||
MemSet((char *) lock->activeHolders, 0, sizeof(int) * MAX_LOCKMODES);
|
MemSet((char *) lock->activeHolders, 0, sizeof(int) * MAX_LOCKMODES);
|
||||||
ProcQueueInit(&(lock->waitProcs));
|
ProcQueueInit(&(lock->waitProcs));
|
||||||
Assert(BlockIdEquals(&(lock->tag.tupleId.ip_blkid),
|
Assert(lock->tag.objId.blkno == locktag->objId.blkno);
|
||||||
&(locktag->tupleId.ip_blkid)));
|
|
||||||
LOCK_PRINT("LockAcquire: new", lock, lockmode);
|
LOCK_PRINT("LockAcquire: new", lock, lockmode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -993,10 +988,8 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag, LOCKMODE lockmode)
|
|||||||
is_user_lock = (lockmethod == USER_LOCKMETHOD);
|
is_user_lock = (lockmethod == USER_LOCKMETHOD);
|
||||||
if (is_user_lock)
|
if (is_user_lock)
|
||||||
{
|
{
|
||||||
TPRINTF(TRACE_USERLOCKS, "LockRelease: user lock tag [%u,%u] %d",
|
TPRINTF(TRACE_USERLOCKS, "LockRelease: user lock tag [%u] %d",
|
||||||
locktag->tupleId.ip_posid,
|
locktag->objId.blkno,
|
||||||
((locktag->tupleId.ip_blkid.bi_hi << 16) +
|
|
||||||
locktag->tupleId.ip_blkid.bi_lo),
|
|
||||||
lockmode);
|
lockmode);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1336,19 +1329,15 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
|
|||||||
{
|
{
|
||||||
/* Should never happen */
|
/* Should never happen */
|
||||||
elog(NOTICE,
|
elog(NOTICE,
|
||||||
"LockReleaseAll: INVALID PID: [%u,%u] [%d,%d,%d]",
|
"LockReleaseAll: INVALID PID: [%u] [%d,%d,%d]",
|
||||||
lock->tag.tupleId.ip_posid,
|
lock->tag.objId.blkno,
|
||||||
((lock->tag.tupleId.ip_blkid.bi_hi << 16) +
|
|
||||||
lock->tag.tupleId.ip_blkid.bi_lo),
|
|
||||||
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||||
nleft++;
|
nleft++;
|
||||||
goto next_item;
|
goto next_item;
|
||||||
}
|
}
|
||||||
TPRINTF(TRACE_USERLOCKS,
|
TPRINTF(TRACE_USERLOCKS,
|
||||||
"LockReleaseAll: releasing user lock [%u,%u] [%d,%d,%d]",
|
"LockReleaseAll: releasing user lock [%u] [%d,%d,%d]",
|
||||||
lock->tag.tupleId.ip_posid,
|
lock->tag.objId.blkno,
|
||||||
((lock->tag.tupleId.ip_blkid.bi_hi << 16) +
|
|
||||||
lock->tag.tupleId.ip_blkid.bi_lo),
|
|
||||||
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1361,10 +1350,8 @@ LockReleaseAll(LOCKMETHOD lockmethod, SHM_QUEUE *lockQueue)
|
|||||||
if (xidLook->tag.pid != 0)
|
if (xidLook->tag.pid != 0)
|
||||||
{
|
{
|
||||||
TPRINTF(TRACE_LOCKS,
|
TPRINTF(TRACE_LOCKS,
|
||||||
"LockReleaseAll: skiping user lock [%u,%u] [%d,%d,%d]",
|
"LockReleaseAll: skiping user lock [%u] [%d,%d,%d]",
|
||||||
lock->tag.tupleId.ip_posid,
|
lock->tag.objId.blkno,
|
||||||
((lock->tag.tupleId.ip_blkid.bi_hi << 16) +
|
|
||||||
lock->tag.tupleId.ip_blkid.bi_lo),
|
|
||||||
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
xidLook->tag.lock, xidLook->tag.pid, xidLook->tag.xid);
|
||||||
nleft++;
|
nleft++;
|
||||||
goto next_item;
|
goto next_item;
|
||||||
@ -1649,7 +1636,7 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Assert(skip_check);
|
Assert(skip_check);
|
||||||
Assert(MyProc->prio == 2);
|
Assert(MyProc->prio >= 2);
|
||||||
|
|
||||||
lockMethodTable = LockMethodTable[1];
|
lockMethodTable = LockMethodTable[1];
|
||||||
xidTable = lockMethodTable->xidHash;
|
xidTable = lockMethodTable->xidHash;
|
||||||
@ -1747,10 +1734,8 @@ LockOwners(LOCKMETHOD lockmethod, LOCKTAG *locktag)
|
|||||||
is_user_lock = (lockmethod == USER_LOCKMETHOD);
|
is_user_lock = (lockmethod == USER_LOCKMETHOD);
|
||||||
if (is_user_lock)
|
if (is_user_lock)
|
||||||
{
|
{
|
||||||
TPRINTF(TRACE_USERLOCKS, "LockOwners: user lock tag [%u,%u]",
|
TPRINTF(TRACE_USERLOCKS, "LockOwners: user lock tag [%u]",
|
||||||
locktag->tupleId.ip_posid,
|
locktag->objId.blkno;,
|
||||||
((locktag->tupleId.ip_blkid.bi_hi << 16) +
|
|
||||||
locktag->tupleId.ip_blkid.bi_lo));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 */
|
/* change the pg_proc tuple */
|
||||||
procrel = heap_openr(ProcedureRelationName);
|
procrel = heap_openr(ProcedureRelationName);
|
||||||
RelationSetLockForWrite(procrel);
|
LockRelation(procrel, AccessExclusiveLock);
|
||||||
|
|
||||||
tup = SearchSysCacheTuple(PROOID,
|
tup = SearchSysCacheTuple(PROOID,
|
||||||
ObjectIdGetDatum(setoid),
|
ObjectIdGetDatum(setoid),
|
||||||
@ -123,7 +123,7 @@ SetDefine(char *querystr, char *typename)
|
|||||||
repl);
|
repl);
|
||||||
|
|
||||||
setheapoverride(true);
|
setheapoverride(true);
|
||||||
heap_replace(procrel, &tup->t_self, newtup);
|
heap_replace(procrel, &tup->t_self, newtup, NULL);
|
||||||
setheapoverride(false);
|
setheapoverride(false);
|
||||||
|
|
||||||
setoid = newtup->t_data->t_oid;
|
setoid = newtup->t_data->t_oid;
|
||||||
@ -139,7 +139,7 @@ SetDefine(char *querystr, char *typename)
|
|||||||
CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup);
|
CatalogIndexInsert(idescs, Num_pg_proc_indices, procrel, newtup);
|
||||||
CatalogCloseIndices(Num_pg_proc_indices, idescs);
|
CatalogCloseIndices(Num_pg_proc_indices, idescs);
|
||||||
}
|
}
|
||||||
RelationUnsetLockForWrite(procrel);
|
UnlockRelation(procrel, AccessExclusiveLock);
|
||||||
heap_close(procrel);
|
heap_close(procrel);
|
||||||
}
|
}
|
||||||
return setoid;
|
return setoid;
|
||||||
|
12
src/backend/utils/cache/relcache.c
vendored
12
src/backend/utils/cache/relcache.c
vendored
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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);
|
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_scan = heap_beginscan(pg_class_desc, 0, SnapshotNow, 1, &key);
|
||||||
pg_class_tuple = heap_getnext(pg_class_scan, 0);
|
pg_class_tuple = heap_getnext(pg_class_scan, 0);
|
||||||
|
|
||||||
@ -388,8 +386,6 @@ scan_pg_rel_seq(RelationBuildDescInfo buildinfo)
|
|||||||
|
|
||||||
/* all done */
|
/* all done */
|
||||||
heap_endscan(pg_class_scan);
|
heap_endscan(pg_class_scan);
|
||||||
if (!IsInitProcessingMode())
|
|
||||||
RelationUnsetLockForRead(pg_class_desc);
|
|
||||||
heap_close(pg_class_desc);
|
heap_close(pg_class_desc);
|
||||||
|
|
||||||
return return_tuple;
|
return return_tuple;
|
||||||
@ -403,7 +399,7 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
|
|||||||
|
|
||||||
pg_class_desc = heap_openr(RelationRelationName);
|
pg_class_desc = heap_openr(RelationRelationName);
|
||||||
if (!IsInitProcessingMode())
|
if (!IsInitProcessingMode())
|
||||||
RelationSetLockForRead(pg_class_desc);
|
LockRelation(pg_class_desc, AccessShareLock);
|
||||||
|
|
||||||
switch (buildinfo.infotype)
|
switch (buildinfo.infotype)
|
||||||
{
|
{
|
||||||
@ -428,7 +424,7 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
|
|||||||
|
|
||||||
/* all done */
|
/* all done */
|
||||||
if (!IsInitProcessingMode())
|
if (!IsInitProcessingMode())
|
||||||
RelationUnsetLockForRead(pg_class_desc);
|
UnlockRelation(pg_class_desc, AccessShareLock);
|
||||||
heap_close(pg_class_desc);
|
heap_close(pg_class_desc);
|
||||||
|
|
||||||
return return_tuple;
|
return return_tuple;
|
||||||
@ -1126,7 +1122,6 @@ RelationIdCacheGetRelation(Oid relationId)
|
|||||||
}
|
}
|
||||||
|
|
||||||
RelationIncrementReferenceCount(rd);
|
RelationIncrementReferenceCount(rd);
|
||||||
RelationSetLockForDescriptorOpen(rd);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1159,7 +1154,6 @@ RelationNameCacheGetRelation(char *relationName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
RelationIncrementReferenceCount(rd);
|
RelationIncrementReferenceCount(rd);
|
||||||
RelationSetLockForDescriptorOpen(rd);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
extern bool PostgresIsInitialized;
|
||||||
|
|
||||||
|
SnapshotData SnapshotDirtyData;
|
||||||
|
Snapshot SnapshotDirty = &SnapshotDirtyData;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX Transaction system override hacks start here
|
* XXX Transaction system override hacks start here
|
||||||
*/
|
*/
|
||||||
@ -88,8 +91,9 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
|
|||||||
{
|
{
|
||||||
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
|
if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
|
||||||
return true;
|
return true;
|
||||||
else
|
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
||||||
return false;
|
return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TransactionIdDidCommit(tuple->t_xmin))
|
if (!TransactionIdDidCommit(tuple->t_xmin))
|
||||||
@ -107,10 +111,18 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
|
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 (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
|
||||||
|
{
|
||||||
|
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!TransactionIdDidCommit(tuple->t_xmax))
|
if (!TransactionIdDidCommit(tuple->t_xmax))
|
||||||
{
|
{
|
||||||
@ -122,6 +134,9 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
|
|||||||
/* by here, deleting transaction has committed */
|
/* by here, deleting transaction has committed */
|
||||||
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
||||||
|
|
||||||
|
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
||||||
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,13 +167,6 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
|
|||||||
* (Xmax is not committed && the row was deleted by another transaction
|
* (Xmax is not committed && the row was deleted by another transaction
|
||||||
* Xmax != my-transaction)))) that has not been committed
|
* 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;
|
* 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
|
* 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
|
* 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));
|
Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
|
||||||
|
|
||||||
|
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (CommandIdGEScanCommandId(tuple->t_cmax))
|
if (CommandIdGEScanCommandId(tuple->t_cmax))
|
||||||
return true; /* deleted after scan started */
|
return true; /* deleted after scan started */
|
||||||
else
|
else
|
||||||
@ -229,10 +240,16 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
|
if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
|
||||||
|
{
|
||||||
|
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
|
if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
|
||||||
{
|
{
|
||||||
|
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
||||||
|
return true;
|
||||||
if (CommandIdGEScanCommandId(tuple->t_cmax))
|
if (CommandIdGEScanCommandId(tuple->t_cmax))
|
||||||
return true; /* deleted after scan started */
|
return true; /* deleted after scan started */
|
||||||
else
|
else
|
||||||
@ -249,5 +266,173 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
|
|||||||
/* xmax transaction committed */
|
/* xmax transaction committed */
|
||||||
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
tuple->t_infomask |= HEAP_XMAX_COMMITTED;
|
||||||
|
|
||||||
|
if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
|
||||||
|
return true;
|
||||||
|
|
||||||
return false;
|
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 */
|
||||||
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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_insert;
|
||||||
int global_delete;
|
int global_delete;
|
||||||
int global_replace;
|
int global_replace;
|
||||||
|
int global_mark4update;
|
||||||
int global_markpos;
|
int global_markpos;
|
||||||
int global_restrpos;
|
int global_restrpos;
|
||||||
int global_BufferGetRelation;
|
int global_BufferGetRelation;
|
||||||
@ -64,6 +65,7 @@ typedef struct HeapAccessStatisticsData
|
|||||||
int local_insert;
|
int local_insert;
|
||||||
int local_delete;
|
int local_delete;
|
||||||
int local_replace;
|
int local_replace;
|
||||||
|
int local_mark4update;
|
||||||
int local_markpos;
|
int local_markpos;
|
||||||
int local_restrpos;
|
int local_restrpos;
|
||||||
int local_BufferGetRelation;
|
int local_BufferGetRelation;
|
||||||
@ -253,9 +255,10 @@ extern void heap_endscan(HeapScanDesc scan);
|
|||||||
extern HeapTuple heap_getnext(HeapScanDesc scandesc, int backw);
|
extern HeapTuple heap_getnext(HeapScanDesc scandesc, int backw);
|
||||||
extern void heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tup, Buffer *userbuf);
|
extern void heap_fetch(Relation relation, Snapshot snapshot, HeapTuple tup, Buffer *userbuf);
|
||||||
extern Oid heap_insert(Relation relation, HeapTuple tup);
|
extern Oid heap_insert(Relation relation, HeapTuple tup);
|
||||||
extern int heap_delete(Relation relation, ItemPointer tid);
|
extern int heap_delete(Relation relation, ItemPointer tid, ItemPointer ctid);
|
||||||
extern int heap_replace(Relation relation, ItemPointer otid,
|
extern int heap_replace(Relation relation, ItemPointer otid, HeapTuple tup,
|
||||||
HeapTuple tup);
|
ItemPointer ctid);
|
||||||
|
extern int heap_mark4update(Relation relation, HeapTuple tup, Buffer *userbuf);
|
||||||
extern void heap_markpos(HeapScanDesc scan);
|
extern void heap_markpos(HeapScanDesc scan);
|
||||||
extern void heap_restrpos(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 PrintHeapAccessStatistics(HeapAccessStatistics stats);
|
||||||
extern void initam(void);
|
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 */
|
#endif /* HEAPAM_H */
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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>
|
#include <utils/rel.h>
|
||||||
|
|
||||||
|
|
||||||
extern void RelationPutHeapTuple(Relation relation, BlockNumber blockIndex,
|
extern void RelationPutHeapTuple(Relation relation, Buffer buffer,
|
||||||
HeapTuple tuple);
|
HeapTuple tuple);
|
||||||
extern void RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple);
|
extern void RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple);
|
||||||
|
|
||||||
#endif /* HIO_H */
|
#endif /* HIO_H */
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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_XMIN_INVALID 0x0200 /* t_xmin invalid/aborted */
|
||||||
#define HEAP_XMAX_COMMITTED 0x0400 /* t_xmax committed */
|
#define HEAP_XMAX_COMMITTED 0x0400 /* t_xmax committed */
|
||||||
#define HEAP_XMAX_INVALID 0x0800 /* t_xmax invalid/aborted */
|
#define HEAP_XMAX_INVALID 0x0800 /* t_xmax invalid/aborted */
|
||||||
|
#define HEAP_MARKED_FOR_UPDATE 0x1000 /* marked for UPDATE */
|
||||||
|
|
||||||
#define HEAP_XACT_MASK 0x0F00 /* */
|
#define HEAP_XACT_MASK 0x0F00 /* */
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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_REPEATABLE_READ 2 /* not implemented */
|
||||||
#define XACT_SERIALIZED 3
|
#define XACT_SERIALIZED 3
|
||||||
|
|
||||||
|
extern int XactIsoLevel;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* transaction states
|
* transaction states
|
||||||
* ----------------
|
* ----------------
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
* NOTES
|
||||||
* the genbki.sh script reads this file and generates .bki
|
* the genbki.sh script reads this file and generates .bki
|
||||||
@ -106,6 +106,7 @@ DESCR("");
|
|||||||
#define BTREE_AM_OID 403
|
#define BTREE_AM_OID 403
|
||||||
DATA(insert OID = 405 ( hash PGUID "o" 1 1 hashgettuple hashinsert hashdelete - - - - hashbeginscan hashrescan hashendscan hashmarkpos hashrestrpos - - hashbuild - - ));
|
DATA(insert OID = 405 ( hash PGUID "o" 1 1 hashgettuple hashinsert hashdelete - - - - hashbeginscan hashrescan hashendscan hashmarkpos hashrestrpos - - hashbuild - - ));
|
||||||
DESCR("");
|
DESCR("");
|
||||||
|
#define HASH_AM_OID 405
|
||||||
DATA(insert OID = 783 ( gist PGUID "o" 100 7 gistgettuple gistinsert gistdelete - - - - gistbeginscan gistrescan gistendscan gistmarkpos gistrestrpos - - gistbuild - - ));
|
DATA(insert OID = 783 ( gist PGUID "o" 100 7 gistgettuple gistinsert gistdelete - - - - gistbeginscan gistrescan gistendscan gistmarkpos gistrestrpos - - gistbuild - - ));
|
||||||
DESCR("");
|
DESCR("");
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
* NOTES
|
||||||
* ``pg_relation'' is being replaced by ``pg_class''. currently
|
* ``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("");
|
DESCR("");
|
||||||
DATA(insert OID = 1269 ( pg_log 99 PGUID 0 0 0 f t s 1 0 0 0 0 0 f f _null_ ));
|
DATA(insert OID = 1269 ( pg_log 99 PGUID 0 0 0 f t s 1 0 0 0 0 0 f f _null_ ));
|
||||||
DESCR("");
|
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_ ));
|
DATA(insert OID = 1215 ( pg_attrdef 109 PGUID 0 0 0 t t r 4 0 0 0 0 0 f f _null_ ));
|
||||||
DESCR("");
|
DESCR("");
|
||||||
DATA(insert OID = 1216 ( pg_relcheck 110 PGUID 0 0 0 t t r 4 0 0 0 0 0 f f _null_ ));
|
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_relcheck 1216
|
||||||
#define RelOid_pg_trigger 1219
|
#define RelOid_pg_trigger 1219
|
||||||
|
|
||||||
|
/* Xact lock pseudo-table */
|
||||||
|
#define XactLockTableId 376
|
||||||
|
|
||||||
#define RELKIND_INDEX 'i' /* secondary index */
|
#define RELKIND_INDEX 'i' /* secondary index */
|
||||||
#define RELKIND_LOBJECT 'l' /* large objects */
|
#define RELKIND_LOBJECT 'l' /* large objects */
|
||||||
#define RELKIND_RELATION 'r' /* cataloged heap */
|
#define RELKIND_RELATION 'r' /* cataloged heap */
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "access/tupdesc.h"
|
#include "access/tupdesc.h"
|
||||||
#include "access/htup.h"
|
#include "access/htup.h"
|
||||||
#include "nodes/parsenodes.h"
|
#include "nodes/parsenodes.h"
|
||||||
|
#include "nodes/execnodes.h"
|
||||||
#include "utils/rel.h"
|
#include "utils/rel.h"
|
||||||
|
|
||||||
typedef uint32 TriggerEvent;
|
typedef uint32 TriggerEvent;
|
||||||
@ -65,9 +66,9 @@ extern void RelationRemoveTriggers(Relation rel);
|
|||||||
|
|
||||||
extern HeapTuple ExecBRInsertTriggers(Relation rel, HeapTuple tuple);
|
extern HeapTuple ExecBRInsertTriggers(Relation rel, HeapTuple tuple);
|
||||||
extern void ExecARInsertTriggers(Relation rel, HeapTuple tuple);
|
extern void ExecARInsertTriggers(Relation rel, HeapTuple tuple);
|
||||||
extern bool ExecBRDeleteTriggers(Relation rel, ItemPointer tupleid);
|
extern bool ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid);
|
||||||
extern void ExecARDeleteTriggers(Relation rel, ItemPointer tupleid);
|
extern void ExecARDeleteTriggers(EState *estate, ItemPointer tupleid);
|
||||||
extern HeapTuple ExecBRUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple tuple);
|
extern HeapTuple ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple tuple);
|
||||||
extern void ExecARUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple tuple);
|
extern void ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple tuple);
|
||||||
|
|
||||||
#endif /* TRIGGER_H */
|
#endif /* TRIGGER_H */
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
* NOTE
|
||||||
* If BUFFERPAGE0 is defined, then 0 will be used as a
|
* 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
|
* Dbname, relname, dbid, and relid are enough to determine where
|
||||||
* to put the buffer, for all storage managers.
|
* 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
|
struct sbufdesc
|
||||||
{
|
{
|
||||||
Buffer freeNext; /* link for freelist chain */
|
Buffer freeNext; /* link for freelist chain */
|
||||||
@ -125,31 +99,25 @@ struct sbufdesc
|
|||||||
#ifdef HAS_TEST_AND_SET
|
#ifdef HAS_TEST_AND_SET
|
||||||
/* can afford a dedicated lock if test-and-set locks are available */
|
/* can afford a dedicated lock if test-and-set locks are available */
|
||||||
slock_t io_in_progress_lock;
|
slock_t io_in_progress_lock;
|
||||||
|
slock_t cntx_lock; /* to lock access to page context */
|
||||||
#endif /* HAS_TEST_AND_SET */
|
#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 */
|
char sb_dbname[NAMEDATALEN]; /* name of db in which buf belongs */
|
||||||
|
char sb_relname[NAMEDATALEN];/* name of reln */
|
||||||
/*
|
|
||||||
* 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)];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* mao tracing buffer allocation
|
||||||
*/
|
*/
|
||||||
@ -201,6 +169,7 @@ extern BufferDesc *BufferDescriptors;
|
|||||||
extern BufferBlock BufferBlocks;
|
extern BufferBlock BufferBlocks;
|
||||||
extern long *PrivateRefCount;
|
extern long *PrivateRefCount;
|
||||||
extern long *LastRefCount;
|
extern long *LastRefCount;
|
||||||
|
extern bits8 *BufferLocks;
|
||||||
extern long *CommitInfoNeedsSave;
|
extern long *CommitInfoNeedsSave;
|
||||||
extern SPINLOCK BufMgrLock;
|
extern SPINLOCK BufMgrLock;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: bufmgr.h,v 1.23 1998/10/08 18:30:43 momjian Exp $
|
* $Id: bufmgr.h,v 1.24 1998/12/15 12:46:56 vadim Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -73,6 +73,14 @@ extern int ShowPinTrace;
|
|||||||
#define BUFFER_FLUSH_WRITE 0 /* immediate write */
|
#define BUFFER_FLUSH_WRITE 0 /* immediate write */
|
||||||
#define BUFFER_LATE_WRITE 1 /* delayed write: mark as DIRTY */
|
#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 --
|
* BufferIsValid --
|
||||||
* True iff the refcnt of the local buffer is > 0
|
* True iff the refcnt of the local buffer is > 0
|
||||||
@ -155,4 +163,7 @@ extern void BufferRefCountRestore(int *refcountsave);
|
|||||||
extern int SetBufferWriteMode(int mode);
|
extern int SetBufferWriteMode(int mode);
|
||||||
extern void SetBufferCommitInfoNeedsSave(Buffer buffer);
|
extern void SetBufferCommitInfoNeedsSave(Buffer buffer);
|
||||||
|
|
||||||
|
extern void UnlockBuffers(void);
|
||||||
|
extern void LockBuffer(Buffer buffer, int mode);
|
||||||
|
|
||||||
#endif /* !defined(BufMgrIncluded) */
|
#endif /* !defined(BufMgrIncluded) */
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
* NOTES
|
||||||
* This file is very architecture-specific. This stuff should actually
|
* This file is very architecture-specific. This stuff should actually
|
||||||
@ -186,6 +186,8 @@ typedef enum _LockId_
|
|||||||
((key == PrivateIPCKey) ? key : 11 + (key))
|
((key == PrivateIPCKey) ? key : 11 + (key))
|
||||||
#define IPCKeyGetWaitIOSemaphoreKey(key) \
|
#define IPCKeyGetWaitIOSemaphoreKey(key) \
|
||||||
((key == PrivateIPCKey) ? key : 12 + (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
|
* NOTE: This macro must always give the highest numbered key as every backend
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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 <utils/rel.h>
|
||||||
#include <catalog/catname.h>
|
#include <catalog/catname.h>
|
||||||
|
|
||||||
/*
|
#define AccessShareLock 1 /* SELECT */
|
||||||
* This was moved from pladt.h for the new lock manager. Want to obsolete
|
#define RowShareLock 2 /* SELECT FOR UPDATE */
|
||||||
* all of the old code.
|
#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
|
typedef struct LockRelId
|
||||||
{
|
{
|
||||||
Oid relId; /* a relation identifier */
|
Oid relId; /* a relation identifier */
|
||||||
Oid dbId; /* a database identifier */
|
Oid dbId; /* a database identifier */
|
||||||
} LockRelId;
|
} LockRelId;
|
||||||
|
|
||||||
#ifdef LowLevelLocking
|
|
||||||
typedef struct LockInfoData
|
|
||||||
{
|
|
||||||
LockRelId lockRelId;
|
|
||||||
bool lockHeld[MAX_LOCKMODES]; /* on table level */
|
|
||||||
} LockInfoData;
|
|
||||||
|
|
||||||
#else
|
|
||||||
typedef struct LockInfoData
|
typedef struct LockInfoData
|
||||||
{
|
{
|
||||||
LockRelId lockRelId;
|
LockRelId lockRelId;
|
||||||
} LockInfoData;
|
} LockInfoData;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef LockInfoData *LockInfo;
|
typedef LockInfoData *LockInfo;
|
||||||
|
|
||||||
#define LockInfoIsValid(lockinfo) PointerIsValid(lockinfo)
|
#define LockInfoIsValid(lockinfo) PointerIsValid(lockinfo)
|
||||||
|
|
||||||
|
extern LOCKMETHOD InitLockTable(void);
|
||||||
extern void RelationInitLockInfo(Relation relation);
|
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 LockRelation(Relation relation, LOCKMODE lockmode);
|
||||||
extern void RelationSetLockForWritePage(Relation relation,
|
extern void UnlockRelation(Relation relation, LOCKMODE lockmode);
|
||||||
ItemPointer itemPointer);
|
|
||||||
|
|
||||||
/* used in nbtpage.c, hashpage.c */
|
/* this is for indices */
|
||||||
extern void RelationSetSingleWLockPage(Relation relation,
|
extern void LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
|
||||||
ItemPointer itemPointer);
|
extern void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
|
||||||
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);
|
|
||||||
|
|
||||||
/* single.c */
|
/* and this is for transactions */
|
||||||
extern bool SingleLockReln(LockInfo lockinfo, LOCKMODE lockmode, int action);
|
extern void XactLockTableInsert(TransactionId xid);
|
||||||
extern bool SingleLockPage(LockInfo lockinfo, ItemPointer tidPtr,
|
extern void XactLockTableDelete(TransactionId xid);
|
||||||
LOCKMODE lockmode, int action);
|
extern void XactLockTableWait(TransactionId xid);
|
||||||
|
|
||||||
/* proc.c */
|
/* proc.c */
|
||||||
extern void InitProcGlobal(IPCKey key);
|
extern void InitProcGlobal(IPCKey key);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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;
|
typedef int LOCKMETHOD;
|
||||||
|
|
||||||
/* MAX_LOCKMODES cannot be larger than the bits in MASK */
|
/* MAX_LOCKMODES cannot be larger than the bits in MASK */
|
||||||
#ifdef LowLevelLocking
|
|
||||||
#define MAX_LOCKMODES 9
|
#define MAX_LOCKMODES 9
|
||||||
#else
|
|
||||||
#define MAX_LOCKMODES 6
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MAX_LOCK_METHODS corresponds to the number of spin locks allocated in
|
* MAX_LOCK_METHODS corresponds to the number of spin locks allocated in
|
||||||
@ -69,7 +65,11 @@ typedef struct LTAG
|
|||||||
{
|
{
|
||||||
Oid relId;
|
Oid relId;
|
||||||
Oid dbId;
|
Oid dbId;
|
||||||
ItemPointerData tupleId;
|
union
|
||||||
|
{
|
||||||
|
BlockNumber blkno;
|
||||||
|
TransactionId xid;
|
||||||
|
} objId;
|
||||||
uint16 lockmethod; /* needed by user locks */
|
uint16 lockmethod; /* needed by user locks */
|
||||||
} LOCKTAG;
|
} LOCKTAG;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
TransactionId xid; /* transaction currently being executed by
|
||||||
* this proc */
|
* this proc */
|
||||||
|
|
||||||
#ifdef LowLevelLocking
|
|
||||||
TransactionId xmin; /* minimal running XID as it was when we
|
TransactionId xmin; /* minimal running XID as it was when we
|
||||||
* were starting our xact: vacuum must not
|
* were starting our xact: vacuum must not
|
||||||
* remove tuples deleted by xid >= xmin ! */
|
* remove tuples deleted by xid >= xmin ! */
|
||||||
#endif
|
|
||||||
|
|
||||||
LOCK *waitLock; /* Lock we're sleeping on */
|
LOCK *waitLock; /* Lock we're sleeping on */
|
||||||
int token; /* info for proc wakeup routines */
|
int token; /* info for proc wakeup routines */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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"
|
#include "storage/ipc.h"
|
||||||
|
|
||||||
|
extern void s_lock_sleep(unsigned spin);
|
||||||
|
|
||||||
#if defined(HAS_TEST_AND_SET)
|
#if defined(HAS_TEST_AND_SET)
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 1994, Regents of the University of California
|
* 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
|
typedef struct SnapshotData
|
||||||
{
|
{
|
||||||
TransactionId xmin; /* XID < xmin are visible to me */
|
TransactionId xmin; /* XID < xmin are visible to me */
|
||||||
TransactionId xmax; /* XID > xmax are invisible to me */
|
TransactionId xmax; /* XID > xmax are invisible to me */
|
||||||
TransactionId *xip; /* array of xacts in progress */
|
TransactionId *xip; /* array of xacts in progress */
|
||||||
} SnapshotData;
|
} SnapshotData;
|
||||||
|
|
||||||
typedef SnapshotData *Snapshot;
|
typedef SnapshotData *Snapshot;
|
||||||
|
|
||||||
#define IsSnapshotNow(snapshot) ((Snapshot) snapshot == (Snapshot) 0x0)
|
|
||||||
#define IsSnapshotSelf(snapshot) ((Snapshot) snapshot == (Snapshot) 0x1)
|
|
||||||
#define SnapshotNow ((Snapshot) 0x0)
|
#define SnapshotNow ((Snapshot) 0x0)
|
||||||
#define SnapshotSelf ((Snapshot) 0x1)
|
#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 TransactionId HeapSpecialTransactionId;
|
||||||
extern CommandId HeapSpecialCommandId;
|
extern CommandId HeapSpecialCommandId;
|
||||||
@ -49,7 +52,11 @@ extern CommandId HeapSpecialCommandId;
|
|||||||
(IsSnapshotSelf(snapshot) || heapisoverride()) ? \
|
(IsSnapshotSelf(snapshot) || heapisoverride()) ? \
|
||||||
HeapTupleSatisfiesItself((tuple)->t_data) \
|
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);
|
#define HeapTupleMayBeUpdated 0
|
||||||
extern bool HeapTupleSatisfiesNow(HeapTupleHeader tuple);
|
#define HeapTupleInvisible 1
|
||||||
|
#define HeapTupleSelfUpdated 2
|
||||||
|
#define HeapTupleUpdated 3
|
||||||
|
#define HeapTupleBeingUpdated 4
|
||||||
|
|
||||||
|
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 void setheapoverride(bool on);
|
||||||
|
extern Snapshot GetSnapshotData(bool serialized);
|
||||||
|
|
||||||
#endif /* TQUAL_H */
|
#endif /* TQUAL_H */
|
||||||
|
Reference in New Issue
Block a user