WRKJOBS
Versionning
- 2007-01-06 first publication
- 2007-04-29 correction to code, removing /COPY had side
effects
- 2007-06-01 option 50 for list of dormant program (the ones
that end with SETON RT instead of SETON LR, or have something stay
opened, or recompiled programs or ...)
- 2007-06-01 options 51 & 52 for STRSRVJOB &
ENDSRVJOB
last version : The SaveFiles
|
Usage :
Screen shows first with *ALL but Jobname = QZDA* : first usage is to
work with ODBC jobs.
The first 3 filter fields are for calling the API, they
are wilcards values (IE terminated with a *). A * is added at end
if
missing
The next fields are masks for filtering when reading
list of jobs : do not need to add a * at end. A * at end is
removed if
any.
For all fields, *BLANK = *ALL = *. So, just clear a
filter-field witch is not in the filter target.
To sort a column, let the cursor on the column then
press F16, such as in WRKACTJOB
Options :
-
7 runs
a WRKACTJOB JOB(jobname). The idea is to provide a way to
answer a
message. I don't know how to (programaticaly) show a message a
job is
waiting for a answer, but WRKACTJOB knows. And I know how to
run
WRKACTJOB. This runs perfectly but when jobname is like
QZDASOINIT, all
jobs have the same name. In this case, note the job number
before
runnning option 7, then (when under wrkactjob) F11 two times
- all other runs WRKJOB. Well know options are runned
directly, other runs option 5 :
- when option = 1 then *STSA
- when option = 2 then *DFNA
- when option = 3 then *RUNA
- when option = 4 then *SPLA
- when option = 5 then *SELECT
- when option =10 then *JOBLOG
- when option =11 then *PGMSTK
- when option =12 then *JOBLCK
- when option =13 then *LIBL
- when option =14 then *OPNF
- when option =15 then *FILOVR
- when option =16 then *CMTCTL
- when option =17 then *CMNSTS
- when option =18 then *ACTGRP
- when option =19 then *MUTEX
- when option =20 then *THREAD
- when option =21 then *MLBA
- other then *SELECT
known issues
- crash when jobname not a name (like *ALL*),
correction coming soon
|
screen snapshot
WRKJOBR B 19/01/07 18:54:11 M170PUB1 JPLTOOLS jp jpltools 195 Lines Filter with Work with jobs S JobName UserName JobNbr Cur User IP address sbs Status *ALL *ALL *ALL JPLTOOLS *ALL *ALL *ALL *ACTIVE Limit to Option : same as WRKJOB 4=spool 10=joblog ... 8888 Lines QPADEV000S JPLTOOLS 259564 JPLTOOLS 181.56.171.44 QINTER RUN QPWFSERVSO QUSER 259230 JPLTOOLS 181.56.171.44 QSERVER QZRCSRVS QUSER 259317 JPLTOOLS 181.56.171.44 QUSRWRK TIMW QZSCSRVS QUSER 259474 JPLTOOLS 181.56.171.44 QUSRWRK TIMW F3=Exit F12=Cancel F5=Refresh F16=Sort
|
WRKJOBR nuggets
wrkjobr is based on well known apis QUS*US, QUSLJOB and
QUSRJOBI. OK, no gold
here. But I have
discover a pretty way when using the user space. After loading the user
space, I
have declared it as ... a working variable. How ? With a pointer ! The
blending
of user space and pointer produce a code very clear. code
excerpt :
start with creating a user space in qtemp (no secret)
quscrtus ( Usrspc// get memory for array .../...
|
then, call the list job API : (no more secret)
qusljob(usrspc : 'JOBL0100' : qjob : cbstatus :errcode )
|
now, I have a based data structure named LAH (for List Api
Header). (it's here the sorcerer had
worked)
I give to the pointer the address of the user space. Clearly, I use LAH
as a mask to format & read the user space
And Voila ! my LAH work field is now "containing" the user
space
data : under STRDBG, i can run EVAL LAH
Now, I can use the list as if it is in an array (in fact, it's really
an array)
for iJob= 0 to lah.count - 1; pJobL0100 = pLAH + LAH.Data_Offset + iJob * LAH.entry_Size ; // Now, the DS JOBL0100 contains one of the jobs listed by QUSLJOB rtvjoba(jobi0200:%size(jobi0200):'JOBI0200':'*INT':jobl0100.Internal_ID:errcode); .../... endfor;
|
Applause the guru ! (yes i'm very proud of myself. it's not
politically
correct, but when I am alone in front of my mirror, no one comes to
antagonize me,
even my reflection, it's to say!)
it's not the end ! there is an other nugget
I have implemented the "F16=sort" with the C-Sort-Array
procedure :
For details search the web about QSORT, there are many
articles on (first
target : SystemINews)
But, to resume, QSORT need
- an array
- a way to sort 2 elements
Below, SortArray is the array, and SortBy is the function that
sorts 2
elements
some data definitions
// Prototype for qsort - which should be in a /COPY member D C_QSort Pr ExtProc('qsort') D DataToSort * value D Elements 10U 0 Value D Size 10U 0 Value D SortFunct * ProcPtr Value d SortElement ds d qualified d based(pSortElement) d JOBNAME like(sbJOBNAME ) d USERNAME like(sbUSERNAME) d JOBNBR like(sbJOBNBR ) d CURUSER like(sbCURUSER ) d IP like(sbIP ) d sts like(sbsts ) d SBS like(sbSBS ) d SortArray s 65535 based(pSortArray) d SortAryNbr s 10i 0 inz(0) d SortAryPos s 10i 0 inz(0) d SortAryLen s 10i 0 inz(0) d SortEltlen s 10i 0 inz(%size(SortElement)) // Constants used by qsort sequencing routines D High C 1 D Low C -1 D Equal C 0 // Prototypes for the sequencing routines used in the program D SortBySbsJob Pr 10I 0 D Element1 Likeds(SortElement) D Element2 Likeds(SortElement) d SortBy s * procptr
|
how to load an element :
// add an element to sort array sortarylen+= sorteltlen; sortAryNbr+=1; pSortArray=%realloc(pSortArray:SortAryLen); // prepare last element for update pSortElement = pSortArray + SortaryLen - sorteltlen ; // update the element sortelement.jobname= JOBI0600.Job_name ; sortelement.username= JOBI0600.User_name ; sortelement.jobnbr = JOBI0600.Job_number ; sortelement.curuser = JOBI0600.Current_user ; sortelement.ip = JOBI0600.Client_IP ; sortelement.sts = JOBI0200.actjob_status;
|
how to sort the elements
SortBy = %Paddr(SortBySbsJob); C_QSort(PSortArray:SortAryNbr:SortEltLen:SortBy);
|
how to unload elements
SortAryPos = 1; // set pointer to first job iJob=0; // get one job if sortARyPos > SortAryNbr; // done iter; endif; // * load one line pSortElement = pSortArray + ( SortaryPos - 1 ) * sortEltLen ; sbjobname = sortelement.jobname ; sbusername = sortelement.username ; sbjobnbr = sortelement.jobnbr ; sbcuruser = sortelement.curuser ; sbip = sortelement.ip ; sbsts = sortelement.sts ; sbsbs = sortelement.sbs ;
|
And the call-back sort procedure for one element :
P SortBySbsJob b D PI 10I 0 D Element1 Likeds(SortElement) D Element2 Likeds(SortElement) /FREE SELECT; // level 1 sort : by sbs WHEN Element1.sbs > Element2.sbs ; RETURN High; WHEN Element1.sbs < Element2.sbs ; RETURN Low ; // next level : by name WHEN Element1.jobname> Element2.jobname; RETURN High; WHEN Element1.jobname< Element2.jobname; RETURN Low ; OTHER; RETURN Equal; ENDSL; BEGSR *PSSR ; DUMP ; ENDSR ; /end-free P e
|
RPGLE + C runtime library, the dream team !