You are not logged in.
Pages: 1
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.
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.
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.
Hello ab.
Any suggestion about it?
Thanks.
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?
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.
Is it possible to do Incremental search with unicode chars?
OK.
Is It right way to use timer to purge deprecated locks on server side?
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;
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?
It may be called from client application?
Hello,
Can you see why
2. There is a timeout on server side.
does not works?
Regards.
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".
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.
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.
Pages: 1