Reading _Lock hangs????

yanfug

New Member
Hi to everyone!

I have a little problem when reading the _Locks table.

I have an window that display the users list (taht hold locks) in one browser, when selecting a user it display the _Lock table for that user.
Everything is loaded in temp-table. But sometimes, it look like Progress hang while doing the Find first _Lock...!

And then, once i have the _Lock record with the RECID, i want to display the record itself in another browser. This part is ok when i can get the _Lock browser filled.

someone have any ideas why it look like it hang doing the find first.
Is it because the process that the user is running has more than 512 locks ????:rolleyes:

Because when i try it, the process that was generating the locks was really big, locking a lot of records and i know that _Lock don't have any index on RECID field.

Thanks a lot!:)

Here's the procedure code:




Procedure pLoadLockInfo
DEF INPUT PARAMETER pUserLockID AS INT NO-UNDO.​
/****************************************************************************/​
DEF VAR i# AS INT NO-UNDO.​
CLOSE QUERY brwLock.​
fStatus:SCREEN-VALUE IN FRAME frmBottom = "Deleting temp table.".​
EMPTY TEMP-TABLE ttLock.​
fStatus:SCREEN-VALUE = "Loading locks information of the selected USER... Please wait...".​
SESSION:SET-WAIT-STATE("GENERAL").​
FIND FIRST _UserLock WHERE _UserLock._UserLock-Id = pUserLockID NO-LOCK NO-ERROR.​
IF AVAIL _UserLock THEN DO:
MESSAGE "begin loop" VIEW-AS ALERT-BOX. /*Yanick*/​
ExtLoop:​
DO i# = 1 TO 512:
IF (_UserLock._UserLock-Chain[i#] <> ? OR _UserLock._UserLock-Recid[i#] <> ?) AND​
(_UserLock._UserLock-Type[i#] <> ? OR _UserLock._UserLock-Flags[i#] <> ?) THEN DO:
/* link to find lock information on the record itself */​
FIND FIRST _Lock WHERE _Lock._Lock-ID <> ? AND _Lock._Lock-RecID = _UserLock._UserLock-RecID[i#] AND _Lock._Lock-chain = _UserLock._UserLock-Chain[i#] NO-LOCK NO-WAIT.​
IF AVAIL _Lock THEN DO:​
/* look for table name */​
FIND FIRST _File WHERE _File._File-number = _Lock._Lock-table NO-LOCK NO-WAIT.​
IF AVAIL _File THEN DO:
CREATE ttLock.​
ASSIGN ttLock.ttLockID = _Lock._Lock-Id​
ttLock.ttRecid = _Lock._Lock-Recid​
ttLock.ttChain = _Lock._Lock-chain​
ttLock.ttTableName = _File._File-name​
ttLock.ttLockFlags = _Lock._Lock-flags​
ttLock.ttLockType = _Lock._Lock-type.​
END. /* avail _File */



END. /* avail _Lock */



END.



END. /* do i# = 1 to 512 */



END. /* if avail _UserLock */

fStatus:SCREEN-VALUE = "Opening query.".
OPEN QUERY brwLock FOR EACH ttLock NO-LOCK.
fStatus:SCREEN-VALUE = "".
SESSION:SET-WAIT-STATE("").



END PROCEDURE.
 
Reading _Lock is especially tricky ;)

There are no indexes on VSTs and they mostly mirror C data structures rather than actual database tables. Many VSTs (including _Lock) should be read in a manner that excludes key values of ? as these indicate unused entries in fixed arrays inside the db engine.

To read _Lock relatively efficiently use code similar to this:

Code:
for each _lock no-lock while _lock-usr <> ?:
  /* do something with _lock records... */
end.

Note the unusual usage of WHILE rather than WHERE in the FOR EACH. This is an important detail for the _lock VST.

_Lock is also problematic because the number of entries in use can change very rapidly. Your code may seem very well behaved under normal conditions but under the circumstances when people sometimes get interested in locks (i.e. when there are a great many of them) it all goes to pieces... Reading _lock can be painfully slow when there are lots of entries. Even with the code above (which is as good as it gets...)

For more insights into programming VSTs check out:

ProTop
 
Hi Tom!

So if understand you correctly, it is easier to just scan the hole _Lock table with a for each while... rather than doing a find on the _UserLock first, then doing finds on the Recid and chain extent that are not equal to "?"

So there is no way of using affactively that _Lock table when you really need it (great amount of locks). :(

I'll take a look at the ProTop tool if that can help me.

By the way, is there any problem with code or it is really the amount of lock and slow find that are problematic?
 
Thanks for the insight!
it work fine now!

instead of reading the _UserLock and _Lock, i only get the _Lock table!;p
 
Hi Tom!

So if understand you correctly, it is easier to just scan the hole _Lock table with a for each while...

You don't scan the whole table when you use WHILE. Only the subset of it that actually has locks.

By the way, is there any problem with code or it is really the amount of lock and slow find that are problematic?

I didn't look all that hard at the code but anything that deals with _lock has to account for the problem of large numbers of locks. Offhand the code looks like it probably retrieves the records that you are interested in but it uses multiple layers of indirection to do it and several queries that will each be painfully slow if run against a database with a large -L setting.
 
Back
Top