Each deployment consisted of a back-office computer, a separate server and at least two POS units. All of these were standard PCs with very limited resources. Every pharmacy was connected to LAN via Ethernet, and used the same IP addresses so remote help and access were possible.
The server contained a modem, that was used to receive software and database updates, connect to suppliers (send orders, receive replies) and remote administration.
The software architecture from outside seemed like a simple two-tiered architecture of it’s time. In fact it was much more. The clients were quite dumb, they downloaded their resources, including their business logic from the server. The server was in-fact several servers rolled in one. Both the client and the server used the same virtual machine to run the pre-compiled byte code. (Note: The first versions of Java were in development at that time)
This would take up an entire article in itself. Why did we think we should create a database server? At the time of the project there were no freely available suitable database engines on the market. The ones available were either servers requiring regular administration, or low-end DBF libraries.
The database engine we ended up with was an extremely fast, mostly relational but not SQL standard based solution. These days it might be called NoSQL, but it wasn’t. The record structure was fixed, so it could be indexed, it supported index based aggregation/statistical functions. Indexes were created on demand. It supported different table types to be even faster. If a table had no dynamic length field it was stored in a smaller, faster format.
There were some interesting features in the engine, but one of the most important aspect was the directional link. The data was structured as a standard relational database, but while programming you could “walk” through the associations to see it’s content. This pattern emerged in ORM tools years later.
Client connection manager
The server managed the incoming connections, served the resources for the clients, as well as provided access to the database functions.
The connections to the server were through standard RPC calls. In the begining the client called the server GOD. Later a client could connect to other servers, and the names became configurable.
The server ran it’s own VM. It executed server side code exposed to the client as well as cron jobs. Several services were provided using the application server itself.
The web server was first an internal joke, that using the socket API’s we created a web server in just a few lines of code. It was used to serve some static content. A couple of months later this was extended to be used as the reporting front-end for the financial data. The reports were collected using the dial-in modem.
As another joke a telnet daemon was written. This was later used, to remotely control the engine itself and became one of the most administration important tool.
The finger daemon was implemented. It returned information about the attached clients and the running threads.
The thin-clients used BOOTP to download their bootstrap code. More about the thin clients later.
There were three kind of clients for different usage scenarios WIN32, DOS and DOSLESS, they all ran the same VM and the same bytecode, and used the same display forms. Their resolution was constrained to 80×25 characters. On the WIN32 client tweaks with the font, the background image, the button graphics and the modifiable color set made the difference.
The WIN32 version was used exclusively in the back office, it started as a simple local application, and looked like one. It could, and if my memory serves me right, did at one particular installation, reside on the same machine as the server itself. This had a unique feature not available on the DOS clients, it was able to show the report interface in an embedded Explorer (3.0) component. The report data was downloaded from the application server’s web server. It was not only an eye-candy, but the presented data showed the actual monthly report with dig-down options.
The DOS version of the client was quite interesting, however never actually used as is in the pharmacies. It was used mainly for development. The client didn’t satisfy with the 640KB, it also paged some of it’s data to the unused portion of the video memory! The character set was redefined, so good looking big text was available to print the large characters on the POS. This client was ran in a dosemu under linux, so rebooting didn’t take as long, and the other terminals were used for development. As my only adventure in Linux kernel development, I created a Hercules kernel module, so I could display debug text on it, my colleagues later wrote an entire debugger that lived on that.
So what’s this DOSLESS version? As we had to go cheap, we created an OS based on Linux kernel networking stack, that enabled the client to run without DOS. This was used in the pharmacies, and was downloaded entirely from the server. The POS terminals had no hard drive installed at all.
Beside running the DOSLESS client, the POS had some issues it had to face. As a cashier it had to drive the cashier drawer. This was simple enough, the drawer was connected to the parallel port, and we printed some character and the drawer opened.
But the parallel port? Isn’t that supposed to be for the printer? No. Direct printing is forbidden from the POS. It can only have a single attached printer, and that can only print through the black-box, that registers the amount of sales (and the VAT) for the tax-authority. Since these cannot be transferred, and we didn’t want to buy from the existing (expensive) black boxes, we created our own. This hardware development was quite a lengthy and painful process, especially when getting the tax-authority’s approval. Fortunately it turned out fine, and there were no faults in any of the units.
The POS had bar code readers as well, but we went for the one attached to the keyboard, so that was quite simple.
There were several tools created to support this framework, both during development, and later on in production.
Naturally there was a byte-code compiler that converted the language (TigC- or tc-) to byte-code (tcb). Then there was a form editor that was used to do the screen layout and set up the tab order. The VM had a built-in debugger, that utilized the Hercules monitors (hard to come by even then)
Later a debugger was created that allowed remote attach to a running VM (server or client) this saved lot of time, as it doubled as an editor. About this time we moved our development to Windows from Linux.
Windiff was modified to support TigC specifics, and enable us to see modifications better.
As we moved to production, remote administration became essential. Several small utilities were created to enable data backup. Later the server core was refactored to be more modular, and enable the server to upgrade itself.
As a final mention, a separate telnet server was created that we installed on the servers. This was used to get command prompt on the remote server. We used FAR commander remotely to create archives, modify settings, view logs. Since the modem was so low-bandwidth, the daemon monitored changes, and sent ANSII (positional and color) codes about changed areas. It was as if I was on my own computer. (Note: Yes there was remote desktop in WinNT, it was incredibly slow through dial-in)