ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

CALL Stack for a given job

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • CALL Stack for a given job

    Hi All,

    I am looking for a sample program which can give entire call stack based on the given job details.
    Regards,
    Vinothkumar S.

  • #2
    Not sure what you want to do with the call stack? (You say "give" the call stack, it is not clear what is to be done with it.)

    If you're looking to print it out, you can do this:
    Code:
    DSPJOB JOB(Z/Y/X) OUTPUT(*PRINT) OPTION(*PGMSTK)
    If you're looking to display it on a 5250 display:
    Code:
    DSPJOB JOB(Z/Y/X) OUTPUT(*) OPTION(*PGMSTK)
    If you are looking to retrieve the details into a program, use the Retrieve Call Stack (QWVRCSTK) API.

    Comment


    • #3
      Hi Scott,

      Thanks for your quick response. During month end process we are planning to kill interactive sessions. Before killing it we need to know the call stack entry. I have see the API QWVRCSTK. But i am not sure how to use this for a given job details.
      Regards,
      Vinothkumar S.

      Comment


      • #4
        ... patiently waiting for the "sql way" (pretty please, someone?)

        Comment


        • #5
          I use this to find the original job in a call stack ... hopefully you can modify it to suit ...

          PHP Code:
          D*  -----  Call Stack API  ---------------------------------
          d FindCaller      PR                  Extpgm('QWVRCSTK')    
          d                             2000a                         
          d                               10I 0                       
          d                                8a   
          CONST                 
          d                               56a                         
          d                                8a   
          CONST                 
          d                               15a                         

          D
          *  -----  Call Stack Data  --------------------------------
          Var             DS          2000                          
          d  BytAvl                       10I 0                       
          d  BytRtn                       10I 0                       
          d  Entries                      10I 0                       
          d  Offset                       10I 0                       
          d  EntryCount                   10I 0                       

          D
          *  -----  Call Stack Job Information  ---------------------
          d JobIdInf        DS                                        
          d  JIDQName                     26a   Inz
          ('*')              
          d  JIDIntID                     16a                         
          d  JIDRes3                       2a   Inz
          (*loval)           
          d  JIDThreadInd                 10I 0 Inz(1)                
          d  JIDThread                     8a   Inz(*loval)           

          D*  -----  Call Stack Program Names  -----------------------
          d Entry           DS           256                          
          d  EntryLen                     10I 0                       
          d  ReqstLvl                     10I 0 Overlay
          (Entry:21)     
          d  PgmNam                       10a   Overlay(Entry:25)     
          d  PgmLib                       10a   Overlay(Entry:35)     
          d VarLen          s             10I 0 Inz(%size(Var))       
          d ApiErr          s             15a                         
          d Caller          s             50a                         
          d WhoCalled       s             10a                         
          d i               s             10I 0                       


          //  ==============================================================
          //  ----- Find the previous program name from the call stack -----
          BegSR GetCallStackInfo;                                           

            
          CallP     FindCaller(Var : VarLen 'CSTK0100' JobIdInf       
                                     
          'JIDF0100' ApiErr );               
            For 
          1 to EntryCount;                                        
              
          Entry = %subst(Var:Offset 1);                               
              
          Caller = %trim(PgmLib) + '/' + %trim(PgmNam);                 
              
          // Ignore c#Pgm1 = FMIFTLOG4                                  
              // Ignore c#Pgm2 = FMIFTLOG41                                 
              // Ignore c#Pgm3 = FMIFTLOG42                                 
              // Ignore IBM programs (Start with Q*)                        
              // Ignore PROC_NAME (should be same as c#Pgm2)                
              
          If ( PgmNam <> PROC_NAME              And                     
                   
          WhoCalled = *blanks              And                     
                   
          PgmNam <> c#Pgm_1                And                     
                   
          PgmNam <> c#Pgm_2                And                     
                   
          PgmNam <> c#Pgm_3                And                     
                   
          %SubSt(PgmNam 1) <> 'Q'                            
                 
          );                                                         
                
          WhoCalled PgmNam;                                         
              Endif;                                                        
              
          Offset Offset EntryLen;                                   
            Endfor;                                                         

            
          FLCHNL = %trim(p@FrmCmd);                                       
            
          FLRQDT = %dec(%char(%date():*iso0):8:0);                        
            
          FLRQTM = %dec(%char(%time():*hms0):6:0);                        

          EndSR;                                                            
          //  ============================================================== 
          Greg Craill: "Life's hard - Get a helmet !!"

          Comment


          • #6
            Hi gcraill,

            I tried the code by providing Jobname, User and Job number in the place of JIDQName.

            But got error "Length or start position is out of range for the string operation (C G D F)" while performing Entry = %subst(Var:Offset + 1);
            Regards,
            Vinothkumar S.

            Comment


            • #7
              My guess is the API has errored and as the example program never checks the apierr, the program is unaware of this. I would suggest this has failed as the example is using a parameter of 1 for the thread indicator (Doco says "specifies that information should be retrieved for the thread that this program is currently running in") but for looking at another jobs call stack, I think it needs to be 2 (specifies that information should be retrieved for the initial thread of the identified job). I would suggest a few changes as follows (changing the job name, user and number as appropriate):

              Code:
              D*  -----  Call Stack API  ---------------------------------
              d FindCaller      PR                  Extpgm('QWVRCSTK')
              d                                     LikeDS(Var)
              d                               10I 0 Const
              d                                8a   Const
              d                                     LikeDS(jobidinf) Const
              d                                8a   Const
              d                                     Like(apierr)
              
              D*  -----  Call Stack Data  --------------------------------
              d Var             DS          2000                          
              d  BytAvl                       10I 0                       
              d  BytRtn                       10I 0                       
              d  Entries                      10I 0                       
              d  Offset                       10I 0                       
              d  EntryCount                   10I 0                       
              
              D*  -----  Call Stack Job Information  ---------------------
              d JobIdInf        DS                                        
              d  JIDQName                     26a
              d   JIDJName                    10a   Overlay(jidqname)
              d   JIDJUser                    10a   Overlay(jidqname : 11)
              d   JIDJNumber                   6a   Overlay(jidqname : 21)
              d  JIDIntID                     16a                         
              d  JIDRes3                       2a   Inz(*loval)           
              d  JIDThreadInd                 10I 0 Inz(2)                
              d  JIDThread                     8a   Inz(*loval)           
              
              D*  -----  API error structure  ----------------------------
              [FONT=courier new]D APIErr          DS                  Qualified
              D  BytesPr                      10i 0
              D  BytesAv                      10i 0
              D  MsgID                         7a  
              D  Reserv                        1a  
              D  MsgDta                      256a [/FONT]
              
              D*  -----  Call Stack Program Names  -----------------------
              d ptrEntry                        *
              d Entry           DS           256    Based(ptrentry)
              d  EntryLen                     10I 0                       
              d  ReqstLvl                     10I 0 Overlay(Entry:21)     
              d  PgmNam                       10a   Overlay(Entry:25)     
              d  PgmLib                       10a   Overlay(Entry:35)     
              d Caller          s             50a                         
              d WhoCalled       s             10a                         
              d Cntr            s             10I 0                       
              
              
              //  ==============================================================
              //  ----- Find the previous program name from the call stack -----
              BegSR GetCallStackInfo;                                           
              
              [FONT=courier new]  apierr.bytespr = %Size(apierr);
                jidjname = 'job name';
                jidjuser = 'job user';
                jidjnumber = 'job number';[/FONT]
                FindCaller(Var : %Size(var) : 'CSTK0100' : JobIdInf : 'JIDF0100' : ApiErr );
              
              [FONT=courier new]  IF  apierr.bytesav = 0;
                   FOR cntr = 1 to entrycount;[/FONT]
                      ptrentry = %Addr(var) + offset + (entrylen * (cntr - 1));
                      caller = %Trim(pgmlib) + '/' + pgmnam;
                         IF  PgmNam <> PROC_NAME    And                     
                             WhoCalled = *blanks    And                     
                             PgmNam <> c#Pgm_1      And                     
                             PgmNam <> c#Pgm_2      And                     
                             PgmNam <> c#Pgm_3      And                     
                             %SubSt(PgmNam : 1 : 1) <> 'Q';
                            WhoCalled = PgmNam;                                         
                         ENDIF;                                                        
                   ENDFOR;                                                         
              [FONT=courier new]  ENDIF;[/FONT]
              
              ENDSR;                                                                 //  ==============================================================

              Obviously you may want to do something if the apierr.bytesav is not 0. Apierr.msgid contains the error message ID that was received and the apierr.msgdta contains the substitution data.



              Comment


              • #8
                The original coding for the "ApiErr" parameter has a serious error that may have also contributed to the problem.

                Code:
                [FONT=courier new]d ApiErr          s             15a
                 ...
                  FindCaller(Var : %Size(var) : 'CSTK0100' : JobIdInf : 'JIDF0100' : ApiErr );[/FONT]

                The API is expecting an integer in the first four bytes of the error code parameter indicating the length of the parameter. By just coding it as a 15A and not initializing it, the API will get x'40404040' for the first four bytes. That tells the API that the parameter has a length of 1,077,952,576, which is a bit bigger than 15. If the API is reporting an error, it will feel free to update a huge amount of storage which may corrupt some of the storage following the 15A ApiErr field. That corrupted storage might happen to be the Var receiver variable.

                It's extremely important to always code the error-code parameter as a data structure, and to set the integer "bytes-provided" subfield in the first four bytes to a value no larger than the size of the data structure. See john.sev99's example for the correct way to code the parameter, except that I would always code INZ on the API error code data structure definition even if I was going to set the "bytes-provided" subfield in the code.

                Just by the way, when I'm working on a new API call, I set the bytes-provided subfield to zero, so that I get an error in the joblog if the API call fails. I find it much easier to debug the API call using the joblog than using the error code parameter. Once I have the call working, and it's possible that the API may get legitimate errors, I change the "bytes-provided" subfield to a larger value so that the error doesn't go to the joblog, and I change my code to check the "bytes-available" subfield to see if there was an error.

                Comment


                • #9
                  Hi John,

                  It works amazingly. As you suggested i used 2 instead of 1 on JIDThreadInd.

                  Thanks a lot for the solution.
                  Regards,
                  Vinothkumar S.

                  Comment

                  Working...
                  X