Best Practice using IO$STS with multiple IO Operations

This Q&A forum allows users to post and respond to "How Do I Do ....." questions. Please do not use to report (suspected) errors - you must use your regional help desk for this. The information contained in this forum has not been validated by LANSA and, as such, LANSA cannot guarantee the accuracy of the information.
Post Reply
jyoung
Posts: 694
Joined: Thu Jan 21, 2016 6:43 am
Location: Oklahoma City, OK USA

Best Practice using IO$STS with multiple IO Operations

Post by jyoung »

I am wondering what the best practice is in terms of using IO$STS when you have multiple IO operations.

For example, on the client (VLF-ONE) after the call to the save server module, I do something like this

Code: Select all

evtroutine handling(#save.Completed)
* Get server messages and issue them in the Framework
#COM_SELF.HighlightProblems( #PanelFields )

#avFrameworkManager.avRecordTraceAValue component(#COM_OWNER) event("Save Completed") avalue(#Status)

if (#Status = OK)
* Message indicating successful update
#avFrameworkManager.avIssueMessage text('Update was successful') requester(#COM_OWNER)
#SaveButton.Enabled := False
endif

if (#Status = VE)
#avFrameworkManager.avIssueMessage text('Update failed due to data validation errors') requester(#COM_OWNER)
endif

#COM_OWNER.avGotoFreeState

endroutine
The save server routine has potentially 3 write based IO operations and 3 read based IO ops (Why is beyond the scope of this topic, but suffice to say I don't think it is good database design, but there is nothing I can do about it).

Since I only return one IO$STS it is always the status of the last write (do read ops affect it?) operation.

In this specific case, my last operation I am doing a check_for and if the if_status is *EQUALKEY then I need to do an update.
Here is a snippet of the server side code.

Code: Select all

* fetch all fields for key and level 1 (was 0 before the above update)
#CMELVL := 1
fetch fields(#BF1103Fields) from_file(BF1103) with_key(#CMOFID #CMOFD #CMOCN #CMOD #CMELVL)

* get the entry from the save list, this will update the fields that we just loaded with their new values
get_entry number(1) from_list(#SaveList)

* reset the level 0 fields
#CMELVL := 0
#vEffectiveDate2 := #STD_DATEX.Now
#vNonEffectiveDate := *SQLNULL
#vLastUpdatedDate := #STD_DATEX.Now
#vLastUpdatedTime := *TIME
#CMULU := #Persistent_ApplicationString1.AsNativeString
#CMAH := 'A'

* finally do the insert
insert fields(#BF1103Fields) to_file(BF1103)

* one last thing to do, if the key exists in BF1147, update the ESI Rating
#CPOFID := #LCOFID
#CPOFD := #LCOFD
#CPOCN := #LCOCN
#CPOD := #LCOD

check_for in_file(BF1147) with_key(#CPOFID #CPOFD #CPOCN #CPOD)
if_status is(*EQUALKEY)
#CPCRE := #CMCRE
update fields(#CPCRE) in_file(BF1147) with_key(#CPOFID #CPOFD #CPOCN #CPOD)
endif
Works well enough, however the IO$STS is now 'NE' (which is to be expected) and that throws off the client status check so I don't get the "Update Successful" message.

So I am curious what others are doing with IO$STS when you have multiple IO operations.

Do you check it on the client or do you ignore it?
Do you maintain a separate status on the server and only flip it if an IO op goes wrong which means checking every IO op?

I am thinking that I should check every IO op and if_status is_not *OKAY then set a return status (aka return code separate of IO$STS) to ER and issue a message. The client can then pick up that status and receive the messages from the server.
MarkD
Posts: 692
Joined: Wed Dec 02, 2015 9:56 am

Re: Best Practice using IO$STS with multiple IO Operations

Post by MarkD »

I don’t know about best practice, but where server routines have multiple operations that can fail prefer to rationalize the overall result into a simple Boolean. For example:

Code: Select all

Srvroutine Name(NewTest)
Field_Map For(*Output) Field(#ServerRoutineSuccess)

Define Field(#ServerRoutineSuccess) Type(*BOOLEAN)
Define_Com Class(#io$STS) Name(#InsertIOStatus)
Define_Com Class(#io$STS) Name(#UpdateIOStatus)

Insert Fields(#xEmployeeAge) To_File(xEmployee) Io_Status(#InsertIOStatus)

Update Fields(#xEmployeeAge) In_File(xEmployee) Io_Status(#UpdateIOStatus)

#ServerRoutineSuccess := ((#InsertIOStatus = OK) And (#UpdateIOStatus = OK))

Return
Endroutine
I find that the problem with returning IO$STS (as a field) is that if you execute other subroutines or methods within the same module they can change it without you noticing because it’s globally scoped. Here #InsertIOStatus and #UpdateIOStatus are scoped within my SrvRoutine and cannot get zapped.
atostaine
Posts: 696
Joined: Wed Jan 20, 2016 7:38 am

Re: Best Practice using IO$STS with multiple IO Operations

Post by atostaine »

Depending on whether you want to consider all of the transactions as a logical transaction, you can get out as soon as an error happens. In that case I set the status to false at the beginning.

Code: Select all

Srvroutine Name(NewTest)
Field_Map For(*Output) Field(#ServerRoutineSuccess)
Define Field(#ServerRoutineSuccess) Type(*BOOLEAN)

#serverRoutineSuccess := False

Insert Fields(#xEmployeeAge) To_File(xEmployee) Io_Status(#InsertIOStatus)
if_status is_not(*okay)
return
endIf

Update Fields(#xEmployeeAge) In_File(xEmployee) Io_Status(#UpdateIOStatus)
if_status is_not(*okay)
return
endIf

#serverRoutineSuccess := True

Endroutine
Art Tostaine
Post Reply