Newsletters   Subscriptions  Forums  Store   Career  Media Kit  About Us  Contact  Search   Home 
fhg
Volume 4, Number 40 -- December 1, 2004

Submit Job Schedule Entries Immediately

by Ted Holt


The code for this article is available for download.


You can buy better job schedulers than the one that comes bundled with OS/400. Unfortunately for many of us, the OS/400 job scheduler is the only one we're permitted to use. Because I recently found myself forced to work within that restriction, I wrote a command to overcome one of the built-in job scheduler's limitations. Later I discovered that my new utility overcame a second limitation. It occurred to me that some of you might like to have this utility.

In "Job Scheduler's Other Defaults," I explained to Beau that the OS/400 job scheduler runs a Submit Job (SBMJOB) command, filling in certain parameters with non-default values. A problem occurs when someone needs to submit a scheduled job to run outside of the regularly scheduled time. The Work with Job Schedule Entries panel includes option 10, "submit immediately," which at first seems to address the need, but doesn't really. The Submit Immediately option runs SBMJOB with SBMJOB's usual default parameter values, not the non-default parameter values that that the job scheduler uses. This means that the job scheduler does not include an option to immediately submit an entry in the same way the job scheduler normally submits the entry. This is the limitation I needed to overcome.

For this reason, I wrote the Submit Job Schedule Entry (SBMJOBSCDE) utility. It retrieves a job scheduler entry and builds a SBMJOB command, filling in the parameters with the non-default values the job scheduler uses. The utility consists of three objects: the SBMJOBSCDE command, an OPM CL command-processing program named JOBSCDE1C, and a help panel group called JOBSCDE1H.

SBMJOBSCDE is easy to use. It has only two parameters. The first is the name of the entry as it appears in the job scheduler. The second parameter works only in interactive mode. It permits you to prompt the generated SBMJOB command so you can make changes before the new job is submitted to batch. Here's the source code.

/* ==================================================== */
/* Submit a job schedule entry for immediate execution. */
/* ==================================================== */
/* To create:                                           */
/*     CRTCMD CMD(xxx/SBMJOBSCDE)                       */
/*            PGM(xxx/JOBSCDE1C)                        */
/*            SRCFILE(xxx/QCMDSRC)                      */
/*            HLPPNLGRP(JOBSCDE1H)                      */
/*            HLPID(*CMD)                               */
/* ==================================================== */
CMD        PROMPT('Submit Job Schedule Entry')
PARM       KWD(JOB) TYPE(*CHAR) LEN(10) MIN(1) +
             EXPR(*YES) PROMPT('Job schedule entry name')
PARM       KWD(PROMPT) TYPE(*CHAR) LEN(4) RSTD(*YES) +
             DFT(*NO) VALUES(*YES *NO) EXPR(*YES) +
             PROMPT('Prompt before submitting?')


The CL program uses the List Job Schedule Entries (QWCLSCDE) API to retrieve the job schedule entry information into user space QTEMP/SBMJOBSCDE. It extracts that information from the user space to build the SBMJOB command.



/* ==================================================== */
/* Submit a job schedule entry for immediate execution. */
/* ==================================================== */
/* To compile:                                          */
/*      CRTCLPGM PGM(xxx/JOBSCDE1C)                     */
/*               SRCFILE(xxx/QCLSRC)                    */
/*               SRCMBR(JOBSCDE1C)                      */
/* ==================================================== */

pgm parm(&inJobScdE &inPrompt)

   dcl &inJobScdE   *char     10
   dcl &inPrompt    *char      4

   dcl &UsrSpcName  *char     10  'SBMJOBSCDE'
   dcl &UsrSpcLib   *char     10  'QTEMP'
   dcl &UsrSpc      *char     20
   dcl &FmtName     *char      8  'SCDL0200'
   dcl &NbrEntries  *dec      10
   dcl &Offset      *dec      10
   dcl &EntryLen    *dec      10
   dcl &Continue    *char     16
   dcl &StartPos    *dec       5
   dcl &UsrSpcData  *char x'1000'
   dcl &UsrSpcSize  *char      4  x'00001000'
   dcl &Error       *char     16  x'00000010'
   dcl &JobType     *char      1

   dcl &Cmd         *char    512
   dcl &CmdLen      *dec       3
   dcl &InfoStatus  *char      1
   dcl &JobName     *char     10
   dcl &JobQ        *char     10
   dcl &JobQLib     *char     10
   dcl &JobD        *char     10
   dcl &JobDLib     *char     10
   dcl &MsgQ        *char     10
   dcl &MsgQLib     *char     10
   dcl &UsrPrf      *char     10

   dcl &CmdString   *char   4096
   dcl &Quote       *char      1  ''''

   dcl &Abending    *lgl
   dcl &MsgID       *char      7
   dcl &MsgDta      *char    256
   dcl &MsgF        *char     10
   dcl &MsgFLib     *char     10
   dcl &MsgKey      *char      4
   dcl &RtnType     *char      2
   dcl &PgmName     *char     10
   dcl &Sender      *char     80

   monmsg cpf0000 exec(goto abend)

   /* retrieve the program name */
   sndpgmmsg msg(' ') topgmq(*same) msgtype(*info) keyvar(&MsgKey)
   rcvmsg    pgmq(*same) msgtype(*info) sender(&Sender) rmv(*yes)
   chgvar    &PgmName   %sst(&Sender 56 10)

   /* create a temporary user space                 */
   /* and load it with job schedule information     */

   chgvar     &UsrSpc   (&UsrSpcName *cat &UsrSpcLib)

   chkobj &UsrSpcLib/&UsrSpcName *usrspc
   monmsg cpf0000 exec(do)
      call quscrtus (&UsrSpc ' ' &UsrSpcSize ' ' *all &Error)
   enddo
   call qwclscde  (&UsrSpc &FmtName &inJobScdE &Continue &Error)
   call qusrtvus  (&UsrSpc x'00000001' &UsrSpcSize &UsrSpcData &Error)

   chgvar &NbrEntries   %bin(&UsrSpcData 133 4)
   if (&NbrEntries *lt 1) do
      chgvar var(&MsgDta) value('Job schedule entry' *bcat &inJobScdE +
                                *bcat 'could not be found.')
      sndpgmmsg  msgid(cpf9897)  msgf(qcpfmsg)   msgtype(*diag) +
                   msgdta(&MsgDta)
      goto Escape
   enddo

/* extract job info from the job schedule entry */
   chgvar &Offset       %bin(&UsrSpcData 125 4)
   chgvar &EntryLen     %bin(&UsrSpcData 137 4)

   chgvar &StartPos     (&Offset + 1)
   chgvar &InfoStatus   %sst(&UsrSpcData &StartPos 1)
   chgvar &StartPos     (&Offset + 2)
   chgvar &JobName      %sst(&UsrSpcData &StartPos 10)
   chgvar &StartPos     (&Offset + 198)
   chgvar &JobQ         %sst(&UsrSpcData &StartPos 10)
   chgvar &StartPos     (&Offset + 208)
   chgvar &JobQLib      %sst(&UsrSpcData &StartPos 10)
   chgvar &StartPos     (&Offset + 527)
   chgvar &JobD         %sst(&UsrSpcData &StartPos 10)
   chgvar &StartPos     (&Offset + 537)
   chgvar &JobDLib      %sst(&UsrSpcData &StartPos 10)
   chgvar &StartPos     (&Offset + 547)
   chgvar &UsrPrf       %sst(&UsrSpcData &StartPos 10)
   chgvar &StartPos     (&Offset + 557)
   chgvar &MsgQ         %sst(&UsrSpcData &StartPos 10)
   chgvar &StartPos     (&Offset + 567)
   chgvar &MsgQLib      %sst(&UsrSpcData &StartPos 10)
   chgvar &StartPos     (&Offset + 641)
   chgvar &CmdLen       %bin(&UsrSpcData &StartPos 4)
   chgvar &StartPos     (&Offset + 645)
   chgvar &Cmd          %sst(&UsrSpcData &StartPos &CmdLen)

/* Was prompting requested? */
   rtvjoba type(&JobType)
   if (&JobType *eq '1') do /* Interactive job */
      if ((%sst(&inPrompt 2 1) *eq 'Y') +
      *or (%sst(&inPrompt 2 1) *eq 'y')) do
         chgvar  &CmdString '?'
      enddo
   enddo

/* build a command string from the job schedule entry */
   chgvar  &CmdString (&CmdString *tcat 'SBMJOB JOB(' +
                       *cat &JobName *tcat ')')

   chgvar  &CmdString (&CmdString *bcat 'JOBD(')
   if (%sst(&JobD 1 1) *ne '*') do
      chgvar  &CmdString (&CmdString *tcat &JobDLib *tcat '/')
   enddo
   chgvar  &CmdString (&CmdString *tcat &JobD *tcat ')')

   chgvar  &CmdString (&CmdString *bcat 'JOBQ(')
   if (%sst(&JobQ 1 1) *ne '*') do
      chgvar  &CmdString (&CmdString *tcat &JobQLib *tcat '/')
   enddo
   chgvar  &CmdString (&CmdString *tcat &JobQ *tcat ')')

   chgvar  &CmdString (&CmdString *bcat 'CMD(' +
                       *cat %sst(&Cmd 1 &CmdLen) +
                       *cat ')')

   chgvar  &CmdString (&CmdString *bcat 'USER(' *cat &UsrPrf *cat ')')

   chgvar  &CmdString (&CmdString *bcat 'MSGQ(')
   if (%sst(&MsgQ 1 1) *ne '*') do
      chgvar  &CmdString (&CmdString *tcat &MsgQLib *tcat '/')
   enddo
   chgvar  &CmdString (&CmdString *tcat &MsgQ *tcat ')')

   chgvar  &CmdString (&CmdString *bcat 'SYSLIBL(*SYSVAL) +
                          CURLIB(*USRPRF) INLLIBL(*JOBD) +
                          PRTDEV(*JOBD) OUTQ(*JOBD) +
                          PRTTXT(*JOBD) RTGDTA(*JOBD) +
                          SRTSEQ(*USRPRF) LANGID(*USRPRF) +
                          CNTRYID(*USRPRF) CCSID(*USRPRF)')

   call   qcmdexc   (&CmdString 4096)
   monmsg cpf6801
   rcvmsg     msgtype(*last) msgdta(&MsgDta) msgid(&MsgID) +
                 rtntype(&RtnType) +
                 msgf(&MsgF) sndmsgflib(&MsgFLib)
   sndpgmmsg  msgid(&MsgID)  msgf(&MsgF) msgtype(*comp) +
                msgdta(&MsgDta)
   return

   /* Routine to handle unexpected errors */
Abend:
      if &Abending then(return)
      chgvar   &Abending '1'

ForwardMsg:
      rcvmsg     msgtype(*any) msgdta(&MsgDta) msgid(&MsgID) +
                    rtntype(&RtnType) +
                    msgf(&MsgF) sndmsgflib(&MsgFLib)
      if ((&RtnType *eq '02') *or   /* diagnostic */ +
          (&RtnType *eq '15') *or (&RtnType *eq '17')) do  /* *escape */
         sndpgmmsg  msgid(&MsgID)  msgf(&MsgF)   msgtype(*diag) +
                   msgdta(&MsgDta)
      enddo
      if (&RtnType *ne '  ') then(goto ForwardMsg)
Escape:
   sndpgmmsg  msgid(cpf9898) msgf(qcpfmsg) msgtype(*escape) +
                msgdta('Program' *bcat &PgmName *bcat +
                       'ended abnormally')
endpgm


The command is easy enough to use, but I put together some brief help text anyway. Store it in member JOBSCDE1H.



.* ====================================================================
.* Help text for the SBMJOBSCDE command
.* ====================================================================
.* To create:
.*      CRTPNLGRP PNLGRP(xxx/JOBSCDE1H)
.*                SRCFILE(xxx/QPNLSRC)
.*                SRCMBR(JOBSCDE1H)
.* ====================================================================

:PnlGrp.


:Help Name = 'SBMJOBSCDE' .Submit Job Schedule Entry - Help

:P.
The Submit Job Schedule Entry (SBMJOBSCDE) command allows you to submit
a job scheduler entry using the parameter values the job scheduler
applies to the SBMJOB command. SBMJOBSCDE allows you to run a scheduled
job on demand in the same way it would run if the job scheduler started
it.

:EHelp.

:Help Name = 'SBMJOBSCDE/Job' .Job name (JOB) - Help
:XH3 .Job entry (JOB)

:P.
The name of the job as it is known to the job scheduler.

:P.
This is a required parameter.

:EHelp.

:Help Name = 'SBMJOBSCDE/PROMPT' .Prompt command (PROMPT) - Help
:XH3 .Prompt command (PROMPT)

:P.
This parameter applies to interactive execution of SBMJOBSCDE only.
It allows you to modify the generated SBMJOB comamnd before submitting
the job to batch for execution.

:P.
The possible values are:

:Parml.
:pt.:pk def.*NO:epk.
:pd.SBMJOB will not be prompted before execution.
:pt.:pk.*YES:epk.
:pd.SBMJOB will be prompted for execution. You will be allowed to
modify parameter values.
:EParmL.

:EHelp.

:EPnlGrp. 


I mentioned that my new utility overcame a second limitation. After I wrote SBMJOBSCDE, I realized I had found the answer to the problem I wrote about in "Scheduling a Job to Run More than Once a Day." In a follow-up to that article, reader Rocky suggested creating multiple, identical job schedule entries in order to run a job schedule entry more than once a day. The problem with that approach is that changing one entry means having to change them all.


SBMJOBSCDE addresses this problem as well. Create one entry with the proper settings. Make the others run SBMJOBSCDE to kick off the original entry at other times.

So far I have been pleased with SBMJOBSCDE. This utility has worked correctly in all my tests and in production. I hope some of you will find it helpful as well. Please contact me with bug reports or suggestions for improvements, if you have a better idea, or just to let me know it's helped you.


Ted Holt is editor of Four Hundred Guru. Click here to contact Ted Holt by e-mail.

Sponsored By
LINOMA SOFTWARE

Linoma Software
Revolutionary Solutions for Your World

TRANSFER ANYWHERE - Affordable PGP Encryption & Distribution
* Secure your internet transmissions with PGP Encryption
* Automate FTP & email distributions of information
* Extract data from database systems
* Convert to Excel, XML and text formats
* Replicate records between database systems
* Connects to DB2, SQL Server, Oracle and Informix
* Runs natively on iSeries or NT
* Includes a
FREE license of Linoma's new PGP Studio to manage keys

AXES - web-enable ALL your iSeries screens with no programmer intervention and no interactive. Load & Go! Be web-enabled in less than 30 minutes.

RPG TOOLBOX - convert to RPG IV and free-form. Includes 70+ predefined SEU commands.

SURVEYOR/400 - graphically edit database files, import, export, convert spooled files to PDF, run SQL and more!

Purchase a new iSeries (upgrades are now included too) and get an IBM rebate to purchase Linoma's IBM ServerProven tools!

Get more information and download your FREE trials today at
www.linomasoftware.com.


Technical Editors: Howard Arner, Joe Hertvik, Ted Holt,
Shannon O'Donnell, Kevin Vandever
Managing Editor: Shannon Pastore
Contributing Technical Editors: Joel Cochran, Wayne O. Evans, Raymond Everhart,
Bruce Guetzkow, Marc Logemann, David Morris
Publisher and Advertising Director: Jenny Thomas
Advertising Sales Representative: Kim Reed
Contact the Editors: To contact anyone on the IT Jungle Team
Go to our contacts page and send us a message.


THIS ISSUE
SPONSORED BY:

Linoma Software
WorksRight Software
Guild Companies


BACK ISSUES

TABLE OF
CONTENTS
Submit Job Schedule Entries Immediately

V5R3 CL Enhancements on V5R2

Admin Alert: Tips for Dealing with Deleted Records in AS/400 Files


The Four Hundred
Myths, Misconceptions Run Wild in World of High Availability

IBM's iSeries for HA, CBU Editions Gain Traction

IT Spending Predicted to Increase Modestly in 2005

Four Hundred Stuff
Original Adds Variable Data to Software Testing Suite

iSeries: The Low-Cost Choice for Kansas County Government

Devon Introduces New Appliance for Secure Remote Access

Four Hundred Monitor


Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.
Guild Companies, Inc. (formerly Midrange Server), 50 Park Terrace East, Suite 8F, New York, NY 10034
Privacy Statement