Feb 1 ’05
Using the DB2 RRS Attachment Facility
Resource Recovery Services (RRS) provide the sync point services component of the z/OS Recoverable Resource Manager Services (RRMS). These sync point services implement two-phase commit across resource managers within z/OS, letting applications have a single recovery point for various data sources without requiring a transaction manager such as CICS. DB2 can participate as one of these resource managers; it provides an Application Programming Interface (API) to connect with programs that want to take advantage of RRS. Programs that use the RRS Attachment Facility (RRSAF) to connect to DB2 can use embedded SQL, issue DB2 commands, and use the Instrumentation Facility Interface (IFI) to collect performance information. Programs that run in stored procedure address spaces managed by Workload Manager (WLM) are required to use RRSAF, but may not issue RRSAF API calls.
So, why would you want to start using this when your current programs work fine without it? The answer lies in the flexibility of using RRSAF and the future of your development environments. Many programmers coming out of school have little or no experience with z/OS, don’t know what TSO is, and probably don’t even know COBOL. On the other hand, they usually know how to work in a Unix shell environment and we do have that available with Unix System Services (USS). Programs that use RRSAF to manage their connection to DB2 can run in TSO, USS, and batch environments with no modification.
Java applications running under WebSphere should already be using RRSAF for their DB2 connections. When strange things happen to the connections from these applications, you may even see RRSAF error messages in the WebSphere logs. Using RRSAF for DB2 connections supports inclusion of other resource managers, such as WebSphere MQ and CICS, in the unit of work.
The step involved in using RRSAF for most programs is easily encapsulated in a simple program that can be reused to establish the connection for each application program. You can create a simple “OpenDB2” program each of our programs calls to establish the connection; it issues the calls to program DSNRLI, which is the high-level interface program for RRSAF.
You must supply some additional information to the OpenDB2 program. This includes the DB2 subsystem name and the plan name that will be used to find the packages the programs will use. It’s helpful to standardize programs to accept both the subsystem and plan names as input parameters. Additionally, you can specify the correlation ID that DB2 will use when reporting performance information on your application. This can be accepted as an input parameter or generated internally by the OpenDB2 program.
After the call to OpenDB2, you can use embedded SQL statements in your programs just as you would in programs that use the TSO attachment facility. If you use only DB2 resources, then you can even use the standard SQL commit and rollback statements to control your units of work. To control a unit of work that includes other resources, you need to use the SRRCMIT and SRRBACK APIs within RRS. Units of work that involve multiple resource managers are called global transactions. You can use these calls for DB2-only transactions as well, since DB2 supplies its own version of the programs.
Building your applications then becomes a matter of following the correct steps. You include the call to OpenDB2 in your program. For the DB2 precompiler, you specify ‘ATTACH(RRSAF)’ as an option. The DSNRLI module should also be included in a link step that builds the load module for your application program. If you use the SRRCMIT and SRRBACK calls for global transactions, then you need to include the RRS modules’ library (SYS1.CSSLIB) before the DB2 library in your link step to make sure you pick up the correct version.
When your program processing completes, the RRSAF connection will be terminated without any need for you to take specific action. You can close the connection explicitly, but this is not necessary. Normal termination will result in your work being committed, while abnormal termination will result in a rollback.
Running RRSAF Programs
Programs that use RRSAF can run under TSO, USS, and as batch programs. This is the same program, not different versions for each environment. Under TSO, programs that use RRSAF run as executable programs directly without the use of the DSN command. In fact, you cannot run an RRSAF program using the RUN subcommand of DSN.
Under USS, you run your program simply by making it an executable program file and storing it in one of your file systems. Then, execute the program from a shell prompt as you would any Unix command.
In batch, use your EXEC card and specify “PGM=MYPGM” just like you would for a non-DB2 program. The return code from the program will translate directly into the condition code for your job step.
To simplify the application programs you write, you can program sample functions that implement the RRSAF calls to abend if any calls fail. This means that the programs can call the OpenDB2 function and, if it returns, the connection was successful.
The DB2 subsystem and plan names are input parameters to the programs to simplify migration from test to production without requiring code changes. This also provides the flexibility to run the programs using different schemas in your test environment. Remember that these parameters will need to be passed into the programs using slightly different syntax based on the execution environment.
Basic API Calls
The DSNRLI program acts as the interface for RRSAF and accepts a variety of parameters. The first parameter is always the function you want the interface to perform. This function is a text field that contains the name of the function you want performed. Establishing a connection to DB2 generally requires three calls to DSNRLI with functions of “IDENTIFY,” “SIGNON,” and “CREATE THREAD.” Each of these functions has a list of additional parameters that are required. All the functions also require output parameters that will receive the return code and reason code for the function call itself.
The first call, “IDENTIFY,” accepts the DB2 subsystem name as its primary input parameter. The input function string is always an 18-byte field and should include spaces as padding. An implementation of OpenDB2 in C would use the call shown in Figure 1.
The ribptr and eibptr fields will contain pointers to information blocks that you probably won’t need to reference. The termecb and startecb fields can be used to specify Event Control Blocks (ECBs) that will be posted when the DB2 subsystem stops and starts. The last parameter, GroupOverride, can contain “NOGROUP” if you want the subsystem name to be used to connect to a DB2 member subsystem that has the same name as a data sharing group. The second call, “SIGNON,” would look like Figure 2.
The CorrelationId contains the correlation name you want in your accounting records. The AcctToken is another field that will show up in the accounting records. The AcctInterval field contains either “SIGNON” or “COMMIT” and controls the frequency with which DB2 will cut accounting records for your application activity. To keep the number of accounting records to a minimum, just specify “SIGNON.”
The third call, “CREATE THREAD,” provides the plan or collection information necessary for DB2 to execute the programs used in the application. It looks like Figure 3. The plan name here should contain all the packages generated when the programs went through the DB2 precompile and bind processes. If you like, you can instead put a question mark in the plan name and specify a collection name or list of specific packages, but this will probably just lead to confusion, since most of us don’t manage our applications that way. The Reuse parameter should contain either “INITIAL” or “RESET” to indicate the action taken if another “SIGNON” call is issued. The default is “INITIAL” and should be used unless you want to get more complicated in your program design.
After each call, the results of the call in fnret should be tested to verify that the call itself worked, then the ReturnCode should be checked to ensure the call was successful. In diagnosing problems, it may be helpful to print the ReturnCode and ReasonCode contents if there’s a failure in any of the calls.
Managing Units of Work
Now that you have a function to let your programs connect to DB2, you’ll need to make sure your units of work are properly controlled. Programs that use only DB2 resources can just issue the SQL COMMIT or ROLLBACK statements. To play it safe, you can instead go ahead and code the calls to SRRCMIT and SRRBACK. The only parameter to these function calls is the integer return code. Here’s a sample commit:
fnret = srrcmit(&ReturnCode);
Implicit RRSAF Calls
DB2 for z/OS Version 8 lets you do all this without actually calling DSNRLI if you’re willing to take a few defaults. You lose a bit of control this way, but you may be able to convert more programs to use RRSAF without any code changes. Using the implicit method, you just precompile and link your program using the RRSAF settings and issue your embedded SQL statements as you would in a TSO attach facility program. When the first SQL statement is issued, the RRSAF module will take the subsystem name from the DSNHDECP module and do the “IDENTIFY” call. It will then take the program name and use that as the plan name for the “CREATE THREAD” call. The implicit connection skips the “SIGNON” call. #Sample Programs
You now have nearly enough information to code your own OpenDB2 function. To make it even easier to get started, you can access a sample program at www.db2expert.com.
The sample source code includes the db2rrsaf.c module. This contains a C version of OpenDB2 and a few helper functions. You must compile this into a library module that’s included during the link step of the programs that call the functions.
A CloseDB2 function is also included for programs that want to explicitly close their connection. You can see in the online sample that the calls required to disconnect are “Terminate Thread” and “Terminate Identity.” Before calling the CloseDB2 function, any open unit of work must be committed or rolled back or the close operation will fail.