Programming Considerations


Using Command IDs

The command ID field of the control block serves an important function during Adabas command execution. This section provides a summary of the uses of this field and describes the procedures to be followed when using command IDs.

A command ID is associated with the following information:

  • If you perform read sequential commands (L2/L5, L3/L6, L9), Adabas needs information to identify the record to be processed with the next command. For this purpose, Adabas has a table for all active sequential command sequences, and the command ID identifies the entry in this table.

  • If you perform search commands, Adabas needs information on the ISN list returned by the search commands. For this purpose, Adabas has a table for all active ISN lists, and the command ID identifies the entry in this table.

  • If a format buffer is associated with a read, S1/S2/S4 search or update command, Adabas converts the format buffer to an internal format buffer that is used for record compression or decompression. Adabas can keep these internal format buffers in memory in order to reuse them for further commands with the same format buffer, which avoids a new conversion of the format buffer. The command ID can be used as a format buffer ID to identify an internal format buffer that already exists.

Command IDs Used with Read Sequential Commands

The read sequential (L2/L5, L3/L6, L9) commands require that a non–blank, non–zero command ID be specified. The command ID is required by Adabas to return the records to the user in the correct sequence. These command IDs are maintained in the table of sequential commands.

The command ID is released by Adabas when an end-of-file condition (Adabas response code 3) is detected during read sequential processing (only from the table of sequential commands).

The command ID value provided with these commands is also entered and maintained in the internal format-buffer pool. It will only be released by an explicit RC command.

Command IDs Used with ISN Lists

If a non-blank, non-zero command ID is specified for any command which results in an ISN list (S1, S2, S4, S8, S9), the command ID value may be used to identify the list at a later time.

If the SAVE ISN LIST option is used for an Sx command, a non-blank, non-zero command ID must be provided. The SAVE ISN LIST option causes the entire ISN list to be stored on the Adabas temporary working space. ISNs from the list may be subsequently retrieved by an Sx command or by using the GET NEXT option of the L1/L4 command.

If the SAVE ISN LIST option is not used and an ISN buffer-overflow condition occurs (the entire ISN list cannot be inserted in the ISN buffer), the overflow ISNs will be stored on the Adabas temporary working space only if a non-blank, non-zero command ID value was used. In this case, the command ID will be released by Adabas (only from the ISN list table) and the ISN list it identifies will be released by Adabas when all the ISNs have been returned to the user by subsequent Sx commands, or by L1 commands with the GET NEXT option when an end-of-file condition (Adabas response code 3) is detected.

Automatic Command ID Generation

Automatic command ID generation is invoked by specifying a command ID of hexadecimal FFFFFFFF. This causes the Adabas nucleus to generate command IDs automatically, starting with hexadecimal 00000001 and incrementing by 1 for each new command ID.

Releasing Command IDs

The user may release a command ID and its associated entries (or ISN list) with an RC or CL command. The RC command contains options which allow the user to release only those command IDs contained in the internal format–buffer pool, the table of sequential commands or the table of ISN lists.

The CL command causes all of the command IDs that are currently active for the user to be released.

Command IDs are not released at the end of a global transaction.

Internal Identification of Command IDs

Each command ID entry is identified by Adabas using the internal user number and the command ID value.

A user need not be concerned with the command ID values in use by other users. The user should, however, exercise care when using the same command ID value for different commands, particularly for command IDs used for sequential read (L2/L5, L3/L6, L9) commands and Sx commands. The notation Sx command as used in this manual refers to any search command (S1, S2, S4, S8, S9).

Empty Command IDs

You may sometimes want to perform Adabas commands without storing a command ID in the table of sequential commands, in the ISN list table or in the internal format buffer pool. This can be achieved by storing one of the following values in the command ID field:

  • Binary zero.

  • ASCII blanks (0x20202020). This is because character values are often used as command ID, although the command ID field is defined as binary.

  • EBCDIC blanks (0x40404040). This is to enable mainframe users performing cross-platform calls to also specify blanks as an empty command ID.

Specifying one of these values in the command ID field has the following consequences:

  • The command ID is not stored in the table of sequential commands, in the ISN list table and inthe internal format buffer pool.

  • No RC command is required to release the command ID.

  • The format buffer is re-translated for each call (unless you have specified a format buffer ID in Additions 5, as decribed in the next section) .

  • It is not possible to perform subsequent commands for this command.

Command ID Usage Examples

This section contains examples of command ID usage.

Example 1: Find/Read processing

A set of records is to be selected and read. The same format buffer is to be used for each record.

Find (S1)   CID=EX1B
Read (L1)   CID=EX1B
Read (L1)   CID=EX1B
    

Example 2: Find/Read using the Get Next option

A set of records is to be selected and read using the GET NEXT option of the L1/L4 command.

Find (S1)    CID=EX2A
Read (L1)    CID=EX2A
Read (L1)    CID=EX2A
Read (L1)    CID=EX2A
...

Example 3: Read/Update processing

A file is to be read and updated in logical sequence. The same format buffer is to be used for reading and updating.

Read Log Seq (L6)  CID=EX3A
Update (A1)         CID=EX3A
Read Log Seq (L6)  CID=EX3A
Update (A1)         CID=EX3A
...

Example 4: Read/Find processing

A file is to be read in logical sequence. A find command is to be issued to a second file using the value of a field read from the first file, and the records which result from the find command are then to be read using the GET NEXT option.

Read Log Seq (L3)  CID=EX4A
Find (S1)          CID=EX4B
Read (L1)          CID=EX4B
Read (L1)          CID=EX4B (RSP 3)
Read Log Seq (L3)  CID=EX4A
Find (S1)          CID=EX4B
Read (L1)          CID=EX4B

Using Format Buffer IDs

Format buffer translations to an internal format buffer are time-consuming. For this reason, Adabas can save the internal format buffers in memory for reusage by other Adabas commands, and format buffer IDs were introduced to identify the internal format buffers to be reused.

Usually the command ID is used as the format buffer ID, but it is also possible to use Additions 5 to specify a format buffer ID separately:

  • If there is more than one active read-sequential or search command using the same format buffer, a separate local format buffer ID may be useful. In this case “local” means user-specific.

  • If several users run the same application program doing Adabas calls in parallel, a separate global format buffer ID may be useful. In this case “global” means valid for all Adabas users.

Using a Command ID and Separate Local Format Buffer ID

Separate values can be used for command IDs and format buffer IDs. As long as the first byte of the Additions 5 field is not alphanumeric, the command ID is also used as the format buffer ID. If, however, the first byte of the Additions 5 field is a lower case character, the bytes 5 to 8 of the Additions 5 field are used as the (local) format buffer ID (see example 2 below). The format buffer ID must not start with hexadecimal FF.

Using a Global Format Buffer ID

In many cases, numerous users who use the same program read or update the same fields of a file and therefore use identical format buffers. Defining a global format buffer ID for each of these programs means that Adabas does not have to store the same format buffer in the internal format buffer pool for each such program. If this option is used, the format buffer for each user is identified by the format buffer ID only, rather than by the format buffer ID and the internal communication ID. The result of this option is that numerous users can `share' a single format buffer, which in turn means that Adabas does not have to overwrite entries in the format buffer pool.

Caution:
If a format buffer contains W fields, and the character set is not specified explicitly in the format buffer, Adabas implicitly uses the character set specified in the Adabs OP command via the parameter WCHARSET (default: 'UTF-8') . The information about the character set is included in the internal format buffer. This has the consequence that you may only use a global format buffer ID for such a format buffer when the same WCHARSET is specified in the OP comand of all Adabas sessions in which this global format buffer ID is used. Otherwise it may happen that the W fields are processed with the wrong character set.

The global format buffer ID option is set by setting the first byte of the Additions 5 field to a digit or upper case letter (see example 3 below).

EBCDIC Characters in Additions 5

Adabas must also be able to process commands issued on mainframes. In this case, Additions 5 may contain EBCDIC characters. Because it may also contain binary data, no EBCDIC-ASCII conversion is performed for Additions 5. Therefore, EBCDIC lower-case characters (hex 8x, 9x) in first byte of Additions 5 indicate a separate local format buffer ID, EBCDIC upper-case characters (hex Cx, Dx) and EBCDIC digits (hex Fx) indicate a separate global format buffer ID, and EBCDIC blank (hex 40) indicates no separate format buffer ID.

The behavior of Adabas is undefined if you specify anything else in the first byte of Additions 5.

Examples of Command ID and Format Buffer ID Usage

Example 1: Using the same command ID and format buffer ID

Additions 5: The first byte of the Additions 5 field is blank or binary zero

Result: the command ID is used as the format buffer ID.

Example 2: Using separate local format buffer ID

Additions 5: The first byte of the Additions 5 field is set to 'a'

Result: bytes 5 to 8 of the Additions 5 field are used as the format buffer ID (the format buffer ID must not start with hexadecimal FF).

Example 3: Using global format buffer ID

Additions 5: The first byte of the Additions 5 field is set to 'A'

Result: the Additions 5 field (8 bytes) is used as the global format buffer ID (usable by several users in parallel).

Example 4: Using a global format buffer ID on mainframe

Additions 5: The first byte of the Additions 5 field is set to hex D1

Result: Hex D1 = EBCDIC ‘J’ -> the Additions 5 field (8 bytes) is used as the global format buffer ID (usable by several users in parallel).

Format Buffer IDs Used with Read, Search and Update Commands

The read commands (L1-L6, L9) and update commands (A1, N1/N2) require a format buffer which specifies the fields to be read or updated. A format buffer can also be specified for an S1/S2/S4 search command to read the first result record. This format buffer must be interpreted and converted into an internal format buffer by Adabas. The same format buffer ID may be used to avoid repetitive interpretation and conversion during successive commands which use the same format buffer. A read or update command in which a format buffer ID is used causes Adabas to check whether it is in the internal format buffer pool. If the format buffer ID is present, the internal format buffer for the format buffer ID is used, and no format buffer interpretation is required. The user may, therefore, achieve a significant decrease in the processing time required for read and update commands by using a format buffer ID when reading or updating a series of records in which the same format buffer is used. If the user is reading and updating the same fields (for example, L5 followed by A1), it is also recommended that the same format buffer ID be used for both commands (see the A1 and N1/N2 commands for restrictions on using the same format buffer for reading and updating).

If the internal format buffer pool is full, and a command is received in which a format buffer ID not in the pool is present, Adabas will overwrite the least active entry in the pool with the new format buffer ID. If a command is subsequently received which uses the deleted command ID, this command ID will in turn replace the least active entry in the pool. The format buffer must be newly interpreted and converted into an internal format buffer whenever the above occurs. For this reason, the format buffer should not be modified between successive read or update commands in which the same format buffer ID is used.

Caution:
Please take care to ensure that you always specify a correct pair of format buffer ID and format buffer:

  • If, for example, you use a new format buffer but forget to specify a new command ID, you may read the fields specified in the format buffer associated to the old command ID. This may lead to wrong results in the record buffer.

  • If you don’t specify the correct format buffer for subsequent commands with the same format buffer ID, the program may work correctly for a long time, but suddenly it may happen that the corresponding internal format buffer has been overwritten in the format buffer pool. Then a new format buffer conversion is required, which may fail, or will be invalid if the correct format buffer has not been specified for the command.

ISN List Processing

This section discusses the procedures used to retrieve ISNs from the Adabas temporary working space. If the GET NEXT option of the L1/L4 command is to be used to read the records which correspond to the ISNs contained in the ISN list, ISN handling as discussed in this section is performed automatically by Adabas, and the user need not make use of these procedures.

Storing ISN Lists

Adabas stores ISNs on the Adabas temporary working space under the following conditions:

  • An Sx command is issued, a non-blank non-zero command ID is specified and the SAVE ISN LIST option is specified. The entire resulting ISN list is stored in this case;

  • An Sx command is issued, a non-blank non-zero command ID is specified, the SAVE ISN LIST option is not specified, and the resulting ISN list contains more ISNs than can be inserted in the ISN buffer. Only the overflow ISNs are stored in this case.

If an Sx command is issued with blanks or binary zeros in the command ID field, Adabas does not store any ISNs on the Adabas temporary working space.

Retrieving ISN Lists

The user may retrieve ISNs stored on the Adabas temporary working space by issuing an Sx command in which the same command ID value is used as that used for the initial Sx command. When an Sx command with an active command ID value is issued, Adabas uses this as an indicator that the user is requesting ISNs from an existing ISN list. Adabas locates the ISN list identified by the command ID specified and inserts the next group of ISNs in the ISN buffer. As many ISNs are returned as can be inserted in the ISN buffer.

If the SAVE ISN LIST option was specified with the Sx command used to create the ISN list, Adabas uses the ISN specified in the ISN lower limit field to determine the next group of ISNs to be returned. The next group begins with the first ISN which is greater than the ISN specified in ISN lower limit. If binary zeros are specified, the next group begins with the first ISN in the list. If a value is specified which is greater than any ISN in the list, response code 3 is returned. Such an S1 call without an ISN buffer can be used for repositioning within the current ISN list.

If the ISN list was created using an S2/S9 command, the ISN specified must be present in the ISN list, otherwise response code 25 is returned. Using the SAVE ISN LIST option thus allows the user to move forwards and backwards within an ISN list. This is useful for programs which must perform forward and backward screen paging.

If the SAVE ISN LIST option was not specified with the Sx command used to create the ISN list, Adabas returns the ISNs in the order in which they are positioned in the list and deletes each group from the temporary working space when it has been inserted in the user's ISN buffer. The command ID used to identify the list is released when the last group of ISNs has been returned to the user. The ISN lower limit field is not used in this case.

The user may determine when all of the ISNs in a list have been retrieved by using the ISN quantity field of the control block. Adabas returns in this field, as a result of an initial Sx command, the total number of records which satisfy the search criteria. Adabas returns, as the result of a subsequent Sx command used to retrieve ISNs from the Adabas temporary working space, the number of ISNs which were inserted in the ISN buffer.

Handling of ISNs that no longer exist

When an ISN list is processed, it may occur that ISNs found by the search operation no longer exist when the ISN is processed, for the following reasons:

  • The ISN has been deleted after the ISN was included in the search result.

  • The search operation processes a previously generated ISN list, and the ISN in that ISN list has already been deleted before the search operation started.

Please note that Adabas generally does not check whether the ISNs still exist when they are included in the search result. An exception is an initial Sx command, where a format buffer has also been specified. In this case, Adabas reads the first ISN of the resulting ISN list - if it no longer exists, the ISN is removed from the resulting ISN list. For subsequent Sx commands with a format buffer, you get a response code 113 if the first ISN in the ISN list to be processed does not exist. This is because the command ID is deleted after the last ISN has been returned. If you did not get all ISNs of the ISN list, it could be that the user assumes that another subsequent Sx command is performed, but in fact a new initial Sx command is performed.

If you process the ISN list using L1 commands with GET NEXT option, ISNs that no longer exist are skipped. Therefore, it may occur that you get an end-of-list condition (response code 3), although the number of ISNs read is less than the ISN quantity returned in the initial Sx command.

Examples of ISN List Processing

Example 1: Initial Sx call using SAVE ISN LIST option

COMMAND = Sx
COMMAND ID = SX01
COMMAND OPTION 1 = H
ISN LOWER LIMIT = 0
ISN BUFFER LENGTH = 20
CALL ADABAS ...

Resulting ISN quantity = 7

Resulting ISN list:
(all ISNs are stored) 8 12 14 15 24 31 33

Resulting ISN buffer: 8 12 14 15 24

Subsequent Sx call

COMMAND = Sx
COMMAND ID = SX01
ISN LOWER LIMIT = 24
ISN BUFFER LENGTH = 20
CALL ADABAS ...

Resulting ISN quantity = 2

Resulting ISN buffer: 31 33 14 15 24

Subsequent Sx call

COMMAND = Sx
COMMAND ID = SX01
ISN LOWER LIMIT = 0
ISN BUFFER LENGTH = 20
CALL ADABAS ...

Resulting ISN quantity = 5

Resulting ISN buffer: 8 12 14 15 24

Example 2: With ISN overflow handling

Initial Sx call (SAVE ISN LIST option not used)

COMMAND = Sx
COMMAND ID = SX02
COMMAND OPTION 1 = blank
ISN LOWER LIMIT = 0
ISN BUFFER LENGTH = 20
CALL ADABAS ...

Resulting ISN quantity = 7

Resulting ISN list: (only ISNs 31 and 33 are stored)
8 12 14 15 24 31 33

Resulting ISN buffer: 8 12 14 15 24

Subsequent Sx call

COMMAND = Sx
COMMAND ID = SX02
ISN LOWER LIMIT  (not used)
ISN BUFFER LENGTH = 20
CALL ADABAS ...

Resulting ISN quantity = 2

Resulting ISN buffer: (ISNs 31 and 33 are deleted from the Adabas temporary working space, command ID SX02 is released).
31 33 14 15 24

A subsequent Sx call with command ID SX02 will be processed as an initial Sx call since SX02 was released after the second call which resulted in the last ISN being returned to the user.

Example 3: Without ISN overflow handling

Initial Sx call with blank or zero command ID

COMMAND = Sx
COMMAND ID = blanks or binary zeros
COMMAND OPTION 1 = blank
ISN LOWER LIMIT = 0
ISN BUFFER LENGTH = 20
CALL ADABAS ...

Resulting ISN quantity = 7

Resulting ISN list:
(no ISNs are stored) 8 12 14 15 24 31 33

Resulting ISN buffer: 8 12 14 15 24

A subsequent Sx call with command ID equal to blanks or binary zeros and ISN lower limit equal to 0 will result in the re-execution of the same find command with the same result as the initial call.

A subsequent call with command ID equal to blanks or binary zeros and ISN lower limit = 24 will re-execute the Sx command. The result of this command will be ISN quantity = 2 and ISNs 31 and 33 in the ISN buffer.

Example 4: Reading ISN list with GET-NEXT option

Inital Sx command

COMMAND = Sx               
COMMAND ID = SX01          
COMMAND OPTION 1 = blank   
ISN LOWER LIMIT = 0        
ISN BUFFER LENGTH = 4      
FORMAT BUFFER = <not empty>
CALL ADABAS ...

Resulting ISN quantity = 3

Resulting ISN = 44

Resulting ISN list:
44 321 344 (only 321 and 344 are stored)

Resulting ISN buffer: 44

Resulting record buffer: field values of ISN 44

Subsequent L1/L4 call

COMMAND = L1 or L4         
COMMAND ID = SX04          
COMMAND OPTION 2 = N       
FORMAT BUFFER = <unchanged>
CALL ADABAS ...

Resulting response code = 0

Resulting ISN = 321

ISN 321 is deleted from the Adabas temporary working space.

Resulting record buffer: field values of ISN 321

Subsequent L1/L4 call

COMMAND = L1 or L4         
COMMAND ID = SX04          
COMMAND OPTION 2 = N       
FORMAT BUFFER = <unchanged>
CALL ADABAS ...

Resulting response code = 0

Resulting ISN = 344

ISN 344 is deleted from the Adabas temporary working space, the remaining ISN list is now empty

Resulting record buffer: field values of ISN 344

Subsequent L1/L4 call

COMMAND = L1 or L4         
COMMAND ID = SX04          
COMMAND OPTION 2 = N       
FORMAT BUFFER = <unchanged>
CALL ADABAS ... 

Resulting response code = 3 (end of ISN list)

Command ID SY04 is released.

Using the Multifetch Feature

The Multifetch feature is used to retrieve more than one record with one call. This leads to a considerable reduction in the communications overhead.

Retrieval

The Multifetch feature is invoked by specifying the value `M' in the Command Option 1 field for any of the commands L1/L4, L2/L5, L3/L6 and L9. If, in addition, the Return option is required for these commands, the value `O' should be specified instead.

If you use the ACBX interface, multifetch buffers must also be defined within the user program.

If you use the ACB interface, an ISN buffer must also be defined within the user program.

Adabas uses the corresponding buffers as storage for data that describe the records returned in the record buffer. The first 4 bytes contain the number of records returned by the call. Each record in the record buffer is represented by a 16-byte entry in the ISN/multifetch buffer:

Byte Usage
1-4 Length of record
5-8 Adabas response code
9-12 ISN of record (L9 command: occurrence count if descriptor is within a periodic group)
13-16 (L9) ISN quantity
13-16 (L3/L6) Index in periodic group if descriptor used is within periodic group

The ISN Lower Limit field in the command block can be used to limit the number of records to be returned. If this field is set to zero, the maximum number of records returned depends on the size of the record buffer and/or the size of the ISN/multifetch buffer.

If an ISN is in hold status for another user or if the hold queue limit is reached, no further records are returned to the record buffer. If the first record is held by another user and the Command Option 1 field is set to `M', an implicit wait is performed. If a record other than the first record is held by another user, Adabas immediately returns the records up to but not including that record to the user. If the Command Option 1 field is set to `O' and a record is held by another user, Adabas response code 145 is returned. For the first record, the response code is within the control block, and for subsequent records it is in the ISN/multifetch buffer.

If an error is detected while a record is being processed, the response code will be returned in the corresponding structure in the ISN/multifetch buffer.

The ISN returned in the control block is the ISN of the first record returned.

If the ISN/multifetch buffer length is less than 20 bytes, or if the record buffer is too small to process at least one record, an Adabas response 53 will be returned in the Control Block.

If an error is detected while the first record is being processed, the error response is returned in the Response Code field of the control block. If an error is detected while a record other than the first record is being processed, Adabas returns the records that were processed successfully and puts the the response code for the unsuccessful record in the corresponding structure in the user-defined ISN/multifetch buffer.

Transaction Control

The Multifetch feature is invoked by specifying the value 'M' in the command option 1 field of the ET/BT command. This specifies that the list of ISNs provided by the user in the ISN buffer are to be released from hold status. The first 4 bytes contain the number of ISNs to be released. Each ISN is represented by an 8-byte entry in the ISN buffer:

Byte Usage
1-4 File number
5-8 ISN of record

If all of the records are to be kept in hold status, the first 4 bytes of the ISN buffer must be set to zeros. In this case, the TT time limit is not restarted.

If a given combination of file number and ISN is not in hold status for the user in question, Adabas response code 144 is returned.

This response is given after the entire ISN buffer is processed.

If the ISN buffer length is less then 4 + (number of ISNs * 8), the Multifetch feature will be ignored (i.e. the call will be processed as a standard call) and an Adabas response 53 will be returned.

Note:
For transaction control, the ACBX interface also uses ISN buffers, rather than Multifetch buffers, for the Multifetch feature.

ACB versus ACBX Functionality

The Adabas functionality that is available with the ACB interface is a subset of the functionality available with the ACBX interface, with one exception - the MC command is only available via the ACB interface.

All ACB calls are transformed into an ACBX call by the Adabas interface routine (e.g. adalnkx), and the results are transformed back to the ACB interface. The following rules apply:

  • All fields that are contained both in the ACB and in the ACBX are copied to the ACBX. Some fields are defined with larger sizes in the ACBX interface; this means that you must use the ACBX interface if you want to specify values that do not fit into an ACB field, but that do fit into the corresponding ACBX field. With Adabas Version 6.2, these larger lengths are not yet used.

  • The ABDs required in the ACBX interface are generated from the Adabas buffer lengths. If a command requires buffers >= 64 KB, you must use the ACBX interface.

  • As described in the previous section, the ISN buffer is sometimes used in the ACB interface when the ACBX interface uses a multifetch buffer. In such cases, the ABD for the ISN buffer of the ACB call is generated as the ABD for a multifetch buffer.

  • Fields that are only contained in the ACBX are set to their default values; if you want to provide other values for these fields, you must use the ACBX interface, but for Adabas Version 6.2, there are no commands that use input from ACBX-only fields.

  • The resulting values in fields that belong to fields contained both in the ACB and in the ACBX are copied back to the ACB. With Adabas Version 6.1, it is not possible that these fields have values that do not fit into the ACB fields, if the fields are defined with a larger size in the ACBX than in the ACB.

  • Information that is returned in ACBX-only fields is lost in ACB calls. In Adabas Version 6.2, only some diagnostic information for the command executed is returned in ACBX-only fields.

With this knowledge about the relationship between ACB and ACBx calls, it is not necessary to provide separate descriptions about how commands are executed with the ACB interface and with the ACBX interface.

System Generated Fields

If a file contains system generated fields, only the behaviour of store and update commands changes - the behaviour of read and search commands remains unchanged.

The values for system generated fields are generated automatically by Adabas. It doesn’t matter whether a record buffer for store and update commands contains values for system generated fields or not - field values for system generated fields in the record buffer are normally ignored, with the exception of using a last update time stamp field for optimistic locking as described below.

If the system generated fields are defined with option CR, the values are generated only during a store command and are never updated.

If the system generated fields are defined without option CR, the values are generated during store commands, and up-dated during update commands. If the field is a multiple-value field, a new first value is inserted and the old fields are shifted one element to the right - if this results in field values with MU index > file parameter SYFMAX, these fields are deleted.

Using Last Update Time Stamp for Optimistic Locking

If you specify command option 2='T' (check time stamp) for an A1 command, you can use a last-update-time-stamp system generated field for optimistic locking:

  • When you read the record to be updated, you either do not lock the record at all, with the disadvantage that you can see uncommitted updates (dirty read), or you lock it with option 'C', which guarantees you that you don’t see uncommitted updates but doesn’t keep the lock beyond the end of the read command. The read command reads a last-update-time-stamp system generated field (field with option SY=TIME without option CR).

  • The update is performed by an A1 command with command option 'T' and must include the last-update-time-stamp field in the format and record buffer; the field value must not have been changed since the read command.

  • If the last update time stamp is stored in an MU field, the field value with index 1 must be specified in the format buffer.

  • If option 'T' was specified and no last-update-time-stamp system generated field is contained in the format buffer, then you receive response code 44, subcode 13.

  • A check is made to see whether the field value specified in the record buffer is the same as the current value in the database record:

    • If the value in the database is the same value, and the current time in the precision of the field with option SY=TIME is still the same, the command fails with response code 22, subcode 42

    • If it is the same value, and the current time in the precision of the field with option SY=TIME has changed, the record is placed in hold status; if the record is held by another user, the behaviour depends on the usage of the return option:

      • If the return option (option 'R' or 'U') is specified, response code 145 is returned.

      • Otherwise the command waits until the record is available again; then the check is repeated.

    • If the system generated value has been changed in the meantime, you receive a response code 48, subcode 34. If you have specified option 'L' or 'U', the modified record is read into the record buffer.

Note:
If the system generated field with option SY=TIME is not a high-precision time stamp, it is only guaranteed that no updates are lost if all updates on this file are performed with option 'T'. If you aren't sure, you should only use this kind of update with high-precision time stamps.

Read Integrity

If you read a record with an L1, L2, L3 or S1 command, you perform a dirty read, i.e. you also see uncommitted updates. In order to see only the committed states of records, Adabas provides shared locks for the records. Depending on your requirements, you can keep the record in shared hold status for different times:

  • The C option does not keep the record in shared hold status beyond the current read operation, unless it was already locked before.

  • The Q option keeps the record in shared hold status until the next record of a read loop is read. It can be used to perform more than one consistent read operation on the same record.

  • The S option keeps the record in shared hold status until the current transaction is committed or rolled back.

  • The RI command enables you to release a record from shared hold status before the record would normally be removed from shared hold status.

Note:
In order to use the C, Q or S options, you must change the commands to L4, L5, L6 or S4.

If you read different parts of a record with more than one read command, for example, if you read a LOB field piece-meal, it is strongly recommended to ensure that the record is not updated between the read operations. The following possibilities are available for this purpose:

  • Place the record in shared or exclusive hold status with command option 3 = Q, S or blank when you perform the first read command for the record.

  • Read a high-precision, system-generated last update time stamp with each read command, and check that it was not changed between the read commands. The advantage of this solution is that you can also read the record when somebody else has put the record in exclusive hold status - but you must be aware that this is still a dirty read, i.e. you can see uncommitted updates.

  • The application guarantees the read integrity; for example, you can read a record without locking it, when another user is only allowed to update the record after locking another record, which you have already locked. Note that you should only use this kind of integrity preservation if you can really be sure that all programs updating the file apply these rules.

Features in the Adabas Command Interface for Large Object (LOB) Support

The following features have been introduced to the Adabas command interface, for LOB support in particular:

Large Buffers with the ACBX Interface

With the old ACB interface, the size of record buffers was limited to 64 KB, which is too small for LOB support. This limitation was removed with the new ACBX interface, which allows record buffer sizes of up to 2 GB.

More than one Format/Record Buffer Pair with the ACBX Interface

When you access LOB fields and other fields with one Adabas call, the LOB value often has a variable length, and you want to be able to allocate the space in a special area, while the other fields have a fixed length, and which are located in a predefined area. The ACBX interface allows you to specify both areas as different record buffers for the same Adabas call.

4-Byte Length Indicator for LOB Fields when reading with variable Length

If you specify 0 as the length in the format buffer to indicate variable length for LOB fields (fields with field option LB), a 4-byte length indicator is used in the record buffer in order to support larger length values.

Length Indicator in Format/Record Buffer

When you want to read a LOB value, you often don't know the length of the LOB value in advance. The length indicator allows you to retrieve the length of the LOB value first, before you allocate the area for the LOB value.

Asterisk (*) Length Notation in the Format Buffer

Specifying an asterisk (*) as length reads a value with variable length. The difference to specifying 0 as length is as follows:

  • The value is a value without the length in front. It is recommended for read commands and required for insert/update commands that you also specify a length indicator for the LOB field.

  • You don't get a record buffer overflow (Adabas response code 53) when you read a value that doesn't fit into the record buffer. If you read the length indicator and the LOB value with * length, you still get the LOB value length even if the LOB value does not fit into the record buffer, and you can reallocate the record buffer with a sufficient size and reread the LOB value.

Accessing Parts of LOBs with the Segment Notation in the Format Buffer

If the available memory is limited, or if you only need a part of a LOB where you know its position within the LOB value, and you want to access large LOB values, you may want to access the LOB value in pieces. This is possible using the segment notation in the format buffer.

Note:
You can find Detailed information on the format buffer entries mentioned above in the section Calling Adabas, Format and Record Buffers.