× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



<snip>
Could you provide some information on where you would use this method?
</snip>

I have seen it used for a Data Mediator (A generic data engine that lives 
between the program and service programs implementing data base access) by 
David Morris from Plum Tree Lumber. If anyone knows where to find the article 
he wrote on the Data Mediator, I would appreciate it. A brilliant piece of 
work. I believe it was in Midrange Computing.

I used it for a Trigger Mediator. My Trigger Mediator was the only program 
called by the data base and it dynamically loaded the correct service program 
for a given data base table. All this was loaded from a data base table and a 
user space allowing me to dynamically load and unload tables from triggers. It, 
also, allowed me to turn triggers on and off for all tables instantly. 

I was thinking of using at shipping software company I was at to dynamically 
load different shipping company modules but left before I could do anything. 

I used it for a FEDX parser. I built a generic front end for a State Transition 
Engine and then dynamically loaded the correct module containing specific 
routines for parsing specific strings. In that scenario, I could have one 
generic parsing engine, load the parsing tables from a user space and only have 
to write a single service program to implement unique logic. I would just need 
to give the user space name and the service program would be loaded from tables 
in the user space. I just happened to use the concept to implement a FEDX 
string parser.  
 
<snip>
Could you explain what criteria you use for deciding that a particular scenario 
is a good candidate for this method?
</snip>

Basically, you can dynamically load service programs anytime that you need to 
defer decisions about which service program to load until runtime. In the 
shipping example, a customer may have FEDX and UPS but not DHL. You don't want 
to load everything, just the shippers you needed. You might, also, have a 
scenario where the customer uses DHL but only occasionally. 

The one requirement is that all the service programs procedures that you call 
have the same type and number of parameters. For example, all the service 
programs that interface to the trigger mediator have the same interface.

Dynamic service programs allow you to do late binding, have multiple entry 
points(Multiple procedures) and have the performance of the service program. 
     
In my trigger mediator, it gave me the ability to load and unload tables from 
triggers dynamically, have the performance of a service program and have the 
data base call only one program. 

In the case of the Data Mediator, it gave the author the ability to have one 
program called by all programs requiring data base access and the mediator took 
care of the rest calling the correct service program and managing the data 
movement.

I always wanted to expand this concept to a generic data engine but figured no 
one would ever use it. 

Another example of this I could think of would be an interface program between 
RPG code and an PC client. A standard interface could be established and tables 
created which store which service program to call for a given transaction 
coming in from a TCP/IP interface. If a service program was not needed, it 
would not get loaded instead of loading everything. The interface program would 
then be generic and would know nothing about the actual processing of the data. 

<snip>
Of course, code samples would always be useful. ;-)
 </snip>

This is kind of long. This was test program I wrote to test my Dynamic Load 
service program. I had a service program that did reads and writes to the IFS. 
In this case, I just wanted to load all the functions dynamically instead 
binding into the program at compile time as a test. 

No guarantee on any of this code. I provide just as example of using dynamic 
service programs. Note that the program does not bind in XVIFSX. 

Sorry, this is not the service programs themselves. Too big to put all in here. 
I have two service programs that do the work, XVRSLV (Resolve System 
Pointer-Takes an object name and get a system pointer to it. XVDYNL calls 
XVRSLV and does the actual work.

There is a price for this power. Because you are loading dynamically, the 
compiler cannot validate parameters. If you screw up and pass parameters 
incorrectly, things are going to get interesting. I have seen some differences 
in performance between static binding and dynamic but not a lot and, of course, 
it is mega times faster than a dynamic program call.  

Everything that I have developed for dynamic service programs has come from 
work done by David Morris whom I am very grateful to.  

Prototype for XVDYNL:

      * ---------------------------------------------------------------
      * Prototype: XVDYNL_PR          Project.....:
      * Author...: A. Campin          Date written: 02/15/2003
      * Purpose..: Prototypes for Dynamically Load Procedures or Exp
      *              variables.
      * ---------------------------------------------------------------
      * Revision history:
      *  Project # Pgmr        Date   Desc
      *
      * End Revision History
      * ---------------------------------------------------------------
     d DYNL_ActivateServiceProgram...
     d                 pr
     d   PR_InServiceProgramName...                  
     d                                     Like(StdNam)
     d                                     Value
     d   PR_InServiceProgramLibrary...
     d                                     Like(StdNam)
     d                                     Value
     d   PR_OutActivationMark...
     d                                     Like(StdInt)

     d DYNL_GetPointerToProcedure...
     d                 pr
     d   PR_InProcedureName...                
     d                              4096   Varying
     d                                     Value
     d   PR_InActivationMark...
     d                                     Like(StdInt)
     d                                     Value
     d   PR_OutProcedurePointer...
     d                                     Like(StdPrcPtr)

     d DYNL_GetPointerToExportVariable...       
     d                 pr
     d   PR_InVariableName...                  
     d                             4096    Varying
     d                                     Value
     d   PR_InActivationMark...
     d                                     Like(StdInt)
     d                                     Value
     d   PR_OutVariablePointer...
     d                                     Like(StdPtr)

Code:
             
      *_> CNLLSTSPLF SRCFILE(@2/@1) SRCMBR(@3)
      *_> DLTMOD MODULE(@5/@4)
      *_> DLTPGM PGM(@5/@4)
      *_> CRTRPGMOD MODULE(@5/@4) SRCFILE(@2/@1) SRCMBR(@3) +
      *_>   DBGVIEW(@9) OPTIMIZE(@8) INDENT('| ')
      *_> CRTPGM PGM(@5/@4) MODULE(@5/@4) +
      *_>   ENTMOD(@5/@4) BNDSRVPGM(XVDYNL) +
      *_>   ACTGRP(QILE)

     h

      /copy *libl/qsrcf,cb_Std_Con

      /copy *libl/qsrcf,cb_StdType

      /copy *libl/qsrcf,XVDYNL_PR

        * Included only for constants needed on opens. 
        /copy *libl/qsrcf,XVIFSX_PR

     d cFilePath       c                   '/home/tranwork/alantest.txt'
     d cCodePage       c                   const(819)
     d cRecord1        c                   '=Now is the time for all good men t-
     d                                     o come to the aid of their country. -
     d                                     Now is the time for all good men to -
     d                                     come to the aid of their country. No-
     d                                     w is the time for all good men to co-
     d                                     me to the aid of their country. Now -
     d                                     is the time for all good men to come-
     d                                      to the aid of their country. Now is-
     d                                      the time for all good men to come t-
     d                                     o the aid of their country.'
     d cRecord2        c                   '=Now is the time for all good men t-
     d                                     o come to the aid of their country. -
     d                                     Now is the time for all good men to -
     d                                     come to the aid of their country.'
     d FileHandle1     s                   Like(StdInt)
     d RtnEOF          s                   Like(StdChr)
     d RtnString       s           32767   Varying
     d x               s                   Like(StdIntSml)
     d ActivationMark...
     d                 s                   Like(StdInt)

        * Procedure pointer to various routines. 
     d OpenFile...
     d                 s                   Like(StdPrcPtr)
     d CloseFile...
     d                 s                   Like(StdPrcPtr)
     d ReadFile...
     d                 s                   Like(StdPrcPtr)
     d WriteFile...
     d                 s                   Like(StdPrcPtr)
     d DeleteFile...
     d                 s                   Like(StdPrcPtr)
        /Free

          DYNL_ActivateServiceProgram('XVIFSX'      :
                                      '*LIBL'       :
                                      ActivationMark);

          DYNL_GetPointerToProcedure('IFSX_OpenFile':
                                     ActivationMark :
                                     OpenFile       );

          DYNL_GetPointerToProcedure('IFSX_CloseFile':
                                                 ActivationMark  :
                                     CloseFile       );

          DYNL_GetPointerToProcedure('IFSX_DeleteFile':
                                     ActivationMark   :
                                 DeleteFile       );

          DYNL_GetPointerToProcedure('IFSX_ReadFile':
                                     ActivationMark :
                                     ReadFile       );

          DYNL_GetPointerToProcedure('IFSX_WriteFile':
                                         ActivationMark  :
                                     WriteFile       );

            // Call to procedures are through procedure pointer instead of to 
the procedures directly. 
  
          OpenFile(cFilePath    :
                   (O_CREAT +
                    O_CODEPAGE +
                    O_RDWR)     :
                   FileHandle1  :
                   (S_IRWXU +
                    S_IROTH)    :
                    cCodePage   );
 
          CloseFile(FileHandle1);

          OpenFile(cFilePath   :
                   (O_WRONLY +
                    O_TEXTDATA):
                   FileHandle1 );

            For x = 1 to 5;
            WriteFile(FileHandle1                   :
                      cYes                          :
                      %Editc(Counter:'X') + cRecord1);

                WriteFile(FileHandle1                   :
                      cYes                          :
                      %Editc(Counter:'X') + cRecord2);
          EndFor;

          CloseFile(FileHandle1);

          OpenFile(cFilePath:
                   (O_RDONLY +
                    O_TEXTDATA):
                   FileHandle1 );

           DoU RtnEOF = cYes;
             ReadFile(FileHandle1:
                      RtnEOF     :
                      RtnString  );
           EndDo;

           CloseFile(FileHandle1);
           DeleteFile(cFilePath);

           *INLR = *On;
           Return; 
 
As you can see, this example uses multiple procedures. It just as well could be 
one procedure calling different service programs. I would just activate 
multiple service programs and use the correct service program I needed to call. 
Because what is returned is just a pointer, I can store it in a table in the 
program and retrieve it when I need it. 

Unfortunatly, I don't have my trigger mediator with me to show example of this 
and I would need to get it. 

Anyway, I hope this helps. 

-----Original Message-----
From: Larry Ducie [mailto:Larry_Ducie@xxxxxxxxxxx]
Sent: Saturday, February 19, 2005 9:24 AM
To: rpg400-l@xxxxxxxxxxxx
Subject: RE: Program binds to Serviceprogram in an fixed library instead
of searching the LibraryList.


Hi Alan,
 
<snip>
I have service programs that implement dynamic load of service programs if 
anyone is interested. You just make the calls and it handles the rest. There
is 
a trick to making it work.
</snip>
Could
you explain what criteria you use for deciding that a particular scenario is
a good candidate for this method?
<snip/>
 
That sounds VERY interesting. I'd more than welcome you sharing this info -
dynamic linking is about as close as we can get to late-binding and is
something I've looked into but not (yet) found a practical use for. It would
be interesting to see how this technique can be used in an RPG environment.
 
Could you provide some information on where you would use this method? Could
you explain what criteria you use for deciding that a particular scenario is
a good candidate for this method? Could you tell us what benefits this
method affords you?
 
Of course, code samples would always be useful. ;-)
 
Cheers
 
Larry Ducie





As an Amazon Associate we earn from qualifying purchases.

This thread ...


Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.