#1 Re: mORMot 1 » Possible bug in mORMot.TTypeInfo » 2015-09-01 14:33:53

Thanks ab.

In SynSelfTests.pas you added:

with PTypeInfo(TypeInfo(WordBool))^.EnumBaseType^ do
  Check(SizeInStorageAsEnum=2);

It would be better to change it like this:

with PTypeInfo(TypeInfo(WordBool))^.EnumBaseType^ do
  Check(SizeInStorageAsEnum=SizeOf(WordBool));

Regards.

#2 Re: mORMot 1 » Possible bug in mORMot.TTypeInfo » 2015-09-01 10:02:22

More details:

Shared.pas

unit Shared;

interface

const
  ROOT_NAME = 'root';
  PORT_NAME = '888';
  APPLICATION_NAME = 'TestMormot';

type
  ITest = interface(IInvokable)
    ['{35F48518-9622-448C-9670-18B77EBD9179}']
    procedure TestProc(out AWStr: WideString; out AWBool: WordBool);
  end;

implementation

uses mORMot;

initialization

TInterfaceFactory.RegisterInterfaces([TypeInfo(ITest)]);

end.

TestMormotServer.dpr

program TestMormotServer;

{$APPTYPE CONSOLE}

uses
  {$I SynDprUses.inc}
  SysUtils,
  Classes,
  SynCommons,
  mORMot,
  mORMotHttpServer,
  Shared in 'Shared.pas';

type
  TServiceTest = class(TInterfacedObject, ITest)
  public
    procedure TestProc(out AWStr: WideString; out AWBool: WordBool);
  end;

procedure TServiceTest.TestProc(out AWStr: WideString; out AWBool: WordBool);
begin
  AWStr := 'test';
  AWBool := False;
end;

var
  Model: TSQLModel;
  Server: TSQLRestServer;
  HTTPServer: TSQLHttpServer;
begin
  Model := TSQLModel.Create([], ROOT_NAME);
  try
    Server := TSQLRestServerFullMemory.Create(Model, 'test.json', false, True);
    try
      Server.ServiceDefine(TServiceTest, [ITest], sicShared);
      HTTPServer := TSQLHttpServer.Create(PORT_NAME, [Server], '+', useHttpApiRegisteringURI);
      try
        Writeln('server started');
        Writeln('press enter to exit');
        Readln;
      finally
        HTTPServer.Free;
      end;
    finally
      Server.Free;
    end;
  finally
    Model.Free;
  end;
end.

TestMormotClient.dpr

program TestMormotClient;

{$APPTYPE CONSOLE}

uses
{$I SynDprUses.inc}
  SysUtils,
  Classes,
  SynCommons,
  mORMot,
  mORMotHttpClient,
  Shared in 'Shared.pas';

var
  Model: TSQLModel;
  Client: TSQLRestClientURI;

procedure TestProc;
var
  Test: ITest;
  I: Integer;
  WStr: WideString;
  WBool: WordBool;
begin
  if Client.Services['Test'].Get(Test) then
    try
      Writeln('client started');
      for I := 0 to 1000 do
      begin
        Test.TestProc(WStr, WBool);
        if (WStr <> 'test') or WBool then 
          Writeln(Format('%s <> ''test''', [WStr])); //here raised accees violation
      end;
    finally
      Test := nil;
    end;
end;

begin
  Model := TSQLModel.Create([], ROOT_NAME);
  try
    Client := TSQLHttpClient.Create('localhost', PORT_NAME, Model);
    try
      Client.ServerTimeStampSynchronize;
      Client.SetUser('User', 'synopse');
      Client.ServiceDefine([ITest], sicShared);
      TestProc;
    finally
      Client.Free;
    end;
  finally
    Model.Free;
  end;
  Writeln('press enter to exit');
  ReadLn;
end.

Accees violation is raising when WStr(WideString) and WBool(WordBool) params are stack allocated (e.g. local variables).
if this params are declared as global variables then no exception happens.

IMHO, problem is in procedure InternalProcess (TInterfacedObjectFake.FakeCall's internal procedure).

procedure InternalProcess;
...
  case ValueType of
    smvBoolean, smvEnum, smvSet, smvCardinal:
      case SizeInStorage of
        1: PByte(V)^     := GetCardinal(Val);
        2: PWord(V)^     := GetCardinal(Val);
        4: PCardinal(V)^ := GetCardinal(Val);
      end;
...
end;

SizeInStorage is 4 and must be 2.

Thanks.

#3 mORMot 1 » Possible bug in mORMot.TTypeInfo » 2015-08-31 15:27:27

Firali
Replies: 3

Hello,

I have WordBool params in methods of my legacy DCOM interface. When I ported this interface to mormot, sometimes output param pointers is broken.

I have found strange behavior of mORMot.TTypeInfo.

var
  wb: WordBool;
  pt: PTypeInfo;
  ValueType: TServiceMethodValueType;
  SizeInStorage: Integer;
  RealSize: Integer;
begin
  pt := TypeInfo(WordBool);
  ValueType := TypeInfoToMethodValueType(pt);
  //ValueType = smvEnum
  SizeInStorage := pt^.EnumBaseType^.SizeInStorageAsEnum;
  //SizeInStorage = 4
  RealSize := SizeOf(wb);
  //RealSize = 2
  if SizeInStorage <> RealSize then
    raise Exception.Create('SizeInStorage <> RealSize');
end;

Must be different SizeInStorage and RealSize?

Thanks.

#5 Re: mORMot 1 » VersionID in TSQLRecord » 2015-02-16 20:28:28

OK, but there are some questions more...

For example, there are two client app and one server app. Logical steps is like this:

1. Client_1 locks some record.
2. Some process purges this lock on server side.
3. Client_2 locks same record.
4. Client_1 updates record.

Must Client_1 be able to update record?

#6 Re: mORMot 1 » TSQLTableToGrid: Incremental search with unicode chars » 2015-02-16 19:31:40

Problem is in mORMotUI.pas unit on line 1353

fIncrementalSearch := fIncrementalSearch+RawUTF8(NormToUpper[AnsiChar(Key)]);

"Key" is Char and is casted as AnsiChar.

Also Table.SearchValue function does not works with unicode chars.

#7 mORMot 1 » TSQLTableToGrid: Incremental search with unicode chars » 2015-02-15 14:22:12

Firali
Replies: 3

Is it possible to do Incremental search with unicode chars?

#8 Re: mORMot 1 » VersionID in TSQLRecord » 2015-02-15 14:07:06

OK.

Is It right way to use timer to purge deprecated locks on server side?

#9 Re: mORMot 1 » VersionID in TSQLRecord » 2015-02-15 09:41:18

This method must purge on server side, not on client side. Something like this

function TSQLRestClientURI.Lock(aTable: TSQLRecordClass; aID: TID; aPurgeOlderThan: cardinal=30): boolean;
var
  SendData: RawUTF8;
begin
  if (self=nil) then
    result := false
  else
  begin
    SendData := UInt32ToUtf8(aPurgeOlderThan);
    result := URI(Model.getURIID(aTable,aID),'LOCK',nil,nil,@SendData).Lo=HTML_SUCCESS;
  end;
end;

#10 Re: mORMot 1 » VersionID in TSQLRecord » 2015-02-14 16:15:11

It is desired to have method in TSQLRestClientURI class like this

function Lock(aTable: TSQLRecordClass; aID: TID; aPurgeOlderThan: cardinal=30): boolean;

What do you think about it?

#11 Re: mORMot 1 » VersionID in TSQLRecord » 2015-02-14 13:58:17

It may be called from client application?

#12 Re: mORMot 1 » VersionID in TSQLRecord » 2015-02-14 13:22:32

Hello,

Can you see why

ab wrote:

2. There is a timeout on server side.

does not works?

Regards.

#13 Re: mORMot 1 » VersionID in TSQLRecord » 2015-02-09 20:46:28

1. Lock() does not checks if there was any update on this record before and the same problem(Previous change will be lost)
2. I think that there is small bug. TSQLLocks.PurgeOlderThan is called from TSQLModel.PurgeOlderThan and TSQLModel.PurgeOlderThan is not called from nowhere.
3. I am going to use MongoDB with StaticMongoDBRegisterAll. I think that there will not be any problems with two or more server applications if it will have functionality like "VersionID".

#14 Re: mORMot 1 » VersionID in TSQLRecord » 2015-02-09 18:30:29

Thanks for reply.

Retrieve(ForUpdate = True) method has some disadvantages:

1: If you have already list of SQLRecords you must again retrieve data from server(needless network bandwidth).
2: If client application crashes record remained locked.
3: If you have two or more server application (e.g. for horizontal scaling), Retrieve(ForUpdate = True) is not working.

In case of "VersionID" all this disadvantages are solved.

Regards.

#15 mORMot 1 » VersionID in TSQLRecord » 2015-02-09 16:05:08

Firali
Replies: 15

Hello,

I am interested in, that are you going to add some VersionID property to TSQLRecord class and check that, VersionID is same in database during updating record? or may be there is this functionality already?

In real application will be situation, when two user has retrived same record and both is updating data at the same time. After that one change will be cleared without notify to user.

Best regards.

Board footer

Powered by FluxBB