#1 2010-12-12 20:21:06

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Load/save image

Hi,

I have TSQLRecord with Image property. I need save an image from TImage component to database then I need load it from database and show it on TImage. To save the image I use this function:

var
  ClientRecord: TSQLClientiRecord;
  doc: RawByteString;
  pic: TSynPicture;
  stream: TMemoryStream;
...
...
...

        pic := TSynPicture.Create;
        try
          ImageDoc.Picture.Bitmap.SaveToStream(stream);
          pic.LoadFromStream(stream);
          if not pic.Empty then
            begin
              SaveAsRawByteString(pic,doc,gptJPG,80,300);
              ClientRecord.Documento := doc;
            end
          else
            begin
              ClientRecord.Documento := '';
            end;
        finally
          Pic.Free;
        end;

...
...
...

However I have an error when I try to call  Database.Add(ClientRecord, true)  function.

Can you help me with a fast function to load and save an TImage image?

thanks

Last edited by array81 (2010-12-13 17:13:09)

Offline

#2 2010-12-13 08:06:50

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

See  http://synopse.info/forum/viewtopic.php?pid=940#p940 about how to embed data/files in records.

See the MainDemo sample: there is a field storing a picture inside all records.

  TSQLMemo = class(TSQLFile)
  public
    fContent: RawUTF8;
  published
    property Name: RawUTF8 read fName write fName;
    property Created: TTimeLog read fCreated write fCreated;
    property Modified: TTimeLog read fModified write fModified;
    property Picture: TSQLRawBlob read fPicture write fPicture;
    property Content: RawUTF8 read fContent write fContent;
    property KeyWords: RawUTF8 read fKeyWords write fKeyWords;
    property SignatureTime: TTimeLog read fSignatureTime write fSignatureTime;
    property Signature: RawUTF8 read fSignature write fSignature;
  end;

Then in FileMain.pas, here is how the picture is stored in the database:

procedure TMainForm.ActionClick(Sender: TObject;
  const RecordClass: TSQLRecordClass; ActionValue: integer);
  (...)
      faCreate:
        if ((RecordClass=TSQLData) or (RecordClass=TSQLSafeData)) then
        if Open then begin
          Rec.fName := S2U(ExtractFileName(FN));
          if RecordClass=TSQLData then
          with TSQLData(Rec) do begin
            Data := StringFromFile(FN);
            if TSynPicture.IsPicture(FN)<>nil then
              EditForm.LoadPicture(FN,RawByteString(fPicture));
          end else
          with TSQLSafeData(Rec) do begin
            fData := StringFromFile(FN);
            if not Cypher(CaptionName,fData,true) then
              exit;
          end;
        end else
          exit;
  (...)

This called the TEditForm.LoadPicture method from FileEdit.pas unit:

function TEditForm.LoadPicture(const FileName: TFileName; var Picture: RawByteString): boolean;
var Pic: TSynPicture;
begin
  result := false;
  if not FileExists(FileName) then
    exit;
  Pic := TSynPicture.Create;
  try
    Pic.LoadFromFile(FileName);
    if Pic.Empty then
      exit;
    SaveAsRawByteString(Pic,Picture,gptJPG,80,300);
    result := true;
  finally
    Pic.Free;
  end;
end;

Offline

#3 2010-12-13 10:00:44

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

Yes, I just see your main demo but it's very confused for me (I'm not a expert), so I cannot extract a simple code to save/load an image or a file sad

Offline

#4 2010-12-13 14:44:52

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

Here are the basic steps:

1) define the Picture as such a property in a TSQLRecord descendant:

property Picture: TSQLRawBlob read fPicture write fPicture;

2) handle this Blob field with RetrieveBlob() and UpdateBlob() methods

3) Use SaveAsRawByteString() to transform a TPicture into a TSQLRawBlob

4) See the PictureToBitmap() function in FileClient.pas to guess how to create a TPicture from a TSQLRawBlob

Offline

#5 2010-12-13 16:58:37

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

I have this code:

1) Define my TSQLRecord:

  TSQLClientsRecord = class(TSQLRecord)
  private
    fname: RawUTF8;
    fdate: TDateTime;
    fpicture: TSQLRawBlob;
  published
    property Name: RawUTF8 read fnamewrite fname;
    property Date: TDateTime read fdatewrite fdate;
    property Picture: TSQLRawBlob read fpicture write fpicture;
  end;

2) Write new record on my database:

var
  ClientsRecord: TSQLClientsRecord;
  pic: RawByteString;
begin
  ClientsRecord := TSQLClientsRecord.Create;
    try
      ClientsRecord.Name:= StringToUTF8(edtName.Text);
      ClientsRecord.Date:= edtDate.Date;

      SaveAsRawByteString(ImageClient.Picture, pic, gptJPG, 80, 300);

      ClientsRecord.Picture := pic;

      if Database.Add(ClientRecord, true) = 0 then
        begin
          MessageBox(0, 'Problems!', 'Try', MB_OK + MB_ICONSTOP);
        end
    finally
      ClientsRecord.Free;
    end;
end;

This code don't work, I think the problem is ClientsRecord.Picture := pic; because I have read on your documentation that ADD method "the BLOB fields values are not set by this method, to preserve bandwidth".

So I have try this code:

var
  ClientsRecord: TSQLClientsRecord;
  pic: RawByteString;
begin
  ClientsRecord := TSQLClientsRecord.Create;
    try
      ClientsRecord.Name:= StringToUTF8(edtName.Text);
      ClientsRecord.Date:= edtDate.Date;

      // I have removed TSQLRawBlob field

      if Database.Add(ClientRecord, true) = 0 then
        begin
          MessageBox(0, 'Problems!', 'Try', MB_OK + MB_ICONSTOP);
        end
    finally
      ClientsRecord.Free;
    end;
end;

to update all the fields except TSQLRawBlob (and use UpdateBlob() after) but in this way I have another problem I thinks because my TSQLClientsRecord have the Picture property and this is not define before call Database.Add.
I think this is my problem, I have understand how use TSQLRecord when I can update or add all fields of records but in my case I cannot do it.
Any idea?

Thanks for your help.

Offline

#6 2010-12-13 17:59:01

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

You can either use:

var
  ClientsRecord: TSQLClientsRecord;
  pic: RawByteString;
begin
  SaveAsRawByteString(ImageClient.Picture, pic, gptJPG, 80, 300);
  ClientsRecord := TSQLClientsRecord.Create;
    try
      ClientsRecord.Name:= StringToUTF8(edtName.Text);
      ClientsRecord.Date:= edtDate.Date;
      if (Database.Add(ClientRecord, true) = 0) or
         not Database.UpdateBlob(TSQLClientsRecord,ClientRecord.ID,'Picture',pic) then
          MessageBox(0, 'Problems!', 'Try', MB_OK + MB_ICONSTOP);
    finally
      ClientsRecord.Free;
    end;
end;

 

Either (works only if Database inherits from TSQLRestClientURI):

var
  ClientsRecord: TSQLClientsRecord;
  pic: RawByteString;
begin
  SaveAsRawByteString(ImageClient.Picture, pic, gptJPG, 80, 300);
  ClientsRecord := TSQLClientsRecord.Create;
    try
      ClientsRecord.Name:= StringToUTF8(edtName.Text);
      ClientsRecord.Date:= edtDate.Date;
      ClientsRecord.Picture := pic;
      if (Database.Add(ClientRecord, true) = 0) or
         not Database.UpdateBlobFields(ClientRecord) then
          MessageBox(0, 'Problems!', 'Try', MB_OK + MB_ICONSTOP);
    finally
      ClientsRecord.Free;
    end;
end;

 

Either (works only if Database inherits from TSQLRestClientURI):

1. when you initialize your Database:

 DataBase := ....Create(....);
 DataBase.ForceBlobTransfert := true;

2. Then you can set the Picture property, and just call Add():

var
  ClientsRecord: TSQLClientsRecord;
  pic: RawByteString;
begin
  SaveAsRawByteString(ImageClient.Picture, pic, gptJPG, 80, 300);
  ClientsRecord := TSQLClientsRecord.Create;
    try
      ClientsRecord.Name:= StringToUTF8(edtName.Text);
      ClientsRecord.Date:= edtDate.Date;
      ClientsRecord.Picture := pic;
      if (Database.Add(ClientRecord, true) = 0) then
          MessageBox(0, 'Problems!', 'Try', MB_OK + MB_ICONSTOP);
    finally
      ClientsRecord.Free;
    end;
end;

Offline

#7 2010-12-14 08:38:44

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

Thanks, the first code works very well. But I have another question: I'm develop a small application, the user can choose if use it as standalone application with a local file as database or use it as client/server application by LAN (the client use a file database on server).
So I need of a Database class that support both two of database (local file and client/server with database file on server). Do you have any advice about it?

Offline

#8 2010-12-14 09:27:27

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

Define your Database as

Database: TSQLRestClient;

Then, when you create the Database instance, use either:
- TSQLRestClientDB for local file access;
- a TSQLRestClientURI child, depending on the communication protocol used for Client/Server access, i.e. either TSQLRestClientURIMessage, TSQLRestClientURINamedPipe or TSQLite3HttpClient. I would recommend using TSQLite3HttpClient for easy network handling (GDI messages are not transmitted over the network, and Named Pipes have some security issue with Vista/Seven version of Windows).

But you'll also have to write a Server application, relying on a TSQLRestServerDB instance.

The whole code could be the same for the client, either with local direct access or remote access via the network, depending on the exact class of the Database instance created.

Offline

#9 2010-12-14 13:39:37

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

Thanks I will try. Thanks again.

Offline

#10 2010-12-14 20:44:57

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

Another think. I like create only an application. The user can use it as: 1) Standalone application (with local database), 2) Client/Server application by LAN (with database file on server).
In case 2) the same application can works as client (on client computer) and as server (on server computer).

Is't possible with only a database class (without change the code from standalone, client ot server)?

Offline

#11 2010-12-15 07:08:58

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

It's perfectly possible to have the same application running as stand-alone, client or server. It does make sense, because the same code will be share for the three way of running.

The way your application is behaving will depend on the TSQLRest class instances created.
- a TSQLRestClientDB for the stand-alone mode;
- a TSQLite3HttpServer for the server mode;
- a TSQLite3HttpClient for the client mode.

Offline

#12 2011-01-23 17:58:15

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

I'm working to create my application. I need of application that can work as Standalone, Client or Server (the user can choose if use as standalone application or Client/Server application, in this case he can choose if use it as client or server). Until now I have develop my application as standalone application only, now I want add client/server support.

In your last post you have told me:

ab wrote:

The way your application is behaving will depend on the TSQLRest class instances created.
- a TSQLRestClientDB for the stand-alone mode;
- a TSQLite3HttpServer for the server mode;
- a TSQLite3HttpClient for the client mode.

So I have write this code:

var
  Server: TSQLite3HttpServer;
  Database: TSQLRest;
  Model: TSQLModel;
// STANDALONE APPLICATION
procedure TMainForm.LoadLocalDatabase(Filename: string; Overwrite: Boolean);
begin
  if FileExists(Filename) then
    begin
      if Overwrite then
        begin
          DeleteFile(Filename);
        end;
    end;

  if Model <> nil then
    Model.Free;

  if Database <> nil then
    Database.Free;

  Model := TSQLModel.Create([TSQLContatti, TSQLProgetti, TSQLProgettiClienti, TSQLProgettiUtenti, TSQLProgettiAttivita, TSQLProgettiFlussi, TSQLProgettiDocumenti, TSQLProgettiFatture, TSQLProgettiFSS]);
  Database := TSQLRestClientDB.Create(Model, nil, Filename, TSQLRestServerDB);

  TSQLRestServerDB(TSQLRestClientDB(Database).Server).CreateMissingTables(0);
end;

// CLIENT/SERVER APPLICATION (CLIENT)
procedure TMainForm.LoadClientDatabase(Server: string; Port: Integer);
begin
  if Model <> nil then
    Model.Free;

  if Database <> nil then
    Database.Free;

  Model := TSQLModel.Create([TSQLContatti, TSQLProgetti, TSQLProgettiClienti, TSQLProgettiUtenti, TSQLProgettiAttivita, TSQLProgettiFlussi, TSQLProgettiDocumenti, TSQLProgettiFatture, TSQLProgettiFSS]);

  Database := TSQLite3HttpClient.Create(Server, IntToStr(Port), Model);
  TSQLRestServerDB(TSQLRestClientDB(Database).Server).CreateMissingTables(0);
end;

// CLIENT/SERVER APPLICATION (SERVER)
procedure TMainForm.LoadServerDatabase(Port: Integer; Filename: string; Overwrite: Boolean);
begin
  if FileExists(Filename) then
    begin
      if Overwrite then
        begin
          DeleteFile(Filename);
        end;
    end;

  if Model <> nil then
    Model.Free;

  if Database <> nil then
    Database.Free;

  if Server <> nil then
    Server.Free;

  Model := TSQLModel.Create([TSQLContatti, TSQLProgetti, TSQLProgettiClienti, TSQLProgettiUtenti, TSQLProgettiAttivita, TSQLProgettiFlussi, TSQLProgettiDocumenti, TSQLProgettiFatture, TSQLProgettiFSS]);
  Database := TSQLRestServerDB.Create(Model, Filename);

  Database.CreateMissingTables(0);
  Server := TSQLite3HttpServer.Create(IntToStr(Port), DB);
end;

Is this code right? I have some problem with my "standalone" code, for example Database.ExecuteList and Database.EngineExecute are not found. With only "standalone" application I used:

var
  Database: TSQLRestClient;

but now I need use

var
  Database: TSQLRest;

So I think there is an error on my code. Can you help me?

NOTE: when my application works as server must be a server for other clients application but I need also use it as standalone application (on server computer). I hope you understand it.

Last edited by array81 (2011-01-23 22:59:37)

Offline

#13 2011-01-24 06:58:07

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

All business logic must be made on the server side only.
For example, CreateMissingTable must be called in the server or the standalone application only.

You should therefore make a difference between server or standalone on one part, and client on the other part.

Your Database should be indeed declared as Database: TSQLRestClient.
For the client, use a dedicated ServerDatabase: TSQLRestServerDB instance.
Then for the standalone, use the

On server computer, you need to launch a client, instead of a standalone application.
If both standalone and server applications access the DB file at the same time, there could be some concurrency race problems. I understand than you close the server before running the stand alone version... but perhaps launching the client could be better.
The stand-alone application could make sense only in case of debugging, or as a "demo" version.

And as I wrote in the main demo presentation article, use a common function to create the TSQLModel.
So you'll have less duplicated code, and your app will be less error prone.

Offline

#14 2011-01-24 08:38:07

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

I hope I have uderstand. What do you think about this new code (only LoadServerDatabase us different):

var
  Server: TSQLite3HttpServer;
  Database: TSQLRestClient;
  DatabaseServer: TSQLRestServerDB;
  Model: TSQLModel;
procedure TMainForm.LoadServerDatabase(Port: Integer; Filename: string; Overwrite: Boolean);
begin
  if FileExists(Filename) then
    begin
      if Overwrite then
        begin
          DeleteFile(Filename);
        end;
    end;

  if Model <> nil then
    Model.Free;

  if Database <> nil then
    Database.Free;

  if DatabaseServer <> nil then
    DatabaseServer.Free;

  if Server <> nil then
    Server.Free;

  Model := TSQLModel.Create([TSQLContatti, TSQLProgetti, TSQLProgettiClienti, TSQLProgettiUtenti, TSQLProgettiAttivita, TSQLProgettiFlussi, TSQLProgettiDocumenti, TSQLProgettiFatture, TSQLProgettiFSS]);
  DatabaseServer := TSQLRestServerDB.Create(Model, Filename);

  if DatabaseServer <> nil then
    begin
      DatabaseServer.CreateMissingTables(0);
      Server := TSQLite3HttpServer.Create(IntToStr(Port), DatabaseServer);
    end;

  Database := TSQLRestClientDB.Create(Model, nil, Filename, TSQLRestServerDB);

  if Database <> nil then
    begin
      TSQLRestServerDB(TSQLRestClientDB(Database).Server).CreateMissingTables(0);
    end;
end;

In this way when my application works as server have 2 Database access (is it a problem?): Database as standalone application and DatabaseServer as server.
What are "concurrency race problems"? It is only a small decrease in performance or stability problem.


I think I just "use a common function to create the TSQLModel" or I don't undestand what you mean.

Offline

#15 2011-01-24 09:06:15

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

About TSQLModel:

function GetDatabaseModel: TSQLModel;
begin
  result := TSQLModel.Create([TSQLContatti, TSQLProgetti, TSQLProgettiClienti, TSQLProgettiUtenti, TSQLProgettiAttivita, TSQLProgettiFlussi, TSQLProgettiDocumenti, TSQLProgettiFatture, TSQLProgettiFSS]);
end;

   (...)
   Model := GetDatabaseModel;
   (...)

It doesn't make sense to test for DatabaseServer<>nil or Database<>nil after a Create method call: by design (like any other Delphi class), it will create an instance, so it will never be nil. In case of an error, it will raise an exception.
So you should put a try..except block to catch any error, and don't check for nil.

Why are you creating a TSQLRestServerDB  then a TSQLRestClientDB instance in your code?
You shouldn't. It will create TWO TSQLRestServerDB instances at the same time...
And you're still calling CreateMissingTable two times...

So you should have better written:

try
  Model := GetDatabaseModel;
  Database := TSQLRestClientDB.Create(Model, nil, Filename, TSQLRestServerDB);
  DatabaseServer := TSQLRestClientDB(Database).Server;
  DatabaseServer.CreateMissingTables(0);
  Server := TSQLite3HttpServer.Create(IntToStr(Port), DatabaseServer);
except
  on E: Exception do
    // handle initialization error here
end;

You could also have created your own TSQLRestServerDB child, calling CreateMissingTables and running a TSQLite3HttpServer instance directly.
This is the way I use it normally: in fact, having its own TSQLRestServerDB descendant allow to put all your business logic (i.e. all that should be done server-side) implemented in a dedicated class, with full direct access to the SQL engine.
And you can even create multiple instance of the same server, at the same time, if you want, to access multiple database files for example.
It's always better for your application architecture to make all your logic in classes, with properties, instead of using globals.

Offline

#16 2011-01-26 08:28:45

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

Thanks it works. I have only a problem of "SPEED" when use client/server by my LAN (my LAN use Windows XP and Windows 7 computers).
My TEST database is only 500 (each tables have only 2/3 rows) kb but when my client need read/write data from server need of 4/5 seconds. (on standalone mode <1 second)
Is it normal? Do you have some suggestions?
I will check to SQL code but I don't think I will found much unnecessary code.

Last edited by array81 (2011-01-26 08:29:32)

Offline

#17 2011-01-26 08:53:17

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

Do you use:

DataBase.ForceBlobTransfert := true;

?

In this case, this could be the problem: all pictures are retrieved when you get all records in any FillPrepare() loop, for instance.
Locally, it's not a problem, but over the network, your 100Mb or 1Gb link is not big enough!

So the solution is to let ForceBlobTransfert to false, then use explicit RetrieveBlob() method calls to get the picture data.

Offline

#18 2011-01-26 09:12:51

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

NO. I use alway RetrieveBlob() when I need of it.

I have a mainform that other 2 form (project and users).

On Clients form I use this piece of code to show data of select user:

      ContattoRecord := TSQLContatti.Create(Database,'ID="%"',[IntToStr(EditItem)]);
      Database.RetrieveBlob(TSQLContatti, ContattoRecord.ID, 'Documento', doc);
      ContattoRecord.Documento := doc;
      Database.RetrieveBlob(TSQLContatti, ContattoRecord.ID, 'FatLogo', doc);
      ContattoRecord.FatLogo := doc;
      Database.RetrieveBlob(TSQLContatti, ContattoRecord.ID, 'FatIntestazioneUtente', ms);

Note: I have 3 test client, only for 1 client I have set 'Documento', 'FatLogo', 'FatIntestazioneUtente' but I have the some problem with all them (read/write lag about 2/3 secons).

In Project form I use about 10 code like this:

 TavolaUtenti := Database.ExecuteList([], 'SELECT Contatti.ID, Contatti.IntNome, ProgettiUtenti.ID FROM Contatti LEFT JOIN ProgettiUtenti ON ProgettiUtenti.IDUtente=Contatti.ID WHERE ProgettiUtenti.IDProgetto="' + IntToStr(EditItem) + '" ORDER BY Contatti.IntNome');

To read the data (lag 2/3 seconds) and about 5 code as these:

  for e := 0 to grdAttivita.RowCount - 1 do
    begin
      if (grdAttivita.Cell[3, e].AsString = '') or
         (grdAttivita.Cell[4, e].AsString = '') then
         Continue;

      ProgettoAttivitaRecord := TSQLProgettiAttivita.Create;

      try
        ProgettoAttivitaRecord.IDProgetto := EditItem;
        if grdAttivita.Cell[4, e].AsString <> '' then
          ProgettoAttivitaRecord.IDUtente := IDUtenti.Counter[IDUtenti.IndexOf(grdAttivita.Cell[4, e].AsString)];
        ProgettoAttivitaRecord.Stato := grdAttivita.Cell[2, e].AsInteger;
        ProgettoAttivitaRecord.Oggetto := StringToUTF8(grdAttivita.Cell[3, e].AsString);
        ProgettoAttivitaRecord.Data := grdAttivita.Cell[5, e].AsDateTime;
        ProgettoAttivitaRecord.ID := grdAttivita.Cell[0, e].AsInteger;

        if grdAttivita.Cell[0, e].AsString = '' then
          begin
            if Database.Add(ProgettoAttivitaRecord, true) = 0 then
              begin
                ErrorDB := True;
              end;
          end
        else
          begin
            ProgettoAttivitaRecord.ID := grdAttivita.Cell[0, e].AsInteger;

            if not Database.Update(ProgettoAttivitaRecord) then
              begin
                ErrorDB := True;
              end;
          end;
      finally
        ProgettoAttivitaRecord.Free;
      end;
    end;

to save the data (lag about 4/5 seconds). As standalone application I don't have any problems.

Offline

#19 2011-01-26 13:45:15

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

You should use a transaction to speed up writing.

  Database.BeginTransaction;
try
  /// add some records
finally
  Database.Commit;
end;

And did you try your client application on the same computer than the server?

How are you creating the client classes?

What is your antivirus software? Did you try turning http inspection off?

Offline

#20 2011-01-26 16:13:38

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

And did you try your client application on the same computer than the server?

No I did, I have tested my application in 2 computers (one for client and one for server). I have made my test in 2 different LAN: one LAN with 3 computers (all Windows 7) and one LAN with 7 computers (all Windows XP Professional).

How are you creating the client classes?

I'm not sure I'm undestand your question. I have used this code:

var
  Server: TSQLite3HttpServer;
  Database: TSQLRestClient;
  DatabaseServer: TSQLRestServerDB;

// STANDALONE APPLICATION
procedure TMainForm.LoadLocalDatabase(Filename: string; Overwrite: Boolean);
begin
  if FileExists(Filename) then
    begin
      if Overwrite then
        begin
          DeleteFile(Filename);
        end;
    end;

  if Database <> nil then
    Database.Free;

  try
    Database := TSQLRestClientDB.Create(Model, nil, Filename, TSQLRestServerDB);
    TSQLRestServerDB(TSQLRestClientDB(Database).Server).CreateMissingTables(0);
    LoadData();
  except
    //on E: Exception do
    // handle initialization error here
  end;
end;

// CLIENT/SERVER APPLICATION (CLIENT)
procedure TMainForm.LoadClientDatabase(Server: string; Port: Integer);
begin
  if Database <> nil then
    Database.Free;

  try
    Database := TSQLite3HttpClient.Create(Server, IntToStr(Port), Model);
    LoadData();
  except
    //on E: Exception do
    // handle initialization error here
  end;
end;

// CLIENT/SERVER APPLICATION (SERVER)
procedure TMainForm.LoadServerDatabase(Port: Integer; Filename: string; Overwrite: Boolean);
begin
  if FileExists(Filename) then
    begin
      if Overwrite then
        begin
          DeleteFile(Filename);
        end;
    end;

  if Database <> nil then
    Database.Free;

  try
    Database := TSQLRestClientDB.Create(Model, nil, Filename, TSQLRestServerDB);
    DatabaseServer := TSQLRestClientDB(Database).Server;
    DatabaseServer.CreateMissingTables(0);
    Server := TSQLite3HttpServer.Create(IntToStr(Port), DatabaseServer);

    LoadData;
  except
    //on E: Exception do
    // handle initialization error here
  end;
end;

I use LoadData() function to load the data from database and put them on a grid. Note: I use "Model := GetDatabaseModel;" when mainform is create.

What is your antivirus software?

In all computers there is Microsoft Essential Security and Windows Firewall.

Did you try turning http inspection off?

I don't have found this option on Microsoft Essential Security.

You should use a transaction to speed up writing. (Database.BeginTransaction;)

When I need write many data I need use Database.BeginTransaction; Is it right? I will tried it.

Thanks, other suggestions are welcome.

Offline

#21 2011-01-26 18:05:06

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

I have check the framework code but I cannot found BeginTransaction function for database object...
I think I don't understand your last post.

Offline

#22 2011-01-27 04:39:50

longge007
Member
Registered: 2010-06-22
Posts: 107

Re: Load/save image

array81 wrote:

I have check the framework code but I cannot found BeginTransaction function for database object...
I think I don't understand your last post.

when on client user add more records or update more records ,the table is locked,other user can't get records.
in this Framework
database.Transactionbegin(TSQLTableclass)
beginTransaction is in order to inform the Table to do something
commitTransaction is in order to ENd your opening the table,

in this Framework
Database.commit
sometimes the Rollback is used .

Last edited by longge007 (2011-01-27 04:45:31)

Offline

#23 2011-01-27 08:58:03

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

So I need use a code like this:

   database.Transactionbegin(TSQLProgettoAttivita)
   try
        if grdAttivita.Cell[0, e].AsString = '' then
          begin
            if Database.Add(ProgettoAttivitaRecord, true) = 0 then
              begin
                ErrorDB := True;
              end;
          end
        else
          begin
            ProgettoAttivitaRecord.ID := grdAttivita.Cell[0, e].AsInteger;

            if not Database.Update(ProgettoAttivitaRecord) then
              begin
                ErrorDB := True;
              end;
          end;
   finally
      Database.commit 
   end;

right?

Offline

#24 2011-01-27 14:08:55

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

Yes, you're right, it was TransactionBegin method.
Sorry I wrote this by memory wink

And the try..finally block above is right.

Offline

#25 2011-01-27 15:23:00

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

OK, I have 2 questions:

1) Do I need use Transactionbegin also when I use Dtabase.Delete(...) function?
2) When I have more pieces of code like my last post I need Transactionbegin only one time (and I put all my code inside try...finally) or I need use Transactionbegin one time for each piace?

I have add Transactionbegin in all my code but the result is the same. When I use my application as standalone all works, when I use as client/server (I use 2 different computers) all works but with this horrible lag (between 2-5 seconds).

Other suggestions are welcome.

Thanks

PS if you want (and you tell me how) I can send you 2 small SWF video of standalone and client application to see the lag.

Last edited by array81 (2011-01-27 16:27:27)

Offline

#26 2011-01-27 17:31:14

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

Transactions are a standard SQL feature.
They will speed up data modification: update, insert or delete.

About the client speed, I guess you're running a lot of requests during your queries.
What is your network traffic generated by the applications?
Use ProcessExplorer to retrieve more info.

What are the info that your browser displayed when you enter this URI:

http://localhost:8080/root/stat

here, 8080 is the port number of your server, root is the URI root (by default), and stat is a standard service retrieving some statistics.

A typical response is:

Clients now=1 max=2
Data in=352 B out=963 B
Requests=6 Updates=0 Invalid=6
Time spent in requests = 200us

Offline

#27 2011-01-27 21:04:47

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

OK I have make some test about my application. I have used a HTTP traffic analizer to know the real traffic of my application.

TEST
I have started Server and Client application then I have connect Client with Server, after this I have only open a windows and retrive some data (only readb data) from database.

RESULT
Result of my HTTP traffic analizer: 12.57 kB in 6.79 seconds. 6.79 seconds!!!

Reselt of http://localhost:8080/root/stat

Clients now=1 max=1
Data in=5784 B out=3969 B
Requests=27 Updates=0 Invalid=0
Time spent in requests = 26.41ms

This is HTTP traffic analizer log:

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 92
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 92
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT Contatti.ID, Contatti.IntNome, Contatti.Ruolo FROM Contatti ORDER BY Contatti.IntNome
HTTP/1.1 400 OK
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 39
Content-Type: text/html
Connection: Keep-Alive

TSQLite3HttpServer Server Error 400<hr>HTTP/1.0 404 OK
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 39
Content-Type: text/html

TSQLite3HttpServer Server Error 404<hr>
GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 44
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive



GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 44
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT * FROM Progetti WHERE ID="1" LIMIT 1;
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 192
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=8,"Values"=["Descrizione","ID","Oggetto","Tipo","Fascicolo","DataInizio","DataFine","Stato",null,1,"prova","Accatastamento","123","2011-01-19T13:22:44","2011-01-19T13:22:44",0]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 196
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT Contatti.ID, Contatti.IntNome, Contatti.Ruolo FROM Contatti LEFT JOIN ProgettiClienti ON ProgettiClienti.IDCliente=Contatti.ID WHERE ProgettiClienti.IDProgetto="1" ORDER BY Contatti.IntNome
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 71
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=3,"Values"=["ID","IntNome","Ruolo",3,"Burbi Massimo",0]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 192
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT Contatti.ID, Contatti.IntNome, Contatti.Ruolo FROM Contatti LEFT JOIN ProgettiUtenti ON ProgettiUtenti.IDUtente=Contatti.ID WHERE ProgettiUtenti.IDProgetto="1" ORDER BY Contatti.IntNome
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 71
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=3,"Values"=["ID","IntNome","Ruolo",2,"Burbi Manuela",1]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 310
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT Contatti.ID, Contatti.IntNome, ProgettiAttivita.ID, ProgettiAttivita.IDProgetto, ProgettiAttivita.Oggetto, ProgettiAttivita.Data, ProgettiAttivita.Stato FROM Contatti LEFT JOIN ProgettiAttivita ON ProgettiAttivita.IDUtente=Contatti.ID WHERE ProgettiAttivita.IDProgetto="1" ORDER BY ProgettiAttivita.Data
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 178
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=7,"Values"=["ID","IntNome","ID","IDProgetto","Oggetto","Data","Stato",1,"Masci Martin",2,1,"asdfaaaa","2011-01-02",1,1,"Masci Martin",1,1,"123458","2011-01-26",1]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 306
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT ProgettiFlussi.ID, ProgettiFlussi.IDProgetto, ProgettiFlussi.IDUtente, ProgettiFlussi.IDCliente, ProgettiFlussi.Descrizione, ProgettiFlussi.Data, ProgettiFlussi.Importo, ProgettiFlussi.IDFattura, ProgettiFlussi.IVA FROM ProgettiFlussi WHERE ProgettiFlussi.IDProgetto="1" ORDER BY ProgettiFlussi.Data
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 201
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=9,"Values"=["ID","IDProgetto","IDUtente","IDCliente","Descrizione","Data","Importo","IDFattura","IVA",1,1,2,3,"prova","2011-01-10","100",1,0,2,1,2,3,"abc1234","2011-01-25","145.36",0,0]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 72
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT Contatti.ID, Contatti.IntNome FROM Contatti WHERE Contatti.ID="2"
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 61
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=2,"Values"=["ID","IntNome",2,"Burbi Manuela"]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 72
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT Contatti.ID, Contatti.IntNome FROM Contatti WHERE Contatti.ID="3"
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 61
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=2,"Values"=["ID","IntNome",3,"Burbi Massimo"]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 72
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT Contatti.ID, Contatti.IntNome FROM Contatti WHERE Contatti.ID="2"
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 61
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=2,"Values"=["ID","IntNome",2,"Burbi Manuela"]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 72
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive



GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 72
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT Contatti.ID, Contatti.IntNome FROM Contatti WHERE Contatti.ID="3"
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 61
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=2,"Values"=["ID","IntNome",3,"Burbi Massimo"]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 350
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT Contatti.ID, Contatti.IntNome, ProgettiDocumenti.ID, ProgettiDocumenti.IDProgetto, ProgettiDocumenti.Descrizione, ProgettiDocumenti.Data, ProgettiDocumenti.Filename, ProgettiDocumenti.Size FROM Contatti LEFT JOIN ProgettiDocumenti ON ProgettiDocumenti.IDUtente=Contatti.ID WHERE ProgettiDocumenti.IDProgetto="1" ORDER BY ProgettiDocumenti.Data
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 100
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=8,"Values"=["ID","IntNome","ID","IDProgetto","Descrizione","Data","Filename","Size"]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 261
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT ProgettiFatture.ID, ProgettiFatture.IDCliente, ProgettiFatture.IDUtente, ProgettiFatture.Oggetto, ProgettiFatture.Data, ProgettiFatture.Importo, ProgettiFatture.Spese FROM ProgettiFatture WHERE ProgettiFatture.IDProgetto="1" ORDER BY ProgettiFatture.Data
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 128
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=7,"Values"=["ID","IDCliente","IDUtente","Oggetto","Data","Importo","Spese",1,0,2,"prova","2011-01-15","100","0"]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 98
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT Contatti.ID, Contatti.IntNome FROM Contatti WHERE Contatti.ID="2" ORDER BY Contatti.IntNome
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 61
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=2,"Values"=["ID","IntNome",2,"Burbi Manuela"]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 180
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT Contatti.ID, Contatti.IntNome FROM Contatti LEFT JOIN ProgettiClienti ON ProgettiClienti.IDCliente=Contatti.ID WHERE ProgettiClienti.IDProgetto="1" ORDER BY Contatti.IntNome
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 61
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=2,"Values"=["ID","IntNome",3,"Burbi Massimo"]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 311
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT ProgettiFatture.ID, ProgettiFatture.IDCliente, ProgettiFatture.IDUtente, ProgettiFatture.Importo, ProgettiFatture.Spese, ProgettiFatture.IVA, ProgettiFatture.CAP, ProgettiFatture.Ritenuta, ProgettiFatture.RitenutaUsa FROM ProgettiFatture WHERE ProgettiFatture.IDProgetto="1" ORDER BY ProgettiFatture.Data
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 136
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=9,"Values"=["ID","IDCliente","IDUtente","Importo","Spese","IVA","CAP","Ritenuta","RitenutaUsa",1,0,2,"100","0",20,4,2,1]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 196
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT Contatti.ID, Contatti.IntNome, Contatti.Ruolo FROM Contatti LEFT JOIN ProgettiClienti ON ProgettiClienti.IDCliente=Contatti.ID WHERE ProgettiClienti.IDProgetto="1" ORDER BY Contatti.IntNome
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 71
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=3,"Values"=["ID","IntNome","Ruolo",3,"Burbi Massimo",0]}

GET root HTTP/1.1
Accept: */*
Host: 192.168.1.4
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 151
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive

SELECT ProgettiFlussi.Importo FROM ProgettiFlussi WHERE ProgettiFlussi.IDProgetto="1" AND ProgettiFlussi.IDCliente="3" AND ProgettiFlussi.IDFattura > 0
HTTP/1.1 200 OK
Server-InternalState: 2
X-Powered-By: SynCrtSock [url]http://synopse.info[/url]
Server: TSQLite3HttpServer
Content-Length: 44
Content-Type: application/json; charset=UTF-8
Connection: Keep-Alive

{"FieldCount"=1,"Values"=["Importo","100"]}

I don't understand where is the error/problem.

Offline

#28 2011-01-28 06:53:38

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

Time spent in requests = 26.41ms

There the problem is in the communication layer, not the database layer!

Did you try setting your AntiVirus off?

Use ProcessExplorer from http://technet.microsoft.com/en-us/sysi … s/bb896653 to check:
- how many threads are created on the server side;
- how many TCP/IP connections are created - there should be only one connection per client, kept alive during all handling (since there is a 20 seconds keep alive parameter value).

Offline

#29 2011-01-28 09:01:50

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

Other test, other result.

TEST
This time I have made the some test of last post but on my Office LAN (all computer with Windows XP, last post test on my Home LAN all computer with Windows 7).

I have disable the real time protection of Windows Essential Security (on Server and Client computer).

RESULT

Reselt of http://localhost:8080/root/stat

Clients now=1 max=1
Data in=5776 B out=3969 B
Requests=27 Updates=0 Invalid=0
Time spent in requests = 92.27ms

ProcessExplorer result:
This is my first time with ProcessExplorer so I'm sure that I have read the correct data, I have run ProcessExplorer before my application then double click on my proccess and check on threads and TCP/IP:
threads = 37 (server) 2 (client)
TCP/IP = In the list I see always 1 item that change color (green -> red)

There is always the LAG time!

Sorry for all my post but I have choose your framework because it's flexible and easy and I'd like solve this stupid problem.
Suggests?

Offline

#30 2011-01-28 09:37:43

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

Is your client remaining during the whole process?

I suspect that 37 threads is a bit high for the server.
Perhaps the client is reconnecting each time, which is not the expected behaviour, and can be slow...
Does the color for TCP/IP blink during the tests, or only stay green, then red when the client is finished?

Offline

#31 2011-01-28 09:59:29

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

Another try:

Set in SynCrtSock.pas:

{...$define USETHREADPOOL}

instead of

{$define USETHREADPOOL}

To disable thread pooling... but I don't think it will help...

Offline

#32 2011-01-28 10:34:06

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

When try to load my data I have these colors for TCP/IP on client application (this is the right order):
1 row white
1 row red and 1 row green (together)
1 row white
1 row red and 1 row green (together)
1 row white

I have tried to use:

{...$define USETHREADPOOL}

threads = 5 (server) 2 (client)

but there is always the LAG problem...

Offline

#33 2011-01-28 10:41:12

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

A) Can you check the value of the ServerConnectionCount property of your TSQLite3HttpServer instance?


B) Try these steps:

1) define DEBUG2 and DEBUG23 conditionals in SynCrtSock.pas:

interface

{$define DEBUG2}
{$define DEBUG23}

2) add a AllocConsole call in your OnCreate event of the main form (or whenever you want)

This will create some logs on a console...
Please put them here...


C) put your code in PasteBin, as I suggested above, so that I could check it...

Offline

#34 2011-01-28 11:09:10

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

A) After my test ServerConnectionCount = 3;

B) Is there a way to save the log from console to TXT file? In alternative I cannot put it here...

C) I have the LAG problem all time that I try to load/write data (not only on a part of my code), do you need of all source code of my project (!) or only the piece of code that I have use to make my test?

Offline

#35 2011-01-28 13:37:28

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

OK I have used PasteBin to send you the piece of code of my test, this is the link (valid for 1 day):

http://pastebin.mozilla.org/995142

When I open a form (on show event) I call one after the other all the functions that you find on the code.

Tell me if there is a awaty to save the log so I post it.

Offline

#36 2011-01-28 14:09:24

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

This code seems correct.

But the part I need is all the Client and Server logic: how you create the TSQLHttpClient instances, for instance...

I've added a new TSQLTable.GetString() method because it could help you having direct access to a property without all those UTF8ToString(TSQLTable.GetU()) calls.

Offline

#37 2011-01-28 14:32:46

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

array81 wrote:

A) After my test ServerConnectionCount = 3;

So you connected a client instance three times.
Is it expected? Should not be only once?

array81 wrote:

B) Is there a way to save the log from console to TXT file? In alternative I cannot put it here...

Click on the system menu box (upper left corner of the window), then select Edit / Select All.
Then press the Enter key on the keyboard.
You have all messages in the clipboard.
Just copy those messages here or in a PasteBin.

One more question: how to you refer to the server PC?
Did you use a fixed IP address?
If not, try using a fixed IP address when you create the TSQLHttpClient instance.

Offline

#38 2011-01-28 15:34:01

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

This is the link of Client and Server logic code: [link]http://pastebin.mozilla.org/995445[/link]

The user select how use my application the I call one of 3 function

CaricaDatabaseLocale(Filename: string; Overwrite: Boolean); // StandAlone
CaricaDatabaseClient(Server: string; Port: Integer); // Client
CaricaDatabaseServer(Port: Integer; Filename: string; Overwrite: Boolean); // Server

Server log:

THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 163
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=163
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 180
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=180
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 176
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=176
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 310
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=310
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 289
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=289
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 92
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=92
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 44
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=44
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 196
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=196
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 192
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=192
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 310
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=310
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 306
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=306
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 72
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=72
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 72
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=72
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 72
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=72
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 72
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=72
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 350
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=350
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 261
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=261
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 98
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=98
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 180
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=180
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 311
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=311
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 196
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=196
THttpServerSocket.HeaderIn Accept: */*
THttpServerSocket.HeaderIn Host: 192.168.0.8
THttpServerSocket.HeaderIn User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Window
s; FREE)
THttpServerSocket.HeaderIn Content-Length: 151
THttpServerSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpServerSocket.HeaderIn Keep-Alive: 20000
THttpServerSocket.HeaderIn Connection: Keep-Alive
GetBody ContentLength=151

Client log:

THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=192

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 196
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 71
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=71

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 192
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 71
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=71

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 310
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 178
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=178

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 306
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 201
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=201

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 72
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 61
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=61

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 72
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 61
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=61

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 72
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 61
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=61

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 72
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 61
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=61

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 350
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 100
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=100

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 261
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK
GET root RETRY Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 261
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 128
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=128

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 98
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 61
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=61

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 180
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 61
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=61

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 311
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 136
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=136

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 196
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 71
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=71

GET root Send
HeaderOut GET root HTTP/1.1
Accept: */*
Host: 192.168.0.8
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows; FREE)
Content-Length: 151
Content-Type: application/json; charset=UTF-8
Keep-Alive: 20000
Connection: Keep-Alive


OK HTTP/1.1 200 OKTHttpClientSocket.HeaderIn Server-InternalState: 1
THttpClientSocket.HeaderIn X-Powered-By: SynCrtSock http://synopse.info
THttpClientSocket.HeaderIn Server: TSQLite3HttpServer
THttpClientSocket.HeaderIn Content-Length: 44
THttpClientSocket.HeaderIn Content-Type: application/json; charset=UTF-8
THttpClientSocket.HeaderIn Connection: Keep-Alive
OK BodyGetBody ContentLength=44

I don't need of "ServerConnectionCount = 3" but I don't know how fix it.

A clarification about my test I always do this steps:
1) Run Application as Server;
2) Run Application as Client, read some value from database and put it on a grid; -> ServerConnectionCount = 1
3) Double click on a grid row -> A new window is open and data read from database (the code of my last post [link]http://pastebin.mozilla.org/995142[/link]) -> ServerConnectionCount = 3;

If I close this window and make a double click on row (to show the window again) -> ServerConnectionCount = 5!

On my Home LAN I use DINAMIC IP address but on my Office LAN all computer have a STATIC IP address.

I will tried TSQLTable.GetString() code.

Do you need of other information/code?

Offline

#39 2011-01-28 17:10:59

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

Please remove DEBUG2 and DEBUG23... there is no handy info here.

Two new ideas - perhaps B is cleaner:

A) Can you run the server in a remote PC, then launch your client program in the Delphi IDE?
Then could you step in the methods from http://pastebin.mozilla.org/995142 using F8 to see if ExecuteList are indeed slow....

B) Could you use a GetTickCount, to make a rough estimation of the speed.
For example, hack SQLite3HttpClient.pas unit with this:

function TSQLite3HttpClient.URI(const url, method: RawUTF8; Resp, Head,
  SendData: PRawUTF8): Int64Rec;
var H,S: RawUTF8;
     tix: cardinal;
begin
  tix := GetTickCount;
  if Head<>nil then
    H := Head^;
  if SendData<>nil then
    S := SendData^;
  writeln(NowToString,' ',method,' ',url,' ',S);
  result.Lo := fSocket.Request(url,method,KeepAliveMS,H,S,JSON_CONTENT_TYPE,false);
  result.Hi := GetCardinal(pointer(fSocket.HeaderValue('Server-InternalState')));
  if Resp<>nil then
    Resp^ := fSocket.Content;
  if Head<>nil then
    Head^ := fSocket.HeaderGetText;
  writeln(result.Lo,' ',GetTickCount-tix,'ms');
end;

Leave the AllocConsole call...
So we'll know how much time is processed inside the framework, and which call is slow...

I've added a DEBUGCLI define in the official source code repository for such speed monitoring.
See http://synopse.info/fossil/fdiff?v1=071 … d7baf4656a

Offline

#40 2011-01-28 17:46:23

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

I have make "TEST B" with hack of SQLite3HttpClient.pas unit.

This is the client log:

2011-01-28 18:42:47 GET root SELECT Progetti.ID, Progetti.Oggetto, Progetti.Tipo
, Progetti.Fascicolo, Progetti.DataInizio, Progetti.DataFine,  Progetti.Stato FR
OM Progetti ORDER BY Progetti.ID
200 281ms
2011-01-28 18:42:47 GET root SELECT Contatti.ID, Contatti.IntNome FROM Contatti
LEFT JOIN ProgettiClienti ON ProgettiClienti.IDCliente=Contatti.ID WHERE Progett
iClienti.IDProgetto="1" ORDER BY Contatti.IntNome
200 297ms
2011-01-28 18:42:48 GET root SELECT Contatti.ID, Contatti.IntNome FROM Contatti
LEFT JOIN ProgettiUtenti ON ProgettiUtenti.IDUtente=Contatti.ID WHERE ProgettiUt
enti.IDProgetto="1" ORDER BY Contatti.IntNome
200 313ms
2011-01-28 18:42:48 GET root SELECT Contatti.ID, Contatti.IntNome, ProgettiAttiv
ita.ID, ProgettiAttivita.IDProgetto, ProgettiAttivita.Oggetto, ProgettiAttivita.
Data, ProgettiAttivita.Stato FROM Contatti LEFT JOIN ProgettiAttivita ON Progett
iAttivita.IDUtente=Contatti.ID WHERE ProgettiAttivita.IDProgetto="1" ORDER BY Pr
ogettiAttivita.Data
200 297ms
2011-01-28 18:42:48 GET root SELECT Contatti.ID, Contatti.AnaCognome, Contatti.A
naNome, Contatti.Societa, Contatti.ResComune, Contatti.LegComune,  Contatti.AbiM
obile, Contatti.AbiFisso, Contatti.AbiMail, Contatti.LavMobile, Contatti.LavFiss
o, Contatti.LavMail, Contatti.Ruolo FROM Contatti ORDER BY Contatti.AnaCognome
200 296ms
2011-01-28 18:42:52 GET root SELECT Contatti.ID, Contatti.IntNome, Contatti.Ruol
o FROM Contatti ORDER BY Contatti.IntNome
200 265ms
2011-01-28 18:42:52 GET root SELECT * FROM Progetti WHERE ID="1" LIMIT 1;
200 297ms
2011-01-28 18:42:53 GET root SELECT Contatti.ID, Contatti.IntNome, Contatti.Ruol
o FROM Contatti LEFT JOIN ProgettiClienti ON ProgettiClienti.IDCliente=Contatti.
ID WHERE ProgettiClienti.IDProgetto="1" ORDER BY Contatti.IntNome
200 297ms
2011-01-28 18:42:53 GET root SELECT Contatti.ID, Contatti.IntNome, Contatti.Ruol
o FROM Contatti LEFT JOIN ProgettiUtenti ON ProgettiUtenti.IDUtente=Contatti.ID
WHERE ProgettiUtenti.IDProgetto="1" ORDER BY Contatti.IntNome
200 297ms
2011-01-28 18:42:53 GET root SELECT Contatti.ID, Contatti.IntNome, ProgettiAttiv
ita.ID, ProgettiAttivita.IDProgetto, ProgettiAttivita.Oggetto, ProgettiAttivita.
Data, ProgettiAttivita.Stato FROM Contatti LEFT JOIN ProgettiAttivita ON Progett
iAttivita.IDUtente=Contatti.ID WHERE ProgettiAttivita.IDProgetto="1" ORDER BY Pr
ogettiAttivita.Data
200 312ms
2011-01-28 18:42:54 GET root SELECT ProgettiFlussi.ID, ProgettiFlussi.IDProgetto
, ProgettiFlussi.IDUtente, ProgettiFlussi.IDCliente, ProgettiFlussi.Descrizione,
 ProgettiFlussi.Data, ProgettiFlussi.Importo, ProgettiFlussi.IDFattura, Progetti
Flussi.IVA FROM ProgettiFlussi WHERE ProgettiFlussi.IDProgetto="1" ORDER BY Prog
ettiFlussi.Data
200 297ms
2011-01-28 18:42:54 GET root SELECT Contatti.ID, Contatti.IntNome FROM Contatti
WHERE Contatti.ID="2"
200 297ms
2011-01-28 18:42:54 GET root SELECT Contatti.ID, Contatti.IntNome FROM Contatti
WHERE Contatti.ID="3"
200 312ms
2011-01-28 18:42:55 GET root SELECT Contatti.ID, Contatti.IntNome FROM Contatti
WHERE Contatti.ID="2"
200 297ms
2011-01-28 18:42:55 GET root SELECT Contatti.ID, Contatti.IntNome FROM Contatti
WHERE Contatti.ID="3"
200 406ms
2011-01-28 18:42:55 GET root SELECT Contatti.ID, Contatti.IntNome, ProgettiDocum
enti.ID, ProgettiDocumenti.IDProgetto, ProgettiDocumenti.Descrizione, ProgettiDo
cumenti.Data, ProgettiDocumenti.Filename, ProgettiDocumenti.Size FROM Contatti L
EFT JOIN ProgettiDocumenti ON ProgettiDocumenti.IDUtente=Contatti.ID WHERE Proge
ttiDocumenti.IDProgetto="1" ORDER BY ProgettiDocumenti.Data
200 94ms
2011-01-28 18:42:55 GET root SELECT ProgettiFatture.ID, ProgettiFatture.IDClient
e, ProgettiFatture.IDUtente, ProgettiFatture.Oggetto, ProgettiFatture.Data, Prog
ettiFatture.Importo, ProgettiFatture.Spese FROM ProgettiFatture WHERE ProgettiFa
tture.IDProgetto="1" ORDER BY ProgettiFatture.Data
200 406ms
2011-01-28 18:42:56 GET root SELECT Contatti.ID, Contatti.IntNome FROM Contatti
WHERE Contatti.ID="2" ORDER BY Contatti.IntNome
200 297ms
2011-01-28 18:42:56 GET root SELECT Contatti.ID, Contatti.IntNome FROM Contatti
LEFT JOIN ProgettiClienti ON ProgettiClienti.IDCliente=Contatti.ID WHERE Progett
iClienti.IDProgetto="1" ORDER BY Contatti.IntNome
200 297ms
2011-01-28 18:42:56 GET root SELECT ProgettiFatture.ID, ProgettiFatture.IDClient
e, ProgettiFatture.IDUtente, ProgettiFatture.Importo, ProgettiFatture.Spese, Pro
gettiFatture.IVA, ProgettiFatture.CAP, ProgettiFatture.Ritenuta, ProgettiFatture
.RitenutaUsa FROM ProgettiFatture WHERE ProgettiFatture.IDProgetto="1" ORDER BY
ProgettiFatture.Data
200 297ms
2011-01-28 18:42:57 GET root SELECT Contatti.ID, Contatti.IntNome, Contatti.Ruol
o FROM Contatti LEFT JOIN ProgettiClienti ON ProgettiClienti.IDCliente=Contatti.
ID WHERE ProgettiClienti.IDProgetto="1" ORDER BY Contatti.IntNome
200 297ms
2011-01-28 18:42:57 GET root SELECT ProgettiFlussi.Importo FROM ProgettiFlussi W
HERE ProgettiFlussi.IDProgetto="1" AND ProgettiFlussi.IDCliente="3" AND Progetti
Flussi.IDFattura > 0
200 296ms

I hope this can help you to help me smile

Another think about TSQLTable.GetString() I cannot find it. Do I need download last biuld of framework?

Thanks again.

Offline

#41 2011-01-28 18:17:57

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

OK sorry for my last stupid question I have upgrade the framework and I have found the new function.

Last edited by array81 (2011-01-28 18:24:46)

Offline

#42 2011-01-28 18:51:15

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

Hoho... the logs you supplied show a 290 ms response time... which is VERY slow!!!!

I'll try to reproduce the issue on some networks... and see what's happening here...
Stay tuned!

What does a "PING serverIP" looks like from your client computer?
Run it in a command line prompt (cmd.exe).

Offline

#43 2011-01-29 10:10:10

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

I have made the PING test, note this test is made on my Home LAN (all Windows 7 and WIFI LAN), all test of yesterday are made on Office LAN (all Windows XP and cable LAN). In any caswe I have the same problem both on Office LAN and Home LAN.

C:\>ping 192.168.1.6

Esecuzione di Ping 192.168.1.6 con 32 byte di dati:
Risposta da 192.168.1.6: byte=32 durata=1ms TTL=128
Risposta da 192.168.1.6: byte=32 durata=1ms TTL=128
Risposta da 192.168.1.6: byte=32 durata=1ms TTL=128
Risposta da 192.168.1.6: byte=32 durata=1ms TTL=128

Statistiche Ping per 192.168.1.6:
    Pacchetti: Trasmessi = 4, Ricevuti = 4,
    Persi = 0 (0% persi),
Tempo approssimativo percorsi andata/ritorno in millisecondi:
    Minimo = 1ms, Massimo =  1ms, Medio =  1ms

C:\>

Offline

#44 2011-01-29 19:16:21

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

Thanks for the info.
I was not able to reproduce the issue yet. But I will.
But perhaps only on next week. Sorry.

Offline

#45 2011-01-29 23:32:35

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

Don't worry. I hope you will reproduce the issue so you can fix it. Until next week I will work on my application to finish it.
Thanks again for your support.

Offline

#46 2011-01-31 10:40:45

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

Until you reproduce my problem I have another question: do my server application can know when a client application edit the database and in particular it can know how table is edit?

I like that when a client edit the db the server send a message on all the client to upgrade your data inside the grid, for this I need of a event to know when the db is edit and know how table is edit. Is this possible?

Offline

#47 2011-01-31 13:50:57

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

Server side synchronization

I guess you want to have some event triggered on the server side when a record is edited.

On the server side, you can use this event:

type
  ///  used to define how to trigger Events on record update
  // - see TSQLRestServer.OnUpdateEvent property
  // - returns true on success, false if an error occured (but action must continue)
  TNotifySQLEvent = function(Sender: TSQLRestServer; Event: TSQLEvent;
    aTable: TSQLRecordClass; aID: integer): boolean of object;

  TSQLRestServer = class(TSQLRest)
 (...)
    /// a method can be specified here to trigger events after any table update
    OnUpdateEvent: TNotifySQLEvent;

Client side synchronization

But if you want all clients to be notified, there is no direct way of broadcasting some event from the server to all clients.
It's not possible with pipe-oriented transport layer, like named pipes or the TCP/IP/HTTP protocol.

What you can do easily, and is what I used in such case, is to have a timer in your client applications which will call TSQLRestClientURI.UpdateFromServer() method to refresh the content.
With a per-second timer, it's quick and reactive.
The stateless aspect of REST allows this approach to be safe, by design.

This is handled natively by our Client User Interface classes, with the following parameter defining the User interface:

  /// defines the settings for a Tab
  TSQLRibbonTabParameters = object
  (...)
    /// by default, the screens are not refreshed automaticaly
    // - but you can enable the auto-refresh feature by setting this
    // property to TRUE, and creating a WM_TIMER timer to the form
    AutoRefresh: boolean;

This parameter will work only if you handle the WM_TIMER message in your main application form, and call Ribbon.WMRefreshTimer.
This for example this method in the main demo (FileMain.pas unit):

procedure TMainForm.WMRefreshTimer(var Msg: TWMTimer);
begin
  Ribbon.WMRefreshTimer(Msg);
end;

Offline

#48 2011-02-02 23:10:46

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

OK. I will try it.

Are there new about my problem with LAN? thanks

Offline

#49 2011-02-03 06:07:13

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,207
Website

Re: Load/save image

I made some modifications to the server-side of the framework.

Could you make it a try?

Could you also try with setting the following conditional (line 1587 of SynCrtSock.pas):

{$define MONOTHREAD}
// define this not to create a thread at every connection (not recommended)

I was not able to reproduce the issue as such...

Offline

#50 2011-02-03 08:46:36

array81
Member
From: Italy
Registered: 2010-07-23
Posts: 411

Re: Load/save image

I have the same result.

Is there a way to send you my application? I don't want put here (pubblic site) the link.
So you can test it and tell me if have the same problem...

If use MAIL button only you can see the message, right? Can I use it to send you the link?

thanks

Last edited by array81 (2011-02-03 08:48:24)

Offline

Board footer

Powered by FluxBB