/** * \brief Linked List Utilities * * This module contains several procedures which uses the linked * list procedures for storing simple data. * * \author Mihael Schmidt * \date 23.02.2008 * * \rev 15.03.2008 Mihael Schmidt * added procedure lutil_listObjects * * \rev 18.03.2009 Mihael Schmidt * added procedure lutil_listDatabaseRelations */ HNOMAIN /if not defined(QUSEC) /define QUSEC /copy QSYSINC/QRPGLESRC,QUSEC /endif *------------------------------------------------------------------------ * Prototypen *------------------------------------------------------------------------ /copy LUTIL_H /copy LLIST_H /copy OS_API_H /copy USRSPC_H /copy PARMEVAL_H /copy LIBC_H /** * \brief List file member names * * All member names of a file are placed into a linked list. * This list is returned to the caller. On any error *null is * returned. * * \author Mihael Schmidt * \date 23.02.2008 * * \param Library name * \param File name * * \return pointer to list or *null if any error occurs */ P lutil_listFileMembers... P B export D PI * D library 10A const D filename 10A const * D list S * D usPtr S * D usHeader DS likeds(userspace_gen) based(usPtr) D usName S 10A D usLib S 10A inz('QTEMP') D dataPtr S * D usData S 10A based(dataPtr) D i S 10I 0 /free monitor; reset QUSEC; QUSBPRV = 0; usName = %subst(%str(tmpnam(*omit)) : 7); createUserSpace(usName + usLib : *blank : 4096 : X'00' : '*ALL' : 'List Util UserSpace' : '*YES' : QUSEC ); // change user space attributes to autoextend userspace_attr.size = 1; // 1=attribute will be changed userspace_attr.key = 3; // 3=extensibility attribute userspace_attr.dataLength = 1; userspace_attr.data = '1'; // user space is extensible changeUserspaceAttr(usLib : usName + usLib : userspace_attr : QUSEC); retrieveUserspacePtr(usName + usLib : usPtr : QUSEC); listFileMembers( usName + usLib : 'MBRL0100' : filename + library : '*ALL' : '1' : QUSEC); list = list_create(); // iterate through retrieved members for i = 0 to usHeader.nmbrEntries - 1; dataPtr = usPtr + usHeader.offsetList + (i * usHeader.entrySize); list_add(list : %addr(usData) : %len(%trim(usData))); endfor; deleteUserspace(usName + usLib : QUSEC); on-error *all; if (list <> *null); list_dispose(list); endif; return *null; endmon; return list; /end-free P E /** * \brief List record format names * * All record format names of a file are placed into a linked list. * This list is returned to the caller. On any error *null is * returned. * * \author Mihael Schmidt * \date 25.02.2008 * * \param Library name * \param File name * * \return Pointer to list or *null if any error occured */ P lutil_listRecordFormats... P B export D PI * D library 10A const D filename 10A const * D list S * D usPtr S * D usHeader DS likeds(userspace_gen) based(usPtr) D usName S 10A D usLib S 10A inz('QTEMP') D dataPtr S * D usData S 10A based(dataPtr) D i S 10I 0 /free monitor; reset QUSEC; QUSBPRV = 0; usName = %subst(%str(tmpnam(*omit)) : 7); createUserSpace(usName + usLib : *blank : 4096 : X'00' : '*ALL' : 'List Util UserSpace' : '*YES' : QUSEC ); // change user space attributes to autoextend userspace_attr.size = 1; // 1=attribute will be changed userspace_attr.key = 3; // 3=extensibility attribute userspace_attr.dataLength = 1; userspace_attr.data = '1'; // user space is extensible changeUserspaceAttr(usLib : usName + usLib : userspace_attr : QUSEC); retrieveUserspacePtr(usName + usLib : usPtr : QUSEC); listRecordFormats( usName + usLib : 'RCDL0100' : filename + library : '1' : QUSEC); list = list_create(); // iterate through retrieved members for i = 0 to usHeader.nmbrEntries - 1; dataPtr = usPtr + usHeader.offsetList + (i * usHeader.entrySize); list_add(list : %addr(usData) : %len(%trim(usData))); endfor; deleteUserspace(usName + usLib : QUSEC); on-error *all; if (list <> *null); list_dispose(list); endif; return *null; endmon; return list; /end-free P E /** * \brief List objects * * All object names are placed into a linked list. * This list is returned to the caller. On any error *null is * returned. * * <br><br> * * The entries in the list have the following format: * <ul> * <li>10A Library name</li> * <li>10A Object name</li> * <li>10A Object type</li> * </ul> * * <br><br> * As this procedure utilizes the QUSLOBJ i5/OS API the parameters * here accept the same names and generic names for library, name and * object type. * * \param Library * \param Object name (default: *all) * \param Object type (default: *all) * * \return Pointer to list or *null if any error occured */ P lutil_listObjects... P B export D PI * D pLibrary 10A const D pObject 10A const options(*omit : *nopass) D pType 10A const options(*nopass) * D lib S 10A inz('*ALL') D obj S 10A inz('*ALL') D type S 10A inz('*ALL') D usHeader DS likeds(userspace_gen) based(usPtr) D usName S 10A D usLib S 10A inz('QTEMP') D usPtr S * * D ptr S * D i S 10I 0 D list S * inz(*null) /free monitor; lib = pLibrary; reset QUSEC; QUSBPRV = 0; usName = %subst(%str(tmpnam(*omit)) : 7); if (%parms() >= 2 and %addr(pObject) <> *null); obj = pObject; endif; if (%parms() = 3); type = pType; endif; // userspace erstellen createUserspace(usName + usLib : 'DATA' : 4096 : X'00' : '*ALL' : %trimr(usName) + ' UserSpace' : '*YES' : QUSEC); userspace_attr.size = 1; // 1=attribute will be changed userspace_attr.key = 3; // 3=extensibility attribute userspace_attr.dataLength = 1; userspace_attr.data = '1'; // user space is extensible changeUserspaceAttr(usLib : usName + usLib : userspace_attr : QUSEC); retrieveUserSpacePtr(usName + usLib : usPtr : QUSEC); listObjects( usName + usLib : 'OBJL0100' : obj + lib : type : QUSEC ); list = list_create(); for i = 0 to usHeader.nmbrEntries - 1; ptr = usPtr + usHeader.offsetList + (i * usHeader.entrySize); list_add(list : ptr : 30); endfor; // delete userspace deleteUserspace(usName + usLib : QUSEC); on-error *all; if (list <> *null); list_dispose(list); endif; return *null; endmon; return list; /end-free P E /** * \brief List Job Library List * * All libraries of the library list of the specified job will be added * in the order of the library list returned in a linked list. * * <br><br> * * The qualified job name consists of the following parts: * <ul> * <li>CHAR (10) - Job Name</li> * <li>CHAR (10) - User Name</li> * <li>CHAR (6) - Job Number</li> * </ul> * * <br> * * If both parameters are passed then the library list of the job with * the qualified job name will be retrieved. * * \author Mihael Schmidt * \date 10.04.2008 * * \param Qualified Job Name (optinal, default = current job) * \param Internal Job Number (optinal) * \param Library parts (see LUTIL_C) * * \return Pointer to list or *null if any error occured */ P lutil_listJobLibraryList... P B export D PI * D qualJobName 26A const options(*omit : *nopass) D internalJobNumber... D 16A const options(*omit : *nopass) D libParts 10I 0 const options(*nopass) * D selLibParts DS qualified D system N D product N D current N D user N D selParts 4A overlay(selLibParts) * D jobi0700ds DS qualified D bytesReturned... D 10I 0 D bytesAvailable... D 10I 0 D jobname 10A D username 10A D jobnumber 6A D intJobNumber 16A D jobstatus 10A D jobtype 1A D jobsubtype 1A D reserved 2A D numberSysLibs... D 10I 0 D numberProdLibs... D 10I 0 D numberCurrentLibs... D 10I 0 D numberUserLibs... D 10I 0 * D offsetSystem S 10I 0 D offsetProduct S 10I 0 D offsetCurrent S 10I 0 D offsetUser S 10I 0 * D list S * D receiver S 65535A D libPtr S * D lib S 11A based(libPtr) D i S 10I 0 /free monitor; reset QUSEC; QUSBPRV = 0; if (%parms() = 3); selLibParts.selParts = evalParm(libParts); else; selLibParts.selParts = '1111'; endif; if (%parms() >= 1 and %addr(qualJobName) <> *null); retrieveJobInformation(receiver : %len(receiver) : 'JOBI0700' : qualJobName : '' : QUSEC); elseif (%parms() >= 2 and %addr(internalJobNumber) <> *null); retrieveJobInformation(receiver : %len(receiver) : 'JOBI0700' : '*INT' : internalJobNumber :QUSEC); else; retrieveJobInformation(receiver : %len(receiver) : 'JOBI0700' : '*' : '' : QUSEC); endif; jobi0700ds = receiver; list = list_create(); // calculate offsets offsetSystem = 80; offsetProduct = offsetSystem + jobi0700ds.numberSysLibs * 11; offsetCurrent = offsetProduct + jobi0700ds.numberProdLibs * 11; offsetUser = offsetCurrent + jobi0700ds.numberCurrentLibs * 11; // add system libraries if (selLibParts.system); libPtr = %addr(receiver) + offsetSystem; for i = 0 to jobi0700ds.numberSysLibs - 1; list_add(list : libPtr : %len(%trimr(lib))); libPtr = libPtr + 11; endfor; endif; // add product libraries if (selLibParts.product); libPtr = %addr(receiver) + offsetProduct; for i = 0 to jobi0700ds.numberProdLibs - 1; list_add(list : libPtr : %len(%trimr(lib))); libPtr = libPtr + 11; endfor; endif; // add current library if (selLibParts.current and jobi0700ds.numberCurrentLibs > 0); libPtr = %addr(receiver) + offsetCurrent; list_add(list : libPtr : %len(%trimr(lib))); endif; // add user libraries if (selLibParts.user); libPtr = %addr(receiver) + offsetUser; for i = 0 to jobi0700ds.numberUserLibs - 1; list_add(list : libPtr : %len(%trimr(lib))); libPtr = libPtr + 11; endfor; endif; on-error *all; if (list <> *null); list_dispose(list); endif; return *null; endmon; return list; /end-free P E /** * \brief List Active Jobs in Subsystem * * All active jobs of the specified subsystem will be added to the list. * The entries of the list are qualified job names which consist of the * following parts: * <ul> * <li>CHAR (10) - Job Name</li> * <li>CHAR (10) - User Name</li> * <li>CHAR (6) - Job Number</li> * </ul> * * <br> * * Subsystem monitor jobs are exluded from the list. * * \author Mihael Schmidt * \date 29.04.2008 * * \param Subsystemdescription library * \param Subsystemdescription name * * \return Pointer to list or *null if any error occured * * \info The user calling this procedure must have *JOBCTL * authorities else this procedure returns *null. */ P lutil_listActiveSubsystemJobs... P B export D PI * D sbsLib 10A const options(*nopass) D sbsName 10A const options(*nopass) * D cSbsName C 1906 * D list S * inz(*null) D usLib S 10A inz('QTEMP') D usName S 10A D usPtr S * D usHeader DS likeds(userspace_gen) based(usPtr) D i S 10I 0 * D jobPtr S * D jobDs DS qualified based(jobPtr) D name 10A D user 10A D number 6A D internalId 16A D status 10A D type 1A D subtype 1A D reserved1 2A D infoStatus 1A D reserved2 3A D fieldsReturned... D 10I 0 D keyArray 1A * D keyArrPtr S * D jobKeyArray DS qualified based(keyArrPtr) D bytesReturned... D 10I 0 D keyField 10I 0 D dataType 1A D reserved 3A D dataLength 10I 0 D data 20A /free monitor; reset QUSEC; QUSBPRV = 0; usName = %subst(%str(tmpnam(*omit)) : 7); // userspace erstellen createUserspace(usName + usLib : 'DATA' : 4096 : X'00' : '*ALL' : %trimr(usName) + ' UserSpace' : '*YES' : QUSEC); userspace_attr.size = 1; // 1=attribute will be changed userspace_attr.key = 3; // 3=extensibility attribute userspace_attr.dataLength = 1; userspace_attr.data = '1'; // user space is extensible changeUserspaceAttr(usLib : usName + usLib : userspace_attr : QUSEC); retrieveUserSpacePtr(usName + usLib : usPtr : QUSEC); listJobs(usName + usLib : 'JOBL0200' : '*ALL *ALL *ALL' : '*ACTIVE' : QUSEC : '*' : 1 : cSbsName); list = list_create(); for i = 0 to usHeader.nmbrEntries - 1; jobPtr = usPtr + usHeader.offsetList + (i * usHeader.entrySize); keyArrPtr = %addr(jobDs.keyArray); if (jobKeyArray.keyField <> cSbsName or jobKeyArray.dataType <> 'C' or jobKeyArray.dataLength <> 20); // TODO send message to job log list_dispose(list); list = *null; leave; endif; // only list jobs in requested subsystem // and ignore subsystem monitor jobs if (jobKeyArray.data = sbsName + sbsLib and jobDs.type <> 'M'); list_add(list : %addr(jobDs) : 26); endif; endfor; // delete userspace deleteUserspace(usName + usLib : QUSEC); on-error *all; if (list <> *null); list_dispose(list); endif; return *null; endmon; return list; /end-free P E /** * \brief List database relations * * All database relations (logical files, views and indices) are added * to the list. This list is returned to the caller. On any error *null is * returned. If the file does not exist *null is returned. If the file has * no relations an empty list is returned. * * <br><br> * * The entries in the list have the following format: * <ul> * <li>10A File name</li> * <li>10A Library name</li> * </ul> * * \author Mihael Schmidt * \date 19.03.2009 * * \param Library name * \param File name * * \return pointer to list or *null if any error occurs */ P lutil_listDatabaseRelations... P B export D PI * D library 10A const D file 10A const * D usAttr DS likeds(userspace_attr) D usLib S 10A D usName S 10A D usPtr S * D usHeader DS likeds(userspace_gen) based(usPtr) * D localPtr S * D dblr0100 DS qualified based(localPtr) D filename 10A D library 10A D depFilename 10A D depLibrary 10A D depType 1A D reserved 3A D joinRefNumber... D 10I 0 D constraintLibraryName... D 10A D constraintNameLength... D 10I 0 D constraintName... D 258A * D i S 10I 0 D list S * /free monitor; usLib = 'QTEMP'; usName = %subst(%str(tmpnam(*omit)) : 7); reset QUSEC; QUSBPRV = 0; // creating/modifying userspace createUserspace(usName + usLib : 'LUTIL' : 65536 : ' ' : '*ALL' : 'LUTIL Userspace' : '*YES' : QUSEC ); usAttr.size = 1; // 1=attribute will be changed usAttr.key = 3; // 3=extensibility attribute usAttr.dataLength = 1; usAttr.data = '1'; // user space is extensible changeUserspaceAttr(usLib : usName + usLib : usAttr : QUSEC); retrieveUserSpacePtr(usName + usLib : usPtr : QUSEC); listDatabaseRelations(usName + usLib : 'DBRL0100' : file + library : *blank : *blank : QUSEC); list = list_create(); for i = 0 to usHeader.nmbrEntries - 1; localPtr = usPtr + (i * usHeader.entrySize) + usHeader.offsetList; if (dblr0100.depFilename = '*NONE'); // no dependencies leave; else; list_add(list : %addr(dblr0100.depFilename) : 20); endif; endfor; if (usPtr <> *null); deleteUserspace(usName + usLib : QUSEC); endif; on-error *all; if (list <> *null); list_dispose(list); endif; return *null; endmon; return list; /end-free P E /** * \brief List jobs * * Returns a list of qualified job names which matches the passed parameters. * * <br><br> * * The qualified job name consists of the following parts: * <ul> * <li>CHAR (10) - Job Name</li> * <li>CHAR (10) - User Name</li> * <li>CHAR (6) - Job Number</li> * </ul> * * <br><br> * * Valid values for the job status are : *ACTIVE, *JOBQ, *OUTQ, *ALL. * * \author Mihael Schmidt * \date 16.04.2009 * * \param Qualified job name * \param Job status (default: *ALL) * \param Active job status (optional) * * \info For valid values for the parameters look at the i5/OS API QUSLJOB * and QUSRJOBI. */ P lutil_listJobs B export D PI * D qualJobName 26A const D pStatus 10A const options(*nopass) D activeStatus 4A const options(*nopass) * D list S * D usLib S 10A inz('QTEMP') D usName S 10A D usPtr S * D usHeader DS likeds(userspace_gen) based(usPtr) D i S 10I 0 D status S 10A inz('*ALL') * D jobPtr S * D jobDs DS qualified based(jobPtr) D qualJobName 26A D name 10A overlay(qualJobName) D user 10A overlay(qualJobName : *next) D number 6A overlay(qualJobName : *next) D internalId 16A D status 10A D type 1A D subtype 1A D reserved1 2A D infoStatus 1A D reserved2 3A D fieldsReturned... D 10I 0 D keyArray 1A * D receiver S 1000A D jobi0200ds DS qualified D raw 226A D activeStatus 4A overlay(raw : 108) /free if (%parms() >= 2); status = pStatus; endif; monitor; reset QUSEC; QUSBPRV = 0; usName = %subst(%str(tmpnam(*omit)) : 7); // userspace erstellen createUserspace(usName + usLib : 'DATA' : 4096 : X'00' : '*ALL' : %trimr(usName) + ' UserSpace' : '*YES' : QUSEC); userspace_attr.size = 1; // 1=attribute will be changed userspace_attr.key = 3; // 3=extensibility attribute userspace_attr.dataLength = 1; userspace_attr.data = '1'; // user space is extensible changeUserspaceAttr(usLib : usName + usLib : userspace_attr : QUSEC); retrieveUserSpacePtr(usName + usLib : usPtr : QUSEC); listJobs(usName + usLib : 'JOBL0200' : qualJobName : status : QUSEC); list = list_create(); for i = 0 to usHeader.nmbrEntries - 1; jobPtr = usPtr + usHeader.offsetList + (i * usHeader.entrySize); if (status = '*ALL' or jobDs.status = status); // for active jobs we may have to check for active job status if (%parms() = 3); retrieveJobInformation(receiver : %len(receiver) : 'JOBI0200' : jobDs.qualJobName : '' : QUSEC); jobi0200ds = receiver; if (jobi0200ds.activeStatus = activeStatus); list_add(list : %addr(jobDs.qualJobName) : 26); endif; else; // don't have to check the active status, just add the job to the list list_add(list : %addr(jobDs.qualJobName) : 26); endif; endif; endfor; on-error *all; if (list <> *null); list_dispose(list); endif; endmon; return list; /end-free P E