Joep,
I am impressed that you went ahead and not only looked at Patrik's
code, but actually compiled and ran it. (I only took a brief look at
the code.) Kudos to you for your willingness to be a full participant
in this learning/teaching experience.
Anyway, I commented the UNLOCKS out and saw the (or better: a) problem: if I select 2, just press enter without changing anything the record is not updated and not unlocked, so there’s your record lock.
Indeed. Before you wrote your response, I was going to mention that I
got an uneasy feeling when Patrik said this:
On Wed, Feb 23, 2022 at 9:57 AM Patrik Schindler <poc@xxxxxxxxxx> wrote:
I signed on twice, started the program, and put up the edit screen on one record. When trying to do the same with the second signon, with the same record, I got a "record already locked" error. That's when I added the UNLOCKs.
I noticed that Patrik didn't say anything about whether he did an
update in the first session before attempting to access the same
record in the second session. So I was going to press him a little
more on that.
Basic problem is that you make no distinction in your between database fields and screen fields. And thus in subroutine CHGREC you do a CHAIN, then an EXFMT, then some checks and if all the checks are OK you do the update. But if not all checks are OK, you leave. And so you leave unfinished business, the locked record.
I fully agree with you that making a clear distinction between
database fields and screen fields is a helpful practice. Yeah, it
costs more lines of code, but ultimately it reduces the mental strain
of keeping track of potential side-effects.
That being said, if we want to focus very precisely on where Patrik
went wrong regarding updates and locks, there is actually this
illustrative example in the ILE RPG Reference. Conveniently, UNLOCK
and UPDATE are alphabetically adjacent, and this is sandwiched between
them:
*...1....+....2....+....3....+....4....+....5....+....6....+....7...+....
FFilename++IPEASFRlen+LKlen+AIDevice+.Keywords++++++++++++++++++++++++++++
*
FUPDATA UF E DISK
*
CL0N01Factor1+++++++Opcode(E)+Factor2+++++++Result++++++++Len++D+HiLoEq....
*
* Assume that the file UPDATA contains record format vendor.
* A record is read from UPDATA. Since the file is an update
* file, the record is locked. *IN50 is set somewhere else in
* the program to control whether an UPDATE should take place.
* otherwise the record is unlocked using the UNLOCK operation.
* Note that factor 2 of the UNLOCK operation is the file name,
* UPDATA, not the record format, VENDOR
*
C READ VENDOR 12
C :
C *IN50 IFEQ *ON
C UPDATE VENDOR
C ELSE
C UNLOCK UPDATA 99
C ENDIF
Yeah, it's positional code and the whitespace is all screwed up in my
pasting of it. But it's still very clear nonetheless. The only things
that need explaining are the 12 at the end of the READ statement
(*IN12 is set on if EOF is reached) and the 99 at the end of the
UNLOCK statement (*IN99 is set on if there's an error).
John Y.
As an Amazon Associate we earn from qualifying purchases.