|
//--- forwarded letter -------------------------------------------------------
> X-Mailer: Novell GroupWise 4.1
> Date: Mon, 02 Feb 98 14:34:31 -0700
> From: "David Morris" <dmorris@plumcreek.com>
> To: MIDRANGE-L@midrange.com
> Reply-To: MIDRANGE-L@midrange.com
> Subject: User Index APIs
>
> We have several procedures that use the user index APIs. They are used to
>create and store
variable length keyed information. They work correctly but the API that
retrieves entries seems to
pass back conflicting length and offset information. IE: Place 12 bytes of
information with an
offset of 0 on the user index. The key is 8 bytes, and the data is 4 bytes.
Retrieve the entry by
equal key and the bytes available and returned are both 16. The offset and
length returned are 8
and 12. The four byte entry is in positions 17-20. What are the available
and returned saying?
By ignoring the available and returned parameters it seems to work as expected.
I cannot find any
example to see where we have misinterpreted the parameters.
>
> Does anyone have an example which uses a variable length user index? I
>remember an article a few
years back in one of the magazines that used user indexes to print a sorted
report. I don't
remember if it used fixed or variable length entries. The code we are using
was based on trial and
error testing. It works for the 8 user indexes that we have but it would be
nice to understand what
is going on.
>
> This application used to use data queues but there was a noticeable impact on
>performance when the
length of the information varied by more than about 50%. Variable length
fields in a database
probably would have worked fine but we decided that the user index would
require the least
conversion. After spending a day trying to understand the returned parameters
it probably would
have been a wash.
>
> Thanks for any input,
>
> David Morris
>
>
>
>
>
>
>
>
>
>
>
>
Without seeing your code it is a little difficult to tell however I think you
are just
misinterpreting the data.
There are two sets of BytesAvailable and BytesReturned; one set is in the
IDXE0100 format which
comes back in your receiver variable (RcvVar), the other set is in the Entry
Lengths and Offsets
structure (EntOff).
The two sets are necessary because you provide two related but separate storage
areas to the API.
One for the actual index entries and one for the offsets and lengths (or
description) of the
entries.
For the first set BytesAvailable is the size of the index entry multipied by
the number of entries
returned. BytesReturned is how much the API could give you. This should be
equal to or less than
the value of the second parameter (RcvVarLen). If BytesReturned is less than
the value of RcvVarLen
then BytesAvailable should be equal to BytesReturned; this is how you know you
have received all the
data. If BytesAvailable is greater than BytesReturned then you know the space
you provided was too
small.
For the second set BytesAvailable is the amount of data describing the entries
which could be
returned if you provided enough space. (This is always a multiple of 8).
BytesReturned is the
amount actually provided. This will be less than or equal to the value of the
fourth parameter
(EntOffLen). If BytesReturned is less than or equal to the value of
BytesAvailable you know you
have descriptions for all the entries in RcvVar.
The ideal situation is to ensure that you provide enough space in EntOff to
describe all the entries
in RcvVar. However, because the entries themselves are variable in length it
is impossible to
formulate a relationship between the sizes of theses areas. That is why both
areas have their own
available and returned values.
Your code is supposed to check both sets of values to:
A) know whether all the entries were returned
and
B) whether what was returned is described -- if you have no length/offset value
for an entry you
can't get to it.
So for your situation I think you will find that the BytesAvailable and
BytesReturned values of 16
refer to the length/offset space which has the following structure:
1 EntOff
2 BytesAvailable bin(4)
2 BytesReturned bin(4)
2 FirstEntryLength bin(4)
2 FirstEntryOffset bin(4)
for a total of 16-bytes.
You should also find that the BytesAvaliable and BytesReturned in the RcvVar
structure reflect the
proper values i.e., BytesAvailable = 20 and BytesReturned = 20
1 RcvVar
2 BytesAvailable bin(4)
2 BytesReturned bin(4)
2 FirstEntry char(12)
3 FirstEntryKey char(8)
3 FirstEntryValue char(4)
Perhaps a diagram will help (excuse the poor graphics):
Assume a key of 'ABCDEFGH' -- 8 bytes; and a value of 1234 -- 4 bytes. The
receiver variable and
entry offset structure will contain the following values:
RcvVar : | 20 | 20 | ABCDEFGH | 1234 |
EntOff : | 16 | 16 | 8 | 12 |
The code checks that we have all the entries by comparing RcvVar.BytesAvailable
with
RcvVar.BytesReturned. It also checks that we can access all the entries via
there offsets by
comparing EntOff.BytesAvailable with EntOff.BytesReturned. If these values are
OK (Note that you
can do partial processing based on the returned length/offset values and then
fetch the rest) then
we start processing the RcvVar entries. See how the value of
EntOff.FirstEntryOffset is the number
of bytes from the start of RcvVar to the FirstEntry subfield? The value of
EntOff.FirstEntryLength
is the number of bytes used by the FirstEntry subfield.
Now, in the normal course of events you would not use static structures as
above. You would use a
based structure and increment the pointer (on which the structure is based) by
the offset and
extract the data according to the length. That way you are not tied to the
structure of the data.
DCL 1 RcvVar CHAR(2567),
2 BytesAvailable BIN(4),
2 BytesReturned BIN(4)
2 Start CHAR(1);
DCL 1 EntOff CHAR(64), /* Should be multiple of 8 -- here room for 7
descriptions */
2 BytesAvailable BIN(4),
2 BytesReturned BIN(4),
2 Start CHAR(1);
DCL SPP @PtrToRcvVar:
DCL SPP @PtrToEntry;
DCL SPP @PtrToOffset;
DCL 1 EntryStruct CHAR(256) BASED(@PtrToEntry), /* Assuming 256-bytes is the
largest entry */
2 IdxEntryKey CHAR(8), /* Note that the key portion is always a fixed
size */
2 IdxEntry CHAR(248); /* Enough room for the largest data entry - not
really required */
DCL 1 OffsetStruct BASED(@PtrToOffset),
2 EntryLen BIN(4),
2 EntryOffset BIN(4);
/* Check that we have enough descriptions and entries */
IF RcvVar.BytesAvailable <> RcvVar.BytesReturned
/* do something about it */
END;
IF EntOff.BytesAvailable <> EntOffBytesReturned
/* do something about it */
END;
@PtrToRcvVar = ADDR(RcvVar); /* Point to start of the receiver variable */
@PtrToOffset = ADDR(EntOff.Start); /* Point to the start of the len/off values
*/
DO NbrEntries; /* Returned by the API */
@PtrToEntry = @PtrToRcvVar + EntOff.EntryOffset;
/* First time through EntryStruct is providing a view of the first entry */
/* do something with the data: EntryStruct.IdxEntryKey references the key value
*/
/* EntryStruct.IdxEntry references the entry value
*/
/* OffsetStruct.EntryLen is the total size of the
entry */
@PtrToOffset = @PtrToOffset + SIZEOF(OffsetStruct); /* Point to next entry
description */
/* Next time through loop we get the next entry */
ENDDO;
Clear as mud, eh?
Regards,
Simon Coulter.
//----------------------------------------------------------
// FlyByNight Software AS/400 Technical Specialists
// Phone: +61 3 9419 0175 Mobile: +61 3 0411 091 400
// Fax: +61 3 9419 0175 E-mail: shc@flybynight.com.au
//
// Windoze should not be open at Warp speed.
+---
| This is the Midrange System Mailing List!
| To submit a new message, send your mail to "MIDRANGE-L@midrange.com".
| To unsubscribe from this list send email to MIDRANGE-L-UNSUB@midrange.com.
| Questions should be directed to the list owner/operator: david@midrange.com
+---
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2025 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.