Index: contrib/userlock/user_locks.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/contrib/userlock/user_locks.c,v
retrieving revision 1.14
diff -c -r1.14 user_locks.c
*** contrib/userlock/user_locks.c 27 Aug 2004 17:07:41 -0000 1.14
--- contrib/userlock/user_locks.c 19 Dec 2004 17:12:30 -0000
***************
*** 25,32 ****
memset(&tag, 0, sizeof(LOCKTAG));
tag.dbId = MyDatabaseId;
! tag.relId = 0;
! tag.objId.blkno = (BlockNumber) id2;
tag.offnum = (OffsetNumber) (id1 & 0xffff);
return LockAcquire(USER_LOCKMETHOD, &tag, InvalidTransactionId,
--- 25,33 ----
memset(&tag, 0, sizeof(LOCKTAG));
tag.dbId = MyDatabaseId;
! tag.classId = InvalidOid;
! tag.objId = InvalidOid;
! tag.objsubId.blkno = (BlockNumber) id2;
tag.offnum = (OffsetNumber) (id1 & 0xffff);
return LockAcquire(USER_LOCKMETHOD, &tag, InvalidTransactionId,
***************
*** 40,47 ****
memset(&tag, 0, sizeof(LOCKTAG));
tag.dbId = MyDatabaseId;
! tag.relId = 0;
! tag.objId.blkno = (BlockNumber) id2;
tag.offnum = (OffsetNumber) (id1 & 0xffff);
return LockRelease(USER_LOCKMETHOD, &tag, InvalidTransactionId, lockmode);
--- 41,49 ----
memset(&tag, 0, sizeof(LOCKTAG));
tag.dbId = MyDatabaseId;
! tag.classId = InvalidOid;
! tag.objId = InvalidOid;
! tag.objsubId.blkno = (BlockNumber) id2;
tag.offnum = (OffsetNumber) (id1 & 0xffff);
return LockRelease(USER_LOCKMETHOD, &tag, InvalidTransactionId, lockmode);
Index: doc/src/sgml/catalogs.sgml
===================================================================
RCS file: /home/alvherre/cvs/pgsql/doc/src/sgml/catalogs.sgml,v
retrieving revision 2.94
diff -c -r2.94 catalogs.sgml
*** doc/src/sgml/catalogs.sgml 13 Dec 2004 18:05:07 -0000 2.94
--- doc/src/sgml/catalogs.sgml 19 Dec 2004 17:02:13 -0000
***************
*** 3958,3975 ****
pg_locks contains one row per active lockable
object, requested lock mode, and relevant transaction. Thus, the same
! lockable object may
! appear many times, if multiple transactions are holding or waiting
! for locks on it. However, an object that currently has no locks on it
! will not appear at all. A lockable object is either a relation (e.g., a
! table) or a transaction ID.
! Note that this view includes only table-level
! locks, not row-level ones. If a transaction is waiting for a
! row-level lock, it will appear in the view as waiting for the
! transaction ID of the current holder of that row lock.
--- 3958,3973 ----
pg_locks contains one row per active lockable
object, requested lock mode, and relevant transaction. Thus, the same
! lockable object may appear many times, if multiple transactions are holding
! or waiting for locks on it. However, an object that currently has no locks
! on it will not appear at all. A lockable object is either a relation (e.g.,
! a table) or a transaction ID.
! Note that this view includes only table-level locks, not row-level ones. If
! a transaction is waiting for a row-level lock, it will appear in the view as
! waiting for the transaction ID of the current holder of that row lock.
***************
*** 3986,3996 ****
! relationoidpg_class.oid
! OID of the locked relation, or NULL if the lockable object
is a transaction ID
--- 3984,4003 ----
! classoidpg_class.oid
! The OID of the system catalog the locked object is in, or NULL if the
! lockable object is a transaction ID
!
!
!
! relation
! oid
! any OID column
!
! OID of the locked object, or NULL if the lockable object
is a transaction ID
Index: src/backend/catalog/system_views.sql
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/system_views.sql,v
retrieving revision 1.10
diff -c -r1.10 system_views.sql
*** src/backend/catalog/system_views.sql 11 Oct 2004 17:24:40 -0000 1.10
--- src/backend/catalog/system_views.sql 19 Dec 2004 16:30:10 -0000
***************
*** 258,264 ****
CREATE VIEW pg_locks AS
SELECT *
! FROM pg_lock_status() AS L(relation oid, database oid,
transaction xid, pid int4, mode text, granted boolean);
CREATE VIEW pg_settings AS
--- 258,264 ----
CREATE VIEW pg_locks AS
SELECT *
! FROM pg_lock_status() AS L(object oid, class oid, database oid,
transaction xid, pid int4, mode text, granted boolean);
CREATE VIEW pg_settings AS
Index: src/backend/storage/lmgr/README
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/storage/lmgr/README,v
retrieving revision 1.15
diff -c -r1.15 README
*** src/backend/storage/lmgr/README 27 Aug 2004 17:07:41 -0000 1.15
--- src/backend/storage/lmgr/README 19 Dec 2004 18:07:48 -0000
***************
*** 79,93 ****
any alignment-padding bytes the compiler might insert in the struct
be zeroed out, else the hash computation will be random.
! tag.relId -
! Uniquely identifies the relation that the lock corresponds to.
tag.dbId -
Uniquely identifies the database in which the relation lives. If
this is a shared system relation (e.g. pg_database) the dbId must
be set to 0.
! tag.objId -
Uniquely identifies the block/page within the relation and the
tuple within the block. If we are setting a table level lock
both the blockId and tupleId (in an item pointer this is called
--- 79,100 ----
any alignment-padding bytes the compiler might insert in the struct
be zeroed out, else the hash computation will be random.
! tag.classId -
! Uniquely identifies the object class that the lock corresponds to.
! To lock a relation, RelOid_pg_class is used, and XactLockTableId
! to lock a transaction. Other objects can be locked using the Oid
! of the system catalog they belong to.
!
! tag.objId -
! Uniquely identifies the object within the class that the lock
! corresponds to.
tag.dbId -
Uniquely identifies the database in which the relation lives. If
this is a shared system relation (e.g. pg_database) the dbId must
be set to 0.
! tag.objsubId -
Uniquely identifies the block/page within the relation and the
tuple within the block. If we are setting a table level lock
both the blockId and tupleId (in an item pointer this is called
Index: src/backend/storage/lmgr/deadlock.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/storage/lmgr/deadlock.c,v
retrieving revision 1.31
diff -c -r1.31 deadlock.c
*** src/backend/storage/lmgr/deadlock.c 29 Aug 2004 04:12:48 -0000 1.31
--- src/backend/storage/lmgr/deadlock.c 19 Dec 2004 18:49:46 -0000
***************
*** 860,883 ****
if (i > 0)
appendStringInfoChar(&buf, '\n');
! if (info->locktag.relId == XactLockTableId && info->locktag.dbId == 0)
{
/* Lock is for transaction ID */
appendStringInfo(&buf,
gettext("Process %d waits for %s on transaction %u; blocked by process %d."),
info->pid,
GetLockmodeName(info->lockmode),
! info->locktag.objId.xid,
nextpid);
}
! else
{
/* Lock is for a relation */
appendStringInfo(&buf,
gettext("Process %d waits for %s on relation %u of database %u; blocked by process %d."),
info->pid,
GetLockmodeName(info->lockmode),
! info->locktag.relId,
info->locktag.dbId,
nextpid);
}
--- 860,909 ----
if (i > 0)
appendStringInfoChar(&buf, '\n');
! if (info->locktag.objId == InvalidOid &&
! info->locktag.classId == XactLockTableId &&
! info->locktag.dbId == InvalidOid)
{
/* Lock is for transaction ID */
appendStringInfo(&buf,
gettext("Process %d waits for %s on transaction %u; blocked by process %d."),
info->pid,
GetLockmodeName(info->lockmode),
! info->locktag.objsubId.xid,
nextpid);
}
! else if (info->locktag.dbId != InvalidOid &&
! info->locktag.classId == RelOid_pg_class)
{
/* Lock is for a relation */
appendStringInfo(&buf,
gettext("Process %d waits for %s on relation %u of database %u; blocked by process %d."),
info->pid,
GetLockmodeName(info->lockmode),
! info->locktag.objId,
! info->locktag.dbId,
! nextpid);
! }
! else if (info->locktag.dbId == InvalidOid)
! {
! /* Lock is for a shared object */
! appendStringInfo(&buf,
! gettext("Process %d waits for %s on object %u of class %u; blocked by process %d."),
! info->pid,
! GetLockmodeName(info->lockmode),
! info->locktag.objId,
! info->locktag.classId,
! nextpid);
! }
! else
! {
! /* Lock is for an object of another class */
! appendStringInfo(&buf,
! gettext("Process %d waits for %s on object %u of class %u of database %u; blocked by process %d."),
! info->pid,
! GetLockmodeName(info->lockmode),
! info->locktag.objId,
! info->locktag.classId,
info->locktag.dbId,
nextpid);
}
Index: src/backend/storage/lmgr/lmgr.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/storage/lmgr/lmgr.c,v
retrieving revision 1.70
diff -c -r1.70 lmgr.c
*** src/backend/storage/lmgr/lmgr.c 16 Sep 2004 16:58:33 -0000 1.70
--- src/backend/storage/lmgr/lmgr.c 19 Dec 2004 15:28:56 -0000
***************
*** 134,142 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objId.blkno = InvalidBlockNumber;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, false))
--- 134,143 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relation->rd_lockInfo.lockRelId.relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objsubId.blkno = InvalidBlockNumber;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, false))
***************
*** 168,176 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objId.blkno = InvalidBlockNumber;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, true))
--- 169,178 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relation->rd_lockInfo.lockRelId.relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objsubId.blkno = InvalidBlockNumber;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, true))
***************
*** 198,206 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objId.blkno = InvalidBlockNumber;
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
}
--- 200,209 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relation->rd_lockInfo.lockRelId.relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objsubId.blkno = InvalidBlockNumber;
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
}
***************
*** 223,231 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relid->relId;
tag.dbId = relid->dbId;
! tag.objId.blkno = InvalidBlockNumber;
if (!LockAcquire(LockTableId, &tag, InvalidTransactionId,
lockmode, false))
--- 226,235 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relid->relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relid->dbId;
! tag.objsubId.blkno = InvalidBlockNumber;
if (!LockAcquire(LockTableId, &tag, InvalidTransactionId,
lockmode, false))
***************
*** 241,249 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relid->relId;
tag.dbId = relid->dbId;
! tag.objId.blkno = InvalidBlockNumber;
LockRelease(LockTableId, &tag, InvalidTransactionId, lockmode);
}
--- 245,254 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relid->relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relid->dbId;
! tag.objsubId.blkno = InvalidBlockNumber;
LockRelease(LockTableId, &tag, InvalidTransactionId, lockmode);
}
***************
*** 261,269 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objId.blkno = blkno;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, false))
--- 266,275 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relation->rd_lockInfo.lockRelId.relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objsubId.blkno = blkno;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, false))
***************
*** 282,290 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objId.blkno = blkno;
return LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, true);
--- 288,297 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relation->rd_lockInfo.lockRelId.relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objsubId.blkno = blkno;
return LockAcquire(LockTableId, &tag, GetTopTransactionId(),
lockmode, true);
***************
*** 299,307 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = relation->rd_lockInfo.lockRelId.relId;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objId.blkno = blkno;
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
}
--- 306,315 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = relation->rd_lockInfo.lockRelId.relId;
! tag.classId = RelOid_pg_class;
tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
! tag.objsubId.blkno = blkno;
LockRelease(LockTableId, &tag, GetTopTransactionId(), lockmode);
}
***************
*** 319,327 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = XactLockTableId;
tag.dbId = InvalidOid; /* xids are globally unique */
! tag.objId.xid = xid;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
ExclusiveLock, false))
--- 327,336 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = InvalidOid;
! tag.classId = XactLockTableId;
tag.dbId = InvalidOid; /* xids are globally unique */
! tag.objsubId.xid = xid;
if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
ExclusiveLock, false))
***************
*** 342,350 ****
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.relId = XactLockTableId;
tag.dbId = InvalidOid; /* xids are globally unique */
! tag.objId.xid = xid;
LockRelease(LockTableId, &tag, GetTopTransactionId(), ExclusiveLock);
}
--- 351,360 ----
LOCKTAG tag;
MemSet(&tag, 0, sizeof(tag));
! tag.objId = InvalidOid;
! tag.classId = XactLockTableId;
tag.dbId = InvalidOid; /* xids are globally unique */
! tag.objsubId.xid = xid;
LockRelease(LockTableId, &tag, GetTopTransactionId(), ExclusiveLock);
}
***************
*** 373,381 ****
Assert(!TransactionIdEquals(xid, myxid));
MemSet(&tag, 0, sizeof(tag));
! tag.relId = XactLockTableId;
tag.dbId = InvalidOid;
! tag.objId.xid = xid;
if (!LockAcquire(LockTableId, &tag, myxid, ShareLock, false))
elog(ERROR, "LockAcquire failed");
--- 383,392 ----
Assert(!TransactionIdEquals(xid, myxid));
MemSet(&tag, 0, sizeof(tag));
! tag.objId = InvalidOid;
! tag.classId = XactLockTableId;
tag.dbId = InvalidOid;
! tag.objsubId.xid = xid;
if (!LockAcquire(LockTableId, &tag, myxid, ShareLock, false))
elog(ERROR, "LockAcquire failed");
***************
*** 393,395 ****
--- 404,462 ----
if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))
TransactionIdAbort(xid);
}
+
+ /*
+ * LockObject
+ *
+ * Lock an arbitrary database object. A standard relation lock would lock the
+ * classId of RelOid_pg_class and objId of the relations OID within the pg_class
+ * table. LockObject allows classId to be specified by the caller, thus allowing
+ * locks on any row in any system table.
+ *
+ * If classId is NOT a system table (protected from removal), an additional lock
+ * should be held on the relation to prevent it from being dropped.
+ */
+ void
+ LockObject(Oid objId, Oid classId, LOCKMODE lockmode)
+ {
+ LOCKTAG tag;
+
+ MemSet(&tag, 0, sizeof(tag));
+ tag.objId = objId;
+ tag.classId = classId;
+ tag.dbId = MyDatabaseId;
+ tag.objsubId.blkno = InvalidBlockNumber;
+
+ /* Only two reasonable lock types */
+ Assert(lockmode == AccessShareLock || lockmode == AccessExclusiveLock);
+
+ if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),
+ lockmode, false))
+ elog(ERROR, "LockObject: LockAcquire failed");
+ }
+
+ /*
+ * UnlockObject
+ */
+ void
+ UnlockObject(Oid objId, Oid classId, LOCKMODE lockmode)
+ {
+ LOCKTAG tag;
+
+ /* NoLock is a no-op */
+ if (lockmode == NoLock)
+ return;
+
+ MemSet(&tag, 0, sizeof(tag));
+ tag.objId = objId;
+ tag.classId = classId;
+ tag.dbId = MyDatabaseId;
+ tag.objsubId.blkno = InvalidBlockNumber;
+
+ /* Only two reasonable lock types */
+ Assert(lockmode == AccessShareLock
+ || lockmode == AccessExclusiveLock);
+
+ LockRelease(LockTableId, &tag, GetCurrentTransactionId(), lockmode);
+ }
+
Index: src/backend/storage/lmgr/lock.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/storage/lmgr/lock.c,v
retrieving revision 1.144
diff -c -r1.144 lock.c
*** src/backend/storage/lmgr/lock.c 20 Nov 2004 20:16:54 -0000 1.144
--- src/backend/storage/lmgr/lock.c 18 Dec 2004 23:45:34 -0000
***************
*** 110,117 ****
return
(((LOCK_LOCKMETHOD(*lock) == DEFAULT_LOCKMETHOD && Trace_locks)
|| (LOCK_LOCKMETHOD(*lock) == USER_LOCKMETHOD && Trace_userlocks))
! && (lock->tag.relId >= (Oid) Trace_lock_oidmin))
! || (Trace_lock_table && (lock->tag.relId == Trace_lock_table));
}
--- 110,117 ----
return
(((LOCK_LOCKMETHOD(*lock) == DEFAULT_LOCKMETHOD && Trace_locks)
|| (LOCK_LOCKMETHOD(*lock) == USER_LOCKMETHOD && Trace_userlocks))
! && (lock->tag.objId >= (Oid) Trace_lock_oidmin))
! || (Trace_lock_table && (lock->tag.objId == Trace_lock_table));
}
***************
*** 120,131 ****
{
if (LOCK_DEBUG_ENABLED(lock))
elog(LOG,
! "%s: lock(%lx) tbl(%d) rel(%u) db(%u) obj(%u) grantMask(%x) "
"req(%d,%d,%d,%d,%d,%d,%d)=%d "
"grant(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)",
where, MAKE_OFFSET(lock),
! lock->tag.lockmethodid, lock->tag.relId, lock->tag.dbId,
! lock->tag.objId.blkno, lock->grantMask,
lock->requested[1], lock->requested[2], lock->requested[3],
lock->requested[4], lock->requested[5], lock->requested[6],
lock->requested[7], lock->nRequested,
--- 120,131 ----
{
if (LOCK_DEBUG_ENABLED(lock))
elog(LOG,
! "%s: lock(%lx) tbl(%d) obj(%u) class(%u) db(%u) objsub(%u) grantMask(%x) "
"req(%d,%d,%d,%d,%d,%d,%d)=%d "
"grant(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)",
where, MAKE_OFFSET(lock),
! lock->tag.lockmethodid, lock->tag.objId, lock->tag.classId, lock->tag.dbId,
! lock->tag.objsubId.blkno, lock->grantMask,
lock->requested[1], lock->requested[2], lock->requested[3],
lock->requested[4], lock->requested[5], lock->requested[6],
lock->requested[7], lock->nRequested,
***************
*** 142,149 ****
if (
(((PROCLOCK_LOCKMETHOD(*proclockP) == DEFAULT_LOCKMETHOD && Trace_locks)
|| (PROCLOCK_LOCKMETHOD(*proclockP) == USER_LOCKMETHOD && Trace_userlocks))
! && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.relId >= (Oid) Trace_lock_oidmin))
! || (Trace_lock_table && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.relId == Trace_lock_table))
)
elog(LOG,
"%s: proclock(%lx) lock(%lx) tbl(%d) proc(%lx) xid(%u) hold(%x)",
--- 142,149 ----
if (
(((PROCLOCK_LOCKMETHOD(*proclockP) == DEFAULT_LOCKMETHOD && Trace_locks)
|| (PROCLOCK_LOCKMETHOD(*proclockP) == USER_LOCKMETHOD && Trace_userlocks))
! && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.objId >= (Oid) Trace_lock_oidmin))
! || (Trace_lock_table && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.objId == Trace_lock_table))
)
elog(LOG,
"%s: proclock(%lx) lock(%lx) tbl(%d) proc(%lx) xid(%u) hold(%x)",
***************
*** 422,429 ****
*
* lockmethodid 1 2
* tag.dbId database oid database oid
! * tag.relId rel oid or 0 0
! * tag.objId block id lock id2
* or xact id
* tag.offnum 0 lock id1
* proclock.xid xid or 0 0
--- 422,430 ----
*
* lockmethodid 1 2
* tag.dbId database oid database oid
! * tag.classId class oid 0
! * tag.objId rel oid or 0 0
! * tag.objsubId block id lock id2
* or xact id
* tag.offnum 0 lock id1
* proclock.xid xid or 0 0
***************
*** 456,462 ****
#ifdef LOCK_DEBUG
if (lockmethodid == USER_LOCKMETHOD && Trace_userlocks)
elog(LOG, "LockAcquire: user lock [%u] %s",
! locktag->objId.blkno, lock_mode_names[lockmode]);
#endif
/* ???????? This must be changed when short term locks will be used */
--- 457,463 ----
#ifdef LOCK_DEBUG
if (lockmethodid == USER_LOCKMETHOD && Trace_userlocks)
elog(LOG, "LockAcquire: user lock [%u] %s",
! locktag->objsubId.blkno, lock_mode_names[lockmode]);
#endif
/* ???????? This must be changed when short term locks will be used */
***************
*** 665,671 ****
elog(LOG, "deadlock risk: raising lock level"
" from %s to %s on object %u/%u/%u",
lock_mode_names[i], lock_mode_names[lockmode],
! lock->tag.relId, lock->tag.dbId, lock->tag.objId.blkno);
break;
}
}
--- 666,672 ----
elog(LOG, "deadlock risk: raising lock level"
" from %s to %s on object %u/%u/%u",
lock_mode_names[i], lock_mode_names[lockmode],
! lock->tag.objId, lock->tag.dbId, lock->tag.objsubId.blkno);
break;
}
}
***************
*** 1150,1156 ****
#ifdef LOCK_DEBUG
if (lockmethodid == USER_LOCKMETHOD && Trace_userlocks)
! elog(LOG, "LockRelease: user lock tag [%u] %d", locktag->objId.blkno, lockmode);
#endif
/* ???????? This must be changed when short term locks will be used */
--- 1151,1157 ----
#ifdef LOCK_DEBUG
if (lockmethodid == USER_LOCKMETHOD && Trace_userlocks)
! elog(LOG, "LockRelease: user lock tag [%u] %d", locktag->objsubId.blkno, lockmode);
#endif
/* ???????? This must be changed when short term locks will be used */
Index: src/backend/utils/adt/lockfuncs.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/utils/adt/lockfuncs.c,v
retrieving revision 1.15
diff -c -r1.15 lockfuncs.c
*** src/backend/utils/adt/lockfuncs.c 29 Aug 2004 04:12:51 -0000 1.15
--- src/backend/utils/adt/lockfuncs.c 18 Dec 2004 23:39:23 -0000
***************
*** 53,70 ****
/* build tupdesc for result tuples */
/* this had better match pg_locks view in system_views.sql */
! tupdesc = CreateTemplateTupleDesc(6, false);
! TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relation",
OIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database",
OIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 3, "transaction",
XIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pid",
INT4OID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 5, "mode",
TEXTOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 6, "granted",
BOOLOID, -1, 0);
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
--- 53,72 ----
/* build tupdesc for result tuples */
/* this had better match pg_locks view in system_views.sql */
! tupdesc = CreateTemplateTupleDesc(7, false);
! TupleDescInitEntry(tupdesc, (AttrNumber) 1, "object",
OIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 2, "class",
OIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 3, "database",
! OIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 4, "transaction",
XIDOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 5, "pid",
INT4OID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 6, "mode",
TEXTOID, -1, 0);
! TupleDescInitEntry(tupdesc, (AttrNumber) 7, "granted",
BOOLOID, -1, 0);
funcctx->tuple_desc = BlessTupleDesc(tupdesc);
***************
*** 93,100 ****
PGPROC *proc;
bool granted;
LOCKMODE mode = 0;
! Datum values[6];
! char nulls[6];
HeapTuple tuple;
Datum result;
--- 95,102 ----
PGPROC *proc;
bool granted;
LOCKMODE mode = 0;
! Datum values[7];
! char nulls[7];
HeapTuple tuple;
Datum result;
***************
*** 155,180 ****
MemSet(values, 0, sizeof(values));
MemSet(nulls, ' ', sizeof(nulls));
! if (lock->tag.relId == XactLockTableId && lock->tag.dbId == 0)
{
/* Lock is for transaction ID */
nulls[0] = 'n';
nulls[1] = 'n';
! values[2] = TransactionIdGetDatum(lock->tag.objId.xid);
}
else
{
/* Lock is for a relation */
! values[0] = ObjectIdGetDatum(lock->tag.relId);
! values[1] = ObjectIdGetDatum(lock->tag.dbId);
! nulls[2] = 'n';
}
! values[3] = Int32GetDatum(proc->pid);
! values[4] = DirectFunctionCall1(textin,
CStringGetDatum(GetLockmodeName(mode)));
! values[5] = BoolGetDatum(granted);
tuple = heap_formtuple(funcctx->tuple_desc, values, nulls);
result = HeapTupleGetDatum(tuple);
--- 157,186 ----
MemSet(values, 0, sizeof(values));
MemSet(nulls, ' ', sizeof(nulls));
! if (lock->tag.objId == InvalidOid
! && lock->tag.classId == XactLockTableId
! && lock->tag.dbId == InvalidOid)
{
/* Lock is for transaction ID */
nulls[0] = 'n';
nulls[1] = 'n';
! nulls[2] = 'n';
! values[3] = TransactionIdGetDatum(lock->tag.objsubId.xid);
}
else
{
/* Lock is for a relation */
! values[0] = ObjectIdGetDatum(lock->tag.objId);
! values[1] = ObjectIdGetDatum(lock->tag.classId);
! values[2] = ObjectIdGetDatum(lock->tag.dbId);
! nulls[3] = 'n';
}
! values[4] = Int32GetDatum(proc->pid);
! values[5] = DirectFunctionCall1(textin,
CStringGetDatum(GetLockmodeName(mode)));
! values[6] = BoolGetDatum(granted);
tuple = heap_formtuple(funcctx->tuple_desc, values, nulls);
result = HeapTupleGetDatum(tuple);
Index: src/include/storage/lmgr.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/storage/lmgr.h,v
retrieving revision 1.44
diff -c -r1.44 lmgr.h
*** src/include/storage/lmgr.h 16 Sep 2004 16:58:42 -0000 1.44
--- src/include/storage/lmgr.h 17 Dec 2004 17:57:36 -0000
***************
*** 61,64 ****
--- 61,68 ----
extern void XactLockTableDelete(TransactionId xid);
extern void XactLockTableWait(TransactionId xid);
+ /* Lock an arbitrary database object in the current database */
+ extern void LockObject(Oid objId, Oid classId, LOCKMODE lockmode);
+ extern void UnlockObject(Oid objId, Oid classId, LOCKMODE lockmode);
+
#endif /* LMGR_H */
Index: src/include/storage/lock.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/storage/lock.h,v
retrieving revision 1.83
diff -c -r1.83 lock.h
*** src/include/storage/lock.h 29 Aug 2004 05:06:58 -0000 1.83
--- src/include/storage/lock.h 17 Dec 2004 17:57:36 -0000
***************
*** 106,118 ****
*/
typedef struct LOCKTAG
{
! Oid relId;
Oid dbId;
union
{
BlockNumber blkno;
TransactionId xid;
! } objId;
/*
* offnum should be part of objId union above, but doing that would
--- 106,119 ----
*/
typedef struct LOCKTAG
{
! Oid objId;
! Oid classId;
Oid dbId;
union
{
BlockNumber blkno;
TransactionId xid;
! } objsubId;
/*
* offnum should be part of objId union above, but doing that would
Index: src/test/regress/expected/rules.out
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/test/regress/expected/rules.out,v
retrieving revision 1.95
diff -c -r1.95 rules.out
*** src/test/regress/expected/rules.out 27 Oct 2004 18:09:41 -0000 1.95
--- src/test/regress/expected/rules.out 19 Dec 2004 18:59:25 -0000
***************
*** 1276,1282 ****
--------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
iexit | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS "tablespace", pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
! pg_locks | SELECT l.relation, l."database", l."transaction", l.pid, l."mode", l.granted FROM pg_lock_status() l(relation oid, "database" oid, "transaction" xid, pid integer, "mode" text, granted boolean);
pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name);
pg_settings | SELECT a.name, a.setting, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text);
pg_stat_activity | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.usename, pg_stat_get_backend_activity(s.backendid) AS current_query, pg_stat_get_backend_activity_start(s.backendid) AS query_start FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_shadow u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.usesysid));
--- 1276,1282 ----
--------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
iexit | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS "tablespace", pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
! pg_locks | SELECT l."object", l."class", l."database", l."transaction", l.pid, l."mode", l.granted FROM pg_lock_status() l("object" oid, "class" oid, "database" oid, "transaction" xid, pid integer, "mode" text, granted boolean);
pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name);
pg_settings | SELECT a.name, a.setting, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text);
pg_stat_activity | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.usename, pg_stat_get_backend_activity(s.backendid) AS current_query, pg_stat_get_backend_activity_start(s.backendid) AS query_start FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_shadow u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.usesysid));