Kbase 5928: Record not released after buffer scope ends
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  4/12/2010 |
|
Status: Verified
SYMPTOM(s):
Share lock not released after BUFFER scope (not record scope) ends.
Exclusive lock downgraded to share lock after transaction end.
Bleeding record locks with Progress versions prior to 7.3B.
FACT(s) (Environment):
All Supported Operating Systems
Progress/OpenEdge Product Family
CAUSE:
When dealing with multiple buffers for the same record, the buffer scope is not the same as the record scope and therefore, locks may not be released when you think they would be. Here's a code example:
def var crec as recid no-undo.
def buffer xcustomer for customer.
for each customer no-lock:
crec = recid(customer).
message "recid=" crec.
message "city=" customer.city.
pause. /* NO-LOCK */
do for xcustomer transaction:
find xcustomer where
recid(xcustomer) eq crec exclusive-lock.
xcustomer.city = string(recid(xcustomer)).
message "xcity=" xcustomer.city.
pause. /* EXCLUSIVE-LOCK */
release xcustomer.
message "xcustomer released".
pause. /* EXCLUSIVE-LOCK */
end.
message "outside the DO TRANSACTION".
pause. /* either NO-LOCK (or SHARE-LOCK with "-brl") */
release customer.
message "customer released".
pause. /* NO-LOCK */
end.
note: Pauses are put in program so that you could run promon while
this is running and see the difference in locks.
Basically, since the xcustomer buffer scope and transaction end at the same time, you would expect that the xcustomer record would be downgraded to no-lock, but it is not. Unless you have BOTH the release on the customer and the release on the xcustomer buffers, the record would remain share locked until the end of the for each loop iteration. Here is the explanation from development:
When the transaction ends, the record is downgraded to SHARE lock, and that is what they expect -- they do not consider this a bug -- it is done by design. Here's how it works: For each active buffer, I have a CI (basically a cursor for each buffer).
For the RECORD, I have an ICB (basically an index cursor buffer, or whatever). The locking occurs at the ICB level, not at the CI level. Therefore, although I had a no-lock on the customer CI, when the xcustomer CI asked for the exclusive-lock, the ICB upgraded the record to exclusive-lock. When the transaction ended, the ICB downgrades the record to share-lock.
When the record scope ends, the ICB breaks the connection with the xcustomer CI, but since the ICB for the record is still active, it leaves the record SHARE locked. If this behavior is changed, there would have to have some sort of backward compatibility for those who are used to the behavior the way it is.
FIX:
This behavior has been modified with 7.3B and later releases. There is a new startup option, -brl, which can be used to obtain the earlier behavior described above.