We use this process of putting an IO layer in front of a file.
1. We try to put a wrapper in front of all files, we generally create
two wrappers, one for write, update, delete modules and one for read,
reade, setll, chain, etc. Most applications do not need to lock the
file for update and so this eliminates that problem. We also put the
extfile/extmbr on the file and include open/close modules so we can use
the same methods for accessing different members of a file or the same
file in a user or history library.
2. We pass a parameter for the error condition back with the request.
CALLP MCxxxxCH(key:recordpointer:FOUNDERR), CALLP
MCxxxxRE(key:recordpointer:EOFERR), CALLP
MCxxxxSL(key:POSITIONERR:EQUALERR), CALLP
MCxxxxRD(recordpointer:EOFERR), CALLP
MCxxxxUP(previousrecordpointer:newrecordpointer:CHANGEDERR:UPDATEERR),
etc. In this example MC is a library designation, xxxx is a file
designation and last two letters are operation:
CH - Chain, RE - Reade, RP - read previous, PE - read previous equal, UP
- update, WR - write, DL - delete, etc.
3. We use externally described data structures in the module for the
file being processed and return/pass the pointer to that data structure.
4. We use the same construct only instead of DOW NOT %EOF we use DOW
EOFERR = *OFF.
5. Since we use a separate wrapper for read vs update most programs will
never lock a record. The only time we lock a record is during the
update process and we code the CHAIN for lock in that process.
6. Most of our write methods receive the primary key as a parameter and
return the pointer of the record created and an add error flag. Outside
of the key and a maintenance timestamp the intial record is set to
blanks/zeros. The requesting program will then update fields in the
data structure returned and call the update method to personalize the
record. This allows us to only have to make sure new fields get
initialized in one place. Programs that don't care about the new field
just need recompiled due to the change in the record format, the only
programs needing changed are ones that use the new field. This does add
overhead to the write process because for every new record you have a
write, chain, update.
Hope this helps.
Scott Feddersen
-----Original Message-----
From: rpg400-l-bounces@xxxxxxxxxxxx
[mailto:rpg400-l-bounces@xxxxxxxxxxxx] On Behalf Of albartell
Sent: Tuesday, September 25, 2007 5:05 PM
To: 'RPG programming on the AS400 / iSeries'
Subject: RE: MVC in RPG?
Couple questions:
1 - What is your criteria as to whether or not a file gets an RPG
*SRVPGM IO layer put in front of it? Or should all files potentially
have a wrapper in your approach? 2 - How do you relay record not found?
3 - How do you return information back to your program? 4 - How would
you do a SETLL, READE, DOW not %EOF loop? 5 - How do you do a READ/CHAIN
for lock vs. no-lock? 6 - How do you WRITE records to a file?
Some of the above are semi-rhetorical, simply because I have already
been down the road of what you are proposing. But I would be interested
to know if somebody came up with a solid and reasoned implementation of
*SRVPGM IO - I have yet to see one that is well reasoned other than
going on a case-by-case (read file-by-file) basis.
Aaron Bartell
http://mowyourlawn.com
-----Original Message-----
From: rpg400-l-bounces@xxxxxxxxxxxx
[mailto:rpg400-l-bounces@xxxxxxxxxxxx]
On Behalf Of Cassidy, Alan
Sent: Tuesday, September 25, 2007 4:40 PM
To: RPG programming on the AS400 / iSeries
Subject: RE: MVC in RPG?
-----Original Message-----
On Behalf Of albartell
Could you post an sample of your approach for review? I am curious to
know how you address partial key chains/setlls/reades/etc, and how you
address PF's with multiple logicals.
__I didn't do it full-blown but have done a little bit of "offloading"
some I/O to a service program, like for validating screen selections and
other things.
I *think* I like the idea for building new applications or application
"suites" from "scratch", since this would make it easier to do things
with the apps. If not for the limitation of the deadline, for example,
it certainly would have made Y2K a lot easier for a bunch of shops (like
mine).
(And the way some shops did it, 2040 will bring Round 2)
For partial key lists to get at a logical, I just used %parms inside the
procedure to count them and do a select list to separate a CHAIN (or
SETLL) for example.
Select
When %parms >= 3 ;
Chain(e) (key1: key2: key3) OrdFile ; When %parms >= 2 ;
Chain(e) (key1: key2 ) OrdFile ;
When %parms >= 1 ;
Chain(e) (key1 ) OrdFile ;
When %parms < 1 ;
Read OrdFile ; // (Didn't use this one, but you could...) EndSL ;
I would suppose you could use %KLST from a DS, and calculate how many
fields from the %parms, but you'd need to load the KLST fields.
You could even set up a STATIC field to track whether it's the first
time in, to determine whether to do a SETLL/READE or just a READE.
I've thought that this might be useful in the stead of using triggers,
IF
->ALL<- your DB access to a file was through this method, because among
other things, it would save the maintenance baggage. That's one reason
they haven't used triggers where I work, where it would complicate
administration for HA with journaling, for example. (Don't ask; too many
files, libraries, environments, etc).
--Alan
As an Amazon Associate we earn from qualifying purchases.