01-21-2008 09:23 PM
I don't post questions very often but am a regular viewer. Anyway, while this looks like an RTFM, I couldn't find the answer so I'll ask here:
I want to do 2 passes on an RMS sequential file in a COBOL program i.e. at end-of-file restore the next record pointer back to the beginning for pass 2.
(Doesn't Basic allow RESTORE #chan_number for sequential files?).
In this case it's a COBOL-created SORT file, but I'd like to be able to do it with standard sequential files too i.e. files you can't use the START command with.
Is there way to do this other than closing and re-opening the file?
(I may have forgotten something really obvious, but maybe not...)
Solved! Go to Solution.
01-21-2008 09:55 PM
(like applications which open and close files around every fre#$*)#$ record operation!)
There is a solution, but it's not worth it for the purpose you describe.
The cost of repeating a recent open is pretty low. And the restore / rewind would be back to a buffer which is probaly long gone from the (rms) cache, so no data IO to be saved. There is far more to be gained by tuning the multyblock and multybuffer counts correctly! Did you?
If you already did that, then maybe, just maybe would a rewind be measurable, but I doubt it. It would be cleaner though! 100% agreed!.
You can use DCOB$RMS_CURRENT_RAB to get the RAB address, and use that for a call to SYS$REWIND to go back to the first record, or even set up RFA access to get back to any record.
Here are snippets from sample code I have for the RFA access. SYS$REWIND is trivial.
01 RAB_PT POINTER.
01 RFA_PT POINTER.
01 RAC_PT POINTER.
01 SAV PIC 9(9) COMP VALUE 0.
01 RAC PIC 9(9) COMP VALUE 2.
03 VBN PIC 9(9) COMP VALUE 0.
03 ID PIC 9(4) COMP VALUE 0.
01 FIND_STS PIC 9(9) COMP VALUE 0.
CALL "DCOB$RMS_CURRENT_RAB" GIVING RAB_PT
ADD 16 to RAB_PT GIVING RFA_PT.
ADD 30 to RAB_PT GIVING RAC_PT.
CALL "OTS$MOVE3" USING BY VALUE 6, BY REFERENCE RFA, BY VALUE RFA_PT.
CALL "OTS$MOVE3" USING BY VALUE 1 BY VALUE RAC_PT, BY REFERENCE SAV.
CALL "OTS$MOVE3" USING BY VALUE 1, BY REFERENCE RAC, BY VALUE RAC_PT.
CALL "SYS$FIND" USING BY VALUE RAB_PT GIVING FIND_STS.
DISPLAY "Find STS = ", FIND_STS WITH CONVERSION.
CALL "OTS$MOVE3" USING BY VALUE 1, BY REFERENCE SAV, BY VALUE RAC_PT.
Hope this helps some,
Hein van den Heuvel (at gmail dot com)
HvdH Performance Consulting
01-22-2008 01:25 PM
That's odd! Basic has RESTORE, Fortran has REWIND, Pascal has RESET. I'd have thought the nearest match in COBOL would be START, but as you say, it doesn't work with sequential files.
I'd recommend against playing with RFAs for such a simple issue. CLOSE and OPEN is much simpler, more obvious and portable.
In most languages I'd be recommending coding it as a subroutine "REWIND" to hide the implementation detail, but in COBOL it would probably be simpler just to do the CLOSE and OPEN in line.
01-22-2008 01:59 PM
For the sake of what I want to do, a close and re-open is the best thing. I just wondered if there was a one-command solution.
Hein, the next time I want to delve into RMS Control Blocks from COBOL(!) I'll use the sample you provided. Actually, it looks like DCOB$RMS_CURRENT_RAB and DCOB$RMS_CURRENT_FAB make the job easier than it would have been in the past.
Closing this call.
01-27-2008 08:49 PM
This is an open for input, not a rewind.
>I'd have thought the nearest match in COBOL would be START, but as you say, it doesn't work with sequential files.
You can use it on a dynamic file.
>CLOSE and OPEN is much simpler, more obvious and portable.
Right. You can also use a nice comment about doing a "rewind".