ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

List of thread api

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

  • List of thread api

    HI all,

    I'm doing an utility relative to list the thread of a job with the api: QWCOLTHD (open list of thread), then I recursive get the list entry by the api Get List Entries (QGYGTLE), but I don't understand the mechanism of this api work. Because I open the list, and then every 5 minutes I get the list entry, but it seems that the list is not refreshed, because the amount of cpu time elapsed by thread is always the same, and the number of thread is still the same. Do I have to make something to refresh the list opened? Here's my utiliy...

    Code:
    **free
    Ctl-opt
      DftActGrp(*no) ActGrp('QILE')
      Bnddir('AL400MNUV2':  'ROBERTO')
      Option(*NoUnRef :*SrcStmt :*NoDebugIo)
      Datfmt(*iso) Timfmt(*iso)
      Thread(*Concurrent)
      Debug
      DftName(APACHETH1R)
      Alwnull(*usrctl);
    //?                                                                   
    
    //??List thread in a Job                                            
    
    dcl-pr APACHETH1R extpgm('APACHETH1R');
    end-pr APACHETH1R;
    
    dcl-pi APACHETH1R;
    end-pi APACHETH1R;
    
    
    //? List Thread                          
    dcl-pr ListThread extpgm('QWCOLTHD');
     *n char(65535); // RcvVar
     *n int(10) const; // RcvVarLen
     *n char(8) const; // Format
     *n char(65535); // RcvVarDefInf
     *n int(10) const; // RcvVarDefInfLen
     *n char(58) const; // JobName
     *n char(8) const; // FmtJobName
     *n char(80); // ListInf
     *n int(10) const; // NumRecReturned
     *n char(16) const; // SortInf
     *n int(10) const; // NumFieldToReturn
     *n int(10) const dim(200); // KeyFields
     *n char(1) const; // ResetStatistics
     *n likeds(qwcgrd); // GeneralData
     *n int(10) const; // GeneralDataLen
     *n char(116); // Error
    end-pr;
    
    //? Get open list entry:                 
    dcl-pr GetOpenlistEntry extpgm( 'QGYGTLE' );
     *n char(65535) options( *varsize ); // RcvVar
     *n int(10) const; // RcvVarLen
     *n char(4) const; // Handle
     *n char(80); // LstInf
     *n int(10) const; // NbrRcdRtn
     *n int(10) const; // RtnRcdNbr
     *n char(1024) options( *varsize ); // Error
    end-pr;
    
    //? Close List                           
    dcl-pr CloseList extpgm('QGYCLST');
     *n char(4); // RequestHandle
     *n char(116); // Error
    end-pr;
    
    
    //?HEX to CHAR
    dcl-pr HexToChar extproc('cvthc');
     *n pointer value; // Char
     *n pointer value; // Hex
     *n int(10) value; // CharSize
    end-pr;
    dcl-s CharThreadId char(16);
    
    //?                                        
    //?  CmdExec - Execute CL Command
    dcl-pr Cmd int(10) extproc('system');
     *n pointer value options(*string); // CmdString
    end-pr;
    dcl-s Command char(32000);
    //?                                        
    dcl-pr sleep uns(10) extproc('sleep');
     *n uns(10) value; // secs
    end-pr;
    
    //?                                        
    dcl-ds DsThdInfo dim(140) qualified;
      ThreadId char(16);
      Cpu      Int(20);
      Status   Char(4);
    end-ds;
    
    dcl-ds ApacheDt1 Len(256) Dtaara qualified;
      Istance   char(10);
      SleepTime Zoned(4);
      Cicli     Zoned(4);
    end-ds;
    
    Dcl-s Cpu  Int(20) dim(140);
    
    Dcl-Ds  DsReturnedData  Qualified template;
      Cpu      Int(20);
      Status   Char(4);
    end-ds;
    //?                                        
    dcl-ds ApiError qualified;
     BytPrv int(10) inz( %size( apierror ));
     BytAvl int(10);
     MsgId char(7);
     *n char(1);
     MsgDta char(128);
    end-ds;
    //?                                        
    //?                                        
    //?Type Definition for the OLTH0100 format.
    //?                                             Qwc OLTH0100
    dcl-ds QWCH0100 based(ptrqwch0100);
    //?                                             ThRead Identifier
     QWCTI03 char(8) pos(1);
    //?                                             ThRead Handle
     QWCTH05 uns(10) pos(9);
     QWCTLDR int(10) pos(13);
    end-ds;
    //?                                             Total Lng Data Rtn
    //?                                        
    //?Type Definition for the OLTH0100 format.
    //?***                                                          ***
    //?NOTE: The following type definition only defines the fixed
    //?   portion of the format.  Any varying length field will
    //?   have to be defined by the user.
    //?                                             Qwc OLTH Receiver InfoData
    dcl-ds QWCTHRID Qualified Based(PtrQWCTHRID);
    //?                                             Length Field Info Rtnd
     QWCLFIR00 int(10) pos(1);
    //?                                             Key Field
     QWCKF00 int(10) pos(5);
    //?                                             Type Of Data
     QWCTOD00 char(1) pos(9);
    //?                                             Reserved
     QWCERVED11 char(3) pos(10);
    //?                                             Length Data
     QWCLD05 int(10) pos(13);
     QWCDTD int(10) pos(17);
     Cpu      Int(20);
     Status   Char(4);
    end-ds;
    //?                                             Displacement To Data
    //?                                        
    //?                                             Qwc OLTH Receiver Informat
    dcl-ds QWCLTHRI inz;
    //?                                             Number Fields Rtnd
     QWCNBRFR int(10) pos(1);
     QWCRI char(20) dim(00001);
     QWCLFIR01 int(10) overlay(qwcri:00001);
     QWCKF01 int(10) overlay(qwcri:00005);
     QWCTOD01 char(1) overlay(qwcri:00009);
     QWCERVED12 char(3) overlay(qwcri:00010);
     QWCLD06 int(10) overlay(qwcri:00013);
     QWCDTD00 int(10) overlay(qwcri:00017);
    end-ds;
    
    //?                                        
    //?Type Definition for List Information
    //?                                             Qwc OLTH List Information
    dcl-ds QWCLTHLI inz;
    //?                                             Total Records
     QWCTR int(10) pos(1);
    //?                                             Records Returned
     QWCRRTN int(10) pos(5);
    //?                                             Request Handle
     QWCRH char(4) pos(9);
    //?                                             Record Length
     QWCRL int(10) pos(13);
    //?                                             Information Complete
     QWCIC char(1) pos(17);
    //?                                             Date Time Created
     QWCDTC char(13) pos(18);
    //?                                             List Status
     QWCLS24 char(1) pos(31);
    //?                                             Reserved
     QWCERVED13 char(1) pos(32);
    //?                                             Information Length
     QWCIL int(10) pos(33);
    //?                                             First Record In Buffer
     QWCFRIB int(10) pos(37);
     QWCRSV204 char(40) pos(41);
    end-ds;
    //?                                             Reserved2
    //?                                        
    //QWCLTHSD         DS                  Inz
    //?                                             Qwc OLTH Sort Data
    //QWCSP03                 1      4B 0
    //?                                             Starting Position
    //QWCKL                   5      8B 0
    //?                                             Key Length
    //QWCDT                   9     10B 0
    //?                                             Data Type
    //QWCSO                  11     11
    //?                                             Sort Order
    //QWCERVED14             12     12
    //?                                             Reserved
    //
    //?                                        
    //?Type Definition for Sort Information
    //?***                                                          ***
    //?NOTE: The following type definition only defines the fixed
    //?   portion of the format.  Any varying length field will
    //?   have to be defined by the user.
    //?                                        
    dcl-s PtrQWCLTHSI pointer inz(%addr(qwclthsi));
    //?                                              Qwc OLTH Sort Information
    dcl-ds QWCLTHSI inz;
    //?                                              Number Sort Keys
     QWCNBRSK int(10);
    //?                                             Starting Position
     QWCSP03 int(10);
    //?                                             Key Length
     QWCKL int(10);
    //?                                             Data Type
     QWCDT int(5);
    //?                                             Sort Order
     QWCSO char(1);
     QWCERVED14 char(1);
    end-ds;
    //?                                             Reserved
    // QWCSK                        12    DIM(00001)
    //  QWCSP04                     10I 0 OVERLAY(QWCSK:00001)
    //  QWCKL00                     10I 0 OVERLAY(QWCSK:00005)
    //  QWCDT00                      5I 0 OVERLAY(QWCSK:00009)
    //  QWCSO00                      1    OVERLAY(QWCSK:00011)
    //  QWCERVED15                   1    OVERLAY(QWCSK:00012)
    
    //?                                       Varying length.
    //?                                        
    //?Type Definition for General return data
    //?***                                                          ***
    //?NOTE: The following type definition only defines the fixed
    //?   portion of the format.  Any varying length field will
    //?   have to be defined by the user.
    dcl-s PtrQwcgrd pointer inz(%addr(qwcgrd));
    //?                                             Qwc General Return Data
    dcl-ds QWCGRD inz;
    //?                                             Bytes Returned
     QWCBRTN05 int(10) pos(1);
    //?                                             Bytes Available
     QWCBAVL06 int(10) pos(5);
    //?                                             Elapsed Time
     QWCET03 uns(20) pos(9);
    //?                                             Job Name Used
     QWCJNU char(10) pos(17);
    //?                                             User Name Used
     QWCUNU char(10) pos(27);
    //?                                             Job Number Used
     QWCJNBRU char(6) pos(37);
     QWCIJI char(16) pos(43);
    end-ds;
    //?                                             Internal Job Identifier
    //?  char Reserved[*];
    //?                         Varying length.
    //?Type Definition for the JIDF0100 format.
    //?****************************************************************
     //?                                             Qwc JIDF0100
    dcl-ds QWCF0100 inz;
     //?                                             Job Name
     QWCJN02 char(10) pos(1);
      //?                                             User Name
     QWCUN char(10) pos(11);
      //?                                             Job Number
     QWCJNBR00 char(6) pos(21);
      //?                                             Int Job ID
     //QWCIJID char(16) pos(27);
     InternalJobId SqlType(Binary :16);
      //?                                             Reserved
     QWCERVED06 char(2) pos(43);
      //?                                             Thread Indicator
     QWCTI00 int(10) pos(45);
     QWCTI01 char(8) pos(49);               //?Thread Id
    end-ds;
    //?Work Variable
    dcl-s OutDataInf varchar(65000);
    dcl-s GeneralData varchar(65000);
    dcl-s GeneralDataLen int(10);
    dcl-s RcvVar char(65535);
    dcl-s RcvVarLen int(10) inz(%size(rcvvar));
    dcl-s Counter int(10);
    dcl-s Idx int(10);
    dcl-s Idx2 int(10);
    dcl-s IdxJob int(10);
    dcl-s Rc     int(10);
    dcl-s RcvVarInfo char(65535);
    dcl-s PJobName char(10);
    dcl-s OutDataInfLen int(10) inz(%size(outdatainf));
    dcl-s NumRec int(10);
    dcl-s NumField int(10);
    dcl-s Stato char(4);
    dcl-s JobName char(10);
    dcl-s Jobuser char(10);
    dcl-s JobNumber char(6);
    dcl-s NumberOfThread Int(10);
    dcl-s HandleRequest char(4);
    dcl-s IpAddr char(46);
    dcl-s ArrayOfKey int(10) dim(200);
    //?Constant
    dcl-c RESETSTATS '1';
    dcl-c NORESETSTATS '0';
    dcl-s FirstCall    Ind Inz(*on);
    //?                                        
    
    Exec Sql Set Option DatFmt = *Iso, TimFmt = *Iso, CloSqlCsr = *EndMod,
                 Commit = *none;
    
    In ApacheDt1;
    
    Dow Not %Shtdn();
    
      If Counter < ApacheDt1.Cicli and Not FirstCall;
        Counter +=1 ;
        Sleep(Apachedt1.SleepTime);
        Iter;
      EndIf;
      FirstCall = *Off;
    
      //?If requested Handle is Blanks I have  to open the list of Thread  
      If HandleRequest = *blanks;
        If ListThreadProc(HandleRequest) < 0;
          Return;
        EndIf;
      EndIf;
    
      ApiError = '';
      QWCLTHLI = '';
      RcvVar   = '';
      GetOpenlistEntry( RcvVar
                      : %Size( RcvVar )
                      : HandleRequest
                      : QWCLTHLI
                      : 200
                      : -1
                      : ApiError);
    
      PtrQWch0100 = %Addr(RcvVar);
      DsThdInfo = '';
    
      Idx2 = 0;
    
      For Idx = 1 To QWCRRTN;
    
        PtrQWCTHRID = PtrQWch0100;
    
        HexToChar (%addr(CharThreadId)
                  : %addr(QWCTI03)
                  : %size(CharThreadId));
    
        If QWCTHRID.Cpu = 0;
          PtrQWch0100 += QWCRL;
          Iter;
        EndIf;
    
    
        Idx2 += 1;
    
        DsThdInfo(Idx2).ThreadId     = %Subst(CharThreadId :9 :8);
    
        DsThdInfo(Idx2).Cpu  = QWCTHRID.Cpu;
        Cpu(Idx2)            = QWCTHRID.Cpu;
        DsThdInfo(Idx2).Status = QWCTHRID.Status;
    
        PtrQWch0100 += QWCRL;
    
      EndFor;
    
      // Voce di Totale
      Idx += 1;
      DsThdInfo(Idx2).ThreadId     = 'SUBTOTALE';
      DsThdInfo(Idx2).Cpu          = %XFoot(Cpu);
      DsThdInfo(Idx2).Status       = %Char(Idx2);
    
      Exec Sql
        Insert into ApacheThread (ThreadId, Cpu, Status)
                  :Idx2 rows Values(:DsThdInfo);
    
      Counter = 0;
    
    EndDo;
    
    ApiError = '';
    CloseList(QWCRH :ApiError);
    
    *Inlr = *On;
    //?                                           
    
    //?? Open List Thread                                              
    dcl-proc ListThreadProc;
    dcl-pi *n Int(10);
      HandleRequest char(4);
    end-pi;
    
    //?                                        
    
      ApiError = '';
      QWCF0100 = *Loval;
    
      Exec Sql
        Select Internal_job_Id,
               SubStr(Job_Name, 1, 6) AS Job_Number,
               SUBSTR(Job_Name, 8, PosStr(SubStr(Job_Name, 8), '/') -1) AS Job_User,
               SUBSTR(SUBSTR(JOB_NAME, 8),POSSTR(SUBSTR(JOB_NAME, 8), '/') +1)  AS JOB_NAME, thread_count
               Into :InternalJobId, :JobNumber, :JobUser, :JobName, :NumberOfThread
           From Table (
               Qsys2.Active_Job_Info('YES', '', :ApacheDt1.Istance, '', 'ALL'))
           where function ='QZSRHTTP' and thread_count > 3;
      If SqlState <> '00000';
        Return -1;
      EndIf;
    
      QWCJN02 = '*INT';
      QWCUN = *blanks;
      QWCJNBR00 = *blanks;
    
      NumField = 2;
      NumRec   = 200;
      QWCLTHSI = *Loval;
      QWCNBRSK = 0;
    
      GeneralDataLen = %Size(QWCGRD);
      OutDataInfLen  = 65535;
      ArrayOfKey(1) = 319;
      ArrayOfKey(2) = 2010;
    
      ApiError = '';
      ListThread(RcvVar
                 :RcvVarLen
                 :'OLTH0100'
                 :RcvVarInfo
                 :OutDataInfLen
                 :QWCF0100
                 :'JIDF0100'
                 :QWCLTHLI
                 :NumRec
                 :QWCLTHSI
                 :NumField
                 :ArrayOfKey
                 :RESETSTATS
                 :QWCGRD
                 :GeneralDataLen
                 :ApiError);
    
      HandleRequest = QWCRH;
    
      Return 0;
    
    end-proc;

  • #2
    I've only had a quick glance over the code and notice there are some external definitions in your code not mentioned however the big question is how do you know the API call is actually working? You are not making any check of the ApiError variable to see if it worked so you are assuming that there has been data returned when there may not have been. If no data is being returned, that could explain why nothing changes cause it's all uninitialised data. Not only that, but you are blanking out the whole APIError DS everywhere even though it contains numeric fields:

    Code:
    dcl-ds ApiError qualified;
      BytPrv int(10) inz( %size( apierror ));
      BytAvl int(10);
      MsgId char(7);
      *n char(1);
      MsgDta char(128);
    end-ds;
    
    ...
    
    ApiError = '';
    So, ApiError.BytPrv will contain a string of hex '40's which is a very large value. Some APIs may work with this but some don't and will generate an error. Given that the API has a CPF3CF1 error (error code parameter is not valid) my first thought is the API is simply failing due to the blanking of the DS. If you step through this using the debugger, what does the ApiError variable contain after the API call?

    I would suggest removing all the "ApiError = ' ' " bits in your code as there is no need to blank this out as the system will set the DS appropriately after calling the API. You should then check the ApiError.BytAvl variable to ensure it is 0 after any API call and take some action. If it is not 0, the API has failed and you can check the MsgID etc to find the actual error.

    Comment


    • #3
      To expand on john.sev99's reply a bit - the first field in APIError is BytPrv (Bytes Provided), which must be the size of ApiError in bytes. This is because the DS can be almost any size but the API is only seeing a pointer, so it has no concept of what the size is. So it replies on BytPrv for that.

      Your DS is initially initialised correctly, using %size(apierror) to define the initial length for BytPrv. But setting a DS to blank, as with "ApiError = '';" sets the entire memory space of the DS to hex 40. This makes all the numeric fields in the DS invalid, including BytPrv. I suspect this means the calls to the API are failing.

      What you should do instead to reset APIError, is "reset" it:
      Code:
      Reset APIError;
      The Reset opcode sets a variable back to its initialisation values - this means the value given by the inz keyword if present, else (I think) hex 40. This will set APIError to its initialisation values - which includes setting BytPrv to %size(apierror)

      Comment


      • #4
        Hi,
        many thanks for your help, I remove the clear and put the reset opcode, but there is no error in ApiError after the GetOpenlistEntry, It seems than the values of the list is evaluated only when I made the ListThread, In fact If I try to cancel a thread in this job the number of thread that return the GetOpenListEntry doesn't change...

        Please let me know if someone could try it.

        Many thanks.

        Comment


        • #5
          Having read the documentation for QWCOLTHD, it looks like it generates the list, and QGYGTLE merely accesses the generated list. So yes, you would need to repeat the call to QWCOLTHD to refresh it

          Comment


          • #6
            Originally posted by Vectorspace View Post
            Having read the documentation for QWCOLTHD, it looks like it generates the list, and QGYGTLE merely accesses the generated list. So yes, you would need to repeat the call to QWCOLTHD to refresh it
            Hi Vector,

            I call the api QWCOLTHD every time and the value are updated.
            Many thanks.

            Bye

            Comment


            • Vectorspace
              Vectorspace commented
              Editing a comment
              It's not uncommon for IBMi API's to wok in this way - one API to retrieve a list into memory, and another to then access the static list
          Working...
          X