|
//--- 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-2024 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.