Background
ASTA 2 for Windows has been in development since 1997 and was
started using Delphi 3. In March of 2000 Borland invited ASTA to view
their exciting new product for Linux coded named Kylix. Kylix was
designed to be cross platform and although the first release was for
Intel computers, the architecture will allow Borland to support other
hardware and we hope that versions of Kylix will eventually be
available for Solaris and other non-Intel platforms.
When doing the design the version of ASTA for Linux we had to decide
whether to worry about backwards compatibility or to just code things
the most elegant way. We choose to support Kylix and Delphi 5 and 6 and
not to worry about backwards compatibility with versions of Delphi
before Delphi 5. Borland has slowly been moving database functions
from BDE specific units to those that are abstracted to the TDataSet
level and we wanted to be able to take advantage of all the VCL code
that was available. The use of TParams is an example of something we
can use now since it is no longer tied to BDE code.
ASTA has used the Borland sockets that were first released in Delphi
3 and made available in the Professional versions of Delphi since
Delphi 3.01. Since these sockets were based on scktcomp.pas and were
based on TCustomWinSockets these classes are certainly not applicable
to Linux. ASTA has always used non-blocking event driven sockets and
under Linux and Unix blocking sockets have always been the standard.
There is much debate as to blocking versus non-blocking sockets and
instead of taking sides in this debate we decided to have an Open
Architecture for the transport layer of the Linux version of ASTA. At
this point we realized that the product we were working on was not
really ASTA 3 as the successor of ASTA 2 but a new product which we
called Asta Inter Op to signify the cross platform nature of the
product and also the open architecture. ASTA 2 will continue to evolve
as a Windows only product with free updates available to all ASTA users
for Delphi 6.
Open Transport Architecture
ASTA for Windows had the following design goals:
- Allow Database Developers to use their existing skills to develop N tier Applications so that existing applications could be quickly ported to ASTA using Client Side SQL
- Allow Experienced N Tier developers to use their N Tier Skills in extending ASTA servers using advanced N Tier features
- Build very scalable and easy to deploy servers and handle all Threading Issues internally so that Developers could concentrate on building applications
- Allow Thin Client Applications that could be deployed with NO DLL's and build in the ability to have client exe's update themselves when new versions were registered on the server
- Require only SQL Select statements so that all insert, update and delete SQL could be generated by ASTA components
- Build an easy to use Messaging Layer so that Database Application Developers that had NO tcp/ip experience could easily stream any kind of data across the internet
- Abstract the server side so that any Delphi 3rd Party Component could be easily plugged into an ASTA Server
Last item is what we call the "Switzerland" concept of ASTA in that
ASTA is database neutral. Any Database can be plugged into the ASTA
architecture in a very straightforward manner. In ASTA IO the Database
abstraction is contained in a component called the DatabasePlugin. In
ASTA Inter OP we have extended "Switzerland" to include the Transport
Layer by also abstracting the Wire.
Abstracting the "Wire"
ASTA Inter Op has an interface based architecture that will allow
for any kind of transport to be plugged in. We have tested ASTA IO with
sockets from Indy,
DXSocks,
IPWorks and ASTA's own
socket implementation using the ASTA PAL Sockets. There is also an
example using a shared buffer that will allow for ASTAServers and
clients to be compiled together to create a 2 tier application that
doesn't require tcp/ip and will have virtually no impact on
performance. Other possible transports could be used like named pipes.
TAstaServerWire
This is the Interface defined for the TastaServerWire. It does
include methods that apply to sockets but since most transports will be
tcp/ip based we felt that it was appropriate to include them to provide
a "roadmap" to know all the methods that must be implemented in order
to plugin any transport.
TIAstaServerTransportInterface = interface
procedure DoClientConnect(Client: TObject);
procedure DoClientDisconnect(Client: TObject);
procedure ReceiveString(Client: TObject; S: string);
procedure SendString(Client: TObject; S: string);
procedure DisconnectClient(Client: TObject);
function RemoteAddress(Client: TObject): string;
function RemotePort(Client: TObject): Word;
function GetPort: Word;
procedure SetPort(Value: Word);
function GetActive: Boolean;
procedure SetActive(Value: Boolean);
function ClientComponentAssertion(Anobject: TObject): Boolean;
end;
TcustomAstaServerWire = class (Tcomponent, TIAstaServerTransportInterface);
By descending from the TastaServerWire and implementing the
TIAstaServerTransportInterface a Transport can be created in a straight
forward manner.
The following is the Interface part of AstaIndyServer.pas that shows
how easy a TastaServerWire can be descended from.
TAstaIndyServerWire = class(TAstaServerWire)
private
FAbout: TAboutString;
FIndyServerSocket: TIdTCPServer;
procedure SocketConnect(AThread: TIdPeerThread);
procedure SocketExecute(AThread: TIdPeerThread);
procedure SocketDisconnect(AThread: TIdPeerThread);
function GetIndyServer: TIdTCPServer;
procedure SetIndyServer(Value: TIdTCPServer);
protected
Function ClientComponentAssertion(Anobject:TObject):Boolean;override;
procedure SetActive(Value: Boolean); override;
function GetActive: Boolean; override;
function GetPort: Word; override;
procedure SetPort(Value: Word); override;
procedure Notification(AComponent: TComponent;Operation: TOperation); override;
public
procedure DisconnectClient(Client: TObject); override;
function RemoteAddress(Client: TObject): string; override;
function RemotePort(Client: TObject): Word; override;
procedure SendString(Client: TObject; S: string); override;
constructor Create(AOwner: Tcomponent); override;
destructor Destroy; override;
published
property About: TAboutString read FAbout write FAbout;
property IndyServerSocket: TidtcpServer read GetIndyServer write SetIndyServer;
end;
Below is a property editor of a TastaIndyServerWire. Notice it has a
property pointing to an Indy specific Component (IndyServerSocket) and
also a property pointing to a TastaDatabasePlugin.
TAstaClientWire
Here is the Interface for the IastaClientMessageTransport. Once
again, methods for tcp/ip are contained in the interface where in a
pure world they are really not need but since most implementions will
use sockets, we decided to add them.
IAstaClientMessageTransport = interface
procedure DoConnect(Sender:TObject);
procedure DoDisconnect(Sender:TObject);
procedure ReceiveString(S: string);
procedure SendString(S: string);
function SendGetString(S: string): string;
Function GetActive:Boolean;
Procedure SetActive(Value:Boolean);
Function GetPort:Word;
Procedure SetPort(Port:Word);
Procedure SetAddress(Value:String);
end;
TAstaCustomClientWire = Class( Tcomponent, IAstaClientMessageTransport);
By descending from the TAstaCustomClientWire and implementing the
IastaClientMessageTransport Interface a custom transport can quickly be
defined. Below is the object inspector from Delphi showing a
TAstaIndyClientWire.
|