Alexey Maslov · Apr 14, 2017 go to post

I've tried it with Cache 2017.1.0. The first impressions are:
- It completely ignored all "blockers" in the class with 300+ methods, while there was a many of them it should not pass by: 'not procedureblock', legacy flow control, etc; maybe some internal limit was exceeded.

- On the smaller class it popped rather funny messages, e.g. 

  1 blocker1 Method declared as "ProcedureBlock = 0"User.test.cls(+6): ClassMethod RestVars(zzzzzzsource As %String, bOref As %Boolean) As %Status [ ProcedureBlock = 0 ]2 major2 Usage of QUIT to exit a methodUser.test.cls(+24): quit $$$OKUser.test.cls(+28): quit $$$ERROR($$$CacheError, $ze)

Well, 'ProcedureBlock = 0' can be considered not a good style, but what if I need it in some special case? This very method restores local variables stored in a global, so it would loose all its sense be it 'procedureblock'. IMHO, there should be a facility to protect such special case methods.

'Usage of QUIT to exit a method': QUIT is standardized command to exit methods/routines/etc. IMHO it's better than RETURN as it prevents coders to exit their methods from inside the loops and try/catches constructs, so it encourages the modular coding: each module (method) should have one enter and one exit.

So, many of such rules seem to be subjective. Without a facility to customize the rules this linter seems to be no more than a demo of some commercial product.

P.S. As I noticed later, it never clears 'mgr/Temp/' sub-folders it creates.

Alexey Maslov · Apr 14, 2017 go to post

Looks like, do you use integration in Studio?

Yes, I do.

...maybe it working so long, and you did not wait for the result. 

Not too long, just a few seconds. It provided an empty report, and AFAIR there was some record in its internal log that no problems were found.

Alexey Maslov · Apr 19, 2017 go to post

Hello Eduard,

Following your 1st link I've failed to find any info on 7-zip usage. It was about Libre Office stuff.

No problems with 7-zip for Windows (its native OS), not worth to mention that 7z format compression method(s) of its last versions can be unsupported (and uncompressed) with old ones. If using zip format (even with 7-zip), your are quite safe.

p7zip, its Linux branch, which I tried several years ago, performed very poor as it was not multi-threaded (as 7-zip was for years). So we decided to drop it mostly for this reason.

One little hint about 7-zip for Windows: we use its 7za.exe build in our deployment and update procedures as it doesn't need installation and can be just dropped in any place before usage.

Alexey Maslov · Apr 20, 2017 go to post

Eduard, can you explain the main difference between Sagun's method of translation table setting:

 open file:"RSK\CP874\"

and yours in this very case? The latter is a piece of code of %Stream.FileCharacter.cls which actually sets a table:

 If (table'=0) && (i%CurrFile'="") {   Set io=$io   Use i%CurrFile
   $$$SETIO(table) ; -> Do $zutil(96,18,2,table)   Use io }

It seems that it's some other problem, perhaps a bug.

Sagun, if you provide us with a small piece of your code where you open the file, use it, and write it, it would be easier to say something.

Alexey Maslov · Apr 20, 2017 go to post

It's better to use stream wrappers instead of open/use directly

Just because of higher abstraction level of streams; nothing special inside: just the same Open/Use/etc COS commands. So, choosing one or another way of working with files can't be the source of errors itself.

By the way, `open file:("NWK\table\")` is a proven and documented way of translation table setting. AFAIK, its only limitation is that it works with Open command only rather than with Use command.

Alexey Maslov · Apr 21, 2017 go to post

Sagun, this code would fail with <WRITE> error as after opening the file for reading:

 ..o resfile:"RSK\CP874\"

it tries to write into it:

 ...w $g(^ztonEDI("TXT","OUT-DATA",ind,fileno,"SEQ",seq))_$c(13),$c(10)

What this code needs as the first remedy is a change of the Open command to:

..o resfile:"NWK\CP874\"
Alexey Maslov · Apr 21, 2017 go to post

... 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.

Alexey Maslov · Apr 24, 2017 go to post

Thank you, John, for this reminder, while I prefer to deliberately enable auditing of all events for the simple reason: a few added-on disk IOPS, as well as 1GB+ of disk space for audit database (even on high loaded Caché instances) do not seem to be a great price for an ability to trace not predicted cases in production.

We even met a prospect's requirement that any audit database write failure should be dealt as a critical error with a notification of admins by all means, even with shutting the Caché down!

Alexey Maslov · Apr 25, 2017 go to post

Hi, Richard.

...to have cache run as a different user to access that macro...

Running Caché for Windows using a dedicated user account (so called service account) may have some other advantages:

  • Caché processes get ability to use MS network resources (shared folders), e.g. Caché Backup can be performed directly to remote folder; 
  • Kerberos authentication can be used.

So long story short just going down the libre office route.

Why do you expect that libre office route would be shorter? Do you plan to use another (not $zf(-1,...)) approach?

Alexey Maslov · Apr 25, 2017 go to post

John, it seems that inquiring folks rarely accept answers, maybe because of their rare visits to this site.

With voting feature (like some sites have) it would be possible to "auto-accept" the most voted answer(s) after some reasonable time, e.g. after two weeks.

Alexey Maslov · Apr 26, 2017 go to post

Neither MERGE nor ^GBLOCKCOPY move the global: they are only copy it, unless somebody KILL it's old instance after copying.

Alexey Maslov · Apr 27, 2017 go to post

Raghuram,

I wrote my answer before reading yoyr comment. In this very case it seems that it's nothing should be done with GUID.

Happy testing!

Alexey Maslov · Apr 28, 2017 go to post

If you are curious, you may try to do it following John's hint, but if you didn't catch the idea, better do not.

Alexey Maslov · Apr 28, 2017 go to post

Question may have more than one right answer.
Several answers may add some useful info to each other.
Complicated question may even collect several competiting answers. Who will be a judge?

Alexey Maslov · May 19, 2017 go to post

Looking at the console log I can see the following which I presume implies it is using large pages?

Definetely yes.

Graham, if you feel that your question is answered please don't hesitate to mark it answered smiley

Alexey Maslov · May 19, 2017 go to post

Do you think that strange name is from MultiValue stuff?
If so, not sure if it's possible to define macros in MultiValue .

Alexey Maslov · May 24, 2017 go to post

Thank you, Jon, you've answered my question.

Frankly, I've noticed that CPUPct object still exists in 2017.1.0, but didn't notice that it's no longer being tracked.

Alexey Maslov · May 24, 2017 go to post
  • Вопросы есть? Вопросов нет!
  • И называйте меня просто — товарищ Сухов!
  • Have you any questions? No questions!
  • And call me simply - comrade Sukhov

Quotes from the cult film "White Sun of the Desert" / "Белое солнце пустыни", 1970.

This film is traditionally watched by Russian cosmonauts before every space flight.

PS. Sorry for off-topic, Jon provoked me :)

Alexey Maslov · May 24, 2017 go to post

And what will happen, if one decides to revert his class def to a previous version with previous storage def state, having some data already populated using new schema?

It seems that there is no "good" choice between TS's two options, only some "bad" vs "worse", unless business logic is accurately separated from data and kept in different classes. In this case the probability of reverting data class def should be lower.

Alexey Maslov · May 24, 2017 go to post

If one simply gets an older storage def from VCS, how Cache internal migration facility can help? The history of schema changes will be lost. It seems that only some ad hoc global level migration code can help in this case.

So this kind of "forced" schema migration (having some populated data which you don'want to loose) would usually be a pain.

Alexey Maslov · May 26, 2017 go to post

I'm voting for Rubens's solution as it is OS independent. Caché as a great sandbox in many cases, why not use its "middleware" capabilities? Developer's time costs much more than CPU cycles, and every piece of OS dependent code should be written and debugged separately for each OS that should be supported.

As to performance, in this very case I doubt if the recursion costs much compared to system calls. Anyway, it's not a great problem to replace it with the iteration.

Alexey Maslov · May 27, 2017 go to post

I don't understand the difference between this two kinds of voting :) Which solution is the best, depends on many factors: if we need turbo performance, we'd take your approach, if not - %ResultSet based one. BTW, I guess that file dirs scanning is a small part of a bigger task and those files are processed after they have been searched and the processing takes much longer than the directory search.

Last 2c for cross-platform approach: the main place where COS developer faces problems is interfacing with 3d party software. As I was told by one German colleague, "Cache is great for seamless integration".

E.g., I've recently found that forcely resetting of LD_LIBRARY_PATH by Cache for Linux may cause problems for some utilities on some Linux versions. It's better to stop here, maybe I'll write about it separately.

Alexey Maslov · May 31, 2017 go to post

90 and 100 lines for serializers is quite the achievement.

At the moment I have a serializer (<glvn> to json string) and a deserializer (json string to <glvn>) of 40-60 lines of pure M COS code. Should run on any Caché version, was tested on 2012.2 and higher. Some proof that they really exist:

USER>d $system.CPU.Dump()
 
-- CPU Info for node maslov --------------------------------------------------
          Architecture: x86
                 Model: Intel(R) Core(TM) i5-4460  CPU @ 3.20GHz
< ... >
USER>d j2gSmall^zmawr

JSON2G^Wmgr Cache for Windows (x86-64) 2017.1
total time = 1.05795 avg time = .0000105795

G2JSON^Wmgr Cache for Windows (x86-64) 2017.1
total time = 1.898275 avg time = .00001898275

sJson <=> arr()? yes ; the result of conversion reversibility check

USER>zw sJson
sJson="{""BirthDate"":""1970-03-25"",""FirstName"":""Sean"",""Hobbies"":[""Photography"",""Walking"",""Football""],""LastName"":""Connelly""}"
 
USER>zw arr
arr("BirthDate")="1970-03-25"
arr("FirstName")="Sean"
arr("Hobbies",0)="Photography"
arr("Hobbies",1)="Walking"
arr("Hobbies",2)="Football"
arr("LastName")="Connelly"

This code is not my own development (while I contributed a bit), so if anybody wants it to be published I should redirect this request to main contributor(s).

BTW: Sean, was this JSON string

TestRawJson = "{""TestAllAsciiChars"":"" !\""#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]"_$c(142,143,144,145,146,147,148,149,150,151,152,153,154,157,158,159)_"...

 from your sample wrong escaped deliberately?

Alexey Maslov · Jun 1, 2017 go to post

Sergey, you are doing a great job popularizing our (unfairly) niche technology!

Despite the article was published on private resource,  such a phrase: 

They were first introduced in 1966 in the M(UMPS) programming language (which later evolved into Caché ObjectScript, COS), which was initially used in medical databases.

sounds (at least for me) as a disrespect to many talented people who contributed to the technology in terms of many other M implementations. Some of them already gone...

Truth should sound like this: COS was developed by InterSystems as a superset of M (see http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY…). The  original language is still accepted by developers' community and alive in a few implementations. There are several signs of activity around the web: MUMPS Google group, user group (http://mumps.org/), effective ISO Standard (http://71.174.62.16/Demo/AnnoStd), etc.

Alexey Maslov · Jun 2, 2017 go to post

Our customers are to check DB integrity on regular basis, usually weekly, while I don't remember a case when it showed errors which were not evidient without it (<DATABASE> errors in error and console logs, etc).

Last time when I had an opportunity to use ^REPAIR was about 1.5 year ago, when our support specialist defragmented free space in a database under Caché 2015.1.2. The bulletin from InterSystems about the possibility of defragmentation errors arrived a bit later... Thanks to backup performed before the defragmentation, the opportunity to use ^REPAIR was closed that time :) After upgrade to 2015.1.4 no errors of such kind were detected in the field.

The faults of Integrity check are:
- when there is some concurrent users' activity it may provide false positives in per database summary report (Errors found in database...) while there are no real errors neither in database nor in per global report;
- (mostly about TASKMGR): there is no way to include into the task completion reports (which can be e-mailed) any information from the task, e.g., about errors found by Integrity. 

Alexey Maslov · Jun 16, 2017 go to post

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.

Alexey Maslov · Jul 19, 2017 go to post

Method with a variable arity can also pass through their arguments to the next method

Good point!

Wouldn't it be great if $classmethod and $method functions support variable arity as well? (Today they don't, Cache 2017.1). How to use them with such a methods without this feature?

PS. Sorry for off-topic.

Alexey Maslov · Aug 10, 2017 go to post

Robert,

thank you for sharing your experience. I'm just curious:
- What was the final database size in GB?
- What tool will be used for data analyzis? If a homemade one, will it be based on Caché?