Home page Home page Home page Home page
Pixel Header R1 C1 Pixel
Pixel Header R2 C1 Pixel
Pixel Header R3 C1 Pixel
By Sprezz | Saturday 21 March 2020 15:14 | 0 Comments
Imagine the scenario - your client is a frugal sort and wants to have your system available to 25 of their office users but knows that it is highly unlikely that all 25 users will want to access the system at the same time - so they pay you for a 20 seat license.

All is well - until their users start to leave the app running on their laptop - and their laptop is configured to sleep after a pre-set period to conserve battery life. Their laptop sleeps and takes with it an OI license. This happens on 5 machines - so now they have 20 users active in the office - but only 15 available licenses. And somehow this is YOUR fault. (Isn't it always - it's probably a bug :D).

Is there anything to be done?

Don't you just love those sort of rhetorical questions? If there wasn't then this blog post would be a little pointless.

Those of you who've read our last blog post on the genesis of OpenInsight will realise that Windows is always trying to tell OpenInsight stuff that frankly, OpenInsight doesn't really care about. And most of the time, the stuff that it ignores, isn't of practical benefit to neither the user nor the developer. But in the situation we're describing there's a Windows message that we DO care about - the WM_POWERBROADCAST message. This is the Windows message that notifies the application that a power management event has occurred, and luckily for us - sleeping or suspending is just such an event. So if we can somehow listen out for that event we can take whatever action we want when it occurs. Well, as long as that action takes less than 2 seconds - the length of time that Windows waits after sending the message and actually doing the suspension.

Using OI 10 to illustrate this we only have add two small snippets of code. The first tells OpenInsight that actually, yes, we are interested in knowing about the WM_POWERBROADCAST message. The second looks at the contents of the message, determines that this particular message is a suspension/sleep message and if it is, kills OpenInsight.

Listen Up!

To tell OpenInsight that we want to be told about the WM_POWERBROADCAST message we add the following lines to our main application window's create event.

   message   = 0x218
   newQual  = 1
   prevQual = Exec_Method( @window, "QUALIFYWINMSG", message,  newQual)

218 HEX (536 DEC) is the code for WM_POWERBROADCAST and the newQual parameter is defined as follows in the documentation "OpenInsight 10 Presentation Server Reference Manual.pdf" in the documents folder. We're effectively saying "If Windows tells you about this, please let me know by raising the WINMSG event on the current Window".


To act upon the notification we simply have to add this code to the WINMSG event (or any other event if you prefer (See the above documentation))

   If wParam = 4 Then
      call exec_Method("SYSTEM", "DESTROY", "SYSTEM")

Where 4 is the code for PBT_APMSUSPEND - the system is suspending operation. Naturally, we don't HAVE to close down OpenInsight - we can take whatever actions we want in the remaining 2 seconds before Windows actually suspends operation.

Of course, when your user repowers up their workstation, OpenInsight will no longer be there - a surprise to them given that the point of a SLEEP is to return to where you left off - but if that's what you as the developer opt to do, that's your prerogative - and your parsimonious bill payer will remain happy!

By Sprezz | Monday 16 March 2020 15:28 | 0 Comments
As I start to write this blog entry, Aaron has pointed out that it is 25 years to the day since Advanced Revelation (AREV) 3.12 was released. That means it is even longer since OpenInsight (OI) 1.0 was released. Recently working with some individuals, it became apparent that not everybody's memory goes back that far, so we thought it'd be a good idea to put together an article which combined a little bit of history with a dollop of technical information about OpenInsight load sequences - to assist in helping debug non-starting OpenInsights.

When people launch OI, they might be aware that they're actually launching an executable file, Oinsight.exe (or OpenInsight.exe for 10+) and Oengine.dll (or RevEngine.dll for 10+), but they might not be aware why this turn of events came to pass. To understand this we have to cast our mind back to the early 90s when the days of DOS were numbered and the future lay in the Windows GUI.

The team at Revelation were justifiably proud of the success of the myriad of alternative Base Filing Systems (BFSs) that were available for the developer community. The separation of the programming logic layer from the physical filing system layer had proven to be very successful with AREV. In fact Revelation had won a special award from Microsoft for driving the sales of their nascent SQL Server product. With the addition of BFSs for Lotus, DB2, dBase et al Revelation realised that they were onto a good thing. And what's better than a good thing? Even more of a good thing!

So deciding that being able to talk to ANY back end was a good thing, they also considered that being able to talk to (or be talked to) by ANY front end must also be a good thing. Ans so was born OE 1.0. The engine. Just the engine. No front end as we know it, linear hash as a back end by default, but any BFS you wanted to use. With hindsight this was genius. Just not commercial genius. The Rev community voted with their feet and refused to use it. The engine as we know it was pretty much the same beast. It could run R/Basic and it could read and write data - but there was no decent IDE. Rev tried to include a simple third party development environment when they released OI 1.0 but it was no AREV.

So back to the drawing board. Rather than start again reengineering the engine, Rev quickly began development of a separate executable whose job was to ;

  • Communicate with Windows
  • Communicate with the engine
  • Support a more familiar IDE
and this became Oinsight.exe. The executable responsible for all of the Windows interaction - the Presentation Server - was embedded within this. So now if we wanted to launch say a CUSTOMER window with a couple of statics, a couple of edit lines and an OK and Cancel button the scenario would unfold as follows where the protagonists are as follows ;

  • Windows
  • Oinsight.exe
  • Oengine.exe
Please note this conversation is simplified for explanatory purposes...
Please launch window CUSTOMER
Oengine - please read the compiled definition of CUSTOMER from SYSREPOSWINEXES
Read it - here you go!
Windows - please create a window called CUSTOMER sized as follows with the following characteristics
OK - I've done that but I don't call it CUSTOMER I call it 12786
OK - I'll remember that - thanks
Windows - now please create a static called TXT.CUST_ID
OK - done - I call it 12787
Windows - now please create another static called TXT.CUST_NAME
OK - done - I call it 12788
Windows - now please create an edit line called EDL_CUST_ID
OK - done - I call it 12789
Windows - now please create an edit line called EDL_CUST_NAME
OK - done - I call it 12790
Windows - now please create a push button called BTN_OK
OK - done - I call it 12791
Windows - now please create a push button called BTN_CANCEL
OK - done - I call it 12792

and there we have it - a working Window.

From hereon in, OI is oblivious to the existence of the Window as it is completely under the control of Windows. Of course, Windows knows who the owner is, so as the user mouses around the screen the following conversation ensues

Hey OI the user just moved the mouse by a pixel in 12786
Don't care
They did it again in 12786
Still don't care
They just right clicked the mouse when over 12789
Don't care - developer doesn't want to do anything
Oh wait - they've clicked on 12791
Really? The OK button? OK Oengine, see if you can find a script for the OK button for CUSTOMERS
Found it and running it
It's finished running so now I'm going to look for promoted events
Found the system click handler and I'm now running that
Right nothing else to do

OK let's wait until Windows tells us something we care about

So there is an ongoing dialog between Windows and OI with OI either ignoring Windows messages it doesn't care about, or asking OE if there's anything it's meant to be doing.

Which leads us on to the question of exactly what happens when the user double clicks the OI icon on the desktop. That sequence is as follows in 9.4 :-

Oinsight.exe loads
imgMan32.dll is loaded to later display the splash screen
Several other OI dlls are loaded
Supporting Windows dlls are loaded
OI then loads various language support dlls including UTF8 support
OI then loads tool specific dlls
OI then loads the routines to support linear hash
OI then loads the engine dll
OI then loads Lotus Notes support
OI then loads font support
OI then displays the splash screen
TCP/IP support is installed
The SYSPROG.DBT is read
The linear hash client is started
Boot revmedia map is loaded
Communication is opened to the UD service
Files are attached
System routines are loaded
Initialise is run
The login dialog is launched

For 10.0+ it is

OpenInsight.exe loads
Supporting Windows dlls are loaded

Windows imaging is loaded
OI then loads various language support dlls including UTF8 support
OI then loads various COM objects
OI then checks the .rxi file for startup options
OI then loads font support
OI then loads the splash screen
OI loads communication libraries
TCP/IP support is installed
OI loads the engine dll
OI checks licensing
The SYSPROG.DBT is read The linear hash client is started
Communication is opened to the UD service
Files are attached
System routines are loaded
Initialise is run
The login dialog is launched
By Sprezz | Thursday 12 March 2020 14:48 | 0 Comments
We've recently been supporting a venerable app for a long time Revelation Client (put it this way, when working on it recently, we came across some of our code taken from a REVMEDIA article nearly 30 years ago!) whose developer has retired.

Year end had come around and some modifications made in the last decade had finally turned around to bite the client. Think of a Y2K bug and then increase its occurrence by two orders of magnitude.

The system - as part of its year end routine - would calculate the starting row id number for a specific temporary table, by taking the last digit of the year and multiplying it by 10,000. It would then drop this into the row id prompt automatically. So for 2017 the starting number would be 7 * 10,000 = 70,000. For 2019, 9 * 10,000 = 90,000. For 2020? Less good. 0 * 10,000 = 0.

Of course, we could get around that issue if it were not for the fact that this calculation was done on the default row id prompt, which also had a validation of 5N.

So the system calculated a starting number of 0, and OI rejected it as not being a 5 digit number. So the system calculated a starting number of 0, and OI rejected it as not being a 5 digit number. So the system calculated a starting number of 0, and OI rejected it as not being a 5 digit number. So the system calculated a starting number of 0, and OI rejected it as not being a 5 digit number. So the system calculated a starting number of 0, and OI rejected it as not being a 5 digit number. So the system calculated a starting number of 0, and OI rejected it as not being a 5 digit number. So the system calculated a starting number of 0, and OI rejected it as not being a 5 digit number. So the system calculated a starting number of 0, and OI rejected it as not being a 5 digit number..... you get the picture.

That was a relatively easy fix once the business decided what they wanted to use instead.

The bug that REALLY threw us, was that in other parts of the system, we would enter a new starting row id, the system would accept it, look up the row and then reset the row id to a seemingly random number. Initially our suspicion was raised by the default program and we took some time analysing that but couldn't see where the issue lay. This being AREV32 we had lots of potential culprits... was it the
  •  Post-prompt routine
  •  Pre-prompt routine
  •  Pre-read routine
  •  Post-read routine
  •  Post-app initialise routine (This did a LOT of work rearranging prompts and prompt logic)
Whatever it was it wasn't screaming out to be identified, but after a couple of hours of debugging we zoomed in on the fact that the pre-prompt routine used a parameter row called 00 to store the defaults.

We opened the parameter row up in the editor and it existed alright - so we updated the defaults in that row, saved them and went off to see if our fix had worked.  We were taken aback to see that it didn't. Despite putting 100,000 into the correct position in the parameter row, the seemingly random number kept turning up like a bad penny.

So we zoomed in on the section of code that grabbed the default number :-  

ReadV defaultNum from vTable, 00, 978 else call fsMsg() 

We double-checked, and yes, 100,000 was indeed in column 978 of row 00. We triple-checked. No change. And then, because we now knew where the problem lay, it became obvious. One of those "Well d'uh" moments.

Opening up the editor we looked to see if there was a parameter row with a row id of 0. Of course there was. And in CAPITAL LETTERS across the top of of the first column was "DEPRECATED - DO NOT USE".  And there in column 978 of row 0 was our seemingly random number.

With hindsight this was so obvious - the 00 was not quoted so wasn't treated as a string, it was treated as a number, and 00 === 0 if we're talking numbers. But it just seemed so strange that a developer would deliberately choose to use 00 over 0 if they meant 0. Of course, the strong likelihood is that the developer thought that they meant 00 - hence the comment in column 1 of row 0!

We even went back to original AREV on an XP (thanks Carl and Bill) to check the original behaviour, and unsurprisingly nothing has changed. So mystery solved and problem averted but a salutary lesson.

Pixel Footer R1 C1 Pixel