Re: issues with f$file_format lexical function (748 Views)
Reply
Regular Advisor
SAMI AHMAD
Posts: 164
Registered: ‎06-19-2008
Message 1 of 12 (994 Views)

issues with f$file_format lexical function

I am unable to get the number of records in a file using the following

why is "file_length_hint"  not working ? and why **bleep**/rms/stats is showing  File Length Hint (Data Byte Count): -1 (invalid)?

 

the vms version is Alpha 7.3-2

 

$ REC = f$file("A.A","file_length_hint")

$ show sym rec

  REC = "(-1,-1)"

 

$ **bleep**/RMS/stat a.a

 

RMS File Statistics                          24-JUL-2013 15:21:24.39   Page 1

PASDISK5:[MDX.OUTGOING.PROCESSED]A.A;1

 

FILE HEADER

        File Spec: PASDISK5:[MDX.OUTGOING.PROCESSED]A.A;1

        File ID: (46161,486,0)

        Owner UIC: [INTEROP,MDX]

        Protection:  System: RWED, Owner: RWED, Group: RE, World:

        Creation Date:   24-JUL-2013 14:54:40.07

        Revision Date:   24-JUL-2013 14:54:40.07, Number: 1

        Expiration Date: none specified

        Backup Date:     none posted

        Contiguity Options:  none

        Performance Options: none

        Reliability Options: none

        Journaling Enabled:  none

 

RMS FILE ATTRIBUTES

        File Organization: sequential

        Record Format: variable

        Record Attributes:  carriage-return

        Maximum Record Size: 0

        Longest Record: 7

        Blocks Allocated: 61, Default Extend Size: 0

        End-of-File VBN: 1, Offset: %X'001C'

        File Monitoring: disabled

        File Length Hint (Record Count):    -1 (invalid)

        File Length Hint (Data Byte Count): -1 (invalid)

        Global Buffer Count: 0

 

The analysis uncovered NO errors.

 

**bleep**/RMS/STAT A.A

Honored Contributor
Steven Schweda
Posts: 9,089
Registered: ‎02-23-2005
Message 2 of 12 (982 Views)

Re: issues with f$file_format lexical function

Honored Contributor
Steven Schweda
Posts: 9,089
Registered: ‎02-23-2005
Message 3 of 12 (977 Views)

Re: issues with f$file_format lexical function

Trusted Contributor
John McL
Posts: 280
Registered: ‎02-24-2008
Message 4 of 12 (951 Views)

Re: issues with f$file_format lexical function

You can't get recod counts that way.

 

The following command procedure will do it for you, P1 is the target file.

 

$!
$       pipe search/stat 'p1' XYZZY | search sys$input "records searched" | -
                 (read sys$input module_name ; define/job MY_REC &module_name)
$       my_sym = f$trnlnm ("MY_REC", "LNM$JOB")
$       deass/job my_rec
$       recs = f$integer(f$extract(26, 10, my_sym))
$       write sys$output "No of records is ''recs'"
$!
$       exit

 

Modify to suit your purpose...

Honored Contributor
Hein van den Heuvel
Posts: 6,588
Registered: ‎05-19-2003
Message 5 of 12 (944 Views)

Re: issues with f$file_format lexical function

>> You can't get recod counts that way.

 

Yes you can, Steven proved that in his second reply.

 

>> pipe search/stat 'p1' XYZZY

 

1) it is my understanding the an early match if quicker than no-match, so i use "" /WIN=0

2) In any reasonably recent openVMS version SEARCH will define statistics symbols for your convenience.

 

$ define/user sys$output nl:
$ searc /stat /win=0  ""  tmp.tmp
$ show symb sear*
:
  SEARCH$RECORDS_SEARCHED = "13"
$

 Works on all file types, contrary to the file hints.

hth,

Hein

 

 

 

Honored Contributor
Steven Schweda
Posts: 9,089
Registered: ‎02-23-2005
Message 6 of 12 (940 Views)

Re: issues with f$file_format lexical function

Regular Advisor
SAMI AHMAD
Posts: 164
Registered: ‎06-19-2008
Message 7 of 12 (888 Views)

Re: issues with f$file_format lexical function

i found the problem after reading openVMS notes from web ,  f$file("<file name>","file_length_hint")

works only if

  - file type is sequential

  - record type is VAR or VFC

  - volume is ODS-5

 

to fix the problem  I :

 

- generated the FDL for the file

- modified the FDL to correct the file type and record type.

- converted the file using the modified FDL

 

and then  f$file("<file name> ","file_length_hint") worked and gave me the record count.

 

Honored Contributor
Steven Schweda
Posts: 9,089
Registered: ‎02-23-2005
Message 8 of 12 (885 Views)

Re: issues with f$file_format lexical function

Trusted Contributor
John McL
Posts: 280
Registered: ‎02-24-2008
Message 9 of 12 (870 Views)

Re: issues with f$file_format lexical function

Hein,

 

Thanks for the tip but your search command seems to have the search string and the filename the wrong way around.

 

Also, I found that I was seeing error messages, so ...

 

$ def/user sys$output nl:
$ def/user sys$error  nl:
$ search/stat/win=0 [-]login.com XYZZY

 

(If sys$error not redefined or messages not disabled, here you'll see "%SEARCH-I-NOMATCHES, no strings matched")


$ sho sym search*
  SEARCH$CHARACTERS_SEARCHED = "2300"
  SEARCH$FILES_SEARCHED = "1"
  SEARCH$LINES_PRINTED = "0"
  SEARCH$RECORDS_MATCHED = "0"
  SEARCH$RECORDS_SEARCHED = "94"

Occasional Contributor
cachaza
Posts: 5
Registered: ‎10-18-2012
Message 10 of 12 (767 Views)

Re: issues with f$file_format lexical function

Hi : ...i dont speak english...only spanish (Chile-south America).....

I know a way to calculate de records quantity ..without read the file ,but only for sequential file (fixed format)

1.- dcl : receive de file name by parameter,extract and send file attributes to a cobol program.

2.- Cobol: calculate de records quantity and display it....send this quantity to dcl too.

3.- below you will find dcl + cobol

 

$ Set NoVer

$ Status:= " "

$ Ws    := "Write Sys$output "

$ On Error Then Goto Err_Com

$!----------------------------------------------------------------*

$! El Pgma Cobol Util_ctareg.sco Devuelve La Variable "Numregs",  *

$! La Cual Contiene El Numero De Registros Que Tiene El Archivo   *

$! Nota: solo acepta archivos Secuenciales de Largo Fijo          *

$!----------------------------------------------------------------*

$  Archivo :='P1'

$  Archivo = F$edit(archivo,"upcase,trim,compress")

$  Archivo = F$string(archivo)

$  Ws " Archivo Ingresado : ''Archivo'"

$!-----------------------------------------------------------------------------------------------*

$  parOrg  = f$file_attributes(archivo,"org")

$  if  parOrg.NeS. "SEQ"

$      then

$      Ws "*** Error : Este archivo NO es Secuencial ***"

$      Exit

$  endif

$!

$  parRfm  = f$file_attributes(archivo,"rfm")

$  if  parRfm.NeS. "FIX"

$      then

$      Ws "*** Error : Solo admite registros de Largo Fijo ***"

$      Exit

$  endif

$!-----------------------------------------------------------------------------------------------*

$  Pareof  = F$file_attributes(archivo,"eof")

$  Pareof9 = F$fao("!(09ZL)",f$integer(pareof))

$!---------------------------------------------------*

$  Parffb  = F$file_attributes(archivo,"ffb")

$  Parffb9 = F$fao("!(09ZL)",f$integer(parffb))

$!---------------------------------------------------*

$  Parmrs  = F$file_attributes(archivo,"mrs")

$  Parmrs9 = F$fao("!(09ZL)",f$integer(parmrs))

$!-----------------------------------------------------------------------------------------------*

$!=====================================================

$  Run/nodeb Dka1:[optiafc.cta.exe]util_ctareg.exe

$!=====================================================

$! Ws " Numero De Registros Recibido: ''Numregs'"

$ If  Status.eqs."-1"

$     Then

$      Ws "***===>>> Util_ctareg  Mal-Mal-Mal <<<===***"

$ Else

$      Ws "***===>>> Util_ctareg  Ok-Ok-Ok    <<<===***"

$ Endif

$!

$ Exit

$!

$!--------

$ Err_Com:

$!--------

$    Set Nover

$    Ws "***===>>> Util_ctareg con ERROR a nivel de .Com <<<===***"

$    Exit

$!-----------------------------------------------------------------------------------------------*

 

 IDENTIFICATION DIVISION.

*************************

 PROGRAM-ID.       UTIL_CTAREG.

*AUTHOR              CACHAZA.

 ENVIRONMENT DIVISION.

**********************

 CONFIGURATION  SECTION.

*=======================

 SPECIAL-NAMES.

*--------------

       DECIMAL-POINT IS COMMA.

 DATA DIVISION.

***************

 WORKING-STORAGE SECTION.

*========================

*

 01 VARIABLES-INICIO.

    02  PAR-EOF9               PIC  9(09).

    02  PAR-FFB9               PIC  9(09).

    02  PAR-MRS9               PIC  9(09).

    02  WS-PIC9                PIC  9(09).

    02  WX-LARGO               PIC  9(04) COMP.

    02  NUM-REG                PIC  9(12) COMP.

    02  NUM-REGZ               PIC  ZZZ.ZZZ.ZZZ.ZZ9.

*

********************

 PROCEDURE DIVISION.

********************

 AAXX.

           INITIALIZE VARIABLES-INICIO

*

           CALL "LIB$GET_SYMBOL" USING BY DESCRIPTOR "PAREOF9", PAR-EOF9,

                                    BY REFERENCE WX-LARGO.

           IF  WX-LARGO = 0

               DISPLAY "PARAMETRO PAR-EOF9 NO DEFINIDO. CANCELA . . ."

               STOP RUN.

*

           move  0  to  WX-LARGO

           CALL "LIB$GET_SYMBOL" USING BY DESCRIPTOR "PARFFB9",PAR-FFB9

                                    BY REFERENCE WX-LARGO.

           IF  WX-LARGO = 0

               DISPLAY "PARAMETRO PAR-FFB9 NO DEFINIDO. CANCELA . . ."

               STOP RUN.

*

           move  0  to  WX-LARGO

           CALL "LIB$GET_SYMBOL" USING BY DESCRIPTOR "PARMRS9",PAR-MRS9

                                    BY REFERENCE WX-LARGO.

           IF  WX-LARGO = 0

               DISPLAY "PARAMETRO PAR-MRS9 NO DEFINIDO. CANCELA . . ."

               STOP RUN.

*

           IF  FUNCTION REM (PAR-MRS9 , 2) = 1

               ADD 1 TO PAR-MRS9

           END-IF.

*

           COMPUTE NUM-REG ROUNDED = (((( PAR-EOF9 - 1 ) * 512 ) + PAR-FFB9 ) / PAR-MRS9 )

           MOVE NUM-REG  TO  NUM-REGZ

*

           DISPLAY "*--------------------------------------------------*".

           DISPLAY "*** ==== > ARCHIVO TIENE:"NUM-REGZ CONVERSION" REGS"

           DISPLAY "*--------------------------------------------------*".

           CALL "LIB$SET_SYMBOL" USING BY DESCRIPTOR "NUMREGS",NUM-REG

           STOP RUN.

*****************************************************************************

*****************************************************************************

*****************************************************************************

Occasional Visitor
Hein_vdHeuvel
Posts: 1
Registered: ‎04-09-2010
Message 11 of 12 (759 Views)

Re: issues with f$file_format lexical function

Thank you cachaza for your contribution. It is clear enough.

 

You are correct, IF-and-only-IF, the file is fixed length record sequential then you can calculate the number of records from eof-block * 512 + ffb / size. 

Note: Size should be picked up from LRL, not MRS, and should be rounded up to even value before dividing.

I the file is larger than 2GB (4194303 blocks) you indeed need a (cobol) helper program to do the math with more than 32 bits, but for most files you can just use DCL divides.

 

Too bad that RMS does not do file-length-hints for this easy file type huh!

 

I had an Email exchange with John... Searching for and empty string makes sure that there is an immediate hit for each record, so that's quicker and lookign at each bytes. Also, this avoids the 'no match found' message to sys$error.

 

Cheers,

Hein

 

 

 

Esteemed Contributor
H.Becker
Posts: 370
Registered: ‎04-09-2009
Message 12 of 12 (748 Views)

Re: issues with f$file_format lexical function

COMPUTE NUM-REG ROUNDED = (((( PAR-EOF9 - 1 ) * 512 ) + PAR-FFB9 ) / PAR-MRS9 )

 

>You are correct, IF-and-only-IF, the file is fixed length record sequential then you can calculate the number of records from eof-block * 512 + ffb / size. 

 

The right formula - subtracting 1 or not - depends on ffb. The one in your Cobol source is correct for ffb>0. The other one  - insert the appropriate parentheses - is correct for ffb==0 (which makes the addition somehow obsolete).

 

$ f:=whatever
$ cre 'f
whatever
 Exit 
$ write sys$output f$file(f,"eof")
1
$ write sys$output f$file(f,"ffb")
10
$ ! here rfm=var and the file size is 10: (eof-1)*512+ffb
$ convert/fdl=tt: 'f 'f.fix/pad=%x20
FILE
ORGANIZATION            sequential
RECORD
CARRIAGE_CONTROL none
FORMAT fixed
SIZE 512
 Exit 
$ write sys$output f$file(f+".fix","eof")
1
$ write sys$output f$file(f+".fix","ffb")
0
$ ! the file size is 512: eof*512+ffb
The opinions expressed above are the personal opinions of the authors, not of HP. By using this site, you accept the Terms of Use and Rules of Participation.