Thursday, July 3, 2008

Understanding User Spaces:

Because quite a few of IBM's system-supplied APIs use a user space to store information, it is important to understand what they are and how they work.
Information is stored in a user space as a "stream," similar to a stream file in the IFS. This is different than the physical files we are used to dealing with in our everyday applications. Instead of each set of data being stored in a physical record, each record is a subsection of a stream of data.
When using a user space with an IBM-supplied API, data is normally sectioned by using a data structure. This data structure defines a record of data in the stream in the user space. For example, let's assume that our user space contains information about a customer. The first nine characters contain the customer number, the next 10 contain the last name, and the last 10 contain the customer's first name. The data may appear in a user space as such:
000012457Stone Brad
001248945Johnson Jerry
045542144Anderson Louis
In order to separate out each record from this stream of data, we will use a data structure. The data structure would appear as shown in the following RPG snippet:
D CustomerInfo DS
D CstNumber 9
D CstLName 10
D CstFName 10
In order to parse the data from the user space, we need to move the data structure to the beginning of each record. The data structure then "overlays" the data so we are able to easily access the information. In RPG, this is done with a pointer. The CustomerInfo data structure as shown above would be defined based on a pointer. We then move the position of that pointer to the beginning of each set of data in order to populate the subfields of the data structure with each customer's information.
When doing this, we will also have to know the size of each structure of data. We know that IBM APIs return a "header" that defines, among other things, the start of the data and the length of each entry in the set of data contained within the user space.
The following piece of RPG code defines a standard header that deal with IBM APIs that store information in a user space:
D GenHeader DS

BASED (HeaderPtr)
D OffsetHdr 117 120B 0
D OffsetLst 125 128B 0
D NumLstEnt 133 136B 0
D EntrySize 137 140B 0
As we can see, there are four subfields defined in this data structure. The first, OffsetHdr, is used to define the offset to the header information. Next is the field OffsetLst. This defines the offset to the start of the list information. The list information is the data that we are interested in parsing from the user space.
Next, the NumLstEnt field is used to define the number of entries in the list. This is an important number to know so that as we parse through the list we know when to stop. Finally, the EntrySize field is used to define the size of each entry. This is used so that we know where to reposition our pointer on the next "record" of data in the user space.
We start reading by setting our basing pointer to the OffsetLst value, entering a loop that executes NumLstEnt times, and, for each subsequent iteration of the loop, repositioning our pointer by adding the value stored in EntrySize to our current pointer position.

No comments: