The IBM NTS functionality is extremely useful, but has its quirks that inhibit mainframe programmers.
IBM's name/token services (NTS) provide functionality for the ancient mainframe problem of anchoring common data structures outside of an individual program's context. NTS is freely exploited at IBM, as well as by mainframe customers and independent software vendors.
NTS pairs a 16-byte name with a 16-byte storage area. The token's name may have any value, as can its corresponding data.
Name/tokens exist at several levels, tasks, address spaces and systems in mainframe programming. The operating system hangs task-level tokens off of task control blocks (TCBs), which limits the token's accessibility to programs executing in the same task. An address-space token hangs off the job's address space secondary block, making it available to all tasks within the address space. A system token is retrievable to all address spaces running in the logical partition. Problem programs -- those not running authorized program facility in an authorized or in supervisor state -- may not create system tokens.
The level where a name/token pair is matters for two reasons: A token's name must be unique at the chosen level, and the token's level determines when it disappears or if it appears in jobs that wish to use OS checkpoint calls.
Learn more about IBM's name/token service
There are three basic routines for name/tokens: IEANTDL deletes a name/token pair, IEANTCR creates one and IEANTRT retrieves an existing pair. References to these modules resolve to a stub that executes the call sequence into NTS.
Programming with name/token pairs
Name/token pairs anchor data structures that need to be referenced without any context, such as a table of referential information or a chain of dynamically built objects shared amongst several programs.
Boundary conditions with names/tokens are more challenging. For example, a common programming practice would first try to retrieve the token and, if it doesn't exist, create it. This might work in batch, but causes problems in a multi-threaded environment like customer information control systems (CICS). When two tasks try to retrieve a token and get a "not found" return code, both tasks try to create the token. When the first one succeeds, the second gets a "token already exists" return code. The initialization logic must be smart enough to understand this and retrieve the new token.
There is no way to directly update a token. To change a token's contents, a program must delete and recreate it. This causes problems in a multi-threaded environment. Use indirect addressing where the name/token contains the address of an anchor block, which in turn points to the actual data structure. After that, any module can change the location of a data structure by updating the address in the anchor block while leaving the token alone.
Name/tokens have performance considerations as well. The system maintains name/tokens in non-ordered lists, so every name/token retrieval request prompts a sequential search through the NTS control blocks. In a really busy CICS or Information Management System (IMS) Message Processing Region (MPR), a long list of tokens could significantly tax CPUs and response time.
While the call itself may be relatively lightweight, making too many calls could hinder performance. If you find NTS calls taking up too much time, consider consolidating individual name/tokens or pass addresses between programs.
Token levels become important in multi-threading environments like CICS. A task-level token created in the quasi-reentrant TCB isn't accessible from one of the open TCBs. Therefore, in most cases, address-space tokens make sense for applications that share data across tasks.
CICS and IMS programmers should also be aware that task-level tokens disappear when the task detaches. In CICS, this doesn't matter. Open TCBs, on the other hand, may come and go. Likewise, during pseudo-ABEND processing, IMS MPRs will occasionally detach and reattach the task application programs run under, thus losing any task level tokens with it. Stow any information an IMS application wants to keep across these detaches in an address-space-level token.