Planning for a Smooth Deployment in Cobol

Article ID: 57613

New software development methodologies, such as Extreme Programming (XP) and Rational Unified Process (RUP), demand the continuous deployment of software releases, both from the development environment to the test environment and from the test environment to the production environment. Because of the iterative, or cyclic, nature of this paradigm, anything that can be effectively automated should be automated. Even some usually manual operations, such as packaging all the objects that make up a release in a SAVF and transferring it (with FTP) to the destination server, can be automated. In this article, I present a Cobol program (BUILDSAVF) for programmatically building a SAVF. The objective is to achieve the smooth deployment of a software product from the development environment to the target (either test or production) environment.

To accomplish this goal, BUILDSAVF (downloadable via the link at the end of this article) uses the Save Object List (QSRSAVO) API. This API falls into the Backup and Recovery APIs category. Unlike the List APIs, which employ a user space to return information from the operating system to the caller program, the QSRSAVO API uses a user space to receive information from the caller program. Therefore, the caller program has the burden of building a relatively complex data structure onto a user space, passing it as a parameter to the API.

The QSRSAVO API offers the same functionality that we find in the Save Object (SAVOBJ) command. Each SAVOBJ command parameter has an equivalent key in the QSRSAVO API, which is identified by a number and with a specific format. The data structure built by the program consists of a four-byte binary field that represents the number of key formats in the user space followed by a series of data structures, each one representing one key format. Each key format is a variable-length record made up of the following fields:

  • The overall length of the variable-length record (four-byte binary)
  • The key number (four-byte binary)
  • The length of the key data (four-byte binary)
  • One or more fields, representing the key data (variable length)

Some of the functional requirements of BULDSAVF are:

  • The input is a database file which contains information about the objects that make up the release and, thence, must be packaged. Information includes the name of the developer who issues the piece of code, the creation date, the name of the destination server, the library in which the object will reside permanently, and so forth.
  • At the development server side, all the objects to be released reside in a single library.
  • There is no restriction about the object types that can be packaged (e.g., database files, executable programs, service programs, data areas, etc.).
  • For database files and source physical files, all their members are saved. The ability to pass a bound list of members for a source physical file requires additional parameters (or keys), not shown in this program.
  • The operation of transferring the SAVF to the destination server with FTP is performed by another program.
  • Some software deployments tasks, such as loading information into a database file or modifying a database record format, fall outside the scope of this program.

As a result of these requirements, the data structure created by the programs looks like this:

       01  user-space-fmt.
           02 number-of-records PIC 9(9) BINARY.

      *-------------------------------------------------*
      * Library key format # 2                          *
      *-------------------------------------------------*
           02 library-key-format.
              03 length-of-overall-key-fmt PIC 9(9) BINARY.
              03 format-key                PIC 9(9) BINARY.
              03 length-of-data-segment    PIC 9(9) BINARY.
              03 library-data.
                 04 number-of-libraries    PIC 9(9) BINARY.
                 04 library-name           PIC x(10).
              03 FILLER                    PIC XX.

      *--------------------------------------------------*
      * Device key format # 3                            *
      *--------------------------------------------------*
           02 device-key-format.
              03 length-of-overall-key-fmt PIC 9(9) BINARY.
              03 format-key                PIC 9(9) BINARY.
              03 length-of-data-segment    PIC 9(9) BINARY.
              03 device-data.
                 04 number-of-devices      PIC 9(9) BINARY.
                 04 device-name            PIC x(10).
              03 FILLER                    PIC XX.

      *--------------------------------------------------*
      * SAVF key format # 4                              *
      *--------------------------------------------------*
           02 savf-key-format.
              03 length-of-overall-key-fmt PIC 9(9) BINARY.
              03 format-key                PIC 9(9) BINARY.
              03 length-of-data-segment    PIC 9(9) BINARY.
              03 savf-data.
                 04 qual-savf-name.
                    05 savf-name           PIC x(10).
                    05 savf-library        PIC x(10).

      *--------------------------------------------------*
      * Object information key format # 1                *
      *--------------------------------------------------*
           02 object-key-format.
              03 fixed-portion.
                 04 length-of-overall-key-fmt PIC 9(9) BINARY.
                 04 format-key                PIC 9(9) BINARY.
                 04 length-of-data-segment    PIC 9(9) BINARY.
                 04 number-of-entries         PIC 9(9) BINARY.
              03 variable-portion.
                 04 objects-array OCCURS 0 TO 500 TIMES
                      DEPENDING ON number-of-entries
                         INDEXED BY t-index.
                    05 object-name            PIC x(10).
                    05 object-type            PIC x(10).

Now let me some characteristics of the above data structure.

The data structure (called user-space-fmt) is declared below the LINKAGE SECTION. Therefore, the compiler doesn't allocate storage for it. It can be referenced only after its address has been set to a pointer data item containing a valid address. BUILDSAVF creates a user space by using the Create User Space (QUSCRTUS) API and obtains its address with the Retrieve Pointer to User Space (QUSPTRUS) API. Later, the pointer returned by this API is assigned to the address of the user-space-fmt data structure. At this point, the program can set all the fields in the data structure.

The BUILDSAVF program declares four keys to be read by the API. Therefore, the program assigns the integer value "4" to the variable called number-of-records. IBM Information Center documents 36 keys (link is provided at the end of this article), two of which (library key and device key) are required and the rest of which are optional. Although the required keys contain arrays, BUILDSAVF uses only one element for each. That is, there is only one library to be saved in one device (the SAVF). For that reason, these two key formats don't contain the OCCURS clause (an "OCCURS 1 TIMES" clause sounds like a nonsense statement).

The object information key format, instead, defines an array that can hold up to 500 elements. At least in my shop, this is large enough to hold a single software release. But, regardless of the number of array elements declared in the OCCURS clause, the amount of data read by the API is determined by the value of the number-of-entries field. It's initialized with the value zero. For each record read from the database file, a new element is added to the array incrementing the number-of-entries field by 1. Thence, the object information obtained from the database file is loaded in the newly created array element.

To avoid hard-coding "magic numbers," the numeric fields in each key format are initialized using the LENGTH OF Cobol intrinsic function:

           MOVE LENGTH OF library-key-format TO
                length-of-overall-key-fmt IN library-key-format.

           MOVE LENGTH OF library-data TO
                length-of-data-segment IN library-key-format.

At the end of the device key and library key formats, I've added a two-byte filler to align these variable-length records on a four-byte boundary. The Information Center includes the following advice: "You should make the length of each variable-length record a multiple of 4, even if the data length is not a multiple of 4."

Notice that I've defined the object information key format after the other key formats, because this is a variable-length record. That is, the program doesn't know its length in advance because the length depends on the number of records in the input file. For that reason, the program can set the numeric fields of this data structure only when it leaves the main loop and the array has reached its maximum length:

       COMPUTE length-of-data-segment IN object-key-format =
                LENGTH OF variable-portion.

       COMPUTE length-of-overall-key-fmt IN object-key-format =
                LENGTH OF variable-portion +
                LENGTH OF fixed-portion.

Once all the fields in the user-space-fmt data structure have been properly set, the BUILDSAVF program can call the QSRSAVO API. It accepts only two parameters: the qualified user space name and the error code data structure. Both are mandatory. The error code output parameter is a variable-length data structure used by many system APIs to return error or exception conditions to the caller program. IBM provides it in QSYSINC/QLBLSRC, and it's called QUSEC.

You should take the sample program presented here only as a code snippet. In my shop, a similar program does things not shown here, for example:

  • It receives the SAVF name as a parameter and checks its existence. If exists, then clears it, otherwise creates it.
  • It receives the library name as a parameter, because each development team has its own library.
  • When the program leaves the main loop, it adds a new element in the array. This last element contains the name of the input database file. At the target box side, an application receives the SAVF, restores it in an auxiliary library and moves each restored object to its final location, freeing the system operator of a tedious and error-prone task. To perform this job the application uses the information provided by the input file.

More Information

It's worth noting that this program is intended for a shop that develops in-house applications. For independent software vendors, IBM provides a suite of tools specifically designed for packaging its software as a "product" such as:

  • Create Product Definition (QSZCRTPD) API
  • Create Product Load (QSZCRTPL) API
  • Package Product Option (QSZPKGPO) API

The IBM Information Center documents the QSRSAVO API. I haven't found any Cobol examples of using the QSRSAVO API. Instead, there are a lot of RPG examples on the web. You can read an RPG implementation written by Ron Turull. In this article, the author uses QSRSAVO API to implement an unattended backup strategy.

To learn about the new methodology approach, you can read "The New Methodology," by Martin Fowler.

You can download the source code for BUILDSAVF here:
http://www.pentontech.com/IBMContent/Documents/article/57613_797_BuildSavf.zip

ProVIP Sponsors

ProVIP Sponsors