#1 Re: mORMot 1 » Rollback a transaction if client timeout » 2016-02-29 12:52:01

So, I can't handle transactions manually on the server side in case of client timeouts?

#2 Re: mORMot 1 » Rollback a transaction if client timeout » 2016-02-26 13:10:05

Unfortunately, this wouldn't work for us.

We need to control the database transaction on the server-side.

We have multiple mormot servers running in parallel (AWS AutoScaling) and receiving the load from a Elastic Load Balancer, so, client requests can hit different servers.

The problem that we are trying to solve is this: A client made a destructive call to the server (Insert/Delete/Update) but the connection was interrupted (client timeout, etc.). In that case, the client would assume that none of the changes are applyed on the database, so, we would like to rollback the transaction if anything goes wrong.

#3 Re: mORMot 1 » WebSocket Pub-Sub with channels? » 2015-11-12 15:33:04

I can try that. AFAIK, the `CallbackReleased` method is used and handled internally by the framework, you are suggesting that I handle manually that behavior with this new method?

#4 Re: mORMot 1 » WebSocket Pub-Sub with channels? » 2015-11-12 13:19:13

ab wrote:

Why not just check for interfaceName='INotificationCallback' then delete the callback: IInvokable from all matching entry in fConnected[]?

that will work, but, I will have more than a thousand channels with potentialy more than 5k callbacks, it would be slow, don't you think? A hashlist would be much more efficient.

ab wrote:

Or not use a dictionary, but an array of records containing the client string and the INotificationCallback entry.

Not sure, but will end up in the same problem, I think.

#5 mORMot 1 » WebSocket Pub-Sub with channels? » 2015-11-12 12:48:53

Roberto Schneiders
Replies: 5

I'm trying to implement a publish-subscribe messaging system with mORMot websockets. I need something like (pusher) channels.

I want to use a unique mormot server to send messages to all clients, so, when a client subscribe to a message/event, it should be only for a determined channel/client. When a notification is sent, it is only for a specific client.

My interfaces look like this:

  INotificationCallback = interface(IInvokable)
    ['{F5D956A4-AE70-4F47-AECC-40E2AB6AC0B4}']
    procedure NotifyRefresh(const message: string);
  end;
  NotificationCallbackArray = array of INotificationCallback;

  INotificationService = interface(IServiceWithCallbackReleased)
    ['{C92DCBEA-C680-40BD-8D9C-3E6F2ED9C9CF}']
    procedure Subscribe(const client: string; const callback: INotificationCallback);
    procedure Refresh(const client, message: string);
  end;

I'm using a dictionary to store the callbacks:

fConnected: TDictionary<string, NotificationCallbackArray>;
...
procedure TNotificationService.Subscribe(const client: string; const callback: INotificationCallback);
begin
  if not fConnected.ContainsKey(client) then
    fConnected.Add(client, []);

  InterfaceArrayAdd(fConnected[client], callback);
end;

The problem is the CallbackReleased method:

  procedure CallbackReleased(const callback: IInvokable; const interfaceName: RawUTF8);

It doesn't provide any information that allow me to identify and release the correct callback.

Any ideas of how to solve this?

#6 Re: mORMot 1 » How can I send a custom http header through TSQLHttpClient? » 2015-11-04 17:42:42

Thanks Daniel,

I was able to change the headers by overriding the InternalRequest on TSQLHttpClient.

function InternalRequest(const url, method: RawUTF8; var Header, Data, DataType: RawUTF8): Int64Rec; override;

#7 Re: mORMot 1 » How can I send a custom http header through TSQLHttpClient? » 2015-11-04 13:38:47

I have some methods that are called in the DBX layer, some sort of a IAPPServer crazy wrapper, so, it will be much easier to send the session id on a HTTP Header rather than a explicit parameter.

In fact, It is perfectly possible to make a full stateless server, but, I will have to send some information from the client (like the user id) in every request, which is fine if I can send via Header or something like that, but, if I have to send those params explicitly in every method, it will became a mess.

About the Load Balancer, use mORMot can be a good idea, but, It will bring me some new problems. The ELB automatically adjust itself according to the traffic, if I use mORMot I will have to use a fixed EC2 machine that can support our peak usage (primarily network bandwidth), which can became expensive. ELB also gives me a free failover system. If one of the servers became offline, it will automatically launch a new server. I think this will be a lot more complicated to do without ELB.

#8 Re: mORMot 1 » How can I send a custom http header through TSQLHttpClient? » 2015-11-04 11:19:05

The major problem is that the load balancer (AWS ELB) will send the request to any of the servers and it is not predictable. So, I can't rely on any in-memory information/session on the server side.

This server will serve a ton of clients with a low usage per client, so, I'm using sicPerThread.

#9 Re: mORMot 1 » How can I send a custom http header through TSQLHttpClient? » 2015-11-03 19:18:16

I could use a modified version of TSQLRestServerAuthenticationHttpBasic, overriding the CheckPassword method, but I have one problem. AFAIK, mORMot save the authentication details (token/signature) in memory, and this would not work for me.

I will have more then one server running (Using AWS Auto-scaling/Load Balancer), so, I need to persist that data on Redis.

Any ideas how to do that?

#10 mORMot 1 » How can I send a custom http header through TSQLHttpClient? » 2015-10-30 18:16:21

Roberto Schneiders
Replies: 7

I'm using only the http layer of mormot (Interface based services) in a legacy (ex-datasnap) project. I'm developing my own authentication methods (because of compatibility issues) and I want to send a session token from the client to the server in every request. I guess I can do that with a custom header.

Which is the right way to do this?

I didn't find any Headers property. I tried to override some internal methods of TSQLHttpClient but without success. I guess I'm looking in the wrong place.

#11 Re: mORMot 1 » Replace DataSnap by mORMot on the HTTP layer of a DBX based project » 2015-10-19 17:30:38

haha, I'm glad you liked it. mORMot is awesome, I switched to another job two years ago (working mostly with Ruby, Go) and no longer had the opportunity to work with it, maybe this will change now. smile

Yeah, I'm doing some tests with Interfaced Based Services now. I was able to serialize the olevariant data and delta with some crazy code (http://stackoverflow.com/questions/2481 … conversion)

I think I will do just a tiny benchmark big_smile to compare to our Datasnap TCP, just for fun.

#12 Re: mORMot 1 » Replace DataSnap by mORMot on the HTTP layer of a DBX based project » 2015-10-19 11:33:34

In this case, I want to serialize the ClientDataSet Data and Delta properties.

The problem with DatasetToJSON danielkuettner is the JSON, in first place, I would prefer something more optimized for speed. The other problem is that I don't have a method that does the inverse. JSONToClientDataSet dose'n work because of the blobs base64 encoding, as stated on the first post.

#13 Re: mORMot 1 » Replace DataSnap by mORMot on the HTTP layer of a DBX based project » 2015-10-16 20:03:33

Unfortunately, we have some process (SQL) that have to be made on the server (actualy using datasets events), so, I don't think this will work for us. hmm

Do you have any idea how I can serialize and send a OleVariant through TSQLRestServer?

#15 Re: mORMot 1 » Replace DataSnap by mORMot on the HTTP layer of a DBX based project » 2015-10-16 17:17:35

Using SynDBRemote, I have access to any connection implementation (TFDConnection, TSQLConnection) that allows me to use the existing datasets with it?

#17 mORMot 1 » Replace DataSnap by mORMot on the HTTP layer of a DBX based project » 2015-10-16 13:51:13

Roberto Schneiders
Replies: 11

Hello,

I'm trying to do some crazy stuff with mORMot.

I'm working on a project that is basically a Datasnap TCP stateful (IAPPServer) with a lot of DBX (Datasets, Clientdatasets, etc) which I can not get away from, despite wanting to.

We are having serious trouble to scale this thing, so, we want to make a stateless REST server. Amazingly, this is not simple to do with Datasnap REST, I mean, it is possible, but, I will have to do manually all the conversion Dataset -> JSON, JSON -> Dataset (also deltas). So, I'm thinking, If I have to do this, why not use mORMot in the HTTP layer?

First, I tought in use only the ninja JSON serialization of mORMot, but I think it would be very nice to use the http layer too. I am even wondering if I can communicate using binary (I don't have to access this data in any other client, so, the fastest, the better.).

Do you guys have any insight about this? 

I haven't tried anything on the HTTP layer yet, but I had some trouble with the JSON serialization and datasets, I'm trying to use the existing datasets helpers. Probably this wasen't the purpose of this classes, or, I just using them wrong, I'm not sure. I tried to do thinks like this:

function TMormotTest.DatasetToJson(Dataset: TDataSet): string;
begin
  Result := SynVirtualDataset.DataSetToJSON(Dataset);
end;

function TMormotTest.JsonToDataSet(json: string): TDataSet;
var
  Dataset: TClientDataSet;
begin
  Dataset:= TCDSUtil.GetEmptyDataSet;
  JSONToClientDataSet(Dataset, json, nil, cdsReplace, false);
  result := Dataset;
end;

The SynVirtualDataset.DataSetToJSON converts the blob fields to base64 and the JSONToClientDataSet does not take this into consideration.

#18 mORMot 1 » Can I use the IN operator with Fillprepare? » 2013-11-14 19:54:15

Roberto Schneiders
Replies: 1

I could not find an example of using the IN operator with FillPrepare (It's a little tricky search for it.)

I tried this way but it does not work:

var
  oMeuProduto: TProduto;
begin
  oMeuProduto := TProduto.Create;
  try
    oMeuProduto.FillPrepare(BaseDeDados, 'estoque IN (?)', [1, 0, 2, 41] );
    while (oMeuProduto.FillOne) do
    begin
      Log(IntToStr(oMeuProduto.ID));
    end;
  finally
    FreeAndNil(oMeuProduto);
  end;
end;

#19 Re: mORMot 1 » I need a help with FillPrepareMany functionality » 2013-10-30 12:20:13

I am using a external SQLite3 database.

I realized that i have not tested exactly what you passed in the other post, so, i did other test with this code:

produto.DestList.FillPrepareMany(DatabaseServer, 'Dest.Codigo=?', [], [1000]);

this error occurs: 'near "and": syntax error';

#20 Re: mORMot 1 » I need a help with FillPrepareMany functionality » 2013-10-30 10:12:11

still have the same problem:

  produto.FillPrepareMany(DatabaseServer, 'Dest.Codigo=?', [], ['1000']);

Error: 'no such column: Dest.A.Codigo'

#21 mORMot 1 » I need a help with FillPrepareMany functionality » 2013-10-29 17:06:11

Roberto Schneiders
Replies: 14

I am trying to use the FillPrepareMany but isen't working. Someone can help me?

These are my entities classes.

  TFornecedor = class(TSQLRecord)
  private
    FCodigo: integer;
    FNome: RawUTF8;
  published
    property Codigo: integer read FCodigo write FCodigo;
    property Nome: RawUTF8 read FNome write FNome;
  end;

  TProdutoXFornecedor= class(TSQLRecordMany)
  private
    fSource: TProduto;
    fDest: TFornecedor;
  published
    property Source: TProduto    read fSource;
    property Dest  : TFornecedor read fDest;
  end;

  TProduto = class(TSQLRecord)
  private
    FDescricao: RawUTF8;
    FCodigo: integer;
    FDepartamento: TDepartamento;
    FProdutoXFornecedor: TProdutoXFornecedor;
    FDataCadastro: TDateTime;
  published
    property Codigo            : integer             read FCodigo              write FCodigo;        stored AS_UNIQUE;
    property Descricao         : RawUTF8   index 40  read FDescricao           write FDescricao;
    property Departamento      : TDepartamento       read FDepartamento        write FDepartamento;
    property DestList          : TProdutoXFornecedor read FProdutoXFornecedor;
    property DataCadastro      : TDateTime           read FDataCadastro        write FDataCadastro;
  end;

I am trying to use in this way:

  produto.FillPrepareMany(DatabaseServer, 'DestList.Dest.Codigo=?', [], ['1000']);

I receive an exception with this message:
ESQLite3Exception with message 'no such column: DestList'

What i am doing wrong?

#22 Re: mORMot 1 » Handle other collection types in mORMot? » 2013-07-31 21:00:59

Why on earth does not TObjectList<T> have a member to retrieve the type information about T ?

I had this same problem today! It's unfortunate.

I solved getting the type of the "First" method.

Rtti.GetType(ObjectList.ClassInfo).GetMethod('First').ReturnType

I know, it's very strange. But so far I have not found a better way.

#23 Re: mORMot 1 » Help with BackupGZ and SQLite External » 2013-07-30 11:17:47

I started to have problems with this backup method. Are experiencing the same error reported in these other posts.
http://synopse.info/forum/viewtopic.php?id=881
http://synopse.info/forum/viewtopic.php?id=643
http://synopse.info/forum/viewtopic.php?id=662

"cannot VACUUM - SQL statements in progress"

We do not perform any SQL command before running the backup. Simply open the program and ran the backup.

What is the correct way to back up an external database?

#24 Re: mORMot 1 » SQLite3 or Embedded Firebird? » 2013-07-29 18:31:19

Today I ran the same software again and got some new errors. I have the latest mORMot version (updated-to:   21a1dd69da94b5736f090f533681abeefcb8460b 2013-07-29 16:18:35 UTC)

When running the test with 4 threads i'm getting this message:
{
"ErrorCode": 408
"ErrorText": "Request Timeout"
}

#25 mORMot 1 » mORMot with SQLite3 - Internal vs. External » 2013-07-29 14:11:03

Roberto Schneiders
Replies: 3

I am in doubt between using the internal database or external in mORMot.

From what I noticed, there are many different procedures that when you use an external database. Correct?

Say I choose to use the internal SQLite database. Can I switch to external later without changing the whole software?

#26 Re: mORMot 1 » Help with BackupGZ and SQLite External » 2013-07-26 16:46:32

Thanks

Only found this option. Is that correct?

TSQLDBSQLite3Connection(Props.MainConnection).DB.Backup('teste.bkp');

Is there any way to restore this backup in the framework?

It has some class that provides a method similar to BackupGz with compression?

#27 mORMot 1 » Help with BackupGZ and SQLite External » 2013-07-26 14:17:41

Roberto Schneiders
Replies: 4

I'm testing methods for backup a SQLite database. More precisely BackupGZ.

This is my code:

var
  Props:TSQLDBConnectionProperties;
begin
  Model := CreateBigSampleModel;
  Props := TSQLDBSQLite3ConnectionProperties.Create('Teste.db3' , '', '', '');
  VirtualTableExternalRegister(Model,TSQLBigSampleData,Props, 'SampleRecord');
  Database := TSQLRestClientDB.Create(Model,nil,'MainDb.db3',TSQLRestServerDB,false,'');
  TSQLRestClientDB(Database).Server.DB.Synchronous := smOff;
  TSQLRestClientDB(Database).Server.DB.LockingMode := lmExclusive;
  TSQLRestClientDB(Database).Server.CreateMissingTables(0);
  TSQLRestClientDB(Database).Server.BackupGZ('Backup.gz');
end;

Apparently he is backing up MainDB.Db3 and not the actual base Teste.db3.

If I use this:

  Database := TSQLRestClientDB.Create(Model,nil,':memory:',TSQLRestServerDB,false,'');

An error occurs when backing up.

What is the correct way to backup a External SQLite database?

#29 mORMot 1 » Performance problems with SQLite » 2013-07-26 13:18:28

Roberto Schneiders
Replies: 2

I ran the performance tests (15 - External DB performance) with Delphi XE4 on my machine and I had very different (Insertion speed) results from yours. Can you help identify why?

Basis for comparison (AB Notebook).

Direct              Batch  Trans  Batch   Trans
SQLite3 (file full)  493    494   88284   108877
SQLite3 (file off)   923    908   93613   117952
SQLite3 (ext full)   498    504  101296   128885
SQLite3 (ext off)    966    930   83708   108700

My PC (SSD)

Direct              Batch Trans  Batch   Trans
SQLite3 (file full)   83     91  53851   67388
SQLite3 (file off)  1886   2053 108731  143282
SQLite3 (ext full)    99     87  70905   60120
SQLite3 (ext off)   2225   2303 125966  164235

My PC (HD)

Direct              Batch  Trans  Batch   Trans
SQLite3 (file full)     7     7   19804   20062
SQLite3 (file off)   2500  1841  112115  141330
SQLite3 (ext full)      6     6   17333   21157
SQLite3 (ext off)    2497  2138  123499  159877

Hardware configuration

Intel Core i7 3770 3.4Ghz (4Cores/8Threads)
SSD 120Gb Sandisk
HD Seagate Barracuda 7200
8Gb Ram DDR3

I disabled the antivirus.

What worries me more are the smFull tests.

#30 Re: mORMot 1 » Problem with mORMot + Delphi 6 + Wine » 2013-07-25 13:34:05

Something very strange happened here.

I set up an environment for remote debugging with Delphi 6 and Wine to try to identify this problem (Never thought it would work, but it works! big_smile).
I removed all of the mORMot units and the application continued not starting. hmm

I removed all the code from the project, it was just the Form. And nothing. neutral
I recreated the project from scratch, including the same things of the previous design. And it worked! big_smile

I have no idea what happened.

#32 Re: mORMot 1 » LockingMode to lmExclusive » 2013-07-24 19:10:31

Sorry. I thought was in last version. But there were some read-only sources (my fault).  When performing "Fossil Update" he did not warned me. I thought it was updated, but it was not. hmm

#33 Re: mORMot 1 » Problem with mORMot + Delphi 6 + Wine » 2013-07-24 11:27:30

In this example, I do not have any communication (for now). It is a standalone application.

The only objects instantiated are TSQLRestServerDB and  TSQLModel. But the problem seems to be before that, because the application does not start. Does not run any of my codes.
Must be something in a Initialization clause.

I can send you the source if it is useful.

#34 Re: mORMot 1 » LockingMode to lmExclusive » 2013-07-24 11:22:21

I'm trying to do some tests to compare the performance of SQLite vs Firebird Embedded.

I wish the two worked with the same kind of synchronization.
According to this article (http://blog.synopse.info/post/2013/06/1 … cking-mode) I should use this:

better Security:
Client.Server.DB.LockingMode := lmExclusive;
Client.Server.DB.Synchronous := smFull;

best Performance
Client.Server.DB.LockingMode := lmNormal;
Client.Server.DB.Synchronous := smOff;

Is that right?

The first problem is that I have not found the property "DB.LockingMode".

Have any way to set the framework to work the same way with the two databases? To be a fair test!

#35 Re: mORMot 1 » Help with Firebird Embedded » 2013-07-23 20:47:26

Sorry about that.

Now trying to ZDBC.

var
  Props:TSQLDBConnectionProperties;
begin
  Model := CreateSampleModel;
  Props := TSQLDBZEOSConnectionProperties.Create( TSQLDBZEOSConnectionProperties.URI(dFirebird, 'fbembed.dll'), 'mormot.fdb', '', '');
  VirtualTableExternalRegister(Model,TSQLSampleRecord,Props, 'SampleRecord');
  Database := TSQLRestServerDB.Create(Model, 'Application');

  TSQLRestServerDB(Database).CreateMissingTables(0);

I noticed some problems.
1) Apparently the word "Time" is a reserved word in firebird. When trying to add the table SampleRecord an error occurs. A boring coincidence.
Simply changed the name of the property and is working.

2) The command to count the records in the table (TSQLRestServerDB(Database).TableRowCount(TSQLSampleRecord)) does not seem to be working. Always returns zero. I checked and there is data in the table.

#36 mORMot 1 » Problem with mORMot + Delphi 6 + Wine » 2013-07-23 19:07:57

Roberto Schneiders
Replies: 5

After the first test (http://synopse.info/forum/viewtopic.php?id=1300), the mORMot REST client is working perfectly with Wine. Just had to add WinHTTP DLLs in wine.

Now I'm testing some other features in an application made in Delphi 6. This application runs on Wine 1.01 on some clients.

Basically the idea is to use SQLite instead of BDE. big_smile

I did two test applications, one in Delphi XE4 and another in Delphi 6.
The application made in Delphi XE4 works perfectly. The application made in Delphi 6 does not open in Wine.

The application is frozen in the background. The status in the linux task manager shows "PIPE_WAIT".

do you have any idea what can be?

These are the sources of the framework being used in the project:

mORMot.dcu
mORMotDB.dcu
mORMotSQLite3.dcu
SampleData.dcu
SynCommons.dcu
SynCrypto.dcu
SynDB.dcu
SynDBFirebird.dcu
SynLZ.dcu
SynSQLite3.dcu
SynSQlite3Static.dcu
SynSSPIAuth.dcu
SynZip.dcu

#37 Re: mORMot 1 » Help with Firebird Embedded » 2013-07-23 16:46:53

I tried to use the same way as the example 15 - External DB performance does, but there is another error.

var
  Props:TSQLDBConnectionProperties;
begin
  Model := CreateSampleModel;
  Props := TSQLDBFirebirdEmbeddedConnectionProperties.Create('firebirdembedded.1', '', '', '');
  VirtualTableExternalRegister(Model,TSQLSampleRecord,Props, 'SampleRecord');
  Database := TSQLRestServerDB.Create(Model, ':memory:');
  TSQLRestServerDB(Database).CreateMissingTables(0);
end;

This error also occurs in example 15.

Stack

exception class   : ESQLite3Exception
exception message : Firebird Error 140000F9: Dynamic SQL Error. SQL error code = -502. Invalid cursor declaration. Statement already has a cursor SYNDB assigned. [ SQLCODE=-502 (The cursor identified in an OPEN statement is already open.) ].

main thread ($50bc):
006ce2ce +02e Project1.exe SynSQLite3      3890   +2 sqlite3_check
006cde05 +041 Project1.exe SynSQLite3      3818   +3 TSQLRequest.Step
006cd3bd +035 Project1.exe SynSQLite3      3439   +5 TSQLRequest.Execute
006cd46a +02e Project1.exe SynSQLite3      3459   +3 TSQLRequest.Execute
006cc048 +074 Project1.exe SynSQLite3      2847   +9 TSQLDatabase.Execute
006cf150 +144 Project1.exe mORMotSQLite3    752  +16 TSQLRestServerDB.CreateMissingTables

what I'm doing wrong?

#38 mORMot 1 » Help with Firebird Embedded » 2013-07-23 14:43:56

Roberto Schneiders
Replies: 4

I'm trying to connect mORMot to a firebird embedded database.

This is the code:

var
  Props:TSQLDBConnectionProperties;
begin
  Model := CreateSampleModel;
  Props := TSQLDBFirebirdEmbeddedConnectionProperties.Create('localhost:C:\TESTE2.fdb', 'TESTE2.fdb', 'SYSDBA', 'asd');
  VirtualTableExternalRegister(Model,TSQLSampleRecord,Props, 'SampleRecord');
  Database := TSQLRestServerDB.Create(Model, ':memory:'); 

  TSQLRestServerDB(Database).CreateMissingTables(0); // ERROR
end;

CreateMissingTables returns this error. What is very strange since the firebird embedded does not have authentication.

Stack:

exception class   : ESQLite3Exception
exception message : Firebird Error 14000098: Your user name and password are not defined. Ask your database administrator to set up a Firebird login. [ SQLCODE=-902 (Unsuccessful execution caused by a system error that precludes successful execution of subsequent statements) ].

main thread ($21bc):
006ce2ce +02e Project1.exe SynSQLite3      3890   +2 sqlite3_check
006cde05 +041 Project1.exe SynSQLite3      3818   +3 TSQLRequest.Step
006cd3bd +035 Project1.exe SynSQLite3      3439   +5 TSQLRequest.Execute
006cd46a +02e Project1.exe SynSQLite3      3459   +3 TSQLRequest.Execute
006cc048 +074 Project1.exe SynSQLite3      2847   +9 TSQLDatabase.Execute
006cf150 +144 Project1.exe mORMotSQLite3    752  +16 TSQLRestServerDB.CreateMissingTables

Can help me?

#39 Re: mORMot 1 » SQLite3 or Embedded Firebird? » 2013-07-22 17:06:05

I think I know what caused the problem. During the test, the database was loaded in SQLite Expert. I did not realize that. My mistake. Apparently it's working as expected with SQLRestServerDB.

So, I should use the TSQLRestClientDB?

I tried this way:

Database := TSQLRestClientDB.Create(Model, Model, ChangeFileExt(paramstr(0),'.db3'), TSQLRestServerDB);
TSQLRestClientDB(Database).Server.CreateMissingTables(0);

but...sometimes this error occurs:
{"ErrorCode":408,"ErrorText":"Invalid Request"}

#40 Re: mORMot 1 » SQLite3 or Embedded Firebird? » 2013-07-22 14:43:14

thank you very much!

I have a problem. What am I doing wrong?

I have this code (Using OmniThread Library):

procedure TForm1.FormCreate(Sender: TObject);
begin
  Model := CreateSampleModel;
  Database := TSQLRestServerDB.Create(Model, ChangeFileExt(paramstr(0),'.db3'));
  TSQLRestServerDB(Database).CreateMissingTables(0);
end;

procedure TForm1.AddValues;
var Rec: TSQLSampleRecord;
  i: Integer;
begin
  for i:=0 to 100 do
  begin
      Rec := TSQLSampleRecord.Create;
    try
      Rec.Name := GetCurrentThreadId().ToString + GetCurrentTime.ToString + i.Tostring;
      Rec.Question := StringToUTF8('TESTE - '+GetCurrentThreadId().ToString + GetCurrentTime.ToString + ' Loop:'+i.ToString);
      if Database.Add(Rec,true)=0 then
        raise exception.create('Error adding the data');
    finally
      Rec.Free;
    end;
  end;
end;

procedure TForm1.BtnParallelClick(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to 20 do
    Parallel.Async(AddValues);
end;

Sometimes when running BtnParallelClick I encounter this error: ESQLite3Exception with message 'database is locked';

#41 mORMot 1 » SQLite3 or Embedded Firebird? » 2013-07-22 12:57:00

Roberto Schneiders
Replies: 8

I need to decide which of these embedded databases use in an point of sale application. It's an important decision because it will affect 5000 users.

From what I've seen the Firebird is faster (http://ea.tl/embeddeddb.shtml). But what really worries me is support for multithreaded and data corruption.

What is your experience about it? Which one would you choose?

1. Can I use the set mORMot + SQLite3 with multiple threads?

I ask this because through the documentation I could not identify what, exactly, is thread-safe and what is not.

SQLite3 documentation: ".. in order to be thread-safe, SQLite must be compiled with the SQLITE_THREADSAFE preprocessor macro set to 1"
mORMot documentation: "SQLite3 source code was compiled without thread mutex: the caller has to be thread-safe " / "low level sqlite3_ aware * () functions are not thread-safe" / "SQLITE_THREADSAFE 0 in sqlite.c"

Is there any example of multiple threads with a mORMot client?

#43 Re: mORMot 1 » Can I use the TSQLHttpClientWinSock in windows? how? » 2013-06-07 13:02:47

With Delphi XE2 and XE4 an error occurs when registering a service using TSQLHttpClientWinSock;

exception class   : EServiceException
exception message : IControleEstacionamento interface or REST routing not supported by server:


Stacktrace:

0068ac07 +11f Project2.exe mORMot            32873 +14 TServiceFactoryClient.Create
0068431d +075 Project2.exe mORMot            29858  +6 TServiceContainer.AddInterface
006724e9 +05d Project2.exe mORMot            21723  +6 TSQLRestClientURI.ServiceRegister
0069593c +12c Project2.exe uClientMOrmothttp    59  +9 TClienteServidorSysmoEstacionamento.Conectar

works using TSQLHttpClient.

My interface:

  IControleEstacionamento = interface(IInvokable)
    ['{9D3E34D0-68D2-4095-9989-49021D89C2D0}']
    procedure CalcularDebitoTicket( ATicket: Int64; AOperador: Integer);
    procedure CalcularDescontoCupomFiscal(ATicket: Int64; ACupom, APDV: Integer;
      AData: TDateTime; AValor: Currency; AOperadorCaixa: Integer);
    procedure PagarTicketLiberarCancela( ATicket: Int64; AOperadorCaixa: Integer );
    procedure EstornarTicketEstacionamento( ATicket: Int64; AOperadorCaixa: Integer );
    procedure EstornarDescontoCupomFiscal(ATicket: Int64; APDV, ACupom, AOperador: Integer; AData: TDateTime; AEmCupomFiscal: Boolean = False);
    procedure LiberarTicketEstacionamentoSemPagar( ATicket: Int64; AOperadorCaixa: Integer );
    function GetEstadoPapel: RawUTF8;
    property EstadoPapel: RawUTF8 read GetEstadoPapel;
    function NotificarStatusPapel: Boolean;
    function RetornarDataHoraServidor: TDateTime;
    function PossuiFaixaDesconto: Boolean;
  end;

#44 mORMot 1 » Can I use the TSQLHttpClientWinSock in windows? how? » 2013-06-06 14:42:04

Roberto Schneiders
Replies: 7

I can easily choose to use TSQLHttpClientWinSock instead of TSQLHttpClientWinHTTP?

I have some customers using our applications for windows on Linux with Wine. And is not working, I imagine the TSQLHttpClientWinSock solve it, but do not know how to use it.

I found this in SynCrtSock.pas:

{$ifdef MSWINDOWS}
  {$define USEWININET}
  /// define this to publish TWinINet / TWinHttp / TWinHttpAPI classes
{$else}
  {$undef USEWININET} // WinINet / WinHTTP / HttpAPI expect a Windows system
{$endif}

and this in mORMotHttpClient:

{$ifdef USEWININET}
  /// HTTP/1.1 RESTFUL JSON default mORMot Client class
  // - under Windows, map the TSQLHttpClientWinHTTP class 
  TSQLHttpClient = TSQLHttpClientWinHTTP;
{$else}
  /// HTTP/1.1 RESTFUL JSON deault mORMot Client class 
  // - not unders Windows, map the WinSock implementation class
  TSQLHttpClient = TSQLHttpClientWinSock;
{$endif}

But I do not want to change the framework. Especially, compilation directives.

#45 Re: mORMot 1 » ServiceRegister and TServiceInstanceImplementation in Client Side » 2013-05-08 11:15:56

ab wrote:
Calculator := Client.GetService<ICalculator>;

is a valid Delphi syntax, which I just implemented with a new TSQLRest.Service<T: IInterface> method.

For newer generic-aware versions of Delphi (i.e. Delphi 2010 and up, since Delphi 2009 is buggy about generics), you can use such a method, which enabled compile-time checking:

var I: ICalculator;
begin
  I := Client.Service<ICalculator>;
  if I<>nil then
    result := I.Add(10,20);
end;

Excellent. Thank you.

ab wrote:

See http://synopse.info/fossil/info/783a67b6d3
(feel free to propose any other syntax extension using generics)

BUT

Client.GetService(ICalculator,Calculator);

will never compile.
There is not "class of IMyInterface" kind of type, as we have "class of TMyClass" in the Delphi syntax, AFAIK.
This is why we are required to use TypeInfo(ICalculator).

In fact, Client.Service<ICalculator> is just a wrapper around Clients.Services.Info(TypeInfo(ICalculator)).Get().

It is true. Sorry.

#46 Re: mORMot 1 » ServiceRegister and TServiceInstanceImplementation in Client Side » 2013-05-03 17:27:20

ab wrote:

The ICalculator is the contract.

It is to be shared between client and server.

It is IMHO a much better approach than generating a client.
In SOAP/WCF it is just a nightmare to generate clients wrappers, from my experiment.

Whereas a shared unit with the interface type definition is just clean and easy.

That is ok. I agree.

ab wrote:

You have to use the overloaded method, using the RTTI, i.e. TypeInfo(ICalculator).

Using generics, we may be able to write something like:

Client.GetService<ICalculator>(Calculator);

but I do not think it is better than:

Client.GetService(TypeInfo(ICalculator),Calculator);

... and will generate much more code.

Certainly any of these methods would already be great. Some of them already exist?
How I have not found this method in class TSQLHttpClient, I deduce not!

I like the implementation with generics, but as it only works in the newer versions of Delphi is not very useful for us.
An even simpler implementation without generics, might look like:

Client.GetService(ICalculator,Calculator);

with generics:

Calculator := Client.GetService<ICalculator>;

#48 Re: mORMot 1 » TSQLModel - Managing dependencies » 2013-05-03 17:10:13

Sometimes I do not know if you're for or against my implementation.  Let's try to clarify.

ab wrote:

AFAIK the client model can not contain all the classes available on the server.
Only the classes the client needs are expected to be part of the model.
Unless you use a TSQLRecordReference kind of field.

I think there may be cases where the client has access to all the classes available on the server. But that's okay. Let's say that the model (SQLModel) client has only a part of the classes that are on the server model. This will slightly change my implementation. But it is still possible.

ab wrote:

Use case of the TSQLModel instance is to be defined in a given object context.
To ensure re-entrance of the classes.
Using such a global model will add a dependency, and will break the dependency inversion model for sure.

I do not understand what you mean by "Use case of the TSQLModel instance is to be defined in a given object context.";

My implementation does not differ so much from the implementation you used in the "CreateSampleModel". However, the "CreateSampleModel" has only one entity. In case you have multiple entities the implementation would be slightly different, I guess. And if not, the unit SampleData.pas (Ex 04) would have to know all the entities.

When you say that my implementation will add a dependency, you mean that all entities will depend on another unit, in my case, EntidadesPublicas.pas?
Regard this entities will have to be shared between several projects. Create a dependency of another unit, also shared, is a problem?

What would you change in my implementation?
You would drive EntidadesPublicas.pas know all the entities and create the model from them?

lele9 wrote:

see MainDemo.
you can find that ab use TFileServer and TFileClient classes like your purpose.

I'm sorry, but this demo is very confusing.

#49 mORMot 1 » Different permissions for each entity (TSQLRecord), is it possible? » 2013-05-03 13:43:32

Roberto Schneiders
Replies: 3

I would like to allow the client to use a read-only entity. Is it possible?

Only the server will write data to that entity and I would like to ensure that developers do not implement a change in a client application.

#50 Re: mORMot 1 » ServiceRegister and TServiceInstanceImplementation in Client Side » 2013-05-03 13:33:53

Got it. I'm thinking of a way to facilitate the use of interfaces for developers. But not reached a conclusion yet. Imagine that developers who make the server are not the same that will implement the client.

Another thing. I'm not pleased about having to use an identifier of type String to get the service. Like that:

var
  Calculator: ICalculator;
begin
  Client.Services['Calculator'].Get(Calculator);
end;

It would not be possible to have something like this?

var
  Calculator: ICalculator;
begin
  Client.GetService(Calculator);
end;

Maybe we can get the identifier via RTTI, what do you think?

Board footer

Powered by FluxBB