You are not logged in.
I wouldn't change so much. My confusing results from working with your tools and not understanding much of it in depth. Some points you understand after years.
But perhaps some small improvements could help.
That _Safe could return a read only fake DocVariantData is perhaps a little bit too much and contrary to the name „_safe“.
Thanks for explaining and your patience!
A clear after each Init is necessary because Variants are managed types, right?
Otherwise the compiler would free a Variant which may be still in using because of a duplicate Init
Ok, @tbo thanks for your good and detailed article.
@ab thanks for your outstanding framework. I'm fare from any critic at all.
But I just can't find any forbidden at this (also after reading your article @tbo):
v:= _ARR([]);
_Safe(v)^.InitArrayFromCsvFile('f1,f2,f3'#10'"1";"2";"3"', [], ',','"');
It seems to work, but am I wrong?
How should I call clear here? What would clear do with an empty []?
I just ask to understand and learn, not to annoy.
Ok, but what’s wrong with a re-initialize of a variant? I could re-initialize it who often I want?
It’s only one variant on the stack and not a class-instance of a create constructor.
I create a Variant with _ARR and will fill this Variant with the data of a csv.
Is the using of _Safe(of a Variant of type 271) in this case so clearly senseless?
Can you explain a little bit. I don't know why it does make any sense.
_Safe(aVariant) gives a TDocVariantData record back and this type has the method InitArrayFromCsvFile.
Hi ab,
the using of InitArrayFromCsvFile in this context overrides memory and results in unexpected behavior:
_Safe(aVariant)^.InitArrayFromCsvFile(aRawUtf8data, [], ';', '"');
But when using a TDocVariantData I can use InitArrayFromCsvFile without issues:
aDocVariantData.InitArrayFromCsvFile(aRawUtf8data, [], ';', '"');
Do you have what's the background of that?
perhaps this info in mormot.core.text.pas can help:
// - note: mORMot 1.18 TTextWriter.RegisterCustomJSONSerializerFromText()
// are moved into Rtti.RegisterFromText() as other similar methods
P.S.
We also have contact with Ingenico
@Márcio Baroni
Thanks a lot
I'm not the one who defines which ContentType hast to be compressed. But over the last 10 years I'm using this ContentType and it was never compressed.
Should be compressing not independent from ContentTypes and compressing tagged by other headers:
Content-Type:application/json - tells what type of content data in the http call
Content-Encoding: gzip - tells what compression being used
Anyway, I need a way to disable compressing, because it isn't nice to decompress synlz compressed responses by browser/js.
Hi ab,
since commit #ebba3ec http response in browser client is compressed because of this line in mormot.net.http.pas:
compressible := IsContentTypeCompressible(pointer(OutContentType));
Do I have to set/config something to prevent this?
My ContentType is application/json.
When changing line 8903 in mormot.core.buffers.pas to this
_CONTENT_APP: array[0..4] of PUtf8Char = (
'APPLICATION/JSON', <-- this works for me
'XML',
'JAVASCRIPT',
'VND.API+JSON',
nil);
it work as expected.
Daniel
I'm aware I'm not speaking for the whole mOMRot community, but in our project we can get without generics. But without mORMot using Delphi/Pascal were impossible.
Thats all what I can say to this topic from side.
In TRttiCustomList.DoRegister Info.KIND has rkBOOL.
But Instance (Result) will not set after GlobalClass.Create and given to AddToPairs(result, Info);
In AddToPairs I can't see from where Instance is getting his KIND (it's just rkUnknown) until inc(Counts[Instance.Kind]);
Yes, with your last patch it works as expected.
Yes, it was rkUnknown.
I've tested and changed code in a very unprofessional way and maybe I'm lost, but I want to share my guess founded in mormon.core.rtti:
The address of the CS will be changed through line 8730 in TRttiCustomList.AddToPairs:
inc(Counts[Instance.Kind]);
After that the RegisterSafe.UnLock; in line 9002 goes with the wrong Pointer address in mutex_unlock_common and therefore it results in a segfault.
If I comment line 8730 the segfault is away and also my real app is running under FreeBSD 13.2 as under Win/Linux.
But I don't know, what's the meaning of line 9002 and the drawbacks of that.
Yes, I do always a clean & build under lazarus. But mormot.core.linux.inc? Do you mean mormot.core.os.posix.inc?
Please look at the stack trace from lazarus. Is #1 und #2 double or normal?
I'm not able to debug constructive (perhaps because of inlining).
#0 mutex_unlock_common(0x9013d1708, false, 0x0) at /usr/src/lib/libthr/thread/thr_mutex.c:976
#1 CTHREADS_$$_CLEAVECRITICALSECTION$formal at :0
#2 SYSTEM_$$_LEAVECRITICALSECTION$POINTER at :0
#3 DOREGISTER(0x801cef6a0, 0xe3d8d8) at ../../mORMot2/src/core/mormot.core.rtti.pas:8630
#4 SETGLOBALCLASS(0x801cef6a0, 0xf8af30) at ../../mORMot2/src/core/mormot.core.rtti.pas:8751
#5 INITIALIZEUNIT at ../../mORMot2/src/core/mormot.core.json.pas:11687
#6 MORMOT.CORE.JSON_$$_init$ at ../../mORMot2/src/core/mormot.core.json.pas:11699
#7 fpc_initializeunits at :0
#8 main at SOneSrv2.dpr:551
Ok, than no progress at all:
mutex_unlock_common (m=0x90134b708, cv=false, mtx_defer=0x0)
at /usr/src/lib/libthr/thread/thr_mutex.c:976
976 if (__predict_false(PMUTEX_OWNER_ID(m) != id))
(gdb) backtrace 10
#0 mutex_unlock_common (m=0x90134b708, cv=false, mtx_defer=0x0)
at /usr/src/lib/libthr/thread/thr_mutex.c:976
#1 0x0000000000434b49 in CTHREADS_$$_CLEAVECRITICALSECTION$formal ()
#2 0x00000000004254ca in SYSTEM_$$_LEAVECRITICALSECTION$POINTER ()
#3 0x00000000004dcae3 in DOREGISTER (this=0x801de8370, INFO=0xeb7b68)
at ../../mORMot2/src/core/mormot.core.rtti.pas:8630
#4 0x00000000004dd357 in SETGLOBALCLASS (this=0x801de8370,
RTTICLASS=0x1004fa0) at ../../mORMot2/src/core/mormot.core.rtti.pas:8751
#5 0x000000000094f8bd in INITIALIZEUNIT ()
at ../../mORMot2/src/core/mormot.core.json.pas:11687
#6 0x000000000094f979 in MORMOT.CORE.JSON_$$_init$ ()
at ../../mORMot2/src/core/mormot.core.json.pas:11699
#7 0x0000000000421652 in fpc_initializeunits ()
#8 0x0000000000403b9f in main () at SOneSrv2.dpr:551
If a do a breakpoint in thr_mutex.c for mutex_lock_common and mutex_unlock_common, than I can see, that this function will be called.
Are you sure, a confusion of libc and libthr functions exists?
I've applied your commit, but
how can I remove the reference to clib in mormot.core.os.posix.inc? There are other functions (e.g. clock_gettime) needing clib.
Do I need cthreads anymore? We have disabled MemoryManager for testing.
@DonAlfredo
This patch is already included in R13.2 and it couldn't be an issue on linker side.
Thanks a lot for your hint!
@DonAlfredo
Thanks for this link. I've alfredy (joke) read about this issue. But the patch is fro 2019 and I've the R13.2 from Apr 2023 and should the backtrace not shown something of libc in such a case? But I will compare the patch with the current source files and perhaps that will help.
with TLightLock app hangs when leaving InizializeUnit in mormot.core.log. After stepping over end; Debugger shows end; of FinalizeUnit.
Assembler show this:
0000000000421472 eb55 jmp 0x4214c9 <fpc_initializeunits+121>
0000000000421474 48c745f800000000 movq $0x0,-0x8(%rbp)
000000000042147C 488b45f8 mov -0x8(%rbp),%rax
0000000000421480 488d4001 lea 0x1(%rax),%rax
0000000000421484 488945f8 mov %rax,-0x8(%rbp)
0000000000421488 488b45f8 mov -0x8(%rbp),%rax
000000000042148C 48c1e004 shl $0x4,%rax
0000000000421490 488d15a99ba100 lea 0xa19ba9(%rip),%rdx # 0xe3b040 <INITFINAL>
0000000000421497 48833c0200 cmpq $0x0,(%rdx,%rax,1)
000000000042149C 7502 jne 0x4214a0 <fpc_initializeunits+80>
000000000042149E eb12 jmp 0x4214b2 <fpc_initializeunits+98>
00000000004214A0 488b45f8 mov -0x8(%rbp),%rax
00000000004214A4 48c1e004 shl $0x4,%rax
00000000004214A8 488d15919ba100 lea 0xa19b91(%rip),%rdx # 0xe3b040 <INITFINAL>
00000000004214AF ff1402 call *(%rdx,%rax,1)
00000000004214B2 488d05879ba100 lea 0xa19b87(%rip),%rax # 0xe3b040 <INITFINAL>
00000000004214B9 488b55f8 mov -0x8(%rbp),%rdx
00000000004214BD 48895008 mov %rdx,0x8(%rax)
00000000004214C1 483b5df8 cmp -0x8(%rbp),%rbx
00000000004214C5 7602 jbe 0x4214c9 <fpc_initializeunits+121>
00000000004214C7 ebb3 jmp 0x42147c <fpc_initializeunits+44>
00000000004214C9 488d0550aea100 lea 0xa1ae50(%rip),%rax # 0xe3c320 <TC_$SYSTEM_$$_INITPROC>
00000000004214D0 48833800 cmpq $0x0,(%rax)
00000000004214D4 7502 jne 0x4214d8 <fpc_initializeunits+136>
00000000004214D6 eb09 jmp 0x4214e1 <fpc_initializeunits+145>
00000000004214D8 488d0541aea100 lea 0xa1ae41(%rip),%rax # 0xe3c320 <TC_$SYSTEM_$$_INITPROC>
00000000004214DF ff10 call *(%rax)
00000000004214E1 488b5df0 mov -0x10(%rbp),%rbx
00000000004214E5 4889ec mov %rbp,%rsp
00000000004214E8 5d pop %rbp
Thanks, with TLightLock app hangs again.
With TOSLightLock segfault again:
#0 mutex_unlock_common (m=0x90134b708, cv=false, mtx_defer=0x0)
at /usr/src/lib/libthr/thread/thr_mutex.c:976
#1 0x00000000004dcae3 in DOREGISTER (this=0x801de8370, INFO=0xeb7b68)
at ../../mORMot2/src/core/mormot.core.rtti.pas:8630
#2 0x00000000004dd357 in SETGLOBALCLASS (this=0x801de8370, RTTICLASS=0x1004fa0)
at ../../mORMot2/src/core/mormot.core.rtti.pas:8751
#3 0x000000000094f8bd in INITIALIZEUNIT ()
at ../../mORMot2/src/core/mormot.core.json.pas:11687
#4 0x000000000094f979 in MORMOT.CORE.JSON_$$_init$ ()
at ../../mORMot2/src/core/mormot.core.json.pas:11699
#5 0x0000000000421652 in fpc_initializeunits ()
#6 0x0000000000403b9f in main () at SOneSrv2.dpr:551
Registers:
rax 0x7fffffff 2147483647
rbx 0x90134b708 38674937608
rcx 0x801349008 34379960328
rdx 0x0 0
rsi 0x0 0
rdi 0x90134b708 38674937608
rbp 0x7fffffffd540 0x7fffffffd540
rsp 0x7fffffffd4e0 0x7fffffffd4e0
r8 0x6c6f6f42 1819242306
r9 0x80000 524288
r10 0x4a7b48 4881224
r11 0x0 0
r12 0x7fffffffd9c0 140737488345536
r13 0x0 0
r14 0x189be 100798
r15 0x801612000 34382880768
rip 0x800f06a33 0x800f06a33 <mutex_unlock_common+51>
eflags 0x10206 [ PF IF RF ]
cs 0x43 67
ss 0x3b 59
ds 0x3b 59
es 0x3b 59
fs 0x13 19
gs 0x1b 27
fs_base 0x800ef1120 34375405856
Now with TLightLock my real app hangs at starting and I have to find out where.
Please give me some more time to find out next issues, because the main issue resists and just a first step of initialization of the units seems to work…
TLightLock works!
TOSLightLock not.
Yes, I think that's the same issue like the docker one. But it's just my intension, because the av is released at the same time in the same unit initializations.
I've tested your new commit (thank's a lot for your investigation), but got the same segfault as without it:
mutex_unlock_common (m=0x901398708, cv=false, mtx_defer=0x0)
at /usr/src/lib/libthr/thread/thr_mutex.c:976
976 if (__predict_false(PMUTEX_OWNER_ID(m) != id))
(gdb) bt 10
#0 mutex_unlock_common (m=0x901398708, cv=false, mtx_defer=0x0)
at /usr/src/lib/libthr/thread/thr_mutex.c:976
#1 0x0000000000431c19 in CTHREADS_$$_CLEAVECRITICALSECTION$formal ()
#2 0x000000000042560a in SYSTEM_$$_LEAVECRITICALSECTION$POINTER ()
#3 0x00000000004d9ea3 in DOREGISTER (this=0x801637188, INFO=0xeb4b58)
at ../../mORMot2/src/core/mormot.core.rtti.pas:8629
#4 0x00000000004da717 in SETGLOBALCLASS (this=0x801637188, RTTICLASS=0x1001a30)
at ../../mORMot2/src/core/mormot.core.rtti.pas:8750
#5 0x000000000094ca5d in INITIALIZEUNIT () at ../../mORMot2/src/core/mormot.core.json.pas:11687
#6 0x000000000094cb19 in MORMOT.CORE.JSON_$$_init$ ()
at ../../mORMot2/src/core/mormot.core.json.pas:11699
#7 0x0000000000421792 in fpc_initializeunits ()
#8 0x0000000000403cdf in main () at SOneSrv2.dpr:550
the segfault comes from thr_mutex.c when the CS will be unlocked a second time:
/*
* Check if the running thread is not the owner of the mutex.
*/
if (__predict_false(PMUTEX_OWNER_ID(m) != id)) <-- here
return (EPERM);
This comes from the second step of a for loop in mormot.core.rtti which calls
function TRttiCustomList.DoRegister(Info: PRttiInfo): TRttiCustom;
and here the finally RegisterSafe.UnLock;
calls in thr_mutex.c
mutex_unlock_common(struct pthread_mutex *m, bool cv, int *mtx_defer)
stack trace:
#0 mutex_unlock_common (m=0x90138e708, cv=false, mtx_defer=0x0) at /usr/src/lib/libthr/thread/thr_mutex.c:976
#1 0x0000000000431c19 in CTHREADS_$$_CLEAVECRITICALSECTION$formal ()
#2 0x00000000004ee651 in UNLOCK (this=...) at ../../mORMot2/src/core/mormot.core.os.pas:9003
#3 0x00000000004d9e59 in DOREGISTER (this=0x801637188, INFO=0xea9f78) at ../../mORMot2/src/core/mormot.core.rtti.pas:8629
#4 0x00000000004da677 in SETGLOBALCLASS (this=0x801637188, RTTICLASS=0xff6df0) at ../../mORMot2/src/core/mormot.core.rtti.pas:8750
#5 0x000000000094bffd in INITIALIZEUNIT () at ../../mORMot2/src/core/mormot.core.json.pas:11679
#6 0x000000000094c0b9 in MORMOT.CORE.JSON_$$_init$ () at ../../mORMot2/src/core/mormot.core.json.pas:11691
#7 0x0000000000421792 in fpc_initializeunits ()
#8 0x0000000000403cdf in main () at SOneSrv2.dpr:550
I've testet with standard memory manager from fpc and with cmem.
No reallocations of large buffers of my own.
Now I've tested the two defines, but with no success.
(freebsd 13.2, fpc 3.2.2)
Same behavior as under FreeBSD.
The AV occurs after unlocking a CriticalSection. I don't think it has to do with an old libc, but with using libthr (instead of libpthread under linux).
I guess it's not an Docker issue rather than an issue of the using image.
I'm not able to find a solution atm. The only thing I've found is the initialization of the CS will be called serveral time in right same thread (the thread of the initialization of the units.
Perhaps the libthr releases a CS when it will be initialized a second time. But it's just a guess.
Although linux is our production environment I'm testing with FreeBSD perhaps as a replacement in future. My last tests some month ago were successful under Proxmox in a FreeBSD13 VM.
Now I'm testing with a real FreeBSD13 host and here I can first compile successfully my program but it comes a runtime exception after starting when mORMot2 initialize a global mutex between initialization und finalization. I've tested with fpc 3.2.0, 3.2.2 and 3.3.1.
gdb show's:
Program received signal SIGSEGV, Segmentation fault.
Address not mapped to object.
mutex_unlock_common (m=0x90139f708, cv=false, mtx_defer=0x0)
at /usr/src/lib/libthr/thread/thr_mutex.c:973
973 if (__predict_false(PMUTEX_OWNER_ID(m) != id))
Something seems to be different under FreeBSD with /lib/libthr.so.3 compared to /lib/x86_64-linux-gnu/libpthread.so.0 under Linux.
PS:
I've also tried several versions of FreeBSD13 and I've build FreeBSD 13.2 Release from source with connected Kernel.
Thanks for your hint (after reading I remember).
After patching ncal.pas it just works with 3.2.2 under freebsd!
Following late binding calls doesn't work:
v._(0)
where v is an _ARR
This post seems related to the issue I have:
https://synopse.info/forum/viewtopic.php?pid=34034
And I know I can work around with using TDocVariant instead of
last binding.
But not using late binding is a regression.
Hi Arnaud,
I could successfully compile our project, but there are runtime av's relating to variants.
Are there patches needed to run under this constellation or should it just work?
Here are a result from mORMot2tests:
#16 4E59E2A5-E8C1-46AB-90E5-F426EC9DBB1E<>4e59e2a5-e8c1-46ab-90e5-f426ec9dbb1e uuid ! - Dmi smbios: 1 / 44 FAILED 527us
0000000000000000 ! fail #16 4E59E2A5-E8C1-46AB-90E5-F426EC9DBB1E<>4e59e2a5-e8c1-46ab-90e5-f426ec9dbb1e uuid
000000000018FA8D ! EXC ESynVariant {Message:"TDocVariant.DispInvoke: invalid (1) call"} [Main] at 684f2d
Daniel
@sakura You should think about an unwanted exception in your sm and the manual inserted raise as an example for that.
Than it's interesting because I often see such external exceptions in my log files and misinterpreted these.
Are you using 32-bit? Postgres14 comes only with a 64-bit client
Nice Blog about new wire protocol! You could be also a salesman or a story-teller. Unusual for a asm optimizer
Yes, this is could be useful in case of big inserts, I guess.
Perfect!
Ok, thanks, that sounds better.
I understand your statements totally and I agree with them, but just some thoughts:
1. also I use your aggregate call it doesn't get the rights count documents. There reply count are 101/34398/16795 (if no BatchSize is set).
But in SendAndGetRepliesAndFree Opaque will override every time OnEachReply is called. Here is the issue!
2. the first 101 batch is just for analyzing of the optimal batch count and I trust the algo at server side here. Because every document could have a special size I don't know the optimal BatchSize of my own database.
The second call brings than 38.000 and the last one 16.000. So there is not so much to optimize. If the batches are to large, than in a client-server architecture with many clients, the first client gets his reply some ms faster, but at costs of waiting all others.
Test with aggregate has same issue as with RunCommand.
From expected DocumentCount of 51294 aggregate returns only 16905.
I think I could find out where the issue is. In SendAndGetCursor first 34398 Documents of reply are replaced by next 16905. But I miss the first 101 before 34398, that comes with the version of dc66841.
Here are my wishes:
1. I want to use RunCommand as under commit dc66841. Because I want to have full control about what is sending and what's the replies are.
2. I need your help because I don't understand all the details of SendAndGetCursor(msg, reply) especially working with BSONVariant and other details (e.g. why has BatchSize a value of 65536 -> I haven't set Batchsize at all)
Sure I'll try it.
But do you want to say, RunCommand isn't supported from mORMot2 any more (after rewriting)? Although all was still working in commit dc66841?
After removing $db params in my Commands I get following error for aggregates:
'{"ok":0,"errmsg":"Requested getMore on namespace ''Rottler.$cmd'', but cursor belongs to a different namespace Rottler.Persons","code":13,"codeName":"Unauthorized"}'
aggregate was:
{aggregate:"Persons",pipeline:[{$match:{PersonTypeID:0,Parents.ParentID:{$in:[903087]},live:{$ne:false}}},{$sort:{LastProcessingDate:-1}},{$project:{_id:0,ID:"$_id",Number:1,Title:1,SecondName:1,FirstName:1,DayOfBirth:1,Sex:1,PersonTypeID:1,Remarks:1,LastProcessingDate:1,CostCenter:{$arrayElemAt:[{$map:{input:{$filter:{input:"$Parents",as:"p",cond:{$eq:["$$p.PersonTypeID",1]}}},as:"cc",in:"$$cc.Number"}},0]},LoginExpiryDate:1,Alive:1,LoginName:1,Parents.ParentID:1,ContactData:1,DSV:1,FirstSalesOrder:1,LastSalesOrder:1}},{$limit:200}],cursor:{},allowDiskUse:true,maxTimeMS:30000}
Problem seems to be in:
SendAndGetRepliesAndFree->call of getMore ($cmd seems to be to needed under new wire protocol (IIRC). It was a virtual collection for OP_QUERY).
When I remove +'.$cmd' in RunCommand Collections is not stetted:
'{getMore:5068573612759429335,collection:"",batchSize:65536,$db:"Rottler"}' -> because Request.CollectionName = '' in line 2786.
Before rewriting every call with RunCommand gets one replay. The getMore request was done by myself, when requested in the reply.
The replay looks like this:
('{"cursor":{"firstBatch":[{"PersonTypeID":4,"Number":"HLD","Alive":true,...
Now replay is:
'[{"PersonTypeID":4,"Number":"HLD","Alive":true,...
If I use your implementation with getMore I tried to set DatabaseName in RunCommand like this:
BsonVariantType.GetItem(command, 'aggregate', v);
if not VarIsEmpty(v) then
GetDocumentsAndFree(NewCommand(
aDatabaseName + '.' + v, command, flags), returnedvalue)
But the replies read with getMore are still not correct this way.
You are right. I had to remove all my $db params.
Sorry for that.
Just a hint: your commit #0ba4230 don't work with JSON-Objects e.g. listCollections with params, because $db have to be the param after listCollections and not the last one.
wrong:
'{listCollections:"Rottler",filter:{name:"revenuesPayments"},$db:"Rottler"}'
right:
'{listCollections:"Rottler",$db:"Rottler",filter:{name:"revenuesPayments"}}'
You would have ti insert the $db param in the command string that comes from the user. That was not necessary in my opinion. I would add $db param only in case of VarIsStr. In all other cases,
the user must deliver the $db param in his command to work with new protocol. So I had to update all my encapsulate methods and added the $db param without the need to change mORMot2 routines.
The AddItem added the $db param also multiple times: '{listCollections:"Rottler",filter:{name:"revenuesPayments"},$db:"Rottler", $db:"Rottler"}'
Daniel
Hello Arnaud,
thanks for implementing new wire protocol. I'm testing your commit and it looks promising.
Daniel
Hello Arnaud,
I've sent you an email with a new version of mormot.db.nosql.mongodb.pas.
But the PR #114 is the better one.
Daniel
Some changes are necessary e.g. replacement of CursorID (not available in > 3.6).
I will send you an other version of mormot.db.nosql.mongodb.pas as soon as I've fixed last errors on my side.
Some errors produced by TMongoConnection.GetReply are not real errors but comes from old handling of replies (e.g. Request.MongoRequestID has wrong value).
Even my statistic request works!
Hi Arnaud,
after making some PRs further changes are necessary to work with new WIRE protocol.
But creating PRs with GitHub is too painful.
If you want, I can send you my version of mormot.db.nosql.mongodb.pas.
Atm my service starts with auth + ssl, list collections and check indexes and insert an array of documents. And all other stuff looks good from my side, because we only used RunCommand and inserting new $db field is the only change we have to do at our side.
Daniel