Article 140102 of comp.os.vms:
Path: nntpd.lkg.dec.com!eps.enet.dec.com!vandenheuvel
From: vandenheuvel@eps.enet.dec.com (Hein RMS van den Heuvel)
Newsgroups: comp.os.vms
Subject: Re: RMS LOcks Manager
Date: 12 FEB 96 00:53:00
Organization: Digital Equipment Corporation
Lines: 171
Message-ID: <4fmlb3$6ps@nntpd.lkg.dec.com>
References: <4fgfp2$kol@news.zocalo.net>
NNTP-Posting-Host: epsys.enet.dec.com


In article <4fgfp2$kol@news.zocalo.net>, Arden Scott <arden@nis.com> writes...
>We are looking for a way to find the user name of the person who has a lock
>on a particular record or file which was locked via RMS SYS$GET(rab) call
>under VMS 5.4 on a VAX. I have not been able to find any documented method
>or even if the information is available. Any help greatly appreciated.
>arden@nis.com at National Information Systems. Thank you.

As pointed out earlier, DECamds is good at helping out in theses case.
Secondly there is always ANALYZE/SYSTEM... SET PROC <name-of-process-
currently-waiting-for-lock>... SHOW PROC /LOCK. For a process waiting 
for an RMS record lock, his will show a lock with a rather cryptic
looking binary resource name as a sublock of RMS$mumble lock.
A subsequent SDA> SHOW LOCK <lockid> will show you which process is
holding that lock. You can also dig deeper with SDA using SHOW
PROCES/RMS=(RAB,IRAB) and look for the IRAB flagged BSY.
The RAB going with that will show a KBF/KSZ describing a key buffer
being used IFF RAC=KEY or RBF/RSZ will likely describe the record 
before the one being stuck.

A little while ago I wrote a proggie to walk a GETLKI provided list
of all the locks on a system, looking for blocked lock. I'll include
it again. It might just do the job for you...

/*
** BLOCKING.C, Hein van den Heuvel, Digital, July 1995
**  
**   List all locks not granted (converting, waiting) for a specified PID.
**   For each, print blocking lock information, resource name and parent.
**   Have fun,
**	Hein van den Heuvel, July 1995.
*/

#include <ssdef>
#include <prvdef>
#include <lkidef>
#include <lckdef>
#include <string>
#include <ctype>
#include <stdio>
#define terminator 0,0,0,0
#define EFN 1

typedef struct { short len, cod; void *address; short *retlen; } item;
int	sys$getlkiw(), sys$getjpi(), sys$setprv(), sys$cmexec();
void	print_resource_name();
char	*mode[]={"NL", "CR", "CW", "PR", "PW", "EX", "??"};































main(argc, argv)
int	argc;
char	*argv[];
{
    int	    stat, s, i, l, parent, grand_parent, lock_id, lock_pid;
    int	    wildcard=0, retlen=0, pid=0, locks=0;
    char    *x;
    struct lkidef lkibuf[50], *lki;
    struct { unsigned all : 16, one : 15, too_small : 1 ;} lkilen;
    int	    privs[] = { PRV$M_WORLD | PRV$M_CMEXEC , 0}, context[] = {0,0};

#pragma nostandard /* Using address of variable where constant is standard */

    struct  {   char	rqmode, grmode, queue, fill;} lki_state;
    struct  {	int	rms; unsigned short fid_num, fid_seq, fid_rvn;
		char	devlocknam[22] ;} parent_resnam;
    struct  {	int	id, vbn, fill[6];} resnam;

    item    getlki_items[] = {	 4, LKI$_LOCKID,    &lock_id, 0, 
				 4, LKI$_PID,       &lock_pid, 0, 
				 3, LKI$_STATE,     &lki_state, 0, terminator};
    item    block_items[] = {	31, LKI$_RESNAM,    &resnam, &retlen,
				 4, LKI$_PARENT,    &parent, 0, 
		     sizeof lkibuf, LKI$_BLOCKING,  &lkibuf, &lkilen, terminator};
    item    parent_items[] = {	31, LKI$_RESNAM,    &parent_resnam, &retlen,
				 4, LKI$_PARENT,    &grand_parent, 0, terminator};
    int
	getlki_args[] = {7, EFN, (int) &wildcard, (int) &getlki_items,0,0,0,0},
	parent_args[] = {7, EFN, (int) &parent, (int) &parent_items,0,0,0,0},
	block_args[] = {7, EFN, (int) &lock_id, (int) &block_items,0,0,0,0};

#pragma standard












    /*
    ** First get some temporary privs for the GETLKI in EXEC mode later on.
    */
    stat = sys$setprv ( 1, privs, 0, 0);
    if (stat != SS$_NORMAL) return (stat & -2);

    if (argc > 1) {
	sscanf (argv[1], "%x", &pid);
	printf (" Looking for non-granted locks for PID %8X\n\n", pid);
	} else {
	printf (" Looking for non-granted locks for all PIDs\n\n");
	};

    /*
    ** Main loop. Get a lock, any lock. 
    ** Find out wether it is held by specified process, and waiting.
    */
    stat = sys$cmexec (&sys$getlkiw, &getlki_args);
    while (stat & 1) {
	locks++;
	if ( (lki_state.queue != LKI$C_GRANTED) &&
	     ((pid == 0) ||  (lock_pid == pid)) ) {
	    parent = 0;
	    /*
	    ** Have blocked lock for specified PID, request details.
	    */
	    stat = sys$cmexec (&sys$getlkiw, &block_args);
	    if (!(stat & 1)) break;
	    l = lkilen.all / lkilen.one;
	    printf ("Pid %08X Lock %08X, Rq=%s, Parent %08X, blocked by %d.\n", 
		lock_pid, lock_id, mode[lki_state.rqmode], parent, l);
	    print_resource_name(&resnam, retlen, "");
	    lki = &lkibuf;
	    for ( i = 0; i < l; i++) {
		printf ("  PID=%8X, Gr=%s, Rq=%s, LockId=%08X, System=%08\n",
			    lki->lki$l_pid,
			    mode[lki->lki$b_grmode], mode[lki->lki$b_rqmode],
			    lki->lki$l_lkid, lki->lki$l_csid);
		lki++;
		}
	    if (parent!=0) {
		s = sys$cmexec (&sys$getlkiw, &parent_args);
		print_resource_name(&parent_resnam, retlen, "Parent ");
		if ((s & 1) && (grand_parent==0) && 
		    (parent_resnam.rms == 'RMS$')) {
		    /*
		    ** Stumbled accross an rms lock.
		    ** Let's printf out formatted resourse names.
		    */
		    printf ("  RMS lock! VBN/ID %X/%X, File (%d,%d,%d) on %s\n", 
			    resnam.vbn, resnam.id,
			    parent_resnam.fid_num, parent_resnam.fid_seq,
			    parent_resnam.fid_rvn, 
			    &parent_resnam.devlocknam[1]);
		    } /* RMS$  ? */
		}     /* Parent? */
	    printf ("\n");
	    }         /* PID   ? */
	if (stat &1) stat = sys$cmexec (&sys$getlkiw, &getlki_args);	
	} /* stat ? */
    if (stat == SS$_NOMORELOCK) stat = SS$_NORMAL;
    printf (" Done. Scanned %d locks.\n", locks);
    return stat;
}
void print_resource_name(void *p, short len, char *t)
{
    int	i, (*x)[8];
    char out[32], *in, c;
    x = in = p;
    if (len >= sizeof out) len = sizeof out - 1;
    for (i=0; i<len; i++){
	c = *in++;
	if (!isalnum (c)) c = '.';
	out[i]=c;
	}
    out[i]=0;
    printf ("    %sResource Name (%d): <%s>\n", t, len, &out[0]);
    printf ("      %08X %08X %08X %08X\n", (*x)[0],(*x)[1],(*x)[2],(*x)[3]);
    if (len > 16) 
       printf ("      %08X %08X %08X %08X\n", (*x)[4],(*x)[5],(*x)[6],(*x)[7]);
}





Hope this helps,		+--------------------------------------+
Hein van den Heuvel, Digital.	| All opinions expressed are mine, and |
  "Makers of VMS and other	| may not reflect those of my employer |
   fine Operating Systems."	+--------------------------------------+


