The Delete Object API offers flexibility in terms of removing unneeded objects.
As a new year approaches, many of you may be looking at general house-cleaning of your i. This activity might include deleting those objects that have been created over the last 12 months and are no longer needed. In the past, if you wanted to automate such cleanup activities from, say, an RPG application program, you may have written various CL programs that were then called from the RPG program in order to run the appropriate DLTxxx CL command or, as an alternative, constructed the appropriate CL DLTxxx command within an RPG program variable and then run the command using an API such as Process Commands. If your system is at V6 or later, you now have another option, one that does not rely on running CL commands. This new technique, of course, is also available to your application programs whenever they need to delete an object, not just for general system maintenance.
The Delete Object (QLIDLTO) API, documented here, can be used to delete many (though not all) types of objects on your system. Object types supported include files, data areas, data queues, programs, menus, panel groups, device descriptions, and so on. A complete list of the object types supported can be found in the API documentation.
The API itself is quite straightforward with five parameters.
The first parameter is a standard 20-byte qualified object name with the first 10 characters identifying the name of the object to be deleted and the second 10 characters the library. The object name can be a specific name, such as FILE1, a generic name, such as FILE1*, or a special value, such as *ALL. Similarly, the library name can be a specific name, such as BHVLIB, or one of several special values, such as *LIBL, *CURLIB, *ALLUSR, etc. You will want to be careful with some of these combinations. For instance, if you specify a generic object name such as FILE1* and the special value *LIBL for the library, then all objects in your library list (of the type identified with the second parameter of the API) starting with the characters FILE1 will be deleted. This behavior might be just what you are looking for, or it might really ruin your day. If, on the other hand, you used the specific object name of FILE1 with the special value of *LIBL, then only the first occurrence of FILE1 within your library list would be deleted.
The second parameter is the type of object you want to delete. The value specified is prefixed by an asterisk (*) as in *FILE, *DTAARA, *DTAQ, *PGM, *MENU, *PNLGRP, *DEVD, etc. Note that there is no special value, such as *ALL, for this parameter. You must explicitly identify the type of object to be deleted by the API.
The third parameter identifies the auxiliary storage pool where the library containing the object(s) to be deleted can be found. Special values include *, *SYSBAS, *ALLAVL, etc.
The fourth parameter allows you to control whether or not completion and informational messages related to the object(s) deleted should be retained in the job log. The parameter is a 1-byte value where a value of '0' indicates that messages should not be removed and a value of '1'indicates that diagnostic and informational messages should be removed following the successful deletion of an object.
The fifth parameter is the standard API error-code parameter.
Here is a sample program demonstrating how to call the QLIDLTO API. To create the program, you can use the CRTBNDRPG command.
dDltObj pr extpgm('QLIDLTO')
d QualObj 20 const
d ObjTyp 10 const
d ASPDevice 10 const
d RmvMsg 1 const
d ErrCde likeds(QUSEC)
dSndPgmMsg pr extpgm('QMHSNDPM')
d MsgID 7 const
d QualMsgF 20 const
d MsgDta 65535 const options(*varsize)
d LenMsgDta 10i 0 const
d MsgTyp 10 const
d CSE 10 const
d CSE_Counter 10i 0 const
d MsgKey 4
d ErrCde likeds(QUSEC)
d LenCSE 10i 0 const options(*nopass)
d QualCSE 20 const options(*nopass)
d PgmMsgWait 10i 0 const options(*nopass)
d CSETyp 10 const options(*nopass)
d MsgDtaCCSID 10i 0 const options(*nopass)
dObjTyp s 10
dLenMsgDta s 10i 0
dMsgKey s 4
d Obj 10
d Lib 10
d MsgF 10 inz('QCPFMSG')
d MsgL 10 inz('*LIBL')
dErrCde ds qualified
d Hdr likeds(QUSEC)
d MsgDta 512
dEscErrCde ds qualified
d Hdr likeds(QUSEC)
ErrCde.Hdr.QUSBPrv = %size(ErrCde);
EscErrCde.Hdr.QUSBPrv = 0;
Obj = 'FILE1';
Lib = 'BHVLIB';
ObjTyp = '*FILE';
DltObj(QualObjName :ObjTyp :'*' :'0' :ErrCde);
when ErrCde.Hdr.QUSBAvl = 0;
// Everything is fine, the object was deleted
when ErrCde.Hdr.QUSEI = 'CPF2105';
// Object not found so no need to worry about
// the delete failing
if ErrCde.Hdr.QUSBAvl <= %size(QUSEC);
LenMsgDta = 0;
LenMsgDta = (ErrCde.Hdr.QUSBAvl -
:ErrCde.MsgDta :LenMsgDta :'*DIAG'
:'*' :0 :MsgKey :EscErrCde);
*inlr = *on;
The program defines two instances of the API error-code structure. The first instance, named ErrCde, is used when calling the QLIDLTO API to delete an object. The bytes-provided subfield of the ErrCde data structure (ErrCde.Hdr.QUSBPrv) is set to a non-zero value so that any error conditions encountered by the API will be returned in ErrCde, as opposed to being sent as escape messages to the application program. You will see how the sample program utilizes this ErrCde data structure shortly.
The second instance of the API error-code structure, named EscErrCde, is used when calling the Send Program Message (QMHSNDPM) API. This API, documented here and previously introduced in the article "Inform Users of Problems by Sending Error Messages from Application Programs," is used by the application program to send some (but not all) error conditions reported by the Delete Object API to the job log. The bytes-provided subfield of the EscErrCde data structure (EscErrCde.Hdr.QUSBPrv) is set to 0 so that any error condition encountered when sending a message will result in an escape message, allowing the user to know that something totally unexpected has occurred.
Having initialized the ErrCde and EscErrCde error-code data structures, the program then identifies what object it wants to delete. The object is a *FILE named FILE1, located in library BHVLIB. The QLIDLTO API is then called with the fourth parameter set to '0' (retain informational messages in the job log) and the fifth parameter to the ErrCde error-code data structure.
When the QLIDLTO API returns control to the application program, the sample program examines the ErrCde data structure to determine if any errors were encountered.
If the file BHVLIB/FILE1 was successfully deleted, the subfield ErrCde.Hdr.QUSBAvl will be 0 and the program moves on to its next task (in our case, setting on LR and returning). In this case, the successful deletion of file FILE1 in BHVLIB (the message CPC2191 – Object FILE1 in BHVLIB type *FILE deleted) will also be found in the job log due to the fourth parameter being set to '0' when calling the QLIDLTO API. If the API's fourth parameter were set to the value '1', then no message would be found in the job log.
If the file BHVLIB/FILE1 was not successfully deleted, the subfield ErrCde.Hdr.QUSBAvl will be non-zero and the program further interrogates the ErrCde data structure in order to determine the cause of the failure. The program first checks whether the subfield ErrCde.Hdr.QUSEI (the message exception ID) is set to the value 'CPF2105'. Message CPF2105 indicates that the file was not found, making it understandably difficult to delete the file. As our objective was to delete the file, and the file does not exist, the program simply continues on to its next task. In this case, no message such as CPC2191 will be in the job log as the file was not deleted, nor will there be any error messages.
If the subfield ErrCde.Hdr.QUSEI was not set to message ID CPF2105, the sample program then uses the QMHSNDPM message to resend the escape message identified by ErrCde.Hdr.QUSEI, as a diagnostic message, to the job log. These messages might be that the user of the program is not authorized to delete the object, that the object could not be deleted due to dependencies, that the object is locked by another job, etc. Using the message replacement data found in subfield ErrCde.MsgDta, the sample program writes to the job log the same message that the API would have sent as an escape message had we not set ErrCde.Hdr.QUSBPrv to a non-zero value—but without having to monitor for the escape message and/or ending abnormally. In this case, a message will be found in the job log documenting why the object was not deleted.
The QLIDLTO API provides a very flexible, and easy, way for application programs to delete objects that are no longer needed. I suspect that many of you will find one or two places within your applications where the API fits right in.