Admin Alert: The Process and Pitfalls of Duplicating Libraries
April 11, 2007 Joe Hertvik
Last fall, I wrote a column discussing the pitfalls of duplicating files to a test library. However copying files and logicals between environments is just the tip of the iceberg. There is an entirely different set of issues involved when you are trying to duplicate an entire library for test purposes. To that end, here’s my procedural checklist for making an (almost) exact copy of any native i5/OS library.
Why We Copy
There are many reasons for copying i5/OS libraries, but the most common needs are to create or refresh a test environment with production data, to use an existing data library as the basis for a new system, or to copy production programs and code for future modifications. While the mechanics of creating a duplicate library are simple, there are a number of additional steps that should be taken to ensure that work in the duplicated library does not affect data or programs in the source library that the new lib is based on.
This checklist is designed so that it duplicates an i5/OS library so that the new library is totally independent from its ancestor library. It contains solutions for the issues that I’ve run into when duplicating libraries and it is as complete as I can make it. If you have any additions or suggestions, please email me and I’ll be glad to include your ideas in a future column.
How to Duplicate
1. Save the library to media or to a save file. While you can create duplicate libraries by using either the Copy Lib (CPYLIB) or Create Duplicate Object (CRTDUPOBJ) commands or by using iSeries Navigator (OpsNav), I find that it’s better to save your source library and restore it to your target library. There are several reasons for copying a library this way, including.
So if you’re trying to copy an entire library, complete with data queues, saving the source library and then restoring it to your target library is your best bet.
In order to perform an SWA backup from your source library to a media device, I can use the following Save Library (SAVLIB) command:
SAVLIB LIB(source_lib) DEV(device_name)
The key parameter here is to set the Save Active parameter (SAVACT) to *SYNCLIB. *SYNCLIB tells the SAVLIB command to make sure that all of the objects in the saved library reach their backup checkpoint together so that they are saved in a consistent relationship to each other. The Save Active Message Queue parameter (SAVACTMSGQ) tells the command which message queue to send any save while active messages to. Once the checkpoint is reached for all library objects, the system will save each object at its particular checkpoint state to tape.
If I want to modify this command so that it backs up the library to a save file, I can run the command like this.
SAVLIB LIB(source_lib) DEV(*SAVF)
This command performs the same function as the media device command, except that it backs up the library to a save file. There are also functions to save and restore a library by using OpsNav, which I’ll try to cover in a later article.
2. If the target library already exists, clear, rename, or delete it before restoring the source library over it. Make sure that you have a current backup of the old target library before clearing it, in case you need to restore objects from the old library later.
To clear the library, I could use the following Clear Library command (CLRLIB)
To rename the library, I would use the following Rename Object command (RNMOBJ).
RNMOBJ OBJ(target_lib) OBJTYPE(*LIB) NEWOBJ(new_lib_name)
If I want to delete the library, I would use the following Delete Library command (DLTLIB).
3. Once the target library is cleared, renamed, or deleted, I can then restore the source library and most of its objects into a fresh version of the target library. To do that from media, I would run the following command.
RSTLIB SAVLIB(source_lib) DEV(device_name) MBROPT(*ALL)
If I am restoring the library from a save file, I would use the following command.
RSTLIB SAVLIB(source_lib) DEV(*SAVF)
4. At this point, I have an almost complete copy of the library. However, I may not be able to use the new library exactly as it is without making some changes. There are two issues that I need to resolve before the lib can be placed into general usage. The first issue is to deal with any objects that could not be restored from the source library. The second issue is to reset any application or configuration object so that they reference the new target library instead of the old source library. If I don’t perform the second step, I run the risk of having programs and data bleed from my target library to my source library when I perform operations on the target library. Again, the goal is to create a completely autonomous library environment where none of the objects in the target library have any affect on the objects in the source library from which they were copied. The next two steps cover that process.
5. You may find that several objects that were present in the original library cannot be restored to the new library. In particular, the following objects cannot be restored to a different library.
In most cases, SQL packages will automatically be created as necessary when a client program attaches to the system. If you need to use journaling for logging changes to your data files in the new target library, you will need to set up new journal files and journal receivers that are specific to the new library objects.
To double-check whether the correct number of objects have been restored from my source library, I can do one of two things. First, I can check the joblog of the job that restored the target library. There generally should be one message in the log for each object that the system attempted to restore. I can scan the log looking for messages designating objects that were not restored. I can also use the Display Library command (DSPLIB) to get a count of the number of objects in the source library and the number of objects in the target library. The DSPLIB command always displays the number of objects in the library you’re reviewing in the upper right hand corner of the screen. If I find that there are significantly fewer objects in the target library than there were in the source library, I can investigate further and even compare the libraries object by object, if needed. To do this, I would need to run two DSPLIB commands to retrieve the number of objects in each library. For my example, the DSPLIB commands would look like this.
6. Determining whether all of the restored objects are configured correctly for the target library is as significant as restoring the objects themselves. Configuration review is important because application programs may retrieve program information from certain library objects in order to locate and update files in your library. If those objects are still configured to modify or read data from the source library, applications running in the new library could fail. If the object points an application towards the wrong library, production data in other libraries could become corrupted. When copying one library to another, here is a partial list of i5 objects that should be checked and adjusted, if necessary, to make sure that applications using these objects are accessing the correct programs, libraries, and files.
Data areas: Some applications retrieve their library locations or library lists from data areas. Check to make sure that any references to the source library in a data area are changed to the target library.
In addition to checking for library names, also check to make sure that any data area literals are set to the right values for your target library. Literals may include control numbers for printed forms, company names, and other identifiers. If you are copying a data library for example, you may need to modify this literal information so that it matches the purpose that you are copying it for. In a test environment, for example, you may want to change your next available form numbers (invoices, shop orders, etc) to a different range from your live system numbers so that users can identify test system forms just by looking at their number range.
Job descriptions: If a batch job is submitted with a job description from your target library, the job may retrieve its library list from that job description, which may still include an entry for your source library. Check all target library job descriptions to ensure that they are using the right library lists for your jobs.
DDM files: DDM files point to companion files on remote servers, and a read, write, or update to a DDM file will access data on another server. Depending on why a source library is being duplicated, you may need to reposition a DDM file to another partition/library or eliminate a DDM file altogether to make sure that a target library application doesn’t update the wrong data on another server. To view and update all the DDM files in your target library and the remote files that they are connected to, run the following Work with DDM Files command (WRKDDMF).
Trigger programs: Ensure that any trigger programs attached to files in your target library are updating the correct data files when an associated target lib file is changed. See my previous article “The Pitfalls of Duplicating Data to a Test Library to understand the rules of how trigger programs are affected when a data file is copied to another library. To print a list of all the trigger programs attached to the files in your target library, run the following Print Trigger Programs command (PRTTRGPGM).
At this point, you should have a complete duplicated library that is reconfigured for your environment. While this checklist displays some of the major issues to consider when duplicating libraries, you should also note that there may be additional issues that are unique to the library you are duplicating. Running through this checklist may take more time that you would like to spend on copying libraries, but it’s better to spend a little more time up front so that you can avoid having to clean up data or application problems caused by a duplicate configuration.
About Our Testing Environment
All configurations described in this article were tested on an i5 550 box running i5/OS V5R3. Most of the commands used here are also available in earlier versions of the i5/OS and OS/400 operating systems, so the configurations should be usable in prior releases. However, you may notice minor variations in pre-V5R3 copies of these commands. These differences may be due to incremental command improvements that have occurred from release to release.