#201 Re: mORMot 1 » mORMot and ScaleMM = AV » 2015-04-09 17:24:23

After few hours debugging... yes, you are right! :-)

I destroyed TSQLModel before TSQLRestServer which used it!

But why at FastMM I had no error? It was set to full debug mode. This is magic ;-)

ps. I use ScaleMM3 (not stable version 2).

ps. SynScaleMM is ready/stable and I can use it?

thx for support
best regards

#202 mORMot 1 » mORMot and ScaleMM = AV » 2015-04-09 13:16:40

jaclas
Replies: 2

I wrote a REST server. Everything works fine, but the performance in the threads is low. I changed the memory manager from FastMM to ScaleMM and now performance is high, but I have a new problem. When I close the application I get the AV:

q6Bk5U0a.png

Error raise this code (after press F8):

WMSgnedG.png


Callstack:

mORMot.JSONObject(TClass($649B740),-1,[cpWrite])
mORMot.TJSONSerializer.WriteObject($649B700,[woFullExpand])
mORMot.TJSONSerializer.WriteObject($649BC00,[woFullExpand])
SynCommons.TTextWriter.Add((105495552, False, #0, $649BC00, $649BC00 {':ź'#0#0'·I'#6#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0'ŕąI'#6'ŕ–Ş'#3'”yj'#0#0#0#0#0'PŞ2'#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0}, $649BC00, '|:ź', $649BC00, TClass($649BC00), '?', '?'#$009F'??', $649BC00, $649BC00, $649BC00, $649BC00, $649BC00, $649BC00, $649BC00, 105495552, 7),twOnSameLine)
SynCommons.TTextWriter.Add('%.Destroy -> %',(...),twOnSameLine)
SynLog.TSynLog.LogInternal(sllInfo,'%.Destroy -> %',(...),nil)
SynLog.TSynLog.Log(sllInfo,'%.Destroy -> %',(...),nil)
mORMot.TSQLRest.Destroy

best regards

#204 mORMot 1 » TSQLRestServer.ServiceRegister and ContractExpected parameter » 2015-03-13 10:14:03

jaclas
Replies: 2

Class TSQLRestServer has three methods of registering services:

    function ServiceRegister(aImplementationClass: TInterfacedClass;   const aInterfaces: array of PTypeInfo;
      aInstanceCreation: TServiceInstanceImplementation=sicSingle): TServiceFactoryServer; overload; virtual;

    function ServiceRegister(aSharedImplementation: TInterfacedObject;  const aInterfaces: array of PTypeInfo): TServiceFactoryServer; overload; virtual;

    function ServiceRegister(aClient: TSQLRest; const aInterfaces: array of PTypeInfo;  aInstanceCreation: TServiceInstanceImplementation=sicSingle;
      const aContractExpected: RawUTF8=''): boolean; overload; virtual;

But only one of these methods allows specify a parameter: aContractExpected

Is possible to add aContractExpected parameter to second method too (with aSharedImplementation: TInterfacedObject parameter)?

In this way:

    function ServiceRegister(aSharedImplementation: TInterfacedObject;  const aInterfaces: array of PTypeInfo; 
                                        const aContractExpected: RawUTF8=''): TServiceFactoryServer; overload; virtual;

best regards

#205 Re: mORMot 1 » Client IP on server side in interface based service » 2015-03-13 09:45:50

Oh, sorry, you are right. Thanks for reply :-)


function TServiceBase.MakeSomething : string;
var
 IP : string;
begin
 IP := FindIniNameValue(Pointer(ServiceContext.Request.Call.InHead),'REMOTEIP: ');
end;

#206 mORMot 1 » Client IP on server side in interface based service » 2015-03-12 14:39:24

jaclas
Replies: 2

Hi,

I need in service method (interface-based service) get client IP. How to do it?

IServiceBase = interface(IInvokable)
  function MakeSomething : string;
end;

TServiceBase = class(TInterfacedObject, IServiceBase)
public
  function MakeSomething : string;
end;

[...]

ServiceRegister(fServiceBase, [TypeInfo(IServiceBase)]);

[...]

function TServiceBase.MakeSomething : string;
begin
 [...]  <------------ how get client IP in this place?
end;

best regards

#207 mORMot 1 » Registering interface by ServiceRegister (server side) » 2015-03-05 09:59:30

jaclas
Replies: 1

The examples show how to register in server a class that implements the ICalculator interface.

  ICalculator = interface(IInvokable)
  ['{E7014BA0-007E-4DCB-9C34-4A8CCB2BF9C3}']
   function Suma(A, B : Integer): Integer;
   function GetName : string;
  end;

  TCalculator = class(TInterfacedObject, ICalculator)
  public
    function Suma(A, B : Integer): Integer;
    function GetName : string;
  end;

And now the registration and use:

var
 aModel: TSQLModel;
begin
 aModel := TSQLModel.Create([],ROOT_NAME);
 try
  with TSQLRestServerDB.Create(aModel,ChangeFileExt(paramstr(0),'.db'),true) do
  try
   ServiceRegister(TServiceCalculator,[TypeInfo(ICalculator)],sicShared);
   ExportServerNamedPipe(APPLICATION_NAME);
   readln;
  finally
   Free;
  end;
 finally
  aModel.Free;
 end;
end.

But I would like to register interface on the server, not a object/class. So this:

var
 aModel: TSQLModel;
 liCalculator : ICalculator;
begin
 aModel := TSQLModel.Create([],ROOT_NAME);
 try
  with TSQLRestServerDB.Create(aModel,ChangeFileExt(paramstr(0),'.db'),true) do
  try

   liCalculator := GetImplementorOfInterface(ICalculator); <----- get interface implementation
   ServiceRegister(liCalculator,[TypeInfo(ICalculator)],sicShared); <--------- register instance of interface!

   ExportServerNamedPipe(APPLICATION_NAME);
   readln;
  finally
   Free;
  end;
 finally
  aModel.Free;
 end;
end.

In my code I operate mainly on interfaces, I don't want to mix object access and interface access. In addition, I would like to have separated implementation of interfaces, because I can easily swap between the implementations (on configuration level).

Is this possible? Can you add this functionality? :-)

thx

#208 mORMot 1 » Serious error in SynCommons.GetExtended; » 2015-02-20 09:03:52

jaclas
Replies: 1

Hi,

I rebuilt example 14 (with a calculator) to work on the numbers of type Double (from Integer).

  ICalculator = interface(IInvokable)
    ['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}']
    function Add(n1,n2: Double): Double;
  end;

[...]

  TServiceCalculator = class(TInterfacedObject, ICalculator)
  public
    function Add(n1,n2: Double): Double;
  end;

Then now I get error in server (SynCommons.GetExtended):

Breakpoint on GetExtended:

20150220-8f8z-14kb.jpg

After Step Over (F8):

m_20150220-rgp8-32kb.jpg

#210 Re: mORMot 1 » Creating TSQLHttpServer without TSQLRestServer » 2015-02-19 13:40:55

And?

How create TSQLHTTPServer with empty "aServers" parameter in constructor?
I need it.

#211 Re: mORMot 1 » Creating TSQLHttpServer without TSQLRestServer » 2015-02-17 19:38:22

I know. But I need create TSQLHttpServer WITHOUT TSQLRestServer(s) parameter in constructor (mORMmot forcing me to do this).

You did not understand me, my english is crooked, sorry :-)

When I execute this line:

server := TSQLHttpServer.Create('808', [], '+', useHttpApi, 8); 

I get exception from TSQLHttpServer constructor:

  if ErrMsg<>'' then
     raise EModelException.CreateUTF8('%.Create(% ): %',[self,ServersRoot,ErrMsg]);

where ErrMsg is 'No TSQLRestServer'

And I need to create a HTTP server without TSQLRestServer (rest server I will add later).

When I modify TSQLHttpServer constructor (wrong, I know, but temporary, for test only):

constructor TSQLHttpServer.Create(const aPort: AnsiString;
  const aServers: array of TSQLRestServer; const aDomainName: AnsiString;
  aHttpServerKind: TSQLHttpServerOptions; ServerThreadPoolCount: Integer;
  aHttpServerSecurity: TSQLHttpServerSecurity; const aAdditionalURL: AnsiString;
  const aQueueName: SynUnicode);
var i,j: integer;
    ServersRoot: RawUTF8;
    ErrMsg: RawUTF8;
begin
  [...]
  if high(aServers)<0 then
    ErrMsg := 'No TSQLRestServer' else
  for i := 0 to high(aServers) do
    if (aServers[i]=nil) or (aServers[i].Model=nil) then
      ErrMsg := 'Invalid TSQLRestServer';
  if ErrMsg='' then
    for i := 0 to high(aServers) do
    with aServers[i].Model do begin
      ServersRoot := ServersRoot+' '+Root;
      for j := i+1 to high(aServers) do
        if aServers[j].Model.URIMatch(Root) then
          ErrMsg:= FormatUTF8('Duplicated Root URI: % and %',[Root,aServers[j].Model.Root]);
    end;

  ErrMsg := '';  <<<-----   my modification, to miss exception

  if ErrMsg<>'' then
     raise EModelException.CreateUTF8('%.Create(% ): %',[self,ServersRoot,ErrMsg]);

then everything works fine, as I expected.

#212 mORMot 1 » Creating TSQLHttpServer without TSQLRestServer » 2015-02-17 11:13:24

jaclas
Replies: 5

Hi,

Is it possible to create instances of the TSQLHttpServer without having to enter TSQLRestServer instance?

I would like in one place the code to create a HTTP server and in other places (controlled by the configuration) add a REST servers.

 TssHTTPServer = class(TSQLHttpServer)
 public
  constructor Create(aHTTPPort: Integer);
 end;

constructor TssHTTPServer.Create(aHTTPPort: Integer);
begin
 inherited Create(aHTTPPort.ToString, [], '+', useHttpApi, 8); // [] <----- I want to create HTTP server without SQLRestServers 
end;

var
 httpserver : TssHTTPServer;

begin
 httpserver := TssHTTPServer.Create(808); 
 SomeRestServer := GetServerFromRepo;
 httpserver.AddServer(SomeRestServer);

At this moment the order is reversed, I must first have a REST server and then create HTTP server :-(

best regards

#213 Re: mORMot 1 » Subclass TSQLAuthUser » 2015-02-11 12:11:52

Hello,

You wrote in docs:

"The Server will search for any class inheriting from TSQLAuthGroup and TSQLAuthUser in its Model. By
default, you can use plain TSQLAuthGroup and TSQLAuthUser classes - and if none is defined in the
model, and authentication is enabled, those mandatory classes will be added. But you can inherit from
TSQLAuthGroup and TSQLAuthUser, and define e.g. your own fields, for any custom purpose at Group
or User level."

TSQLAuthUser class contains published properties:
   LogonName property: RawUTF8
   DisplayName property: RawUTF8
   PasswordHashHexa property: RawUTF8
   GroupRights property: TSQLAuthGroup
   Date: TSQLRawBlob

If I want to have my own table with users I should inherit from TSQLAuthUser, but it will make the original field will be in my class. Is it possible to delete these fields from the model?
I would like to my TMySQLAuthUser class had only those fields which I'll define.

--
best regards

#214 mORMot 1 » Server off-line, client raises strange exception » 2014-12-22 12:59:28

jaclas
Replies: 1

Hi,

When I turn off the server (off-line) and when I call from the client the service registration method:


     CalcClient: TSQLHttpClientWinHTTP;
     [...]
     CalcClient.ServiceRegister ([TypeInfo (ICalculator)], sicShared);

then mORMot mapping connection error to HTML_NOTIMPLEMENTED connection (code 501), why?

w1ho3T1v.png

At a later stage this error is resolved as:

'TServiceFactoryClient.Create (): ICalculator TSQLRestRoutingREST routing interface or not supported by server:'

by this code in TServiceFactoryClient.Create(...) method:

  if not InternalInvoke(SERVICE_PSEUDO_METHOD[imContract],'',@RemoteContract,@Error) then
    raise EServiceException.CreateUTF8('%.Create(): I% interface or % routing not '+
      'supported by server%',[self,fInterfaceURI,fRest.ServicesRouting,Error]);

Why not "connection error"?

--
best regard
Jacek

#216 mORMot 1 » CrossPlatform and Connection Timeout problem » 2014-10-07 15:52:23

jaclas
Replies: 2

Hi,

I'm trying to use CrossPlatform client and encountered a problem when I need to define Connection Timeout.
When I do not set Connection Timeout on Android then the connection to the server off (eg. when server is down) lasts nearly seven minutes! During this time an application is not responding (is suspended). I found a place where it should be set Connection Timeout.

In unit SynCrossPlatformSpecific.pas, in procedure TIndyHttpConnectionClass.URI():

    fConnection.ConnectTimeout := MY_CONNECTION_TIMEOUT_VALUE;     //in this place I add my code
    if Call.Verb='GET' then // allow 404 as valid Call.OutStatus
      fConnection.Get(fURL+Call.Url,OutStr,[HTML_SUCCESS,HTML_NOTFOUND]) else
    if Call.Verb='POST' then
      fConnection.Post(fURL+Call.Url,InStr,OutStr) else
    if Call.Verb='PUT' then
      fConnection.Put(fURL+Call.Url,InStr) else
    if Call.Verb='DELETE' then
      fConnection.Delete(fURL+Call.Url) else
      raise Exception.CreateFmt('Indy does not know method %s',[Call.Verb]);

This setting causes the application returns control at the specified time.
Is possible to add properties to these settings at TSQLRestClientURI? And then pass them along with other parameters by TSQLRestURIParams? Or in any other similar manner?

Another option is to provide your own implementation TAbstractHttpConnection class, by indicating the type of class in any other way than by the following function:

function HttpConnectionClass: TAbstractHttpConnectionClass;
begin
  result := TMyHttpConnectionClass;
end;

Maybe it would be good to put this function in the TSQLRestClientHTTP class?

TSQLRestClientHTTP = class
[...]
public
  function HttpConnectionClass: TAbstractHttpConnectionClass; virtual;
end; 

Or pass it as a procedural type?

type
 TAbstractHttpConnectionClassFunction = function HttpConnectionClass: TAbstractHttpConnectionClass;

TSQLRestClientHTTP = class
private
 fHttpConnectionClassFunction : TAbstractHttpConnectionClassFunction;
[...]
public
 property HttpConnectionClassFunction : TAbstractHttpConnectionClassFunction write fHttpConnectionClassFunction;
end;

The same applies to the Read Timeout parameter.

best regards
Jacek

#217 mORMot 1 » Events » 2014-09-12 13:47:39

jaclas
Replies: 1

Hi,

http://blog.synopse.info/post/2012/09/0 … laboration

"On the mORMot roadmap, we added a new upcoming feature, to implement one-way callbacks from the server.
[...]
Some callback interface may be registered via a new EventRegister() method - similar to ServiceRegister() - on both TSQLRestClient and TSQLRestServer sides.
In fact, a callback / event can be seen as a service, but in the reverse order: from server to client."

That was two years ago (september 2012).
Is there a chance that this functionality will soon appear?

kind regards
Jacek

Board footer

Powered by FluxBB