Creating a Logical File or Index
A logical file provides a different view of a physical file.
The most common and simplest use of logical files is to change the order of the data.
To define a logical file, you use the DDS specifications.
The most common and simplest use of logical files is to change the order of the data.
To define a logical file, you use the DDS specifications.
You must start the Programming Development Manager and create a member with TYPE of LF (for logical file). Usually, this goes in the object QDDSSRC.
Here is how to make a logical file named CUS01 which orders the CUS physical file by name.
For simple logical files like this, the first line defines the record name of the physical file that has the data. This line also has the PFILE function that names the physical file.
Then, add a K definition for each key file.
A R CUSREC PFILE(CUS01)
Here is how to make a logical file named CUS01 which orders the CUS physical file by name.
For simple logical files like this, the first line defines the record name of the physical file that has the data. This line also has the PFILE function that names the physical file.
Then, add a K definition for each key file.
A R CUSREC PFILE(CUS01)
A*
A K NAME
Name the member in QDDSRC the same as the desired file. In this case, I named it CUS01.
Then, you must compile or create the file. In PDM you can do this with the option 14. When you use option 14, you actually execute the command:
A K NAME
Name the member in QDDSRC the same as the desired file. In this case, I named it CUS01.
Then, you must compile or create the file. In PDM you can do this with the option 14. When you use option 14, you actually execute the command:
CRTLF FILE(MYLIB/CUS01) SRCFILE(MYLIB/QDDSSRC) SRCMBR(CUS01)
The AS/400 knows to use this command because you specified that this member is describing a LF.
Add a SELECT spec to select only customers with STATUS of 'A'
A R CUSREC PFILE(CUS01)
A*
A K NAME
A S STATUS COMP(EQ 'A')
Or to omit records with a STATUS of 'D'
A R CUSREC PFILE(CUS01)
A*
A K NAME
A O STATUS COMP(EQ 'D')
An RPG program uses logical files almost identically to physical files.
Activation Groups In As400
I like to think of an activation group as a container for memory and other resources. According to the ILE Concepts manual (PDF format), this container is considered a "substructure of a job." In other words, the job owns the activation group. In fact, a job can own many activation groups.
So an activation group is a resource container within a job. Simple enough. But what does the container hold? The short answer is that it holds a bunch of activations, hence the term "activation" group. An activation is a reference to the storage allocation and runtime program binding activities that the operating systems perform when a program executes.
If it sounds complex, that's because it is. The good news is that you don't really have to understand these details in order to use activation groups. In fact, whether you realize it or not, you're already are using activation groups! Your job has a DAG, or default activation group, that is automatically created when your job is started. Actually, two default activation groups are created, but we'll treat them as one for the purpose of this article. This activation group is where your system code and OPM (Original Program Model) programs run. ILE programs can run in the default activation group, but I'll come back to that in a bit.
DAG-NAB IT!
Previous articles discussed creating programs out of modules, which is a two-step process: In RPG, this would include CRTRPGMOD (Create RPG Module) and then CRTPGM (Create Program). I use this approach exclusively, but for single-module programs, these steps can be consolidated into one command: CRTBNDRPG (Create Bound RPG Program). In PDM, this is the old stand by option 14, and the result is a *PGM object: The interim *MODULE object is not created. The reason why I mention this approach now is that this is typically the first run-in that new RPG IV programmers have with activation groups.
If you prompt 14 in PDM, you will see an option for Default Activation Group, with a default of *YES. If you try to create a program with DFTACTGRP(*YES), that program can't use any ILE features: no procedures (not even internal), no service programs, no binding directories. This sort of program is considered OPM even if it is written in RPG IV. As a result, you frequently see examples that include an H-spec of DFTACTGRP(*NO). This allows the program to compile with all of those ILE goodies because now, by virtue of being created with something other than the DAG, it is an ILE program.
For clarification, I should point out that a program created from *MODULE objects, whether one or many, cannot be created with DFTACTGRP(*YES). In fact, even if you include DFTACTGRP(*NO) in a source member and try to create a module (option 15 in PDM), you will receive a compile error because DFTACTGRP is not a valid parameter for the CRTMOD command. This makes sense when you consider that only ILE programs can use *MODULE objects, so a non-ILE option cannot be allowed.
Now that we are firmly entrenched in ILE territory, we are going to leave the DAG behind and explore our ILE options. There are several approaches you can use when creating a program or service program.
USING ACTGRP(*NEW)
The default for CRTPGM (and not an option for CRTSRVPGM) is ACTGRP(*NEW), so let's start there. This means that every time the program is executed, it creates a new activation group, or container, for all the resources necessary to run the program. Memory is allocated, the program is copied into the activation group, variables are initialized, and so on: This is very similar to OPM behavior. When the program reaches termination, the activation group is deleted and the resources are reclaimed.
As you can probably guess, this can be a labor-intensive process for the operating system, especially if the program is executed frequently. If you have a program that you execute 50 times a day from the same job (remember this is all job-oriented!), you are creating the activation group, executing the program, and destroying the activation group 50 times. This adds a lot of overhead to your job and will certainly affect performance.
The most important thing to remember about *NEW is that every call to the program is an island unto itself: Variable values and file states are new and fresh every time the program is called, even if called recursively. As such, it is advisable to use *NEW sparingly.
USING ACTGRP(*CALLER)
The default for CRTSRVPGM is *CALLER. Any program or service program invoked with *CALLER will run inside the activation group of the calling program or procedure. This can really improve performance in your applications, because it removes the overhead of creating the activation group. Using *CALLER works well for most procedures that are activated by other procedures, which is why it is the logical default for service programs.
I mentioned earlier that ILE programs can run in the DAG. You do so by specifying *CALLER, then executing the program directly from a command line or calling it from an OPM program. Since you are in the DAG when you do so, the program executes within the DAG. This is generally considered a poor practice, for several reasons. First, it defeats the purpose of having activation groups by lumping all resources together into a single group. Second, it unnecessarily clutters up the DAG: Remember that the DAG's main job is to run operating system code, so it seems logical that the less you can make that group worry about, the better. Finally, it prevents you from isolating the activities of an activation group because it doesn't have a unique name, a topic that will be covered a little later.
USING ACTGRP(named)
The final option for activation groups is to give them a name. This is also the coolest option, and has the best promise for performance. A named activation group is just that: one for which you specify the name. The first time the program or service program executes, it goes through the overhead of creating the group, but then that group remains active until it is reclaimed or the job has ended. Now any subsequent time the program is called it will run in the already extant group. Since the activation group is already running, start up time can be greatly diminished. As promised, this means faster performance.
To illustrate this, let me tell a story on myself. When I first went live several years ago with my RPG-CGI Web site, www.vamanet.com, I noticed that it ran great for a few users but that performance seriously degraded with more visitors. There were lots of explanations for that scenario, and I think we tried every one we could think of, to no avail. As I have frequently done in the past, I turned to an e-mail list for assistance. After going around the barn a few times, someone asked about the activation group specified when the CGI programs were created. After that, it didn't take long to realize my mistake: I had created all the programs with ACTGRP(*NEW).
By using *NEW, every Web request required the AS/400 to create an activation group, execute the program, answer the request, and destroy the activation group. That was a lot of overhead for something as simple as a Web page! Multiply that overhead by several thousand hits an hour, and my poor little 270 simply couldn't keep up with the demand. The solution was simple: I recreated all the programs with ACTGRP(named), where named is the name of the CGI program. Now, within each CGI job, once a page has been requested the activation group remains and is constantly reused. This provided a dramatic increase in performance.
SERVICE PROGRAMS WITH ACTGRP(named)
So far I've primarily discussed programs, so I'll shift a little and talk about service programs in particular. Again, the most common approach for CRTSRVPGM is to use ACTGRP(*CALLER). When you consider that most service programs consist of procedures that are called and used by other programs, it makes perfect sense to let the service program run in the same activation group as the program that's calling it.
Now, if you have 100 programs in 100 activation groups all using the same procedure in service program A, there will be 100 activations of that service program. That could obviously hamper performance. To improve that, you could put your service program into a named activation group, so that all the calling activations are sharing the same service program activation. This would be worth examining if you have a service program that is used extensively. As always, though, there is a caveat.
Using a named activation group introduces another interesting feature: Any static or global variables you use in a service program with a named activation group are available across other activation group boundaries.
A FEW MORE GOODIES
I'll leave you this time with a couple of quick goodies about activation groups. If you have an activation group that is not being used, and you would like to get rid of it, you can use the Reclaim Activation Group (RCLACTGRP) command. Indicate ACTGRP(*ELIGIBLE) to delete all non-active but existing activation groups (not including the DAG) or indicate ACTGRP(name), where name is the specific activation group you want to delete.
So how do you see an activation group? Well, you can't really see the activation group, but you can find a list of all the active groups for a particular job. Go to WRKJOB (or WRKACTJOB, and select option 5 for the job you want), and select option 18 ("display activation groups, if active"). You will see a listing of all the active groups associated with that job and a status indicator.
What is LEVEL CHECK in As400
Whenever PF is compiled, the system generates unique code for identifying the file for future reference.
When we compile the Program that uses the PF, will use that unique code of the PF.
If we now call the program, then its run successfully. But if we change the PF and recompile the PF, the system regenerates a new unique code for that PF. So, our program Don't have this unique code and hence terminates abnormally with a Level Check error.
The solution of Level Check error is when ever it happens we have to either compile the PF with Level Check parameter value *NO or we have to compile the program again.
Display and understand your Library List
The library list on the AS/400 is similar to the "path" on PC's. Mainframe programmers may compare it to the "steplib" or "joblib". It defines the order of libraries that the operating system uses to find objects.
When you execute a command or call a program, the AS/400 must know where to find the command or program. Sometimes, you specify the library explicitly. But if you don't, the AS/400 will find your command or program but looking in each library in your library list. It will use the first one that it finds.
This is very handy for testing. If you are testing a version of a program, you can put it in a test library which is at the top of your library list. Then, whenever you specify a program or refer to a file, the system will use any object it can find in the test library. If it can't find it there, it will look further through your library list until it finds it.
So, setting up a test environment is as simple as:1) Create a test library.2) Put objects that you want to test in the library. These can be files, menus, programs or any AS/400 object.3) Insert the test library name in your library list before your production libraries.
Now you can execute test programs and modify test data. The best part is that you don't need to copy production programs or files into the test library unless they will be affected by the test. That is, all those supporting database files that you need to run a program, but that are used for input only, do not need to be copied to the test library. Of course, if you are unsure if a file will be modified during your test procedure, copy it to the test library anyway.
Once you have inserted the test library name in your library list, you will want to make sure everything is in the proper order. Use the DSPLIBL command to see your library list. You will probably see three types of list entries:
1) The SYS libraries have operating system objects. This is where the AS/400 commands and menus live.2) The CUR library is your current library. This is your first user library and is where objects are created if you don't specify which library to use.3) The USR libraries list your other user libraries.
Use EDTLIBL to change your USR libraries. You can rearrange the list, remove libraries or add libraries. Notice that you can't see the SYS or CUR libraries when you use EDTLIBL. The only way to change the current library is with the CHGCURLIB command.
The WRKOBJ command will help see which object is being used. This command is similar to the directory ("dir") command on PC's. Use it to list objects in your library list.
So, if you have three copies of a program, "PAYCALC", in different libraries, use the command WRKOBJ PAYCALC to see which copy of "PAYCALC" will be used. The command will list all objects named "PAYCALC" in the sequence that the AS/400 finds them. If you ever say to yourself in frustration, "I know I changed the program but it looks like I'm still running the original program", it's a pretty good bet that you're executing a different copy of the program than you think. This is only a fraction of the power of the WRKOBJ command. It is the easiest way to navigate through an undocumented system.
DSPLIBL - Display complete library list
EDTLIBL - Edit library list
CHGCURLIB - Change Current Library
WRKOBJ - Work with objects (similar to PC "dir")
When you execute a command or call a program, the AS/400 must know where to find the command or program. Sometimes, you specify the library explicitly. But if you don't, the AS/400 will find your command or program but looking in each library in your library list. It will use the first one that it finds.
This is very handy for testing. If you are testing a version of a program, you can put it in a test library which is at the top of your library list. Then, whenever you specify a program or refer to a file, the system will use any object it can find in the test library. If it can't find it there, it will look further through your library list until it finds it.
So, setting up a test environment is as simple as:1) Create a test library.2) Put objects that you want to test in the library. These can be files, menus, programs or any AS/400 object.3) Insert the test library name in your library list before your production libraries.
Now you can execute test programs and modify test data. The best part is that you don't need to copy production programs or files into the test library unless they will be affected by the test. That is, all those supporting database files that you need to run a program, but that are used for input only, do not need to be copied to the test library. Of course, if you are unsure if a file will be modified during your test procedure, copy it to the test library anyway.
Once you have inserted the test library name in your library list, you will want to make sure everything is in the proper order. Use the DSPLIBL command to see your library list. You will probably see three types of list entries:
1) The SYS libraries have operating system objects. This is where the AS/400 commands and menus live.2) The CUR library is your current library. This is your first user library and is where objects are created if you don't specify which library to use.3) The USR libraries list your other user libraries.
Use EDTLIBL to change your USR libraries. You can rearrange the list, remove libraries or add libraries. Notice that you can't see the SYS or CUR libraries when you use EDTLIBL. The only way to change the current library is with the CHGCURLIB command.
The WRKOBJ command will help see which object is being used. This command is similar to the directory ("dir") command on PC's. Use it to list objects in your library list.
So, if you have three copies of a program, "PAYCALC", in different libraries, use the command WRKOBJ PAYCALC to see which copy of "PAYCALC" will be used. The command will list all objects named "PAYCALC" in the sequence that the AS/400 finds them. If you ever say to yourself in frustration, "I know I changed the program but it looks like I'm still running the original program", it's a pretty good bet that you're executing a different copy of the program than you think. This is only a fraction of the power of the WRKOBJ command. It is the easiest way to navigate through an undocumented system.
DSPLIBL - Display complete library list
EDTLIBL - Edit library list
CHGCURLIB - Change Current Library
WRKOBJ - Work with objects (similar to PC "dir")
A collection of thousands of interview questions and answers on AS400
ReplyDeleteAS400 Interview Questions