Topic
IC4NOTICE: developerWorks Community will be offline May 29-30, 2015 while we upgrade to the latest version of IBM Connections. For more information, read our upgrade FAQ.
17 replies Latest Post - ‏2012-05-10T14:52:18Z by SystemAdmin
SystemAdmin
SystemAdmin
535 Posts
ACCEPTED ANSWER

Pinned topic using linear-main procedures

‏2011-08-26T20:55:27Z |
I have a simple linear-main proc. with an F spec inside the proc. The file is apparently automatically opened and closed even though I am doing a return. Is that correct? or is it closed by the *new activation group going away? By eliminating then the RPG cycle, you have to manage the file opens and closes, right?
Updated on 2012-05-10T14:52:18Z at 2012-05-10T14:52:18Z by SystemAdmin
  • barbara_morris
    barbara_morris
    384 Posts
    ACCEPTED ANSWER

    Re: using linear-main procedures

    ‏2011-08-26T22:07:01Z  in response to SystemAdmin
    If you code the file inside the proc, it behaves the same as a local file in any procedure. If it doesn't have the STATIC keyword, it gets opened when the procedure starts and gets closed when the procedure ends. If you do have the STATIC keyword, it gets opened when the procedure is first called, and it never gets closed unless you use a CLOSE opcode, or the activation group ends.

    If you code the file in global F specs, before any P specs, then it behaves the same as a file in a NOMAIN module. It gets opened the first time any procedure in the module is called, and it never gets closed unless you use a CLOSE opcode, or the activation group ends.

    No matter how you code the file, as a global or local, as static or not, the file will be closed when the program ends if you're using the *NEW activation group. For experimenting to find out how files are opened/closed with a linear main, you'll probably learn more if you use a named activation group.
    • SystemAdmin
      SystemAdmin
      535 Posts
      ACCEPTED ANSWER

      Re: using linear-main procedures

      ‏2011-08-27T02:26:13Z  in response to barbara_morris
      Thanks for clearing that up for me Barbara. Your input is helpful as always.
    • Anvil
      Anvil
      2 Posts
      ACCEPTED ANSWER

      Re: using linear-main procedures

      ‏2012-03-28T17:41:20Z  in response to barbara_morris
      What is the "best practice" for defining files when using linear main procedures? Should they be defined in the "global" section (before P specs) or in the local section (after 1st P spec)? When I say "best practice", I mean in terms of performance, maintainability, file management...
      • barbara_morris
        barbara_morris
        384 Posts
        ACCEPTED ANSWER

        Re: using linear-main procedures

        ‏2012-03-29T15:17:30Z  in response to Anvil
        Anvil, a linear main module is very similar to a no-main module.

        This doesn't answer your question, but you may already have some ideas about your question in terms of a no-main module.

        Actually, I'm not sure there is a best practice anyway. It depends on how you want to use the file.

        One thing that's not really common to a no-main module is that when you want all the procedures in the module to use the file, you have two options:
        1. Code it as a global file.
        2. Code it local to the main procedure and pass it around the other procedures as a parameter. That way, you have more control over which procedures have access to the file. And if it's coded without the STATIC keyword, it will automatically get closed when the main procedure returns.

        Below is a working example of coding the file locally in the main procedure and passing it around to the subprocedures. Recoding this to compare how it would look using a global file is "left as an exercise for the keen student" (hehe).

        Try the same exercise for an externally-described file. A global file would mean that all the procedures have access to the file and to the fields in the file which would also be global. Using a local file and file parameters would mean that all the procedures in the module would have to use data structures for I/O. Again, depending on circumstances that might be good (more control over where the data goes) or bad (can feel clumsy and awkward compared to just using the fields directly).

        
        H main(fileParm)   FprtFile_T o    f   80        printer template D prtDs_T         ds            80    template   P fileParm        b FprintFile                            likefile(prtFile_T) F                                     extfile(
        'QPRINT') /free prtHeader(printFile); prtDetail(printFile : 
        'Hello'); prtDetail(printFile : 
        'world'); /end-free P fileParm        e   P prtHeader       b D                 pi D   prtFile                           likefile(prtFile_T) /free print (prtFile : 
        'Some greetings from program FILEPARM'); /end-free P prtHeader       e   P prtDetail       b D                 pi D   prtFile                           likefile(prtFile_T) D   line                        50a   varying 
        
        const /free print (prtFile : 
        '  - ' + line); /end-free P prtDetail       e   P print           b D                 pi D   prtFile                           likefile(prtFile_T) D   line                              likeDs(prtDs_T) 
        
        const /free write prtFile line; /end-free P print e
        
        • Anvil
          Anvil
          2 Posts
          ACCEPTED ANSWER

          Re: using linear-main procedures

          ‏2012-03-29T17:41:59Z  in response to barbara_morris
          In the vast majority of cases I have only 1 procedure in my linear main modules, so, in that case is there a "best practice"? I know there is more coding when it is local because of having to create data structures for input and output of records, but does that inconvenience offset any possible performance gains compared to making the files global? I can see how having multiple procedures in a module might warrant the use of local files based on your philosophy of managing local/global variables in that case...
          • scott_klement
            scott_klement
            242 Posts
            ACCEPTED ANSWER

            Re: using linear-main procedures

            ‏2012-04-02T17:41:40Z  in response to Anvil
            For a single procedure there's no performance difference between a local or global file. Just do whatever makes your code easier to read.
            • barbara_morris
              barbara_morris
              384 Posts
              ACCEPTED ANSWER

              Re: using linear-main procedures

              ‏2012-04-03T15:55:28Z  in response to scott_klement
              Scott is right that there is no difference in performance. At least, there's no difference in the performance for the I/O operations.

              But there could be a difference in the overall performance of your program if you are not careful.

              If you code an ordinary global F spec in a linear main module with no other procedures, the file will be implicitly opened when the main procedure is first called, and it will never be closed until it does a CLOSE opcode. (Similar to returning with LR off in a cycle module.)

              If you code the exact same F spec local to a subprocedure, the file will be implicitly opened and closed every time the procedure gets called. (Similar to always setting on LR in a cycle module.)

              If you would always be closing the file at the end of your main procedure and opening it on the next call, then the performance of the local file is the same. But if you want the file to remain open across calls, you have to do a tiny bit more coding to avoid the repeated opens and closes and get the same overall performance as if the file were global.

              If you want your file to remain open when your main procedure ends so that it is still open when the main procedure is called again, then for a local file you need to add the STATIC keyword to the file. That way, the file will be opened the first time the main procedure gets called, and it will only be closed when you use the CLOSE opcode, and the performance will be the same as for a global file.
              • SystemAdmin
                SystemAdmin
                535 Posts
                ACCEPTED ANSWER

                Re: using linear-main procedures

                ‏2012-04-26T19:51:23Z  in response to barbara_morris
                Thanks Barbara and Scott.

                Here is another issue I am unsure about as I begin converting some programs to linear-main. Here is a snippet:

                
                *###### header specifications ######* h option(*nodebugio) h text(*srcmbrtxt) h copyright(
                'My Company, Inc.') h*actgrp(*caller) h*dftactgrp(*no) h ccsid(*
                
                char : *jobrun) h main(ita281b)     *###### global specifications ######* * application constants /copy qcpylesrc,uua1000r   * prototypes *** edit excel template /copy qcpylesrc,ita281b     *###### local specifications ######* p ita281b         b
                


                This SQLRPGLE program (embedded SQL) will only compile when I comment out the activation group related H specs (It will also not let me embed copy sources within each other). Can I not use the 2 commented out H specs with a linear-main, SQLRPG?
                • barbara_morris
                  barbara_morris
                  384 Posts
                  ACCEPTED ANSWER

                  Re: using linear-main procedures

                  ‏2012-04-26T20:58:52Z  in response to SystemAdmin
                  About those two keywords, you can only use them if you specify OBJTYPE(*PGM) for CRTSQLRPGI. I think it defaults to *PGM, but maybe you have a different default.

                  If you're trying to create a module, then you can't have those keywords. They are only allowed with CRTSQLRPGI OBJTYPE(*PGM) or CRTBNDRPG.

                  What you could do is code those keywords like this so that they only get used when you are creating a program.
                  
                  /
                  
                  if defined(*crtbndrpg) H dftactgrp(*no) H actgrp(*caller) /endif
                  


                  About the nested /COPY, the SQL precompiler doesn't support that. You have a couple of options

                  • you can compile with CRTSQLRPGI RPGPPOPT(*LVL1) or *LVL2. That will allow the nested /COPY.
                  • you can change one or both of the /COPY directives to /INCLUDE. The two mean exactly the same thing to the RPG compiler, but the SQL precompiler ignores /INCLUDE.
                  • SystemAdmin
                    SystemAdmin
                    535 Posts
                    ACCEPTED ANSWER

                    Re: using linear-main procedures

                    ‏2012-04-27T13:06:13Z  in response to barbara_morris
                    Got it to work! Thanks.
                  • SystemAdmin
                    SystemAdmin
                    535 Posts
                    ACCEPTED ANSWER

                    Re: using linear-main procedures

                    ‏2012-04-27T13:13:02Z  in response to barbara_morris
                    As always, thanks for your help.

                    I seems that WORKSTN files don't mix as easily with the linear-main module as DISK files do, especially when using the INFDS and INDDS structures. I had to end up defining them globally instead of locally. Am I missing something, or are they a little quirky when defined locally?
                    • barbara_morris
                      barbara_morris
                      384 Posts
                      ACCEPTED ANSWER

                      Re: using linear-main procedures

                      ‏2012-04-27T16:28:12Z  in response to SystemAdmin
                      What do you mean by quirky? Did you get a compile-time error or a run-time error or strange results or ... ?

                      For what it's worth, this works for me:
                      
                      H main(mypgm) D mypgm           pr                  extpgm(
                      'MYPGM')   P mypgm           b Fmydspf    cf   e             workstn infds(infds) F                                     indds(indds) D infds           ds           100 D indds           ds            99 
                      // ... P mypgm           e
                      
                      • SystemAdmin
                        SystemAdmin
                        535 Posts
                        ACCEPTED ANSWER

                        Re: using linear-main procedures

                        ‏2012-05-09T16:47:27Z  in response to barbara_morris
                        Well one thing that is different in my pgm is that I am defining INFDS and INDDS in the global section (it is included as part of an application constants copysrc). Would that matter?
                        • barbara_morris
                          barbara_morris
                          384 Posts
                          ACCEPTED ANSWER

                          Re: using linear-main procedures

                          ‏2012-05-09T17:32:30Z  in response to SystemAdmin
                          Maybe it would matter. It sounds like you are seeing a difference. In your earlier post you said you ended up having to define the INFDS and INDDS globally.

                          What problem were you having when you defined them locally that got fixed when you defined them globally?
                          • SystemAdmin
                            SystemAdmin
                            535 Posts
                            ACCEPTED ANSWER

                            Re: using linear-main procedures

                            ‏2012-05-09T17:45:49Z  in response to barbara_morris
                            It does not compile. I get: File ITA290AD and INFDS KEYBOARD not defined with the same owning procedure and storage type

                            Here is the code:

                            
                            * standard header specs /copy qcpylesrc,uua1001r h main(ita290a)     *###### global section ######* * workstation configuration *** file definition   * application constants /copy qcpylesrc,uua1000r   * prototypes *** label prompt /copy qcpylesrc,ita290a     *###### local section ######* p ita290a         b   * database configuration *** file definitions FIT0200A   IF   E           K DISK    RENAME(IT20Rcd:LablFilter) F                                     
                            
                            static FITA290AD  CF   E             WORKSTN INFDS(Keyboard) F                                     INDDS(Indicators) F SFILE(lblpsfd:lbSC.#LPSRN) f                                     usropn *** file buffers d lbWF            ds                  likerec(lblpwfr:*output) d lbSD            ds                  likerec(lblpsfd:*all) inz d lbSC            ds                  likerec(lblpsfc:*all) inz d lbTl            ds                  likerec(lblpttl:*output) d lbOp            ds                  likerec(lblpopt:*output) d lbNR            ds                  likerec(lblpnor:*output) d lbCm            ds                  likerec(lblpcmd:*output) *** file buffers d lbIn            ds                  likerec(LablFilter:*input)   * procedure 
                            
                            interface d ita290a         pi d  Label                         2a
                            


                            the defs in UUA1000R are as follows:

                            
                            * program status data structure d                sds           263 d UserID                254    263a   * display file indicator representation d Indicators      ds d  dView                 81     81n   inz(*off)                            View Option d  dEdit                 82     82n   inz(*off)                            Edit Option d  dCopy                 83     83n   inz(*off)                            Copy Option d  dDelete               84     84n   inz(*off)                            Delete Option d  dAdd                  86     86n   inz(*off)                            Add Option d  dClrGrid              87     87n   inz(*off)                            Clear Grid d  dHidGrid              88     88n   inz(*off)                            Hide Grid d  dEndGrid              89     89n   inz(*off)                            End of Grid   * representation of which key was pressed on the keyboard d Keyboard        ds d  KeyPressed           369    369 Key Pressed
                            
                            • barbara_morris
                              barbara_morris
                              384 Posts
                              ACCEPTED ANSWER

                              Re: using linear-main procedures

                              ‏2012-05-09T21:51:01Z  in response to SystemAdmin
                              Ah, ok. I guess that does qualify as quirky.

                              I think this only matters for the INFDS. There's no rule like that for INDDS. The reason for the INFDS rule is that the INFDS has to have the same "lifetime" as the file. They both have to be initialized at the same time, which means they have to be in the same procedure, and have to have the same storage type.

                              So if you want to have a local file with an INFDS, you have to also define the INFDS locally, and they both have to have the STATIC keyword, or both not have the STATIC keyword.

                              For your INFDS in the procedure, you could define the INFDS using LIKEDS of the data structure that is brought in through the /COPY file. But then you'd have to refer to the subfield using the qualified name.
                              
                              FITA290AD  CF   E             WORKSTN INFDS(LKeyboard) D LKeyboard       ds                  likeds(Keyboard)   ... 
                              
                              if LKeyboard.KeyPressed = something;
                              

                              It looks like you're already using qualified structures anyway, so that might not be a problem.

                              If you also have /copy files with calculations using that subfield, then you could create another copy file that just has that data structure, that you can /copy within subprocedure. Or you could create additional versions of the calculation copy files that use the LKeyboard.KeyPressed qualified name.

                              Maybe that's too much jumping through hoops just to avoid having a global file. There's nothing necessarily wrong with a global file anyway.
                              • SystemAdmin
                                SystemAdmin
                                535 Posts
                                ACCEPTED ANSWER

                                Re: using linear-main procedures

                                ‏2012-05-10T14:52:18Z  in response to barbara_morris
                                I like having all files in the same "spot" in my programs. I think it makes things less confusing for anyone coming behind me. LIKEDS is a good suggestion, I will have to think about what I want to do to keep them together. Thanks for your help!