]> granicus.if.org Git - postgresql/blobdiff - src/backend/utils/adt/lockfuncs.c
Run pgindent on 9.2 source tree in preparation for first 9.3
[postgresql] / src / backend / utils / adt / lockfuncs.c
index f1ed9673a39c78ef30526608ec836fff555158d1..33c5b64f50ac9b8f05a64f4e3a985d4cee2ceaca 100644 (file)
@@ -3,10 +3,10 @@
  * lockfuncs.c
  *             Functions for SQL access to various lock-manager capabilities.
  *
- * Copyright (c) 2002-2009, PostgreSQL Global Development Group
+ * Copyright (c) 2002-2012, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *             $PostgreSQL: pgsql/src/backend/utils/adt/lockfuncs.c,v 1.36 2009/01/01 17:23:49 momjian Exp $
+ *             src/backend/utils/adt/lockfuncs.c
  *
  *-------------------------------------------------------------------------
  */
@@ -15,7 +15,7 @@
 #include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "miscadmin.h"
-#include "storage/proc.h"
+#include "storage/predicate_internals.h"
 #include "utils/builtins.h"
 
 
@@ -32,13 +32,24 @@ static const char *const LockTagTypeNames[] = {
        "advisory"
 };
 
+/* This must match enum PredicateLockTargetType (predicate_internals.h) */
+static const char *const PredicateLockTagTypeNames[] = {
+       "relation",
+       "page",
+       "tuple"
+};
+
 /* Working status for pg_lock_status */
 typedef struct
 {
        LockData   *lockData;           /* state data from lmgr */
        int                     currIdx;                /* current PROCLOCK index */
+       PredicateLockData *predLockData;        /* state data for pred locks */
+       int                     predLockIdx;    /* current index for pred lock */
 } PG_Lock_Status;
 
+/* Number of columns in pg_locks output */
+#define NUM_LOCK_STATUS_COLUMNS                15
 
 /*
  * VXIDGetDatum - Construct a text representation of a VXID
@@ -69,6 +80,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
        FuncCallContext *funcctx;
        PG_Lock_Status *mystatus;
        LockData   *lockData;
+       PredicateLockData *predLockData;
 
        if (SRF_IS_FIRSTCALL())
        {
@@ -85,7 +97,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
 
                /* build tupdesc for result tuples */
                /* this had better match pg_locks view in system_views.sql */
-               tupdesc = CreateTemplateTupleDesc(14, false);
+               tupdesc = CreateTemplateTupleDesc(NUM_LOCK_STATUS_COLUMNS, false);
                TupleDescInitEntry(tupdesc, (AttrNumber) 1, "locktype",
                                                   TEXTOID, -1, 0);
                TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database",
@@ -114,6 +126,8 @@ pg_lock_status(PG_FUNCTION_ARGS)
                                                   TEXTOID, -1, 0);
                TupleDescInitEntry(tupdesc, (AttrNumber) 14, "granted",
                                                   BOOLOID, -1, 0);
+               TupleDescInitEntry(tupdesc, (AttrNumber) 15, "fastpath",
+                                                  BOOLOID, -1, 0);
 
                funcctx->tuple_desc = BlessTupleDesc(tupdesc);
 
@@ -126,6 +140,8 @@ pg_lock_status(PG_FUNCTION_ARGS)
 
                mystatus->lockData = GetLockStatusData();
                mystatus->currIdx = 0;
+               mystatus->predLockData = GetPredicateLockStatusData();
+               mystatus->predLockIdx = 0;
 
                MemoryContextSwitchTo(oldcontext);
        }
@@ -136,21 +152,17 @@ pg_lock_status(PG_FUNCTION_ARGS)
 
        while (mystatus->currIdx < lockData->nelements)
        {
-               PROCLOCK   *proclock;
-               LOCK       *lock;
-               PGPROC     *proc;
                bool            granted;
                LOCKMODE        mode = 0;
                const char *locktypename;
                char            tnbuf[32];
-               Datum           values[14];
-               bool            nulls[14];
+               Datum           values[NUM_LOCK_STATUS_COLUMNS];
+               bool            nulls[NUM_LOCK_STATUS_COLUMNS];
                HeapTuple       tuple;
                Datum           result;
+               LockInstanceData *instance;
 
-               proclock = &(lockData->proclocks[mystatus->currIdx]);
-               lock = &(lockData->locks[mystatus->currIdx]);
-               proc = &(lockData->procs[mystatus->currIdx]);
+               instance = &(lockData->locks[mystatus->currIdx]);
 
                /*
                 * Look to see if there are any held lock modes in this PROCLOCK. If
@@ -158,14 +170,14 @@ pg_lock_status(PG_FUNCTION_ARGS)
                 * again.
                 */
                granted = false;
-               if (proclock->holdMask)
+               if (instance->holdMask)
                {
                        for (mode = 0; mode < MAX_LOCKMODES; mode++)
                        {
-                               if (proclock->holdMask & LOCKBIT_ON(mode))
+                               if (instance->holdMask & LOCKBIT_ON(mode))
                                {
                                        granted = true;
-                                       proclock->holdMask &= LOCKBIT_OFF(mode);
+                                       instance->holdMask &= LOCKBIT_OFF(mode);
                                        break;
                                }
                        }
@@ -177,10 +189,10 @@ pg_lock_status(PG_FUNCTION_ARGS)
                 */
                if (!granted)
                {
-                       if (proc->waitLock == proclock->tag.myLock)
+                       if (instance->waitLockMode != NoLock)
                        {
                                /* Yes, so report it with proper mode */
-                               mode = proc->waitLockMode;
+                               mode = instance->waitLockMode;
 
                                /*
                                 * We are now done with this PROCLOCK, so advance pointer to
@@ -205,22 +217,22 @@ pg_lock_status(PG_FUNCTION_ARGS)
                MemSet(values, 0, sizeof(values));
                MemSet(nulls, false, sizeof(nulls));
 
-               if (lock->tag.locktag_type <= LOCKTAG_LAST_TYPE)
-                       locktypename = LockTagTypeNames[lock->tag.locktag_type];
+               if (instance->locktag.locktag_type <= LOCKTAG_LAST_TYPE)
+                       locktypename = LockTagTypeNames[instance->locktag.locktag_type];
                else
                {
                        snprintf(tnbuf, sizeof(tnbuf), "unknown %d",
-                                        (int) lock->tag.locktag_type);
+                                        (int) instance->locktag.locktag_type);
                        locktypename = tnbuf;
                }
                values[0] = CStringGetTextDatum(locktypename);
 
-               switch ((LockTagType) lock->tag.locktag_type)
+               switch ((LockTagType) instance->locktag.locktag_type)
                {
                        case LOCKTAG_RELATION:
                        case LOCKTAG_RELATION_EXTEND:
-                               values[1] = ObjectIdGetDatum(lock->tag.locktag_field1);
-                               values[2] = ObjectIdGetDatum(lock->tag.locktag_field2);
+                               values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
+                               values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
                                nulls[3] = true;
                                nulls[4] = true;
                                nulls[5] = true;
@@ -230,9 +242,9 @@ pg_lock_status(PG_FUNCTION_ARGS)
                                nulls[9] = true;
                                break;
                        case LOCKTAG_PAGE:
-                               values[1] = ObjectIdGetDatum(lock->tag.locktag_field1);
-                               values[2] = ObjectIdGetDatum(lock->tag.locktag_field2);
-                               values[3] = UInt32GetDatum(lock->tag.locktag_field3);
+                               values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
+                               values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
+                               values[3] = UInt32GetDatum(instance->locktag.locktag_field3);
                                nulls[4] = true;
                                nulls[5] = true;
                                nulls[6] = true;
@@ -241,10 +253,10 @@ pg_lock_status(PG_FUNCTION_ARGS)
                                nulls[9] = true;
                                break;
                        case LOCKTAG_TUPLE:
-                               values[1] = ObjectIdGetDatum(lock->tag.locktag_field1);
-                               values[2] = ObjectIdGetDatum(lock->tag.locktag_field2);
-                               values[3] = UInt32GetDatum(lock->tag.locktag_field3);
-                               values[4] = UInt16GetDatum(lock->tag.locktag_field4);
+                               values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
+                               values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
+                               values[3] = UInt32GetDatum(instance->locktag.locktag_field3);
+                               values[4] = UInt16GetDatum(instance->locktag.locktag_field4);
                                nulls[5] = true;
                                nulls[6] = true;
                                nulls[7] = true;
@@ -252,7 +264,8 @@ pg_lock_status(PG_FUNCTION_ARGS)
                                nulls[9] = true;
                                break;
                        case LOCKTAG_TRANSACTION:
-                               values[6] = TransactionIdGetDatum(lock->tag.locktag_field1);
+                               values[6] =
+                                       TransactionIdGetDatum(instance->locktag.locktag_field1);
                                nulls[1] = true;
                                nulls[2] = true;
                                nulls[3] = true;
@@ -263,8 +276,8 @@ pg_lock_status(PG_FUNCTION_ARGS)
                                nulls[9] = true;
                                break;
                        case LOCKTAG_VIRTUALTRANSACTION:
-                               values[5] = VXIDGetDatum(lock->tag.locktag_field1,
-                                                                                lock->tag.locktag_field2);
+                               values[5] = VXIDGetDatum(instance->locktag.locktag_field1,
+                                                                                instance->locktag.locktag_field2);
                                nulls[1] = true;
                                nulls[2] = true;
                                nulls[3] = true;
@@ -278,10 +291,10 @@ pg_lock_status(PG_FUNCTION_ARGS)
                        case LOCKTAG_USERLOCK:
                        case LOCKTAG_ADVISORY:
                        default:                        /* treat unknown locktags like OBJECT */
-                               values[1] = ObjectIdGetDatum(lock->tag.locktag_field1);
-                               values[7] = ObjectIdGetDatum(lock->tag.locktag_field2);
-                               values[8] = ObjectIdGetDatum(lock->tag.locktag_field3);
-                               values[9] = Int16GetDatum(lock->tag.locktag_field4);
+                               values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
+                               values[7] = ObjectIdGetDatum(instance->locktag.locktag_field2);
+                               values[8] = ObjectIdGetDatum(instance->locktag.locktag_field3);
+                               values[9] = Int16GetDatum(instance->locktag.locktag_field4);
                                nulls[2] = true;
                                nulls[3] = true;
                                nulls[4] = true;
@@ -290,13 +303,84 @@ pg_lock_status(PG_FUNCTION_ARGS)
                                break;
                }
 
-               values[10] = VXIDGetDatum(proc->backendId, proc->lxid);
-               if (proc->pid != 0)
-                       values[11] = Int32GetDatum(proc->pid);
+               values[10] = VXIDGetDatum(instance->backend, instance->lxid);
+               if (instance->pid != 0)
+                       values[11] = Int32GetDatum(instance->pid);
                else
                        nulls[11] = true;
-               values[12] = CStringGetTextDatum(GetLockmodeName(LOCK_LOCKMETHOD(*lock), mode));
+               values[12] = CStringGetTextDatum(GetLockmodeName(instance->locktag.locktag_lockmethodid, mode));
                values[13] = BoolGetDatum(granted);
+               values[14] = BoolGetDatum(instance->fastpath);
+
+               tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
+               result = HeapTupleGetDatum(tuple);
+               SRF_RETURN_NEXT(funcctx, result);
+       }
+
+       /*
+        * Have returned all regular locks. Now start on the SIREAD predicate
+        * locks.
+        */
+       predLockData = mystatus->predLockData;
+       if (mystatus->predLockIdx < predLockData->nelements)
+       {
+               PredicateLockTargetType lockType;
+
+               PREDICATELOCKTARGETTAG *predTag = &(predLockData->locktags[mystatus->predLockIdx]);
+               SERIALIZABLEXACT *xact = &(predLockData->xacts[mystatus->predLockIdx]);
+               Datum           values[NUM_LOCK_STATUS_COLUMNS];
+               bool            nulls[NUM_LOCK_STATUS_COLUMNS];
+               HeapTuple       tuple;
+               Datum           result;
+
+               mystatus->predLockIdx++;
+
+               /*
+                * Form tuple with appropriate data.
+                */
+               MemSet(values, 0, sizeof(values));
+               MemSet(nulls, false, sizeof(nulls));
+
+               /* lock type */
+               lockType = GET_PREDICATELOCKTARGETTAG_TYPE(*predTag);
+
+               values[0] = CStringGetTextDatum(PredicateLockTagTypeNames[lockType]);
+
+               /* lock target */
+               values[1] = GET_PREDICATELOCKTARGETTAG_DB(*predTag);
+               values[2] = GET_PREDICATELOCKTARGETTAG_RELATION(*predTag);
+               if (lockType == PREDLOCKTAG_TUPLE)
+                       values[4] = GET_PREDICATELOCKTARGETTAG_OFFSET(*predTag);
+               else
+                       nulls[4] = true;
+               if ((lockType == PREDLOCKTAG_TUPLE) ||
+                       (lockType == PREDLOCKTAG_PAGE))
+                       values[3] = GET_PREDICATELOCKTARGETTAG_PAGE(*predTag);
+               else
+                       nulls[3] = true;
+
+               /* these fields are targets for other types of locks */
+               nulls[5] = true;                /* virtualxid */
+               nulls[6] = true;                /* transactionid */
+               nulls[7] = true;                /* classid */
+               nulls[8] = true;                /* objid */
+               nulls[9] = true;                /* objsubid */
+
+               /* lock holder */
+               values[10] = VXIDGetDatum(xact->vxid.backendId,
+                                                                 xact->vxid.localTransactionId);
+               if (xact->pid != 0)
+                       values[11] = Int32GetDatum(xact->pid);
+               else
+                       nulls[11] = true;
+
+               /*
+                * Lock mode. Currently all predicate locks are SIReadLocks, which are
+                * always held (never waiting) and have no fast path
+                */
+               values[12] = CStringGetTextDatum("SIReadLock");
+               values[13] = BoolGetDatum(true);
+               values[14] = BoolGetDatum(false);
 
                tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
                result = HeapTupleGetDatum(tuple);
@@ -342,6 +426,23 @@ pg_advisory_lock_int8(PG_FUNCTION_ARGS)
        PG_RETURN_VOID();
 }
 
+/*
+ * pg_advisory_xact_lock(int8) - acquire xact scoped
+ * exclusive lock on an int8 key
+ */
+Datum
+pg_advisory_xact_lock_int8(PG_FUNCTION_ARGS)
+{
+       int64           key = PG_GETARG_INT64(0);
+       LOCKTAG         tag;
+
+       SET_LOCKTAG_INT64(tag, key);
+
+       (void) LockAcquire(&tag, ExclusiveLock, false, false);
+
+       PG_RETURN_VOID();
+}
+
 /*
  * pg_advisory_lock_shared(int8) - acquire share lock on an int8 key
  */
@@ -358,6 +459,23 @@ pg_advisory_lock_shared_int8(PG_FUNCTION_ARGS)
        PG_RETURN_VOID();
 }
 
+/*
+ * pg_advisory_xact_lock_shared(int8) - acquire xact scoped
+ * share lock on an int8 key
+ */
+Datum
+pg_advisory_xact_lock_shared_int8(PG_FUNCTION_ARGS)
+{
+       int64           key = PG_GETARG_INT64(0);
+       LOCKTAG         tag;
+
+       SET_LOCKTAG_INT64(tag, key);
+
+       (void) LockAcquire(&tag, ShareLock, false, false);
+
+       PG_RETURN_VOID();
+}
+
 /*
  * pg_try_advisory_lock(int8) - acquire exclusive lock on an int8 key, no wait
  *
@@ -377,6 +495,26 @@ pg_try_advisory_lock_int8(PG_FUNCTION_ARGS)
        PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
 }
 
+/*
+ * pg_try_advisory_xact_lock(int8) - acquire xact scoped
+ * exclusive lock on an int8 key, no wait
+ *
+ * Returns true if successful, false if lock not available
+ */
+Datum
+pg_try_advisory_xact_lock_int8(PG_FUNCTION_ARGS)
+{
+       int64           key = PG_GETARG_INT64(0);
+       LOCKTAG         tag;
+       LockAcquireResult res;
+
+       SET_LOCKTAG_INT64(tag, key);
+
+       res = LockAcquire(&tag, ExclusiveLock, false, true);
+
+       PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
+}
+
 /*
  * pg_try_advisory_lock_shared(int8) - acquire share lock on an int8 key, no wait
  *
@@ -396,6 +534,26 @@ pg_try_advisory_lock_shared_int8(PG_FUNCTION_ARGS)
        PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
 }
 
+/*
+ * pg_try_advisory_xact_lock_shared(int8) - acquire xact scoped
+ * share lock on an int8 key, no wait
+ *
+ * Returns true if successful, false if lock not available
+ */
+Datum
+pg_try_advisory_xact_lock_shared_int8(PG_FUNCTION_ARGS)
+{
+       int64           key = PG_GETARG_INT64(0);
+       LOCKTAG         tag;
+       LockAcquireResult res;
+
+       SET_LOCKTAG_INT64(tag, key);
+
+       res = LockAcquire(&tag, ShareLock, false, true);
+
+       PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
+}
+
 /*
  * pg_advisory_unlock(int8) - release exclusive lock on an int8 key
  *
@@ -451,6 +609,24 @@ pg_advisory_lock_int4(PG_FUNCTION_ARGS)
        PG_RETURN_VOID();
 }
 
+/*
+ * pg_advisory_xact_lock(int4, int4) - acquire xact scoped
+ * exclusive lock on 2 int4 keys
+ */
+Datum
+pg_advisory_xact_lock_int4(PG_FUNCTION_ARGS)
+{
+       int32           key1 = PG_GETARG_INT32(0);
+       int32           key2 = PG_GETARG_INT32(1);
+       LOCKTAG         tag;
+
+       SET_LOCKTAG_INT32(tag, key1, key2);
+
+       (void) LockAcquire(&tag, ExclusiveLock, false, false);
+
+       PG_RETURN_VOID();
+}
+
 /*
  * pg_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys
  */
@@ -468,6 +644,24 @@ pg_advisory_lock_shared_int4(PG_FUNCTION_ARGS)
        PG_RETURN_VOID();
 }
 
+/*
+ * pg_advisory_xact_lock_shared(int4, int4) - acquire xact scoped
+ * share lock on 2 int4 keys
+ */
+Datum
+pg_advisory_xact_lock_shared_int4(PG_FUNCTION_ARGS)
+{
+       int32           key1 = PG_GETARG_INT32(0);
+       int32           key2 = PG_GETARG_INT32(1);
+       LOCKTAG         tag;
+
+       SET_LOCKTAG_INT32(tag, key1, key2);
+
+       (void) LockAcquire(&tag, ShareLock, false, false);
+
+       PG_RETURN_VOID();
+}
+
 /*
  * pg_try_advisory_lock(int4, int4) - acquire exclusive lock on 2 int4 keys, no wait
  *
@@ -488,6 +682,27 @@ pg_try_advisory_lock_int4(PG_FUNCTION_ARGS)
        PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
 }
 
+/*
+ * pg_try_advisory_xact_lock(int4, int4) - acquire xact scoped
+ * exclusive lock on 2 int4 keys, no wait
+ *
+ * Returns true if successful, false if lock not available
+ */
+Datum
+pg_try_advisory_xact_lock_int4(PG_FUNCTION_ARGS)
+{
+       int32           key1 = PG_GETARG_INT32(0);
+       int32           key2 = PG_GETARG_INT32(1);
+       LOCKTAG         tag;
+       LockAcquireResult res;
+
+       SET_LOCKTAG_INT32(tag, key1, key2);
+
+       res = LockAcquire(&tag, ExclusiveLock, false, true);
+
+       PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
+}
+
 /*
  * pg_try_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys, no wait
  *
@@ -508,6 +723,27 @@ pg_try_advisory_lock_shared_int4(PG_FUNCTION_ARGS)
        PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
 }
 
+/*
+ * pg_try_advisory_xact_lock_shared(int4, int4) - acquire xact scoped
+ * share lock on 2 int4 keys, no wait
+ *
+ * Returns true if successful, false if lock not available
+ */
+Datum
+pg_try_advisory_xact_lock_shared_int4(PG_FUNCTION_ARGS)
+{
+       int32           key1 = PG_GETARG_INT32(0);
+       int32           key2 = PG_GETARG_INT32(1);
+       LOCKTAG         tag;
+       LockAcquireResult res;
+
+       SET_LOCKTAG_INT32(tag, key1, key2);
+
+       res = LockAcquire(&tag, ShareLock, false, true);
+
+       PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
+}
+
 /*
  * pg_advisory_unlock(int4, int4) - release exclusive lock on 2 int4 keys
  *
@@ -554,7 +790,7 @@ pg_advisory_unlock_shared_int4(PG_FUNCTION_ARGS)
 Datum
 pg_advisory_unlock_all(PG_FUNCTION_ARGS)
 {
-       LockReleaseAll(USER_LOCKMETHOD, true);
+       LockReleaseSession(USER_LOCKMETHOD);
 
        PG_RETURN_VOID();
 }