Articles menu

 

The best components for the best developers

maj 01. 2007
Running Win32 kbmMW application servers on Linux using WINE
User article

apr 03. 2007
Performance comparison of kbmMemTable Std/Pro and AnyDAC CDS

nov 15. 2006
The king has died...
Borland/CodeGear

jun 16. 2006
The story of 3rdparty announcements and reactions on them
General

maj 29. 2006
Solving the 'cannot find drf file' problem when compiling packages.
Delphi

feb 21. 2006
kbmMWCnnfig.inc explained
kbmMW

feb 14. 2006
ReportBuilder 10 enduser report design with kbmMW
kbmMW/RB10

feb 09. 2006
Tips to setup IIS/ISA to operate as proxy between kbmMW client and server.
kbmMW/IIS

feb 08. 2006
Some thoughts about Borlands decision to split out its IDE/Tools division
Borland

jan 08. 2006
Things to be aware about when moving from Datasnap to kbmMW
kbmMW related

jan 08. 2006
Long running client controlled (stateful) transactions and the query service.
kbmMW related

jan 08. 2006
Secure messaging tips.
kbmMW WIB related

jan 08. 2006
Updating time in MSAccess Database with ADO
kbmMW related

jan 08. 2006
Upgrade from kbmMW v1 to kbmMW v2
kbmMW related

jan 08. 2006
Cross database and macro support
kbmMW related

Running Win32 kbmMW application servers on Linux using WINE

User article
 

Author: Christian A. Pradelli
Date: 04/20/2007
kbmMW version: 2.61
Wine version 0.9.30

Introduction

I did this tutorial because after some time dealing with a Kylix compiled kbmMWserver I arrived to the conclusion that today it is a waste of time to work with Kylix if you can avoid it.

It works fine, but any time you have a problem is very hard to find and fix it (right now, debug is only possible using GDB debbuger). Other problem is that after all that effort you can only compile to 32 bit linux, not 64bits, FreeBsd, MacOs, etc.

One day on a production server I found a bug in my Kylix kbmMWserver application that takes me an entire day to solve it, so during that time I leave the windows version running with Wine to let my customer work. At that moment I discover that it performs at the same speed that the Kylix version and sometimes faster. So I did I extensive benchmarks that report that a Delphi 7 compiled server under wine performs at the same speed that a Kylix 3 compiled one most the time and some times perform up to 20% faster than the Kylix compiled server.

How can this be possible?, basically wine is not an emulator, it provides the libraries to let a windows application run under Linux and only make some kind of emulation when the application needs to interface with the OS, so if the application does not perform any operation with X server it practically doesn't suffer any performance penalty. How can it be faster?, because in Delphi 7 you can use some high optimized libraries like FastZLib that performs better that the ones that are available to Kylix.

Running a kbmMWserver using wine is very safe a stable, I tested it under heavy load (40 concurrent and demanding connections) and I never have a crash.

I'm not considering FreePascal at this moment, may be in the near future we can use it for compile kbmMWserver application to 64bits platforms where I think we will get better performance.

Requirements

To make a kbmMWserver application to work as a Linux daemon using wine, the application should not make any call to the X server. To do that, you must ensure that the application should not use the Forms unit at all.

A simple trick to confirm that Forms unit is not used in any place, is to temporally rename Forms.dcu in Delphi7\Lib directory to Forms.dcu.xxx and rebuild application, it Forms is not used the application will compile successfully and it size will be about 300k less than with Form unit included.

Also doing this you can run on a Linux server that have no X server installed.

Example

Following you will find a project example to make you server without Forms unit (because without it you don't have the Application variable), and at the end I put and script example to use it under Ubuntu (you can easily change to other Linux).

****************************************************************************************************
winedaemon.dpr
****************************************************************************************************

program winedaemon;

uses
  Windows,
  System,
  SysUtils,
  Srv1 in 'Srv1.pas' {Main: TDataModule};

{$R *.res}

var
  fAplNme: string;
  LogFile: string = '';
  ShutNme: string;
  ShutHdl: THandle;
  StopNme: string;
  StopHdl: Thandle;

// do a log
procedure DoLog(s: string);
var
  TFile: TextFile;
begin
  if LogFile = '' then
    WriteLn(s)
  else
    try
      AssignFile(TFile, LogFile);
      try
        Append(TFile);
      except
        Rewrite(TFile);
      end;
      try
        WriteLn(TFile, dato);
      finally
        CloseFile(TFile);
      end;
    except
    end;
end;

// this only work if you use wineconsole, but wineconsole doesn't work a a daemon
function ConProc(CtrlType : DWord) : Bool; stdcall; far;
begin
  // a KILL SIGINT (2) is the same as CTRL_C_EVENT
  if CtrlType in [CTRL_C_EVENT,CTRL_BREAK_EVENT,CTRL_CLOSE_EVENT,CTRL_LOGOFF_EVENT
                
,CTRL_SHUTDOWN_EVENT] then
  if not SetEvent(ShutHdl) then
    DoLog('Can't stop server');
  Result := True;
end;

begin
  fAplNme := ParamStr(0);
  if FindCmdLineSwitch('?',True) then begin
    WriteLn('options: -outlog -shutdown');
    Exit;
  end;

  ShutNme := StringReplace(fAplNme,'\','/',[rfReplaceAll])+'-shutdown';
  StopNme := StringReplace(fAplNme,'\','/',[rfReplaceAll])+'-stoped';
  ShutHdl := OpenEvent(EVENT_ALL_ACCESS,False,PChar(ShutNme));

  // the log will be done to a file
  if FindCmdLineSwitch('outlog',True) then
    LogFile := ChangeFileExt(fAplNme,'.log');

  // stop the server if it's executing
  if FindCmdLineSwitch('shutdown',True) then
  begin
    if ShutHdl = 0 then
      DoLog('shutdown – The server is not running')
    else
    begin
      StopHdl := CreateEvent(nil,False,False,PChar(StopNme));
      if SetEvent(ShutHdl) then
        WaitForSingleObject(StopHdl, 10000) // espero como maximo 10 segundos a que termine
      else
        DoLog('shutdown – Can't stop server');
    end;
    Exit;
  end
  else if ShutHdl <> 0 then
  begin
    DoLog('The server is already running');
    Exit;
  end;

  // start server
  DoLog('Starting server');
  Main := Tmain.Create(nil); // here you create the main kbmMWServer datamodule and configure it
  try
    // I create an event to trap shutdown signal
    ShutHdl := CreateEvent(nil,False,False,PChar(ShutNme));
    if ShutHdl = 0 then
      DoLog('Error creating stop event');

    // start kbmMW server
    Main.Srv.Active := True;
    DoLog('Server started');

    // trap ctr-c if you are running in a console with wineconsole
    SetConsoleCtrlHandler(@ConProc, True);

    // here we wait until shutdown
    WaitForSingleObject(ShutHdl, INFINITE);

    // stop the server
    Main.Srv.Active := False;

    // signal that I already shutdown
    StopHdl := OpenEvent(EVENT_ALL_ACCESS,False,PChar(StopNme));
    if StopHdl <> 0 then
      SetEvent(StopHdl);
  finally
    Main.Free;
    DoLog('Server stoped');
  end;

end.


****************************************************************************************************
init.d script for ubuntu
****************************************************************************************************
#!/bin/sh
#
# Start/Stop Wine Server
#
#
# This file belongs in /etc/init.d where it will be run
# on system startup and shutdown to start the background
# Wine Sever daemon

# Source function library.
#. /etc/init.d/functions

APP_NAME=winedaemon
APP_BIN=/home/user/mydaemon/$APP_NAME
APP_USER=user

case "$1" in
  start)
    echo -n "Starting $APP_NAME: "
   
sudo -u $APP_USER /usr/bin/wine $APP_BIN -outlog > /dev/null 2>&1 &
   
RETVAL=$?
   
echo
   
;;

 
stop)
   
echo -n "Stopping $APP_NAME: "
   
sudo -u $APP_USER /usr/bin/wine $APP_BIN -shutdown
   
RETVAL=$?
    e
cho
   
;;

 
status)
   
# to do
   
RETVAL=$?
   
;;

 
restart|reload)
   
$0 stop
   
$0 start
   
RETVAL=$?
   
;;

 
*)
   
echo "Usage: winedaemond {start|stop|status|restart|reload}"
   
exit 1
esac

exit $?



(Top)

 
 

User comments

<newsgroup snippet>

I'm start to use kbmMW with very little info about them, I ask Kim ...
(more)

I am an advanced Asta user ...
(more)

Just ported my 2tier app to use kbmMW™ in 1 1/2 days. 17 services, great performance.

 



 
 
 
CodeGear Technology Partner Components4Developers is the only major 3rdparty CodeGear Technology Partner approved n-tier vendor!

Copyright© 2001-2008 Components4Developers - All rights reserved