go to post Alexey Maslov · Aug 2, 2018 Hi Mark,Several years ago we faced the similar problem. External system needed to pull new requests from our Caché DB and to push back the responses. We maintained a transition table in Caché where we placed new requests, external system polled the table each N seconds fetching the requests from the table and placing the responses back. Communication was implemented via ODBC.You can do something like this filling transition table on remote Caché side using triggers associated with the "main" table.
go to post Alexey Maslov · Jul 13, 2018 If you prefer to code global size calculation by yourself rather than amend ^%GSIZE, the feasible option is to call set bSize=$$AllocatedSize^%GSIZE(global)which returns size in bytes for a global mapped to the current namespace. It recognizes the database the global is mapped from, so you don't need to do it yourself. The only thing you need is a global list for the namespace, which can be fetched in several ways, e.g. using $Order(^$G(global)). It can be used on per database basis as well. Pros of this approach:- speed, as it neither runs query nor instantiates %SYS.GlobalQuery objects;- AFAIR, there was an error in global size calculation with %SYS.GlobalQuery::Size() query in old Caché versions, up to 2015.1;- starting from 2015.1, it can be used with subglobals.Cons:- this $$-function is not documented;- not sure if it existed in 2010.1.
go to post Alexey Maslov · Jul 5, 2018 Agree, it's trivial in most cases, except that one, when there is a series of commands depending on previous ones, e.g. (not from the production code))):set rc=$zf(-1,"[ -f /etc/environment ] && . /etc/environment && export TZ")$zf(-1) allows to execute such series at the whole, while $zf(-100) needs to split it into parts, moving checkup logic to COS code. It's trivial as well, but ruins the idea of (semi-)formal substitution of $zf(-1) calls with $zf(-100) ones.
go to post Alexey Maslov · Jul 5, 2018 It seems that the docs is ambiguous here as it's not clear when one can use "" as a <null> value: in comma separated options list only, or in options array as well.As to possible ways to exploit $zf(-1), there is some clue in ISC's announcement. It can be compromised if its arguments come from user input. Similar vulnerabilities are usually associated with dynamic SQL, not only in Caché. Other (Caché specific) samples: Xecute, $Xecute, argument indirection. This stuff is well-known, is it a secret for anybody?It seems that if we never use such coding style, we are safe enough. As to our company's code base, we rarely use $zf(-1), and all its usage is encapsulated in a couple of class methods.We'll follow ISC's security recommendations, as we always do, while I don't feel myself comfortable when I don't understand the reasons of doing something. "Don't repair, if it works", as it was said by some wise man. Does it need any comment?
go to post Alexey Maslov · Jul 5, 2018 Using a comma-delimited list of arguments works fine, even with a null argNull arg is not the same as an empty string arg (""), as usual in COS. Therefore the settings ofset options(1)=""made your first argument an empty string, and the whole command behaved asdir "" e:\nbupg\webserver\Didn't check your *nix version, just noticed that "NUL" should be spelled as "/dev/null".P.S. May I ask you in turn :):Why did you undertake this task, changing of $zf(-1) to $zf(-100), at all? Do you clearly understand the kind of treat you try to eliminate?
go to post Alexey Maslov · Jun 16, 2018 The solution I've found is rather simple than smart: to start a dejournalizer as a JOB with an 'answer file' specified as a principal-input device. The code prototype looks like this: set fin=$zu(12)_"Temp\fin.txt" set fout=$zu(12)_"Temp\fout.txt" open fin:("NW"):1 if '$t {write "not opened!",! quit} use fin write "N",!,"N",!,"Y",! close fin job jrnrest^ztestFF("20180614.006"):(::fin:fout):1 if '$t { w "not started!" q} Its execution resulted in "fout.txt" file like this: 20180614.006 to 20180614.006; c:\intersystems\cache\mgr\user\ => c:\intersystems\cache\mgr\test\ Do you want to rename your journal filter? o Do you want to delete your journal filter? o c:\intersystems\cache\mgr\journal\20180614.006 8.88% 14.29% 15.26% 16.79% 18.08% 19.31% 20.35% 21.32% .... ***Journal file finished at 16:39:36 Do you want to rename your journal filter? es Journal filter ZJRNFILT renamed to XJRNFILT [journal operation completed] "o" and "es" were provided by the auto-completion of "N" and "Y" answers. Cons of this approach is that ISC can change the ^JRNRESTO dialog in some future version.Pros: no need in reverse engineering of ^JRNREST stuff to derive a non-interactive journal restore utility. Hope my writing will be useful for somebody besides myself. Happy coding!
go to post Alexey Maslov · May 28, 2018 As a remedy, you can process compilation in a separated job, something like this:- Create environment { }- JOB ImportAndCompileStuff- Wait for the job completion- Destroy environment { }
go to post Alexey Maslov · May 8, 2018 Thank you, Dima.Could I reproduce, I'd call WRC.Ther were some errors stipulated by the fact that the class was not compiled. Posting them in another comment.
go to post Alexey Maslov · May 7, 2018 Hi Joan,It seems that the right way to perform this task would be using MemberStatusList query of the class SYS.Mirror. See Documatic for details.HTH.
go to post Alexey Maslov · Mar 15, 2018 C:\Users\%USERNAME%\AppData\Local\Application Data\Temp\InterSystems\
go to post Alexey Maslov · Mar 13, 2018 It seems that you are to write a couple of lines anyway, because nobody will do it but yourself. As you certainly know, it's possible to do it using shell scripting without going inside Caché, e.g.: #!/bin/sh csession cacheuc1 << EOF write ##class(%SYSTEM.Version).GetVersion(),! halt EOF
go to post Alexey Maslov · Dec 6, 2017 Just 2c to add. If a "national" locale is effective, e.g. %SYS>zw ^%SYS("LOCALE","CURRENT") ^%SYS("LOCALE","CURRENT")="yruw" and the setting was done before Caché restart: %SYS>set ^SYS("NLS","Config","LocaleFormat")=1 you will get your national day name if don't forget to set localeopt=0, e.g. USER>f localeopt=0,1 w localeopt," ",$ZD($h,12,,,,,,,,localeopt),! 0 Среда 1 Wednesday It's also possible to achieve the same overriding format defaults for the current process (see $ZDATE description for details). I emphasized the need in Caché restart just because didn't find it in docs.
go to post Alexey Maslov · Nov 30, 2017 Yes, I did.It did not seem working, STOP / START of the System Monitor didn't help.I lost my interest to Callback functionality because of its absence in newer Caché version, so I would not investigate it anymore.
go to post Alexey Maslov · Oct 2, 2017 It all depends.Attempts to connect a port or even to connect a super-server using potentially wrong password spoil Cache Audit with nasty records, so if they are done frequently those records can easilly overfill the Audit.Several years ago I faced the similar problem in opposite direction: how to let load balancer recognize Cache instances which are no longer alive to remove them from its list. Load balancer was to distribute super-server connections as well as web based ones. The idea of polling 1972/tcp was dropped as soon as I recognized its impact on auditting. So I used a web app which allowed unauthenticated access for the simple reason that if 57772/tcp port had reasonably answered, 1972/tcp should be accessible as well. There were no firewall(s) between the load balancer and application servers, therefore I was sure that there were no external "forces" that could prevent them from answering. The solution was deployed on a couple of different load balancers and showed its robustness on a farm of 4-7 application servers and 1000-3000 concurrent users.
go to post Alexey Maslov · Sep 6, 2017 We have a TASKMGR's task that purges such kind of globals daily. (Sub)globals are cleaned using the following criteria:Global has a structure of @name@(PID)Global is listed in predefined "known globals" listCaché process identified with PID is not running.
go to post Alexey Maslov · Jun 16, 2017 Via SSH (putty, etc), am I right that you need to call csession <instance> to enter the Caché terminal? If so, there is no talk about SSH all. Caché has got embedded libssh2.dll/.so ages ago. Why not implement internal SSH server which can be a reasonable replacement for outdated (and Windows only) telnet one? It seems that some other projects (besides Web terminal) would take advantage from it.
go to post Alexey Maslov · Jun 1, 2017 Another option is to use a classmethod %SYS.ProcessQuery::ExamStackByPid().
go to post Alexey Maslov · May 19, 2017 Routines can't be named as "%zu2f%zt" because only the first letter of routine name can be "%". Maybe such "name" occured due to some encoding, having in mind that $char($zhex("2F"))="/"? If so, the original could look like:$$zt^%zu/%ztIf so, a macro can be defined as:#define YourMacro(%yourparam) $$zt^%zu/%yourparam
go to post Alexey Maslov · May 17, 2017 During Cache backup it appears that all the available memory on the server is being used.It's usually not a problem as the more memory is used for buffering the quicker file i/o operates. Only free memory is used for this purpose, so memory allocated by users' or system processes should not be swapped. Please add more details, why it turned to be a problem in your case?PS. Double check in console log whether Cache allocates its shared memory segment using large pages as it guaranties that it is totally allocated at Cache startup and will neither be expanded nor swapped afterwards.
go to post Alexey Maslov · Apr 21, 2017 ... and second thing is to insert a Close command before the correspondent Open, e.g. ..c resfile o resfile:"NWK\CP874\" even if you are quite sure that the file is closed at the moment of opening. The reason is to avoid the cases when your program have failed with error without closing the file, so its open parameters (at least, the translation table setting) keep unchanged despite of subsequent Open command. Such cases often happen during development / debugging, when the error trap code is completely switched off or greatly simplified.