3 * Set-returning functions to view the state of locks within the DB.
5 * Copyright (c) 2002, PostgreSQL Global Development Group
8 * $Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.1 2002/08/17 13:11:43 momjian Exp $
14 #include "storage/lmgr.h"
15 #include "storage/lock.h"
16 #include "storage/lwlock.h"
17 #include "storage/proc.h"
19 Datum lock_status_srf(PG_FUNCTION_ARGS);
21 static int next_lock(int locks[]);
24 lock_status_srf(PG_FUNCTION_ARGS)
26 FuncCallContext *funccxt;
29 if (SRF_IS_FIRSTCALL())
34 funccxt = SRF_FIRSTCALL_INIT();
35 tupdesc = RelationNameGetTupleDesc("pg_catalog.pg_locks_result");
36 funccxt->slot = TupleDescGetSlot(tupdesc);
37 funccxt->attinmeta = TupleDescGetAttInMetadata(tupdesc);
39 oldcxt = MemoryContextSwitchTo(funccxt->fmctx);
42 * Preload all the locking information that we will eventually format
43 * and send out as a result set. This is palloc'ed, but since the
44 * MemoryContext is reset when the SRF finishes, we don't need to
47 funccxt->user_fctx = (LockData *) palloc(sizeof(LockData));
49 GetLockStatusData(funccxt->user_fctx);
51 MemoryContextSwitchTo(oldcxt);
54 funccxt = SRF_PERCALL_SETUP();
55 lockData = (LockData *) funccxt->user_fctx;
57 while (lockData->currIdx < lockData->nelements)
68 int currIdx = lockData->currIdx;
70 holder = &(lockData->holders[currIdx]);
71 lock = &(lockData->locks[currIdx]);
72 proc = &(lockData->procs[currIdx]);
73 num_attrs = funccxt->attinmeta->tupdesc->natts;
75 values = (char **) palloc(sizeof(*values) * num_attrs);
77 for (i = 0; i < num_attrs; i++)
78 values[i] = (char *) palloc(32);
80 /* The OID of the locked relation */
81 snprintf(values[0], 32, "%u", lock->tag.relId);
82 /* The database the relation is in */
83 snprintf(values[1], 32, "%u", lock->tag.dbId);
84 /* The PID of the backend holding or waiting for the lock */
85 snprintf(values[2], 32, "%d", proc->pid);
88 * We need to report both the locks held (i.e. successfully acquired)
89 * by this holder, as well as the locks upon which it is still
90 * waiting, if any. Since a single PROCLOCK struct may contain
91 * multiple locks, we may need to loop several times before we
92 * advance the array index and continue on.
94 if (holder->nHolding > 0)
96 /* Already held locks */
97 mode = next_lock(holder->holding);
98 holder->holding[mode]--;
101 strcpy(values[4], "t");
103 else if (proc->waitLock != NULL)
105 /* Lock that is still being waited on */
106 mode = proc->waitLockMode;
107 proc->waitLock = NULL;
108 proc->waitLockMode = NoLock;
110 strcpy(values[4], "f");
115 * Okay, we've displayed all the lock's belonging to this PROCLOCK,
116 * procede to the next one.
122 strncpy(values[3], GetLockmodeName(mode), 32);
124 tuple = BuildTupleFromCStrings(funccxt->attinmeta, values);
125 result = TupleGetDatum(funccxt->slot, tuple);
126 SRF_RETURN_NEXT(funccxt, result);
129 SRF_RETURN_DONE(funccxt);
133 next_lock(int locks[])
137 for (i = 0; i < MAX_LOCKMODES; i++)
143 /* No locks found: this should not occur */