星期四, 11月 09, 2023

2015-07-02 Get AS400 Subsystem jobs with java( Open List of Jobs (QGYOLJOB) API format OLJB0300)


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




沒有留言: