Starter Kit- Chapter 21 System iNetwork (formerly iSeries Network)
Home Site Map Contact Us My Profile Log In Join Now!
Info Centers
 Forums

 Tech Center

 News & Analysis

 Solution Center

 UK Centre
Popular Spots
 25th Anniversary

 Article Archive

 ProVIP Center (Club Tech)

 Code

 System i DocFinder

 Essential Guides

 Blogs

 Wikis

 e-Learning

 Webcasts

 Podcasts

 System i Jobs

 Events
Products
 i5 Route Finders

 Learning Center (Store)

 Product Directory
Network Poll
Determining a programmer's desktop requirements is not a black-and-white proposition, but matching equipment to programmer type can help productivity. Which "programmer type" are you?
Vote Now!
Network Memberships
 See Membership Levels

 Free E-Mail Newsletters

 Free RSS Feeds

 Subscribe/Join

 Upgrade Now

 Renew Now
About Us
 About the Network

 Network Publications

 Tech Editor Profiles

 Editorial Calendar

 Contact Us

 Subscribe

 Media Kit (PDF)

 Write For Us


System iNetwork November Sponsor





        System iNetwork November Sponsor


Home » Starter Kit » TOC » Chapter 21
  AS/400-iSeries Starter Kit


Chapter 21 - So You Think You Understand File Overrides

"Try using OvrScope(*Job)."

How many times have you heard this advice when a file override wasn't working as intended? Changing your application to use a job-level override may produce the intended results, but doing so is a bit like replacing a car's engine because it has a fouled spark plug.

Actually, with a fully functional new engine, the car will always run right again. A job-level override, on the other hand, may or may not produce the desired results, depending on your application's design. And even if the application works today, an ill-advised job-level override coupled with modifications may introduce application problems in the future.

If you're considering skipping this article because you believe you already understand file overrides, think again! I know many programmers, some excellent, who sincerely believe they understand this powerful feature of OS/400 — after all, they've been using overrides in their applications for years. However, I've yet to find anyone who does fully understand overrides. So, read on, surprise yourself, and learn once and for all how the system processes file overrides. Then put this knowledge to work to get the most out of overrides in your applications.

Anatomy of Jobs

Before examining file overrides closely, you need to be familiar with the parts of a job's anatomy integral to the function of overrides. The call stack and activation groups both play a key role in determining the effect overrides have in your applications.

Jobs typically consist of a chain of active programs, with one program calling another. The call stack is simply an ordered list of these active programs. When a job starts, the system routes it to the beginning program to execute and designates that program as the first entry in the call stack. If the program then calls another program, the system assigns the newly called program to the second call stack entry. This process can continue, with the second program calling a third, the third calling a fourth, and so on, each time adding the new program to the end of the call stack. The call stack therefore reflects the depth of program calls.

Consider the following call stack:

ProgramA
ProgramB
ProgramC
ProgramD

You can see four active programs in this call stack. In this example, the system called ProgramA as its first program when the job started. ProgramA then called ProgramB, which in turn called ProgramC. Last, ProgramC called ProgramD. Because these are nested program calls, each program is at a different layer in the call stack. These layers are known as call levels. In the example, ProgramA is at call level 1, indicating the fact that it is the first program called when the job started. ProgramB, ProgramC, and ProgramD are at call levels 2, 3, and 4, respectively.

As programs end, the system removes them from the call stack, reducing the number of call levels. For instance, when ProgramD ends, the system removes it from the call stack, and the job then consists of only three call levels. If ProgramC then ends, the job consists of only two call levels, with ProgramA and ProgramB making up the call stack. This process continues until ProgramA ends, at which time the job ends.

So far, you've seen that when one program calls another, the system creates a new, higher call level at which the called program runs. The called program then begins execution, and when it ends, the system removes it from the call stack, returning control to the calling program at the previous call level.

That's the simple version, but there's a little more to the picture. First, it's possible for one program to pass control to another program without the newly invoked program running at a higher call level. For instance, with CL's TfrCtl (Transfer Control) command, the system replaces (in the call stack) the program issuing the command with the program to which control is to be transferred. Not only does this action result in the invoked program running at the same call level as the invoking program, but the invoking program is also completely removed from the chain of programs making up the call stack. Hence, control can't be returned to the program that issued the TfrCtl command. Instead, when the newly invoked program ends, control returns to the program at the immediately preceding call level.

You may recall that earlier I said that as programs end, the system removes them from the call stack. In reality, when a program ends, the system removes from the call stack not only the ending program but also any program at a call level higher than that of the ending program. You might be thinking about our example and scratching your head, wondering, "How can ProgramB end before ProgramC?" Consider the fact that ProgramD can send an escape message to ProgramB's program message queue. This event results in the system returning control to ProgramB's error handler. This return of control to ProgramB results in the system removing from the call stack all programs at a call level higher than ProgramB — namely, ProgramC and ProgramD. ProgramB's design then determines whether it is removed from the call stack. If it handles the exception, ProgramB is not removed from the call stack; instead, processing continues in ProgramB.

You should also note that under normal circumstances, the call stack begins with several system programs before any user-written programs appear. In fact, system programs will likely appear throughout your call stack. This point is important only to demonstrate that the call stack isn't simply a representation of user-written programs as they are called.

In addition to an understanding of a job's call levels, you need a basic familiarity with activation groups to comprehend file overrides. You're probably familiar with the fact that a job is a structure with its own allocated system resources, such as open data paths (ODPs) and storage for program variables. These resources are available to programs executed within that job but are not available to other jobs. Activation groups, introduced with the Integrated Language Environment (ILE), are a further division of jobs into smaller substructures.

As is the case with jobs, activation groups consist of private system resources, such as ODPs and storage for program variables. An activation group's allocated resources are available only to program objects that are assigned to, and running in, that particular activation group within the job. You assign ILE program objects to an activation group when you create the program objects. Then, when you execute these programs, the system creates the activation group (or groups) to which the programs are assigned. A job can consist of multiple activation groups, none of which can access the resources unique to the other activation groups within the job. For example, although multiple activation groups within a job may open the same file, each activation group can maintain its own private ODP. In such a case, programs assigned to the same activation group can use the ODP, but programs assigned to a different activation group don't have access to the same ODP.

A complete discussion of activation groups could span volumes. For now, it's sufficient simply to note that activation groups exist, that they are substructures of a job, and that they can contain their own set of resources not available to other activation groups within the job.

Override Rules

The rules governing the effect overrides have on your applications fall into three primary areas: the override scope, overrides to the same file, and the order in which the system processes overrides. After examining the details of each of these areas, we'll look at a few miscellaneous rules.

Scoping an Override

An override's scope determines the range of influence the override will have on your applications. You can scope an override to the following levels:

  • Call level — A call-level override exists at the level of the process that issues the override, unless the override is issued using a call to program QCmdExc; in that case, the call level is that of the process that called QCmdExc. A call-level override remains in effect from the time it is issued until the system replaces or deletes it or until the call level in which the override was issued ends.
  • Activation group level — An activation-group­level override applies to all programs running in the activation group associated with the issuing program, regardless of the call level in which the override is issued. In other words, only the most recently issued activation-group­level override is in effect. An activation-group­ level override remains in effect from the time the override is issued until the system replaces it, deletes it, or deletes the activation group. These rules apply only when the override is issued from an activation group other than the default activation group. Activation-group­level overrides issued from the default activation group are scoped to call-level overrides.
  • Job level — A job-level override applies to all programs running in the job, regardless of the activation group or call level in which the override is issued. Only the most recently issued job-level override is in effect. A job-level override remains in effect from the time it is issued until the system replaces or deletes it or until the job in which the override was issued ends.

You specify an override's scope when you issue the override, by using the override command's OvrScope (Override scope) parameter. Figure 1 depicts an ILE application's view of a job's structure, along with the manner in which you can specify overrides.

First, notice that two activation groups, the default activation group and a named activation group, make up the job. All jobs have as part of their structure the default activation group and can optionally have one or more named activation groups.

Original Program Model (OPM) programs can run only in the default activation group. Figure 1 shows two OPM programs, Program1 and Program2, both running in the default activation group. Because OPM programs can't be assigned to a named activation group, jobs that run only OPM programs consist solely of the default activation group.

ILE program objects, on the other hand, can run in either the default activation group or a named activation group, depending on how you assign the program objects to activation groups. If any of a job's program objects are assigned to a named activation group, the job will have as part of its structure that named activation group. In fact, if the job's program objects are assigned to different named activation groups, the job will have each different named activation group as part of its structure. Figure 1 shows five ILE programs: Program3 and Program4 are both running in the default activation group, and Program5, Program6, and Program7 are running in a named activation group.

The figure not only depicts the types of program objects that can run in the default activation group and in a named activation group; it also shows the valid levels to which you can scope overrides. Programs running in the default activation group, whether OPM or ILE, can issue overrides scoped to the job level or to the call level. ILE programs running in a named activation group can scope overrides not only to these two levels but to the activation group level as well. Figure 1 portrays each of these possibilities.

Overriding the Same File Multiple Times

One feature of call-level overrides is the ability to combine multiple overrides for the same file so that each of the different overridden attributes applies. Consider the following program fragments, which issue the OvrPrtF (Override with Printer File) command:

ProgramA:

OvrPrtF  File(Report) OutQ(Sales01) +    
         OvrScope(*CallLvl) 
Call     Pgm(ProgramB)

ProgramB:

OvrPrtF  File(Report) Copies(3) + 
         OvrScope(*CallLvl) 
Call     Pgm(PrintPgm)

When program PrintPgm opens and spools printer file Report, the overrides from both programs are combined, resulting in the spooled file being placed in output queue Sales01 with three copies set to be printed.

Now, consider the following program fragment:

ProgramC:

OvrPrtF  File(Report) OutQ(Sales01) + 
         OvrScope(*CallLvl) 
OvrPrtF  File(Report) Copies(3) + 
         OvrScope(*CallLvl) 
Call     Pgm(PrintPgm)

What do you think happens? You might expect this program to be functionally equivalent to the two previous programs, but it isn't. Within a single call level, only the most recent override is in effect. In other words, the most recent override replaces the previous override in effect. In the case of ProgramC, the Copies(3) override is in effect, but the OutQ(Sales01) override is not. This feature provides a convenient way to replace an override within a single call level without the need to first delete the previous override. It's also fun to show programmers ProgramA and ProgramB, explain that things worked flawlessly, and then ask them to help you figure out why things didn't work right after you changed the application to look like ProgramC! When they finally figure out that only the most recent override within a program is in effect, show them your latest modification —

ProgramA:

OvrPrtF  File(Report) OutQ(Sales01) + 
         OvrScope(*CallLvl) 
TfrCtl   Pgm(ProgramB)

ProgramB:

OvrPrtF  File(Report) Copies(3) + 
         OvrScope(*CallLvl) 
Call     Pgm(PrintPgm)

— and watch them go berserk again! This latest change is identical to the first iteration of ProgramA and ProgramB, except that rather than issue a Call to ProgramB from ProgramA, you use the TfrCtl command to invoke ProgramB. Remember, TfrCtl doesn't start a new call level. ProgramB will simply replace ProgramA on the call stack, thereby running at the same call level as ProgramA. Because the call level doesn't change, the overrides aren't combined.

You may need to point out to the programmers that they didn't really figure it out at all when they determined that only the most recent override within a program is in effect. The rule is: Only the most recent override within a call level is in effect.

The Order of Applying Overrides

You've seen the rules concerning the applicability of overrides. In the course of a job, many overrides may be issued. In fact, as you've seen, many may be issued for a single file. When many overrides are issued for a single file, the system constructs a single override from the overridden attributes in effect from all the overrides. This type of override is called a merged override. Merged overrides aren't simply the result of accumulating the different overridden file attributes, though. The system must also modify, or replace, applicable attributes that have been overridden multiple times and remove overrides when an applicable request to delete overrides is issued.

To determine the merged override, the system follows a distinct set of rules that govern the order in which overrides are processed. The system processes the overrides for a file when it opens the file and uses the following sequence to check and apply overrides:

  1. call-level overrides up to and including the call level of the oldest procedure in the activation group containing the file open (beginning with the call level that opens the file and progressing in decreasing call-level sequence)
  2. the most recent activation-group­level overrides for the activation group containing the file open
  3. call-level overrides lower than the call level of the oldest procedure in the activation group containing the file open (beginning with the call level immediately preceding the call level of the oldest procedure in the activation group containing the file open and progressing in decreasing call-level sequence)
  4. the most recent job-level overrides

This ordering of overrides can get tricky! It is without a doubt the least-understood aspect of file overrides and the source of considerable confusion and errors.

To aid your understanding, let's look at an example. Figure 2A shows a job with 10 call levels, programs in the default activation group and in two named activation groups (AG1 and AG2), and overrides within each call level and each activation group. Before we look at how the system processes these overrides, see whether you can determine the file that ProgramJ at call level 10 will open, as well as the attribute values that will be in effect due to the job's overrides. In fact, try the exercise twice, the first time without referring to the ordering rules.

Figure 2B reveals the results of the job's overrides. Did you arrive at these results in either of your tries? Let's walk, step by step, through the process of determining the overrides in effect for this example.

Step 1 — call-level overrides up to and including the call level of the oldest procedure in the activation group containing the file open

Checking call level 10 shows that the system opens file Report1 in activation group AG1. The oldest procedure in activation group AG1 appears at call level 2. Therefore, in step 1, the system processes call-level overrides beginning with call level 10 and working up the call stack through call level 2. When the system processes call level 2, step 1 is complete.

  1. There is no call-level override for file Report1 at call level 10.
  2. There is no call-level override for file Report1 at call level 9.
  3. There is no call-level override for file Report1 at call level 8.
  4. There is no call-level override for file Report1 at call level 7.
  5. Call level 6 contains a call-level override for file Report1. The Copies attribute for file Report1 is overridden to 7.

  6. Active overrides at this point: Copies(7)

  7. Call level 5 shows an activation-group­level override, but the program is running in the default activation group. Remember, activation-group­level overrides issued from the default activation group are scoped to call-level overrides. Therefore, the system processes this override as a call-level override. The CPI attribute for file Report1 is overridden to 13.3, and the previous Copies attribute value is replaced with this latest value of 6.

  8. Active overrides at this point: CPI(13.3) Copies(6)

  9. There is no call-level override for file Report1 at call level 4.
  10. Call level 3 contains a call-level override for file Report1. The LPI attribute for file Report1 is overridden to 9, and the previous Copies attribute value is replaced with this latest value of 4.

  11. Active overrides at this point: LPI(9) CPI(13.3) Copies(4)

  12. There is no call-level override for file Report1 at call level 2.

Step 1 is now complete. Call level 2 contains the oldest procedure in activation group AG1 (the activation group containing the file open).

Step 2 — the most recent activation-group­level overrides for the activation group containing the file open

The system now checks for the most recently issued activation-group­level override within activation group AG1, where file Report1 was opened.

  1. There is no activation-group­level override for file Report1 at call level 10.
  2. There is no activation-group­level override for file Report1 in activation group AG1 at call level 9. The activation-group­level override in call level 9 is in activation group AG2 and is therefore not applicable.
  3. Call level 8 contains an activation-group­level override in activation group AG1 for file Report1. The FormFeed attribute for file Report1 is overridden to *Cut, the previous LPI attribute value is replaced with this latest value of 12, and the previous Copies attribute value is replaced with this latest value of 9.

Active overrides at this point:
LPI(12) CPI(13.3) FormFeed(*Cut) Copies(9)

Step 2 is now complete. The system discontinues searching for activation-group­level overrides because this is the most recently issued activation-group­level override in activation group AG1.

Step 3 — call-level overrides lower than the call level of the oldest procedure in the activation group containing the file open

Remember, call level 2 is the call level of the oldest procedure in activation group AG1. The system begins processing call-level overrides at the call level preceding call level 2. In this case, there is only one call level lower than call level 2.

  1. Call level 1 contains a call-level override for file Report1. The OutQ attribute for Report1 is overridden to Prt01, and the previous Copies attribute value is replaced with this latest value of 2.

Active overrides at this point:
LPI(12) CPI(13.3) FormFeed(*Cut) OutQ(Prt01) Copies(2)

Step 3 is now complete. The call stack has been processed through call level 1.

Step 4 — the most recent job-level overrides

The system finishes processing overrides by checking for the most recently issued job-level override for file Report1.

  1. There is no job-level override for file Report1 at call level 10.
  2. There is no job-level override for file Report1 at call level 9.
  3. There is no job-level override for file Report1 at call level 8.
  4. Call level 7 contains a job-level override for file Report1. Notice that the program runs in activation group AG2 rather than AG1. Job-level overrides can come from any activation group. The previous Copies attribute value is replaced with this latest value of 8.

Active overrides at this point:
LPI(12) CPI(13.3) FormFeed(*Cut) OutQ(Prt01) Copies(8)

Step 4 is now complete. The system discontinues searching for job-level overrides because this is the most recently issued job-level override.

This completes the application of overrides. The final merged override that will be applied in call level 10 is

LPI(12) CPI(13.3) FormFeed(*Cut) OutQ(Prt01)
Copies(8)

All other attribute values come from the file description for printer file Report1. It's easy to see how this process could be confusing and lead to the introduction of errors in applications!

Now, let's make the process even more confusing! In the previous example, our HLL program (ProgramJ) opened file Report1, and no programs issued an override to the file name. What do you think happens when you override the file name to a different file using the ToFile parameter on the OvrPrtF command? Once the system issues an override that changes the file, it searches for overrides to the new file, not the original. Let's look at a slightly modified version of our example. Figure 2C contains the new programs.

Only two of the original programs have been changed in this new example. In ProgramC at call level 3, the ToFile parameter has been added to the OvrPrtF command, changing the file to be opened from Report1 to Report2. And ProgramB at call level 2 now overrides printer file Report2 rather than Report1.

Figure 2D shows the results of the overrides. Again, let's step through the process of determining the overrides in effect for this example.

Step 1 — call-level overrides up to and including the call level of the oldest procedure in the activation group containing the file open

Checking call level 10 shows that the system opens file Report1 in activation group AG1. The oldest procedure in activation group AG1 appears at call level 2. Therefore, in step 1, the system processes call-level overrides beginning with call level 10 and working up the call stack through call level 2. When the system processes call level 2, step 1 is complete.

  1. There is no call-level override for file Report1 at call level 10.
  2. There is no call-level override for file Report1 at call level 9.
  3. There is no call-level override for file Report1 at call level 8.
  4. There is no call-level override for file Report1 at call level 7.
  5. Call level 6 contains a call-level override for file Report1. The Copies attribute for file Report1 is overridden to 7.

  6. Active overrides at this point: Copies(7)

  7. Call level 5 shows an activation-group­level override, but the program is running in the default activation group. Again, activation-group­level overrides issued from the default activation group are scoped to call-level overrides. Therefore, the system processes this override as a call-level override. The CPI attribute for file Report1 is overridden to 13.3, and the previous Copies attribute value is replaced with this latest value of 6.
  8. Active overrides at this point: CPI(13.3) Copies(6)

  9. There is no call-level override for file Report1 at call level 4.
  10. Call level 3 contains a call-level override for file Report1. The LPI attribute for file Report1 is overridden to 9, and the previous Copies attribute value is replaced with this latest value of 4. Notice that the printer file has also been overridden to Report2. This is especially noteworthy because the system will now begin searching for overrides to file Report2 rather than file Report1.
  11. Active overrides at this point:
    ToFile(Report2) LPI(9) CPI(13.3) Copies(4)

  12. There is no call-level override for file Report2 at call level 2.

Step 1 is now complete. Call level 2 contains the oldest procedure in activation group AG1 (the activation group containing the file open).

Step 2 — the most recent activation-group­level overrides for the activation group containing the file open

The system now checks for the most recently issued activation-group­level override within activation group AG1 where file Report1 (actually Report2 now) was opened.

  1. There is no activation-group­level override for file Report2 at call level 10.
  2. There is no activation-group­level override for file Report2 in activation group AG1 at call level 9. The activation-group­level override in call level 9 is in activation group AG2 and is therefore not applicable.
  3. There is no activation-group­level override for file Report2 at call level 8.
  4. There is no activation-group­level override for file Report2 at call level 7.
  5. There is no activation-group­level override for file Report2 at call level 6.
  6. There is no activation-group­level override for file Report2 at call level 5.
  7. There is no activation-group­level override for file Report2 at call level 4.
  8. There is no activation-group­level override for file Report2 at call level 3.
  9. Call level 2 contains an activation-group­level override in activation group AG1 for file Report2. The FormType attribute for file Report2 is overridden to FormB, the previous LPI attribute value is replaced with this latest value of 7.5, and the previous Copies attribute value is replaced with this latest value of 3.

Active overrides at this point: ToFile(Report2) LPI(7.5) CPI(13.3) FormType(FormB) Copies(3)

Step 2 is now complete. The system discontinues searching for activation-group­level overrides because this is the most recently issued activation-group­level override in activation group AG1.

Step 3 — call-level overrides lower than the call level of the oldest procedure in the activation group containing the file open

Again, call level 2 is the call level of the oldest procedure in activation group AG1. The system begins processing call-level overrides at the call level preceding call level 2 (i.e., call level 1).

  1. There is no call-level override for file Report2 at call level 1.

Step 3 is now complete. The call stack has been processed through call level 1.

Step 4 — the most recent job-level overrides

The system finishes processing overrides by checking for the most recently issued job-level override for file Report2.

  1. There is no job-level override for file Report2 at call level 10.
  2. There is no job-level override for file Report2 at call level 9.
  3. There is no job-level override for file Report2 at call level 8.
  4. There is no job-level override for file Report2 at call level 7.
  5. There is no job-level override for file Report2 at call level 6.
  6. There is no job-level override for file Report2 at call level 5.
  7. There is no job-level override for file Report2 at call level 4.
  8. There is no job-level override for file Report2 at call level 3.
  9. There is no job-level override for file Report2 at call level 2.
  10. There is no job-level override for file Report2 at call level 1.

Step 4 is now complete. There are no job-level overrides for file Report2.

This completes the application of overrides. The final merged override that will be applied to printer file Report2 in call level 10 is

LPI(7.5) CPI(13.3) FormType(FormB) Copies(3)

All other attribute values come from the file description for printer file Report2.

Protecting an Override

In some cases, you may want to protect an override from the effect of other overrides to the same file. In other words, you want to ensure that an override issued in a program is the override that will be applied when you open the overridden file. You can protect an override from being changed by overrides from lower call levels, the activation group level, and the job level by specifying Secure(*Yes) on the override command.

Figure 3 shows excerpts from two programs, ProgramA and ProgramB, running in the default activation group and with call-level overrides only. ProgramA simply issues an override to set the output queue attribute value for printer file Report1 and then calls ProgramB. ProgramB in turn calls two HLL programs, HLLPrtPgm1 and HLLPrtPgm2, both of which function to print report Report1. Before the call to each of these programs, ProgramB issues an override to file Report1 to change the output queue attribute value.

When you call ProgramA, the system first issues a call-level override that sets Report1's output queue attribute to value Prt01. Next, ProgramA calls ProgramB, thereby creating a new call level. ProgramB begins by issuing a call-level override, setting Report1's output queue attribute value to Prt02. Notice that the OvrPrtF command specifies the Secure parameter with a value of *Yes. ProgramB then calls HLL program HLLPrtPgm1 to open and print Report1. Because this call-level OvrPrtF command specifies Secure(*Yes), the system does not apply call-level overrides from lower call levels — namely, the override in ProgramA that sets the output queue attribute value to Prt01. HLLPrtPgm1 therefore places the report in output queue Prt02.

ProgramB continues with yet another call-level override, setting Report1's output queue attribute value to Prt03. Because this override occurs at the same call level as the first override in ProgramB, the system replaces the call level's override. However, this new override doesn't specify Secure(*Yes). Therefore, the system uses the call-level override from call level 1. This override changes the output queue attribute value from Prt03 to Prt01. ProgramB finally calls HLLPrtPgm2 to open and spool Report1 to output queue Prt01. These two overrides in ProgramB clearly demonstrate the behavioral difference between an unsecured and a secured override.

Explicitly Removing an Override

The system automatically removes overrides at certain times, such as when a call level ends, when an activation group ends, and when the job ends. However, you may want to remove the effect of an override at some other time. The DltOvr (Delete Override) command makes this possible, letting you explicitly remove overrides.

With this command, you can delete overrides at the call level, the activation group level, or the job level as follows:

Call level: DltOvr File(File1) OvrScope(*) Activation
group level: DltOvr File(File2) OvrScope(*ActGrpDfn) Job level: DltOvr File(File3) OvrScope(*Job)

Value *ActGrpDfn is the default value for the DltOvr command's OvrScope (Override scope) parameter. If you don't specify parameter OvrScope on the DltOvr command, this value is used.

The command's File parameter also supports special value *All, letting you extend the reach of the DltOvr command. This option gives you a convenient way to remove overrides for several files with a single command.

Miscellanea

I've covered quite a bit of ground with these rules of overriding files. In addition to the rules you've already seen, I'd like to introduce you to a few tidbits you might find useful.

You've probably grown accustomed to the way a CL program lets you know when you've coded something erroneously — the program crashes with an exception! However, specify a valid, yet wrong, file name on an override, and the system gives you no warning you've done so. This seemingly odd behavior is easily explained. Consider the following code:

OvrPrtF  File(Report1) OutQ(Prt01)
Call Pgm(HLLPrtPgm)

However, HLLPrtPgm opens file Report2, not Report1. The system happily spools Report2 without any regard to the override. Although this is clearly a mistake in that you've specified the wrong file name in the OvrPrtF command, the system has no way of knowing this. The system can't know your intentions. Remember, this override could be used somewhere else in the job, perhaps even in a different call level.

The second tidbit involves a unique override capability that exists with the OvrPrtF command. OvrPrtF's File parameter supports special value *PrtF, letting you extend the reach of an override to all printer files (within the override scoping rules, of course). All rules concerning the application of overrides still apply. Special value *PrtF simply gives you a way to include multiple files with a single override command.

Also, you may recall an earlier reference to program QCmdExc and how its use affects the scope of an override. This program's primary purpose is to serve as a vehicle that lets HLL programs execute system commands. You can therefore use QCmdExc from within an HLL program to issue a file override. Remember that when you issue an override using this method, the call level is that of the process that invoked QCmdExc.

You should note that override commands may or may not affect system commands. For more information about overrides and system commands, see "Overrides and System Commands,".

Important Additional Override Information

With the major considerations of file overrides covered, let's now take a brief look at some additional override information of note.

Overriding the Scope of Open File

At times, you'll want to share a file's ODP among programs in your application. For instance, when you use the OpnQryF (Open Query File) command, you must share the ODP created by OpnQryF or your application won't use the ODP created by OpnQryF. To share the ODP, you specify Share(*Yes) on the OvrDbF (Override with Database File) command.

You can also explicitly control the scope of open files (ODPs) using the OpnScope (Open scope) parameter on the OvrDbF command. You can override the open scope to the activation group level and the job level.

Non-File Overrides

In addition to file overrides, the system provides support for overriding message files and program device entries used in communications applications.

You can override the message file used by programs by using the OvrMsgF (Override with Message File) command. However, the rules for applying overrides with OvrMsgF are quite different from those with other override commands. You can override only the name of the message file used, not the attributes.

During the course of normal operations, the system frequently sends various types of messages to various types of message queues. OvrMsgF provides a way for you to specify that when sending a message for a particular message ID, the system should first check the message file specified in the OvrMsgF for the identified message. If the message is found, the system sends the message using the information from this message file. If the message isn't found, the system sends the message using the information from the original message file.

Using the OvrICFDevE (Override ICF Program Device Entry) command, you can issue overrides for program device entries. Overrides for program device entries let you override attributes of the Intersystem Communications Function (ICF) file that provides the link between your programs and the remote systems or devices with which your program communicates.

Overrides and Multithreaded Jobs

The system provides limited support for overrides in multithreaded jobs. Some restrictions apply to the provided support. The system supports the following override commands:

  • OvrDbF — You can issue this command from the initial thread of a multithreaded job. Only overrides scoped to the job level or an activation group level affect open operations performed in a secondary thread.
  • OvrPrtF — You can issue this command from the initial thread of a multithreaded job. As with OvrDbF, only overrides scoped to the job level or an activation group level affect open operations performed in a secondary thread.
  • OvrMsgF — You can issue this command from the initial thread of a multithreaded job. This command affects only message file references in the initial thread. Message file references performed in secondary threads are not affected.
  • DltOvr — You can issue this command from the initial thread of a multithreaded job.

The system ignores any other override commands in multithreaded jobs.

File Redirection

You can use overrides to redirect input or output to a file of a different type. For instance, you may have an application that writes directly to tape using a tape file. If at some time you'd like to print the information that's written to tape, you can use an override to accomplish your task. When you redirect data to a different file type, you use the override appropriate for the new target file. In the case of our example, you would override from the tape file to a printer file using the OvrPrtF command.

I mention file redirection so that you know it's a possibility. Of course, many restrictions apply when using file redirection, so if you decide you'd like to use the technique, refer to the documentation. IBM's File Management provides more information about file redirection. You can find this manual on the Internet at IBM's iSeries Information Center (http://publib.boulder.ibm.com/pubs/html/as400/infocenter.htm).

Surprised?

Did you find any surprises along the way? My guess is that you did. The important thing is that now you should be able to find your way around file overrides without having to resort to job-level overrides in desperation!

This article is excerpted from the book Starter Kit for the IBM iSeries and AS/400 by Gary Guthrie and Wayne Madden (NEWS/400 Books, 2001)

Gary Guthrie is a NEWS/400 technical editor and technical support consultant with more than 20 years of progressive IT experience. You can reach him at gguthrie@iseriesnetwork.com.



  Sponsored Links   Featured Links


Penton Technology Media
Connected Home | SQL Server Magazine | Windows IT Pro
Report Bugs | Contact Us | Comments/Suggestions | Terms & Conditions | Privacy Policy | Trademarks
See Membership Levels | Subscribe | Free E-mail Newsletters | Free RSS Feeds | My Profile | Upgrade Now | Renew Now

Copyright © 2008 - Penton Technology Media
Penton Media
System i is a trademark of International Business Machines Corporation and is used by Penton Media, Inc., under license. SystemiNetwork.com is published independently of International Business Machines Corporation, which is not responsible in any way for the content. Penton Media, Inc., is solely responsible for the editorial content and control of the System iNetwork.