Recent

Author Topic: DataSnap Alternative for Lazarus  (Read 41384 times)

jixian.yang

  • Full Member
  • ***
  • Posts: 173
Re: DataSnap Alternative for Lazarus
« Reply #15 on: November 05, 2011, 06:47:40 pm »
Why do you close the dataset in TOnlineQuery.SetPrimaryKey?

Some more problems:
- date fields can't be updated. TOnlineQuery.GenerateUpdateData doesn't quote the date time string. TOnlineQuery.ComputePrimaryKeyForSQLData and TOnlineQuery.GenerateInsertData) have the same problem. May I suggest to create a FieldToSQL function to avoid repeating the same code?
- strings can't contain single quotes since the are not escaped. The string O'Hara should be quoted as 'O''Hara'.
- server errors, such as above, are not transmitted to the client.

Issues on the server side:
- when port is in use the server thread exits but no exception is raised.
- server thread is not stopped in TSSocketServer.Close, only the client threads. As a result, when TZeosDataServer1.Port is changed on an active ZeosDataServer1, the server will be listening on 2 ports. To demonstrate this, add the following to the demo ServerUnit.pas:
Code: [Select]
procedure TServerForm.FormShow(Sender: TObject);
begin
  ZeosDataServer1.Port:='8081';
end;
The server in now listening on port 8080 and 8081.
- TZeosDataServer.SetPort should only call close,listen if port is different from earlier value. In the demo where active:=true and port:=8080, when loading the component a server thread listening on the same port will be created from both TZeosDataServer.SetActive and TZeosDataServer.SetPort.

Thanks for so many tests and advice. All of them are fixed and submitted to svn.

ludob

  • Hero Member
  • *****
  • Posts: 1173
Re: DataSnap Alternative for Lazarus
« Reply #16 on: November 05, 2011, 09:00:19 pm »
Much better :)

Still some issues:
- the local dateformat is used to convert tdatetime to SQLString. Mine is dd/mm/yyyy hh:mm:ss which is not recognized by the DBserver. You should force the string to the ISO 8601 format yyyy-mm-dd hh:mm:ss.  Take a look at TSQLConnection.GetAsSQLText in packages\fcl-db\src\sqldb\sqldb.pp.
-
Quote
when port is in use the server thread exits but no exception is raised.
problem wasn't fixed. A simple fix would be to insert a sleep(100) in TSSocketServer.Listen after TSrvThread.Create(Self) and then test on a TSrvThread flag set in TSrvThread.Execute and set FActive accordingly. Set the flag just before before the synchronize, otherwise you can sleep as long as you want, synchronize will wait even longer ;)

jixian.yang

  • Full Member
  • ***
  • Posts: 173
Re: DataSnap Alternative for Lazarus
« Reply #17 on: November 06, 2011, 07:12:54 am »
Quote
- the local dateformat is used to convert tdatetime to SQLString. Mine is dd/mm/yyyy hh:mm:ss which is not recognized by the DBserver. You should force the string to the ISO 8601 format yyyy-mm-dd hh:mm:ss.  Take a look at TSQLConnection.GetAsSQLText in packages\fcl-db\src\sqldb\sqldb.pp.

Great.

Just set DateSeparator := '-'; on both side.  Then they are ISO 8601 now.

Quote
Quote
when port is in use the server thread exits but no exception is raised.
problem wasn't fixed. A simple fix would be to insert a sleep(100) in TSSocketServer.Listen after TSrvThread.Create(Self) and then test on a TSrvThread flag set in TSrvThread.Execute and set FActive accordingly. Set the flag just before before the synchronize, otherwise you can sleep as long as you want, synchronize will wait even longer ;)

On server side, it call "select" of socket api in CanRead function at last, and there is timeout parameter in "select". Therefore if there is sleep(n), there will be problem on large connection situation. Maybe that is why there is no sleep(n) in all of the synapse server demo.

The Active property is set after connection in the socket thread now.

An exception will cause a GUI library include. On the client side, the Application.MessageBox is used instead of raise exception.create(). Because there should not be the ok and cancel button in the raise exception in Lazarus.





ludob

  • Hero Member
  • *****
  • Posts: 1173
Re: DataSnap Alternative for Lazarus
« Reply #18 on: November 06, 2011, 10:32:14 am »
A step backwards  :(

Quote
Just set DateSeparator := '-'; on both side.  Then they are ISO 8601 now.
1) note the inversion of the files dd/mm/yyyy and yyyy-mm-dd. Setting DateSeparator := '-'; results in dd-mm-yyyy which is not compatible with yyyy-mmm-dd. As a result displaying a date now also raises an exception.
2) I don't want to change the default date format since that affects also the display and entry of dates.

In a n-tier implementation you should standardize the date format between client and server and leave the display/entry format to the client default settings. Since the ISO 8601 yyyy-mm-dd hh:mm:ss format is recognized by all db servers, you could as well use that format to communicate between client and server.

A similar issue exists with the decimal separator. In my country it is a "," and I can't change a floating point value. It returns a "syntax error at ","". So their also you need to convert to a "." in the communication between client and server. And drop the thousand separator that is used in some locales.

Quote
On server side, it call "select" of socket api in CanRead function at last, and there is timeout parameter in "select". Therefore if there is sleep(n), there will be problem on large connection situation. Maybe that is why there is no sleep(n) in all of the synapse server demo.
I don't see how a 100ms sleep in the main thread would affect the multi second select time-out in a different thread. The idea of the sleep in the thread creation routine was to start the thread execution immediately and since a listen on a busy port will bail out instantly (no timeout-for that one) at the return of the sleep you can test if the listen failed or not. I agree that on a heavy server load, there is no guarantee the the new thread will execute immediately and that 100ms scan be too short. You could also just put the setting of Factive in the server thread instead of the main thread, synchronize(SetActive()) if need be. I think that is what you meant with
Quote
The Active property is set after connection in the socket thread now.
but that change didn't make it to svn, I think.
Latest svn still allows to start several servers listening on the same port without any message on the servers that failed to listen on the port.
Quote
An exception will cause a GUI library include. On the client side, the Application.MessageBox is used instead of raise exception.create(). Because there should not be the ok and cancel button in the raise exception in Lazarus.
Exceptions don't cause a GUI include. A plain console program can also use exceptions. The OK and cancel button is only displayed for exceptions that are not caught in the program. A console program will stop and dump a backtrace if the exception isn't caught. Nothing stops you from doing a try .. except Application.MessageBox end;

jixian.yang

  • Full Member
  • ***
  • Posts: 173
Re: DataSnap Alternative for Lazarus
« Reply #19 on: November 06, 2011, 03:50:47 pm »
Quote
1) note the inversion of the files dd/mm/yyyy and yyyy-mm-dd. Setting DateSeparator := '-'; results in dd-mm-yyyy which is not compatible with yyyy-mmm-dd. As a result displaying a date now also raises an exception.
2) I don't want to change the default date format since that affects also the display and entry of dates.

In a n-tier implementation you should standardize the date format between client and server and leave the display/entry format to the client default settings. Since the ISO 8601 yyyy-mm-dd hh:mm:ss format is recognized by all db servers, you could as well use that format to communicate between client and server.

A similar issue exists with the decimal separator. In my country it is a "," and I can't change a floating point value. It returns a "syntax error at ","". So their also you need to convert to a "." in the communication between client and server. And drop the thousand separator that is used in some locales.

There should be the client format. Fixed.

Quote
I don't see how a 100ms sleep in the main thread would affect the multi second select time-out in a different thread. The idea of the sleep in the thread creation routine was to start the thread execution immediately and since a listen on a busy port will bail out instantly (no timeout-for that one) at the return of the sleep you can test if the listen failed or not. I agree that on a heavy server load, there is no guarantee the the new thread will execute immediately and that 100ms scan be too short. You could also just put the setting of Factive in the server thread instead of the main thread, synchronize(SetActive()) if need be. I think that is what you meant with

The Sleep(100) is required to get the Active flag which is changed in the socket thread. Fixed. But the Active is only write by the socket thread, it is safe.

Quote
but that change didn't make it to svn, I think.
Latest svn still allows to start several servers listening on the same port without any message on the servers that failed to listen on the port.

Now there is.

Quote
Exceptions don't cause a GUI include. A plain console program can also use exceptions. The OK and cancel button is only displayed for exceptions that are not caught in the program. A console program will stop and dump a backtrace if the exception isn't caught. Nothing stops you from doing a try .. except Application.MessageBox end;

It should be accepted.  There is no Application.MessageBox in the component but in the demo.





ludob

  • Hero Member
  • *****
  • Posts: 1173
Re: DataSnap Alternative for Lazarus
« Reply #20 on: November 06, 2011, 05:41:26 pm »
That fixed all issues :)

One small change I had to make to TSSocketServer.Listen. On a slow system the bind took slightly longer than 100ms and Active wasn't set yet. This worked for me:
Code: [Select]
procedure TSSocketServer.Listen;
const TIMEOUT=10;
var count:integer;
begin
  count:=TIMEOUT;
  FListenSrvThread := TSrvThread.Create(Self);
  while not Active and (count>0) do
    begin
    Sleep(100);
    count:=count-1;
    end;
  if not Active then
    RaiseListenError;
end;


jixian.yang

  • Full Member
  • ***
  • Posts: 173
Re: DataSnap Alternative for Lazarus
« Reply #21 on: November 07, 2011, 02:06:00 am »
Quote
That fixed all issues :)

One small change I had to make to TSSocketServer.Listen. On a slow system the bind took slightly longer than 100ms and Active wasn't set yet. This worked for me:
Code: [Select]
Code: [Select]
procedure TSSocketServer.Listen;
const TIMEOUT=10;
var count:integer;
begin
  count:=TIMEOUT;
  FListenSrvThread := TSrvThread.Create(Self);
  while not Active and (count>0) do
    begin
    Sleep(100);
    count:=count-1;
    end;
  if not Active then
    RaiseListenError;
end;

For this reason, it should be handled when thread terminated.
Now the exception raised in the event of thread onterminate by reading the flag:

Code: [Select]
procedure TSSocketServer.OnListenerTerminate(Sender: TObject);
begin
  if FListenSrvThread.ListenFailed then
    RaiseListenError;
end;

ludob

  • Hero Member
  • *****
  • Posts: 1173
Re: DataSnap Alternative for Lazarus
« Reply #22 on: November 07, 2011, 11:57:19 am »
Quote
Now the exception raised in the event of thread onterminate by reading the flag
OnTerminate is run in the main thread (synchronize) and there is nobody to catch the exception. As a result, the Exception is re-raised in the thread where nobody is catching it neither. The standard Lazarus "OK cancel" window is created from the thread without synchronize and a second EThread exception is generated "CheckSynchronize called from non-main thread" and the program aborts.
OnTerminate could set a ListenFailed flag in TSSocketServer which has to be checked later on (timer, requires LCL). If you don't want to use sleep, I only see a waitable object (semaphore fe.) . Using TApplication.QueueAsyncCall would also require the LCL.
As I wrote before sleep is the easy solution (not perfect). TSSocketServer.Listen returns with a valid FActive or raises an exception which allows for the program to act upon failure: show the exception, try another port, retry a little later...

jixian.yang

  • Full Member
  • ***
  • Posts: 173
Re: DataSnap Alternative for Lazarus
« Reply #23 on: November 08, 2011, 10:02:28 am »
Quote
OnTerminate is run in the main thread (synchronize) and there is nobody to catch the exception. As a result, the Exception is re-raised in the thread where nobody is catching it neither. The standard Lazarus "OK cancel" window is created from the thread without synchronize and a second EThread exception is generated "CheckSynchronize called from non-main thread" and the program aborts.
OnTerminate could set a ListenFailed flag in TSSocketServer which has to be checked later on (timer, requires LCL). If you don't want to use sleep, I only see a waitable object (semaphore fe.) . Using TApplication.QueueAsyncCall would also require the LCL.
As I wrote before sleep is the easy solution (not perfect). TSSocketServer.Listen returns with a valid FActive or raises an exception which allows for the program to act upon failure: show the exception, try another port, retry a little later...

Thanks.

The idea is absolutely better than raising exception on terminate.




haword

  • New Member
  • *
  • Posts: 13
Re: DataSnap Alternative for Lazarus
« Reply #24 on: December 20, 2011, 10:42:34 am »
Hi. I like you component, but component not compress transmitted data :( You have in plans add compression transmitted data?

teos

  • Full Member
  • ***
  • Posts: 161
Re: DataSnap Alternative for Lazarus
« Reply #25 on: August 21, 2012, 04:29:06 pm »
I have solved several places in code where the defines are the wrong way around and not compatible between Delphi 2007 and Lazarus.

I keep switching the code within the compiler directives..

The error that I cannot find is

ServerProc.pas(1160,28) Error: function header doesn't match any method of this class "procedure DoInternalSpecialSQL(Byte;AnsiString;SQLStyle;AnsiString):Boolean;"

Especially because the next line is:
ServerProc.pas(156,14) Hint: Found declaration: procedure DoInternalSpecialSQL(Byte;AnsiString;SQLStyle;AnsiString):Boolean;

Any help is higly appericiated.

nullpointer

  • New Member
  • *
  • Posts: 40
  • impossible is nothing
    • tauhidslab
Re: DataSnap Alternative for Lazarus
« Reply #26 on: June 28, 2017, 06:37:09 am »
i got an error message MemDBUtils

{$IFDEF OverRad2k7}
          DataSet.Bookmark := ABookmark;
{$ELSE}
DataSet.Bookmark := PAnsiChar(ABookmark);
{$ENDIF}         

Thaddy

  • Hero Member
  • *****
  • Posts: 17476
  • Ceterum censeo Trumpum esse delendum (Tnx Charlie)
Re: DataSnap Alternative for Lazarus
« Reply #27 on: June 28, 2017, 07:29:33 am »
See the release documentation for 3.0.0-3.0.2.
This is a breaking change for TBookMark.
http://wiki.freepascal.org/User_Changes_3.0#TBookmark_TBookmarkstr_and_TDataset.Bookmark_change_to_Delphi2009.2B_compatible_definitions

The author should update his code accordingly.

There are three options:
- Replace TBookmark ocurrances with TBookMarkStr. Quick fix, but generates deprecated warning
- Replace TBookMark (ansi string type) with the new TBookmark (Tbytes type), slightly more involved but the preferred solution.This is also D2009+ compatible.
- Keep using 2.6.4 for affected projects.


I opened a discussion on the project page on sourceforge although the code hasn't been touched for two years.
« Last Edit: June 28, 2017, 07:52:14 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

nullpointer

  • New Member
  • *
  • Posts: 40
  • impossible is nothing
    • tauhidslab
Re: DataSnap Alternative for Lazarus
« Reply #28 on: June 28, 2017, 07:52:15 am »
See the release documentation for 3.0.2.
This is a breaking change for TBookMark.
http://wiki.freepascal.org/User_Changes_3.0#TBookmark_TBookmarkstr_and_TDataset.Bookmark_change_to_Delphi2009.2B_compatible_definitions

The author should update his code accordingly.

There are two options:
- Replace TBookmark ocurrances with TBookMarkStr. Quick fix, but generates deprecated warning
- Replace TBookMark (ansi string type) with the new TBookmark (Tbytes type), slightly more involved but the preferred solution.
This is also D2009+ compatible.

I opened a discussion on the project page on sourceforge although the code hasn't been touched for two years.

thank you thaddy you save my time.  :D :D

nullpointer

  • New Member
  • *
  • Posts: 40
  • impossible is nothing
    • tauhidslab
Re: DataSnap Alternative for Lazarus
« Reply #29 on: June 29, 2017, 03:00:30 am »
i try to create insert process but nothing found the ExecSQL procedure on TOnlineQuery like ZQuery or AdoQuery.  :'( 
how to ExecSQL like ZQuery or AdoQuery on TOnlineQuery?

 

TinyPortal © 2005-2018