Your example shows https but you try a http connection. Is this a mistake or a typo?
- Log in to post comments
Your example shows https but you try a http connection. Is this a mistake or a typo?
Is my assumption correct, you use for the property "PrijsAkCatVm" an own data type (Asci.Getal) instead of %Numeric, in order to be able to use some extra parameters like HINT, VIEW, VISIBLE etc.
Is that correct? If yes, then there is a much simpler solution where neither MS nor SQL won't stumble over it. The catchword is PropertyClass.
/// Create a new Cache class.
/// Define here all the extra parameter you need.
///
Class Extra.Props
{
Parameter HINT;
Parameter VIEW = 1;
Parameter VISIBLE = 1;
Parameter VOLGORDE;
// etc.
}
/// then take your Cache Table, add the above defined class
/// to your Cache Table, complete the property definitions with
/// the appropriate parameters - Done.
///
Class Your.CacheTable Extends %Persistent [ PropertyClass = Extra.Props ]
{
Property PrijsAkCatVm As %Numeric (CAPTION="...", "HINT=...", etc.);
}Now you can use the above defined (extra) parameters in each and every property in this class.
Usually, you get a <COMMAND> error, if you call a (class)method as an expression but the called method does not provide a value
Method SomethingErr()
{
write "Hello"
}
Method SomethingOk()
{
quit "Hello"
}
do ..SomethingErr() // this is OK
do ..SomethingOK() // this is OK
write ..SomethingErr() // gives a <COMMAND> error
write ..SomethingOK() // is OKAs an addition to the above said
set mydir="C:\dir1\dir2\newdir"
//
// creates newdir ONLY if dir1 and dir2 exists
write ##class(%File).CreateDirectory(mydir)
// creates newdir and, IF NECESSARY, the intermediate directories dir2 and dir1 too
write ##class(%File).CreateDirectoryChain(mydir)
There are two aspects of the question,
a) how to get the old property value of a modified property and
b) what happens, if one still opens the same object in the SAME PROCESS once again.
For a) the answer is already given by either using the GetStored() method or cloning the object. In cases, where an old propvalue is needed, I prefer the object cloning, especially if the base object contains embedded objects.
Of course, if the application uses the %Reload() method, then the %OnReload() callback method should do the same as %OnOpen() does.
Class DC.Data Extends %Persistent
{
Property Name As %String;
Property Addr As DataAddr;
Property oldObj As Data [ ReadOnly, Transient ];
Method %OnOpen() As %Status [ Private, ServerOnly = 1 ]
{
set r%oldObj=..%ConstructClone(1) // do a deep clone
do ..%SetModified(0) // clear modified state
Quit $$$OK
}
}
Class DC.DataAddr Extends %SerialObject
{
Property Street As %String;
Property City As %String;
}
kill
set obj=##class(DC.Data).%New(),obj.Name="Joe"
set obj.Addr.Street="Abbey Rd. 123", obj.Addr.City="London"
write obj.%Save() --> 1
kill
set obj=##class(DC.Data).%OpenId(1)
set obj.Name="Paul"
write obj.Name --> Paul
write obj.oldObj.Name --> Joe
set obj.Addr.City="London East"
write obj.Addr.City --> London East
write obj.oldObj.Addr.City --> London
For b), it was said, that a second open (of the same object) returns the same OID. This is true. But there is one more thing. That second open doesn't even trys to get that object from the database but just keeps a lookout in the memory. This means two things (assuming no locks are used)
1) if the object was modified by another process, you "open the old version" already in the memory of your process, and
2) nevertheless that an other process deletes that object, your proces will open a nonexisting object...
Seq Process-A Process-B
-------------------------------------------------------------------------
1 set obj1=##class(DC.Data).%OpenId(1)
2 do ##class(DC.Data).%DeleteId(1)
3 write ##class(DC.Data).%ExistsId(1) --> 0
4 set obj2=##class(DC.Data).%OpenId(1)
5 write obj1=obj2 --> 1
As a consequence of the above, I have learned not to use a simple open:
set obj=##class(Some.Class).%OpenId(oid)but a more secure open, by invalidating a possible old instance:
set obj="", obj=##class(Some.Class).%OpenId(oid)Nice, the first part of the problem (or project, if you wish) is solved. What about a "side project", not pinging all but the active VPNs only? Use the netstat command to get all the established connections
/// Execute an arbitrary OS command and return the command output
ClassMethod OSCmd(cmd, ByRef ans)
{
kill ans
open cmd:"QR":10
set old=$system.Process.SetZEOF(1), ans=0
if $test {
use cmd
for {read line quit:$zeof set ans($increment(ans))=line}
close cmd
}
quit ans
}
Of course, you have to take into account OS specific differences and access rights
do ##class(your.classname).OSCmd("ping google.com", .ans) zw ans
ans=11
ans(1)=""
ans(2)="Pinging google.com [142.250.185.174] with 32 bytes of data:"
ans(3)="Reply from 142.250.185.174: bytes=32 time=21ms TTL=114"
ans(4)="Reply from 142.250.185.174: bytes=32 time=27ms TTL=114"
ans(5)="Reply from 142.250.185.174: bytes=32 time=19ms TTL=114"
ans(6)="Reply from 142.250.185.174: bytes=32 time=18ms TTL=114"
ans(7)=""
ans(8)="Ping statistics for 142.250.185.174:"
ans(9)=" Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),"
ans(10)="Approximate round trip times in milli-seconds:"
ans(11)=""
do ##class(your.classname).OSCmd("netstat -ano | findstr ""ESTABLISHED""", .ans) zw ans
ans=6
ans(1)=" TCP 127.0.0.1:23 127.0.0.1:50814 ESTABLISHED 8272"
ans(2)=" TCP 127.0.0.1:23 127.0.0.1:60874 ESTABLISHED 2872"
ans(3)=" TCP 127.0.0.1:23 127.0.0.1:63199 ESTABLISHED 8272"
ans(4)=" TCP 127.0.0.1:1972 127.0.0.1:49436 ESTABLISHED 2404"
ans(5)=" TCP 127.0.0.1:1972 127.0.0.1:51840 ESTABLISHED 2404"
ans(6)=" TCP 127.0.0.1:1972 127.0.0.1:54330 ESTABLISHED 2404"
Now you can analyse and process the command output...
Also, see this post too.
Some remarks:
// on Linux, it's a good idea to limit the ping count
set cmnd="ping -c 3 "_host
// if $zeof isn't alway on, as on my systems the case is
// we need two more lines
set cmd="..."
set old=$system.Process.SetZEOF(1) // turn $ZEOF on
open cmd...
...
close cmd
do $system.Process.SetZEOF(old) // reset to old stateFour short lines of Objectscript code
ClassMethod Ping(host)
{
set cmd="ping "_host
open cmd:"QR":10
for {use cmd read ans quit:$zeof use 0 write ans,!}
close cmd
}
// some test
do ##class(your.class).Ping("google.com")
Pinging google.com [142.250.185.110] with 32 bytes of data:
Reply from 142.250.185.110: bytes=32 time=25ms TTL=114
Reply from 142.250.185.110: bytes=32 time=26ms TTL=114
Reply from 142.250.185.110: bytes=32 time=19ms TTL=114
Reply from 142.250.185.110: bytes=32 time=19ms TTL=114
Ping statistics for 142.250.185.110:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 19ms, Maximum = 26ms, Average = 22ms
Using a two digit year in 2023 is the same as wishing to get a Y2K problem again. Probably it will be now the Y2.1K issue.
My favorit is
write $tr($zd($h,15),"/.")👍👌👏
Nice, and where are those 4 byte floating point data? Do you have some information about that record?
also, you could try the
$SCONVERT(s,format,endian,position)
function (Format: F4)
Instead of ZW RECORD (which only gives an ASCII rubbish) please give some examples as hex-dump (ZZDUMP RECORD or something similar). A few values together with hex-dump.
Merely you have to "open" the article to get those tags into top position. If you just browse (see the screenshot) over the articles: (a) you have to scroll down and (b) a tag name could have but must not have the same meaning as an acronym. In my opinion, an acronym should always be explained after the first usage - either you write it out or you insert a link or whatever...
By the way, you can also "shorten" a given node and start over...
// from the above example,
// name = ^A("TEST1","TEST2", ... "TEST10")
// now we take that global with the first two subscripts
set name = $name(@name,2)
// and add new subscripts
set name = $name(@name@(3333,4444))
set @name = "new data"Try it and then ZWRITE ^A to see the effect
set name = $name(^A)
for i=1:1:10 { set name = $name(@name@("TEST"_i)) }
set @name=""Excuse me, but it's a bad habit to introduce something with an acronym without saying what that acronym stands for. The site: https://acronyms.thefreedictionary.com/CCR lists 241 possible meanings for CCR. Which one is yours?
I assume, we are talking about ObjectScript? Then you got in the main method a <SYNTAX> error because "calling" is not a command keyword. So what are you really doing? We don't need the whole main method, the line with the call would be enough. By the way, a method name like "this_method" is not a valid name except if you place it in (double)quotes. Something, which is formal correct, looks like this:
Method "this_MainMethod"()
{
do ..SecondMethod()
}
Method SecondMethod()
{
// ...
}Your contribution is included too...
I just saw now, I published the next to last version instead of the last... sorry. I end up 53 bytes. This "s_0" was a work-around for not to use $g(z) by getting at least one loop for case, someone calls the method with an empty string
ClassMethod IsValid(s)
{
f{s c=$a(s,$i(i))+1 ret:$i(z,c=42-(c=41))>0!'c 'z}
}
After I put all the solutions in a pot, salting them with some own ideas then filtering, I got a really nice solution with 55 bytes. Works for all the examples given by @Eduard.Lebedyuk.
The best idea-donors where, among others, @Stuart Strickland and @Lorenzo Scalese, thank you.
ClassMethod IsValid(s)
{
f{s c=$a(s_0,$i(i))+1 ret:$i(z,c=42-(c=41))>0!'c 'z}
}Two more bytes and the problem is solved:
Property refDate As %Date [InitialExpression = {$piece($horolog,",",1)}];
//.............................................^......................^
If my aging brain me do not misleads, you could save two more bytes
g:"()"'[$c(c) // instead of this (13 bytes)
g:c=41-c+40 // use this (11 bytes)
I hope, this change does not affect the way I use (some of the) mnemonics - am I right?
Class My.Mnemonics Extends %RegisteredObject
{
/// Set-/Reset mnemonic routine
ClassMethod SetMnemonics(rou={$zname}) [ ProcedureBlock = 0 ]
{
set old=##class(%Device).GetMnemonicRoutine()
use $i::"^"_rou
quit old
MA(x) write "This is MA "_x quit
MB() write "This is MB" quit
}
}
// for example:
set old=##class(My.Mnemonics).SetMnemonics()
write /ma(123)
do ##class(MyMnemonics).SetMnemonics(old)
It seems, that will be hard to underbid... Congratulations!
OK, one can short down those 20 bytes into 17 and we end up with 64 bytes.
ClassMethod IsValid(x)
{
1 s z=x,x=$replace($tr(x,$tr(x,"()")),"()","") g 1:x'=z q x=""
}Again, speed wasn't asked
OK, I start with 47 chars... unfortunately, I have to add 20 chars more for that (stupid) extra requirement of ignoring characters like {, [, <, etc. therefore end up with 67 chars
ClassMethod IsHalfValid(x)
{
1 s z=x,x=$replace(x,"()","") g 1:x'=z q x=""
}
ClassMethod IsFullValid(x)
{
1 s z=x,x=$replace($zstrip(x,"*e",,"()"),"()","") g 1:x'=z q x=""
}Speed was'n asked...
In the mean time the answer is already given by Mr Maslennikov and others, but to shorten your runtime, you could also try a "variablenless" loop, maybe this gives you some seconds more... The emphasis is on "maybe".
// if you have null-subscripts enabled
if $d(^YYY(""))!1 for i=0:1 {quit:$order(@$zr)=""} write i
// if null-subscripts are not enabled
if $d(^YYY(-9E18))!1 for i=0:1 {quit:$order(@$zr)=""} write i
// of course, you can do that on any arbitrary level too
if $d(^YYY(1,2,3,""))!1 for i=0:1 {...} write i
// the value of -9E19 ist just for explanation, use a value suitable for your needs
May I ask for the background, why do you need that node count?
Caution, backward $order() is always slower than forward $order(). If you need the last (hopefully few) entries, than it's OK to use a backward-$O() but running (counting) from the bottom to the top over several millions of nodes is definitely not an effective run.