Module D Module B Module C Module A Service Program A
Key Information Regarding Module Creation Header SpecificationMost modules are created with the NOMAIN keyword. Prototype DefinitionThese are placed in the global D Specs define how the parameters are expected in the procedure. Exported proceduresExported procedures are callable entry points. Which means that external programs can use the procedure. Non-exported procedures can be used by other procedures in the module but cannot be called by external programs.
Creating Modules To create modules in PDM, use option 15. From the command line, use the CRTxxxMOD commands. A module can consist of a single procedure or many procedures. Generally a module is created in a single source member and procedures that need to access each other or otherwise related should be in the same module. Modules can be accessed by other independent modules by using the IMPORT keyword on the prototype for the procedure calls. I recommend having a single module for interrelated procedures instead of using IMPORT. Module creation does not allow you to specify activation group attributes like programs. Modules inherit the attributes from the program or service program it is bound to. Modules do not have to be part of a service program. They can be added to programs individually by using the CRTPGM command or by adding them using the CRTBNDxxx command.
Module A Displayed above is the Module A module. As stated previously, this module can be used to create program or service program objects. One or more modules can be created & bound together to form a service program. To use the module for a program, a MAIN module must be created. The difference between a program object and a service program is that with a program there is only one point of entry, with a service program there can be many points of entry. So then Module A, B, C and D can be used to create a service program by binding them together using the CRTSRVPGM command.
Binding Binding can be performed 2 different ways. By specifying them individually on the CRTPGM or CRTSRVPGM command or by using binding directories. Specifying the modules individually makes the objects harder to maintain, since each time you have to recompile you have to remember to add all the modules on the CRTxxxx commands. Using binding directories makes the process much less prone to error. The binding directory contains a list of modules or service programs. A binding directory works much like a library list. The compiler looks through the service programs & modules for the defined procedures. To use the binding directory, you can add the BNDDIR keyword to the H spec of your program like so: BNDDIR(MYBNDDIR) You can also specify the binding directory to use on the CRTBNDxxx command at compile time, however, this brings back the issue of human error to the equation.
Creating A Binding Directory To properly construct a binding directory, you will have to create the directory & add the entries to the directory. Binding directories are created using the CRTBNDDIR command. After you have created the binding directory, you can add directory entries by using the ADDBNDDIRE command. As mentioned before, you can add individual modules or service programs. I prefer using service programs since they are, in essence, a collection of modules bound together, meaning easier access to your programs & easier maintenance.
Service Program Creation Service Program NameName desired for service program ModulesModules to include in the object Export Type*ALL will export all procedures defined with the EXPORT keyword, or specify a source file & member for export definitions Bind Service ProgramAllows you to bind other service programs to the one you are creating Binding DirectoryCan be used instead of specifying the service programs & modules to bind in the service program Activation GroupYou can specify a named activation group or use *CALLER (preferred)
Service Program Creation (contd) Modules can be specifically listed or added by using a binding directory. Export type can be either *ALL, or from a source member of type BND. Using a source member is preferred, since you can specify your own signature for the service program & include only the procedures you need exported from the module. Also using export *ALL will place the procedures in whatever order it wants to. Since the service program uses a numeric ordinal position to determine where a procedure is in the service program, this makes adding exported procedures more difficult since the service program ordinal positions can change. Using export source members, you tell the compiler what order the procedures are defined. Activation group can be either a named activation group or *CALLER. *CALLER is preferred with service programs, since you dont know when you create the service program where the service program might be called from. This prevents issues with open data paths trying to span multiple activation groups.
Export Binder Source To create an export binder source, create a source member of type BND. Edit the source member using SEU, EDTF or WDSC. A sample binder source is shown below: The first line is always STRPGMEXP (start program export list). This is where you define your signature. If no signature is specified, the compiler will generate a generic signature. Generic signatures can cause issues with adding modules, etc. and is not recommended. The EXPORT keyword defines the exported procedures in the service program you are creating. The source is always terminated by the ENDPGMEXP (end program export list) keyword.
KRCONTROL Processing Service Program The KRCONTROL processing service program is named CONTROLSP. Currently the service program consists of one module, RTVCTLVAL. This module contains a non-exported procedure & 3 exported procedures. This module will retrieve control values from the control file & update control file values. The reason I chose to name the service program is due to the fact that other modules may be necessary & will have to be bound to the service program at some future date. Below is the header specification for the RTVCTLVAL module. Notice that this is a NOMAIN module, meaning that this module alone cannot be compiled into a program by itself. It must be bound to a program either individually or as a service program in order to be used. OPTION(*NODEBUGIO) is a standard I use to make debugging less painful.
KRCONTROL Processing Service Program The File specification is displayed below. Notice that the file is defined as user open. The file opening is controlled by the Initialize_SP procedure which well look at later on in the module. Next, we define our non-exported prototype: This procedure can be used only in this module & cannot be used by external programs.
KRCONTROL Processing Service Program Next well define our global variables which can be used in all procedures in the module. Our exported prototypes reside in copybooks that can be referenced by our calling programs to ensure parameter consistency. The contents of the copybook are presented on the next few slides.
KRCONTROL Processing Service Program This prototype defines the parameters that are necessary to successfully call the RTVCTLVAL procedure in the module. When calling this procedure the CONST parameters can be passed as a constant value since the procedure will use them as read-only parameters & cannot be changed by the procedure. Later well illustrate this using a program which calls this procedure.
KRCONTROL Processing Service Program This prototype defines the parameters that are necessary to successfully call the UPDCTLVAL procedure in the module. This procedure only receives CONST type parameters. None of these values will be modified by the procedure.
KRCONTROL Processing Service Program This prototype defines the parameters that are necessary to successfully call the CLOSE_CONTROL_FILES procedure. This procedure accepts no parameters but returns an indicator value. Use of this will be shown in the calling program well cover later.
KRCONTROL Processing Service Program All procedures begin with a Procedure Specification and must contain the procedure name and EXPORT/IMPORT keywords, if needed, as shown below: All procedures end with a Procedure Specification as shown below: The procedure name is not necessary on the ending P specification, but makes it clearer which procedure is ending.
KRCONTROL Processing Service Program After the beginning Procedure specification, the prototype interface must be defined. A prototype interface is basically defining the parameters that are to be received from the calling program or procedure. With prototype interfaces, the variable names are required, whereas on the prototype definition, the names are for description only.
KRCONTROL Processing Service Program The next item is to define any local variables, if any are needed. The local variables are only usable by the procedure they are defined in. Now that the Definition specifications are complete for this procedure, its time to look at the executable code.
KRCONTROL Processing Service Program First, the procedure checks to see if the control file has been opened. If not, it calls the INITIALIZE_SP procedure to open it. The OPENED variable is our globally defined indicator field. In the INITIALIZE_SP procedure, the indicator will be set to *ON after the file has been opened to prevent additional calls to the RTVCTLVAL procedure from trying to open the file again.
KRCONTROL Processing Service Program Next, the procedure looks for the values to retrieve. If no matching values are found, *NONE is placed in the first element of the return values array. If values are found, they are loaded into the arrays for return to the calling program.
KRCONTROL Processing Service Program The begin procedure, prototype interface, local variables & key list section of the UPDCTLVAL procedure is shown below.
KRCONTROL Processing Service Program Like the RTVCTLVAL procedure, the UPDCTLVAL checks to determine if the control file is opened. If the file hasnt been opened yet, a call is placed to the INITIALIZE_SP procedure to open the file.
KRCONTROL Processing Service Program The received parameters are then used to chain to the control file. If the record doesnt exist, the new record is written to the control file. If the record already exists, the record is updated with the new value.
KRCONTROL Processing Service Program This is the INITIALIZE_SP procedure, which returns an indicator value to let the calling procedures know if the file was successfully opened.
KRCONTROL Processing Service Program Below is the CLOSE_CONTROL_FILES procedure. This procedure should be called from your program to close the control file at the end of processing.
KRCONTROL Processing Service Program Now that we have finished coding our module, the next step is to compile the module & create the service program. With our service program completed, well create our binding directory for the service program, so it will be there for our calling programs to bind with. Ok, now that we have our service program & binding directory, the module is no longer needed and can be deleted if you so desire. Next, well see how to leverage the service programs functionality within our calling programs.
Accessing The Service Program Procedures Well be looking at the KRPPCSEQ program which is used to retrieve the punch porter file sequence number for combined databases. Below is the Header specification, prototype & prototype interface: Notice that we have our binding directory & activation group attributes defined in the Header. This makes accurate compilation of the program much easier. This program receives a 10 byte character field called Combine.
Accessing The Service Program Procedures Well use our copybook to get our prototypes for the service program & define our variables for the program.
Accessing The Service Program Procedures Below is the call to the service programs RTVCTLVAL procedure. Since the CONST keyword is defined for the record type parameter we can simply pass the constant PPCOMBSEQ#. The Value & Desc fields are defined as arrays & are returned from the procedure. The RTNCOUNT is also returned & will contain the number of array elements populated by the procedure.
Accessing The Service Program Procedures Now that we have retrieved the values from the service program we can process the entries by using a loop until we reach the RTNCOUNT value.
Accessing The Service Program Procedures Lets take a closer look at the call to the UPDCTLVAL procedure. Since all the parameters for this procedure are defined as CONST, we could simply pass all constants to the procedure. For this program, we will pass the value of Combine, the PPCOMBSEQ# constant, the original value & description retrieved from the RTVCTLVAL procedure & the HldSeq value for updating the control file value.
Accessing The Service Program Procedures Last, but not least, we load the Combine parameter to return to the program which called KRPPCSEQ & we terminate the process. Notice that we call the CLOSE_CONTROL_FILES procedure to close the control file prior to setting on the last record indicator.
One MAJOR Gotcha To Avoid!!! Using OPTIONS(*VARSIZE) In the above prototype interface the RETURNDATA parameter is defined as 32767 Character with OPTIONS(*VARSIZE). While the options(*varsize) allows you to pass or receive data up to 32767a in most cases this procedure will be called using actual variables with a much smaller length.
One MAJOR Gotcha To Avoid!!! For instance, the calling program is passing a named data structure into the procedure. The data structure is defined as below.
One MAJOR Gotcha To Avoid!!! Since the DS is only 99 bytes long. The RETURNDATA should not access more than 99 bytes of memory. In the procedure, if you reference the entire RETURNDATA variables like this: You have just wiped out 32668 bytes of memory that may belong to this process & possibly others!!! The way to prevent this is to pass a RETURNLENGTH to the procedure as shown in the prototype interface & use it to determine how much of the RETURNDATA to populate like this: This will ensure that when you load the data to pass back to the calling program that only the memory you wanted to use is accessed & does not corrupt memory that you shouldnt have touched.
Downloads This powerpoint presentation & other tidbits are available for download at http://tommyholden.com under the My i link.http://tommyholden.com Other places to obtain assistance, information & just great insight: http://systeminetwork.com Join the mailing lists at Midrange.com http://midrange.com/lists.htm
Works In Progress ILEDOCS – The iSeries answer to javadocs Join the official forum at http://tommyholden.com/phpbb2 the official mailing list (big thanks ti David Gibbs for allowing us to setup this mailing list…) http://lists.midrange.com/mailman/listinfo/iledocs WRKSPL Just something Ive wanted for years. The ability to repeat options on a list of spooled files, etc. DBFINFO – Database Information Tool Uses APIs & other system goodies to retrieve all information about files on your system, no nightly refreshes of DSPxxx to outfile required. Everything is done dynamically & current. Not every shop can afford big money tools (like HAWKEYE, etc.) so this is a handy alternative.