Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  lockfuncs.c

  Sprache: C
 

/*-------------------------------------------------------------------------
 *
 * lockfuncs.c
 *  Functions for SQL access to various lock-manager capabilities.
 *
 * Copyright (c) 2002-2025, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *  src/backend/utils/adt/lockfuncs.c
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include "access/htup_details.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "storage/predicate_internals.h"
#include "utils/array.h"
#include "utils/builtins.h"


/*
 * This must match enum LockTagType!  Also, be sure to document any changes
 * in the docs for the pg_locks view and update the WaitEventLOCK section in
 * src/backend/utils/activity/wait_event_names.txt.
 */

const char *const LockTagTypeNames[] = {
 "relation",
 "extend",
 "frozenid",
 "page",
 "tuple",
 "transactionid",
 "virtualxid",
 "spectoken",
 "object",
 "userlock",
 "advisory",
 "applytransaction"
};

StaticAssertDecl(lengthof(LockTagTypeNames) == (LOCKTAG_LAST_TYPE + 1),
     "array length mismatch");

/* This must match enum PredicateLockTargetType (predicate_internals.h) */
static const char *const PredicateLockTagTypeNames[] = {
 "relation",
 "page",
 "tuple"
};

StaticAssertDecl(lengthof(PredicateLockTagTypeNames) == (PREDLOCKTAG_TUPLE + 1),
     "array length mismatch");

/* 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  16

/*
 * VXIDGetDatum - Construct a text representation of a VXID
 *
 * This is currently only used in pg_lock_status, so we put it here.
 */

static Datum
VXIDGetDatum(ProcNumber procNumber, LocalTransactionId lxid)
{
 /*
  * The representation is "<procNumber>/<lxid>", decimal and unsigned
  * decimal respectively.  Note that elog.c also knows how to format a
  * vxid.
 */

 char  vxidstr[32];

 snprintf(vxidstr, sizeof(vxidstr), "%d/%u", procNumber, lxid);

 return CStringGetTextDatum(vxidstr);
}


/*
 * pg_lock_status - produce a view with one row per held or awaited lock mode
 */

Datum
pg_lock_status(PG_FUNCTION_ARGS)
{
 FuncCallContext *funcctx;
 PG_Lock_Status *mystatus;
 LockData   *lockData;
 PredicateLockData *predLockData;

 if (SRF_IS_FIRSTCALL())
 {
  TupleDesc tupdesc;
  MemoryContext oldcontext;

  /* create a function context for cross-call persistence */
  funcctx = SRF_FIRSTCALL_INIT();

  /*
   * switch to memory context appropriate for multiple function calls
 */

  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

  /* build tupdesc for result tuples */
  /* this had better match function's declaration in pg_proc.h */
  tupdesc = CreateTemplateTupleDesc(NUM_LOCK_STATUS_COLUMNS);
  TupleDescInitEntry(tupdesc, (AttrNumber) 1"locktype",
         TEXTOID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 2"database",
         OIDOID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 3"relation",
         OIDOID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 4"page",
         INT4OID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 5"tuple",
         INT2OID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 6"virtualxid",
         TEXTOID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 7"transactionid",
         XIDOID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 8"classid",
         OIDOID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 9"objid",
         OIDOID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 10"objsubid",
         INT2OID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 11"virtualtransaction",
         TEXTOID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 12"pid",
         INT4OID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 13"mode",
         TEXTOID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 14"granted",
         BOOLOID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 15"fastpath",
         BOOLOID, -10);
  TupleDescInitEntry(tupdesc, (AttrNumber) 16"waitstart",
         TIMESTAMPTZOID, -10);

  funcctx->tuple_desc = BlessTupleDesc(tupdesc);

  /*
   * Collect all the locking information that we will format and send
   * out as a result set.
 */

  mystatus = (PG_Lock_Status *) palloc(sizeof(PG_Lock_Status));
  funcctx->user_fctx = mystatus;

  mystatus->lockData = GetLockStatusData();
  mystatus->currIdx = 0;
  mystatus->predLockData = GetPredicateLockStatusData();
  mystatus->predLockIdx = 0;

  MemoryContextSwitchTo(oldcontext);
 }

 funcctx = SRF_PERCALL_SETUP();
 mystatus = (PG_Lock_Status *) funcctx->user_fctx;
 lockData = mystatus->lockData;

 while (mystatus->currIdx < lockData->nelements)
 {
  bool  granted;
  LOCKMODE mode = 0;
  const char *locktypename;
  char  tnbuf[32];
  Datum  values[NUM_LOCK_STATUS_COLUMNS] = {0};
  bool  nulls[NUM_LOCK_STATUS_COLUMNS] = {0};
  HeapTuple tuple;
  Datum  result;
  LockInstanceData *instance;

  instance = &(lockData->locks[mystatus->currIdx]);

  /*
   * Look to see if there are any held lock modes in this PROCLOCK. If
   * so, report, and destructively modify lockData so we don't report
   * again.
 */

  granted = false;
  if (instance->holdMask)
  {
   for (mode = 0; mode < MAX_LOCKMODES; mode++)
   {
    if (instance->holdMask & LOCKBIT_ON(mode))
    {
     granted = true;
     instance->holdMask &= LOCKBIT_OFF(mode);
     break;
    }
   }
  }

  /*
   * If no (more) held modes to report, see if PROC is waiting for a
   * lock on this lock.
 */

  if (!granted)
  {
   if (instance->waitLockMode != NoLock)
   {
    /* Yes, so report it with proper mode */
    mode = instance->waitLockMode;

    /*
     * We are now done with this PROCLOCK, so advance pointer to
     * continue with next one on next call.
 */

    mystatus->currIdx++;
   }
   else
   {
    /*
     * Okay, we've displayed all the locks associated with this
     * PROCLOCK, proceed to the next one.
 */

    mystatus->currIdx++;
    continue;
   }
  }

  /*
   * Form tuple with appropriate data.
 */


  if (instance->locktag.locktag_type <= LOCKTAG_LAST_TYPE)
   locktypename = LockTagTypeNames[instance->locktag.locktag_type];
  else
  {
   snprintf(tnbuf, sizeof(tnbuf), "unknown %d",
      (int) instance->locktag.locktag_type);
   locktypename = tnbuf;
  }
  values[0] = CStringGetTextDatum(locktypename);

  switch ((LockTagType) instance->locktag.locktag_type)
  {
   case LOCKTAG_RELATION:
   case LOCKTAG_RELATION_EXTEND:
    values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
    values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
    nulls[3] = true;
    nulls[4] = true;
    nulls[5] = true;
    nulls[6] = true;
    nulls[7] = true;
    nulls[8] = true;
    nulls[9] = true;
    break;
   case LOCKTAG_DATABASE_FROZEN_IDS:
    values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
    nulls[2] = true;
    nulls[3] = true;
    nulls[4] = true;
    nulls[5] = true;
    nulls[6] = true;
    nulls[7] = true;
    nulls[8] = true;
    nulls[9] = true;
    break;
   case LOCKTAG_PAGE:
    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;
    nulls[7] = true;
    nulls[8] = true;
    nulls[9] = true;
    break;
   case LOCKTAG_TUPLE:
    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;
    nulls[8] = true;
    nulls[9] = true;
    break;
   case LOCKTAG_TRANSACTION:
    values[6] =
     TransactionIdGetDatum(instance->locktag.locktag_field1);
    nulls[1] = true;
    nulls[2] = true;
    nulls[3] = true;
    nulls[4] = true;
    nulls[5] = true;
    nulls[7] = true;
    nulls[8] = true;
    nulls[9] = true;
    break;
   case LOCKTAG_VIRTUALTRANSACTION:
    values[5] = VXIDGetDatum(instance->locktag.locktag_field1,
           instance->locktag.locktag_field2);
    nulls[1] = true;
    nulls[2] = true;
    nulls[3] = true;
    nulls[4] = true;
    nulls[6] = true;
    nulls[7] = true;
    nulls[8] = true;
    nulls[9] = true;
    break;
   case LOCKTAG_SPECULATIVE_TOKEN:
    values[6] =
     TransactionIdGetDatum(instance->locktag.locktag_field1);
    values[8] = ObjectIdGetDatum(instance->locktag.locktag_field2);
    nulls[1] = true;
    nulls[2] = true;
    nulls[3] = true;
    nulls[4] = true;
    nulls[5] = true;
    nulls[7] = true;
    nulls[9] = true;
    break;
   case LOCKTAG_APPLY_TRANSACTION:
    values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
    values[8] = ObjectIdGetDatum(instance->locktag.locktag_field2);
    values[6] = ObjectIdGetDatum(instance->locktag.locktag_field3);
    values[9] = Int16GetDatum(instance->locktag.locktag_field4);
    nulls[2] = true;
    nulls[3] = true;
    nulls[4] = true;
    nulls[5] = true;
    nulls[7] = true;
    break;
   case LOCKTAG_OBJECT:
   case LOCKTAG_USERLOCK:
   case LOCKTAG_ADVISORY:
   default:   /* treat unknown locktags like OBJECT */
    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;
    nulls[5] = true;
    nulls[6] = true;
    break;
  }

  values[10] = VXIDGetDatum(instance->vxid.procNumber, instance->vxid.localTransactionId);
  if (instance->pid != 0)
   values[11] = Int32GetDatum(instance->pid);
  else
   nulls[11] = true;
  values[12] = CStringGetTextDatum(GetLockmodeName(instance->locktag.locktag_lockmethodid, mode));
  values[13] = BoolGetDatum(granted);
  values[14] = BoolGetDatum(instance->fastpath);
  if (!granted && instance->waitStart != 0)
   values[15] = TimestampTzGetDatum(instance->waitStart);
  else
   nulls[15] = true;

  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] = {0};
  bool  nulls[NUM_LOCK_STATUS_COLUMNS] = {0};
  HeapTuple tuple;
  Datum  result;

  mystatus->predLockIdx++;

  /*
   * Form tuple with appropriate data.
 */


  /* 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.procNumber,
          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);
  nulls[15] = true;

  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
  result = HeapTupleGetDatum(tuple);
  SRF_RETURN_NEXT(funcctx, result);
 }

 SRF_RETURN_DONE(funcctx);
}


/*
 * pg_blocking_pids - produce an array of the PIDs blocking given PID
 *
 * The reported PIDs are those that hold a lock conflicting with blocked_pid's
 * current request (hard block), or are requesting such a lock and are ahead
 * of blocked_pid in the lock's wait queue (soft block).
 *
 * In parallel-query cases, we report all PIDs blocking any member of the
 * given PID's lock group, and the reported PIDs are those of the blocking
 * PIDs' lock group leaders.  This allows callers to compare the result to
 * lists of clients' pg_backend_pid() results even during a parallel query.
 *
 * Parallel query makes it possible for there to be duplicate PIDs in the
 * result (either because multiple waiters are blocked by same PID, or
 * because multiple blockers have same group leader PID).  We do not bother
 * to eliminate such duplicates from the result.
 *
 * We need not consider predicate locks here, since those don't block anything.
 */

Datum
pg_blocking_pids(PG_FUNCTION_ARGS)
{
 int   blocked_pid = PG_GETARG_INT32(0);
 Datum    *arrayelems;
 int   narrayelems;
 BlockedProcsData *lockData; /* state data from lmgr */
 int   i,
    j;

 /* Collect a snapshot of lock manager state */
 lockData = GetBlockerStatusData(blocked_pid);

 /* We can't need more output entries than there are reported PROCLOCKs */
 arrayelems = (Datum *) palloc(lockData->nlocks * sizeof(Datum));
 narrayelems = 0;

 /* For each blocked proc in the lock group ... */
 for (i = 0; i < lockData->nprocs; i++)
 {
  BlockedProcData *bproc = &lockData->procs[i];
  LockInstanceData *instances = &lockData->locks[bproc->first_lock];
  int     *preceding_waiters = &lockData->waiter_pids[bproc->first_waiter];
  LockInstanceData *blocked_instance;
  LockMethod lockMethodTable;
  int   conflictMask;

  /*
   * Locate the blocked proc's own entry in the LockInstanceData array.
   * There should be exactly one matching entry.
 */

  blocked_instance = NULL;
  for (j = 0; j < bproc->num_locks; j++)
  {
   LockInstanceData *instance = &(instances[j]);

   if (instance->pid == bproc->pid)
   {
    Assert(blocked_instance == NULL);
    blocked_instance = instance;
   }
  }
  Assert(blocked_instance != NULL);

  lockMethodTable = GetLockTagsMethodTable(&(blocked_instance->locktag));
  conflictMask = lockMethodTable->conflictTab[blocked_instance->waitLockMode];

  /* Now scan the PROCLOCK data for conflicting procs */
  for (j = 0; j < bproc->num_locks; j++)
  {
   LockInstanceData *instance = &(instances[j]);

   /* A proc never blocks itself, so ignore that entry */
   if (instance == blocked_instance)
    continue;
   /* Members of same lock group never block each other, either */
   if (instance->leaderPid == blocked_instance->leaderPid)
    continue;

   if (conflictMask & instance->holdMask)
   {
    /* hard block: blocked by lock already held by this entry */
   }
   else if (instance->waitLockMode != NoLock &&
      (conflictMask & LOCKBIT_ON(instance->waitLockMode)))
   {
    /* conflict in lock requests; who's in front in wait queue? */
    bool  ahead = false;
    int   k;

    for (k = 0; k < bproc->num_waiters; k++)
    {
     if (preceding_waiters[k] == instance->pid)
     {
      /* soft block: this entry is ahead of blocked proc */
      ahead = true;
      break;
     }
    }
    if (!ahead)
     continue/* not blocked by this entry */
   }
   else
   {
    /* not blocked by this entry */
    continue;
   }

   /* blocked by this entry, so emit a record */
   arrayelems[narrayelems++] = Int32GetDatum(instance->leaderPid);
  }
 }

 /* Assert we didn't overrun arrayelems[] */
 Assert(narrayelems <= lockData->nlocks);

 PG_RETURN_ARRAYTYPE_P(construct_array_builtin(arrayelems, narrayelems, INT4OID));
}


/*
 * pg_safe_snapshot_blocking_pids - produce an array of the PIDs blocking
 * given PID from getting a safe snapshot
 *
 * XXX this does not consider parallel-query cases; not clear how big a
 * problem that is in practice
 */

Datum
pg_safe_snapshot_blocking_pids(PG_FUNCTION_ARGS)
{
 int   blocked_pid = PG_GETARG_INT32(0);
 int     *blockers;
 int   num_blockers;
 Datum    *blocker_datums;

 /* A buffer big enough for any possible blocker list without truncation */
 blockers = (int *) palloc(MaxBackends * sizeof(int));

 /* Collect a snapshot of processes waited for by GetSafeSnapshot */
 num_blockers =
  GetSafeSnapshotBlockingPids(blocked_pid, blockers, MaxBackends);

 /* Convert int array to Datum array */
 if (num_blockers > 0)
 {
  int   i;

  blocker_datums = (Datum *) palloc(num_blockers * sizeof(Datum));
  for (i = 0; i < num_blockers; ++i)
   blocker_datums[i] = Int32GetDatum(blockers[i]);
 }
 else
  blocker_datums = NULL;

 PG_RETURN_ARRAYTYPE_P(construct_array_builtin(blocker_datums, num_blockers, INT4OID));
}


/*
 * Functions for manipulating advisory locks
 *
 * We make use of the locktag fields as follows:
 *
 * field1: MyDatabaseId ... ensures locks are local to each database
 * field2: first of 2 int4 keys, or high-order half of an int8 key
 * field3: second of 2 int4 keys, or low-order half of an int8 key
 * field4: 1 if using an int8 key, 2 if using 2 int4 keys
 */

#define SET_LOCKTAG_INT64(tag, key64) \
 SET_LOCKTAG_ADVISORY(tag, \
       MyDatabaseId, \
       (uint32) ((key64) >> 32), \
       (uint32) (key64), \
       1)
#define SET_LOCKTAG_INT32(tag, key1, key2) \
 SET_LOCKTAG_ADVISORY(tag, MyDatabaseId, key1, key2, 2)

/*
 * pg_advisory_lock(int8) - acquire exclusive lock on an int8 key
 */

Datum
pg_advisory_lock_int8(PG_FUNCTION_ARGS)
{
 int64  key = PG_GETARG_INT64(0);
 LOCKTAG  tag;

 SET_LOCKTAG_INT64(tag, key);

 (void) LockAcquire(&tag, ExclusiveLock, truefalse);

 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, falsefalse);

 PG_RETURN_VOID();
}

/*
 * pg_advisory_lock_shared(int8) - acquire share lock on an int8 key
 */

Datum
pg_advisory_lock_shared_int8(PG_FUNCTION_ARGS)
{
 int64  key = PG_GETARG_INT64(0);
 LOCKTAG  tag;

 SET_LOCKTAG_INT64(tag, key);

 (void) LockAcquire(&tag, ShareLock, truefalse);

 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, falsefalse);

 PG_RETURN_VOID();
}

/*
 * pg_try_advisory_lock(int8) - acquire exclusive lock on an int8 key, no wait
 *
 * Returns true if successful, false if lock not available
 */

Datum
pg_try_advisory_lock_int8(PG_FUNCTION_ARGS)
{
 int64  key = PG_GETARG_INT64(0);
 LOCKTAG  tag;
 LockAcquireResult res;

 SET_LOCKTAG_INT64(tag, key);

 res = LockAcquire(&tag, ExclusiveLock, truetrue);

 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, falsetrue);

 PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
}

/*
 * pg_try_advisory_lock_shared(int8) - acquire share lock on an int8 key, no wait
 *
 * Returns true if successful, false if lock not available
 */

Datum
pg_try_advisory_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, truetrue);

 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, falsetrue);

 PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
}

/*
 * pg_advisory_unlock(int8) - release exclusive lock on an int8 key
 *
 * Returns true if successful, false if lock was not held
*/

Datum
pg_advisory_unlock_int8(PG_FUNCTION_ARGS)
{
 int64  key = PG_GETARG_INT64(0);
 LOCKTAG  tag;
 bool  res;

 SET_LOCKTAG_INT64(tag, key);

 res = LockRelease(&tag, ExclusiveLock, true);

 PG_RETURN_BOOL(res);
}

/*
 * pg_advisory_unlock_shared(int8) - release share lock on an int8 key
 *
 * Returns true if successful, false if lock was not held
 */

Datum
pg_advisory_unlock_shared_int8(PG_FUNCTION_ARGS)
{
 int64  key = PG_GETARG_INT64(0);
 LOCKTAG  tag;
 bool  res;

 SET_LOCKTAG_INT64(tag, key);

 res = LockRelease(&tag, ShareLock, true);

 PG_RETURN_BOOL(res);
}

/*
 * pg_advisory_lock(int4, int4) - acquire exclusive lock on 2 int4 keys
 */

Datum
pg_advisory_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, truefalse);

 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, falsefalse);

 PG_RETURN_VOID();
}

/*
 * pg_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys
 */

Datum
pg_advisory_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, truefalse);

 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, falsefalse);

 PG_RETURN_VOID();
}

/*
 * pg_try_advisory_lock(int4, int4) - acquire exclusive lock on 2 int4 keys, no wait
 *
 * Returns true if successful, false if lock not available
 */

Datum
pg_try_advisory_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, truetrue);

 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, falsetrue);

 PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
}

/*
 * pg_try_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys, no wait
 *
 * Returns true if successful, false if lock not available
 */

Datum
pg_try_advisory_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, truetrue);

 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, falsetrue);

 PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
}

/*
 * pg_advisory_unlock(int4, int4) - release exclusive lock on 2 int4 keys
 *
 * Returns true if successful, false if lock was not held
*/

Datum
pg_advisory_unlock_int4(PG_FUNCTION_ARGS)
{
 int32  key1 = PG_GETARG_INT32(0);
 int32  key2 = PG_GETARG_INT32(1);
 LOCKTAG  tag;
 bool  res;

 SET_LOCKTAG_INT32(tag, key1, key2);

 res = LockRelease(&tag, ExclusiveLock, true);

 PG_RETURN_BOOL(res);
}

/*
 * pg_advisory_unlock_shared(int4, int4) - release share lock on 2 int4 keys
 *
 * Returns true if successful, false if lock was not held
 */

Datum
pg_advisory_unlock_shared_int4(PG_FUNCTION_ARGS)
{
 int32  key1 = PG_GETARG_INT32(0);
 int32  key2 = PG_GETARG_INT32(1);
 LOCKTAG  tag;
 bool  res;

 SET_LOCKTAG_INT32(tag, key1, key2);

 res = LockRelease(&tag, ShareLock, true);

 PG_RETURN_BOOL(res);
}

/*
 * pg_advisory_unlock_all() - release all advisory locks
 */

Datum
pg_advisory_unlock_all(PG_FUNCTION_ARGS)
{
 LockReleaseSession(USER_LOCKMETHOD);

 PG_RETURN_VOID();
}

Messung V0.5 in Prozent
C=94 H=93 G=93

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

letze Version des Elbe Quellennavigators


Jenseits des Üblichen ....
    

Besucher

Besucher

Statistik
#Sources=141584
#Domains=752002