# 8. M Lock Utility (LKE)¶

## Introduction¶

The M Lock Utility (LKE) is a tool for examining and changing the YottaDB LOCK environment. For a description of M LOCKs, refer to the LOCKs section in the General Language Features of M and the description of the LOCK command in the Commands chapter of the Programmer’s Guide.

The two primary functions of the M Lock Utility (LKE) are:

1. SHOW all or specified LOCKs currently active
2. CLEAR all or specified LOCKs currently active

When debugging an M application, you may use LKE to identify a possible deadlock situation, that is, two or more processes have LOCKs and are waiting to add resource names LOCKed by the other(s).

Process 1   Process 2
LOCK A
LOCK B
LOCK +A
LOCK +B


Process 1 has A LOCKed and attempts to LOCK B. Process 2 has B LOCKed and attempts to LOCK A. Because these processes do not release their current LOCKs before adding additional LOCKs, nor do they provide a timeout to detect the problem, they are deadlocked. Neither process can proceed normally. You can use LKE to release one of the LOCKs so both processes may execute. However, because releasing a LOCK may cause the process to violate its design assumptions, terminating one process is generally a safer way to break the deadlock.

Note

When a process leaves M, YottaDB normally releases any LOCKs or ZALLOCATEs held by that process. If a YottaDB process terminates abnormally, or if the system “crashes” while a YottaDB process is active, YottaDB cannot perform normal clean-up. However, as soon as any other process waits several seconds for a LOCK owned by a process that no longer exists, YottaDB automatically clears the “orphaned” LOCK.

### To Invoke and Exit LKE¶

YottaDB installation procedure places the LKE utility package in a directory specified by the environment variable ydb_dist.

LKE requires that the environment variable ydb_gbldir be defined.

Invoke LKE using the following command at the shell prompt. If this does not work, consult your system manager to investigate setup and file access issues.

$ydb_dist/lke LKE>  Note Always run LKE on the node where the lock is held. When LKE is ready to accept commands, it displays the LKE> prompt. To leave LKE, enter the EXIT command at the LKE> prompt. When additional information is entered on the command line after the LKE command, LKE processes the additional information as its command. $ydb_dist/lke show -all


This command displays all current LOCKs and then returns to the shell prompt.

If your LKE argument contains quotes, precede each quote in the argument by a back-slash () or enclose the entire argument in a set of quotes (matching single or double). Apply this convention only for those LKE commands that you run from the shell.

$ydb_dist/lke show -lock="^Account("Name")"$ydb_dist/lke show -lock='^Account("Name")'


Both these commands display the status of LOCK ^Account(“Name”) in the default region.

### To Establish a Global Directory¶

LKE uses the environment variable ydb_gbldir to identify the active global directory. ydb_gbldir should be defined by individual users in their login files.

$ydb_gbldir=prod.gld$ export ydb_gbldir


## LKE Commands and Qualifiers¶

The general format of LKE commands is:

command [-qualifier[=qualifier-value]]


LKE accepts command and qualifier abbreviations. The section describing each command provides the minimal abbreviation that can be used for that command, and the command qualifiers, if any. YottaDB recommends the use of a minimum of four characters for key words in scripts to ensure new keywords do not conflict with older scripts.

### SHOW¶

Use the SHOW command to get status of the LOCK mechanism and the LOCK database. The format of the SHOW command is:

SH[OW] [-qualifier...]


The optional qualifiers are:

-A[LL]
-L[OCK]
-[NO]C[RIT]
-O[UTPUT]="file-name"
-P[ID]=pid
-R[EGION]=region-name
-W[AIT]

• By default, SHOW displays -A[LL].
• The SHOW command reports active LOCKs. Information includes the LOCK resource name and the process identification (PID) of the LOCK owner.
• LKE SHOW displays lock space usage with a message in the form of: “%YDB-I-LOCKSPACEUSE, Estimated free lock space: xxx% of pppp pages.” If the lock space is full, it also displays a LOCKSPACEFULL error.
• A LOCK command that finds no room in LOCK_SPACE to queue a waiting LOCK, does a slow poll waiting for LOCK_SPACE to become available. If LOCK does not acquire the ownership of the named resource with the specified timeout, it returns control to the application with \$TEST=0. If timeout is not specified, the LOCK command continues to do a slow poll till the space becomes available.
• LOCK commands that find no available lock space send a LOCKSPACEFULL message to the operator log. To prevent flooding the operator log, YottaDB suppresses further such messages until the lock space usage drops below 75% full.
• The results of a SHOW may be immediately “outdated” by M LOCK activity.
• If the LOCK is owned by a GT.CM server on behalf of a client YottaDB process, then LKE SHOW displays the client NODENAME (limited to the first 15 characters) and clientPID. The client PID (CLNTPID) is a decimal value in UNIX

Note

GT.CM is an RPC-like way of remotely accessing a YottaDB database.

#### -ALL¶

Specifies all current LOCKs.

• -ALL displays all current LOCKs in all regions and information about the state of processes owning these LOCKs.
• The -ALL qualifier is compatible with all other qualifiers.
• When -ALL is combined with -PID or -REGION, the most restrictive qualifier prevails.
• SHOW -ALL and -WAIT displays both -ALL and -WAIT information.

#### -L[OCK]=resource_name¶

resource_name specifies a single lock.

• The resource_name is enclosed in double quotation marks (“” “”). Because M resource names are formatted the same as global nodes with punctuation characters, in this context they are usually enclosed in sets of double quotation marks with string subscripts enclosed in sets of two double quotations.
• When used with the CLEAR command, the LOCK qualifier removes the specified lock.
• When used with the SHOW command, the LOCK qualifier provides a precise way to examine the specified lock and any descendant LOCKed resources.

#### -[NO]C[RIT]¶

Allows the SHOW command to work even if another process is holding a critical section.

• By default, LKE operates in CRIT mode and ensures a consistent view of LOCKs by using the database critical section(s).
• Use NOCRIT with SHOW only when normal operation is unsuccessful, as NOCRIT may cause LKE to report incomplete or inconsistent information.

#### -O[UTPUT]=”file-name”¶

Directs the reporting of all specified LOCKs to a file.

• If you specify an existing file, LKE creates a new version and overwrites that file.
• The -OUTPUT qualifier is compatible with all other qualifiers.
• By default, the SHOW command sends output messages to stdout.

#### -P[ID]=pid¶

Specifies the process identification number that holds a LOCK on a resource name.

• LKE interprets pid as a decimal number.
• PID displays all LOCKs owned by the specified process identification number.
• The -PID qualifier is compatible with all other qualifiers; the most restrictive of the qualifiers prevails.
• By default, SHOW displays the LOCKs for all PIDs.

#### -R[EGION]=region-name¶

Specifies the region that holds the locked resource names.

• The REGION qualifier displays LOCKs of that specified region.
• The REGION qualifier is compatible with all other qualifiers; the most restrictive of the qualifiers prevails.
• By default, SHOW displays the LOCKs for all regions.

#### -W[AIT]¶

Displays the LOCK resource name and the process state information of all processes waiting for the LOCK to be granted.

• SHOW -WAIT does not display the owner of the LOCK.
• SHOW -ALL -WAIT displays both -ALL and -WAIT information.
• When a process abandons a “wait” request, that request may continue to appear in LKE SHOW -WAIT displays. This appearance is harmless, and is automatically eliminated if the YottaDB lock management requires the space which it occupies.

Use the following procedure to display all LOCKs active in the database(s) defined by the current global directory.

LKE> SHOW -ALL -WAIT


This produces an output like the following:

No locks were found in DEFAULT
AREG
^a Owned by PID=2080 which is an existing process
BREG
^b(2) Owned by PID= 2089 which is a nonexistent process
No locks were found in CREG


Example:

LKE>SHOW -ALL


This command displays all LOCKs mapped to all regions of the current global directory. It produces an output like the following:

DEFAULT
^A Owned by PID= 5052 which is an existing process
^B Owned by PID= 5052 which is an existing process
%YDB-I-LOCKSPACEUSE, Estimated free lock space: 99% of 40 pages


Example:

LKE>show -lock="^a"(""b"")"


This command shows lock ^a(“b”) in the default region.

Example:

LKE>SHOW -CRIT


This command displays all the applicable locks held by a process that is holding a critical section.

Example:

LKE>show -all -output="abc.lk"


This command create a new file called abc.lk that contains the output of the SHOW -ALL command.

Example

LKE>show -pid=4109


This command displays all locks held by process with PID 4109 and the total lock space usage.

Example:

LKE>show -region=DEFAULT -lock=""^A""


This command displays the lock on ^A in the region DEFAULT. It produces an output like the following:

DEFAULT
^A Owned by PID= 5052 which is an existing process
%YDB-I-LOCKSPACEUSE, Estimated free lock space: 99% of 40 pages


### EXIT¶

The EXIT command ends an LKE session. The format of the EXIT command is:

E[XIT]


### HELP¶

The HELP command explains LKE commands. The format of the HELP command is:

H[ELP] [options...]


Enter the LKE command for which you want information at the Topic prompt(s) and then press RETURN or CTRL-Z to return to the LKE prompt.

Example:

LKE> HELP SHOW


This command displays help for the SHOW command.

### SPAWN¶

Use the SPAWN command to create a sub-process for access to the shell without terminating the current LKE environment. Use the SPAWN command to suspend a session and issue shell commands such as ls or printenv.

The format of the SPAWN command is:

SP[AWN]


The SPAWN command has no qualifiers.

Example:

LKE>spawn


This command creates a sub-process for access to the current shell without terminating the current LKE environment. Type exit to return to LKE.

## Summary¶

C[LEAR] -ALL, -L[OCK], -[NO]EXACT, -[NO]I[NTERACTIVE], -O[UTPUT]=file-name, -P[ID]=pid, -R[EGION]=name Use CLEAR with care and planning.
E[XIT] None -
H[ELP] [option] -
SH[OW] -ALL, -L[OCK], -[NO]CRIT, -N[OINTERACTIVE], -O[UTPUT]=file-name, -P[ID]=pid, -R[EGION]=name, -W[AIT] -
SP[AWN] none shellcommand

## LKE Exercises¶

When using M Locks, you must use a well designed and defined locking protocol. Your locking protocol must specify guidelines for acquiring LOCKs, selecting and using timeout, releasing M Locks, defining a lock strategy according to the given situation, identifying potential deadlock situations, and providing ways to avoid or recover from them. This section contains two exercises. The first exercise reinforces the concepts of YottaDB LOCKs previously explained in this chapter. The second exercise describes a deadlock situation and demonstrates how one can use LKE to identify and resolve it.

### Exercise 1: Preventing concurrent updates using M Locks¶

Consider a situation when two users (Mary and Ken) have to exclusively update a global variable ^ABC.

Note

Transaction Processing may offer a more efficient and more easily managed solution to the issue of potentially conflicting updates. For more information, see the General Language Features of M chapter of the Programmer’s Guide.

At Mary’s prompt, execute the following commands:

YDB>lock +^ABC


This command places a YottaDB LOCK on “^ABC ” (not the global variable^ABC). Note: LOCKs without the +/- always release all LOCKs held by the process, so they implicitly avoid dead locks. With LOCK +, a protocol must accumulate LOCKs in the same order (to avoid deadlocks).

Then execute the following command to display the status of the LOCK database.

YDB>zsystem "lke show -all"


This command produces an output like the following:

DEFAULT ^ABC Owned by PID=3657 which is an existing process


Now, without releasing lock^ABC, execute the following commands at Ken’s prompt.

YDB>lock +^ABC


This command waits for the lock on resource “^ABC” to be released. Note that the LOCK command does not block global variable ^ABC in any way. This command queues the request for locking resource “^ABC” in the LOCK database. Note that you can still modify the value of global variable ^ABC even if it is locked by Mary.

Now, at Mary’s prompt, execute the following command:

YDB>zsystem "LKE -show -all -wait"


This command produces output like the following:

DEFAULT ^ABC Owned by PID=3657 which is an existing process
Request PID=3685 which is an existing process


This output shows that the process belonging to Mary with PID 3657 currently owns the lock for global variable ^ABC and Ken’s PID has requested the ownership of that lock. You can use this mechanism to create application logic that adhere to your concurrent access protocols.

### Exercise 2: Rectifying a deadlock situation¶

Now, consider another situation where both these users (Mary and Ken) have to update two text files. While an update is in progress, a YottaDB LOCK should prevent the other user from LOCKing that file. In some cases, a deadlock occurs when both users cannot move forward because they do not release their current LOCKs before adding additional LOCKs.

A deadlock situation can occur in the following situation:

Mary           Ken
LOCK +file_1   LOCK +file_2
LOCK +file_2   LOCK +file_1


Here both the users are deadlocked and neither can move forward. Note that a deadlock situation does not actually block the underlying resource.

Let us now create this situation.

At Mary’s prompt, execute the following commands:

YDB>set file1="file_1.txt"
YDB>lock +file1
YDB>open file1:APPEND
YDB>use file1
YDB>write "Mary",!
YDB>close file1


Note that Mary has not released the LOCK on resource “file1”.

At Ken’s prompt, execute the following commands:

YDB> set file2="file_2.txt"
YDB> lock +file2
YDB> open file2:APPEND
YDB> use file2
YDB>write "Ken",!
YDB>close file2


Note that Ken has not released the LOCK on resource “file2”.

Now, at Mary’s prompt, execute the following commands.

YDB>set file2="file_2.txt"
YDB>lock +file2


The latter command attempts to acquire a lock on resource file2 that is already locked by Ken. Therefore, this results in a deadlock situation. Repeat the same process for Ken and attempt to lock resource file1.

Execute the following command at LKE prompt to view this deadlock situation.

LKE>show -all -wait
file1 Owned by PID=2080 which is an existing process
Request PID=2089 which is an existing process
file2 Owned by PID=2089 which is an existing process
Request PID=2080 which is an existing process


This shows a deadlock situation where neither user can proceed because it is waiting for the other user to release the lock. You can resolve this situation by clearing the locks using the LKE CLEAR -PID command.

Note

Avoid using the LKE CLEAR command to clear a deadlock in a production environment, as it may lead to unpredictable application behavior. Always use the MUPIP STOP command to clear a deadlock situation in your production environment. However, in a debugging environment, you can use LKE to debug LOCKs, analyze the status of the LOCK database and even experiment with LKE CLEAR.