Get AS400 Subsystem jobs with java( Open List of Jobs (QGYOLJOB) API format OLJB0300)
(SubsystemJobOpenListTest.java, SubsystemJobListItem.java, SubsystemJobOpenList.java)
File : SubsystemJobListItem.java
///////////////////////////////////////////////////////////////////////////////
//
//
// Filename: SubsystemJobListItem.java
//
// Author : Vengoal Chang
//
// Date : 2015/07/01
//
//
///////////////////////////////////////////////////////////////////////////////
package com.vengoal.as400.list;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import com.ibm.as400.access.BinaryConverter;
public class SubsystemJobListItem {
public static final int ACTIVE_JOB_STATUS_FOR_JOBS_ENDING = 103; // Active job status for jobs ending
public static final int CURRENT_USER = 305; // Current user profile
public static final int CPU_TIME_USED_LARGE = 312; // Processing unit time used - total for the job
public static final int CPU_TIME_USED_FOR_DATABASE = 313; // Processing unit time used for database - total for the job (Deprecated)
public static final int ELAPSED_CPU_PERCENT_USED = 314; // Processing unit used - percent during the elapsed time (job)
public static final int ELAPSED_CPU_TIME_USED = 315; // Processing unit used - time during the elapsed time (job)
public static final int ELAPSED_CPU_PERCENT_USED_FOR_DATABASE = 316; // Processing unit used for database - percent during the elapsed time (job) (Deprecated)
public static final int ELAPSED_CPU_TIME_USED_FOR_DATABASE = 317; // Processing unit used for database - time during the elapsed time (job) (Deprecated)
public static final int DATE_ENTERED_SYSTEM = 402; // Date and time job entered system
public static final int ELAPSED_DISK_IO = 414; // Disk I/O count during the elapsed time (job)
public static final int DISK_IO = 415; // Disk I/O count - total for the job
public static final int ELAPSED_DISK_IO_ASYNCH = 416; // Disk I/O count during the elapsed time - asynchronous I/O (job)
public static final int ELAPSED_DISK_IO_SYNCH = 417; // Disk I/O count during the elapsed time - synchronous I/O (job)
public static final int CONTROLLED_END_REQUESTED = 502; // End status
public static final int FUNCTION_NAME = 601; // Function name
public static final int FUNCTION_TYPE = 602; // Function type
public static final int INTERNAL_JOB_IDENTIFIER = 902; // Internal job identifier
public static final int ELAPSED_INTERACTIVE_RESPONSE_TIME = 904; // Interactive response time - total during the elapsed time
public static final int ELAPSED_INTERACTIVE_TRANSACTIONS = 905; // Interactive transactions - count during the elapsed time
public static final int JOB_USER_IDENTITY = 1012; // Job user identity
public static final int JOB_END_REASON = 1014; // Job end reason
public static final int JOB_LOG_PENDING = 1015; // Job log pending
public static final int JOB_TYPE_ENHANCED = 1016; // Job type - enhanced
public static final int MEMORY_POOL = 1306; // Memory pool name
public static final int MESSAGE_REPLY = 1307; // Message reply
public static final int MESSAGE_KEY = 1308; // Message key, when active job waiting for a message
public static final int MESSAGE_QUEUE = 1309; // Message queue name - qualified, when active job waiting for a message
public static final int MESSAGE_QUEUE_ASP = 1310; // Message queue library ASP device name, when active job waiting for a message
public static final int ELAPSED_PAGE_FAULTS = 1609; // Page fault count during the elapsed time (job)
public static final int RUN_PRIORITY = 1802; // Run priority (job)
public static final int SUBSYSTEM = 1906; // Subsystem description name - qualified
public static final int SERVER_TYPE = 1911; // Server type
public static final int SPOOLED_FILE_ACTION = 1982; // Spooled file action
public static final int THREAD_COUNT = 2008; // Thread count
public static final int TEMP_STORAGE_USED_LARGE = 2009; // Temporary storage used, in megabytes(from V7R2)
private String jobName;
private String jobUser;
private String jobNumber;
private String status;
private String jobType;
private String jobSubtype;
private String currentUser; // key 305
private String functionName; // key 601
private String functionType; // key 602
private String messageReply; // key 1307
private byte[] messageKey; // key 1308
private String qualMessageQueue; // key 1309
private String qualSubsystem; // key 1906
private TreeMap keyValues = new TreeMap(); // key others
public SubsystemJobListItem(String jobName, String jobUser, String jobNumber,
String status, String jobType,String jobSubtype, String currentUser, String functionName,
String functionType,
String messageReply, byte[] messageKey, String qualMessageQueue, String qualSubsystem) {
this.jobName = jobName;
this.jobUser = jobUser;
this.jobNumber = jobNumber;
this.status = status;
this.jobType = jobType;
this.jobSubtype = jobSubtype;
this.currentUser = currentUser;
this.functionName = functionName;
this.functionType = functionType;
this.messageReply = messageReply;
this.messageKey = messageKey;
this.qualMessageQueue = qualMessageQueue;
this.qualSubsystem = qualSubsystem;
}
public Object getObject(int key){
return keyValues.get(key);
}
public void setKeyValues(TreeMap keyValues){
this.keyValues = keyValues;
}
public String getJobName() {
return jobName;
}
public String getJobUser() {
return jobUser;
}
public String getJobNumber() {
return jobNumber;
}
public String getStatus() {
return status;
}
public String getJobType() {
return jobType;
}
public String getJobSubtype() {
return jobSubtype;
}
public String getCurrentUser() {
return currentUser;
}
public String getFunctionName() {
return functionName;
}
public String getFunctionType() {
return functionType;
}
public String getMessageReply() {
return messageReply;
}
public byte[] getMessageKey() {
return messageKey;
}
public String getQualMessageQueue() {
return qualMessageQueue;
}
public String getQualSubsystem() {
return qualSubsystem;
}
public String toString(){
StringBuffer strBuf = new StringBuffer();
strBuf.append(jobName).append("/");
strBuf.append(jobUser).append("/");
strBuf.append(jobNumber).append(",");
strBuf.append(status).append(",");
strBuf.append(jobType).append(",");
strBuf.append(jobSubtype).append(",");
strBuf.append("305=" + currentUser).append(",");
strBuf.append("601=" + functionName).append(",");
strBuf.append("602=" + functionType).append(",");
strBuf.append("1307=" + messageReply).append(",");
strBuf.append("1308(MSGKEY 4 bytes hex string)=" + BinaryConverter.bytesToHexString(messageKey)).append(",");
strBuf.append("1309=" + qualMessageQueue).append(",");
strBuf.append("1906=" + qualSubsystem);
if(keyValues.size() > 0){
Set set = keyValues.entrySet();
Iterator i = set.iterator();
while(i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
strBuf.append("," + me.getKey() + "=" + me.getValue());
}
}
return strBuf.toString();
}
}
File : SubsystemJobOpenList.java
///////////////////////////////////////////////////////////////////////////////
//
//
// Filename: SubsystemJobOpenList.java
//
// Author : Vengoal Chang
//
// Date : 2015/07/01
//
//
///////////////////////////////////////////////////////////////////////////////
package com.vengoal.as400.list;
import java.io.IOException;
import java.util.TreeMap;
import com.ibm.as400.access.AS400;
import com.ibm.as400.access.AS400Exception;
import com.ibm.as400.access.AS400SecurityException;
import com.ibm.as400.access.AS400Text;
import com.ibm.as400.access.BinaryConverter;
import com.ibm.as400.access.CharConverter;
import com.ibm.as400.access.ErrorCodeParameter;
import com.ibm.as400.access.ErrorCompletingRequestException;
import com.ibm.as400.access.Job;
import com.ibm.as400.access.ObjectDoesNotExistException;
import com.ibm.as400.access.ProgramCall;
import com.ibm.as400.access.ProgramParameter;
import com.ibm.as400.access.Trace;
import com.ibm.as400.access.list.OpenList;
/**
* Represents a list of subsystem jobs on the system with Open List of Jobs (QGYOLJOB) API.
* By default, following keys retrieved:
* keys_[0] = 305;
* keys_[1] = 601;
* keys_[2] = 602;
* keys_[3] = 1307;
* keys_[4] = 1308;
* keys_[5] = 1309;
* keys_[6] = 1906;
*
* List of Keys Supported for Format OLJB0300 reference:
* http://www-01.ibm.com/support/knowledgecenter/ssw_ibm_i_72/apis/qgyoljob.htm?lang=en
*
*/
public class SubsystemJobOpenList extends OpenList {
private String subsystem_;
private Job[] subsystemJobs_;
// Sort keys.
private int currentSortKey_ = 1;
// Info saved between calls to load() and getJobs().
private int numKeysReturned_;
private int[] keyFieldsReturned_;
private char[] keyTypesReturned_;
private int[] keyLengthsReturned_;
private int[] keyOffsetsReturned_;
// Keys to pre-load.
private int currentKey_ = 7;
private int[] keys_ = new int[currentKey_];
public SubsystemJobOpenList(AS400 system, String subsystem) {
super(system);
this.subsystem_ = subsystem;
// Figure out Job information default return key fields
keys_[0] = 305;
keys_[1] = 601;
keys_[2] = 602;
keys_[3] = 1307;
keys_[4] = 1308;
keys_[5] = 1309;
keys_[6] = 1906;
}
public void addJobAttributeToRetrieve(int attribute){
if (currentKey_ >= keys_.length){
// Resize.
int[] temp = keys_;
keys_ = new int[temp.length * 2];
System.arraycopy(temp, 0, keys_, 0, temp.length);
}
keys_[currentKey_++] = attribute;
}
public Job[] getSubsystemJobs(){
return subsystemJobs_;
}
@Override
protected byte[] callOpenListAPI() throws AS400SecurityException,
ErrorCompletingRequestException, InterruptedException, IOException,
ObjectDoesNotExistException {
if (Trace.isTraceOn()) Trace.log(Trace.DIAGNOSTIC, "Opening spooled file list.");
int lengthOfReceiverVariableDefinitionInformation = 4 + 20 * currentKey_;
byte[] keyOfFieldsToBeReturned = new byte[4 * currentKey_];
for (int i = 0; i < currentKey_; ++i)
{
BinaryConverter.intToByteArray(keys_[i], keyOfFieldsToBeReturned, i * 4);
}
// Figure out our sort information
byte[] sortInformation = new byte[4 + currentSortKey_ * 12];
BinaryConverter.intToByteArray(currentSortKey_, sortInformation, 0);
int fieldStartingPosition = 1;
int fieldLength = 10;
short dataType = (short)4;
BinaryConverter.intToByteArray(fieldStartingPosition, sortInformation, 4 );
BinaryConverter.intToByteArray(fieldLength, sortInformation, 8);
BinaryConverter.shortToByteArray(dataType, sortInformation, 12);
// Sort order 0xF1 = ascending, 0xF2 = descending.
sortInformation[14] = (byte)0xF1;
// Figure out our selection criteria.
byte[] jobSelectionInformation = new byte[206];
// Generate text objects based on system CCSID.
CharConverter conv = new CharConverter(system_.getCcsid(), system_);
for (int i = 0; i < 26; ++i) jobSelectionInformation[i] = 0x40;
String selectionJobName_ = "*ALL";
String selectionUserName_= "*ALL";
String selectionJobNumber_= "*ALL";
String selectionJobType_= "*";
conv.stringToByteArray(selectionJobName_.toUpperCase(), jobSelectionInformation, 0);
conv.stringToByteArray(selectionUserName_.toUpperCase(), jobSelectionInformation, 10);
conv.stringToByteArray(selectionJobNumber_, jobSelectionInformation, 20);
conv.stringToByteArray(selectionJobType_, jobSelectionInformation, 26);
int offset = 195;
int numberOfSubsystem = 1;
BinaryConverter.intToByteArray(offset, jobSelectionInformation, 76);
BinaryConverter.intToByteArray(numberOfSubsystem, jobSelectionInformation, 80);
// Subsystem name
AS400Text subsystemText = new AS400Text(10, system_);
byte[] subSystemBytes = subsystemText.toBytes(subsystem_);
System.arraycopy(subSystemBytes, 0, jobSelectionInformation, offset, 10);
offset += 10;
// Setup program parameters.
ProgramParameter[] parameters = new ProgramParameter[]
{
// Receiver variable, output, char(*).
new ProgramParameter(0),
// Length of receiver variable, input, binary(4).
new ProgramParameter(new byte[] { 0x00, 0x00, 0x00, 0x00 } ),
// Format name, input, char(8), EBCDIC 'OLJB0300'.
new ProgramParameter(new byte[] { (byte)0xD6, (byte)0xD3, (byte)0xD1, (byte)0xC2, (byte)0xF0, (byte)0xF3, (byte)0xF0, (byte)0xF0 } ),
// Receiver variable definition information, output, char(*).
new ProgramParameter(lengthOfReceiverVariableDefinitionInformation),
// Length of receiver variable definition information, input, binary(4).
new ProgramParameter(BinaryConverter.intToByteArray(lengthOfReceiverVariableDefinitionInformation)),
// List information, output, char(80).
new ProgramParameter(80),
// Number of records to return, input, binary(4).
// Special value '-1' indicates that "all records are built synchronously in the list".
new ProgramParameter(new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF } ),
// Sort information, input, char(*).
new ProgramParameter(sortInformation),
// Job selection information, input, char(*).
new ProgramParameter(jobSelectionInformation),
// Size of job selection information, input, binary(4).
new ProgramParameter(BinaryConverter.intToByteArray(jobSelectionInformation.length)),
// Number of fields to return, input, binary(4).
new ProgramParameter(BinaryConverter.intToByteArray(currentKey_)),
// Key of fields to be returned, input, array(*) of binary(4).
new ProgramParameter(keyOfFieldsToBeReturned),
// Error code, I/0, char(*).
new ErrorCodeParameter(),
// Job selection format name, input, char(8), EBCDIC 'OLJS0200'.
new ProgramParameter(new byte[] { (byte)0xD6, (byte)0xD3, (byte)0xD1, (byte)0xE2, (byte)0xF0, (byte)0xF2, (byte)0xF0, (byte)0xF0 } )
};
// Call the program.
ProgramCall pc = new ProgramCall(system_, "/QSYS.LIB/QGY.LIB/QGYOLJOB.PGM", parameters);
if (!pc.run())
{
throw new AS400Exception(pc.getMessageList());
}
// Key information returned.
byte[] defInfo = parameters[3].getOutputData();
numKeysReturned_ = BinaryConverter.byteArrayToInt(defInfo, 0);
keyFieldsReturned_ = new int[numKeysReturned_];
keyTypesReturned_ = new char[numKeysReturned_];
keyLengthsReturned_ = new int[numKeysReturned_];
keyOffsetsReturned_ = new int[numKeysReturned_];
offset = 4;
for (int i = 0; i < numKeysReturned_; ++i)
{
keyFieldsReturned_[i] = BinaryConverter.byteArrayToInt(defInfo, offset + 4);
keyTypesReturned_[i] = conv.byteArrayToString(defInfo, offset + 8, 1).charAt(0); // 'C' or 'B'
keyLengthsReturned_[i] = BinaryConverter.byteArrayToInt(defInfo, offset + 12);
keyOffsetsReturned_[i] = BinaryConverter.byteArrayToInt(defInfo, offset + 16);
offset += 20;
}
// List information returned.
return parameters[5].getOutputData();
}
@Override
protected Object[] formatOutputData(byte[] data, int recordsReturned, int recordLength)
throws AS400SecurityException, ErrorCompletingRequestException,
InterruptedException, IOException, ObjectDoesNotExistException {
int number = recordsReturned; // request entire list
CharConverter conv = new CharConverter(system_.getCcsid(), system_);
SubsystemJobListItem[] listItems = new SubsystemJobListItem[number];
subsystemJobs_ = new Job[number];
String currentUser = null;
String functionName = null;
String functionType = null;
String messageReply = null;
byte[] messageKey = null;
String qualMessageQueue = null;
String qualSubsystem = null;
TreeMap keyValues = new TreeMap();
for (int i = 0, offset = 0; i < listItems.length; ++i, offset += recordLength)
{
String jobName = conv.byteArrayToString(data, offset, 10);
String jobUser = conv.byteArrayToString(data, offset + 10, 10);
String jobNumber = conv.byteArrayToString(data, offset + 20, 6);
String status = conv.byteArrayToString(data, offset + 26, 4);
String jobType = conv.byteArrayToString(data, offset + 30, 1);
String jobSubtype = conv.byteArrayToString(data, offset + 31, 1);
for (int j = 0; j < numKeysReturned_; ++j)
{
int keyOffset = keyOffsetsReturned_[j];
if (keyTypesReturned_[j] == 'C')
{
String value = conv.byteArrayToString(data, offset + keyOffset, keyLengthsReturned_[j]);
if(keyFieldsReturned_[j] == 305 ) currentUser = value;
if(keyFieldsReturned_[j] == 601 ) functionName = value;
if(keyFieldsReturned_[j] == 602 ) functionType = value;
if(keyFieldsReturned_[j] == 1307) messageReply = value;
if(keyFieldsReturned_[j] == 1309) qualMessageQueue = value;
if(keyFieldsReturned_[j] == 1906) qualSubsystem = value;
if(keyFieldsReturned_[j] == 1308)
{
byte[] msgKey = new byte[4];
System.arraycopy(data, offset + keyOffset, msgKey, 0, 4);
messageKey = msgKey;
}
if(j > 6){
if(keyFieldsReturned_[j] == 312 || keyFieldsReturned_[j] == 313 ||
keyFieldsReturned_[j] == 315 || keyFieldsReturned_[j] == 317 ||
keyFieldsReturned_[j] == 414 || keyFieldsReturned_[j] == 415 ||
keyFieldsReturned_[j] == 416 || keyFieldsReturned_[j] == 417 ||
keyFieldsReturned_[j] == 1609)
keyValues.put(keyFieldsReturned_[j], new Long(BinaryConverter.byteArrayToLong(data, offset + keyOffset))) ;
else
keyValues.put(keyFieldsReturned_[j], value) ;
}
}
else
{
if ((keyFieldsReturned_[j] == Job.TEMP_STORAGE_USED_LARGE))
keyValues.put(keyFieldsReturned_[j], new Long(BinaryConverter.byteArrayToUnsignedInt(data, offset + keyOffset))) ;
else
keyValues.put(keyFieldsReturned_[j], new Integer(BinaryConverter.byteArrayToInt(data, offset + keyOffset))) ;
}
}
listItems[i] = new SubsystemJobListItem(jobName, jobUser, jobNumber,
status, jobType,jobSubtype, currentUser, functionName, functionType,
messageReply, messageKey, qualMessageQueue, qualSubsystem);
subsystemJobs_[i] = new Job(this.getSystem(), jobName, jobUser, jobNumber);
listItems[i].setKeyValues(keyValues);
}
return listItems;
}
@Override
protected int getBestGuessReceiverSize(int number) {
return 300 * number;
}
}
File : SubsystemJobOpenListTest.java
//////////////////////////////////////////////////////////////////////////////
//
//
// Filename: SubsystemJobOpenListTest.java
//
// Author : Vengoal Chang
//
// Date : 2015/07/01
//
//
///////////////////////////////////////////////////////////////////////////////
package com.vengoal.as400.list;
import java.util.Enumeration;
import com.ibm.as400.access.AS400;
import com.ibm.as400.access.CallStackEntry;
import com.ibm.as400.access.Job;
import com.vengoal.as400.common.MessageUtil;
public class SubsystemJobOpenListTest {
public static void main(String[] args) {
AS400 as400 = new AS400("as400ip", "user", "pass");
String subsystem = "QBATCH";
SubsystemJobOpenList list = new SubsystemJobOpenList(as400, subsystem);
list.addJobAttributeToRetrieve(SubsystemJobListItem.MEMORY_POOL);
list.addJobAttributeToRetrieve(SubsystemJobListItem.RUN_PRIORITY);
list.addJobAttributeToRetrieve(SubsystemJobListItem.DATE_ENTERED_SYSTEM);
list.addJobAttributeToRetrieve(SubsystemJobListItem.JOB_LOG_PENDING);
list.addJobAttributeToRetrieve(SubsystemJobListItem.JOB_TYPE_ENHANCED);
list.addJobAttributeToRetrieve(SubsystemJobListItem.SPOOLED_FILE_ACTION);
list.addJobAttributeToRetrieve(SubsystemJobListItem.THREAD_COUNT);
list.addJobAttributeToRetrieve(SubsystemJobListItem.CPU_TIME_USED_LARGE);
list.addJobAttributeToRetrieve(SubsystemJobListItem.ELAPSED_CPU_PERCENT_USED);
list.addJobAttributeToRetrieve(SubsystemJobListItem.ELAPSED_CPU_TIME_USED);
list.addJobAttributeToRetrieve(SubsystemJobListItem.ELAPSED_PAGE_FAULTS);
list.addJobAttributeToRetrieve(SubsystemJobListItem.DISK_IO);
list.addJobAttributeToRetrieve(SubsystemJobListItem.ELAPSED_DISK_IO_ASYNCH);
list.addJobAttributeToRetrieve(SubsystemJobListItem.ELAPSED_DISK_IO_SYNCH);
try {
list.open();
Enumeration items = list.getItems();
while (items.hasMoreElements())
{
SubsystemJobListItem item = (SubsystemJobListItem)items.nextElement();
System.out.println(item);
if(item.getMessageReply().equalsIgnoreCase(Job.MESSAGE_REPLY_WAITING)){
System.out.println(MessageUtil.getErrMsgTxtWithAPI(as400, item.getMessageKey(), item.getQualMessageQueue()));
Job msgwJob = new Job(as400, item.getJobName(), item.getJobUser(), item.getJobNumber());
CallStackEntry[] callstackEntry = msgwJob.getCallStack(Job.INITIAL_THREAD);
System.out.println("job call stack as following:");
for(int i = 0; i< callstackEntry.length; ++i){
//System.out.println(callstackEntry[i].getProgramLibrary() + "/" + callstackEntry[i].getProgramName() + " " + callstackEntry[i].getProcedureName());
}
}
System.out.println("Spooled file action=" + item.getObject(SubsystemJobListItem.SPOOLED_FILE_ACTION));
System.out.println("====================================");
}
Job[] subsystemJobs = list.getSubsystemJobs();
if(subsystemJobs != null){
for(int i =0; i < subsystemJobs.length; ++i){
// do your work related job
System.out.println(subsystemJobs[i].getNumber() + "/" + subsystemJobs[i].getUser() + "/" + subsystemJobs[i].getName());
}
} else {
System.out.println("Subsystem " + subsystem + " is inactive or not exist");
}
list.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
參照: Open List of Jobs (QGYOLJOB) API
A blog about IBM i (AS/400), MQ and other things developers or Admins need to know.
星期四, 11月 09, 2023
2015-07-02 Get AS400 Subsystem jobs with java( Open List of Jobs (QGYOLJOB) API format OLJB0300)
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言