Menu

Using 'EXTERNAL' to get around VBIsam sharing problem.

David Wall
2020-06-15
2021-12-26
  • David Wall

    David Wall - 2020-06-15

    I rather prefer using VBIsam over BDB for Indexed files as the 'data' file is a plain text file.
    I have a need to be able to access the 'same' indexed file in program A and then whilst that
    file is still open - have program A call program B which also reads the 'same' indexed file.
    Since VBIsam presently is unable to 'share' indexed files I thought I would try using 'EXTERNAL.
    Having the indexed file described as EXTERNAL 'should' enable it to be used at the same
    time in both the calling & called programs.
    I wrote 3 programs - A creates an indexed file - reads a record - displays it then calls program B.
    B opens the file shared - reads a record - then calls program C. C reads a record displays it then ends.

    Program B displays correctly because program A closes the file - but program C crashes with:
    libcob: TSTPRG6C.cbl:26: error: file already open (status = 41)
    for file FILA ('TSTPRG6' => C:\TEST\TSTPRG6) on OPEN
    libcob: TSTPRG6C.cbl:26: warning: implicit CLOSE of FILA ('TSTPRG6')

    I've attached the 3 simple programs if anyone's interested in what I'm doing wrong.

    I'd really like to get EXTERNAL files working because VBIsam can't share files at present.

     
    • David Wall

      David Wall - 2020-06-16

      Then again - I note with interest the Programming guide says this:
      2.2.8.1. File Sharing
      GnuCOBOL controls concurrent-file access at the highest level through the concept of file shar-
      ing, enforced when a program attempts to open a file. This is accomplished via a UNIX
      operating-system routine called "fcntl()". That module is not currently supported by Win-
      dows and is not present in the MinGW Unix-emulation package. GnuCOBOL builds created
      using a MinGW environment will be incapable of supporting file-sharing controls
      files will
      always be shared in such environments.

      Perhaps this is not actually the case..

       
      • Simon Sobisch

        Simon Sobisch - 2020-06-16

        @vcoen Can you please adjust that part of the PG? GnuCOBOL uses whatever is available to create and release locks and if "nothing" is available then there are still:

        • the OS taking care of file locks and sharing
        • for ORGANIZATION IS INDEXED - the indexed handler (which in the BDB case is only active if DB_HOME is set to the same directory for all COBOL processes that want to use the same indexed files); possibly only rudimentary but then at the DB level for the new SQL handlers in trunk

        One may could say that the control is possibly not as fine-graned in Win32/DOS (not only MinGW) in general, but even there they are not "always shared".

         
        • Vincent (Bryan) Coen

          This is too indefinite i.e., if and but.

          When you get an actual precise process for users I can change it but at the moment it looks like it is a heavy may be for, - well any thing.

          It is some times flacky under Linux (use of DB_HOME etc some times does not work with and without.

          So I will keep it as it is for the moment.

           
    • Simon Sobisch

      Simon Sobisch - 2020-06-16

      Concerning BDB you may want to use db_dump to get a plain textfile (which would obviosuly not work well if you have binary fields in there).

      Since VBIsam presently is unable to 'share' indexed files ...

      It definitely is. What exact version do you use? Please provide a sample program to reproduce it.

      To the EXTERNAL issue - an EXTERNAL file shares the open and record positions, therefore the error message is completely correct.

       
      • David Wall

        David Wall - 2020-06-16

        I refer to a discussion earlier this year.
        https://sourceforge.net/p/open-cobol/discussion/cobol/thread/630d1a2d/#918e/e6c5/5edf/be52/378f

        Where I supplied the 'almost' identical 3 programs showing that using open I-o sharing all FILE
        didn't appear to work.

        I'm using VBIsam 2.0.1 which I believe is the same version that Arnold uses for the 'official' releases - although I have tried 2.1.1 with similar 'no worky' results.

        I don't know what your definition of 'sharing' is - but mine is that a file is opened shared in one program and another program opening the same file - also shared - can read it.
        That is NOT the case in the original 3 programs - nor the 3 that I attached at the top.
        The 3 at the top I 'attempted' to use EXTERNAL in addition to sharing all.

         
        • David Wall

          David Wall - 2020-06-16

          I've amended the 3 programs and reduced them to 2.
          The first creates an indexed file - closes that file - then reopens it shared all.
          It then reads a record and passes the key to the second program.
          The second program opens the same file shared all - AND CRASHES AT THIS POINT.
          It's supposed to read the passed key - then read the next record and pass that key back.

          It crashes with : libcob: TSTPRG6B.cbl:26: error: file sharing conflict (status = 61) for file FILA ('TSTPRG6' => C:\TEST\TSTPRG6) on OPEN

          That's pretty specific that file sharing doesn't work - isn't it.

           
          • Simon Sobisch

            Simon Sobisch - 2020-06-16

            That's pretty specific that file sharing doesn't work - isn't it.

            Yes. I'm at least investigating this now...

             
  • Ralph Linkletter

    Hey David.
    I use a common I-O routine per dataset.
    If your file access is limited to a single .EXE this technique works for me.
    The common I-O routine services COBOL I-O from programs within the current run unit.
    In your example, program "A", "B", and "C" would have access to the dataset.
    You must replace all COBOL I-O in your application with calls to the common I-O module.
    Example:

               MOVE 'OPOT' TO ZRETPID-FUNC
               CALL ZRETPID USING
                           ZRETPID-FUNC
                           ZPROCESS-ID
                           ZRETPID-STATUS
               MOVE 'ISRT' TO ZRETPID-FUNC
               CALL ZRETPID USING
                           ZRETPID-FUNC
                           ZPROCESS-ID
                           ZRETPID-STATUS
               MOVE 'CLOSE' TO ZRETPID-FUNC
               CALL ZRETPID USING
                           ZRETPID-FUNC
                           ZPROCESS-ID
                           ZRETPID-STATUS.
    

    Here is a snippet of a common I-O routine.
    It has logic in it for VSAM / ISAM support. For instance START, READ NEXT...

           LINKAGE SECTION.
           01  PARM-FUNC                          PIC X(08).
           01  LTRIGGER-DATA.
               05  LTPID-9                        PIC 9(08).
           01  LINK-FILE-STATUS                 PIC X(02).
           PROCEDURE DIVISION USING
                              PARM-FUNC
                              LTRIGGER-DATA
                              LINK-FILE-STATUS.
           A-000-MAINLINE.
               IF FIRST-TIME = '1'
                   MOVE 'GNUDATA' TO READV-KEY
                   MOVE LENGTH OF READV-KEY TO READV-KEY-LEN
                   CALL ZREADENV USING
                                 READV-KEY
                                 READV-KEY-LEN
                                 READV-VALUE
                                 READV-VALUE-LEN
                   IF RETURN-CODE NOT = 0
                       MOVE 'ZRETPID: "GNUDATA" SETTING NOT FOUND'
                        TO ZMSG1
                       CALL ZMSGBOX1 USING
                                     ZMSG1
                       STOP RUN
                   END-IF
                   MOVE SPACES TO TRIGGER-DSN
                   STRING
                       READV-VALUE (1:READV-VALUE-LEN) DELIMITED BY SIZE
                       '\'                        DELIMITED BY SIZE
                       'EXEPID.DAT'               DELIMITED BY SIZE
                   INTO TRIGGER-DSN
                   MOVE '0' TO FIRST-TIME
               END-IF
               IF TRIGGER-OPEN = '1'
                   MOVE LTRIGGER-DATA TO TRIGGER-DATA
               END-IF
               PERFORM B-000-EVALUATE THRU B-000-EXIT.
               IF TEST-FILE-STATUS = '00'
                   IF PARM-FUNC (1:2) NOT = 'OP' AND
                     PARM-FUNC (1:4) NOT = 'CLOS'
                       MOVE TRIGGER-DATA TO LTRIGGER-DATA
                   END-IF
               END-IF.
               MOVE TEST-FILE-STATUS TO LINK-FILE-STATUS.
               GOBACK.
           A-000-EXIT.
               EXIT.
           B-000-EVALUATE.
               EVALUATE PARM-FUNC
                   WHEN 'CLOS    '
                       MOVE 'CLOS' TO LOCAL-FUNC
                       PERFORM B-001-SERVICE-IO THRU B-001-EXIT
                   WHEN 'OPEN    '
                       MOVE 'OPIO' TO LOCAL-FUNC
                       PERFORM B-001-SERVICE-IO THRU B-001-EXIT
                   WHEN 'BROWSE  '
                       MOVE 'OPEN' TO LOCAL-FUNC
                       PERFORM B-001-SERVICE-IO THRU B-001-EXIT
                   WHEN OTHER
                       MOVE PARM-FUNC TO LOCAL-FUNC
                       PERFORM B-001-SERVICE-IO THRU B-001-EXIT
               END-EVALUATE.
           B-000-EXIT.
               EXIT.
           B-001-SERVICE-IO.
               MOVE '0' TO IO-OK.
               MOVE '1' TO FIRST-CALL.
               MOVE '00' TO TEST-FILE-STATUS
               EVALUATE LOCAL-FUNC
                    WHEN 'UPDT'
                      PERFORM B-070-REWRITE THRU B-070-EXIT
                              UNTIL IO-OK NOT = '0'
                    WHEN 'REPL'
                      PERFORM B-070-REWRITE THRU B-070-EXIT
                              UNTIL IO-OK NOT = '0'
                    WHEN 'CLOS'
                      MOVE 'C' TO FILE-STATUS
                      PERFORM B-030-CLOSE THRU B-030-EXIT
                    WHEN 'CLOSE'
                      MOVE 'C' TO FILE-STATUS
                      PERFORM B-030-CLOSE THRU B-030-EXIT
                    WHEN 'DLET'
                      PERFORM B-050-DLET THRU B-050-EXIT
                              UNTIL IO-OK NOT = '0'
                    WHEN 'GET'
                      PERFORM B-010-GU THRU B-010-EXIT
                              UNTIL IO-OK NOT = '0'
                    WHEN 'GN  '
                      PERFORM B-020-GN THRU B-020-EXIT
                              UNTIL IO-OK NOT = '0'
                    WHEN 'GU  '
                      PERFORM B-010-GU THRU B-010-EXIT
                              UNTIL IO-OK NOT = '0'
                    WHEN 'ISRT'
                      PERFORM B-060-ISRT THRU B-060-EXIT
                              UNTIL IO-OK NOT = '0'
                    WHEN 'OPEN'
                      IF TRIGGER-OPEN = '1'
                          MOVE '0' TO TRIGGER-OPEN
                          CLOSE TRIGGER-FILE
                      END-IF
                      PERFORM B-005-OPEN THRU B-005-EXIT
                    WHEN 'OPIO'
                      IF TRIGGER-OPEN = '1'
                          MOVE '0' TO TRIGGER-OPEN
                          CLOSE TRIGGER-FILE
                      END-IF
                      PERFORM B-005-OPEN THRU B-005-EXIT
                    WHEN 'OPOT'
                      IF TRIGGER-OPEN = '1'
                          MOVE '0' TO TRIGGER-OPEN
                          CLOSE TRIGGER-FILE
                      END-IF
                      PERFORM B-005-OPEN THRU B-005-EXIT
                    WHEN 'PREV'
                      PERFORM B-090-GET-PREV THRU B-090-EXIT
                              UNTIL IO-OK NOT = '0'
                    WHEN 'STN<'
                      PERFORM B-040-START-KEY THRU B-040-EXIT
                              UNTIL IO-OK NOT = '0'
                    WHEN 'STN>'
                      PERFORM B-045-START-KEY THRU B-045-EXIT
                              UNTIL IO-OK NOT = '0'
                    WHEN 'SKILL'
                          MOVE '0' TO TRIGGER-OPEN
                          CALL 'CBL_DELETE_FILE' USING
                                                 TRIGGER-DSN
               END-EVALUATE.
           B-001-EXIT.
               EXIT.
           B-005-OPEN.
               IF LOCAL-FUNC = 'OPIO'
                   MOVE '1' TO TRIGGER-OPEN
                   OPEN I-O TRIGGER-FILE
                   MOVE 'B' TO FILE-STATUS
                   MOVE TRIGGER-STATUS TO TEST-FILE-STATUS
                   IF TEST-FILE-STATUS NOT = '00' AND NOT = '35'
                       MOVE 'ZRETPID: OPEN I-O FAILED'
                        TO ZMSG1
                       MOVE TEST-FILE-STATUS TO ZMSG1 (25:2)
                       MOVE TRIGGER-DSN TO ZMSG1 (28:50)
                       CALL ZMSGBOX1 USING
                                     ZMSG1
                       STOP RUN
                   END-IF
                   GO TO B-005-EXIT
               END-IF.
               IF LOCAL-FUNC = 'OPOT'
                   MOVE '1' TO TRIGGER-OPEN
                   OPEN OUTPUT TRIGGER-FILE
                   MOVE 'O' TO FILE-STATUS
                   MOVE TRIGGER-STATUS TO TEST-FILE-STATUS
                   IF TEST-FILE-STATUS NOT = '00'
                       MOVE 'ZRETPID: OPEN OUT FAILED'
                        TO ZMSG1
                       MOVE TEST-FILE-STATUS TO ZMSG1 (25:2)
                       MOVE TRIGGER-DSN TO ZMSG1 (28:50)
                       CALL ZMSGBOX1 USING
                                     ZMSG1
                       STOP RUN
                   END-IF
                   GO TO B-005-EXIT
               END-IF.
               IF LOCAL-FUNC NOT = 'OPIO' AND NOT = 'OPOT'
                   MOVE '1' TO TRIGGER-OPEN
                   MOVE 'I' TO FILE-STATUS
                   OPEN INPUT TRIGGER-FILE
                   MOVE TRIGGER-STATUS TO TEST-FILE-STATUS
                   IF TEST-FILE-STATUS NOT = '00'
                       MOVE 'ZRETPID: OPEN IN FAILED'
                        TO ZMSG1
                       MOVE TEST-FILE-STATUS TO ZMSG1 (25:2)
                       MOVE TRIGGER-DSN TO ZMSG1 (28:50)
                       CALL ZMSGBOX1 USING
                                     ZMSG1
                       STOP RUN
                   END-IF
                   GO TO B-005-EXIT
               END-IF.
           B-005-EXIT.
               EXIT.
           B-010-GU.
               MOVE '0' TO EOD-IO.
               PERFORM B-011-READ THRU B-011-EXIT
                UNTIL EOD-IO NOT = '0'.
               IF TEST-FILE-STATUS = '00'
                   MOVE '1' TO IO-OK
               END-IF.
           B-010-EXIT.
               EXIT.
    

    I use this technique extensively.
    It isn't quite "sharing" - in some aspects it is better.
    A caveat when you locate a postion with START it is advisible to store the READ NEXT value to isolate the file position from one .DLL to another. Reposition on subsequent calls if necessary.

    I presume you could generalize the common I-O routine by using EXTFH.

    Ralph

     
    • David Wall

      David Wall - 2020-06-16

      Thanks Ralph, I'll have a good look through it & see if I can make use of it - the actual set of programs have a maximum of 12 indexed files in them and there are 7 subroutines that would use up to 6 files at any one time - so it may become a bit unweildy, compared to just having 'file sharing' work as described - I'm surprised no-one has come across this before as ISAM files was a big thing back in the good old days.
      I'm converting from another language - that using files in a shared manner just works.

       
      • Ralph Linkletter

        It gets real easy.
        Second nature to me at this point.
        Once you create a common I-O routine for the first time, cloning it is a simple matter for the next data set.
        Using it is simple as well.
        Let me know if you want a fulling working caller and common I-O example set.
        I even use it as a poor man's inter-process communication facility.
        Ralph

         
        • David Wall

          David Wall - 2020-06-16

          Thanks Ralph,

          I'm thinking of maybe just closing each file before I call the called program - hopefully that won't take up too much time and whilst not actually 'sharing' the file - will allow the called program to do its thing.

          I may still take you up on that offer.

          David

           

          Last edit: Simon Sobisch 2020-06-16
  • Simon Sobisch

    Simon Sobisch - 2020-06-16

    Rechecked: the issue is not related to VB-ISAM at all, instead it is related to the issue that GnuCOBOL 3.x doesn't actually support the SHARING clause.
    It looks like trunk won't do the correct thing here, too - but that's an actual easy fix there. I have to see when I find time to work on this :-(
    I may be able to manually merge the SHARING part from trunk (2016 changes, only did not got in so far as they were intermixed with other changes) and then fix this case (+merge the fix back).

     
    • David Wall

      David Wall - 2020-06-16

      Strange that the identical 2 latest programs work fine under BDB where they fail under VBI.
      Identical.!!!

       
    • David Wall

      David Wall - 2021-12-25

      @sf-mensch - Is there any resolve to this - 18 months later ???

       
      • Simon Sobisch

        Simon Sobisch - 2021-12-26

        No. I've lost the track on this and likely won't do much in the next days on this- but it would help if you could create a bug-report for this with the minimal information needed to show the issue - as discussion board entries are much less likely to loose track of.

         

Anonymous
Anonymous

Add attachments
Cancel