A z/TPF transaction example
This section presents an example transaction that is followed through the system. Some of the coding details have been simplified for the purposes of discussion. Many of the C functions used in coding this example are further discussed in z/TPF application program interface functions.
- LOGI CRED
- Step 1
- The CCP gives control to a system program called OPZERO, which
performs 2 principal functions.
- OPZERO allocates an ECB from the ECB area and initializes it as an ECB. This block will be associated with this message (entry) throughout its life in the system. The ECB will be passed to all processing programs. Later, this section discusses in detail the function and format of the ECB because it is the key facility by which the application interfaces with the z/TPF system and controls its processing.
- OPZERO gets a main storage block into which it formats the input message and stores the address of the message block in the ECB at data level 0. The ECB contains references to 16 data levels (level 0–F). The data levels are a series of slots used to store pointers and control information for data blocks. No priority or nesting is implied by the use of the term level. All levels may be used to suit the needs of the application. However, to simplify interfaces, certain conventions have been established about the use of specific levels. One of these conventions is that the input message is passed to the application on data level zero.
- Step 2
- OPZERO passes control to the communications source processor (COMM
SOURCE), whose principal function is to determine the intended destination
of the message and to create the routing control parameter list (RCPL).
The RCPL, like the ECB, will be associated with this entry throughout
its life in the system; it defines the origin and destination of the
message as well as descriptive information to facilitate routing and
processing. COMM SOURCE stores the RCPL in the ECB work area at location
EBW000.
COMM SOURCE also retrieves a routing control block (RCB) or agents assembly area (AAA), or both, depending on what the application expects. (See Routing control block) By convention, the RCB address is placed in data level 3 of the ECB, while the AAA address is placed in data level 1. In a central processor complex with more than 1 instruction stream COMM SOURCE also may be used to determine the routing of the message to an application specific I-stream or to the I-stream determined by the system. This is done by a COMM SOURCE user exit. Finally, COMM SOURCE passes control to the log processor (assuming the terminal is not already logged to an application).
- Step 3
- The log processor in effect connects the inputting terminal to
application CRED. The log processor updates the slot for the terminal
in the WGTA table. If the terminal is an SNA logical unit, the resource
vector table (RVT) also is updated. The index value indicates the
connection and also points to the program to be activated to begin
processing the message for application CRED.
The log processor generates a message stating that the terminal has been successfully connected to application CRED and requests the z/TPF message router to send it to the requesting terminal. The details of how this is done are deferred to the next message.
- Step 4
- The terminal operator is now in a position to enter messages for
the credit verification application. Until the connection is terminated
all input from this terminal will be so routed. The operator enters
a message requesting credit against a specific account number for
a value of $75. For example:
/4247852601709 $75The first character (/) is an action code identifying the format and expected function of the message. Now assume for clarity in following the flow that the terminal is connected to a 3270 local line. Processing will begin as described in Step 1. It continues with Step 2 in creating the RCPL and retrieving the RCB. However, when COMM SOURCE looks at the WGTA slot for this terminal it finds that it is already connected to an application. The index value in the WGTA points to information in the application name table and the routing control application table, which supply the file address of the input message editor for application CRED. COMM SOURCE passes control to this program, which we will call CRC1. Figure 1 shows the conditions when CRC1 (the application) is activated.

- The ECB is in main storage, pointed to by register 9.
- The input message, formatted according to the am0sg structure, is in main storage, pointed to by data level 0 of the ECB.
- The routing control block (RCB) is in main storage, pointed to
by data level 3 of the ECB, and it is in hold status. Or,
- The agents assembly area (AAA) is in main storage, pointed to by data level 1 of the ECB.
- Both an RCB and an AAA are present in main storage as previously described.
- The RCPL, which specifies the origin of the message as the terminal address (LNIATA/CPUID) and the destination as CRED, is stored in the ECB at location EBW000.
- The object code for CRC1 is in main storage, pointed to by register 8.
Should this message come in from an SNA network, conditions would be identical except that there would be no RCB on level 3 (unless the application is RCB-dependent), and the origin field of the RCPL would be in SNA format (sequence number, resource ID/CPU ID).
- Step 5
- There are different procedures for assembler language programs
and C language programs.
For assembler language, after first determining that this is a normal new input message, CRC1 must edit the message and determine which function is being requested. The z/TPF system provides a data macro that defines the fields in the input message and allows the program to refer to it by symbolic tags. The data macro name is AM0SG.
Example:
By issuing the data macro statement, CRC1 indicates to the assembler that it intends to address the AM0SG record using register 2 as a base. The symbolic tags can be referred to by loading R2 with the pointer to the input message from level 0 of the ECB.AM0SG REG=R2The input message tokenization support macro BPKDC might be used, or the program could supply its own logic for the edit. In any case, CRC1 determines that the message is a valid standard request for credit.
For C language, after first determining that this is a normal new input message, CRC1 must edit the message and determine which function is being requested. CRC1 uses the scanf function to read the data in. The scanf function locates and then parses the input message into an account number and an amount and returns the number of fields that were successfully converted and assigned. Note that the gets function must be implemented for the scanf function to work properly. The scanf and gets functions are not implemented according to the ANSI standard. See the z/TPF C/C++ Language Support User's Guide for details on scanf and gets.
Alternatively, the C language parser (IPRSE_parse) can be used in this example.
Example:
For the purposes of this discussion, assume that the message is a valid standard request for credit.rc = scanf("/%[0123456789] $%d", acctnbr, &amount); - Step 6
- The program then retrieves the negative credit file, which resides
on the fixed file. The fixed file is a DASD file area assigned permanently
to specific functions or record types, as opposed to the dynamic pools,
which may be used repeatedly for various purposes. There are many
types of records on the fixed file, but the z/TPF system file access
routines see it as one file. Therefore, before requesting the z/TPF system to retrieve
the negative credit file record you must supply its ordinal number
(relative record number) in the entire fixed file. The application
only knows the ordinal number in the negative credit file. To resolve
this, all records on the fixed file are assigned a record type, identified
by a symbolic name.
The z/TPF system provides an index table and utility program called FACS, which, when given the symbolic record type and ordinal number in that type, will calculate the ordinal number in the entire fixed file. Hereafter, ordinal number in the entire fixed file will be referred to in this information as the symbolic file address.
Assembler program CRC1 calculates the ordinal number of the desired negative credit file record and transfers control to FACS, supplying this ordinal number, the symbolic record type (for example: #VD1VD), and the location in the file address reference word (Step 8) at which the symbolic file address is to be stored.
ENTRC FACS Pseudo logic for credit application segment CRC1.
-------------------------------------------------
Edit input message into acct# and amount.
Compute Negative file record address on level D2. /* FACS or face_facs */
Retrieve Negative file record on level D2. /* finwc or find_record */
If acct# is in Negative file record,
Indicate negative response.
Unhold RCB. /* unfrc */
Else,
Get floor limit address /*GLOBZ or glob */
If floor limit is exceeded,
Indicate floor limit reject.
Unhold RCB. /* unfrc */
Else,
Release message block (D0). /* crusa */
Release Negative file record block (D2).
Release RCB (D3).
Unhold RCB. /* unfrc */
Call CRC2. /* Process activity file */
Get block for output message on level D6. /* getcc */
Edit output message in block on level D6.
Build output message RCPL.
Request send output message. /* routc */
Exit.
Program CRC1 calculates the ordinal number of the desired negative credit file record and calls FACS, supplying this ordinal number, the symbolic record type (for example: #VD1VD), and the location in the file address reference word (Step 8) at which the symbolic file address is stored.
ENTRC FACSIn C language, include the header file <tpf/tpfio.h> to declare the FACS function. FACS takes a single parameter, a pointer to a TPF_regs structure (defined in <tpf/tpfregs.h>). The fields of the TPF_regs structure (R0, R6, and R7) imitate the assembler interface to FACS.
The z/TPF C library also provides a face_facs function, which is a more intuitive interface for calculating a fixed file address.
#include <tpfio.h>
#define VD1RI "#VD1VD "
#define VD1RI_ordinal 10
⋮
unsigned long rtnord ; /* return ordinal */
⋮
/*
** Locate negative credit record (VD1VD) for account on fixed file.
*/
int ffrc = face_facs(VD1RI_ordinal,VD1RI,0,D2,&rtnord) ;
/* Calc fixed file address */
- Step 7
- The assembler program FACS or the C language face_facs function calculates the symbolic file address of the desired negative credit file record, stores it at the location specified, and returns control to CRC1.
- Step 8
- CRC1 now can request that the z/TPF system read the
record from file storage into main storage. This is done with the
FINDC macro (assembler language) or the find_record (C language)
file reference function. Before the function is called, a data level
must be chosen and the FARW set up. The FARW is an 8-byte control
field for file activity associated with each ECB data level. The low
order 4 bytes will contain the symbolic file address because FACS
or face_facs placed
it there in Step 6. The high order 4 bytes of the FARW are for data integrity. Normally, the requesting program must specify the record identification as an argument in the function call so that it will be entered in to the high-order 2 bytes of the FARW. The record identification will also appear in the header of the record in file storage. (This record identification is assigned to your application by an application or data base designer.) CRC1 enters the ID (for example, VD) and then requests the z/TPF system to read the record into level 2 and return control to CRC1 only after the I/O is complete. The coding for this form of the macro is:
FINWC D2,ERROR1ERROR1 is the symbolic tag in CRC1 to which control will be returned if there is any abnormal I/O condition.
For C, the find_record function call requires the following arguments:
- level
- The data level of an available FARW and CBRW for use by the system.
- address
- A pointer to the file address of the record to be retrieved; NULL if the FARW has been preinitialized.
- ID
- A 2-character string that must match the identification characters
in the record to be retrieved; RECIDRESET if the identification
field has been preinitialized. If the requested ID does not match
the record's identification characters, the ECB error fields
will indicate an identification check failure and control will return
to the application at I/O completion. No comparison will be made if
the identification field is zero (
'\0'). - rcc
- An unsigned character that must match the record code check (rcc) byte in the record to be
retrieved. If the requested rcc does not match the record's rcc, then the ECB error fields will
indicate an identification check failure and control will return to the application as previously
described for the ID argument. If rcc is zero (
'\0'), then no comparison will be made. - type
- What the record's hold status will be after I/O completion, either NOHOLD or HOLD.
CRC1 requests the z/TPF system to read the record into level 2 and return control to CRC1 only after the I/O is complete. An example of the coding for this form of the function is:vd1ptr = find_record(D2, NULL, "VD", '\0', NOHOLD); - Step 9
- The z/TPF system obtains an appropriate storage block and reads the negative credit file record into main storage, then returns control to CRC1. Assume that there are no errors or integrity failures.
- Step 10
- CRC1 searches the record for the input account number. Assume it is not found; the account is, therefore, in good standing, and the next step proceeds.
- Step 11
- The dollar value requested in the message must now be checked against a floor limit; requests
greater than the floor limit are rejected. The floor limit is only a 4-byte field, but must be
accessed by every entry (except those found in the negative credit file). For performance
considerations, it should be stored in an area accessible to all entries but not requiring a file
retrieval. For such requirements, the z/TPF system
maintains the format-1 global area.
The format-1 global area is a section of main storage accessible to all users by executing the appropriate functions. It can be used for any type of data requiring quick access, from miscellaneous constants to main storage resident data records.
By issuing one macro (GLOBZ), the assembler application program can load the base register and have access to any field in the first 4096 bytes of the global area. These 4096-byte format-1 global areas are unique to each I-stream. If there are any shared resources in these areas, you must provide a way to handle the synchronization of accessing or updating these resources. Therefore, it is a common practice to place, in the first 4096 bytes, address pointers to the remaining format-1 global area.
Example:GLOBZ REGR=R5The system loads register 5 with the base of the format-1 global area. By convention, all tags in the format-1 global area (used by assembler programs) begin with the @ character. For example, the floor limit might be stored in a field labeled @CFLTH. CRC1 now compares the input value with the global field; it finds that the request value is smaller than the floor limit and proceeds to the next step.
The c_globz.h C language header file contains symbolic tags and displacements for miscellaneous data fields and pointers to records in the format-1 global area. By calling one function (glob), the application program can examine any format-1 global field or record.
By z/TPF convention, all tags in the format-1 global area begin with the underscore character (_) for C language code; however, it is important to note that when the same tags are referenced in assembler code, the corresponding names must begin with the @ character. Other characters in the tag name are converted to lowercase. For example, the floor limit might be stored in a field labeled _cfltn for C language access and atcfltn for assembler access.
CRC1 now compares the input value with the global field; it finds that the request value is smaller than the floor limit and proceeds to the next step.
cfltn = glob(_cfltn); /* Check against global limit */
if(amount > *cfltn)
msgnexit("OVER FLOOR LIMIT\n");
- Step 12
- The next functional requirement is to check the requesting account
number for excessive activity on this date and during this week.
For this purpose an activity file is maintained. All processing cannot be contained in one segment so that activity file processing will be handled by program segment CRC2.
Before passing control to CRC2, however, CRC1 will return any system resources not in use or imminently planned for use. All system resources such as main storage blocks and file pool addresses should be returned promptly. Since many ECBs operate concurrently, failure to do this could be a significant drain on system performance and require excessive resource allocation.
CRC1 finds three items no longer required:- The input message block—the message has been edited and the account number and dollar value stored.
- The negative credit file—it has already been searched.
- The RCB—it was passed to CRC1 or CRC1 on activation, in hold status, but the application design does not require it for update or terminal lock-out. (See Routing control block.)
These blocks are returned to the system with the crusa function, which requires only the number of levels to be released and the names of the data levels themselves.
Because CRC1 expects to be reactivated after activity file processing, it passes control to CRC2 with the return option.
Example:ENTRC CRC2Figure 3 shows the logic flow for CRC2.
/*
** Discard input message, VD1VD record block, and RCB
*/
crusa(3, D2, D3, D0); /* Release core blocks */
unfrc(D3); /* Unhold the RCB file record */
Pseudo logic for credit application segment CRC2.
-------------------------------------------------
Compute Activity file record address on level D4. /* FACS or face_facs */
Retrieve and HOLD Activity file record on level D4. /* fiwhc or find_record */
If acct# is in Activity file record,
Update usage counts.
Else,
If there is room for acct# in Activity record,
Add acct# and set usage count to 1.
Else,
Get block for chained Activity record (D5).
Get file address for chained record (D5). /* getfc */
Chain new file address to prime record.
Initialize new Activity file record.
Add acct# and set usage count to 1.
File chained record (D5). /* filec */
File and UNHOLD prime record (D4). /* filuc or file_record */
Create CRC3 to record transaction log. /* cremc */
Return to caller.
- Step 13
- The next functional requirement is to check the requesting account
number for excessive activity on this date and during this week. For
this purpose an activity file is maintained. The activity file also
resides on the fixed file. CRC2 calculates the ordinal number of the
required activity record and calls FACS (or face_facs for C language),
passing the ordinal number, the activity file record type (for example,
"#VU1VU "), and the level 4 FARW as the location for storing the symbolic file address.
#define vu1vu "#VU1VU "
#define vu1vu_ordinal 100 struct TPF_regs regs ;
⋮
/*
** Check if there has been excessive activity for this account.
** Locate credit activity record on fixed file.
*/
regs.r0 = vu1vu_ordinal /* Ordinal number */
regs.r6 = (long) vu1vu; /* Record identification (type) */
regs.r7 = (long) &(ecbptr()->ce1fa4); /* Data level */
FACS(®s); /* Calculate record address */
- Step 14
- The FACS macro (or the face_facs function) calculates the symbolic file address of the activity record, stores it in the FARW of level 4, then returns control to CRC2.
- Step 15
- CRC2 enters the record identification for the activity file in the FARW, then calls a find-wait-and-hold form of the find_record function to read the record into data level 4.
FIWHC D4,ERROR2
if(!(vu1ptr = find_record(D4, NULL, "VU", '\0', HOLD)))
serrc_op(SERRC_EXIT,00x1238, "ACTIVITY FILE FIND ERROR",NULL);
/* If no prime exists, error. */
To assure data integrity and proper sequencing of updates
when modifying a file, programs intending to update a record must
ensure that the record is not currently being updated by another program.
The program does this either by: - Holding the record itself
- Holding the first record in a chain that includes the record to
be updated.
A chain is a series of records, each with an address pointer to the next record in the series. The first record in the chain is usually called the prime record. This technique will not work if the record to be updated is part of more than one chain. See Record hold facility for further details.
- Step 16
- CRC2 must add the item to the file and note its use today. However, the record is full and no records are chained from it. A new record must be created, chained to the first record (now called the prime record), and filed in the random pool. Unlike the fixed file, the random pool is a section of DASD storage assigned to no specific record type. It is a dynamic pool of file blocks from which any entry may request a record from the z/TPF system and return it when no longer required. The pools are divided only by record size and usage classification. (Refer to Random pool file area).
- It requests from the z/TPF system a file address
from the random pool and a main storage block in which to build the
record. The GETFC macro in assembler language or the getfc function in C
language obtains the file pool address and storage block. Although
transparent to the application, this record identification is an index
into the RIAT and tells the z/TPF system the pool
type from which to take the address. The application need know only
the record identification of the it is building. The size of the acquired
working storage block is determined by the attributes associated with
the record identification.
The ID (“VU” in this example) is stored in the header of the new block on level 5 and in the FARW for level 5. The ID is the same because this block is a chain extension of the prime record, whose identification is VU. All records chained together have the same record identification. (The record identification is assigned to the application by an application designer.)
Assembler language example:GETCC D5,L2 Request a 1055-byte (L2) block on level 5C language example:
The c language arguments and descriptions are as follows:vu1ptr->vu1fch = getfc(D5, GETFCOVERF, "VU", GETFCBLOCK, GETFCSERRC); /* model: getfc(level,type,ID,block,error)- level
- The data level.
- type
- The pool type and size to be used with the ID argument.
- ID
- A pointer to a 2-character record identification that will be used in scanning the record identification attribute table (RIAT).
- block
- Whether or not a block of working storage should simultaneously be obtained.
- error
- Whether or not control should be returned to CRC1 in the event of an error.
- CRC2 store upon return the new random pool address returned by the z/TPF system in the FARW for level 5 in the forward chain field of the prime record on level 4.
- CRC2 initializes the chain record and enters the new data item and item count of 1 in the new record.
- CRC2 files the newly created chain record and then files and unholds the prime record.
FILEC D5 Files chain record from level 5.
FILUC D4 Files and unholds prime record from level 4. if (newpool) /* If we got a pool, */
holdstatus = NOHOLD; /* D4 record is not locked */
/* File the D4 record block. */
file_record (D4, NULL, NULL, '\0', holdstatus);
if (newpool) /* If we got a pool, */
file_record (D5, NULL, NULL, '\0', UNHOLD);
/* file the prime record. */
- Step 17
- The user wishes to keep a transaction log containing a copy of the input values (account number and dollar value) for each request for which credit is granted. The items are to be blocked in a 1055-byte main storage block and then written to the real-time tape (RTA tape). However, the user does not want to keep the customer and operator waiting on line for this processing, since all key decisions that relate to approving the credit have been made. CRC2, therefore, creates a separate entry to process the transaction log independently, passing to it the required log data and specifying the program to be called for initial processing (CRC3). This is done with a create macro in assembler language or a create function in C language, and CRC2 uses a form of the function that requests an immediate activation of the new entry.
LA R14,48 Number of bytes to pass to the new entry
LA R15,EBW020 Location of data to pass
CREMC CRC3 Program to be activated to process the new entry
cremc(sizeof(packedacct), cremargs, CRC3);
/* Create entry CRC3 */
- Step 18
- CRC2 processing is now complete. In assembler, it issues a BACKC
macro, which returns control to CRC1. In C language, control
is returned by a return statement. Note that it is not necessary to
return the main storage blocks on levels 4 and 5 because the z/TPF system does this
automatically unless instructed not to do so.
All that remains is to send a message to the terminal operator indicating that the credit may be granted.
The first requirement for an assembler language program to send a message is to build the message block. The first or only segment of the message must be in main storage, attached to any level of the ECB. CRC1 requests a 127-byte block from the z/TPF system on level 6. The same data macro (AM0SG) is used for output and input messages. The data macro is issued, and register 3 loaded with the pointer from level 6.GETCC D6,L0 AM0SG REG=R3 L R3,CE1CR6The header of the record is initialized with the record ID (‘OM'), the forward chain field is zeroed, and the character count and text are entered.
In a C language program, CRC1 uses the puts function to output the message to terminal.
- Step 19
- CRC1 builds the output RCPL for assembler language.
The puts function is not ANSI or ISO compliant. Its action is defined by site installation. The input RCPL, received from the COMM SOURCE program at EBW000, has not been disturbed and contains the necessary data for output. The first two fullwords containing destination and origin are exchanged; destination becomes the LNIATA and CPU ID of the terminal, origin becomes CRED. The control field bits are modified as described in the DSECT RC0PL for assembler language or the c_rc0pl.h header for C language.
Assembler language program CRC1 loads register 3 with the address of the RCPL (EBW000) and requests the z/TPF system to send the message by issuing the ROUTC macro.
Example:ROUTC LEV=D6,LIST=R3This specifies that the message is in core at level 6 and register 3 points to the RCPL.
- Step 20
- Processing for the entry is now complete; the application has no further function to perform. CRC1 stops by calling the EXITC macro in assembler language or the exit function in C language. The z/TPF system removes the entry from the system and releases the main storage block containing the ECB. If any main storage blocks are attached to the ECB, they are released at exit.
The preceding process by no means presents a definitive review of all application facilities. It is meant to be illustrative and to give a practical framework into which to fit the detailed descriptions that follow.