Pages

Friday, May 13, 2011

I Use the Ib'm i

It seems that I've been forever reading blog, forums, articles, and tweets arguing one way or the other about what to call the latest incarnation of the pantheon that we all worship. It's gotten so bad that Cardinal Klement had to write an encyclical to set some ground rules as to the proper terminology. I've been watching this argument go on and on and on with no end in sight and I don't for a minute think that this blog post will put an end to the oodles of disk storage dedicated to its living spirit, but I do hope that this story might have some bearing on it.

For years I was in the AS/400 camp. Meaning I was pissed off at our lord Ib'm for continually re-naming its liturgy and the damage it was continually causing to the AS/400 brand. That is, until I had a conversation with someone outside of our rarefied community. When he asked me what platform I worked on I told him it was the "Ib'm i". When he inevitably asked "what's that?" I told him it used to be called the AS/400. To which he asked: "Wasn't that the dinosaur platform that was supposed to be dead or dying?" I realized at that moment that the AS/400 brand was dead and it was never coming back. The whole world believes that the AS/400 is an old out-dated platform that is slowly withering away, like the HP 3000, or the DEC VAX.

Yes, I know they're wrong, but in a way they're also right, because while the AS/400 platform is alive and well, it's the AS/400 brand that is a dead-end. It belongs to the world of 5250 terminals, Twin-axial cables, Token-Ring networks, SNA, and SNADS. A world dominated by libraries, physical & logical files, OPM, RPG-III, CLP, EPM-C, SEU, SDA, RLU, out-files, and Net.Data.

Today there's a bright and shiny new brand that our lord Ib'm calls the "Power Systems running i", but since that's too much of a mouthful I like to use the much simplified version "Ib'm i". It belongs to a new world of PC clients, CAT5 cables, Ethernet & WiFi networks, TCP/IP, FTP, Apache, and NetServer. A world dominated by directories, relational databases (tables, indexes, views, triggers, constraints, etc.), SQL, ILE RPG (free-format), ILE CL, ILE C, C++, Java, API's, QSH, PASE, Eclipse, Rational, WebServices, XML, and PHP.

We're on the cusp of a new dawn and if we play our cards right it will flower into a beautiful meadow. When the outside world is invited to sees how wonderful it really is they don't need to be reminded of the dusty over grown field behind them that was repeatedly sown with salt. I'm never going to say to anyone again that I work on an AS/400 and I encourage everyone who reads this to do the same. The "Power Systems running i" or "Ib'm i" is the platform I use.

Say it with me now: "I used to use the AS/400, yes that old dinosaur. It's true; it's gone, but it's been replaced by something better, something called the Ib'm i." Amen.

Saturday, February 19, 2011

CL Program to Apply Technology Refresh PTF

I had a deep sense of foreboding when I found that a HIPER PTF I downloaded came with technology refresh PTF 5770999-MF99002. These things are a pain in the butt to apply as it requires one to do the following steps: 
  1. Perform a full system save, like GO SAVE, option 21.
  2. Apply all microcode PTFs permanently.
  3. Load the TR PTF and set it to be applied temporarily.
  4. IPL the system.
  5. Apply the TR PTF permanently.
On our system there were two pre-requisite PTFs that were downloaded with MF99002; plus we already had a number of microcode PTFs that were set to be applied during the next IPL. I didn't want to permanently apply these new microcode PTFs, so I took the following steps:
  1. Unloaded the microcode PTFs set for delayed apply, except for those that were pre-requisites to MF99002.
  2. Performed a full system save.
  3. IPLed the system to apply the pre-requiste microcode PTFs.
  4. Permanently applied all microcode PTFs.
  5. Loaded MF99002 and set it to delayed apply.
  6. IPLed the system.
  7. Permanently applied MF99002.
  8. Loaded the rest of the microcode PTFs and set them to delayed apply.
  9. IPLed the system.
Our weekly "full system save and IPL" is full automated, so I needed some way to insert a CL program into this mix that would do the job. After finishing it I realized that others might be able to use it as well. It was designed to run in the QSTRUPPGM program, before it actually starts anything. It's assumed that the very first IPL, after the full system save, would first apply any PTFs that were pre-requisites of the TR PTF. All pending microcode PTFs to be applied, including the TR, would remain in a "Save file only" un-loaded state.

After that first IPL it would find that the TR PTF wasn't loaded yet, so it would apply all microcode PTFs permanently, load the TR PTF, set it to delayed apply, and IPL. When the system came up again it would find that the TR PTF was applied. It would then permanently apply it, load the rest of the microcode PTFs sitting in *SERVICE, set them to be applied delayed, and IPL again.

I've included the code below:

/******************************************************************************/
/* Program....: APYTRPTF                                                      */
/* Description: Apply technology refresh PTF.                                 */
/* Author.....: Joe Code                                                      */
/* Date.......: 02/18/2011                                                    */
/*                                                                            */
/* Create                                                                     */
/* ------                                                                     */
/* CRTCLMOD DBGVIEW(*ALL)                                                     */
/* CRTPGM USRPRF(*OWNER) AUT(*EXCLUDE)                                        */
/* CHGOBJOWN OBJTYPE(*PGM) NEWOWN(QSECOFR)                                    */
/* GRTOBJAUT OBJTYPE(*PGM) USER(QPGMR) AUT(*USE)                              */
/*                                                                            */
/* License                                                                    */
/* -------                                                                    */
/* This library is free software; you can redistribute it and/or modify it    */
/* under the terms of the GNU Lesser General Public License as published by   */
/* the Free Software Foundation; either version 2.1 of the License, or (at    */
/* your option) any later version. (Unlike the normal GNU GPL, the "lesser"   */
/* GPL allows libraries to be used in commercial/proprietary software.)       */
/*                                                                            */
/* This library is distributed in the hope that it will be useful, but        */
/* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANT-       */
/* ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General    */
/* Public License for more details.                                           */
/*                                                                            */
/* You should have received a copy of the GNU Lesser General Public License   */
/* along with this library; if not, write to the Free Software Foundation,    */
/* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA           */
/* (http://www.gnu.org/licenses/lgpl.html#SEC3)                               */
/******************************************************************************/

PGM

   COPYRIGHT TEXT('Copyright (c) 2011 Joe Code')

   DCL VAR(&COUNT)     TYPE(*DEC)  LEN(3 0)
   DCL VAR(&ERROR)     TYPE(*LGL)          VALUE('0')
   DCL VAR(&RCVVARLEN) TYPE(*INT)  LEN(4)  VALUE(131)

   DCL VAR(&PTFINFO)   TYPE(*CHAR) LEN(50)
   DCL VAR(&PTFID)     TYPE(*CHAR) LEN(7)  STG(*DEFINED) DEFVAR(&PTFINFO  1)
   DCL VAR(&PRODID)    TYPE(*CHAR) LEN(7)  STG(*DEFINED) DEFVAR(&PTFINFO  8)
   DCL VAR(&RLSLVL)    TYPE(*CHAR) LEN(6)  STG(*DEFINED) DEFVAR(&PTFINFO 15)
   DCL VAR(&CCSID)     TYPE(*INT)  LEN(4)  STG(*DEFINED) DEFVAR(&PTFINFO 21)
   DCL VAR(&CLSPTFF)   TYPE(*CHAR) LEN(1)  STG(*DEFINED) DEFVAR(&PTFINFO 25)
   DCL VAR(&RESERVED)  TYPE(*CHAR) LEN(25) STG(*DEFINED) DEFVAR(&PTFINFO 26)

   DCL VAR(&RCVVAR)    TYPE(*CHAR) LEN(131)
   DCL VAR(&BYTESRTN)  TYPE(*INT)  LEN(4)  STG(*DEFINED) DEFVAR(&RCVVAR   1)
   DCL VAR(&BYTESAVL)  TYPE(*INT)  LEN(4)  STG(*DEFINED) DEFVAR(&RCVVAR   5)
   DCL VAR(&LOADEDSTS) TYPE(*CHAR) LEN(1)  STG(*DEFINED) DEFVAR(&RCVVAR  41)
   DCL VAR(&IPLACTION) TYPE(*CHAR) LEN(1)  STG(*DEFINED) DEFVAR(&RCVVAR  66)

   MONMSG MSGID(CPF0000 CEE0000 MCH0000) EXEC(GOTO CMDLBL(ERROR))

   QSYS/CHKOBJ OBJ(QGPL/APYTRPTF) OBJTYPE(*DTAARA)
   MONMSG MSGID(CPF9801) EXEC(QSYS/CRTDTAARA DTAARA(QGPL/APYTRPTF) +
      TYPE(*DEC) LEN(3 0) VALUE(0) TEXT('Stop infinite loop if error +
      applying TR PTF.'))

   QSYS/RTVDTAARA DTAARA(QGPL/APYTRPTF) RTNVAR(&COUNT)
   CHGVAR VAR(&COUNT) VALUE(&COUNT + 1)
   QSYS/CHGDTAARA DTAARA(QGPL/APYTRPTF) VALUE(&COUNT)

   CHGVAR VAR(&PTFID)    VALUE('MF99002')
   CHGVAR VAR(&PRODID)   VALUE('5770999')
   CHGVAR VAR(&RLSLVL)   VALUE('V7R1M0')
   CHGVAR VAR(&CCSID)    VALUE(0)   /* Use job's CCSID. */
   CHGVAR VAR(&CLSPTFF)  VALUE('0') /* Close PTF files afterwards. */
   CHGVAR VAR(&RESERVED) VALUE(' ')

   QSYS/CALL PGM(QSYS/QPZRTVFX) PARM(&RCVVAR &RCVVARLEN &PTFINFO +
      'PTFR0100' X'00000000')

   SELECT

      WHEN COND(&BYTESRTN < &RCVVARLEN *OR &BYTESAVL < &RCVVARLEN) +
         THEN(QSYS/SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('No data +
         returned') TOPGMQ(*PRV (*PGMBDY)) MSGTYPE(*ESCAPE))

      WHEN COND(&LOADEDSTS = '0') THEN(DO) /* Not loaded? */
         IF COND(&COUNT = 1) THEN(DO)
            QSYS/APYPTF LICPGM(5770999) APY(*PERM)
            MONMSG MSGID(CPF3660) /* No PTFs identified. */
            QSYS/LODPTF LICPGM(5770999) SELECT(MF99002)
            QSYS/APYPTF LICPGM(5770999) SELECT(MF99002) DELAYED(*YES)
            QSYS/PWRDWNSYS OPTION(*IMMED) RESTART(*YES) IPLSRC(B)
         ENDDO
      ENDDO

      WHEN COND(&LOADEDSTS = '1') THEN(DO) /* Loaded, but not applied? */
         IF COND(&COUNT = 1) THEN(DO)
            QSYS/APYPTF LICPGM(5770999) APY(*PERM)
            MONMSG MSGID(CPF3660) /* No PTFs identified. */
            IF COND(&IPLACTION = '0') THEN(QSYS/APYPTF LICPGM(5770999) +
               SELECT(MF99002) DELAYED(*YES)) /* IPL action isn't set? +
               Then set it. */
            QSYS/PWRDWNSYS OPTION(*IMMED) RESTART(*YES) IPLSRC(B)
         ENDDO
      ENDDO

      WHEN COND(&LOADEDSTS = '2') THEN(DO) /* Temporarily applied? */
         IF COND(&COUNT = 2) THEN(DO)
            QSYS/APYPTF LICPGM(5770999) SELECT(MF99002) APY(*PERM)
            QSYS/LODPTF LICPGM(5770999)
            MONMSG MSGID(CPF35A8) /* No PTFs to be loaded. */
            QSYS/APYPTF LICPGM(*ALL) DELAYED(*YES)
            MONMSG MSGID(CPF3660) /* No PTFs identified. */
            QSYS/PWRDWNSYS OPTION(*IMMED) RESTART(*YES) IPLSRC(B)
         ENDDO
      ENDDO

   ENDSELECT

   RETURN

/******************************************************************************/
       /*                                                                     */
ERROR: /* Global error handling section.                                      */
       /*                                                                     */
/******************************************************************************/

   IF COND(&ERROR) THEN(RETURN)  /* Prevents an infinite loop if an error     */
   CHGVAR VAR(&ERROR) VALUE('1') /* occurs within the error handling section. */

   QSYS/SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Unexpected error +
      occurred. See previous messages') TOPGMQ(*PRV (*PGMBDY)) MSGTYPE(*ESCAPE)

ENDPGM

On our small system this program added an extra two hours to the normal weekend backup/IPL. The only problem I ran into was that the microcode PTFs that I removed weren't loaded again. Apparently when you permanently remove a microcode PTF, it's also removed from the list of "*ALL PTFs in *SERVICE", meaning they can't be loaded when you specify LODPTF DEV(*SERVICE) SELECT(*ALL). You have to specifically name them in the SELECT parameter. Next week when I do this again I am going to load all of the microcode PTFs and leave the delayed apply flags shut off. (Except of course for the TR PTF's pre-requisites.)

Looking at the program again this morning I realized that if there was a subtle problem with applying the TR PTF then it might cause an infinite loop of IPLing, which would be very bad. I've since changed the program to include a safety valve in the form of a data area used to count the number of IPLs. If the count doesn't match up with what is supposed to happen then it doesn't do anymore IPLs. This amended version of the program compiles, but I haven't tested it yet. If you want to wait, it will be tested again next weekend when I apply the TR PTF to another system in our network. I will update this post with the results.

Update (2011-02-28): This version of the program did it's job and applied the TR PTF without error.

Update (2011-06-07): IBM has since issued PTFs to make this task easier, so it would seem that the program above is obsolete.

Monday, January 03, 2011

Parallel Lines

Had kind of a wild ride with this one liturgical conundrum, but I think it's resolved now. It was deep, but the ultimate solution was very simple.

The main program is written in ILE RPG and it does all of it's I/O using SQL. The main result set consists of multiple sub-selects that are UNIONed together into one giant pile. In the WHERE and HAVING clauses of most of these sub-selects it utilizes a user defined function (UDF) that does some data massaging.

This all ran perfectly fine on v5.4 of i5/OS, but after the upgrade to v7.1 of IBM i the job started behaving strangely. Sometimes it would work fine. Sometimes it would run inside the first FETCH statement all day long and take up huge amounts of CPU. Other times the UDF would function check because of invalid data in the strangest places, like on the RETURN statements.

To try and stem the function checking I added MONITOR/ENDMON blocks to all of the RETURN statements in the UDF. When an error occurred they would return *LOVAL instead. Then it started function checking on the statements that were calling the functions with the aforementioned function checking RETURN statements. It was very weird.

Over a two month period I was sending all kinds of traces, SERVICEDOCS, and job logs to Ib'm support angels. The last thing we did was set up a job watcher in iDoctor and the output found that when the FETCH was looping and it was doing so in one of the functions in the UDF. That's when they asked me if it the service program was specified to support multi-threading.

Doh!

As it turns out the SQL to create the functional stubs that called the RPG service program functions defaulted to PARALLEL while the program did not. So remember, if you're writing (or have written) an SQL UDF in a language other than SQL, don't forget that you might have to make your program or service program multi-thread capable. In RPG it means adding the keyword THREAD to the control specifications (aka H-specs) with either the *CONCURRENT or *SERIALIZE attribute. (THREAD(*CONCURRENT) did the trick for me.) Be sure also to thoroughly read the sections in the RPG and SQL manuals on multi-threaded processing.

Friday, November 26, 2010

Influencing the Heavens

While it's a lot of fun hanging out with fellow priests discussing liturgy, I think the most fun I've ever had was walking the hallways of mecca itself and getting to talk to the angels and minions of our lord Ib'm. (Especially building 20, which is a football field size room filled with our lord's most holy systems.) It's also very satisfying to know that you've had an influence in such an august environment. My instance of influence was tiny, but no less satisfying.

My support angel had arranged it all. I gave him a list of the subjects and problem areas I wanted to discuss and he set up all of the meetings. What I remember most clearly is that every angel or minion that I met said something along the lines of "this is great, we never get to speak to our ministerial brethren." After awhile I started to conclude that our lord Ib'm made it an unspoken policy to keep them all in darkness writing code away from the light of earthly interaction.

I talked to a lot of people that day and it was a whole lot of years ago, so I don't remember everything that was discussed or every person I met. I do remember speaking to angels and minions involved with PTFs, command definitions, message handling, journaling, work management, CL programming, and request message processing. There are several salient areas that stood out.

The Command Definition angel actually remembered my name because he'd worked on a lot of the PMR's I'd opened over the years. When I thought about it later I figured he was probably also the one that I had argued with on the phone for over an hour about a fix to command prompting that was made on the AS/400, but wasn't done quite as well on the System/38. (If you're reading this now, I'm sorry about that.)

At one point I walked past some cubicles talking with another minion when the hairiest angel I'd ever seen poked his head above the wall and exclaimed "you're a priest? I've never seen a priest before." (It was the theme du jour.) I felt a small pang of jealously because I of course had to cut my hair to get a job. He seemed so happy to see me I had to go over and shake his hand. He said he wrote microcode and judging from his appearance and general demeanor I have to admit that I wasn't the least bit surprised. I'll bet his code was tighter than most.

We'd been having a problem with Mimixing file records to another system. We were using commitment control and therefore everything was journaled, but we were only Mimixing a small subset of files to the other system. Consequently when Mimix was plowing through the journal receivers looking for something to replicate, it got down deep into the microcode, took over the CPU, and didn't come up for air very often. (The minions of our lord Ib'm closed my APAR on that issue as "working as designed".)

At that time a file could only be attached to one journal at a time and one of the requests I'd made of the journaling angel was for the ability to attach a file to more than one journal. With this feature we could journal those files being Mimixed to a 2nd journal and Mimix could then plow through that secondary journal and not take over the system. He said he thought it was a good idea, but he wouldn't say when or if it would ever be available.

In a subsequent release that feature was made available. However with that release the AS/400 also supported two-phase commit and this new feature was a side-effect of that support, so I can't say that I had any influence on the decision. The journaling angel probably knew this support was coming, but wasn't able to reveal it to me at that time.

I also remember speaking to an angel who was responsible for CL and Request Processing. I had designed a lot of applications that processed sub-file options using commands, so every program was a request processor similar QCL or QCMD. The problem I was having was that some commands had password parameters and I wasn't able to hide the parameter's contents using the QCMDEXC API in my request processors.

I asked him if a CL API could be created where I'd give it the message ID of a logged request message and it would handle the execution, prompting, and redaction of sensitive data. He too said he thought it was a good idea, but of course wouldn't commit to it. In a future release the QCAPCMD API appeared and it was exactly what I needed to resolve my issue. Of course that API does a great many different things with various CL environments so I can't be sure that my request had any influence.

The only request I made during that visit where I'm absolutely sure I had a direct influence was with the crew of Work Management minions that I met with. Unlike everyone else in the building they were all wearing ties. I couldn't resist asking them if their manager had made them put them on for my visit and they sheepishly admitted that he had. Meeting with them was fun and afterwards they took me on a tour of the fabled building 20.

One of the Work Management problems my shop was having was with duplicate job names. An operator would enter WRKJOB MYUSERID/MYJOBNAME and the system would send 25 or 50 messages listing all of the jobs whose name and user ID were MYUSERID/MYJOBNAME. Then they'd have to search through the job log and write down the job number (this was in the age of dumb tubes, so copy/paste wasn't possible) and enter it on the command to view the job. Since the messages didn't say anything about when those jobs had been started the operators would invariably pick the wrong job number, and so they'd have go through the list again and pick another one, and on, and on, ad infinitum. It was a pain in the butt.

The three of them didn't think there were any good solutions for this issue given how the commands were already set up. I asked if it was possible that when there were duplicate jobs the command could display a screen where the user could select the job they wanted from a list. One of them exclaimed "Oooh! That's a good idea" and immediately wrote it down. In the very next release the DSPJOB and WRKJOB commands both had a new parameter named DUPJOBOPT (Duplicate Job Option) whose default value was *SELECT. It's the only change to the system where I'm absolutely sure I had an influence.

Sunday, November 21, 2010

ILE RPG %ALLOC() Built-in Function Can Fail with CEE0808

I had an interesting problem with the ILE RPG %ALLOC() built-in function recently. In one particular spot in a single program, whenever I tried to allocate some storage it failed with CEE0808 (requested storage size is not valid). The help text on the message said that the storage to be allocated was a negative number, but since it was a four byte unsigned integer that was impossible. Debugging it also showed that it was only trying to allocate a little over 3,100 bytes, so there was no issue with a signed number mapping over a huge unsigned number and mistaking it for a negative.

Searching on this message in our lord Ib'm's support site found v7.1 APAR SE44538, which fixed several problems with the RPG compiler. One of them resolved an anomaly where %ALLOC() failed with CEE0808 in programs that were optimized with *FULL, which my program was. The fixing PTF is 5770WDS-SI41005, which will require any problem programs to be re-compiled. There is a run-time PTF too that is a pre-requisite: 5770SS1-SI41000.

It's not on any cum or group packs yet and it fixes several problem, not just mine. The text of the APAR makes it look like it's a hot fix (if not HIPER), so whether you use this built-in function or not you might want to download it.

Sunday, October 31, 2010

Heads up for Those Installing v7.1

This is a heads up to any priest or lay operator planning to install v7.1 with cumulative PTF package C0229710 (or above). There is a chance that the initial IPL to apply 5770999-MF99001 (required technology refresh) could fail with SRC B600-0102. You would then be forced to drive to work and slip install LIC from your physical media.

Our lord Ib'm's support angels have instructed that one must first load PTF 5770SS1-SI40878 from the HIPER group CD image and apply it immediately. Then load PTF 5770999-MF50003 from the cumulative PTF package (currently superseded by MF50836 in the HIPER group PTF SF99709), set it to apply delayed, and IPL the system.

When the system comes up you can start installing the PTF package again. Be forewarned that your attempt to load it will result in a failure message, but this is probably nothing to be alarmed about. View previous messages and most likely you'll find that it'll be because the system wants you to IPL now to install the MF99001 PTF before anything else. Once this technology refresh PTF along with its pre and co-requisites have been applied you can continue loading and applying the rest of the cumulative PTF package. (Be sure the "initialize system is complete" message has been sent to QSYSOPR before IPLing the 2nd time.)

I was very surprised that none of this was in the instructions for the cumulative PTF package. I think it would behoove our lord Ib'm if at the very least its minions added this information to the cumulative PTF package PSP document as a heads up. For more information on the technical refresh PTF see this document: FAQ for Technical Refresh for R710.

Update (Nov 11, 2010): The minions of our lord Ib'm have "re-saved" (or re-spun) the I_BASE_01 LIC installation disk, so that it now contains the 5770999-MF99001 technology refresh, among other things. They're designating it as RS-710-B. The above problems I experienced installing v7.1 on two separate systems were presumably because I was using the re-save designated as RS-710-A, but that hasn't been proven. In any case, anyone upgrading to v7.1 is advised to install from the new re-save disk as it will probably save some headaches. For more information see this web page: IBM i Resaves.

Tuesday, October 12, 2010

Bug in Websphere Application Server v7.0 Migration

This is a heads-up to all worshipers of our Lord Ib'm who also use the Java liturgy known as "Websphere Application Server" (WAS) -and- who are intending to migrate their applications to WAS v7.0.

Our parish was using WAS v6.0 and we intended to upgrade the most holy O/S to v7.1. The "Memo to Users" encyclical warned us that WAS v6.0 wasn't supported under O/S v7.1. It does support WAS v6.1 and v7.0, so we decided to load the latest WAS version since it had been out for quite a while now.

The migration process steps themselves are actually very easy. All you have to do is execute a pre-migration script for all of the instances (or profiles) with applications you'll be moving over. Then create matching profile names (with different blocks of port numbers) in the new version of WAS. Then you do a post-migration and -viola- it's done and it works. (Amazing!)

Except in our case there was one problem with one of the application not "deploying" to the new version of WAS. I opened a PMR with the support minions of our Lord Ib'm and they requested all manner of logs. Then they had me zip up the pre-migration directory and send that in too.

It turned that the offending application had single-quote(') characters in its description and the pre-migration script had unwittingly embedded a syntax error in the Jython code it had written. When the post-migration ran, it encountered the syntax problem and stopped the deployment for that application.

The pre-migration should have "escaped" those single-quote(') characters in the description. The Ib'm minions manually corrected the Jython code and sent it back to me with instructions on how to run it. Thank the Lord Ib'm that my prayers to the support minions were heard because the corrected Jython code ran fine and deployed the problematic application.

This problem with the Jython code generation is corrected in v7.0.0.13 of WAS which is scheduled to be released for general availability on Oct 25th, 2010. If you have single-quote(') character(s) in the description(s) of your application(s) you should either remove them, or wait until you've had a chance to install that update to WAS, before attempting the migration.

Tuesday, October 05, 2010

Special *NULL CL Value Undocumented Since v6.1

We've all heard about the *NULL special value in ILE RPG. It's a nifty little item associated with pointer fields. You can use it to assign *NULL to a pointer field or in a conditional statement to test if a pointer is null. Did you know that CL has had a *NULL special value since v6.1? I didn't know about it because it doesn't appear anywhere in the v6.1 or v7.1 Information Center. Nor does it appear in the PDF formatted version of the CL Programming Concepts Guide. I only learned about it recently and am a little embarrassed to admit that I had included a "*NULL Special Value" as one of My Top 10 Requirements for CL Enhancements.

I currently have a PMR open with the support minions of our lord Ib'm for v7.1 concerning un-initialized pointer variables containing errant data at start-up time. (The problem doesn't occur on v5.4.) This has lead them to open an APAR SE45175 which they said would be closed as PE (Programming Error). This is only related to the subject at hand because at one point I let the support minion know that I wouldn't have even known about this problem if CL had some kind of *NULL special value like RPG currently has. He passed this comment to the saints of development and they responded that it actually did and it's had it since v6.1. They even included a little program I could compile to prove it.

After proving it I immediately re-scoured the "What's New in CL" sections of the Information Center for v6.1 and v7.1, but couldn't find anything. Then I searched the CL sections for both releases, but came up with nada. The support minion also searched through the Info Center and like me came up empty handed. He's since notified the powers that be to get that fixed but we might not see it documented until the next release.

I also asked around and fellow high priest Father Jerome Hughes was kind enough to pass along this link to a Power-Point presentation given by Ib'm saint Guy Vig at an Omni User Group ecumenical dinner. Discussion of the *NULL value can be found on slides 93 & 94.

In any case here's the small program that the saints of development passed onto me:
PGM
              DCL        VAR(&PTR1) TYPE(*PTR) ADDRESS(*NULL)
              DCL        VAR(&CHAR1) TYPE(*CHAR) LEN(1)
              CHGVAR     VAR(&PTR1) VALUE(%ADDR(&CHAR1))
              CHGVAR     VAR(&PTR1) VALUE(*NULL)
              IF (&PTR1 *EQ *NULL) THEN(DO)
              SNDPGMMSG  MSG('The pointer is null')
              ENDDO
ENDPGM
As you can see *NULL can be used to initialize declarations (DCL) assignments (CHGVAR) and in conditional statements (IF).

UPDATE (10/06/10): Here's something pretty interesting. On a lark I compiled the program to TGTRLS(V5R4M0). I had to remove the ADDRESS(*NULL) parameter from the DCL statement, but other than that it compiled. I installed the program object to a v5.4 system and it ran exactly like it did on the v7.1 system. However when I FTPed the source to that system and compiled it the compile failed saying the "*NULL" was incompatible with the variable.

Friday, October 01, 2010

The Cult of Ib'm and the Most Holy iSeries

My sermon today concerns the deeper meaning of the cult of Ib'm and the future of its most holy computer, the iSeries.

By using the word "cult" I of course don't mean some fringe religion with only a few adherent, although we are slowly becoming that (but I digress). I mean it in the way of the ancients when they worshiped temporal objects that helped them survive and/or gave their lives meaning. For example, everyone knows that among the ancient Egyptians there was a cult of cat worship. It got its start, not top-down with prophets, visions, and visitations from the cat god, but bottom-up because it was the cats that kept the rodents in their grain stores under control.

In a recent Maxed Out blog post Chris Maxcer wrote, among other interesting things, that my blog is "not trying to disparage any religion". Of course he's right. There is no intended disparagement of any religions. If there are any computer geeks out there who are also adherents to the Abrahamic religions, please do not be offended by my conflation of the language of said religions with this little cult of ours. Outside of work many of us have pledged our souls to a deity (or pantheon of deities) of our choice, but at work our hearts belong to the lord Ib'm and its most holy computer, the iSeries; for not only does it help us survive but it gives our lives meaning.

Most of the readers of this blog are well versed in the worship our lord Ib'm and its most holy computer, but computer geeks everywhere generally are priests in the temples of other idols at the same time. Unlike its behavior in the distant past, Ib'm will no longer get wrathful and send down plagues upon your systems and withhold service when one worships idols. In fact, the minions of lord Ib'm should probably, if they're on the ball, redouble their efforts to get people away from those false religions.

It's nice when all of the worlds religions can play nice together and be worshiped at once, but life isn't always like that. In an earlier time and much larger parish than my current one, we had several of the most holy AS/400s. We even had a System/36 -and- there was some worship of the Sun god, the ancient pagan rites of the Unix daemons, and the goddess Sybase. I personally had nothing against the worship of these pagan deities in my parish. After all, the nature worship that is Unix is almost as old as the F.S. Project itself and both grew out of that ancient tradition of geekdom's distance past where the command line interface (CLI) held supreme.

Eventually some new PHB's came on board and without warning there was an inundation of adherents to the twin gods Hewlett and Packard, and their object of worship, the HPUX O/S. Along with HPUX came the twin Mephistopheles of Unix faith everywhere; I am of course speaking of the foul beasts Oracle and NT. The houses of worship for these deities did not hold the CLI in high regard. Theirs was a world of graphical user interfaces (GUIs) that mesmerized and held the bean counters in a trance such that they couldn't resist these temptations.

The most high and benevolent Ib'm and his many saints and angels were powerless to stem the tide of GUI worship amongst my flock. The temples to both the Sun god and the Sybase goddess were destroyed. The small System/36 cult was suppressed and the iSeries became a minority cult among this new tide. Attendance at my parish shrank, until finally there was no parish anymore. I too was tempted to abandon my faith, but it would have meant becoming a novice again after so many years as a high priest, so I chose to remain an iSeries adherent, but that also meant moving on.

As our lord Ib'm has taught us time and again, change happens, and we've all had to get used to that. I can't say that it's been easy watching this transition take place in our community. I attend the ecumenical conventions and I'm struck by how few young people are there. It appears that we are all aging out and that gives me pause. In addition the holy of hollies itself is slowly being inundated with more and more aspects of the pagan Unix cults. So much so that one day we may find that our beloved iSeries has become a pSeries.

Our lord Ib'm makes the light of the truth of the most holy iSeries, but we are its keepers. We have it in our hands to rise up and perpetuate this calling that gives our lives meaning. We cannot wait for Ib'm to come down from on high and preach to the masses the benefits of our faith. That's not going to happen, so we have to do it ourselves. In the same Maxed Out post Chris also wrote that Bishops Paris and Gantner were out teaching RPG to some VB acolytes and they most certainly have garnered more than a few converts. (You can read their blog post on the subject here: Good News in i Land.) Our counterparts in Japan have taken up the reins of proselytizing the iSeries to the unwashed masses and doing very well from what I've read. If we all do the same there is so much we could potentially accomplish not only for our benefit, but for future generations.

Amen.

Friday, September 24, 2010

ILE CL Does Something Weird

A little background:

In v5.4 CL doesn't have a special value of *NULL or any way of representing a null value as a literal. (This was for many years one of my bones to pick with our gracious lord Ib'm, but I digress.) To get around this I created a *PTR field named &NULLPTR and I never changed it so that it always contained a null pointer. This way I could compare pointer fields to &NULLPTR to see if they were null.

A CL module of mine contains a &NULLPTR *PTR field. It was compiled last year under v5.4 and hard-linked into a couple of programs. The module has worked fine in both v5.4 and v7.1.

Recently I had to change a couple of modules in one program, so I recompile them. This program also used the CL module, but that module didn't change. When I created the program I simply linked to the existing module object that was still stored in the source library that it was compiled into last year.

The problem:

For some reason when this same old hard-linked CL module is called within this re-created program, the &NULLPTR field isn't null anymore. It now contains a pointer, or at least it contains some kind of errant data. This causes the program to bomb out because when it tests for a null pointer the outcome of course turns out false when it should be true.

If I create the program to run under v5.4 it bombs on v7.1 but not on v5.4. If I re-compile the CL module (to run under v5.4 or v7.1) then the problem goes away almost completely (that is, until you save and restore it to another system, then it start bombing again).

The issue I have is that there are other modules compiled under v5.4 with &NULLPTR *PTR fields that might be re-linked into new programs in the future. I can't be sure the same thing isn't going to happen to them.

I have sent prayers and made sacrifices to the patron saints of support that our lord Ib'm might provide insight as to what is going on. If you're having the same issue in your parish then please say a prayer for me and post a comment and let me know what you think.

Update (10/25/2010): Our lord I'bm issued PTFs for this problem: v7.1: SI41596, v6.1: SI41595, and v5.4: SI41594.