Thursday, May 1, 2014

When was object last used?

object last used dspobjd

Any company who has used an IBM i, or any other server, find that over time the amount of free disk space becomes an issue. Most of the reduction in free disk space can probably be explained by the amount of data being added to files. This makes a need for regular data purges a necessity. But how many also consider purging unused objects from their servers?

As part of regular maintenance of the applications I am responsible for I purge objects that have not been used in the past two years. I do this for two reasons:

  1. If I need to make a mass change I only have to be concerned with objects that are being used.
  2. By removing objects that are not used the size of the library is kept to a minimum. Therefore, the time to save the library as part of the daily save is kept to a minimum.

Once I identify an object that has not been used in that time I move it from the "live" library to an "archive" library, if there is a source member for the object I move it to the a source file in the "archive" library too.

When the purging has been completed the "archive" library can be backed up to tape, and then the library can be deleted from the IBM i. The tape of the save of the "archive" library is stored in a fire proof safe, or equivalent, on site. If any of the purged objects are needed they can be restored from the tape.

So how do you identify when objects were last used?

The 'Display Object Description', DSPOBJD, command contains all the information I need and much more. When I run the command to output to an output file, then I can run reports over the file for the information I want.

                      Display Object Description (DSPOBJD)

 Type choices, press Enter.

 Object . . . . . . . . . . . . . > *all      
   Library  . . . . . . . . . . . >   lib1      
 Object type  . . . . . . . . . . > *all   
                + for more values >        
 Detail . . . . . . . . . . . . . > *BASIC  
 ASP device:
   Device . . . . . . . . . . . . > *        
   Search type  . . . . . . . . . >        
 Output . . . . . . . . . . . . . > *OUTFILE
 File to receive output . . . . .   @dspobjd 
   Library  . . . . . . . . . . .     qtemp     
 Output member options:
   Member to receive output . . .   *FIRST    
   Replace or add records . . . .   *REPLACE

I am only interested in a few of the fields from the output file, these being:

Field Field description
ODLBNM Library name
ODOBNM Object name
ODOBTP Object type
ODOBAT Object attribute
ODCRTU Object created by
ODCDAT Object creation date
ODUDAT Last used date
ODOBTX Object text

Note: I am in the USA and the two date fields are in MMDDYY format. I do not know if format of those fields is hard coded or mirrors the format from the system value QDATFMT. If you are not in the USA check the format.

My current responsibilities include a good number of libraries. I leave any library provided by our ERP vendor alone. I only scrutinize all of the home grown software libraries. As there are so many libraries I could create a CL program that look like below:

01  PGM




90  SUBR       SUBR(SUBR01)
                 OUTPUT(*OUTFILE) +
                 OUTFILE(QTEMP/@DSPOBJD) +
                 OUTMBR(*FIRST *ADD)

Lines 3 and 4 are repeated for each library, changing the library name in the CHGVAR command.

You can learn more about executing subroutines by reading Subroutines in CL.

I recommend that this program run in batch, as it could take some time to complete depending upon the number of libraries and the number of objects in each one.

As the date is not in an useful format and there is a lot of additional fields in the file that I do not need for this task I use an RPGLE program to write the fields I want, and format the date fields, into another file. Below is the source for that phyiscal file:

A          R LASTUSEDR
A            LIB           10A         TEXT('Library')
A            OBJ           10A         TEXT('Object')
A            OBJTYPE        8A         TEXT('Object type')
                                       COLHDG('Object' 'type')
A            OBJATTR       10A         TEXT('Object attribute')
                                       COLHDG('Object' 'attribute')
A            CRTDTE          L         TEXT('Creation date')
                                       COLHDG('Creation' 'date')
A            CRTUSER       10A         TEXT('Created by user')
                                       COLHDG('Created' 'by user')
A            LASTDTE         L         TEXT('Last used date')
                                       COLHDG('Last used' 'date')
A            OBJTXT        50A         TEXT('Text description')
                                       COLHDG('Text description')

The RPGLE program is simple:

01 F@DSPOBJD  IF   E             DISK
02 FLASTUSED  O    E             DISK
03   dow (1 = 1) ;
04     read @DSPOBJD ;
05     if (%eof) ;
06       leave ;
07     endif ;

08     LIB = ODLBNM ;
09     OBJ = ODOBNM ;
13     OBJTXT = ODOBTX ;
14     CRTDTE = %date(ODCDAT:*mdy0) ;

15     test(de) *mdy0 ODUDAT ;
16     if (%error) ;
17       clear LASTDTE ;
18     else ;
19       LASTDTE = %date(ODUDAT:*mdy0) ;
20     endif ;

21     write LASTUSEDR ;
22   enddo ;

23   *inlr = *on ;

Note: If the format of the date in ODCDAT and ODUDAT is not MMDDYY, see previous Note, then lines 14, 15, and 19 will need to be changed to be appropriate date format code.

If the object has never been used the field ODUDAT is blank, which is not a valid date. Therefore, I perform a TEST(DE) operation to validate ODUDAT, line 15, and if the date is invalid I CLEAR the date field LASTDTE, line 17. When a date field is CLEARed it is initialized with the date 0001-01-01, therefore, if LASTDTE = 0001-01-01 then I know that the object has never been used.

I can now take the file LASTUSED and use it to search for objects that have not been used in two years.

Here's a gotcha. When a library is moved from one IBM i to another all of the 'Last Used date' fields are set to blank. If you are moving from an older IBM i to a newer one run the DSPOBJD on the old IBM i the day everything is moved to the new server. That way you have a last snapshot of when the objects were used.


You can learn about the DSPOBJD command from the IBM website here.


This article was written for IBM i 7.1, and it should work with earlier releases too.


  1. What about moving to a different IASP?

    1. I have to admit I have never used iASP (independent Auxillary Storage Pool). Doing a quick (Google) search I do not see many results from people using them.

      If you use them I would like to hear more about them and their pros/cons.

  2. James Michael Gerard JonesMay 2, 2014 at 4:32 AM

    Doesn't utilities such as Hawkeye allow reports of objects and sources which haven't been used in over two years? If your shop takes annual complete backups, deleting all objects in that list right afterward is a start. Yet some objects may get only called in low-probability cases (say to send an error message), yet exist for good reason.

    1. Hawkeye probably does have some functionality like that but not everyone has it on their IBM i. The solution I describe will work on all IBM i, without any additional software.

      You are correct I do not blindly delete everything that has not been used in the last 2 years. This is why I create the file. The objects are reviewed to see if there is process that might need them in the future. If there is the object is not deleted.

      I do not use the regular SAVSYS tapes as my backup as they are stored offsite by a 3rd party. My backup of the “archive” libraries is stored onsite, if I need to restore objects it can be done quickly. If I need to restore from a SAVSYS tape it takes 24 hours to request it from the 3rd party before I receive it.

      In my 8 years of doing this process I have only had to move 3 objects back from "archive" to "live", and I have deleted thousands of objects.

    2. James Michael Gerard JonesMay 2, 2014 at 4:42 PM

      Anyone running a seriously-in-business i/OS operation will have some sort of software-inventory and change-control package, either bought or home-grown. I know I would never return to those bad old days of just slamming things into production like a Microsoft.

      The review process you describe may be overkill. Just ensuring that annual complete backups onto media which persists as long as the system platform does is likely sufficient.

      But each SysAdmin knows his circumstance best.

    3. You do not want to have tapes that are kept for many, many years as they could become part of a e-discovery warrant. My current employer keeps tapes for 7 years at the most & then have then destroyed. If they do not exist then the lawyers cannot go on a "fishing trip" to see what data you have from 7+ years ago.

    4. James Michael Gerard JonesMay 2, 2014 at 4:43 PM

      Magnetic media more than 7 years old likely unreliable anyway. Optical media, who knows?

      If a need for an object not discovered in 5 years, maybe never needed in first instance. Dynamic -living- operations will have moved on in various ways, not least different ways of doing business.

  3. Another issue you might want to consider is that some low level i5/os functions do not update the last used date. so... deleting objects from IBM libraries should not be done no matter what the last used date is.

    1. Thank you Spencer for the reminder. I agree. What I have suggested should NEVER be performed on any IBM libraries.

  4. One other step to consider in this process as it did happen to us. If you are removing a program object you should also check to see if the object is on any users menus. We had one office who had a process that they run monthly when it was first setup, then went to yearly, then every 3 years. We looked for unused objects over 2 years old and archived them. This one option got archived and never removed from the users menu and when it was time to use it, it was a report due in 24 hours and when the user tried to run it of course it failed. Took some major scrambling to find the tape it was on, restore all the parts (was actually 4 RPG apps, 5 print files, a display file and 3 CLs) and got it to run again. MIght be a good step to check with the end user before archiving

  5. If the object has not been referenced(use wrkobjpdm and place a 8) in the past 18 months. I delete the object and copy the source to a library that is called obsolete. If the object is needed we always have backups.

  6. Don't be fooled by any IBM supplied object that does not get used. I was duped into believing that an IBM program product was not being used because the last used date field was blank. The programmer told me he thought I was wrong. So I turned on auditing and audited the use of the objects in the program library. The programmer was right. I was wrong. I called IBM to try to understand. IBM says that 'most' IBM supplied objects do not update the 'Last Used ' field in the object description.

    I currently have an IBM PMR open regarding the last Saved field in the object description. I did the dspobjd on all objects on my system and I have over 25,000 objects that have never been saved!!! and that was 20 minutes after I completed an option 21 full system save!

  7. Hi Simon: Excellent article; I am wondering if there is any way that I can check in our IBM i, which users have used a determined object. As in example, I need to make changes and test a RPG P5600500RG. I know this object was used 50 times; but I need a list of the users who used the job. BTW, I do not have any journals. Can you help me please. Carlos

    1. Alas, that is not possible. IBMi only records "on" the object those details, and not who used it.


To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.