Service Program Parameters Written Directly to PF

65 pts.
Tags:
PF/LF
RPG
Service program
I'm taking an old RPG program that does all the writing of records to a PF & converting it to a service program. This should reduce the processing of these records considerably (no more opening & closing the file for each record). I've created the service program & tested it, the only problem seems to be with the parameters passed into it that are never modified by the service program... when writing to the PF they are written as the default value (blank or zero depending on the type) instead of what is passed in. What is causing this & is there any easy way to fix it without changing the parameter name & moving each field into its final destination?

Answer Wiki

Thanks. We'll let you know when a new response is added.

The data that is written to the file is based on the fields implicitly referenced by the RPG WRITE operation, so somewhere along the way you need to set these fields to the values passed by your service program caller. Without seeing your programs it’s difficult to say exactly what needs to be changed and whether the change is trivial or significant. Can you provide the relevant parts of your service program code?

Bruce Vining

Hi Adam,

some elements you may have forgotten are:
If i assume that your work with *BEFORE Trigger

ADDPFTRG FILE(&lib/&file) TRGTIME(*BEFORE)

and that you “Trigg” *insert, *Update and *Delete

TRGEVENT(*INSERT)
TRGEVENT(*UPDATE
TRGEVENT(*DELETE)

In PARAMETER 1 you find pointers to old and new record (that means before update and after).
For *ADD, NEW pointer must be used.
For *DELETE, OLD pointer must be used.
For *UPDATE, this is linked to what you want to do.

According to your explanations, your problem could be that you use OLD pointer for new record, that means emply fields.

You should also use prefix and DS with external descriptions for your old and new records.

Also do not forget general consideration for service programs
- Mind overriding file before opening them (library list concern)
- Every update requires new loggon to be active.

Please find hereafter one single Trigger program skeleton that worked (This is no more used but it should be ok. This was created with V4R5 os level) .

Hope it may help you.

TSCHMITZ.

H ACTGRP(*CALLER) DFTACTGRP(*NO)
D*****************************************************************
***------------------------------------------------------------*
*** Trigger Program name = (replace) #pgm
*** Apply to File (replace) #file
***
*** Purpose : Update File (replace) #updatfile (!!replace 10 bytes)
*** with record (replace) #updrecord (!!replace 10 bytes)
***------------------------------------------------------------*
*** ASSUME : Old fields values in #file : O_&fieldname
*** New fields values in #file : N_&fieldname
***------------------------------------------------------------*
** DATE CREATED : __/__/____ By __________
** DATE MODIFIED : __/__/____ By __________
*****************************************************************************
** File(s) to be updated
*****************************************************************************
F#updatfileUF A E K DISK

D PARM1 DS
* Physical file name
D FNAME 10
* Physical file library
D LNAME 10
* Member name
D MNAME 10
* Trigger event 1=Ins, 2=Del, 3=Upd
D TEVEN 1
* Trigger time 1=After, 2=Before
D TTIME 1
* Commit lock level
D CMTLCK n
* Reserved
D 3
* CCSID
D CCSID 10i 0
* Reserved
D 8
* Offset to the original record
D OLDOFF 10i 0
* length of the original record
D OLDLEN 10i 0
* Offset to the original record null byte map
D ONOFF 10i 0
* length of the null byte map
D ONLEN 10i 0
* Offset to the new record
D NEWOFF 10i 0
* length of the new record
D NEWLEN 10i 0
* Offset to the new record null byte map
D NNOFF 10i 0
* length of the null byte map
D NNLEN 10i 0

* Trigger Buffer Length
D parm2 s 10i 0

* Record to be inserted or new values
D NEW E DS EXTNAME(#file)
D PREFIX(N_)
D based(pn)
* Record to be deleted or old values
D OLD E DS EXTNAME(#file)
D PREFIX(O_)
D based(po)

***------------------------------------------------------------*
*** Trigger Events Constants *
***------------------------------------------------------------*
D insert_record C const('1')
D delete_record C const('2')
D update_record C const('3')

***------------------------------------------------------------*
*** Entry parms *
***------------------------------------------------------------*
C *ENTRY PLIST
C PARM PARM1
C PARM PARM2
***------------------------------------------------------------*
*** Check parms transmitted *
***------------------------------------------------------------*
c if %parms = 0
c eval *inlr = *on
c return
c endif

***------------------------------------------------------------*
*** &updatfile opened ? *
***------------------------------------------------------------*
c if not %open(&updatfile)
c open &updatfile
c endif
***------------------------------------------------------------*
*** Execute event *
***------------------------------------------------------------*

c select
*** Add
c when teven = insert_record
c eval pn = %addr(parm1) + newoff
*** Delete
c when teven = delete_record
c eval po = %addr(parm1) + oldoff
c** Update
c when teven = update_record
c eval pn = %addr(parm1) + newoff
c eval po = %addr(parm1) + oldoff

c endsl
c return

Discuss This Question: 15  Replies

 
There was an error processing your information. Please try again later.
Thanks. We'll let you know when a new response is added.
Send me notifications when members answer or reply to this question.

REGISTER or login:

Forgot Password?
By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy
  • bvining
    There's a trigger program involved here? There's nothing in the original question that gave me that impression.
    6,620 pointsBadges:
    report
  • TSCHMITZ
    Oops, i'm afraid you are right Bruce. My mistake. I was to quick. Sorry. T.
    470 pointsBadges:
    report
  • Adamdowen
    Yeah, there isn't a trigger program involved. I'm including the parameter initialization info below of the service program. Note that the fields of the file it writes to are prefixed with "LB". Any fields in the below that are not explicitly modified within the service program are left either blank or zero.
    D   PLWHSE                       2A  
    D   PLWHNO                       5S 0
    D   PLCUST                       5S 0
    D   PLPROD                      10A  
    D   PLPRD                       30A  
    D   LBCTG                       10A  
    D   PLLOT                        7S 0
    D   PLPRCD                      20A  
    D   LBNWGT                       9P 2
    D   LBGWGT                       9P 2
    D   LBCASE                      11P 2
    D   LBRATE                       7P 4
    D   LBRAMT                      11P 2
    D   TAXPCT                       4S 4
    D   INVTYP                       1A  
    D   INVNO                        7S 0
    D   INVCC                        2S 0
    D   INVYY                        2S 0
    D   INVMM                        2S 0
    D   LBGWGT                       9P 2
    D   LBCASE                      11P 2
    D   LBRATE                       7P 4
    D   LBRAMT                      11P 2
    D   TAXPCT                       4S 4
    D   INVTYP                       1A  
    D   INVNO                        7S 0
    D   INVCC                        2S 0
    D   INVYY                        2S 0
    D   INVMM                        2S 0
    D   INVDD                        2S 0
    D   LBSCHG                       3A  
    D   TRID                         3A  
    D   TRREFE                       8A  
    D   LBPGMID                     10A  
    
    The old program (non service program) didn't have to have each of these fields explicity modified. Why does a service program require it? Thanks!
    65 pointsBadges:
    report
  • bvining
    It looks like not all of your source made it into the discussion. What I would like to see is the program interface into the service program procedure, the fields associated with the parameter defining the fields that are meant to be written to the physical file (just one or two would be sufficient - and are they standalone or within a data structure), the fields that are defined within the physical file (again just one or two and are they standalone or within a data structure), and the actual write statement. Bruce
    6,620 pointsBadges:
    report
  • bvining
    PS - and it certainly wouldn't hurt to have the same for the original OPM program that did work.
    6,620 pointsBadges:
    report
  • Adamdowen
    Included below is the actual source code of the service program (like I said, there were VERY few changes to convert it from OPM to Service Pgm). An example of a field that is being written to a blank value is LBPGMID (it's basically the name of the program that is calling this & causing the record to be written). A few more examples are LBRAMT & LBRATE. [code] h nomain H DEBUG OPTION(*SRCSTMT:*NODEBUGIO) *--------------------------------------------------------------------- * PROGRAM ID: BIWLBRSV (Service Pgm ver of BIWLBR) * < additional comments removed... > *--------------------------------------------------------------------- FLOTBILL UF A E K DISK FPRODLF3 IF E K DISK RENAME(FPRODUCT:FPRODLF3) FPRODUCT IF E K DISK FLOTLF4 IF E K DISK FCORPC001 IF E K DISK ************************************************************************** * WrtLotBill Prototypes * ************************************************************************** D WrtLotBill... D PR D PLWHSE 2A D PLWHNO 5S 0 D PLCUST 5S 0 D PLPROD 10A D PLPRD 30A D LBCTG 10A D PLLOT 7S 0 D PLPRCD 20A D LBNWGT 9P 2 D LBGWGT 9P 2 D LBCASE 11P 2 D LBRATE 7P 4 D LBRAMT 11P 2 D TAXPCT 4S 4 D INVTYP 1A D INVNO 7S 0 D INVCC 2S 0 D INVYY 2S 0 D INVMM 2S 0 D LBGWGT 9P 2 D LBCASE 11P 2 D LBRATE 7P 4 D LBRAMT 11P 2 D TAXPCT 4S 4 D INVTYP 1A D INVNO 7S 0 D INVCC 2S 0 D INVYY 2S 0 D INVMM 2S 0 D INVDD 2S 0 D LBSCHG 3A D TRID 3A D TRREFE 8A D LBPGMID 10A ************************************************************************** * DltLotBill Prototypes * ************************************************************************** D DltLotBill... D PR D PLWHSE 2A D INVTYP 1A D INVNO 7S 0 ************************************************************************** * Procedures * ************************************************************************** p WrtLotBill b Export D WrtLotBill PI D PLWHSE 2A D PLWHNO 5S 0 D PLCUST 5S 0 D PLPROD 10A D PLPRD 30A D LBCTG 10A D PLLOT 7S 0 D PLPRCD 20A D LBNWGT 9P 2 D LBGWGT 9P 2 D LBCASE 11P 2 D LBRATE 7P 4 D LBRAMT 11P 2 D TAXPCT 4S 4 D INVTYP 1A D INVNO 7S 0 D INVCC 2S 0 D INVYY 2S 0 D INVMM 2S 0 D LBGWGT 9P 2 D LBCASE 11P 2 D LBRATE 7P 4 D LBRAMT 11P 2 D TAXPCT 4S 4 D INVTYP 1A D INVNO 7S 0 D INVCC 2S 0 D INVYY 2S 0 D INVMM 2S 0 D INVDD 2S 0 D LBSCHG 3A D TRID 3A D TRREFE 8A D LBPGMID 10A D* .... work variables D TIHI S 7P 0 INZ(*ZEROS) D REMAIN S 7P 0 INZ(*ZEROS) D WRWGHT S LIKE(LBGWGT) ********************************************************************** C PRODLF3KEY KLIST C KFLD PLWHSE C KFLD PLCUST C KFLD PLPROD C LOTLF4KEY KLIST C KFLD PLWHSE C KFLD PLCUST C KFLD PLPROD C KFLD PLLOT C CORPC001KEY KLIST C KFLD LBSCHG * Retrieve product information C CLEAR *ALL FPRODUCT C IF PLPROD > *BLANKS C PRODLF3KEY CHAIN PRODLF3 C IF NOT(%FOUND(PRODLF3)) C PRODLF3KEY CHAIN PRODUCT C ENDIF C ENDIF * Retrieve corporate charge information C CORPC001KEY CHAIN CORPC001 C IF NOT %FOUND(CORPC001) C CLEAR *ALL CCFMT C ENDIF C EVAL LBWHSE = PLWHSE C EVAL LBWHNO = PLWHNO C EVAL LBCUST = PLCUST C EVAL LBCDRJ = PRCDRJ C EVAL LBPRCD = PRCODE C EVAL LBCFD = PRCFD C IF LBCTG = *BLANKS C EVAL LBCTG = PRCTG C ENDIF * If the billing category was not received from the calling program * and it is not defined in the Product file, it is now defaulted to * 'UNKNOWN'. C IF LBCTG = *BLANKS C EVAL LBCTG = 'UNKNOWN' C ENDIF C EVAL LBCTG2 = PRCTG2 C EVAL LBBUNT = PRBUNT C EVAL LBLOT = PLLOT C EVAL LBLPRC = PLPRCD C EVAL LBINTP = INVTYP C EVAL LBIVNO = INVNO C EVAL LBINVC = INVCC C EVAL LBINVY = INVYY C EVAL LBINVM = INVMM C EVAL LBINVD = INVDD C SELECT C WHEN LBRAMT>=*ZEROS C MOVE CCGLOA LBDEBT C MOVE CCGLOF LBDEBTSUB C MOVE CCGLAA LBCRDT C MOVE CCGLAF LBCRDTSUB C WHEN LBRAMT<*ZEROS C EVAL LBRAMT=%ABS(LBRAMT) C MOVE CCGLOA LBCRDT C MOVE CCGLOF LBCRDTSUB C MOVE CCGLAA LBDEBT C MOVE CCGLAF LBDEBTSUB C ENDSL C EVAL LBTRID = TRID C EVAL LBREF = TRREFE C EVAL LBAPYR = *ZEROS C EVAL LBAPMM = *ZEROS C TIME LBAUTS * Determine net and gross weights based on parameter values. If * neither parameter value was received, use the product unit tare * weight and case quantity to calculate net and gross weights. tare C SELECT C WHEN LBNWGT > *ZEROS AND C LBGWGT = *ZEROS C EVAL LBGWGT = LBNWGT + (PRTARE * LBCASE) C WHEN LBNWGT = *ZEROS AND C LBGWGT > *ZEROS C EVAL LBNWGT = LBGWGT - (PRTARE * LBCASE) C WHEN LBNWGT > *ZEROS AND C LBGWGT > *ZEROS C OTHER C IF PLPROD > *BLANKS C EXSR PRODCALC C ENDIF C ENDSL * Calculate cube by multiplying the cube value from the product file * by the case count. C EVAL(H) LBCUBE = PRCUBE * LBCASE * Calculate pallet count by multiplying the pallet row and height from * the product file and dividing that result by the case count. If * a remainder is present, one is adde to the pallet count for a * partial pallet. C EVAL LBPALC = *ZEROS C EVAL(H) TIHI = PRPLTR * PRPLTH C IF TIHI > *ZEROS C LBCASE DIV TIHI LBPALC C MVR REMAIN C IF REMAIN > *ZEROS C EVAL LBPALC = LBPALC + 1 C ENDIF C ENDIF * Calculate the taxes for this line item C EVAL LBTAXRAT = TAXPCT C EVAL(H) LBTAXAMT = LBTAXRAT * LBRAMT C WRITE FLOTBILL * The LOTBILL record format is cleared to ensure values from the * current transaction are not returned to the calling program via * LOTBILLPRM. LOTBILLPRM is not cleared because it contains fields * which are not prefixed by 'LB' and may be used by the calling * program for other purposes. C CLEAR *ALL FLOTBILL C RETURN ********************************************************************** * PRODCALC - Calculate net and gross weights using the case countnt * received and information from product file. the ********************************************************************** C PRODCALC BEGSR * The LOTLF4 file is read to retrieve the lot average weight. If a * weight is found, it is placed in PRWGHT for a later calculation. C LOTLF4KEY CHAIN LOTLF4 C IF %FOUND(LOTLF4) AND C PLAWGT > *ZEROS C Z-ADD PLAWGT WRWGHT C ENDIF * Calculate net and gross weights using the case count and the unit * weight from the product file (or lot average weight if available). C IF PRBTYP = 'N' C EVAL(H) LBGWGT = LBCASE * (WRWGHT + PRTARE) C ELSE C EVAL(H) LBNWGT = LBCASE * (WRWGHT - PRTARE) C EVAL(H) LBGWGT = LBCASE * WRWGHT C ENDIF C ENDSR P WrtLotBill e ************************************************************************** * Procedures * ************************************************************************** p DltLotBill b Export D DltLotBill PI D PLWHSE 2A D INVTYP 1A D INVNO 7S 0 ************************************************************************** C LOTBILLKEY KLIST C KFLD PLWHSE C KFLD INVNO C KFLD INVTYP * Purge all LOTBILL records for an Invoice if requested (i.e., Special * Charge Code = *HIVAL) C IF INVNO <> *ZEROS ************************************************************************** * Purge records based on Invoice number. This is necessary for RCPTPRT * which may run more than once and result in different LOTBILL records. ************************************************************************** C DOU not %found(LOTBILL) C LOTBILLKEY DELETE(E) LOTBILL C ENDDO C EVAL *INLR = *ON C RETURN C ENDIF P DltLotBill e [/code]
    65 pointsBadges:
    report
  • Adamdowen
    When in the debugger, I can see that the values were passed into the service program correctly... they have the correct value both directly before & after the WRITE statement, but even though the values are correct the record that is created still has the zero/blank values. Ideas?
    65 pointsBadges:
    report
  • TSCHMITZ
    Hi, I think the problem could be that you define inside your Prototype (PR) the same fields that you also define inside your Program interface (PI). This is neither recommended, nor necessary. A typical PR definition never presents names for fields. d*-------------------------------------- d* Prototype for procedure: S_Rem Reminder d*-------------------------------------- d S_Rem PR 10i 0 Return %rem A(10i0):B(10i0) d 10i 0 A 10i 0 d 10i 0 B 10i 0 Try to cleanup your PR like the previous one and it should improve your program process. BYE. TSCHMITZ
    470 pointsBadges:
    report
  • Adamdowen
    Thanks for the info, TSCHMITZ, but unfortunately that's not it. I did go ahead & make the change (within both the SRVPGM & calling pgm). After running the same test, I still get the same result. In all actuality I'm using a /COPY command that holds the field definitions for both the PR & PI sections (For simplicity, I just copied those sections in for you guys). I wasn't aware that we could leave the field names off in the PR section. We were taught that the PR & PI field sections should match. Having them match made it easy to use the /COPY & for them to be more easily maintained in the future. Any other ideas that might help? Thanks!
    65 pointsBadges:
    report
  • Gilly400
    Hi, I'm going to ask a couple of stupid questions. Are you sure that the fields in your externally described file LOTBILL match the ones in your FLOTBILL record format? Is the correct version of LOTBILL in your library list at compile time? Do these fields show as being in the correct record format on your compile listing? Are they shown as input/output? Is LOTBILL a physical file or a logical file? Regards, Martin Gilbert.
    23,730 pointsBadges:
    report
  • Adamdowen
    Martin, Thanks for your reply.... here's my answers: 1. Are you sure that the fields in your externally described file LOTBILL match the ones in your FLOTBILL record format? Yes, they have both the same fieldname & characteristics 2. Is the correct version of LOTBILL in your library list at compile time? Yes, otherwise I would get a level check error. 3. Do these fields show as being in the correct record format on your compile listing? Are they shown as input/output? The fields are part of the FLOTBILL record format, which is defined as Update/Add. Also, the fields have to match exactly what is in LOTBILL, otherwise there will be a compile error (since there would be 2 different definitions for the same field name). 4. Is LOTBILL a physical file or a logical file? It's a physical file
    65 pointsBadges:
    report
  • Sloopy
    May I make a suggestion, which may or may not work? The parameters coming into the program are actually the addresses of fields in the calling program. They happen to have the same names as fields in the FLOTBILL record format, but I suspect that the procedure is treating the fields in FLOTBILL either as unreferenced fields when the names coincide, or as locally-scoped variables. Either way, the procedure does not recognise the fields in the record format and the 'fields' incoming as procedure parameters as the same fields. So, change the names in the parameter list (e.g. prefix them with 'p_', so you have p_LBRATE, p_LBAMT etc.), and then explicitly move these parameters to the fields in the format (Eval LBRATE = p_LBRATE, etc.). For myself, I'm dubious about using a service program to do basic database processing like this. You have less control - for example, these procedures and their ODPs are going to be hanging around forever; and if you get locking problems it would be very difficult to work out where the lock was, if control was not in the procedure at the time when you were investigating. But maybe that's just my own prejudices. I use service programs for well-used general (utility) procedures, and not for application database handling. Regards, Sloopy
    2,195 pointsBadges:
    report
  • TSCHMITZ
    Something that sounds strange to me, but i'm not sure because i miss files definitions is :
    * Retrieve product information
    C CLEAR *ALL FPRODUCT
    C IF PLPROD > *BLANKS
    C PRODLF3KEY CHAIN PRODLF3
    C IF NOT(%FOUND(PRODLF3))
    C PRODLF3KEY CHAIN PRODUCT
    C ENDIF
    C ENDIF
     
    Is it possible that your CLEAR some parameters you've passed to the program with this coding ? in other words, do you have common fields name between your parameters (PI) and records definition of your files, especially the one you CLEAR or the one you may read without succesfull retrieve ? Have you tried to debug you SRVPGM to trace when your parameter values are gone ? The code is not very long so this should be realistic to do. I hope it may help you. TSCHMITZ
    470 pointsBadges:
    report
  • Adamdowen
    Unfortunately that's not it either.... the only place the fields in question are defined are in the FLOTBILL record (& also as parameters). As mentioned previously, I have put the SRVPGM in the debugger: "When in the debugger, I can see that the values were passed into the service program correctly… they have the correct value both directly before & after the WRITE statement, but even though the values are correct the record that is created still has the zero/blank values." Thanks!
    65 pointsBadges:
    report
  • TSCHMITZ
    I think that's the fact. Your fields are defined as Global variable (File definition) and also as Local variable inside your Procedure. That means, for example, local PLPROD (inside PI) will never be moved to file during update because the field is also defined at GLOBAl level. (Files definition are allways global) And this one is *ZERO or *blank because not initialize. When you debug, you see local fileds, but global one remain empty. I suggest you these changes : 1) Rename your PI fields to something different than file fields (for example using prefix E_) and initialize the file fields (GLOBAL) using eval, move.... 2) If any other field from file (GLOBAl) also defined in local, rename it in local. 3) Mind your KLIST too. The fields to be used should be the renamed ones. I hope now, your code will run the trick. TSchmitz.
    470 pointsBadges:
    report

Forgot Password

No problem! Submit your e-mail address below. We'll send you an e-mail containing your password.

Your password has been sent to:

To follow this tag...

There was an error processing your information. Please try again later.

REGISTER or login:

Forgot Password?
By submitting you agree to receive email from TechTarget and its partners. If you reside outside of the United States, you consent to having your personal data transferred to and processed in the United States. Privacy

Thanks! We'll email you when relevant content is added and updated.

Following