You are on page 1of 2

Four Hundred Guru--Files in Subprocedures http://www.itjungle.com/fhg/fhg042810-printer01.

html

Newsletters Subscriptions Forums Safari Store Career Media Kit About Us Contact Search Hom

Volume 10, Number 14 -- April 28, 2010

Files in Subprocedures Back to the Web Version

Published: April 28, 2010


TABLE OF CONTENTS
by Jon Paris
Files in Subprocedures
Subprocedures have been with us since V3R2/V3R6 and have had a major impact on the way that we
build applications. Or at least they should have done. Sadly, many RPGers remain firmly rooted in the Let One Row Represent a Group
past.
Admin Alert: Diary of a Production System
Those of you who do make regular use of subprocedures have undoubtedly found yourself wishing from Upgrade, Part 1
time to time that you could define files within them rather than having to resort to accessing globally
defined files. With the advent of the 6.1 release of the IBM i operating system, your wishes were
granted. Files can indeed now be defined within subprocedures.
The sample subprocedure presented here accesses two files to build a composite product description.
Since there are a number of considerations when using files within subprocedures, I'll work my way
through the code to point out the areas in which it differs from conventional file handling.
The two files are defined at (A) and (B). Note that with (A), in keeping with regular RPG specification
sequence, these F-specs must come before the subprocedure's Procedure Interface (PI) definition (at B),
since in the world of RPG, F comes before D! The result is that the P-spec that marks the start of the
subprocedure is now separated from the PI, something that I found hard to remember to begin with.
In this example there is nothing unusual about the F-specs themselves, but we will discuss one new
F-spec feature later in this tip.
Although not new for this release, the data structure definitions at (C) may not be familiar to you, since
they use the LikeRec keyword. The reason that these definitions are required is quite simple. In
subprocedures there is no support for I or O specs, and therefore none are generated for any files
defined in the subprocedure. As a result, all I/O must be done using the result-field data structure option,
and we must therefore define data structures to match the record layouts we require.

// GetDescr subprocedure - uses Product and Category files


P GetDescription B
(A) FXProducts IF E K Disk
FXCategors IF E K Disk

(B) D GetDescription PI 50a Varying


D categoryCode 2a
D productCode 5a

(C) D categoryData DS LikeRec(CATEGORREC)


D productData DS LikeRec(PRODUCTREC)
D fullDesc S 50a Varying
/Free
(D) Chain (categoryCode: productCode) XProducts productData;
If %Found(XProducts);
fullDesc = %Trim(productData.shortDesc);
(E) Chain productData.catCode XCategors categoryData;
If %Found(XCategors);
fullDesc += ' (' + %Trim(categoryData.catName) + ')';
Else;
fullDesc += ' (Category ' + productData.catCode + ' Not found)';
EndIf;
Else;
fullDesc = 'Product ' + productCode + ' Not found';
EndIf;
Return fullDesc;
/End-Free
P GetDescription E

You can see the first of the file operations at (D) where we use the Category and Product codes to
CHAIN to the XProducts file. The ability to simply reference the two key fields within parentheses was
added back in V5R2 in case you are unfamiliar with it. No more KLISTS! The productData data
structure is specified as the result field to receive the record. If the record is found, we proceed to the
second CHAIN, at (E), to retrieve the category description.
Although I could have used the category code that was passed in as part of the product code, I chose to
use the category code from the product file as the key. I did so for one reason: to highlight that the
productData data structure is implicitly qualified, since it was defined with the LikeRec keyword. So the
full name of the category code in the data structure is actually productData.catCode, and this is the name
used as the key field.

1 of 2 27.08.2010 05:48
Four Hundred Guru--Files in Subprocedures http://www.itjungle.com/fhg/fhg042810-printer01.html

The rest of the logic is just standard RPG and builds the complete description for return to the calling
program. Similarly, the balance of the program, whose only role in life is to allow me to test this
subprocedure, is pretty simple so I won't waste time describing it here.
So, is that all there is to it?
Not really. There are a few other things to consider.
First, all subprocedures allocate the storage for their variables when they are called, and release it when
they return. Guess what? The same thing happens with files opened within subprocedures. They are
opened when the subprocedure is called, and closed when it exits, much the same as it would be in a
program that always sets on LR before it returns to its caller. This could result in significant
performance problems for the unwary. Constantly opening and closing files is an expensive business. So
how can we avoid this overhead?
One answer is to specify the keyword STATIC on the file's F-spec. When this is done, the file will be
opened the first time the subprocedure is called and will remain open until explicitly closed, or when
the Activation Group ends, whichever comes first. Using STATIC in conjunction with USROPN would
allow you to have full control of the file. Remember, you will also need to add the STATIC keyword to
the data structure if you want to retain record data between subprocedure invocations.
The STATIC approach is not going to work if you intend to make use of the subprocedure's ability to call
itself recursively--for example when building a manufacturing parts list. If the file were defined as
static, then the same open, and therefore the same file cursor, will be "seen" by all invocation levels just
as a static variable is visible at all recursion levels. The other issue to consider when using the STATIC
keyword is that STATIC storage is not released by setting on LR in the main body of the program. As a
result any files declared as STATIC will remain open--even if the program ends. It will only be closed
when explicitly closed, or when the Activation Group ends.
The ability to define files within subprocedures certainly increases their utility and our ability to build
reusable components, but because of the performance implications you need to think about how you are
going to use them.
One byproduct of this 6.1 support was that IBM also added the ability to pass files as parameters. In the
long run, this capability may be far more interesting as it allows you to write reusable subprocedures
that can manipulate files, but allows the "ownership" of the file to remain with the program or procedure
that originally opened it. But that's a topic for a future tip.

Jon Paris is one of the world's most knowledgeable experts on programming on the System i
platform. Paris cut his teeth on the System/38 way back when, and in 1987 he joined IBM's Toronto
software lab to work on the COBOL compilers for the System/38 and System/36. He also worked on
the creation of the COBOL/400 compilers for the original AS/400s back in 1988, and was one of the
key developers behind RPG IV and the CODE/400 development tool. In 1998, he left IBM to start his
own education and training firm, a job he does to this day with his wife, Susan Gantner--also an
expert in System i programming. Paris and Gantner, along with Paul Tuohy and Skip Marchesani, are
co-founders of System i Developer, which hosts the new RPG & DB2 Summit conference. Send your
questions or comments for Jon to Ted Holt via the IT Jungle Contact page.

Copyright © 1996-2010 Guild Companies, Inc. All Rights Reserved.


Guild Companies, Inc., 50 Park Terrace East, Suite 8F, New York, NY 10034

Privacy Statement

2 of 2 27.08.2010 05:48

You might also like