Try OpenEdge Now
skip to main content
ABL Essentials
Handling Data and Locking Records : Record locking in ABL : Record locking examples : Using the NO-WAIT Option with the AVAILABLE and LOCKED functions
 
Using the NO-WAIT Option with the AVAILABLE and LOCKED functions
Just for the record, there are options you can use to make other choices in your procedures in the case of lock contention. If for some reason you do not want your procedure to wait for the release of a lock, you can include the NO-WAIT keyword on the FIND statement. Normally, you should also include the NO-ERROR keyword on the statement to avoid the default "record is locked" message from the AVM. Following the statement, you can use one of two built-in functions to test whether your procedure got the record it wanted. The following variant of the procedure for  User 2 uses the AVAILABLE keyword to test for the record, and is saved as h-findCustUser2.p. Because the NO-WAIT option causes the FIND statement in this procedure to fail and execution to continue if the record is already locked by another session, the record is not in the buffer, and the AVAILABLE(Customer) function returns FALSE:
/* h-findCustUser2.p */
FIND Customer 1 EXCLUSIVE-LOCK NO-WAIT NO-ERROR.
IF NOT AVAILABLE Customer THEN
  MESSAGE "That Customer isn't available for update." VIEW-AS ALERT-BOX.
ELSE DO:
  DISPLAY
    "User 2:" Customer.CustNum FORMAT "ZZZ9" Customer.Name FORMAT "X(12)"
    Customer.CreditLimit Customer.Balance
    WITH FRAME CustFrame.

  ON "LEAVE":U OF Customer.CreditLimit IN FRAME CustFrame DO:
    ASSIGN Customer.CreditLimit.
  END.

  ENABLE Customer.CreditLimit Customer.Balance WITH FRAME CustFrame.
  WAIT-FOR CLOSE OF THIS-PROCEDURE.
END.
If you run h-findCustUser1.p and h-findCustUser2.p, in that order from different sessions, the second session displays the MESSAGE statement, as shown in the following figure.
Figure 47. EXCLUSIVE-LOCK message
This message occurs because h-findCustUser1.p has read the record with a SHARE-LOCK and h-findCustUser2.p has attempted to read it with an EXCLUSIVE-LOCK, which fails.
Alternatively, if you want to distinguish between the case where the record is not available because it has been locked by another user and the case where the record wasn't found because the selection was invalid in some way, you can use the LOCKED function:
FIND Customer 1 EXCLUSIVE-LOCK NO-WAIT NO-ERROR.
IF LOCKED Customer THEN
  MESSAGE "That Customer isn't available for update." VIEW-AS ALERT-BOX.
ELSE IF NOT AVAILABLE Customer THEN
  MESSAGE "That Customer was not found." VIEW-AS ALERT-BOX.
...
Once again, because SHARE-LOCKS are of very limited use in application procedures that are distributed or might be distributed between sessions, it is good practice to bypass this method of reading records altogether and always read records with an EXCLUSIVE-LOCK if you know that your procedure updates them immediately.
Also, because the NO-WAIT option is designed for possible record contention in an environment where a user might hold a record lock for a long time while viewing the record on screen or going out for lunch, this option is not normally needed in an application where all database access is confined to the server, where there should be no user interaction with locked records. If you code your application properly to make sure that record locks are not held unnecessarily, then lock contention should almost never be an issue.