I received a question from a reader asking if there was a way to copy data from a central IBM i to a number of remote IBM i using SNADS, and then have the central server call a program on the remote ones. Fortunately this is easy to do just using a few simple commands and a bit of common sense.
Distributed Data Management (DDM) files have been available on IBM computers for as many years as I can remember. DDM files are a quick and easy way to copy data to and from one IBM computer to another. Most of my experience with them has between AS400 and later IBM i, but I have also worked receiving data from an IBM mainframe via DDM files.
There are restrictions to what tools and utilities you can use with DDM files:
(only IBM utilities listed, I will not vouch for non-IBM products)
|Works with DDM files||Does not with DDM files|
|RPG/RPGLE using native I/O
Most CL commands
SQL embedded in RPG/RPGLE
While all DDM files are created using the Create DDM File command, CRTDDMF, there is a difference in the way they work depending upon the desired communication type:
CRTDDMF FILE(QTEMP/DDMFILE1) RMTFILE(RMTLIB/TFRFILE) + RMTLOCNAME(OTHERSVR) CRTDDMF FILE(QTEMP/DDMFILE2) RMTFILE(RMTLIB/TFRFILE) + RMTLOCNAME('10.000.000.000' *IP)
The command's parameters are straight forward.
FILE: This is the file name and library where the DDM file will be placed on this IBM i.
RMTFILE: Name of the file and the library where the file occurs on the remote system, in our case another IBM i.
RMTLOCNAME: The first parameter is the remote system's name. In the first example I have used the network id, OTHERSVR, and in the second its IP address, it makes no difference which I use.
The second parameter is important. There are two values to choose from depending upon what I want to do:
- *SNA this is the command's default, which is why is it not shown in the first example. The job at the remote end will use the user profile QUSER. I will have to give QUSER authority to all files accessed via DDM, which means that any user using DDM files could access any of the files that QUSER has been authorized to.
- *IP if used then the user profile used on this server will need to exist on the remote server. Well, not actually true, there is another way to "map" a user profile on the local server to one on the remote server, but I will have to cover that in another post. This is the more secure way of controlling access to file on the remote server as you can authorize only certain profiles to the various files on the remote server.
I can build the DDM file to any Physical or a Logical file on the remote system.
In RPG I use the DDM files just like I would a local one:
dcl-f DDMFILE1 keyed extfile('QTEMP/DDMFILE') ; dcl-f DDMFILE2 keyed usage(*input:*update) rename(TFRFILER:TFRFILER2) ; read TFRFILER ; update TFRFILER2 %fields(TFR003) ;
Now comes one of those philosophical questions I argue all the time with other IBM i developers. Do I...
- Create the DDM file in a specific library so it can be used by any program at any time
- Create the DDM file when it is needed in QTEMP (where else would I put work files?)
In my opinion there is not one correct answer. It depends on how the DDM file is going to be used. If it is going to be used by a lot of programs and users, then I would put it in a library that these users can access. If it is only going to be used once a day, I would build it in QTEMP. I will leave it to you to come to a decision for your own DDM files.
Now we have to deal with an issue that plagues all DDM files, what happens when...
- The remote system is down, it could be for something as simple as for IPL or backup.
- If communications fails between the local and the remote. This is unlikely to happen if they are IBM i partitions on the same server. But if they on different servers in different locations this will happen.
If the remote system is down the RPG program will start, open the DDM file, and when it performs the first read to the DDM file it will hang almost indefinitely waiting for the data from the remote. I have seen programs that have been in this state for hours, even when communications had been reestablished.
What I need is a quick way to test that the "other end" of the DDM file is OK before I use it:
01 OPNDBF FILE(QTEMP/DDMFILE) OPTION(*INP) 02 MONMSG MSGID(CPF4125) EXEC(DO) 03 SNDMSG MSG('Cannot connect to remote system') TOUSR(&USER) 04 RETURN 05 ENDDO 06 CLOF OPNID(DDMFILE) 07 CALL PGM(PGM1)
If can open the DDM file with the Open Database File command, OPNDBF, line 1, then the connection to the remote system is good, and the logic jumps to line 6 to close the file.
But if I cannot open the file as there is an issue with the DDM file, I issue a message to the user and quit the program. Feel free to put looping logic here to check to see if the link is reestablished, etc.
There are a couple of other useful DDM file commands:
CHGDDMF: Change an existing DDM file to "point" to another file or IBM i. I do use this command a lot, especially when I need to copy the latest data from the Production server to the Development server. For example:
01 CRTDDMF FILE(QTEMP/DDMFILE) RMTFILE(PRODLIB/ORDHDR) + RMTLOCNAME(PRODUCTN *IP) 02 CPYF FROMFILE(QTEMP/DDMFILE) TOFILE(MYLIB/ORDHDR) + MBROPT(*REPLACE) FROMRCD(1) 03 CHGDDMF FILE(QTEMP/DDMFILE) RMTFILE(PRODLIB/ORDDTL) 04 CPYF FROMFILE(QTEMP/DDMFILE) TOFILE(MYLIB/ORDDTL) + MBROPT(*REPLACE) FROMRCD(1)
I have not given the RMTLOCNAME on line 3. As the two files are at the same location I can use the command's default, which is *SAME.
The other command I want to bring to your attention is the Display DDM file command, DSPDDMF. As you would expect this displays all the information about the DDM file. When you find a DDM file you did not know of, this is the way to find out what server and which file it links to.
DSPDDMF FILE(QTEMP/DDMFILE) DSPDDMF FILE(MYLIB/*ALL) OUTPUT(*PRINT)
After all that information about how to create, change, and display DDM files, how can I call a program on another IBM i using DDM files?
The command Submit Remote Command, SBMRMTCMD, allows me to submit any IBM i command to a remote system using a pre-existing DDM file. For example:
SBMRMTCMD CMD('call mylib/pgm1') DDMFILE(QTEMP/DDMFILE)
This is where the type of connection comes into play. If you have a DDM file created using *SNA then the program will run under the user profile QUSER, with all of its authorities, etc., which I would hope is not much. If I had used *IP then the program will run under the same user profile on the remote system as I am using on the local one. This allows me to authorize only certain users to certain files on the remote system, and prevent everyone from accessing information that is not relevant to them.
I do not recommend you call a program on the remote system that does "stuff". The job on the local system will wait for the job on the remote system to finish. When I use the SBMRMTCMD I use it to SBMJOB a command to the remote system. This way I can set all the things like library list, output queue, etc. in the submit job command, and the job on the local system will continue without waiting for the processing on the remote system to finish.
Here is a simple example of what I was describing:
01 CRTDDMF FILE(QTEMP/DDMFILE) RMTFILE(PRODLIB/TFRFILE) + RMTLOCNAME(OTHERSVR *IP) 02 CPYF FROMFILE(ORDTRS) TOFILE(QTEMP/DDMFILE) + MBROPT(*REPLACE) FROMRCD(1) + INCREL((*IF SITCOD *EQ '015') (*AND PFLAG *EQ 'G')) 03 CHGVAR VAR(&SBMJOB) + VALUE('SBMJOB CMD(CALL PGM(PRODLIB/TFRPGM1)) + JOB(TFRUPDATE) + JOBD(PRODLIB/TFRJOBD) + JOBQ(QBATCH1)') 04 SBMRMTCMD CMD(&SBMJOB) DDMFILE(QTEMP/DDMFILE)
Another place to store data you might want to get to and from a remote system is in a data area. It is also possible to make a DDM data area and then use it on the local system.
01 CRTDTAARA DTAARA(QTEMP/DDMDTAARA) TYPE(*DDM) + RMTDTAARA(PRODLIB/TFRDA) RMTLOCNAME(OTHERSVR) 02 RTVDTAARA DTAARA(QTEMP/DDMDTAARA *ALL) RTNVAR(&DATAAREA)
You can learn more about this from the IBM website:
This article was written for IBM i 7.2, and should work for earlier releases too.