|The API Corner: Renaming and Moving Objects Doesn't Have to Be Difficult|
|Programming - APIs|
|Written by Bruce Vining|
|Wednesday, 18 January 2012 00:00|
The Rename Object API offers flexibility above and beyond just renaming.
In last month's article, Deleting Objects, we reviewed a rather general-purpose API: Delete Object (QLIDLTO). This month, we'll look at another general purpose API: the Rename Object (QLIRNMO) API, which is documented here and has been available since V2R3. The Rename Object API, as you might expect, allows you to rename an object. Not as obvious, the QLIRNMO API also allows you to move an object. As with QLIDLTO, using the Rename Object API allows you to directly operate on an object without having to run a CL command from your RPG application program under the covers.
The Rename Object API defines seven parameters: five that are required, two that are optional.
The first parameter is a standard 20-byte qualified object name with the first 10 characters identifying the name of the object to be renamed and the second 10 characters the library associated with the object. Though it's not a feature you are likely to use very often, I will mention that the qualified object name does not have to conform to the standard naming conventions of the i. You can, for instance, identify an object with a name of all lowercase characters or a name containing special characters such as imbedded blanks, and then you can rename the object to a standard name so that it can be referenced by other applications on your system. This ability to use non-standard object names is fairly common to system APIs but, in most cases, is a feature to be avoided. In the case of QLIRNMO, this feature can, when you find an object on your system with an "unusual" name (typically an object coming from another system), save you from a lot of grief.
The second parameter is the type of object you want to rename. The value specified is prefixed by an asterisk as in *FILE, *DTAARA, *DTAQ, *PGM, etc. Note that there is no special value for this parameter such as *ALL. You must explicitly identify the type of object to be renamed by the API.
The third parameter identifies the new name of the object and provides the ability to also move the object to another library. While CL commands such as RNMOBJ allow only a simple (non-qualified) name for the NEWOBJ parameter, the QLIRNMO API supports the standard 20-byte qualified object name with the first 10 characters identifying the name of the object to be renamed and the second 10 characters the library to be associated with the renamed object. Change the library portion of the qualified object name and you have moved the object (in addition to optionally renaming the object, assuming you also change the object name portion) from the library identified by the first parameter of the Rename Object API to the library identified by the third parameter of the API.
If you want to have some fun with an understanding colleague (one who enjoys a joke and is not under any deadlines), you can also rename an object in a co-worker's personal library from a "good" name such as MYSRC (which should not have a large number of members if it's a file) to a rather difficult name to use such as BAD SOURCE (where there's a blank between the words BAD and SOURCE) or MYSRC? using the object name portion of the third parameter. Your co-worker will quickly find that commands such as STRSEU, CRTBNDRPG, etc. do not like these object names. To correct the situation, simply use the Rename Object API to rename the file back to MYSRC (and make sure you are available to perform this recovery action in a hurry!).
The fourth parameter allows you to control what action should be taken if the qualified object identified by the third parameter already exists. This parameter is a 1-byte character variable and defines three values. A value of '0' causes the API to return an error message if an object already exists with the object type identified by parameter two and the name identified by parameter three. A value of '1' instructs the API to replace the object identified by parameters two and three with the object identified by parameter one. A value of '2' has the API replace the object identified by parameters two and three with the object identified by parameter one and log a message to the job log if the object identified by parameters two and three was moved as part of the replacement. This movement can occur, for instance, if a *PGM object is being replaced and the system moves the replaced object to the QRPLOBJ library. If no movement took place, then no message is logged.
The fifth parameter is the standard API error code parameter, which allows you to control whether error situations should be returned as escape messages or as data within the error code parameter.
The sixth and seventh optional parameters, not used by this article, allow you to identify the auxiliary storage pools associated with the libraries identified by the first and third parameters, respectively.
Below is a sample program utilizing the QLIRNMO API. The sample program demonstrates both the rename and move capabilities of the API.
dRnmObj pr extpgm('QLIRNMO')
d FrmQualObj 20 const
d ObjTyp 10 const
d ToQualObj 20 const
d RplObj 1 const
d ErrCde likeds(QUSEC)
d FrmASPDevice 10 const options(*nopass)
d ToASPDevice 10 const options(*nopass)
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
dFrm ds qualified
d Obj 10
d Lib 10
dTo ds qualified
d Obj 10
d Lib 10
dArchive ds qualified
d Obj 10
d Lib 10 inz('ARCHIVE')
dRplOpt s 1
dRplNo c '0'
dRplYes c '1'
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;
Frm.Obj = 'FILE1';
Frm.Lib = 'BHVLIB';
ObjTyp = '*FILE';
To.Obj = 'FILE1A';
To.Lib = 'BHVLIB';
RplOpt = RplNo;
RnmObj(Frm :ObjTyp :To :RplOpt :ErrCde);
when ErrCde.Hdr.QUSBAvl = 0;
// Everything is fine, the object was renamed
when ErrCde.Hdr.QUSEI = 'CPF3201';
// Already have :To file object. Archive to ARCHIVE
// library, replacing any current archived instance
Archive.Obj = To.Obj;
RnmObj(To :ObjTyp :Archive :RplYes :EscErrCde);
RnmObj(Frm :ObjTyp :To :RplOpt :EscErrCde);
if ErrCde.Hdr.QUSBAvl <= %size(QUSEC);
LenMsgDta = 0;
LenMsgDta = (ErrCde.Hdr.QUSBAvl -
:ErrCde.MsgDta :LenMsgDta :'*DIAG'
:'*' :0 :MsgKey :EscErrCde);
*inlr = *on;
The application attempts to rename the file object FILE1 to FILE1A in library BHVLIB. When the object is a *FILE (which it is in the provided sample program) and the new object name (FILE1A in the example) already exists in BHVLIB, then the current instance of the new object name (FILE1A) is moved to a library named ARCHIVE. This move to ARCHIVE replaces any previous version of the new object name in the ARCHIVE library. The original object (FILE1) of BHVLIB is then renamed to the new name (FILE1A), still in BHVLIB.
If the object being renamed is not a *FILE and the new object name already exists in BHVLIB, then the application program does not use the ARCHIVE library. Instead, the program logs a diagnostic message to the job log indicating that the new object name currently exists and continues.
For demonstration purposes of how the Error code parameter can be used (an area of confusion that I receive lots of email about), the distinction in how different object types (*FILE vs. non-*FILE) are handled by the application program will be accomplished by examining the message ID field of the Error code parameter.
When the Bytes provided field of an error code structure (QUSBPrv) is set to a value of eight or more (the ErrCde instance of the error code parameter used by the sample application), then APIs do not return escape messages when an error situation is encountered. Rather, the message ID, and the replacement data associated with the message, can be returned in the API Error code parameter. This information can then be examined by the application program and various recovery actions can be implemented.
When the Bytes provided field of an error code structure is set to a value of zero (the EscErrCde instance of the error code parameter used by the sample application), then APIs will return escape messages when an error is encountered. The application program can then monitor for the escape message (which is not as efficient as simply examining an error code structure such as ErrCde) in order to implement recovery actions or, more often the case, end due to the un-monitored escape message being received by the application.
As seen in the sample application program, you can decide on an API call-by-call basis which version of the Error code parameter (ErrCde with no escape messages or EscErrCde with escape messages) you want to use. For a more extensive discussion of the Error code parameter see System API Basics.
When initially calling the QLIRNMO API, the sample program sets the first parameter to the qualified name FILE1 in library BHVLIB, the second parameter identifies the object type as a *FILE, the third parameter indicates that the new object name should be FILE1A in BHVLIB, the fourth parameter passed to the API is set to '0' (do not replace any object found with the name specified by the third parameter), and the fifth parameter indicates that errors encountered by the API should be returned as data within the fifth parameter (ErrCde).
If the object identified by the third parameter currently does not exist in BHVLIB, the API will rename the object and return to the application program. No error was encountered and the Bytes available (QUSBAvl) field of the ErrCde parameter will be set to zero.
If an error was encountered in the running of the API, then the Bytes available (QUSBAvl) field of the ErrCde data structure will be set to a non-zero value. The application program can determine what error was encountered by then examining the exception ID (QUSEI) field of the ErrCde parameter.
If the object identified by the third parameter currently exists in BHVLIB, and the object type is *FILE, the system will return CPF3201 - File &1 in library &2 already exists. Other object types, such as *PGMs, *DTAQs, etc., will return other messages. These messages may include CPF2112 - Object &1 in &2 type *&3 already exists, CPF2132 - Object &1 already exists in library &2, etc.
In the case of CPF3201 being returned to the sample program, the QLIRNMO API is called two additional times as part of the error recovery. The first call is to move the currently existing object (FILE1A in BHVLIB) to the ARCHIVE library. In this case, the fourth parameter is set to '1' (replace any existing instances of FILE1A in ARCHIVE) and the fifth parameter is specified as being the EscErrCde error code data structure. If any error is encountered during the move (for instance, the ARCHIVE library doesn't exist or the user is not authorized to replace the object in ARCHIVE), an escape message is to be sent by the API. As this escape message is not being monitored, the sample program will end abnormally, allowing the developer (or support personnel) to clearly see what went wrong. If the move request was successful, then the next call to the API attempts to rename the original object (FILE1) to the new name (FILE1A). Here, the EscErrCde error code data structure is also used as no error recovery is being attempted if this rename fails.
If any other error is encountered by the initial call to the QLIRNMO API, that is QUSEI is not 'CPF3201', then the program uses the Send Program Message (QMHSNDPM) API to send the error as a diagnostic message to the job log. The program does not end due to the error but does log the error for problem-determination purposes. When calling the QMHSNDPM API, the sample program again uses the EscErrCde error code parameter so that any error in logging the message will result in an escape message.
In this article, we've looked at how you can rename and move objects, a capability that is sure to be of use in some application programs. We've also reviewed how the API error code structure can be used to control how errors are returned to an application program, an essential tool when using system APIs.
As usual, if you have any API questions, send them to me at firstname.lastname@example.org. I'll see what I can do about answering your burning questions in future columns.
|Last Updated on Wednesday, 18 January 2012 00:00|