]> granicus.if.org Git - postgresql/commitdiff
- Modifies LOCKTAG to include a 'classId'. Relation receive a classId of
authorBruce Momjian <bruce@momjian.us>
Wed, 19 Feb 2003 04:02:54 +0000 (04:02 +0000)
committerBruce Momjian <bruce@momjian.us>
Wed, 19 Feb 2003 04:02:54 +0000 (04:02 +0000)
RelOid_pg_class, and transaction locks XactLockTableId. RelId is renamed
to objId.

- LockObject() and UnlockObject() functions created, and their use
sprinkled throughout the code to do descent locking for domains and
types. They accept lock modes AccessShare and AccessExclusive, as we
only really need a 'read' and 'write' lock at the moment.  Most locking
cases are held until the end of the transaction.

This fixes the cases Tom mentioned earlier in regards to locking with
Domains.  If the patch is good, I'll work on cleaning up issues with
other database objects that have this problem (most of them).

Rod Taylor

src/backend/commands/typecmds.c
src/backend/parser/parse_type.c
src/backend/storage/lmgr/deadlock.c
src/backend/storage/lmgr/lmgr.c
src/backend/storage/lmgr/lock.c
src/backend/utils/adt/lockfuncs.c
src/bin/initdb/initdb.sh
src/include/storage/lmgr.h
src/include/storage/lock.h
src/test/regress/expected/rules.out

index ad954605373b25b2ca82ab96d6ca910f6204d0df..7ae852672c5028aed87db2f22e581a35ff5e53bc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.30 2003/02/03 21:15:43 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.31 2003/02/19 04:02:53 momjian Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -353,6 +353,12 @@ RemoveType(List *names, DropBehavior behavior)
                elog(ERROR, "Type \"%s\" does not exist",
                         TypeNameToString(typename));
 
+       /*
+        * Grab an exclusive lock on the type id, the SearchSysCache confirms
+        * the type still exists after locking
+        */
+       LockObject(typeoid, RelOid_pg_type, AccessExclusiveLock);
+
        tup = SearchSysCache(TYPEOID,
                                                 ObjectIdGetDatum(typeoid),
                                                 0, 0, 0);
@@ -376,6 +382,9 @@ RemoveType(List *names, DropBehavior behavior)
        object.objectSubId = 0;
 
        performDeletion(&object, behavior);
+
+       /* Hold the lock until the end of the transaction */
+       UnlockObject(typeoid, RelOid_pg_type, NoLock);
 }
 
 
@@ -680,7 +689,7 @@ void
 RemoveDomain(List *names, DropBehavior behavior)
 {
        TypeName   *typename;
-       Oid                     typeoid;
+       Oid                     domainoid;
        HeapTuple       tup;
        char            typtype;
        ObjectAddress object;
@@ -692,20 +701,26 @@ RemoveDomain(List *names, DropBehavior behavior)
        typename->arrayBounds = NIL;
 
        /* Use LookupTypeName here so that shell types can be removed. */
-       typeoid = LookupTypeName(typename);
-       if (!OidIsValid(typeoid))
+       domainoid = LookupTypeName(typename);
+       if (!OidIsValid(domainoid))
                elog(ERROR, "Type \"%s\" does not exist",
                         TypeNameToString(typename));
 
+       /*
+        * Lock the domain.  The SearchSysCache confirms the domain still exists
+        * after locking
+        */
+       LockObject(domainoid, RelOid_pg_type, AccessExclusiveLock);
+
        tup = SearchSysCache(TYPEOID,
-                                                ObjectIdGetDatum(typeoid),
+                                                ObjectIdGetDatum(domainoid),
                                                 0, 0, 0);
        if (!HeapTupleIsValid(tup))
                elog(ERROR, "RemoveDomain: type \"%s\" does not exist",
                         TypeNameToString(typename));
 
        /* Permission check: must own type or its namespace */
-       if (!pg_type_ownercheck(typeoid, GetUserId()) &&
+       if (!pg_type_ownercheck(domainoid, GetUserId()) &&
                !pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace,
                                                                 GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(typename));
@@ -723,10 +738,13 @@ RemoveDomain(List *names, DropBehavior behavior)
         * Do the deletion
         */
        object.classId = RelOid_pg_type;
-       object.objectId = typeoid;
+       object.objectId = domainoid;
        object.objectSubId = 0;
 
        performDeletion(&object, behavior);
+
+       /* Hold the lock until the end of the transaction */
+       UnlockObject(domainoid, RelOid_pg_type, NoLock);
 }
 
 
@@ -941,6 +959,12 @@ AlterDomainDefault(List *names, Node *defaultRaw)
                elog(ERROR, "Type \"%s\" does not exist",
                         TypeNameToString(typename));
 
+       /*
+        * Lock the domain.  The SearchSysCacheCopy confirms the type
+        * still exists after locking
+        */
+       LockObject(domainoid, RelOid_pg_type, AccessExclusiveLock);
+
        tup = SearchSysCacheCopy(TYPEOID,
                                                         ObjectIdGetDatum(domainoid),
                                                         0, 0, 0);
@@ -1025,6 +1049,7 @@ AlterDomainDefault(List *names, Node *defaultRaw)
        /* Clean up */
        heap_close(rel, NoLock);
        heap_freetuple(newtuple);
+       UnlockObject(domainoid, RelOid_pg_type, NoLock);
 };
 
 /*
@@ -1056,6 +1081,12 @@ AlterDomainNotNull(List *names, bool notNull)
                elog(ERROR, "Type \"%s\" does not exist",
                         TypeNameToString(typename));
 
+       /*
+        * Lock the domain.  The SearchSysCacheCopy confirms the domain
+        * still exists after locking
+        */
+       LockObject(domainoid, RelOid_pg_type, AccessExclusiveLock);
+
        tup = SearchSysCacheCopy(TYPEOID,
                                                         ObjectIdGetDatum(domainoid),
                                                         0, 0, 0);
@@ -1137,6 +1168,7 @@ AlterDomainNotNull(List *names, bool notNull)
        /* Clean up */
        heap_freetuple(tup);
        heap_close(typrel, RowExclusiveLock);
+       UnlockObject(domainoid, RelOid_pg_type, NoLock);
 }
 
 /*
@@ -1172,6 +1204,12 @@ AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior beha
                elog(ERROR, "Type \"%s\" does not exist",
                         TypeNameToString(typename));
 
+       /*
+        * Lock the domain.  The SearchSysCacheCopy confirms the type still
+        * exists after locking.
+        */
+       LockObject(domainoid, RelOid_pg_type, AccessExclusiveLock);
+
        tup = SearchSysCacheCopy(TYPEOID,
                                                         ObjectIdGetDatum(domainoid),
                                                         0, 0, 0);
@@ -1219,6 +1257,7 @@ AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior beha
        heap_close(conrel, RowExclusiveLock);
 
        heap_close(rel, NoLock);
+       UnlockObject(domainoid, RelOid_pg_type, NoLock);
 };
 
 /*
@@ -1259,6 +1298,12 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
                elog(ERROR, "Type \"%s\" does not exist",
                         TypeNameToString(typename));
 
+       /*
+        * Lock the domain.  The SearchSysCacheCopy confirms the domain
+        * still exists after locking.
+        */
+       LockObject(domainoid, RelOid_pg_type, AccessExclusiveLock);
+
        tup = SearchSysCacheCopy(TYPEOID,
                                                         ObjectIdGetDatum(domainoid),
                                                         0, 0, 0);
@@ -1393,6 +1438,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
 
        /* Clean up */
        heap_close(typrel, RowExclusiveLock);
+       UnlockObject(domainoid, RelOid_pg_type, NoLock);
 }
 
 /*
@@ -1696,7 +1742,10 @@ GetDomainConstraints(Oid typeOid)
                Form_pg_type typTup;
                ScanKeyData key[1];
                SysScanDesc scan;
-               
+
+               /* Lock the domain */
+               LockObject(typeOid, RelOid_pg_type, AccessShareLock);
+
                tup = SearchSysCache(TYPEOID,
                                                         ObjectIdGetDatum(typeOid),
                                                         0, 0, 0);
@@ -1824,6 +1873,12 @@ AlterTypeOwner(List *names, AclId newOwnerSysId)
                elog(ERROR, "Type \"%s\" does not exist",
                         TypeNameToString(typename));
 
+       /*
+        * Lock the type.  The SearchSysCacheCopy serves to confirm the
+        * domain still exists after locking
+        */
+       LockObject(typeOid, RelOid_pg_type, AccessExclusiveLock);
+
        tup = SearchSysCacheCopy(TYPEOID,
                                                         ObjectIdGetDatum(typeOid),
                                                         0, 0, 0);
@@ -1846,4 +1901,5 @@ AlterTypeOwner(List *names, AclId newOwnerSysId)
 
        /* Clean up */
        heap_close(rel, RowExclusiveLock);
+       UnlockObject(typeOid, RelOid_pg_type, NoLock);
 }
index 8f7c34cbd3d7ddafcafeacad11f5c99fa2152370..56379a28119cb6ef7633ed06030bae963913f4bc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.51 2003/02/09 06:56:28 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.52 2003/02/19 04:02:53 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,6 +23,7 @@
 #include "parser/parser.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_type.h"
+#include "storage/lmgr.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
@@ -127,6 +128,15 @@ LookupTypeName(const TypeName *typename)
                }
        }
 
+       /*
+        * Lock the type as having been read for remainder of the transaction
+        *
+        * XXX: There is a small time between the above and now when the type
+        *              could dissapear.  We *should* recheck to confirm the type still
+        *              exists, but won't for speed.
+        */
+       LockObject(restype, RelOid_pg_type, AccessShareLock);
+
        return restype;
 }
 
index 61ab1962fb697bfe6b644115e6be192000aa75c9..9191d40b1e7a95b652dd90ff6782a7809b693a48 100644 (file)
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/deadlock.c,v 1.17 2003/02/18 02:13:24 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/deadlock.c,v 1.18 2003/02/19 04:02:53 momjian Exp $
  *
  *     Interface:
  *
@@ -855,22 +855,25 @@ DeadLockReport(void)
                else
                        nextpid = deadlockDetails[0].pid;
 
-               if (info->locktag.relId == XactLockTableId && info->locktag.dbId == 0)
+               if (info->locktag.objId == InvalidOid
+                       && info->locktag.classId == XactLockTableId
+                       && info->locktag.dbId == InvalidOid)
                {
                        /* Lock is for transaction ID */
                        elog(NOTICE, "Proc %d waits for %s on transaction %u; blocked by %d",
                                 info->pid,
                                 GetLockmodeName(info->lockmode),
-                                info->locktag.objId.xid,
+                                info->locktag.objsubId.xid,
                                 nextpid);
                }
                else
                {
                        /* Lock is for a relation */
-                       elog(NOTICE, "Proc %d waits for %s on relation %u database %u; blocked by %d",
+                       elog(NOTICE, "Proc %d waits for %s on object %u class %u database %u; blocked by %d",
                                 info->pid,
                                 GetLockmodeName(info->lockmode),
-                                info->locktag.relId,
+                                info->locktag.objId,
+                                info->locktag.classId,
                                 info->locktag.dbId,
                                 nextpid);
                }
index a4e9197edc72a2fe00983f69baa1f5e833ef3166..a1011054fa3672c1b346f749dadea1e98ce7731b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.54 2002/08/01 05:18:33 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.55 2003/02/19 04:02:53 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -126,9 +126,10 @@ LockRelation(Relation relation, LOCKMODE lockmode)
        LOCKTAG         tag;
 
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = relation->rd_lockInfo.lockRelId.relId;
+       tag.objId = relation->rd_lockInfo.lockRelId.relId;
+       tag.classId = RelOid_pg_class;
        tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
-       tag.objId.blkno = InvalidBlockNumber;
+       tag.objsubId.blkno = InvalidBlockNumber;
 
        if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),
                                         lockmode, false))
@@ -160,9 +161,10 @@ ConditionalLockRelation(Relation relation, LOCKMODE lockmode)
        LOCKTAG         tag;
 
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = relation->rd_lockInfo.lockRelId.relId;
+       tag.objId = relation->rd_lockInfo.lockRelId.relId;
+       tag.classId = RelOid_pg_class;
        tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
-       tag.objId.blkno = InvalidBlockNumber;
+       tag.objsubId.blkno = InvalidBlockNumber;
 
        if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),
                                         lockmode, true))
@@ -190,9 +192,10 @@ UnlockRelation(Relation relation, LOCKMODE lockmode)
        LOCKTAG         tag;
 
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = relation->rd_lockInfo.lockRelId.relId;
+       tag.objId = relation->rd_lockInfo.lockRelId.relId;
+       tag.classId = RelOid_pg_class;
        tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
-       tag.objId.blkno = InvalidBlockNumber;
+       tag.objsubId.blkno = InvalidBlockNumber;
 
        LockRelease(LockTableId, &tag, GetCurrentTransactionId(), lockmode);
 }
@@ -215,9 +218,10 @@ LockRelationForSession(LockRelId *relid, LOCKMODE lockmode)
        LOCKTAG         tag;
 
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = relid->relId;
+       tag.objId = relid->relId;
+       tag.classId = RelOid_pg_class;
        tag.dbId = relid->dbId;
-       tag.objId.blkno = InvalidBlockNumber;
+       tag.objsubId.blkno = InvalidBlockNumber;
 
        if (!LockAcquire(LockTableId, &tag, InvalidTransactionId,
                                         lockmode, false))
@@ -233,9 +237,10 @@ UnlockRelationForSession(LockRelId *relid, LOCKMODE lockmode)
        LOCKTAG         tag;
 
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = relid->relId;
+       tag.objId = relid->relId;
+       tag.classId = RelOid_pg_class;
        tag.dbId = relid->dbId;
-       tag.objId.blkno = InvalidBlockNumber;
+       tag.objsubId.blkno = InvalidBlockNumber;
 
        LockRelease(LockTableId, &tag, InvalidTransactionId, lockmode);
 }
@@ -253,9 +258,10 @@ LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
        LOCKTAG         tag;
 
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = relation->rd_lockInfo.lockRelId.relId;
+       tag.objId = relation->rd_lockInfo.lockRelId.relId;
+       tag.classId = RelOid_pg_class;
        tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
-       tag.objId.blkno = blkno;
+       tag.objsubId.blkno = blkno;
 
        if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),
                                         lockmode, false))
@@ -271,9 +277,10 @@ UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
        LOCKTAG         tag;
 
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = relation->rd_lockInfo.lockRelId.relId;
+       tag.objId = relation->rd_lockInfo.lockRelId.relId;
+       tag.classId = RelOid_pg_class;
        tag.dbId = relation->rd_lockInfo.lockRelId.dbId;
-       tag.objId.blkno = blkno;
+       tag.objsubId.blkno = blkno;
 
        LockRelease(LockTableId, &tag, GetCurrentTransactionId(), lockmode);
 }
@@ -294,9 +301,10 @@ XactLockTableInsert(TransactionId xid)
        LOCKTAG         tag;
 
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = XactLockTableId;
+       tag.objId = InvalidOid;
+       tag.classId = XactLockTableId;
        tag.dbId = InvalidOid;          /* xids are globally unique */
-       tag.objId.xid = xid;
+       tag.objsubId.xid = xid;
 
        if (!LockAcquire(LockTableId, &tag, xid,
                                         ExclusiveLock, false))
@@ -317,9 +325,10 @@ XactLockTableWait(TransactionId xid)
        Assert(!TransactionIdEquals(xid, myxid));
 
        MemSet(&tag, 0, sizeof(tag));
-       tag.relId = XactLockTableId;
+       tag.objId = InvalidOid;
+       tag.classId = XactLockTableId;
        tag.dbId = InvalidOid;
-       tag.objId.xid = xid;
+       tag.objsubId.xid = xid;
 
        if (!LockAcquire(LockTableId, &tag, myxid,
                                         ShareLock, false))
@@ -334,3 +343,59 @@ XactLockTableWait(TransactionId xid)
        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 d0c5a055f9e0d24a144eb547cdd69c1392bc954b..959fe7877a05e4e618256d7813784ce218ac2398 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.120 2003/02/18 02:13:24 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.121 2003/02/19 04:02:53 momjian Exp $
  *
  * NOTES
  *       Outside modules can create a lock table and acquire/release
@@ -97,8 +97,8 @@ LOCK_DEBUG_ENABLED(const LOCK *lock)
        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));
+                && (lock->tag.objId >= (Oid) Trace_lock_oidmin))
+               || (Trace_lock_table && (lock->tag.objId == Trace_lock_table));
 }
 
 
@@ -107,12 +107,12 @@ LOCK_PRINT(const char *where, const LOCK *lock, LOCKMODE type)
 {
        if (LOCK_DEBUG_ENABLED(lock))
                elog(LOG,
-                        "%s: lock(%lx) tbl(%d) rel(%u) db(%u) obj(%u) grantMask(%x) "
+                        "%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.lockmethod, lock->tag.relId, lock->tag.dbId,
-                        lock->tag.objId.blkno, lock->grantMask,
+                        lock->tag.lockmethod, 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,
@@ -129,16 +129,16 @@ PROCLOCK_PRINT(const char *where, const PROCLOCK *proclockP)
        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))
+        && (((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(%d,%d,%d,%d,%d,%d,%d)=%d",
                         where, MAKE_OFFSET(proclockP), proclockP->tag.lock,
                         PROCLOCK_LOCKMETHOD(*(proclockP)),
                         proclockP->tag.proc, proclockP->tag.xid,
-                  proclockP->holding[1], proclockP->holding[2], proclockP->holding[3],
-                  proclockP->holding[4], proclockP->holding[5], proclockP->holding[6],
+                        proclockP->holding[1], proclockP->holding[2], proclockP->holding[3],
+                        proclockP->holding[4], proclockP->holding[5], proclockP->holding[6],
                         proclockP->holding[7], proclockP->nHolding);
 }
 
@@ -417,8 +417,9 @@ LockMethodTableRename(LOCKMETHOD lockmethod)
  *
  *             lockmethod                                              1                               2
  *             tag.dbId                                                database oid    database oid
- *             tag.relId                                               rel oid or 0    0
- *             tag.objId                                               block id                lock id2
+ *             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
@@ -449,7 +450,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 #ifdef LOCK_DEBUG
        if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
                elog(LOG, "LockAcquire: user lock [%u] %s",
-                        locktag->objId.blkno, lock_mode_names[lockmode]);
+                        locktag->objsubId.blkno, lock_mode_names[lockmode]);
 #endif
 
        /* ???????? This must be changed when short term locks will be used */
@@ -572,7 +573,7 @@ LockAcquire(LOCKMETHOD lockmethod, LOCKTAG *locktag,
                                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);
+                                lock->tag.objId, lock->tag.dbId, lock->tag.objsubId.blkno);
                                break;
                        }
                }
@@ -993,7 +994,7 @@ LockRelease(LOCKMETHOD lockmethod, LOCKTAG *locktag,
 
 #ifdef LOCK_DEBUG
        if (lockmethod == USER_LOCKMETHOD && Trace_userlocks)
-               elog(LOG, "LockRelease: user lock tag [%u] %d", locktag->objId.blkno, lockmode);
+               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 37788d8ff0d847b9bd51f8f66d0e3d18dbd85f78..25bc726cba2389a2c3d5986138a3cd2c2bc21e4f 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (c) 2002, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *             $Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.8 2003/02/18 02:13:24 momjian Exp $
+ *             $Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.9 2003/02/19 04:02:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,18 +53,20 @@ pg_lock_status(PG_FUNCTION_ARGS)
 
                /* build tupdesc for result tuples */
                /* this had better match pg_locks view in initdb.sh */
-               tupdesc = CreateTemplateTupleDesc(6, false);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relation",
+               tupdesc = CreateTemplateTupleDesc(7, false);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 1, "object",
                                                   OIDOID, -1, 0, false);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 2, "class",
                                                   OIDOID, -1, 0, false);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 3, "transaction",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 3, "database",
+                                                  OIDOID, -1, 0, false);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 4, "transaction",
                                                   XIDOID, -1, 0, false);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 4, "pid",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 5, "pid",
                                                   INT4OID, -1, 0, false);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 5, "mode",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 6, "mode",
                                                   TEXTOID, -1, 0, false);
-               TupleDescInitEntry(tupdesc, (AttrNumber) 6, "granted",
+               TupleDescInitEntry(tupdesc, (AttrNumber) 7, "granted",
                                                   BOOLOID, -1, 0, false);
 
                funcctx->slot = TupleDescGetSlot(tupdesc);
@@ -93,8 +95,8 @@ pg_lock_status(PG_FUNCTION_ARGS)
                PGPROC     *proc;
                bool            granted;
                LOCKMODE        mode;
-               Datum           values[6];
-               char            nulls[6];
+               Datum           values[7];
+               char            nulls[7];
                HeapTuple       tuple;
                Datum           result;
 
@@ -152,26 +154,30 @@ pg_lock_status(PG_FUNCTION_ARGS)
                MemSet(values, 0, sizeof(values));
                MemSet(nulls, ' ', sizeof(nulls));
 
-               if (lock->tag.relId == XactLockTableId && lock->tag.dbId == 0)
+               if (lock->tag.objId == InvalidOid
+                       && lock->tag.classId == XactLockTableId
+                       && lock->tag.dbId == InvalidOid)
                {
                        /* Lock is for transaction ID */
                        nulls[0] = 'n';
                        nulls[1] = 'n';
-                       values[2] = TransactionIdGetDatum(lock->tag.objId.xid);
+                       nulls[2] = 'n';
+                       values[3] = TransactionIdGetDatum(lock->tag.objsubId.xid);
                }
                else
                {
                        /* Lock is for a relation */
-                       values[0] = ObjectIdGetDatum(lock->tag.relId);
-                       values[1] = ObjectIdGetDatum(lock->tag.dbId);
-                       nulls[2] = 'n';
+                       values[0] = ObjectIdGetDatum(lock->tag.objId);
+                       values[1] = ObjectIdGetDatum(lock->tag.classId);
+                       values[2] = ObjectIdGetDatum(lock->tag.dbId);
+                       nulls[3] = 'n';
 
                }
 
-               values[3] = Int32GetDatum(proc->pid);
-               values[4] = DirectFunctionCall1(textin,
+               values[4] = Int32GetDatum(proc->pid);
+               values[5] = DirectFunctionCall1(textin,
                                                                 CStringGetDatum(GetLockmodeName(mode)));
-               values[5] = BoolGetDatum(granted);
+               values[6] = BoolGetDatum(granted);
 
                tuple = heap_formtuple(funcctx->slot->ttc_tupleDescriptor,
                                                           values, nulls);
index 5dad4e34a05031ee64cfad015001f063459d9274..b75e8c2a48a4db2b931e3a55e1ce4832ec37fb18 100644 (file)
@@ -27,7 +27,7 @@
 # Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
 # Portions Copyright (c) 1994, Regents of the University of California
 #
-# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.182 2003/01/23 23:39:01 petere Exp $
+# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.183 2003/02/19 04:02:54 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -974,7 +974,7 @@ CREATE VIEW pg_stat_database AS \
 
 CREATE VIEW pg_locks AS \
     SELECT * \
-    FROM pg_lock_status() AS L(relation oid, database oid, \
+    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 8437e104f4ae6b059aec4325aff62d56a154647a..17b095b274b8c39f7774b47a6ff057eb3437101b 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lmgr.h,v 1.36 2002/06/20 20:29:52 momjian Exp $
+ * $Id: lmgr.h,v 1.37 2003/02/19 04:02:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,4 +62,8 @@ extern void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
 extern void XactLockTableInsert(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 f31dc1d9b8803ff219a6a438b80f1c5bc254bc01..fb40a5d104046f42639897713b622752897b3584 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: lock.h,v 1.69 2003/02/18 02:13:24 momjian Exp $
+ * $Id: lock.h,v 1.70 2003/02/19 04:02:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -100,13 +100,14 @@ typedef struct LOCKMETHODTABLE
  */
 typedef struct LOCKTAG
 {
-       Oid                     relId;
+       Oid                     objId;
+       Oid                     classId;
        Oid                     dbId;
        union
        {
                BlockNumber blkno;
                TransactionId xid;
-       }                       objId;
+       }                       objsubId;
 
        /*
         * offnum should be part of objId.tupleId above, but would increase
index f302ad93138dd534887fa255f0683584b45faba1..12bfccc0173d4c610a0bd7e6c3331f44bbc06caa 100644 (file)
@@ -1271,7 +1271,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
 --------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  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, 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))) 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_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 FROM pg_show_all_settings() a(name text, setting 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 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));