You are not logged in.
No need to free.
From docs:
4.4.1. TDocVariant documents
...
Instance life-time is managed by the compiler (like any other variant type), without the need to use interfaces or explicit try..finally blocks;
I have introduced a new TDocVariantData.InitJsonFromFile method.
Very good, thanks.
This is something to pay attention.
doc.InitObject(['value', 1.012345678]);
FileFromString(doc.ToJson(), 'test.json');
doc.InitJson(StringFromFile('test.json'));
writeln(FloatToStr(doc.D['value'])); // print 0 because 'value' are a string now
After having problems with this conversion, when saving and loading a json, I'm just using string for the doubles.
From 4 decimal places double is quoted as a string.
What I don't understand in your example is why "pi" wasn't quoted as a string.
Expected would be:
{"FloatLong":"3.14159265358979","FloatShort":3.1415,"Pi":"3.14159265358979"}
hi ab,
Using the same topic about tdocvariant.
From certain decimal places on a double value json is no longer recognized as valid.
Is this expected behavior?
NOTE: I know about the loss of precision, and that I can use the dvoAllowDoubleValue option. Just checking if it's expected.
v := _JSON('{"value":0.001}'); //ok
v := _JSON('{"value":0.00001}'); //not recognized as valid json
I have converted Project31SimpleEchoServer to mormot2 to do some tests:
https://github.com/devaex/ClientServerWebSocketSample
Thanks for clarification
Hi ab,
We are referring to that in one part of the documents it says that it returns UTC and in another the local time.
mormot1
SynDB.pas
/// the current Date and Time, as retrieved from the server
// - note that this value is the DB_SERVERTIME[] constant SQL value, so
// will most likely return a local time, not an UTC time
mORMot.pas
/// the current UTC Date and Time, as retrieved from the server
// - this property will return the timestamp as TTimeLog / Int64
mormot2
motmot.db.sql.pas
/// the current Date and Time, as retrieved from the server
// - note that this value is the DB_SERVERTIME[] constant SQL value, so
// will most likely return a local time, not an UTC time
I believe you can use TSynTimezone for this:
localtime = UtcToLocal(TimeLogToDateTime(Server.ServerTimeStamp), 'Your Timezone');
See: https://synopse.info/forum/viewtopic.php?id=5976
But docs says:
/// the current Date and Time, as retrieved from the server
// - note that this value is the DB_SERVERTIME[] constant SQL value, so
// will most likely return a local time, not an UTC time ...
property ServerTimestamp: TTimeLog
Thanks ab,
I was initially searching for an TRestHttpAsyncServer , but it's even simpler than that.
Hi ab,
To use the new async features with TRestHttpServer just use useHttpAsync option?
You should be able to register several services per server, for sure.
Okay, ab.
Strangely, in my real application I experience freezes and slowdowns that I can't reproduce in the WebSocketChat sample.
The difference is that in the application the server is running in a daemon.
I'm going to modify the WebSocketChat to do more testing.
Updates to the posts above, both resolved
It seems that after the last updates the server doesn't accept new connections when the client disconnects.
Reproducible through the example project.
https://github.com/devaex/ClientServerWebSocketSample
1 - Connect to server with 1 client only
2 - Disconnect
3 - The server no longer accepts new connections and freezes.
Update: This is caused by the -gh option (report memory leaks) in Server.
The error went away after disabling. And it only occurs on Linux.
But it sounds like if our WebSockets support is a bit unstable on mORMot 2.
So any feedback is welcome.
I'm getting random 404 on the client side.
Same machine, and right after opening server and client, so it's not related to downtime.
It occurs much more frequently on linux than on Windows. On Windows it is rare, on linux it is constant.
TInterfacedObjectFakeClient.FakeCall(IClientService.ListDetails) failed: 'URI root/ClientService.ListDetails[] returned status 'Not Found' (404 - Network problem or request timeout)'
Note: I'm registering 2 services on the server.
And I'm pretty sure this only happens when I register more than one service.
Because it hasn't happened yet when I removed one of the services.
But I still need to run more tests to confirm.
Update: I'm not sure I can actually register more than one service on the same server. Maybe this really isn't supported.
Resolved by creating a server for each service.
Error: Compilation raised exception internally
Lazarus 2.0.10 + FPC 3.2.0 Win 32.
PUREMORMOT2
Edit: The problem seems to be in LoadFromFile when the file doesn't exist.
It also occurs on Windows and even creating the instance.
I believe that in TSynTimeZone.LoadFromFile the existence of the file must be checked, because if an empty string is passed, as CreateDefault does, it tries to load a file that might not exist.
And pass a empty string to LoadFromBuffer.
procedure TSynTimeZone.LoadFromFile(const FileName: TFileName);
var
FN: TFileName;
begin
if FileName = '' then
FN := ChangeFileExt(Executable.ProgramFileName, '.tz')
else
FN := FileName;
LoadFromBuffer(StringFromFile(FN)); <-- if FileName are empty or invalid pass a empty string to LoadFromBuffer
end;
Hi ab,
Lazarus 2.0.10 + FPC 3.2.0 Win 32 Cross compiling to Linux x64.
Ubuntu 20.04.2 LTS (GNU/Linux 5.11.0-1016-oracle x86_64)
This is an instance in oracle's "Always Free", but running on x86_64 / not ampere Aarch64.
Sample project:
https://github.com/devaex/TestTimeZone
My findings:
Creating an instance works.
But when calling the TSynTimeZone.Default instance, the error occurs.
Yes tests pass, but from what I saw, TTestCoreBase.TimeZones don't test using TSynTimeZone.Default, on linux.
writeln(TSynTimeZone.Default.NowToLocal('UTC')); <-- error here
On Linux only, I'm getting "EFastReader: Reached End of Input" when trying to load timezones, either using file or resource.
On Windows it works OK, even loading from very same file.
Really everything is ok.
The Settings property was removed in the update, and for inattention, for the project to compile I commented the entire line including WebSocketsEnable.
Sorry for the inconvenience
// HttpServer.WebSocketsEnable(Server,PROJECTEST_TRANSMISSION_KEY).Settings.SetFullLog;
Hi ab, after this last update I'm getting a 404 timeout on the server when calling any callback method.
It can be verified in the same example:
https://github.com/devaex/ClientServerWebSocketSample
EInterfaceFactory {Message:"TInterfacedObjectFakeServer.FakeCall(IChatCallback.NotifyBlaBla) failed: 'TWebSocketServerRest.Callback(2) received status=404 from root/ChatCallback.NotifyBlaBla/1'"}
Both Server and Client compiled with lastet version.
Complete log:
https://gist.github.com/devaex/b06194e8 … ab28325767
Thanks ab, working fine with these updates.
As it is information extracted from Windows, I don't know if there may be any problem in making this file available in the repository.
Maybe it's better that each one does the extraction.
LoadFromRegistry/SaveToFile simplify a lot.
Thank you for the detailed explanations.
The server needs to get the date from a file with FileAgeToDateTime and pass it to the client in UnixTimeUTC.
As a temporary solution I used UnixTime - UnixTimeUTC to find the difference in hours and make the adjustment.
It works in this specific case but obviously there must be situations where this fails.
I was trying to avoid TSynTimeZone so I wouldn't have to deal with extracting data from the Windows registry to use on Linux.
But I'm going to use it to do it right.
Making TSynTimeZone thread safe helps a lot.
Thank you for the changes.
Probably a silly question, but is there any way to convert a TDateTime to UnixtimeUTC without using TSynZone?
Forget about it, my mistake.
Analyzing better the memory leak I saw that could be due to logs being generated for the console.
The logs are sending the entire content of the request to the console.
Fixed reducing logs level and/or disabling the output to console.
I'm playing with Websockets and when using a rawbytestring parameter the server freezes at some point to process the request.
IRunService = interface(IServiceWithCallbackReleased)
...
procedure CacheContentInServer(const ACacheName: String; AContent: RawByteString; out ASaved: Boolean; out AError: String);
end;
I didn't get many clues in the debug but it caused a memory leak:
https://gist.github.com/devaex/d6b7ad7c … 9fd811e8af
The error disappeared when changing the parameter to RawUtf8.
For my case, the correct type would be RawUft8 because the content are text.
But I believe this will be a problem for anyone who needs to send binary content with RawbyteString.
mormot2 + Lazarus + FPC Win32 + Cross to Win 64.
I assumed it was something unrelated to mormot.
Thanks for reply.
Sample project to reproduce:
https://github.com/devaex/QuickJsTest
With packages
Note: I don't use win32, I'm just reporting the problem I found by "accident".
Yes, I'm using it from now on.
Thank you ab,
Issue resolved in this latest update.
These are my first tests with websockets and mormot, any observation I can tell.
Good news about the asynchronous http server.
Hadn't noticed this new feature, I'll see.
Good tip about packages. It is already installed to run the tests.
I will use it from now.
When application are compiled for win32, and evaluating some javascript with "var d = new Date(..)", causes an exception.
ELibStatic {Message:"Panic in quickjs2.c:15702: assert(list_empty(&rt->gc_obj_list))"} [Main] at 436b27
The exception occurs at the exact moment that "new Date()" is used, not in Runtime.done...
Lazarus + FPC Win32
When cross compiled to Win64 run without errors.
Hi @ab,
I have converted Project31ChatClient to "pure" mormot2.
Everything works correctly, but when disconnecting the client it generates "IInvokable has no GUID" error on the server, and as a consequence a memory leak.
log
mormot.rest.memserver.TRestServerFullMemory(015ed360) TRestServerRoutingRest.Error: { "errorCode":406, "error": {"EInterfaceFactory": { "ClassName": "EInterfaceFactory", "Address": "tinterfacefactory.create", "Message": "TInterfaceFactoryRtti.Create: IInvokable has no GUID" }} }
mormot.core.interfaces, 3734
...
if IsNullGuid(fInterfaceIID) then
raise EInterfaceFactory.CreateUtf8(
'%.Create: % has no GUID', [self, aInterface^.RawName]); <<--- here
Lazarus + FPC Win 32
Cross compiled to Win x64
Solved with TProcess from FP.
Process := TProcess.Create(nil);
...
Process.InheritHandles := False;
Process.Options := [];
Process.ShowWindow := swoNone;
Process.Executable := '/home/ubuntu/app/targetapp';
Process.Parameters.Add('myParam');
Process.Execute;
Secondary app run detached.
Hello,
A need to start a secondary console application inside the daemon, and not wait for execution.
When using RunProcess (or RunCommand) inside a daemon, the target application does not start and generates the error "File not open".
- Both Daemon App and Target dont uses Writeln.
- When running the very same Daemon as console (./mydaemon --console), works fine.
- When using Free Pascal native process.RunCommandIndir method works inside the Daemon, but dont have the option to "not wait".
procedure TDaemon.Start;
try
mormot.core.os.RunProcess('/home/ubuntu/app/targetapp', 'myParam', false);
except
on E : Exception do
FileFromString('Error: ' + E.Message, 'error.txt'); //Write: File not open
end;
Thank you for the informations.
I'll see more about this in QuickJs documentation.
As I understand it would not be necessary to create a runtime per thread.
I'm going to test if there are any performance and resource utilization benefits.
Hi @ab,
Is this implementation Thread safe, right?
Both the runtime and context will be created, and used inside the thread.
Any concerns I should consider when running inside threads?
procedure TMyThread.execute;
var
ctx : JSContext;
rt: JSRuntime;
begin
rt := JS_NewRuntime;
ctx := rt.New;
...
ctx.Done;
rt.Done;
end;
Thanks ab,
I updated and removed mormot.lib.static.pas from uses.
Now it compiles for Win32 but Win64 keeps asking for these functions, because LIBDEFLATESTATIC is not defined for it.
But it's ok, I'll leave mormot.lib.static.pas in the project.
mormot.defines.inc
{$ifdef OSWINDOWS}
{$ifdef CPUX86}
{$define LIBDEFLATESTATIC}
{$define LIBQUICKJSSTATIC}
{$endif CPUX86}
{$ifdef CPUX64}
{.$define LIBDEFLATESTATIC} // Win64 + FPC 3.2 = internal error 200603061 <<-------
{$define LIBQUICKJSSTATIC}
{$endif CPUX64}
{$endif OSWINDOWS}
Sorry for taking your time.
I was ignoring that it was necessary to include mormot.lib.static.pas.
Solved.
i'm working on my first application using mormot2 + orm and i'm getting this same error when compiling.
Undefined symbol: memcpy (and the same about memset, malloc, free)
Lazarus 2.0.10 Win32
FPC 3.2.0
Win32 - Same error
Cross compile Win64 - Same error
Cross compile Linux64 - OK
Mormot2 with latest updates on git and latest static files (from git releases).
...I think Delphi IDE is more comfortable than Lazarus at a few points.
I had this feeling about Delphi too.
But when I started using Lazarus more deeply this changed.
Some links that may be of interest to you
Several really useful tips using the editor
https://wiki.lazarus.freepascal.org/Lazarus_IDE_Tools
Use pascal macros (to duplicate / move lines, etc.)
https://forum.lazarus.freepascal.org/in … 907.0.html
Docked IDE like Delphi.
http://newpascal.org/docked.html
You have already done some testing of an application compiled in delphi running on different distributions of Linnux?
When I tested the portability are not good. I had several link problems.
I never tested it again and I don't know how it is now.
But with FPC the same executable runs perfectly in different distributions.
You can use a daemon as mentioned by mpv to run in the background.
If you want the console window to be visible, use a WriteLn()...
begin
...
fHttpServer := TSQLHttpServer.Create(FISHSHOP_PORT, fServer);
try
writeln('Server running. Press any key to stop...');
finaly
fHttpServer.Free;
....
end;
end.
Maybe related to codepage?
Edit: I am not able to reproduce your problem. The regression tests have no issue with C functions.
Thanks ab, it's working now.
It was necessary to adapt the type of parameters.
From
function Log(ctx: JSContext; this_val: JSValueConst; argc: Integer; argv: PJSValueConstArr): JSValue; cdecl;
to
function Log(ctx: JSContext; this_val: JSValueRaw; argc: Integer; argv: PJSValues): JSValueRaw; cdecl;
Yes, is suported.
Example of how get post content as json
procedure TMBService.MyPostRequest(Ctxt: TSQLRestServerURIContext);
var j: variant;
begin
if (Ctxt.Method = mPOST) and (Ctxt.Call^.InBodyTypeIsJson(True)) then
j := _JsonFast(Ctxt.Call^.InBody);
end;
Has anything changed in this final version regarding the registration of functions?
The same example I posted above is not working now.
//registration
global := JS_GetGlobalObject(ctx);
JS_SetPropertyStr(ctx,global,'log',JS_NewCFunction(ctx, @log, 'log', 1));
...
function Log(ctx: JSContext; this_val: JSValueConst; argc: Integer; argv: PJSValueConstArr): JSValue; cdecl;
begin
//when this function is called argc is 20965536 and argv is empty
end;
Thank, @ab for this great addition.
I created a small pull request to add "mormot.lib.static" to the uses. Required by Before/AfertLibraryCall.
https://github.com/synopse/mORMot2/pull/23
Sharing some code. I hope this is the correct way to start using it.
var
ctx : JSContext;
rt: JSRuntime;
global : JSValueRaw;
begin
rt := JS_NewRuntime;
try
ctx := rt.New;
try
global := JS_GetGlobalObject(ctx);
JS_SetPropertyStr(ctx,global,'log',JS_NewCFunction(ctx, @log, 'log', 1));
ctx.Free(global);
Memo1.Lines.Add(ctx.EvalGlobal(SynEdit1.Lines.Text, 'code'));
finally
ctx.Done;
end;
finally
rt.Done;
end;
end;
I just saw that the quikjs is already in the mORMot2.
I'll try.
Thanks
TSynTests is not accepting the creation of the instance:
with TSynTestsLogged.Create('mORMot2 Regression Tests') do
try
...
finally
end;
Exception on SETPARSERTYPE, line 9658 of ../../../../mORMot2/trunk/src/core/mormot.core.json.pas
Edit: I forgot that it is necessary to disable -CR option in project properties.
SyNode looks excellent.
But I'm trying to add script support to an application, and I confess that I'm a little lost with versions.
I'll even try to add the LUA, as I don't need compatibility with Node.js and other more sophisticated features.
QuickJS and or ChakraCore, will be good additions.