Home page Home page Home page Home page
Pixel
Pixel Header R1 C1 Pixel
Pixel Header R2 C1 Pixel
Pixel Header R3 C1 Pixel
Pixel
By Captain C | Friday 22 May 2009 11:00 | 0 Comments
It is a common requirement in many applications to initialise data before the application itself begins to execute proper. Many OpenInsight applications are desktop applications, and as such have a “main” or “start-up” window. It is generally sufficient in these cases to initialise the data during the CREATE event of the start-up window, usually before anything is displayed to the user – this approach also has the advantage of knowing that both the Presentation Server (the part of OpenInsight responsible for displaying forms and controls) and OpenEngine are both fully booted and initialised themselves, which means all their features are available for use.

Of course, it is possible to use OpenEngine without using the Presentation Server, via such tools as OECGI, RevODBC, Xrev.dll and so on. In these cases another method is needed to initialise the data as there is no “main window” to speak of that we can hook into. Fortunately such a method does exist because OpenEngine provides a “Startup Procedure” facility (or “StartProc” as we’ll call it here) that allows you to nominate a stored procedure to be executed during the engine boot-up phase. Using this facility is actually quite simple, but there are some points to be aware of to use it successfully which is what we’ll be covering here.


Creating a StartProc

The first step is of course to create a stored procedure to initialise your system. When creating this procedure it must support one of the following two interfaces:


compile subroutine myStartProc( initflag, atstation ) 
   * // Do your stuff here 
return 
  
compile subroutine myStartProc( initflag ) 
   * // Do your stuff here 
return 


As you can see the Engine boot process will pass you one or two arguments depending on which interface you chose:

initFlag – If this is TRUE$ then it means that StartProc is being called for the first time during the engine bootup process. It can be called at subsequent points after the engine bootup process, usually as a side effect of running another procedure like swapping out the database. The points at which your StartProc can be called are:
  • During the actual engine bootup process. At this point initFlag will be TRUE$.

  • During a Swap_Database() call when changing the database. At this point initFlag will be FALSE$ or null (i.e. an empty string).

  • It is also possible for an application to call the Initialize() stored procedure “manually” to re-initialize itself. This is rare and is something you as a developer may want to do, but as Initialize() is the routine responsible for calling the your StartProc then expect it to be executed here as well.

atStation – When a StartProc is called during the engine boot phase (i.e. when initFlag is TRUE$) it is possible to use it to modify the contents of the @Station system variable. The system passes the StartProc what it considers @Station should be (usually this is the actual workstation name as set by Windows), but this may be overridden by altering this argument before the StartProc returns.


Installing a StartProc

Once you have created your procedure the next job is to tell your application about it. This is quite simple and is achieved by entering the name of the procedure in field 32 of your application environment record (documentation to this effect can be found in the ENVIRON_CONSTANTS insert record).

Care must be taken however, when dealing with an application outside of SYSPROG. When the StartProc is called there is a very good chance that it is called before the engine is fully booted, and one factor that impacts us here is that the @AppID variable will not be set. This in turn has consequences for the program loader (RTP27) which relies on @AppID to resolve program names using the application inheritance chain when searching for object code.

To overcome this the application suffix MUST be included when adding the StartProc name to the application environment name (The application suffix is the same as the suffix added to the program name when it is compiled and stored in SYSOBJ, minus the leading “$” character). The name should also be entered in uppercase.

e.g.
  • You wish to specify a StartProc called MYSTARTUPPROC for the SYSPROG application and MYSTARTUPPROC was compiled in SYSPROG:

    Open up the ENV_SYSPROG record in the SYSENV table and enter MYSTARTUPPROC in field 32.


  • You wish to specify a StartProc called MYSTARTUPPROC for the MYAPP application and MYSTARTUPROC was compiled in the MYAPP application:

    Open up the ENV_MYAPP record in the SYSENV table and enter MYSTARTUPPROC*MYAPP in field 32.


  • You wish to specify a StartProc called MYSTARTUPPROC for the MYAPP2 application and MYSTARTUPROC was compiled in the MYAPP application:

    Open up the ENV_MYAPP2 record in the SYSENV table and enter MYSTARTUPPROC*MYAPP in field 32.


Calling other procedures from a StartProc

Just as care must be taken when specifying the StartProc for an application, the same can be said of calling programs from within the actual StartProc due to the limitations encountered by RTP27 as described above. If the StartProc only calls system procedures or procedures belonging to the SYSPROG application then there will be no changes needed to the StartProc code when calling them.

If you wish to call procedures compiled in a non-SYSPROG application however, the application suffix must be added to the procedure name to execute it, in the same manner as described above when adding a StartProc name to the environment record. Of course a “*” character is not valid in a procedure name and the compiler will reject it, so to get around this we can use the “call” and “function” statements instead. The modified stored procedure name can simply be loaded into a variable and then invoked with one of the afore-mentioned statements.

e.g.

compile subroutine myStartProc( initflag, atstation )

   * // Call a subroutine MYSUB compiled in the MYAPP account
   procid = "MYSUB*MYAPP" ; * // Ensure UPPER CASE!
   arg1   = "Hello"
   arg2   = "World"
   call @procid( arg1, arg2 )

   * // Call a function MYFUNC compiled in the MYAPP account
   procid = "MYFUNC*MYAPP" ; * // Ensure UPPER CASE!
   arg1   = "Hello"
   arg2   = "World"
   retval = function( @procid( arg1, arg2 ) )

return

Labels: , ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]



<< Home

Pixel
Pixel Footer R1 C1 Pixel
Pixel
Pixel
Pixel