You are not logged in.
Hi,
we have another issue with TSynSystemTime.FromDate, where also minutes...milliseconds are not initialized to 0,
which lead to nasty things...
yes it works. thank you
Even if I use date only, milliseconds part is fixed in some random number:
isotime.FromText('1962-11-13');
dt := isotime.ToDateTime; // fails, because of millisecond part
function TSynSystemTime.ToDateTime: TDateTime;
var time: TDateTime;
begin
if TryEncodeDate(Year,Month,Day,result) then
if TryEncodeTime(Hour,Minute,Second,MilliSecond,time) then // fails !
result := result+time else
result := 0 else
result := 0;
end;
thank you
Yes, but the milliseconds are always 2333 (in my case) and the fuction ToDateTime fails,
because TryEncodeTime fails because milliseconds are greater then 1000.
maybe they should be always 0 then.
Hi, (latest mormot from github, D11.2ent)
if I do:
var isotime: TSynSystemTime;
if isotime.FromText('1962-11-12T21:59:48') then
or
if isotime.FromText('1962-11-12T21:59:48.000') then
result is false, because milliseconds are always 2333.
intialization of values are random numbers (milliseconds are 2333). Also year, ...
Maybe I'm missing soemthing.
thank you,
Vojko
Hi,
is there ?
thank you
I see, very nicely spotted.
thank you
yes,
I've added
if Assigned(Another) then begin
fDynArray.AddDynArray(Another.Data, Offset, Limit);
if (fHasher <> nil) then
fHasher^.ForceReHash;
end;
and it works
hi,
What about hash performance when it is copied from another list?
listnormal := Collections.NewList<TDateTime>;
listnormal gets populated ...
// want to copy from normal list to fast
listfast := Collections.NewList<TDateTime>([loCreateUniqueIndex]);
listfast.AddFrom(casi); // copy
// lots of iterations in some loop
if listfast.IndexOf(cas)<0 then // is slower when using AddFromversus just looping through listnormal and .Add
anotherlist.add(cas);
Do we need to rehash it?
hi,
is it possible to:
1. copy/insert/add from another list in one line ?
thank you
Hi,
Is it possible to convert to loCreateUniqueIndex after mylist := Collections.NewList<TDateTime> creation ?
maybe: mylist.UniqeIndex := True;
thank you
thank you,
Good to know
Hi,
Mormot 1 (latest), and D11 ent, win32
This was hidden ... and I don't know if this is normal.
We have object of TPersistent that is part of main object TPersistent:
TMainObj=clas(TPersistent)
...
published
mySubObject:TMySubObject...
...
end;
We normally use json to store objects and retreive them.
property in question:
TMySubObject
published
property PropAlwaysRestored: TDatetime read FPropAlwaysRestored; // <== FPropAlwaysRestored gets updated !!!??
I checked the JSON file value of property. And after JSON2Object this value is restored in object.
Thank you,
Vojko Cendak
@ab
Yes it works with plain records. (managed not yet );
thank you
Hi, (D10.4.2 ent)
Is it possible to use IList<> for records ?
It reports Type is too complex.
thank you,
Vojko
Hi, (D10.4.2 ent)
We want to have array of records to use with TDynArray.
1. Mormot 1.18 works ok with managed and plain records
2. Mormot2 plain ok, managed record throws access violation in init of dynarray.
thank you,
Vojko
thank you,
is there any other way ?
because we have lots of situations where ridiculously long timeouts stuck the app,
not gui, but termination of threads, restart of threads, ... getting user to see what is happening.
I don't know how others deal with situations when network breaks (which is normal situation), then you retry until it reestablishes the connection.
thank you
Is it possible to add to mormot too ?
I'm not shure if we can migrate to mormot2 yet ...
The properties are set through SetInt32Option
// open client connection
if ConnectTimeout>0 then begin
SetInt32Option(result,SO_RCVTIMEO,ConnectTimeout); <== ConnectTimeout = 3000
SetInt32Option(result,SO_SNDTIMEO,ConnectTimeout); <== ConnectTimeout = 3000
end;
if Connect(result,sin)<>0 then begin <== waits around 20 - 30 secs
CloseSocket(result);
result := -1;
end;
Hi, (Windows 10 pro 64bit, Sydney 10.4.2)
TSQLHttpClientWebsockets.Create(Host,Port,TSQLModel.Create([],ROOT_NAME),
false,'','',
SendTimeout,ReceiveTimeout,ConnectTimeout);
ConnectTimeout takes very long (over 40 seconds) in case of non existent IP / service, although we set it to 3000 miliseconds.
Thank you,
Vojko Cendak
Great,
Thank you
Hi,
Is it possible ?
(I know about multithreading, but we're using COM objects ...)
It's possible in interfaced methods (and they work perfectly for several years now).
Thank you,
Vojko
Thank you,
The exception is generated serverside and trapped on clientside:
server side:
procedure TSomeService.myProcWithException(... ; out Err:TSomeEnum);
begin
...
...
if SomeCondition then begin
Err := MyValueForError; //==> here I set it serverside, but it's value isn't transmitted to client(it stays default enum) !
Raise Exception.Create('my error message'); //==>
end;
end;
client side:
try
...
RestSvc.myProcWithException(...., Err); //== here exception happens, but Err is not valid
...
except on E: Exception do begin
ReportErrorValue := Err; // here err is not valid !
end;
end;
Question is whether out parameter Err should be transitted as set on server side in
case of exception.
Thank you, Vojko
Hi, (Rio10.3.3 ent, mormot latest)
we noticed that when we implement exception in service call that returned
parameters are not properly returned. Is this intentional?
TAllParkHTTPResponeType = (
response_OK,
response_InvalidDeviceID,
response_DeviceTimeout,
...
);
...
procedure SomeCallWithExceptionInside(const DeviceID: integer;out Park: TParkingsArray; out Err:TAllParkHTTPResponeType);
Err is internally set before exception, but on the client side's out Err value is wrong.
thank you,
Vojko Cendak
Hi, W10pro, Rio10.3.3ent
We have a problem when we have nested object in published properties.
We can't use j2oSetterNoCreate in interfaced service, so we propose this code: lines with // <==
function TPropInfo.ClassFromJSON(Instance: TObject; From: PUTF8Char;
var Valid: boolean; Options: TJSONToObjectOptions): PUTF8Char;
var Field: ^TObject;
{$ifndef FPC}tmp: TObject;UserCreatedObj: Boolean;{$endif} ; // <==
begin
valid := false;
UserCreatedObj := False; // <==
result := nil;
if (@self=nil) or (PropType^.Kind<>tkClass) or (Instance=nil) then
exit;
if SetterIsField then
// setter to field -> direct in-memory access
Field := SetterAddr(Instance) else
{$ifndef FPC}
if WriteIsDefined and not (j2oSetterNoCreate in Options) then begin
// it is a setter method -> create a temporary object
tmp := GetObjProp(Instance); // <==
UserCreatedObj := tmp<>nil; // <==
if tmp=nil then tmp := PropType^.ClassCreate; // <==
// tmp := PropType^.ClassCreate;
try
result := JSONToObject(tmp,From,Valid,nil,Options);
if (not Valid) and (not UserCreatedObj) then // <==
FreeAndNil(tmp) else begin
SetOrdProp(Instance,PtrInt(tmp)); // PtrInt(tmp) is OK for CPU64
if j2oSetterExpectsToFreeTempInstance in Options then
FreeAndNil(tmp);
end;
except
on Exception do
if (not UserCreatedObj) then tmp.Free; // <==
end;
exit;
end else
{$endif FPC}
if GetterIsField then
// no setter -> use direct in-memory access from getter (if available)
Field := GetterAddr(Instance) else
// no setter, nor direct field offset -> impossible to set the instance
exit;
result := JSONToObject(Field^,From,Valid,nil,Options);
end;
The code checks whether object is already present and just updates properties and leaves creation/destruction.
Hope the code is not too long.
Thank you,
Vojko Cendak
Hi, Windows 10 pro, Rin 10.3.3 ent
TtcpParkCLientBase=Class(TInterfacedObject);
TObejctWithObejctSetGet = class(TtcpParkCLientBase,ItcpParkClientCustom)
published
...
property MyObject: TMyObject read GetMyObject write setMyObject; // if we omit write setBarieraObj we get exception from json to object
...
Interfaced service:
TParkingsArray=class(TObjectList);
procedure TAllParkService.GetObjectList(const DeviceID: integer;[b]out Park: TParkingsArray[/b]; out Err: Integer);
begin
// here we return objectlist of TtcpParkClientCustom objects and when method returns framework throws exception (without write setBarieraObj)
end;
Thank you ,
Vojko Cendak
Thank you for replies.
Indeed sicShared only has one instance and does not lock anything.
-- If you have some very long process
It's not so much about long process, here's situation where's a device that must have serialized access (which happen a lot in real life)
and mwthods need to be serialized (wait in que from multiple sources). So we need some kind of control: number of calls in que, timeouts, priorities...
Maybe isn't crazy idea to implement some kind of serialization of per method calls.
It's already impelented with SyncWithMainThread actually (what we use in production succesfully for several years )
that was done gratiously by ab.
Regards, Vojko
Thank you,
sicShared works this way but then another mothods are also blocked.
sicSingle:
We solved it with application logic, eg. per mothod calls managment, timoeut, max number of wait in que.
Is there posibility to get count of currently executing methods by name or ... ?
Thank you all,
Vojko Cendak
Hi,
I'm asking this and maybe this is a stupid question:
We need to implement sicSingle service (multithreaded) and each call (same method) should wait for previous to end:
We get 1., 2., 3., ... n. call ... 1. is processing and others should wait and when the 1. ends, 2. comes in.
Is this already implemented in Mormot ?
We want to stay in method until it finishes or timeouts.
Or does someone has better idea ?
Thank you,
Vojko Cendak
I implemented published string property and use RecordSaveJSON and RecordLoadJSON.
Worka perfectly, Thank you
Hi, (latest Mormot and Rio 10.3.2)
Whe we use record in property:
TAllParkDeviceConfiguration = packed record
DeviceID: Integer;
IP: RawUTF8;
PORT: Integer;
MODE: Integer;
BAR_CLOSE: Integer;
TIM_ZAP_CLOSE: Integer;
TIMEOUT_PREHOD: Integer;
TIMEOUT_ISVALID: Integer;
TRIGER_LPR: Integer;
TIMEOUT_LPR: Integer;
PROVIDER: Integer;
GSM_SERVICE: RawUTF8;
end;
property MyRecord:TAllParkDeviceConfiguration read getMyRecord write setMyRecord;
it throws : Invalid TJSONSerializer.AddRecordJSON(41541b0e).
But if I use:
property MyRecord:TAllParkDeviceConfiguration read fMyRecord write fMyRecord ;
We need this because we use Interfaces where get and set have to be defined.
Thank you,
Vojko
I've change the function so that the streamer checks whether the property has object. If it does it just write properties
and it doesn't free the object even if j2oSetterExpectsToFreeTempInstance is present.
function TPropInfo.ClassFromJSON(Instance: TObject; From: PUTF8Char;
var Valid: boolean; Options: TJSONToObjectOptions): PUTF8Char;
var Field: ^TObject;
tmp: TObject;
origobj: Boolean; // internal object
begin
valid := false;
origobj := False; // assume nil
result := nil;
if (@self=nil) or (PropType^.Kind<>tkClass) or (Instance=nil) then
exit;
if SetterIsField then
// setter to field -> direct in-memory access
Field := SetterAddr(Instance) else
{$ifndef FPC}
if (SetProc<>0) and not (j2oSetterNoCreate in Options) then begin
// it is a setter method -> create a temporary object
tmp := GetObjProp(Instance); // get property object
if tmp=nil then // nil
tmp := PropType^.ClassCreate
else
origobj := True; // flag it is already present
try
result := JSONToObject(tmp,From,Valid,nil,Options);
if not Valid then
if not origobj then FreeAndNil(tmp) else begin // free only if not internal
SetOrdProp(Instance,PtrInt(tmp)); // PtrInt(tmp) is OK for CPU64
if (not origobj) and (j2oSetterExpectsToFreeTempInstance in Options) then // free only if not internal
FreeAndNil(tmp);
end;
except
on e:Exception do
if (not origobj) then tmp.Free; // free only if not internal
end;
exit;
end else
{$endif}
if GetterIsField then
// no setter -> use direct in-memory access from getter (if available)
Field := GetterAddr(Instance) else
// no setter, nor direct field offset -> impossible to set the instance
exit;
result := JSONToObject(Field^,From,Valid,nil,Options);
end;
thank you
Hi,
We have an published property that is actually TCollectionItem and internally created. In delphi's object inspector it is normally visible
and streamable ...
1. problem with code in :
function TPropInfo.ClassFromJSON
...
if SetProc<>0 then begin
// it is a setter method -> create a temporary object
tmp := PropType^.ClassCreate; // it doesn't create TCollectionItem class
2. Is it possible to just set properties without creating published objects ?
Thank you and all the best,
Vojko Cenda
yes. Where can I do that ?
I've implemented variant in objects and it work's in production. It can translate even variant arrays
and it saves actual variant type.
Saved string is in hex. It's not JSON friendly but it could be used in some special cases.
D2009ent
we too. We recently upgraded to last version (1-2 months ago) and now app is receiving these EXCOS eAccessviolation (C0000005).
It happens after some time, application hangs let's say after couple of hours.
Client apps work flawlessly (calls from several threads, ...) .
App runs on Windows 7 pro. The application just stops. I have Eurekalog and it doesn't detects any errors.
I now have a program that automatically restarts production server .
Glad someone also found it.
We have normal interface based services with HTTP sys server.
thank you.
Vojko
we need badly streaming of fullblown variants:
check http://synopse.info/forum/viewtopic.php?pid=7817#p7817
I found a nice Variant streaming code on the website
http://npavlov.kodar.net/blog/?p=11
and
http://npavlov.kodar.net/blog/?p=12
Streaming full variant including arrays and varTypes
Although there are some errors and missing vartypes, it seems to work ok.
It streams with varType and also arrays.
I changed the code so that it's working.
Hope you'll find it interesting
Streaming components into/from JSON? -> Yes
Storing TPersistent properties of a TSQLRecord ORM table? -> Yes
Yes it can be BLOB storage.
thank you, vojko
Hi,
is there any way to implement this ?
This would be major enhancement in streaming existing components.
I'll create ticket for it -> http://synopse.info/fossil/tktview/3369 … fb5c6f49a1
thank you, Vojko
Hopefully you'll add variant arrays . That would be really nice.
thank you, vojko
Hi, delphi2009 ent
variant in object work only for one of getter/setter methods, if there are BOTH getter+setter method
we get access violation in
tkVariant: begin // stored as JSON, e.g. '1.234' or '"text"'
HR(P);
AddVariantJSON(PVariant(P^.GetFieldAddr(Value))^,twJSONEscape); // <== access v. with setter method or no setter method
end;
to reproduce ...
tmyobject=class(TPersistent)
private
fValue: variant;
fq: word;
function getValue: variant;
procedure setValue(const Value: variant);
published
published
property Value:variant read getValue write fValue; // if you put here BOTH getValue+setValue -> access violation; if there is onla one of getter/setter it works
property Quality:word read fq write fq;
end;
procedure TForm1.btnDemoClick(Sender: TObject);
var
lobj: tmyobject;
XML: RawUTF8;
begin
lobj := tmyobject.Create;
lobj.FValue := 1.34;
lobj.Quality := 192;
XML := ObjectToJSON(lobj);
Memo1.Text := XML;
end;
That would do us a lot of good,
because we have other proxy objects, which makes code complcated, less readable ...
Hope you will fix it ASAP.
thank you, vojko
It's working now. Thank you.
Hi, Delphi2009ent
We have a working TCollection item from TInterfacedCollection. (it worked with previous version of mOrmot).
TremotePLC = class(TCollectionItem)
published
// server itemhandle
property lokacija:string read flokacija write flokacija;
property IP:string read fIP write fIP;
property Connected:Boolean read fConnected write fConnected;
property ErrStr:string read fErrStr write fErrStr;
property numPersecs:Integer read fnumPersecs write fnumPersecs;
property dbblokov:Integer read fdbblokov write fdbblokov;
property dbblocksstrs:string read fdbblocksstrs write fdbblocksstrs;
{ Description:
db;tagname;connectionstr;value;quality;active;sessiontime }
property tagsstr:string read ftagsstr write ftagsstr; // if this is longer than 257 -> access violation
end;
to reproduce:
var
I: Integer;
ljsonstr: RawUTF8;
begin
aPLCStatuess:= TremotePLCs.Create;
plc := aPLCStatuess.Add;
plc.tagsstr := '';
for J := 0 to 257 do plc.tagsstr := plc.tagsstr +'_';
ljsonstr := ObjectToJSON(aPLCStatuess);
JSONToObject(aPLCStatuess,PUTF8Char(ljsonstr),lvalid); ==> access violation
if we use widestring it's ok.
thank you, vojko
HI, Delphi2009ent
we have a problem with compiling latest source in mOrmot:
{$ifdef UNICODE}
/// create a TObjectList<TSQLRecord> with TSQLRecord instances corresponding
// to this TSQLTable result set
// - use the specified TSQLRecord class or create instances
// of the first associated record class (from internal QueryTables[])
// - always returns an instance, even if the TSQLTable is nil or void
function ToObjectList<T: TSQLRecord>: TObjectList<T>; overload; <== [DCC Error] mORMot.pas(4571): E2511 Type parameter 'T' must be a class type
{$endif}
I commented it and for now it works.
thank you,
Vojko
Hi, Delphi2009ent
1. Is it possible to set maximum file size and maximum rotating files (if any) ?
I had a problem that log file got over 80G :rolleyes.
We need that logging be able to limit itself:
a. maximum logfile size
b. possible to have rotating logfiles ?
2. It would be nice to have possibility to have same logfilename without time.
3. We want to add console in GUI application but we saw the StdOut in initialized in initialisation section.
We create Console woth AlloCConsole and FreeConsole.
For Now we just put RetrieveSystemInfo in Interface for now.
4. (newest version): we have problem with Logview viewing files when debugged (all lines are white). In Run mode works ok.
5. some kind of general function that would run LogView with latest logfile ? that would be nice
thank you,
Vojko Cendak
superbe.
Where can I get these files ? Tried in downloads but there are no changes in there.
this is great. We're using already in production with success: easy, small and fast . Thank you for your great work.
- Is it possible to implement general retry mechanism on the level of interfaces,
so that it will always be ready to reconnect if possible not just do access violation.
Let's say: we use a lot in app:
// this impl needs constant chekcing and recreating ===
// initialization start
FMySvc := nil;
FClient:= TSQLite3HttpClientWinSock.Create(Host,IntToStr(Port),lmodel); // don't put connect method here, otherwise we have to
// constantly recreate FClient. IMHO it's not needed. Open could be when first interface call is attempted.
FClient.Services.Info(TypeInfo(IMySvc)).Get(FMySvc); // we just initialize at one point
// this impl needs constant checingk and recreating ===
...
// we want to use FMySvc interface all over application:
FMySvc.MyMethod; // this statement should be able to ALWAYS try to reconnect in case of network failure
// that way IMHO the client is rock solid
At current implementation we now have to have function where we always check whether the service
is available, or if something gets wrong, so that we are able to reconnect our selves.
1. This is messy
2. we can do it only one function for one service
3. we have to kill the client and recreate it again and again in case of failure
For example: I looked at the pipe client server sample and it didn't reconnect when the server was restarted in between.
maybe I'm missing something., (Delphi2009ent)
We try to use TCrtSocket.
It is said is faster that Indy and blcksock, but the use of latter are running ok in
case of network disruption.
1. Issue: I cannot call close (it's private), if I want to -> I need to recreate object.
2. serious issue
FTcp.OpenBind(Host,IntToStr(Port),false); // this one works ok , it says cannot open socket ....
// this one is strange
FTcp.Open(Host,IntToStr(Port)); // after we have access violation ????
How can this be?
We just try to call same FTCP.Open(...) over and over untill it really opens and why AV comes in ?
please note that we used succesfully blcksock in same scenario and in production.
3. Could OpenBind have shorter timeout delay (no need to be so long) ?
You can easily use your application-level session, then use it on server side using it as parameter to your services.
we already did that, our auth on client and that's it.
But we miss serverside statistics, eg. how many clients, which clients, ...
Or you can use the user id to identify the session.
I still don't understand how can we use this serverside?
I'm new to morm, so any code helpers would be nice.