3

I'm trying to retrieve a list of active processes that match my criteria. I've already got a working implementation that uses JobList that uses an as400 object:

// New as400 object

as400Environment = new AS400();
as400Environment.setSystemName(systemName);
as400Environment.setUserId(userID);
as400Environment.setPassword(password);

// New Job list
JobList jobList = new JobList(as400Environment);
Enumeration e = jobList.getJobs();

while(e.hasMoreElements()) {

    // Store current job
    Job j = (Job) e.nextElement();

    // Do things with the job ........
}

But this takes too long to get to the root of what I need, up to 10 minutes on some computers.

I've started looking at using Subsystem:

 Subsystem sbs = new Subsystem(as400Environment, subsystRequired, subsystRequired);

But I can't seem to get the job list as a string, only as a integer to tell me how many jobs there are.

Is there anyways to immediately return a job list with limited overhead ? I'm still looking through API's now but if anyone has any guidance it would be greatly appreciated.

Nathan
  • 266
  • 4
  • 16
  • what is meant by "get the job list as a string"? What is "the root" of what you want to do? Are you trying to get **all** jobs? Only jobs that left entries on *OUTQs? Active jobs? (You don't show any selection criteria.) When you say it takes 10 minutes "on some computers", are those client systems or servers? Is this a client request against a remote server, or is it Java that's always running **on** a server? Is this a Java performance problem, or are there simply hundreds of thousands of jobs "on some computers". (I've seen both cases.) – user2338816 Apr 24 '14 at 13:45
  • The search criteria is dynamic, the user is the one who wants to look at a specific system and the jobs on it, the original code iterated through all jobs, checking if it was part of the system/library required. Its always a client request running over a JDBC driver and its simply hundreds of thousands of jobs on certain computers. I'm new to this, only few weeks knowledge to be honest. – Nathan Apr 24 '14 at 14:49
  • What does "part of the system/library required" mean? Surely, all jobs will always be part of whatever system from which the list is retrieved, but how is "library" involved as a 'job' criterion? – user2338816 Apr 24 '14 at 18:58
  • The overall result of this is that the user will have control over the processes running in certain systems. Each system would have systematic jobs running and I only wanted to display them to a user but couldn't find a work around of using anything but the enumeration, which can end up shifting through thousands and thousands of records and is very time consuming. And apologies, I had just meant system the user specifies, not system/library. – Nathan Apr 25 '14 at 08:37

1 Answers1

3

It is possible to ask for a subset of the jobs on the system; to have IBM i do the work of filtering rather than returning all the jobs and having your code do that filtering. Does answer 16359926 help?

EDIT: Code for crude filter

I think I understand the issue. You want to choose jobs running in a specific subsystem, but addJobSelectionCriteria does not include SUBSYSTEM as one of the possible choices to filter on. One way to reduce the number of jobs being returned to you is to filter on active jobs only:

JobList jobList = new JobList(system);
jobList.clearJobSelectionCriteria();
jobList.addJobSelectionCriteria(JobList.SELECTION_PRIMARY_JOB_STATUS_ACTIVE, Boolean.TRUE);
jobList.addJobSelectionCriteria(JobList.SELECTION_PRIMARY_JOB_STATUS_JOBQ, Boolean.FALSE);
jobList.addJobSelectionCriteria(JobList.SELECTION_PRIMARY_JOB_STATUS_OUTQ, Boolean.FALSE);

Once you have a list of active jobs, you'll need to test for subsystem in your code by looping through the Enumeration. One way to make that more efficient is to have the call to getJobs() include the subsystem name in the list of attributes it returns. This will enable the use of getValue() instead of getSubsystem(). getSubsystem() results in another call to the system API to get that information, so it is somewhat inefficient.

jobList.clearJobAttributesToRetrieve();
jobList.addJobAttributeToRetrieve(Job.SUBSYSTEM);

All together then, here is a simple example:

import java.util.*;
import com.ibm.as400.access.*;

public class TestGetJobList {
    public static void main(String[] args) {
       int raw=0;
       int selected=0;

try {
    AS400 system = new AS400();

    // Create a list and subset it
       // looking for all jobs in QINTER, but subsystem is not in the list of things we can filter on
       // so filter the list as small as possible and then this code will pick through that list
    JobList jobList = new JobList(system);
    jobList.clearJobSelectionCriteria();
    jobList.addJobSelectionCriteria(JobList.SELECTION_PRIMARY_JOB_STATUS_ACTIVE, Boolean.TRUE);
    jobList.addJobSelectionCriteria(JobList.SELECTION_PRIMARY_JOB_STATUS_JOBQ, Boolean.FALSE);
    jobList.addJobSelectionCriteria(JobList.SELECTION_PRIMARY_JOB_STATUS_OUTQ, Boolean.FALSE);

       // we can eliminate another call to the system API by adding subsystem to the attributes retrieved in the getJobList()
    jobList.clearJobAttributesToRetrieve();
    jobList.addJobAttributeToRetrieve(Job.SUBSYSTEM);
    jobList.addJobAttributeToRetrieve(Job.JOB_NAME);
    jobList.addJobAttributeToRetrieve(Job.JOB_NUMBER);
    jobList.addJobAttributeToRetrieve(Job.USER_NAME);

       // get the list of jobs
    Enumeration list = jobList.getJobs();

    while (list.hasMoreElements())  {
        Job  j= (Job) list.nextElement();
               raw++;    // count them

               // choose jobs in one subsystem
               // this is pretty efficient because we told getJobs() to include the subsystem in the first retrieval
               if (j.getValue(Job.SUBSYSTEM).toString().substring(0, 6).equals("QINTER")) {
                 selected++;
                 System.out.println(j.getValue(Job.JOB_NUMBER) + "/" +
                   j.getValue(Job.USER_NAME) + "/" +
                   j.getValue(Job.JOB_NAME) );
                 }
        }

    System.out.println(raw + " raw jobs found");
    System.out.println(selected + " QINTER jobs found");
    System.exit(0);

    } catch (Exception e) {
        e.printStackTrace();
    }

    }
}

This processes 500 active jobs, selecting about 75 in QINTER in under 1 second.

Community
  • 1
  • 1
Buck Calabro
  • 7,558
  • 22
  • 25
  • Its kinda the way I had it set up, but because of the Enumeration, it takes time shifting through as there can be hundreds of thousands of jobs running. I wont have access to specific things like job numbers, only the name of the subsystem, so this was the way I was hoping to build it. Thank you for trying to help though ! – Nathan Apr 25 '14 at 08:44
  • @Nathan Still, is there any server-side filtering that can be done? In particular, would the end-user only be interested in jobs that are actively running at the time of the request, or those that have finished? That could potentially reduce the count by two or three orders of magnitude. Any server-side filtering at all will be helpful. If no filtering is possible, then it'll always be at the mercy of the environment and have major variability. – user2338816 Apr 25 '14 at 09:13
  • @user2338816 I'll look into trying to apply a filter, they would only be interested in actively running jobs, I'll create the filters, apply them and test it. Thanks for your help guys ! – Nathan Apr 25 '14 at 10:03