The User Index tool provides an interface to allow reading, writing,
updating, and deleting entries from a user index. Several other
tools such as CRTUSRIDX also use interfaces provided by USRIDX. Only
keyed fixed length user indexes are supported. The maximum entry
length is 2000 bytes including the key.
OPM and ILE users may use a dynamic call to TAAIDXAR5. An externally
described data structure (TAAIDXAP) is the only parameter that is
passed which contains fields for the operation requested and the data
to be returned.
An ILE user may also use a bound call. A service program is
provided.
User Index concepts
-------------------
The system supports a *USRIDX object. Both keyed and non-keyed types
are supported (similar to *DTAQ objects) and the entries may be fixed
or variable length. APIs are used to create, read, write, and delete
entries in a user index.
In some applications, a program must read an unknown amount of data,
place it into an array, possibly update some of the values, and then
sort the array to allow processing in sequence.
If an unknown amount of data exists, a typical solution is to define
an array with a large number of entries (the RPG OPM limit is 9,999).
This can make functions like RPG's LOKUP very slow if a value does
not exist. Sorting an array in RPG must be done by placing the key
in the high order position of each element.
A *USRIDX object can simplify this type of processing by allowing
keyed operations. The data can be written randomly to the user
index. If updating is required, random updates may be made by key.
To output the entries in sequence, the program only needs to read
sequentially by key.
From an external perspective, you can consider a *USRIDX object to be
similar to a simple data base work file. The key to the entry makes
up the first n bytes of an entry. When a user index is created, you
define the length of the entry and the length of the key.
The system supports a single command to operate on user indexes:
DLTUSRIDX Delete user index
The TAA support of *USRIDX objects allows the following commands:
CRTUSRIDX Create user index (only keyed fix length)
CVTUSRIDX Convert user index entries
RTVUSRIDXA Retrieve user index attributes
DSPUSRIDXA Display user index attributes
DSPUSRIDX Display user index entries
CLRUSRIDX Clear user index
Also supported by TAA are programs which allow you to interface from
a HLL program to cause operations such as read, write, etc to a user
index. This allows a typical RPG programmer to use a user index
without knowledge of the APIs.
For dynamic calls from OPM or ILE, use the TAAIDXAR5 program.
For bound calls from ILE, use the TAAIDXA *SRVPGM.
The TAA support is limited to keyed fix length entries and supports a
maximum entry length of 2000 bytes. The maximum size of a user index
may be 4GB.
Sample OPM program
------------------
Sample OPM programs are provided that will create a user index,
write, read, update, and delete entries. To run the programs, enter:
CALL PGM(TAAIDXAC6)
A spooled file will be displayed with the results.
The TAAIDXAC6 CL program creates the MYUSRIDX user index (*USRIDX) in
QTEMP and calls the TAAIDXAR6 RPG program. The program writes 3
entries to the user index, retrieves them in keyed order, randomly
retrieves an entry, updates it, deletes a different entry, and then
retrieves the entries in keyed order. A listing occurs to show the
results.
After the programs run, you can try out the following commands:
DSPUSRIDXA USRIDX(QTEMP/MYUSRIDX)
CLRUSRIDX USRIDX(QTEMP/MYUSRIDX)
An externally described data structure is used to pass information
the supplied program. You can display the format of the externally
described data structure with the command:
DSPFMT FILE(TAAIDXAP)
To understand how you use the TAA interface to manipulate a user
index, the following TXTnn entries refer to the corresponding values
within the TAAIDXAR6 RPG OPM source test program. You can print this
program out and refer to it as you go thru the discussion. To print
the code, use:
DSPTAA TAAARCMBR(TAAIDXAR6) OUTPUT(*PRINT)
** TXT010. The externally described data structure (TAAIDXAP)
has two fields which are larger than the RPG OPM maximum
length of 256 bytes. These two fields UIDATA and UIMSTX are
defined as arrays to prevent compilation errors. Using arrays
requires the use of MOVEA when the fields are referenced (if
using ILE RPG, the arrays would not be needed and the MOVEA
operations could be replaced with MOVEL).
** TXT020. The externally described data structure (TAAIDXAP) is
defined and given a name IDXDS.
** TXT030. The sub program described as USRIDX is defined to be
TAAIDXAR5. This is the TAA supplied program for programs that
will cause operations to a user index by passing an externally
described data structure as the only parameter.
** TXT040. The MSGDS data structure of 512 bytes is defined to
allow use by the TAA Tool SNDDIAG.
** TXT050. In the TAAIDXAC6 CL program, the MYUSRIDX user index
object was created with a length of 20 and a key length of 10.
If you used the DSPUSRIDXA command after the call to the test
program (TAAIDXAC6) you would see this information. The
definition means that each entry will begin with a 10 byte key
and then have 10 bytes of data associated with the key. The
MYDS data structure is defined with a key of 10 bytes in 1-10
and data in 11-20. Thus the key is part of the entry and
always begins in the high order for the length defined when
the user index was created.
** TXT060. The program moves the name of the user index and user
index library (MYUSRIDX in QTEMP) to fields within the
TAAIDXAP externally described data structure. The *WRITE
operation code is requested. Each entry to be written then
requires a move of a key value and corresponding data to the
fields in the MYDS data structure. The WRITE subroutine is
used to write each entry to the user index.
** TXT070. The WRITE subroutine moves the data from the MYDS
data structure to the UIDATA field in the externally described
data structure. This UIDATA field is the entry that will be
written to the user index.
Note that each time the program writes to the user index, it
moves data from the MYDS data structure to the UIDATA field.
Similarly, each time a read occurs, the returned entry is in
UIDATA and is moved to the MYDS data structure for processing.
The USRIDX program (TAAIDXAR5) is called and the IDXDS data
structure is passed. If an error occurs, the UIMSID field
will not be blank. A typical error that might occur is
CPF3C74 meaning a duplicate key occurred.
** TXT080. The entries that were written will be sequentially
read and printed by the READ subroutine.
** TXT090. The 'low value' is placed into the key field and the
MYDS data structure is moved to UIDATA.
** TXT100. The operations are set to *READ and *GT. Note that
you should use a MOVEL with padding when placing data in the
UIOPCD and UISCOD fields. The call to USRIDX ignores any data
in the data portion of UIDATA. The key portion of UIDATA (now
containing 'low value') is used to access the first record
because *READ *GT was specified.
** TXT110. The UIMSID field must be checked after each call. A
value of TAA9891 means that the entry was not returned. When
a sequential read is used, TAA9891 means 'end of entries' and
the program branches to the end of the subroutine.
Any other error value causes the program to abort.
** TXT120. If the UIMSID field is blank, it means that an entry
was placed in the UIDATA field. The data is moved to the MYDS
data structure for processing.
** TXT130. After the first entry is returned, the program loops
back to request the next entry. The USRIDX program uses the
value in the key portion of the UIDATA field to determine how
to request the next entry. Since the first *READ request
returns the first entry, a request for *READ and *GT will
cause the second entry by key to be returned. Each time an
entry is processed, this same loop occurs.
** TXT140. A random request will now be made to retrieve the
'234' key. The key is set to '234' and the MYDS data
structure is moved to the UIDATA field.
** TXT150. The UIOPCD field is set for *READ, and *EQ is placed
in the UISCOD field requesting an equal key. Note that there
is probably data in bytes 11-20 of the UIDATA field when the
call occurs. This data will be ignored by a *READ request to
the USRIDX program.
** TXT160. The UIMSID field is checked for errors. Since the
program assumes the key will exist, the program will abort if
the message field is non-blank.
** TXT170. If the UIMSID field is blank, the entry has been
placed in the UIDATA field. It is moved to the MYDS data
structure for processing.
** TXT180. The entry that was just read will be changed in the
data portion. The new value 'MILLER' is moved the the DATA
field and the key ('234'). The MYDS data structure is moved
to UIDATA.
** TXT190. A request is made then for *UPDATE of an equal key
(*EQ).
Note that it would not have been necessary to read the entry
first. The update request requires that a key be named.
Note there is no locking mechanism to prevent two jobs from
updating the same entry at the same time. You must ensure
this such as in this example by placing the user index is in
QTEMP. You could consider locking the user index with ALCOBJ.
** TXT200. A check for errors occurs and if UIMSID is not blank,
the program will abort.
** TXT210. A delete will now be requested of key '456'. The key
is placed in MYDS and the data structure is moved to the
UIDATA field.
** TXT220. A request for *DELETE with an *EQ key is made and the
USRIDX program is called. Note that there is probably data in
positions 11-20 of the UIDATA field, but this is ignored and
only the key portion is used.
** TXT230. A check for errors occurs and if UIMSID is not blank,
the program will abort.
** TXT240. The READ subroutine is used again to list the entries
in sequential order.
** TXT250. The USRIDX program is kept open after each call to
allow faster processing. To end the program with LR on, a
*CLOSE request is made and the USRIDX program is called. The
activation group used for the USRIDX program is destroyed.
Any UIDATA value is ignored and none is passed back. A check
for errors occurs and if UIMSID is not blank, the program will
abort.
** TXT260. The SNDERR routine is used any time there is an error
in the UIMSID field that is not handled by the program. For
example, the program considered a TAA9891 value as meaning
'end of entries' when a *READ was used to process sequentially
by key.
To provide for feedback relating to error conditions, the
current contents of IDXDS (the data structure passed to the
USRIDX program) is moved to the MSGDS data structure which is
512 bytes in length. The SNDDIAG TAA program is called to
send the text as a diagnostic message. The message will thus
describe the first 512 bytes of the data structure last sent
to the USRIDX program.
The SNDDIAG program is used again to send the message text
that was returned by the USRIDX program in the UIMSTX field.
The message will begin with the message ID received from an
API (or created by USRIDX) followed by the message text.
The program then calls the TAA ABORT program which will
abnormally terminate the program with an escape message
(TAA9861).
Format of TAAIDXAP Externally Described Data Structure
------------------------------------------------------
UINM The User Index name. 10 bytes in positions 1-10.
UILIB The User Index library name. 10 bytes in positions
11-20.
UIOPCD The Operation code. 7 bytes in positions 21-27.
The following are valid (some operations are
modified by the UISCOD field).
*READ - Reads one entry
*WRITE - Writes one entry
*UPDATE - Updates one entry
*DELETE - Deletes one entry
*CLEAR - Clears all entries
*CLOSE - Closes the processing program. This
should be used when a program calls TAAIXDAR5.
The activation group for TAAIXDAR5 is
destroyed.
UISCOD The Search code. 6 bytes in positions 28-33. The
values *EQ, *GT, *LT, *GE, *LE, *FIRST (first
entry), and *LAST (last entry) are supported. The
search code is used with *READ, *ADD, *UPDATE, and
*DELETE operations.
The value is ignored for *CLEAR and *CLOSE.
When *FIRST or *LAST is specified, the UIDATA field
is ignored.
UIDATA The entry data. 2000 bytes in positions 34-2033.
The length of the key portion (high order bytes) is
determined by accessing the attributes of the user
index. The length of the data portion is determined
by subtracting the length of the key from the entry
length defined for the user index.
For *READ operations, only the key portion is
used. The data portion is ignored. If an
entry is found, both the key and the data are
returned.
For *WRITE operations, both the key and the
data portion are used. The value of UIDATA is
not changed.
For *UPDATE operations, both the key and the
data portion are used. The value of UIDATA is
not changed. Note that it is valid to request
a UISCOD value such as *GT in which case the
key higher than the one specified is updated.
The key of the entry that was updated is not
returned.
For *DELETE operations, only the key portion is
used. The value of UIDATA is not changed.
For *CLEAR operations, the UIDATA value is
ignored.
For *CLOSE operations, the UIDATA value is
ignored.
UIMSID The message ID field. 7 bytes in positions
2034-2040. This field must be checked after each
operation to ensure valid results. The user index
program does not return escape messages.
TAA9891 will be returned if no entry is found on a
*READ, *UPDATE, or *DELETE operation. Note that
when reading sequentially, TAA9891 means no more
entries exist ('end of entries').
Any error messages sent from the APIs used will be
returned. For example, CPF3C74 is returned if a
duplicate key is attempted to be written by a *WRITE
request.
UIMSDT The message data field. 256 bytes in positions
2041-2296. Any message data for an error message
will be placed in this field.
For a *CLEAR operation, the number of entries that
were cleared is placed in the first 10 bytes as a
zoned value.
UIMSTX The message text field. 512 bytes in positions
2297-2808. The complete text of the message if an
error occurs.
Using an ILE bound program
--------------------------
The TAAIDXAR98 and TAAIDXAR99 RPG members contain the QUSEC error
data structure and all the prototypes. Use CPYTAA as follows to
extract the source:
CPYTAA TAAARCMBR(TAAIDXAR98)
CPYTAA TAAARCMBR(TAAIDXAR99)
This places the source in the QATTRPG file in TAATOOL.
The following items should be in the users source.
h bnddir('TAATOOL/TAADIXA')
/ copy taatool/qattrpg/TAAIDXAR98
/ copy taatool/qattrpg/TAAIDXAR99
All the ILE functions are provided by the DoUsrIdxOp (do user index
operation) subprocedure using parameters for the fields described for
the TAAIDXAP data structure. Note that you do not need the TAAIDXAP
data structure.
Sample ILE programs exist that cause 3 entries to be written to a
user index. You may try these programs by:
CALL TAAIDXAC7
This creates the user index object and calls the RPG ILE program
TAAIDXAR7. The DSPUSRIDXA command is used to display the results.
You can review the code with the command:
DSPTAA TAAARCMBR(TAAIDXAR7)
Review and recommendations
--------------------------
** To access by key, you must place the key in the UIDATA field
before doing a read.
** If you are using the TAAIDXAP externally described data
structure in either an OPM or ILE program, you must remember
to move your data (probably a data structure) to the UIDATA
field before making a write request. Conversely, you must
remember to move from the UIDATA field to your data (probably
a data structure) after a successful read operation.
** If you have decimal values, you probably want to keep them in
zoned format to simplify debugging. This allows the DSPUSRIDX
TAA command to be used normally without requesting a display
by hex value.
** Assuming you use a data structure for your data, it can be
helpful to separate the fields by a blank value to simplify
reviewing the data with DSPUSRIDX.
Escape messages you can monitor for
-----------------------------------
None.
The call to the supplied programs should always complete normally.
You are responsible for checking the UIMSID field. If blank, the
request was successful.
TAA9891 will be returned for a *READ, *UPDATE, or *DELETE request
when the key does not exist (such as no more entries can be found to
be read).
Other message IDs may be sent by the APIs used.
Restrictions
------------
Only fixed length keyed user indexes are supported with a maximum
length of 2000 bytes.
The maximum supported size is 4GB.
Prerequisites
-------------
The following TAA Tools must be on your system:
ABORT Abort
CRTUSRIDX Create user index
DSPLSTSPLF Display last spooled file
DSPUSRIDXA Display user index attributes
SNDDIAG Send diagnostic message
SNDSTSMSG Send status message
Implementation
--------------
None, the tool is ready to use.
Objects used by the tool
------------------------
Object Type Attribute Src member Src file
------ ---- --------- ---------- ----------
TAAIDXAC6 *PGM CLP TAAIDXAC6 QATTCL
TAAIDXAC7 *PGM CLP TAAIDXAC7 QATTCL
RPGLE TAAIDXAR QATTRPG
TAAIDXAR4 *PGM RPGLE TAAIDXAR4 QATTRPG
TAAIDXAR6 *PGM RPG TAAIDXAR6 QATTRPG
TAAIDXAR7 *PGM RPGLE TAAIDXAR7 QATTRPG
TAAIDXAR98 TAAIDXAR98 QATTRPG
TAAIDXAR99 TAAIDXAR98 QATTRPG
TAAIDXA *SRVPGM TAAIDXAR QATTRPG
TAAIDXA *BNDDIR
TAAIXDAR creates a module for the TAAIDXA *SRVPGM.
The test programs TAAIDXAC6, TAAIDXAC7, TAAIDXAR6, and TAAIDXAR7
require the tool commands (CRTUSRIDX, RTVUSRIDXA, and DSPUSRIDXA) to
exist. An escape message occurs during the create if they do not
exist stating that CRTTAATOOL should be used for the 3 tools and then
USRIDX again.
|