This (getFiles) method is marked as internal in Cache, and yes, it's typical internal as it's usage is relied on the strong internals knowledge :). Besides, it's hidden in IRIS, and its caller should be rewritten to achieve DBMS independence:
ClassMethod ListDir2(path = "", wildchar = "*", recursive As %String(VALUELIST=",y,n") = "y", ByRef dirlist)
{
s pExtension=1
s pExtension(1)=wildchar
#if $zversion["IRIS"
s temp=$name(^IRIS.Temp)
#else
s temp=$name(^CacheTemp)
#endif
s pTempNode=$i(@temp)
k @temp@(pTempNode)
d ##class(%SQL.Util.Import).getFiles(path,.pExtension,pTempNode,recursive="y")
m dirlist=@temp@(pTempNode)
k @temp@(pTempNode) ;zw dirlist
}
your initial question should be reformulated as "how to find global's [main] database" because all namespaces have "equal rights" for any global which is visible from (= mapped to) them.
Julias is quite correct in his answering, but you should take into account that it concerns the global's main database only. If global subscript mapping is used, the full solution to get the list of all databases where the global is partially mapped is a more tricky task. If somebody is interested, I can write about how I solved it once.
What about the second pass with the same ObjectScript code w/o restarting IRIS? 1.7GB is not too much to be stored in the file system cache, so it should be ~5 times quicker. Besides, it's well-known that Cache (IRIS) as a record readeris not so good as a block reader. Everybody knows that %GIF is 5-10 times quicker than %GI. I have the same experience with my own developments: processing files at the block level (read block#$$$BLOCKSIZE) with records parsing at the COS level is quicker than read it record by record. `5*5=25` is close to the time difference between your ObjectScript and Python code runs.
I've written this just to emphasize that we should love Python mostly for the power of its ecosystem, as Nigel wrote. As to speed, it would be better if you InterSystems guys do something to improve file i/o record level operations in IRIS engine...
Meanwhile, I was definitely logged in at InterSystems sites. I've already have checked it up in two different browsers with the same result. Not a great problem for me, just to inform the community team.
if there will be an error this won't change the namespace back even with the "new $namespace" command
It would be still "%SYS" inside the `catch` block, so it's unsafe to call any code in its context. Even if you write something like this:
...
try {
new $namespaceset$namespace="%SYS"
...
} catch ex { // process the errorsetsc=ex.AsStatus()
do ..logErr(sc) // do some debug logging
}
returnsc
and the ..logErr() call will be successful (generated .int code was not split into parts), the global where the log goes should be the same for all namespaces (e.g. mapped via %ALL pseudo-namespace). There are so many complications that it seems better to avoid any error processing inside the `catch` block above returning the error code. BTW, it sounds reasonable in any case, not only in this one associated with %SYS.
It would change. I mean that try/catch is still needed to handle exceptions that can occur during namespace change or after the change, working in "%SYS" (mostly security violation errors). Otherwise the method can produce unsolicited exceptions.
The key feature here is `new $namespace` command rather than the method of its changing, while `set $namespace="%SYS"` seems to be the preferred one as it is well documented and good looking.
I'd still use try / catch outside namespace changing as there can be security errors on attempt to do it. I mean something like this:
classmethod DoSomethingInSYS() as%Status
{
set sc=$$$OKtry {
new$namespaceset$namespace="%SYS"// do something, e.g. config change
} catch ex {
// process the errorset sc=ex.AsStatus()
}
return sc
}
Jack, your results are easy to explain. When you use $list*, you must perform conversion to string which adds extra cost.
When you check some conditions inside the loop, you add some cost as well, how much - it depends on checkup method.
So, the best results should be achieved with Robert's and Alex's approaches. I'd prefer the Robert's one as it doesn't force special processing of the first element.
My writing was just a result of quick prototyping using the terminal. Just for curiosity, I dived into %occFile.inc and there was no macro to get the current directory. It is possible through class method call (##class(%Library.File).NormalizeDirectory("")), while all this stuff looks like a great overkill for such a small sample.
As you probably know, there are two explorers in VS Code: client-side (<Ctrl-Shift-E>) and server-side ("ObjectScript", which comes with InterSystems extensions). If you don't see your routine in the first one, you just need to export it using the second one.
it sounds promising, while I've found only a facility of adding web links here. My case is a "plain" COS command line to execute. In the meanwhile, it seems that I've found a solution; if anybody is interested, I'll write a couple of words about it earlier.
I should be more specific in formulating the question. So, attempt #2:
We used server-side source control in Studio just for having additional menu items, not for source control itself;
Now, after switching to VSCode, we started using "normal" client-side source control based on GitLab;
What I want is to revive those additional menu items I was able to add using Studio.
...And I don't see how to achieve it as the server-side source control menu is only active on "server-side" WorkSpaces, while client-side source control is not available there.
I'm not sticking to this way of adding menu items to VSCode, it just seemed that it will be the easiest one.
Now I see that how wrong I was. Any idea of how to add menu items (with associated server commands) would be appreciated.
go to post
@Tony Alexander,
your method is ~30% faster then "ready made" on the directory tree populated with ~ 200 files.
Keep re-inventing wheels!
go to post
This (getFiles) method is marked as internal in Cache, and yes, it's typical internal as it's usage is relied on the strong internals knowledge :). Besides, it's hidden in IRIS, and its caller should be rewritten to achieve DBMS independence:
go to post
Hi Yuri,
What do you mean by IoC?
1) Indicator of Compromise, IoC
or
2) Inversion of Control
go to post
That approach works only for *.INT routines. Don't you use *.MAC and *.INC as well?
go to post
Bharathsimha,
your initial question should be reformulated as "how to find global's [main] database" because all namespaces have "equal rights" for any global which is visible from (= mapped to) them.
Julias is quite correct in his answering, but you should take into account that it concerns the global's main database only. If global subscript mapping is used, the full solution to get the list of all databases where the global is partially mapped is a more tricky task. If somebody is interested, I can write about how I solved it once.
go to post
What about the second pass with the same ObjectScript code w/o restarting IRIS? 1.7GB is not too much to be stored in the file system cache, so it should be ~5 times quicker. Besides, it's well-known that Cache (IRIS) as a record reader is not so good as a block reader. Everybody knows that %GIF is 5-10 times quicker than %GI. I have the same experience with my own developments: processing files at the block level (read block#$$$BLOCKSIZE) with records parsing at the COS level is quicker than read it record by record. `5*5=25` is close to the time difference between your ObjectScript and Python code runs.
I've written this just to emphasize that we should love Python mostly for the power of its ecosystem, as Nigel wrote. As to speed, it would be better if you InterSystems guys do something to improve file i/o record level operations in IRIS engine...
go to post
Hi Olga,
Thanks, it's working now.
go to post
Hello Olga,
I'm getting from Global Masters:
https://login.intersystems.com/oauth2...
----> Unexpected request - invalid_request
Meanwhile, I was definitely logged in at InterSystems sites.
I've already have checked it up in two different browsers with the same result. Not a great problem for me, just to inform the community team.
go to post
It would be still "%SYS" inside the `catch` block, so it's unsafe to call any code in its context. Even if you write something like this:
... try { new $namespace set $namespace="%SYS" ... } catch ex { // process the error set sc=ex.AsStatus() do ..logErr(sc) // do some debug logging } return sc
and the ..logErr() call will be successful (generated .int code was not split into parts), the global where the log goes should be the same for all namespaces (e.g. mapped via %ALL pseudo-namespace). There are so many complications that it seems better to avoid any error processing inside the `catch` block above returning the error code. BTW, it sounds reasonable in any case, not only in this one associated with %SYS.
go to post
It would change. I mean that try/catch is still needed to handle exceptions that can occur during namespace change or after the change, working in "%SYS" (mostly security violation errors). Otherwise the method can produce unsolicited exceptions.
go to post
The key feature here is `new $namespace` command rather than the method of its changing, while `set $namespace="%SYS"` seems to be the preferred one as it is well documented and good looking.
I'd still use try / catch outside namespace changing as there can be security errors on attempt to do it. I mean something like this:
classmethod DoSomethingInSYS() as %Status { set sc=$$$OK try { new $namespace set $namespace="%SYS" // do something, e.g. config change } catch ex { // process the error set sc=ex.AsStatus() } return sc }
go to post
Jack, your results are easy to explain. When you use $list*, you must perform conversion to string which adds extra cost.
When you check some conditions inside the loop, you add some cost as well, how much - it depends on checkup method.
So, the best results should be achieved with Robert's and Alex's approaches. I'd prefer the Robert's one as it doesn't force special processing of the first element.
go to post
Agree with you: to guess that the "kosher" way to get a current directory is to call
set currentDir = ##class(%Library.File).NormalizeDirectory("")
one should not be a priest; being a modest monk should be quite enough.
go to post
Thanks for the good advices, guys.
Robert, you should be aware that $zu(12) (a.k.a. $$$FileMgrDir) is usually not the same as $zu(12,""):
My writing was just a result of quick prototyping using the terminal. Just for curiosity, I dived into %occFile.inc and there was no macro to get the current directory. It is possible through class method call (##class(%Library.File).NormalizeDirectory("")), while all this stuff looks like a great overkill for such a small sample.
go to post
runs fast enough with FastFlag=1.
go to post
%GSIZE is written in ObjectScript. What "analogous ObjectScript functionality" do you mean?
go to post
As you probably know, there are two explorers in VS Code: client-side (<Ctrl-Shift-E>) and server-side ("ObjectScript", which comes with InterSystems extensions). If you don't see your routine in the first one, you just need to export it using the second one.
go to post
Thank you, John,
it sounds promising, while I've found only a facility of adding web links here. My case is a "plain" COS command line to execute. In the meanwhile, it seems that I've found a solution; if anybody is interested, I'll write a couple of words about it earlier.
go to post
Hi George
I came to the same conclusion. The task is not too urgent, so we'd likely cope with it by our own means, but thanks anyway.
go to post
I should be more specific in formulating the question.
So, attempt #2:
...And I don't see how to achieve it as the server-side source control menu is only active on "server-side" WorkSpaces, while client-side source control is not available there.
I'm not sticking to this way of adding menu items to VSCode, it just seemed that it will be the easiest one.
Now I see that how wrong I was. Any idea of how to add menu items (with associated server commands) would be appreciated.