Determining the Version and Release Level of OS/400
If you are writing software for multiple AS/400s, or if your job requires you to program on more than one AS/400, youve probably worked on more than one release of OS/400 at the same time.
Sometimes, the ability of your software to function correctly is dependent upon a particular release level of the operating system. For example, you may need to call a certain program or command if your software is running on a CISC machine and call a different program or command if it is running on a RISC machine. So, how can you programmatically check the OS/400 level? Simple, just insert the code fragment shown in Figure 1 in your CL program, and then execute the appropriate commands, depending on the release of the operating system. The OS level will be returned as a 9-byte character variable of the format VxxRxxMxx, where xx indicates version, release, and modification level numbers in two-digit format. T. V. S. Murthy
V4R2 File Layout Gotcha!
V4R2 introduced a couple of changes to the system database that you may not be
prepared for. IBM changed the record formats of files QADBIFLD and QADBKFLD. QADBIFLD contains the field definitions for all of the files on your AS/400, while file QADBKFLD contains all of the key fields for all of the files on your system. If you use these files in your own applications, as I do, you may need to modify your code to handle these changes.
David Mayle Beaver, Pennsylvania
V4R2 IPL Options
V4R2 of OS/400 has introduced many enhancements in the area of IPLs, one of
which is a new attribute table for IPLs. You can view this table with the Display IPL
Attributes (DSPIPLA) command, which works much like the Display Net Attributes (DSPNETA) command. You can change the values in this table using the Work IPL Attributes (WRKIPLA) command to specify where certain IPLs are to begin, e.g., Power Down System (PWRDWNSYS) with RESTART. Using this new table, you can eliminate some of the early IPL steps, like the one that checks resources three times during IPL. Depending on the machine size, this can save up to 10 or 15 minutes off of the IPL.
Jack McGuigan MIS Manager, American Life Ins. Co.
Logging Commands
Q: Commands entered into a command line of an IBM display are logged and can be retrieved with the F9 key. However, commands entered into a command line in a display file and executed by QCMDEXC in one of my programs are not logged. How can I make the system log commands executed within my program?
Ron Adams
A: You need to send the command to the job as a request message. To add a command that is not executed from a command line to the jobs request messages, send the command as a request message and immediately receive it. You must receive it, or QCMD will consider it an active request message and try to execute it. Figure 2 is an example of how to send a command as a request message. Each time your application issues a command, call this program, passing it the command string and a blank message key.
Jerry Jewel
Ted Holt Senior Technical Editor Midrange Computing
Retrieving Commands
Q: When I press F9 from a menu, OS/400 retrieves previously executed commands. How can I make my programs retrieve previously executed commands?
A: Your program needs to call the QMHRTVRQ API, which retrieves the request messages for the job. The code in Figure 3 illustrates how to do this.
Jerry Jewel
Ted Holt Senior Technical Editor Midrange Computing
Retrieving Journal Entries
Q: I would like to retrieve journal information programatically. Ideally, Id like to have the functionality of the Work with Journal Attributes (WRKJRNA) command and/or the Display Journal Attribution (DSPJRNRCVA) command in a program. I cant find any Retrieve (RTV) journal commands or, even better, journal APIs that will give me this information.
Dale Monti
A: In V4R2, there are several new APIs in the area of journaling. Two that will be of interest to you are QjoRetrieveJournalInformation() and QjoRtvJrnReceiverInformation(). These are documented in the Journal and Commit APIs chapter of the System API Reference manual (SC41-5801-00).
For earlier releases, the information was also available through the MI instructions MATJPAT and MATJSAT; and for systems at security level 40 and above, the systems MI were handled by APIs like (QusMaterializeJournalPortAttr and QusMaterializeJournalSpaceAttr). The APIs were provided to get around the domain failures seen in the direct MI usage at higher security levels. These APIs are also in the System API Reference and Journal and Commit APIs (SC41-5882-02) manuals.
Bruce Vining Rochester, Minnesota
Using the Javap Utility
Q: I cant get the javap program you demonstrated in a previous issue [see Object- oriented Design for AS/400 Java Applications: Standard Encapsulation Strategies, MC, July 1998] to run against the Clock class/package. However, I can get it to work against the AlarmClock class. I was wondering if you could give me directions on how to get it to work with the Clock class/package. When I attempt to use it, I get the following error message: Binary File Clock contains Clock.Clock.
Peter T. Sheridan
A: Running the javap utility to list the API of my little class is not all that worthwhile, but javap over standard Java classes and any toolkit packages is worthwhile, so your question is well founded. The keyword here is package. The javap utility worked for the AlarmClock class because it was not a part of a package. That is, the AlarmClock class code did not have a package statement (SomePackageName) qualifier as the first statement of its source. The Clock class did have a package statement. The javap utility requires that you fully qualify a class when it is a part of a package, as I demonstrate in Figure 4. Such qualification is not necessary when you want to see documentation for a packaged class. For example, Figure 5 lists the API of IBMs Java Toolbox for the AS/400 KeyedFile class.
Don Denoncourt Senior Technical Editor Midrange Computing
Displaying DASD Utilization
Q: Im trying to call the Retrieve System Status (QWCRSSTS) API in a CL program to display the percentage of DASD utilization used. The problem is that every time I run the program, I get the error message, Receiver variable too small to hold result (MCH1210 message identifier). Willy Tamayo Makati, Metro Manila, Phillipines
A: I had the same problem trying to access the percentage of Auxiliary Storage Pool (ASP) utilized. This problem occurred because I used a field defined as packed 3,0. What I
should have done was use a field defined as packed 7,0 because the data from the API is returned in a field defined as binary 4 and the value returned is 10,000 times the actual percentage. For example, a value of 850883 means 85.0883 percent. A field defined less than packed 7,0 just wont hold the result, hence the error message. Try using the CL example in Figure 6
Chuck Pence
Restarting the RSTLIB During CISC-to-RISC TEST System
When youre performing the Restore Library (RSTLIB) option from the UPGRADE2 menu (option 72 and then option QR040 to Restore User Information) and something goes wrong, you must restart the RSTLIB option. The commands given in Chapter 26 of the CISC-to-RISC Upgrade Roadmap under the topic Recovering from an Error While Restoring Libraries may not be correct in every situation, and restart may be difficult. Heres an easier way to do your restart:
1. Run the command CHKTAP Device(tape device) Endopt(*rewind) for the volume that contains the beginning of the SAVLIB *NONSYS created by the QP150 procedure. The first file to be used for the restart is QFILE.
2. On the TEST RISC system, delete the library that did not finish being restored.
3. Use the UPGRADE2 menu, option 72, and select option QR040 for the restart.
4. Specify the command prompting YES and messages *BREAK.
5. When the command to RSTLIB *NONSYS prompts you, move down to the Starting Library (STRLIB) parameter and key in the name of the library that did not get restored for the Restart Library. The system will read in the QFILE and then ask you to mount the tape with the library name specified on the Restart Library parameter. The restore procedure will then continue as if the process were never interrupted.
Dan Herron Houston, Texas
Using a Subfile as a Work File in Batch
Normally, you wouldnt even consider using a display file in a batch program. After all, where is the batch job going to resolve the display device to? The default is *REQUESTER, and once it is submitted to batch, the submitting display device is no longer available. Even if it were, chances are good that the allocating of that device would fail because its probably already in use, displaying some other application or menu. So, how can you use a display file in a batch program?
The trick is to override your display device to one that is not allocated (but it must be varied on). For example, a terminal that is sitting idle with just the sign-on screen being displayed is a good candidate. The code in Figure 7 shows you how to run your interactive program in batch. You will need to pass it the name of the display device to override to, the name of the program to be run, and the name of the display file used by the program. In this example, I use display device session ITPC03S1 to submit the job, passing the program a display device name of ITPC03S2, a program name of MY_PGM and the display file for that program called MY_PGMD. To submit the interactive job to batch, enter the following from the command line at session (ITPC03S1):
SBMJOB CMD(CALL PGM(PROGRAMCL) PARM(ITPC03S2 MY_PGM MY_PGMD))
Now, I can have the interactive program running in batch and let it write to my subfiles or any other display fields.
Load
Why would you want to do this? You could embed some logic in the program to see if it is running interactively or in batch. If its running in batch, when the normal processing is occurring, (i.e., writing records to a subfile, for example), you could have the program pass that information to another program or write it to a database. This procedure offers an interesting way to use interactive programs in batch with minimal recoding.
Tom Conover Los Angeles, California
Spice Up Your Windows!
Pop-up windows are great things in applications, but sometimes they need to be spiced up. One way of doing this is to place headings and comments in the border of the window rather than within it (see Figure 8). Additionally, headings and comments can have different color and display attributes from the border that contains them. DDS has special keywords to allow you to do this. The DDS that causes the window heading to be displayed within the Window surround is as follows: WDWTITLE((*TEXT Put your Title Here) *CENTER *TOP (*COLOR RED))
Notice the use of the Color parameter. This lets you add colors to the title. Titles can be positioned at the top or bottom of the window as well as left or right justified. You can even use the reverse image and blink attributes! Go for it! Make your windows a little more exciting!
Allan M. Telford Distribution Service Technologies Irvine, California Figure 1: Determining the version and release level of OS/400 Figure 2: This code can be used to send commands as request messages
DCL VAR(&VRM) TYPE(*CHAR) LEN(9)
RTVOBJD OBJ(QSYS) OBJTYPE(*LIB) SYSLVL(&VRM)
PGM PARM(&CMD)
DCL VAR(&CMD) TYPE(*CHAR) LEN(2000)
DCL VAR(&MSGKEY) TYPE(*CHAR) LEN(4)
SNDPGMMSG MSG(&CMD) TOPGMQ(*EXT) MSGTYPE(*RQS) +
KEYVAR(&MSGKEY)
RCVMSG PGMQ(*EXT) MSGTYPE(*RQS) MSGKEY(&MSGKEY) +
RMV(*NO) MSG(&CMD)
ENDPGM
PGM
DCL VAR(&APIDTAFMT) TYPE(*CHAR) LEN(8) +
VALUE('RTVQ0100') /* API data formt */
DCL VAR(&APIDTALEN) TYPE(*CHAR) LEN(4) +
VALUE(X'000007D0') /* API data length: +
2000 */
DCL VAR(&APIDTARTV) TYPE(*CHAR) LEN(2000) /* +
Retrieved API data */
DCL VAR(&APIERRCD) TYPE(*CHAR) LEN(4) +
VALUE(X'00000000') /* API error code (no +
data returned) */
DCL VAR(&APIMSGKEY) TYPE(*CHAR) LEN(4) /* No +
message key */
DCL VAR(&APIMSGTYP) TYPE(*CHAR) LEN(10) +
/* Request message type */
DCL VAR(&BYTESAVL) TYPE(*DEC) LEN(5)
DCL VAR(&BYTESRTN) TYPE(*DEC) LEN(5)
DCL VAR(&CMD) TYPE(*CHAR) LEN(256)
DCL VAR(&CMDLEN) TYPE(*DEC) LEN(5)
/* Set to retrieve info on last request message ***/
CHGVAR VAR(&APIMSGTYP) VALUE('*LAST')
CHGVAR VAR(&APIMSGKEY) VALUE(' ')
NEXT:
CALL PGM(QMHRTVRQ) PARM(&APIDTARTV &APIDTALEN +
&APIDTAFMT &APIMSGTYP &APIMSGKEY &APIERRCD)
CHGVAR VAR(&BYTESAVL) VALUE(%BIN(&APIDTARTV 1 4))
CHGVAR VAR(&BYTESRTN) VALUE(%BIN(&APIDTARTV 5 4))
IF COND((&BYTESAVL *EQ 8) *AND (&BYTESRTN *EQ +
0)) THEN(GOTO CMDLBL(END))
IF COND(&BYTESRTN *GT 0) THEN(DO)
CHGVAR VAR(&CMDLEN) VALUE(&BYTESRTN - 40)
CHGVAR VAR(&CMD) VALUE(%SST(&APIDTARTV 41 &CMDLEN))
ENDDO
ELSE CMD(CHGVAR VAR(&CMD) VALUE(' '))
/* Variable &CMD now contains a command or blanks */
/* set to get previous messages */
CHGVAR VAR(&APIMSGTYP) VALUE('*PRV')
CHGVAR VAR(&APIMSGKEY) VALUE(%SST(&APIDTARTV 9 4))
GOTO CMDLBL(NEXT)
END:
ENDPGM C:WorkMCJulyClock> javap Clock.Clock
Compiled from Clock.java
public class Clock.Clock extends java.lang.Thread {
public Clock.Clock();
public void run();
public void killClock();
public int getHour();
public int getMinute();
public void setMinute(int);
public void setHour(int);
protected void resetToSystem();
}
Figure 3: The QMHRTVRQ API can retrieve commands previously executed during a job Figure 4: Using javap to display a class from a package
C:WorkMCJulyClock> javap com.ibm.as400.access.KeyedFile
Compiled from KeyedFile.java
public synchronized class com.ibm.as400.access.KeyedFile extends
com.ibm.as400.access.AS400File implements java.io.Serializable /* ACC_SUPER bit set */
{
static final long serialVersionUID;
public static final int KEY_EQ;
public static final int KEY_GT;
public static final int KEY_GE;
public static final int KEY_LT;
public static final int KEY_LE;
public com.ibm.as400.access.KeyedFile();
public com.ibm.as400.access.KeyedFile(com.ibm.as400.access.AS400,java.lang.String);
public void deleteRecord(java.lang.Object[]);
public void open(int, int, int);
public void positionCursor(java.lang.Object[]);
public void positionCursor(java.lang.Object[], int);
public void positionCursorAfter(java.lang.Object[]);
public void positionCursorBefore(java.lang.Object[]);
public com.ibm.as400.access.Record read(java.lang.Object[]);
public com.ibm.as400.access.Record read(java.lang.Object[], int);
public com.ibm.as400.access.Record readAfter(java.lang.Object[]);
public com.ibm.as400.access.Record readAll()[];
public com.ibm.as400.access.Record readBefore(java.lang.Object[]);
Public com.ibm.as400.access.Record readNextEqual();
public com.ibm.as400.access.Record readPreviousEqual();
public void update(java.lang.Object[], com.ibm.as400.access.Record);
public void update(java.lang.Object[], com.ibm.as400.access.Record, int);
static static {};
}
DCL VAR(&RCVDTA) TYPE(*CHAR) LEN(067) /* +
Receiver var for API */
DCL VAR(&RCVLEN) TYPE(*CHAR) LEN(4) +
VALUE(X'00000043') /* &rcvdta is 067 +
bytes */
DCL VAR(&RESETO) TYPE(*CHAR) LEN(10) +
VALUE('*YES ') /* Reset Statistics +
Opt */
DCL VAR(&FMTNAM) TYPE(*CHAR) LEN(08) +
VALUE('SSTS0200') /* Fmt name for API rqs */
DCL VAR(&ERRSTS) TYPE(*CHAR) LEN(08) +
VALUE(X'0000000800000000') /* Err code +
struc */
DCL VAR(&PCTASP) TYPE(*DEC) LEN(7) VALUE(0) /* % +
System ASP used */
/* get system status : DASD percentage */
CALL PGM(QWCRSSTS) PARM(&RCVDTA &RCVLEN &FMTNAM +
&RESETO &ERRSTS)
CHGVAR VAR(&PCTASP) VALUE(%BIN(&RCVDTA 53 4))
Figure 5: Using javap over a packaged class does not require qualification Figure 6: Using the QWCRSSTS API to retrieve DASD utilization
PGM PARM(&DEVD &PGM &DISPLAY)
DCL VAR(&DEVD) TYPE(*CHAR) LEN(10)
DCL VAR(&PGM) TYPE(*CHAR) LEN(10)
DCL VAR(&DISPLAY) TYPE(*CHAR) LEN(10)
DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(512)
DCL VAR(&MSGF) TYPE(*CHAR) LEN(10)
DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10)
DCL VAR(&MSGID) TYPE(*CHAR) LEN(07)
MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(FWDMSG))
OVRDSPF FILE(&DISPLAY) DEV(&DEVD)
CALL PGM(&PGM)
RETURN
FWDMSG:
RCVMSG MSGTYPE(*EXCP) MSGDTA(&MSGDTA) MSGID(&MSGID) +
MSGF(&MSGF) MSGFLIB(&MSGFLIB)
SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
MSGDTA(&MSGDTA) MSGTYPE(*ESCAPE)
ENDPGM
Figure 7: Running an interactive program in batch
Figure 8: Spice up window titles
|
LATEST COMMENTS
MC Press Online