go to post Alexey Maslov · Nov 13, 2017 ...and spread over documentation...Or undocumented, as it is in cases #3 and #4. It seems that it's possible to form a simple rule whether you can use a private variable: if you can consider its name to be evaluated at compile time, you can, otherwise - no:1) Indirection: variable names (or expression that contains them) are evaluated at runtime.2) Xecute: similar to #1. In contrast, $xecute() arguments names can be evaluated at compile time.3) Child process's symbol table filled with switch#2=1: runtime. In contrast, job's entry arguments names can be evaluated at compile time.4) %SYS.ProcessQuery is dynamically querying other process's symbol table, so, run time only.
go to post Alexey Maslov · Nov 13, 2017 Hi Robert,There are at least two additional exceptions:3. JOB command with passing the symbol table to the spawned jobSee http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...When switch#2=1, only public variables of parent process are passed to its child.4. Class %SYS.ProcessQuery, query VariableByPid() (or $zutil(88,2,Pid,Variable) for old schoolers)Only public variables of another process can be queried.
go to post Alexey Maslov · Nov 7, 2017 $ ccontrol qlist CACHE1^/opt/cache1^2015.1.4.803.0.16768^running, since Fri Sep 15 18:44:33 2017^cache.cpf^1972^57772^62972^ok^ CACHE2^/opt/cache2^2015.1.4.803.0.16768^running, since Mon Jul 24 08:43:47 2017^cache.cpf^56773^57773^62973^ok^ CACHE3^/opt/cache3^2015.1.4.803.0.16768^down, last used Thu Jul 27 18:02:03 2017^cache.cpf^56774^57774^62974^^ Windows analogue exists as well.
go to post Alexey Maslov · Nov 7, 2017 It depends.If you don't care about uniqueness of this hash, you can use any algorithm (the quicker the better, MD5Hash or even CRC32) and store your index like normal non-unique one. On calculated hash match to already stored (indexed) hash value you just compare the correspondent strings to separate real matches from the collisions. Maybe it's worth to use whole string as an index for reasonably short strings.
go to post Alexey Maslov · Nov 6, 2017 You can calculate a hash for each string and index this hash value. If use pure COS for index building, you can find duplicates earlier, just during index building, without quiering the index afterwards.
go to post Alexey Maslov · Nov 3, 2017 Hi Mikhail, you've done a really nice job!I'm just curious, why:We don’t care about output to a file.Wasn't it easier to parse mgstat's output file?
go to post Alexey Maslov · Oct 31, 2017 Just a quick note: the last sample with $tr removes _all_ listed chars, so all blanks (rather than leading, trailing and repeationg) would be removed as well.
go to post Alexey Maslov · Oct 31, 2017 Stuart,Your solution is really beatiful. As to speed, it's just a bit slower than the solution #1 (based on $replace) and ~ twice quicker than my solution #2 (pure Mumps). That's a real pearl to add to my snippets collection, thank you!
go to post Alexey Maslov · Oct 25, 2017 You may need to make the CACHELIB database R/W to save the edit to %ZSTART No, because %Z* routines are stored in CACHESYS database. The only exception is `%ZEN.*`. You may want to check `do SHOW^%NSP` output: Routine name/Range Type Dirset Target directory ------------------------------------------------------------------------------- ... [%SYS/:%Z) INT c:\intersystems\cache\mgr\cachelib\ [%Z:%ZEN.) INT c:\intersystems\cache\mgr\ [%ZEN.:%ZEN/) INT c:\intersystems\cache\mgr\cachelib\ ... =============================================================================== ... a square bracket [] means that left or right margin is inclusive, while a parenthesis means that the margin is exclusive...
go to post Alexey Maslov · Oct 20, 2017 Yet another variant of quotes duplicator (pure Mumps): dupP(str) quit:str'[$c(34) str new strdup,j set strdup="" for j=1:1:$length(str,$char(34))-1 set strdup=strdup_$piece(str,$char(34),j)_$char(34,34) quit strdup_$piece(str,$char(34),j+1) Quick testing showed that the quickest variant is my initial $$dupquote(), $$dupocc() is very close (5-15% slower), $$dupP() took 3d place (2 times slower), $$QT() is the slowest (not surprise as it uses recursion). It was interesting to find that the good quality of $replace() implementation allowed it to beat $zutil(144,) "system" function. While I'll keep using it, analyzing Vitaliy's code I've found the error in my own $$dupP().
go to post Alexey Maslov · Oct 17, 2017 Thank you for taking part, Vitaliy!BTW, your second solution should be amended: dupocc(str) ; after the macro substitution quit $s(str'[$c(34):str,1:$e($zutil(144,1,str),2,*-1)) otherwise it would destroy numbers: USER> set b=1 set c=$e($zutil(144,1,b),2,*-1) zwrite b,c b=1 c=""
go to post Alexey Maslov · Oct 16, 2017 Both had the need to pass along data by references as memory was very limitedand processors were incredible slow (compared to today).Robert, thank you for this quick historical excursion!Just adding 2c: it seems that the reasons to introduce pointers were deeper than just resources saving:it was the reasonable way to pass arrays back and forth,it was the reasonable way to return several values from functions/subroutines.
go to post Alexey Maslov · Oct 9, 2017 You can find all levels and badges at the Global Masters Advocate Hub hereThis link seems to be broken.
go to post Alexey Maslov · Oct 2, 2017 Only the web app's home page was requested, without any attempt to log on, so it didn't write any audit record. In contrast, any attempt to connect 1972/tcp always wrote a "Logon Failure" record described as "Authentication broken" or something like this.
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 · Oct 2, 2017 It's better to use CACHETEMP mapped global, e.g. ^CacheTempUserYourGlobal($job,...).BTW there is another option: having a wrapper job, pass it an array serialized to JSON, other steps are evidient. I used it in one of my projects, and it was quicker than using of ^CacheTemp* intermediate global, while performance gain was not too sufficient (AFAIR)The approach with a global is apparently easier, so I'd use it if performance would not of great importantance.
go to post Alexey Maslov · Sep 6, 2017 I remember well times when routines used to start with KILL ^CacheTemp*($JOB)Our developers do the same, but modern versions of OSs usually have 6 digit PIDs, so it may take several days till PIDs would re-cycle their numbers.PPGs are used, however sometimes they are not applicable, e.g. when information is passed between processes via temp globals.Clean-up is a good idea, but can be fully implemented when (and only when) all app classes use the same before-exit-processing code, i.e. the app is always finish through one exit point. Sometimes it's difficult to achieve, while it's worth to.A while ago I thought about some enhancements of my purging task:automatic detection of too quick growing globalsautomatic detection of globals which belong to its scope, i.e. have @name@(PID) format. Maybe I do it when have some spare time... the priority of this work is rather medium.
go to post Alexey Maslov · Sep 6, 2017 Robert, You are quite right, but... life is life, and application can finish abnormally. In this case its temp globals are left till Caché restart, sometimes it may cause noticeable growth of CACHETEMP database. So, scheduling a nightly housekeeping task like ours makes some sense.
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.