Kbase P96242: Error 396 is not generated when multiple buffer access the same record
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  4/7/2005 |
|
Status: Verified
SYMPTOM(s):
Error 396 is not generated where seemingly expected.
** <filename> record has NO-LOCK status, update to field not allowed. (396)
FIND NO-LOCK locks the record with an EXCLUSIVE-LOCK, if this record is held by another buffer with an EXCLUSIVE-LOCK
Multiple buffers access the same record
A situation like this occur:
DEFINE BUFFER bufOrder FOR Order.
FIND FIRST order EXCLUSIVE.
FIND FIRST bufOrder NO-LOCK.
FIND FIRST order NO-LOCK.
/*at this point the lock is still exclusive and so 396 is not raised*/
order.instructions = order.instructions + 'x'.
CAUSE:
This is expected behavior. Each buffer has its own memory space, but the record they point to is always the same.
In this case:
FIND FIRST order EXCLUSIVE.
/*find first bufOrder no-lock. */
FIND FIRST order NO-LOCK.
There is only one buffer, and when we get to the find no-lock, 4GL checks that there is no other buffer that is pointing to that record, so we disconnect the record from the buffer (at this point if there was any changed made to the record, we would write them out), and reconnect it with NO-LOCK.
Now, in this case:
FIND FIRST order EXCLUSIVE.
FIND FIRST bufOrder NO-LOCK.
FIND FIRST order NO-LOCK.
There are two buffers. When 4GL gets to the "find bufOrder" statement, it checks a that there is another buffer pointing to the same record, and since it has EXCLUSIVE-LOCK, it leaves it, and points the buffer to that same record. When we get to the 3rd statement, since there is another buffer pointing to that the same record, we can't release the record, and again, since it has EXCLUSIVE-LOCK, it leaves it and so it end up with an exclusive lock.
FIX:
In order to prevent this kind of confusion, we recommend that you do EXCLUSIVE locking in a do transaction block, as close to the place where update/create/delete will occur as possible. We have the FIND-CURRENT statement to allow upgrading of a lock (not downgrading) so that you do not have to release the record to change the lock status.
Here is the modification of the example for illustration:
DEFINE BUFFER bufOrder FOR order.
FIND FIRST buforder NO-LOCK.
FIND FIRST order NO-LOCK.
DO TRANS.
IF AVAIL order THEN FIND CURRENT order EXCLUSIVE-LOCK.
ELSE FIND FIRST order EXCLUSIVE-LOCK.
order.instructions = order.instructions + 'x'.
END.