Not sure what is responsible for the change in effect, the RPG or the
API, but the idea of using storage for an input parameter that is the
same memory location as the output parameter is something I would want
to avoid generally. Plus normally I would perform validation that the
size requirement does not exceed the available storage in the receiver.
While the output in the given scenario is to a User Space (*USRSPC)
object, a value that is too large means the effects are merely that an
ugly error will be logged by the API, e.g. MCH2804, before giving
feedback that the API can not complete the request. And although it was
noted that "for V7R1 the second call to the API stopped actually
retrieving the data into the userspace", what the values of
DSPF0100.BytesAvail and DSPF0100.BytesRetn were after the invocation was
unstated; presumably the former matches what was returned on the first
invocation.? If so, then unless the latter shows eight or fewer bytes,
then the results are inconsistent [between what is claimed to have been
returned and what was actually returned]. After the second invocation,
there typically would be another test to ensure the amount of data
returned is expected, before trying to address that data.
Of course if the RPG implements the effect of CONST by copying the
parameter data before the call, then that would make the invocation
work; the compiler, under no obligation either way, may or may not do
so. Perhaps in the past the RPG was making that copy, but perhaps
having gotten smarter, the RPG realized that the temporary copy of the
value was unnecessary; i.e. according to the rules, not according to the
effect seen. Thus, another /resolution/ would have been as simple as
making the second parameter an expression, thus requiring the RPG make
the temporary copy; e.g. DSPF0100.BytesAvail*1 for which the RPG is
obliged to make the temporary copy to store the result of the expression.
If the API had copied the parameter to local storage before writing
anything to the receiver variable, then the invocation also should have
worked. Interesting that the API apparently does not, especially if it
had previously; noting: different security levels potentially could
impact that, due to parameter integrity validation. I tested that the
API apparently does overwrite the storage in the receiver variable in
v5r3 before making a copy of the second argument in its local storage;
tested by removing the CONST specification for the parameter. That test
result also suggests that on v5r3 the CONST specification alone was
sufficient to prevent the issue.... so it seems maybe the RPG changed?
Even if the API does not make a local copy of the parameter value
before writing to the receiver variable, I would not consider that API
to be operating /incorrectly/, but I would consider the API to be
working less than ideally. But based upon my observations on v5r3, what
seems *is a defect* is that the API will return no data, even while
telling the caller that *all data* was returned; i.e. after the second
invocation, retrieving information from a DSPF for which there is
sufficient storage supplied for the receiver, the test
"DSPF0100.BytesAvail=DSPF0100.BytesRetn" evaluates to True. While
arguably it was daft to have addressed output storage as input to the
API, the API still should never claim to have provided all output while
having provided none. It seems then, that the simple fix to the API is
to copy the value from the second argument into local storage, and then
reference that local storage throughout the API. Currently the API must
[at least once, somewhere,] refer to some storage at the address of
second argument that was since-corrupted by its having written data
starting at the address of the first argument.
Regards, Chuck
On 16-Dec-2013 14:07 -0800, Hiebert, Chris wrote:
I have resolved an issue that I wanted to share with everyone.
The issue: on V7R1 QDFRTVFD doesn't appear to process correctly when
the second input parameter (Length of receiver variable ) is inside
the memory of the first parameter (Receiver variable).
http://pic.dhe.ibm.com/infocenter/iseries/v7r1m0/topic/apis/qdfrtvfd.htm
Background:
We went to V7R1 last year and all of our programs went through the
conversion process, most without recompiling.
I had need to update a RPGLE program that was using the QDFRTVFD
API.
The original program was compiled on our test system when our test
system was at v7r1 and our production system was at v5r4.
The program was compiled on v7r1, created for release V5R4, and then
eventually converted to V7R1.
The V5R1 version functioned like this:
Data structure DSPF0100 is based into a Userspace that was created in
QTEMP as auto-extendable.
The program was coded to call the API twice. First to retrieve the
needed size, and second to retrieve the data using that size.
D QDFRTVFD PR EXTPGM('QDFRTVFD')
D Receiver 1A CONST OPTIONS(*VARSIZE)
D Receiverlen 10I 0 CONST
D Dataformat 8A CONST
D Qualfile 20A CONST
D Apierror LIKEDS(Apierrords)
D ptrDSPF0100 S *
D DSPF0100 DS BASED(ptrDSPF0100) QUALIFIED
D BytesRetn 10I 0
D Bytesavail 10I 0
D Offset_QDFFINFO...
D 5U 0
D RcdFmtCount 5U 0
D DspAtrBits 1A
D ScnSizeCount 5U 0
D Offset_SortSeqTable...
D 5U 0
D Source_ccsid 2A
// Retrieve display file description
QDFRTVFD(DSPF0100 :8 :'DSPF0100' :FILE :APIERRORDS);
IF APIERRORDS.BYTESAVAIL = 0;
QDFRTVFD(DSPF0100 :DSPF0100.BytesAvail
:'DSPF0100' :FILE :APIERRORDS);
ENDIF;
On V5R4 and the converted V7R1 the second call correctly retrieves the
data into the userspace.
Once the program was compiled on V7R1 for V7R1 the second call to the
API stopped actually retrieving the data into the userspace.
During debugging I ended up recompiling the program on V7R1 without any
changes, and still the second call does not populate the userspace with
the requested data.
I made a small modification.
Added a work field:
D wkBytes S 10I 0
Modified the second call to use the work field:
// Retrieve display file description
QDFRTVFD(DSPF0100 :8 :'DSPF0100' :FILE :APIERRORDS);
IF APIERRORDS.BYTESAVAIL = 0;
wkBytes = DSPF0100.BytesAvail;
QDFRTVFD(DSPF0100 :wkBytes
:'DSPF0100' :FILE :APIERRORDS);
ENDIF;
Now the data is being returned to the user space just like the prior
(V5R4) version of the program.
As an Amazon Associate we earn from qualifying purchases.