gtpa2m2a | Application Programming |
There is an entry control block assigned to each input message or entry that defines all resources allocated to process that entry. The C data structure corresponding to the ECB is called eb0eb, and is defined in header file c$eb0eb.h. The macro, ecbptr, is used to obtain access to the ECB. Figure 19 shows 2 examples of using this macro. In the first example, pointer ecb is initialized to point to the current ECB. In the second example, amsg is a pointer data object that is assigned to point to the AM0SG record on data level 1. The ecbptr macro returns the base address of the ECB.
Figure 19. Using ecbptr to Access the Contents of ce1cr1
struct eb0eb *ecb; struct am0sg *amsg; |
The ecbptr macro is resolved by a single instruction. Repeated calls to ecbptr, therefore, generate more efficient code than storing the result and using that result as a pointer to the eb0eb structure.
The ECB contains areas for application use and reference, as well as several areas that only TPF can use. Areas available to the application program are known as work areas. There are 2 work areas, known as the EBW and EBX work areas, which are controlled by the application. These areas are used as transient work areas, as register save areas, for switch settings, or for other application purposes. C/C++ programmers, however, must use these areas judiciously, because they are subject to modification by any program segment that processes this entry. In the course of processing the entry, the contents of these areas are used for different purposes. Because automatic storage is available in C/C++ programming, it should be used for internal variables. For C/C++ programmers, the preferred purpose of the ECB work areas is to interface with assembler programs. There are several ways to pass parameters or values in assembler, including using registers and by using these ECB areas.
Programming Rule |
---|
Avoid using the ECB work areas for storing transient data. The preferred use of these areas is to pass arguments to or receive values from a called assembler segment. Use automatic storage for internal variables. |
Information about file addresses is stored in 8-byte fields called file address reference words (FARWs). Information about certain main storage blocks is stored in 8-byte fields called core block reference words (CBRWs). There are 16 FARWs and 16 CBRWs per ECB, each of which is associated with a data level. The data levels are identified in hexadecimal notation as D0 (data level 0) through DF (data level 15).
Think of a data event control block (DECB) as another ECB data level, but it does not reside in an ECB. An ECB data level and a DECB are very similar, but in a DECB the FARW has been expanded to 12 bytes to provide 8-byte file addressing. For more information, see Data Event Control Blocks.
The TPF system supports stream input/output (I/O) at an abstract level, with a hierarchical file system modeled on the UNIX and Portable Operating System Interface for Computer Environments1 standards (POSIX) TPF also supports record-level DASD I/O using TPF-specific FIND and FILE protocols. The TPF tape and general file interfaces are also record-level protocols.
The TPF file system automatically and transparently handles low-level problems such as record blocking, allocation, chaining, and locking protocols. The TPF file system also gives efficient direct access to data in a file. When used appropriately, the hierarchical file system can significantly reduce the cost and time required to design, implement, and maintain applications.
The TPF file system application programming interface (APIs) include all of the ANSI Standard C library (ISO/IEC 9899-1990, section 7) and most of the POSIX1, standards sections 5 and 6. The TPF file system is not POSIX compliant but for most of the API functions, the interfaces and semantics are identical to POSIX1 (see TPF C/C++ Language Support User's Guide for details about deviations between the TPF file system APIs and the POSIX.1 standards).
The TPF file system APIs work at two levels:
The more abstract level is the buffered I/O functions, declared in <stdio.h>. The buffered I/O functions operate on a pointer to FILE. Examples include fopen, fclose and fflush; fread and fwrite; the formatted I/O functions such as fprintf and fscanf; the character I/O functions such as fgetc, fgets, fputc, fputs; and many others. These APIs are typically used in C language applications that need to create and access files. In general, they are easier to use and more efficient than the less abstract system-level functions that follow.
The system-level I/O functions, declared in <unistd.h>, <fcntl.h>, <dir.h>, and other headers, are appropriate in cases where an application needs to work on the directory structure itself or where more control over files than is provided by the buffered I/O functions is required. The system-level I/O functions operate on a file descriptor, a path name (which is a C string), or a pointer to DIR. Examples include creat, open, close, read, write, fcntl, chdir, chown, chmod, mkdir, mknod, and stat, and many others.
It is possible to switch levels if necessary. The fileno function returns the file descriptor underlying a pointer to FILE, allowing you to switch from buffered I/O to system-level I/O. Conversely, the fdopen function creates a pointer to FILE from a previously opened file descriptor, allowing you to switch from system-level I/O to buffered I/O.
The term DASD refers to direct access storage devices. C programmers can think of the term DASD as being synonymous with disk file, or disk, or file.
The basic record-level DASD I/O actions are implemented in TPF API functions find_record and file_record. The waitc function is used in TPF for error detection at the record I/O level. See TPF C/C++ Language Support User's Guide for more information about these functions.
Figure 20. Using the waitc Function for Error Detection
if(waitc()) /* if nonzero return code */ { snapc(SNAP_EXIT,0x6404,"I/O ERROR",NULL,'U',SNAPC_NOREGS,SNAPC_ECB,NULL); /* force abnormal exit */ } |
There are two groups of find and file functions. The first group is higher level in the sense that invoking one function takes care of several different operations with one command. These functions are also simpler to use, because the programmer can specify certain fields (id and rcc) as parameters on the function call, rather than setting these CBRW fields with separate assignment statements.
Additional find and file functions that give the C programmer more control, and should, therefore, be used with more caution are:
When using this second set of functions, programmers must have a greater understanding of the system file-record-level I/O routines and may need to call the waitc function to make sure the record is attached to the ECB.
See the detailed API function descriptions in TPF C/C++ Language Support User's Guide for more information about the use of these functions.
The TPF system also uses another entity for file I/O, called a general data set. General data sets are organized on the basis of contiguous space on DASD, and are compatible with MVS. Two functions are used to manage this type of data set:
Real-time tapes are tapes that can be written to (and only written to) at any time by any operation in the system. There are two API functions available to write to real-time tapes:
General tapes are I/O tapes used for application programming. They allow the application program to write to consecutive files and read them in logical sequence. There are two groups of API functions for managing general tapes: basic general tape functions and high-level general tape functions.
A basic general tape function performs a single tape function and gives an ECB absolute control over a tape. (However, a tape can be shared between ECBs by assigning and reserving a tape in the appropriate sequence.) Using the basic general tape functions can also provide more efficient processing if it is needed. The basic general tape functions are:
A high-level general tape function performs multiple tape functions from the set of basic general tape functions and allows all ECBs to share a tape.
At the beginning of processing a high-level general tape function, all the functions, except for tape_open, assign the tape. Therefore, when you use these functions, except for tape_open, you must reserve the tape or the tape must be in a reserved state from previous processing.
At the end of processing a high-level general tape function, all the functions, except for tape_close, reserve the tape. Therefore, when using these functions, except for tape_close, the tape will be left in a reserved state at the end of processing.
The high-level general tape functions are:
In the TPF system each active entry has an ECB associated with it. Once created, the ECB is processed by a specific application, which can consist of many individual program segments.
An ECB or entry has control when it has the attention of the CPU. Control is granted based on the CPU loop, the TPF system's scheduling system. (See TPF Concepts and Structures or TPF Main Supervisor Reference for more detail about the CPU loop and task dispatching.)
Control is lost under the following circumstances:
The TPF system will also force an ECB to exit if it does not relinquish control to the operating system in 500 milliseconds (that is, it appears to be looping). This timer is reset when an ECB waits for pending I/O with the waitc function and when it suspends processing through the dlayc and defrc functions.
When TPF Enter/Back services are invoked, the same ECB remains in control and continues processing with another program segment.
You can create an entry (ECB) by calling one of the following TPF API functions:
The application program is responsible for passing any required data to the newly created ECB when it calls the TPF API library function. In particular, note that the input message and terminal address are not automatically copied to the new ECB. In the TPF system environment, there is not a strong parent-child relationship between entries; the new ECB cannot communicate anything back to the ECB that created it unless the tpf_cresc or system function is used, whereby the child ECB may pass or return a value back to the parent ECB.
Use caution when using the ECB creation functions. There is a limit to the number of entries that can be active in the system and approaching this limit too closely can degrade performance.
When an entry is completed, control is returned to the operating system. If the entry was created by the system function calling a DLM with a main function, or if it was created by the CRESC macro or the tpf_cresc function, the system adds the parent process to the CPU ready list so that it can resume processing.
The entry's exit status is returned to the parent process as the system function's return code. Returning from the initial call to a main function is equivalent to calling the exit function with the return value as its status parameter. For example:
int main(void) { return 15; }
is equivalent to:
#include <stdlib.h> int main(void) { exit(15); }
If the initial program that the entry ran does not contain a main function, the entry must explicitly call a process-terminating function, such as exit, abort, serrc_op, snapc, and others to return control to the operating system. The abort function forces the current ECB to exit under abnormal circumstances; no dumps are issued for invalid ECB states such as having a hold on a file address, or having a general tape opened or assigned. The serrc_op function causes a system error dump to be generated. Following the dump the ECB will be exited if the defined term SERRC_EXIT was coded as one of the parameters. The snapc function causes a system error dump to be generated. Following the dump the ECB will be exited if the defined term SNAPC_EXIT was coded as one of the parameters.
The user input terminal can only send messages to the system, which is then responsible for scheduling a process associated with the message. TPF application programs are activated by these input messages. Although they can send output messages in response, they do not remain active and wait for additional input messages except for TPF/APPC where the TP remains active in the same ECB throughout the life of a conversation. For non-TPF/APPC messages each new input message that arrives will cause the TPF system to create a new, independent ECB.
Therefore, non-TPF/APPC application programs must obtain all information required to process the transaction from the single input message along with data contained in the TPF file system. TPF application programs cannot operate in an interactive mode because they are not able to "listen" for additional input messages.
Programming Rule |
---|
Use the parser (IPRSE) or sscanf to obtain portions of the input message. Do not attempt to interact with the user input terminal. Design applications in such a manner that all information required to process the transaction is available in either the input message itself or in existing data records available to the process. |
When a user enters a message, it is processed by the appropriate network facilities and passed to the TPF system. The message is then added to the input list (processed by the CPU loop), and becomes associated with data level 0 (D0). The standard C function sscanf has been adapted to the TPF system to access these user input messages from D0. The only difference is that these functions do not solicit terminal input, but will access the message on D0. If the user attempts to get input message lines that do not exist, a null will be returned. Likewise, if the message associated with D0 has been released or is not an input message, a null will be returned.
There are several different options available to C and C++ programmers who want to send an output message to the user terminal:
The routc function can be used with either single line or full-screen formatted output (SNA) terminals. Also, TPF Advanced Program-to-Program Communication support allows TPF application programs to communicate with LU 6.2 applications on remote platforms. (For more information about TPF Advanced Program-to-Program Communications support, see TPF ACF/SNA Data Communications Reference.)
The TPF system also supports direction of output using a device driver. A device driver should be designed by the user to output streams to the desired terminal.
There must be a tag name for each global field and record defined in the c$globz.h header file. This file is included by tpfglbl.h, which is required whenever you access global fields or records. Whenever changes are made to c$globz.h, you must recompile any programs that access the global tags.
There are 2 functions that you can use to access TPF globals:
The following functions are available in ISO-C only.
The glob function provides read-only access, whereas the global function allows you to update, modify, keypoint, lock (reserve for exclusive use), unlock, copy, or synchronize global fields. These command options must be run in the correct order; for example, you cannot issue an UNLOCK before you have issued a LOCK. For more detail about these options, see TPF C/C++ Language Support User's Guide.
The global tags acted on by C functions must be defined in the c$globz.h header file or unpredictable results can occur.
Naturally, locks should not be held longer than necessary. Programs using the glob_lock function should be prepared to call glob_update, glob_sync or glob_unlock as soon as possible to prevent severe system degradation caused by other ECBs waiting for the lock.
If the global field or record can be synchronized, glob_lock must be called before calling glob_modify or glob_update.
Programs using these functions should not have any pending I/O operations outstanding because they can perform the equivalent of a waitc function.
You can find more detailed information about TPF globals as follows:
Type of Information | Reference |
---|---|
High-level description | Creating Globals for C |
Installation details | Customizing C/C++ Language Support |
Basic TPF global concepts, terminology, overview | TPF System Installation Support Reference |
Global program logic | TPF System Installation Support Reference. |