9.130 LOCK_OBJECT
Note: Built-In Function Rules Usage Options
Attempts to place a lock on the specified User Object and returns an error if unsuccessful.
Arguments
|
Return Values
|
This Built-In Function allows the locking of User Objects. Once a User Object is locked any other attempt to lock that User Object results in an error condition and a Return Code of "ER" being returned. The exception to this is when an attempt is made to lock a User Object that is already locked by the current job. When this occurs the lock request is ignored and a Return Code of "IG" is return.
A User Object need not be a physical object on the system, it can be ANYTHING you require. User Objects are more conceptual than physical, and can represent a particular customer number or an entire LANSA partition. The only limitation is your imagination.
The word 'ALL' is reserved by the system and must not be used as an Object Identifier.
This method of locking is controlled by your application, it is NOT controlled by the operating system. Therefore system commands cannot be used to investigate the lock status of User Objects.
Some of the advantages of using LOCK_OBJECT over the LOCK(*YES) parameter of I/O commands include:
-
You can devise a proper locking "protocol". For example LOCK_OBJECT ('ORDER' #ORDNUM is the "protocol" to lock the order identified by #ORDNUM. By using a protocol you do not have to worry/think about how your application will lock the order header, the associated line items and line items charges across 3 differing database files.
-
You do not introduce inter or intra operating system dependencies. For example IBM i will lock multiple records in the same file when full before/after image commitment control is used, but it won't in other situations.
-
You can lock multiple objects easily.
-
You can "invent" objects to handle any type of situation, you are no longer dependent on file "records".
-
You can have "permanent" locks lasting days, months or years.
The Object Type argument is used to organize the object identifiers into groups of common attributes. For example an Object Type could be used to group customers, orders or printer names.
The Object Identifiers then specify a single object.
Current User Object locks are stored in the file DC@FOL. There exists one record in DC@FOL for each User Object lock present. The layout of DC@FOL is:
|
The Logical Views present and their keys are:-
|
Be aware that backup and recovery of this file is a user responsibility. Any locks that are present when a backup is done will be reinstated when that backup is restored.
Should LANSA or a function crash due to error any locks that are present will be removed. But if the system were to crash, LANSA will be unable to remove the locks. Locks remaining due to a system crash become the responsibility of the user to remove.
The User Object locks are either unlocked automatically or when the UNLOCK_OBJECT Built-In Function is used.
The Locking Level used on the LOCK_OBJECT determines when the User Object would be automatically unlocked.
-
A Locking Level of 'FUNC' indicates that the lock will be automatically removed at the end of the function that created it.
-
A Locking Level of 'JOB' indicates that the lock will be automatically removed when you exit JOB, for example, a form or process.
-
If you need a User Object lock to exist after you have exited LANSA then a Locking Level of 'PERM' is required. This is a permanent User Object lock that exists until explicitly removed with UNLOCK_OBJECT.
Examples
By using the four User Object Identifiers to build a structure to your object locking it is possible to do generic key unlocking.
DEFINE FIELD(#RETURN) TYPE(*CHAR) LENGTH(2)
DEFINE FIELD(#STATE) TYPE(*CHAR) LENGTH(3)
DEFINE FIELD(#CUSTNO) TYPE(*CHAR) LENGTH(6)
********** Lock Customers to be Updated
USE BUILTIN(LOCK_OBJECT)
WITH_ARGS('CUSTOMER' #STATE #CUSTNO '' '' 'FUNC') TO_GET(#RETURN)
********** Unlock ALL Customers for the STATE
USE BUILTIN(UNLOCK_OBJECT) WITH_ARGS('CUSTOMER' #STATE 'ALL' '' '' 'FUNC')
TO_GET(#RETURN)
In this example a number of User Objects relating to customers had locks placed on them. All the locked 'customers' belong to the same 'state'. When the update process is complete the locks can be removed. Rather than remove each individual lock for each customer, all the locks for a state can be removed generically by specifying 'ALL' on the second Object Identifier.
User Object locking can also be used to limit the number of concurrent users a function can have. For example, if you wish to impose a three user limit on your order entry function, then create three User Objects, each relating to a user. Then at the top of your order entry function attempt to obtain a lock on one of the User Objects. If none are available then you could display a message stating this, and exit the function. If a lock is granted then allow access to the function. Remember to unlock the User Object when exiting the function, or specify 'FUNC' as the Locking Level so the lock will be automatically removed when the function is finished. Use the following example as a guide.
DEFINE FIELD(#RETURN) TYPE(*CHAR) LENGTH(2)
********** Attempt lock on 1st instance
USE BUILTIN(LOCK_OBJECT)
WITH_ARGS('ORDER_ENTRY' 'ORDER#1' '' '' '' 'FUNC') TO_GET(#RETURN)
IF COND('#RETURN *EQ ER')
********** Attempt lock on 2nd instance
USE BUILTIN(LOCK_OBJECT)
WITH_ARGS('ORDER_ENTRY' 'ORDER#2' '' '' '' 'FUNC') TO_GET(#RETURN)
IF COND('#RETURN *EQ ER')
********** Attempt lock on 3rd instance
USE BUILTIN(LOCK_OBJECT)
WITH_ARGS('ORDER_ENTRY' 'ORDER#3' '' '' '' 'FUNC') TO_GET(#RETURN)
IF COND('#RETURN *EQ ER')
********** Cannot obtain any locks
MESSAGE MSGTXT('No Order Entry sessions are Available')
RETURN
ENDIF
ENDIF
ENDIF
********** Protected processing
********** Unlock ALL Order Entry locks for this Function
USE BUILTIN(UNLOCK_OBJECT) WITH_ARGS('ORDER_ENTRY' 'ALL' '' '' '' 'FUNC') TO_GET(#RETURN)