![]() |
|||||||
![]() |
|
||||||
![]() |
|||||||
|
In the recent posting on OI initialization we touched upon the program loader process, or RTP27 as it's officially known. This is the stored procedure that is responsible for loading object code onto the OpenEngine program stack so it can be executed.
An integral part of this loading process is the SYSENV SYSPROCNAMES record, which is simply a list of all the stored procedures that OpenInsight considers to be system stored procedures. It is cached in memory during the engine boot process. Under most circumstances you'll see RTP27 use the application inheritance chain to find the correct version of the object code to load - i.e. it parses @AppID appending an extracted application name to the specified program name until it finds the correct record in SYSOBJ or until it reaches the SYSPROG application. For example, if the application inheritance chain looks like this:
Then RTP27 will search for the object code record for TESTPROC in SYSOBJ in the following order:
However, this is not the whole story: RTP27 first attempts to locate the program name in the cached SYSPROCNAMES list. If found then the SYSPROG version of the program is loaded - the application inheritance chain is never used. This is to prevent application specific programs with the same name as a system program from loading and possibly interfering with the system processes. You may think this sort of thing doesn't happen, but on a recent site visit we moved an existing OI 4.1.3 system to version 9.0.0 (We did this the simple way - an APPBACKUP from 4.1.3 into a clean 9.0.0 system). One of the big issues we encountered during the upgrade process were naming conflicts: Being a well established system there were some stored procedures in the client application that had the same name as those found in the SYSPROG application. For example, the clients PlaceDialog() function conflicted with the SYSPROG PlaceDialog() function - the result? No dialogs were visible in the System Editor++ when run from the client app - ouch! Of course I just said that SYSPROCNAMES protects system routines right? Unfortunately the OI 9.0.0 installation process installed a blank SYSPROCNAMES record which meant that nothing was protected. This has been corrected in the next release (OI 9.0.1 as of writing), but as a workaround for now simply copy the SYSPROCNAMES across from your OI 8.x system if you need to. Compiler Protection and modifying SYSPROCNAMES Just as it protects RTP27 at runtime the SYSPROCNAMES record also protects the system from accidental compilation and overwriting of system stored procedures: The compiler will not let you compile any stored procedure if it's name can be found in SYSPROCNAMES. If you need to disable this feature for any reason you can modify the desired program name in SYSPROCNAMES (usually by inserting a ";" or "*" in front of it), saving the changes, and then rebooting OI (This is how the aforementioned client had programs in their own application with the same name as system programs). This will have the added effect of forcing RTP27 to load your modified version rather than the SYSPROG version at runtime. Bear in mind however that OI upgrades from Revelation will overwrite SYSPROCNAMES so make sure you remember any changes you make to it! Labels: Compiler, Initialize, OpenInsight, RTP27, SYSPROCNAMES
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:
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.
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: Initialize, OpenInsight, RTP27
Previous Posts
Archives
BlogRoll
Subscribe
Subscribe via RSS
(For those who still appreciate civilised technology.)
Add to your reader
Scan to subscribe
Subscribe to
|
|||||||
![]() |
|||||||
| |||||||