go to post Eduard Lebedyuk · Mar 29, 2019 <FILEFULL> - Caché attempted to allocate a disk block for more global data or routine storage, but the attempt failed because the Caché database is full and could not be expanded.Affected db is /hs-connect-hom/db/BPINTEGRADEV-GLB.
go to post Eduard Lebedyuk · Mar 28, 2019 Bitmap indices maintain one node per each chunk of 64 000 id's, if at least one id from that range exists. So random integer ids can slow bitmaps down. On the other hand if there are two consecutive but spread (i.e 1..1000 and 100000...110000) id sequences it would generate just 2 global nodes so everything should be ok in that scenario.Check index global in various scenarios: Example.Bitmap Class Example.Bitmap Extends %Persistent { Property ID As %Integer(MINVAL = 1); Property Value As %Integer(MAXVAL = 9, MINVAL = 0); Index IDKEY On ID [ IdKey, Unique ]; Index ValueIndex On Value [ Type = bitmap ]; ClassMethod Populate(startid, endid, step = 1) As %Integer { set count = 0 do ..%KillExtent() for i = startid:step:endid { set count = count + 1 set ^Example.BitmapD(i) = $lb("", $random(10)) } do ..%BuildIndices() quit count } Query Select(value) As %SQLQuery { SELECT ID FROM Example.Bitmap WHERE Value = :value } /// do ##class(Example.Bitmap).Test() ClassMethod Test() { do ..TestOne(1, 1000000) do ..TestOne(100000000, 101000000) do ..TestOne(1, 1000000000, 1000) } ClassMethod TestOne(startid, endid, step = 1) { set startTS = $zh set count = ..Populate(startid, endid, step) set endTS = $zh set populateTime = endTS - startTS set startTS = $zh set rs = ..SelectFunc($random(10)) set endTS = $zh set queryTime = endTS - startTS write $$$FormatText("Start: %1, End: %2, Step: %3, Count: %4, Populate Time: %5, Query Time: %6", startid, endid, step, count, populateTime, queryTime),! } }
go to post Eduard Lebedyuk · Mar 25, 2019 The easiest way is to use JSON_OBJECT for everything. Fastest would be just writing to device from resultset. Combine these approaches to get the performance you need (add this code to Parent class and call Test method): Query Display() As %SQLQuery { SELECT JSON_OBJECT( 'ID':%ID, 'Name': Name, 'Description': Description, 'Children': Example.Parent_GetChildrenInfo(%ID) ) FROM Example.Parent } /// do ##class(Example.Parent).Test() ClassMethod Test(count = 0) { if count>0 { do ##class(Example.Child).%KillExtent() do ..%KillExtent() do ##class(Example.Child).Populate(count,,,,$$$NO) do ..Populate(count,,,,$$$NO) } do ..DisplayFunc().%Display() } ClassMethod GetChildrenInfo(id) As %String [ SqlProc ] { #define CRLF $c(13,10) #define ZENJSISNUM(%val) ($IsValidNum(%val)&&(%val=+(%val))) #define ZENJSNUM(%num) $fnumber(%num,"LON") #; JSON utility macros that use the JSON translation table instead of the JS translation table #define ZENJSTABLE(%format) ("JS"_$S(%format["u":"ML",1:"")) #define ZENJSONTABLE(%format) ("JSON"_$S((%format["u"):"ML",1:"")) #define ZENJSONESCAPE(%str,%format) $S(%format["s":$ZCVT(%str,"O",$$$ZENJSONTABLE(%format)),1:$Replace($ZCVT(%str,"O",$$$ZENJSTABLE(%format)),"\'","'")) #define ZENJSONSTR(%str,%format) (""""_$$$ZENJSONESCAPE(%str,%format)_"""") #define ZENJSONPROP(%prop,%format) $$$ZENJSONSTR(%prop,%format) #define ZENJSONVALUE(%val,%format) $S($$$ZENJSISNUM(%val):$$$ZENJSNUM(%val),$C(0)=(%val)||$ListValid(%val):"""""",1:$$$ZENJSONSTR(%val,%format)) #define ZENJSONPAIR(%pr,%val,%format) $$$ZENJSONPROP(%pr,%format)_":"_$$$ZENJSONVALUE(%val,%format) set out = "[" set ids = ..ChildrenGetStored(id) set ptr=0 set separator=0 while $listnext(ids,ptr,value) { set value = $lg(value) set:separator out = out _ "," set out = out _ "{" set out = out _ $$$ZENJSONPAIR("Name",##class(Example.Child).NameGetStored(value),"") _"," set out = out _ $$$ZENJSONPAIR("Description",##class(Example.Child).DescriptionGetStored(value),"") set out = out _ "}" set separator = 1 } set out = out _ "]" quit out }
go to post Eduard Lebedyuk · Mar 25, 2019 I think it would be better to do with REST, but SQLQuery tag can do what you want.
go to post Eduard Lebedyuk · Mar 14, 2019 The easiest way would be to configure web server on customersdomain.com to act as a reverse proxy. In this case it would proxy requests to yourownserver.com or wherever you need.Another way is to install CSP Gateway on a customersdomain.com. After that connect CSP Gateway to your Cache/Ensemble/InterSystems IRIS instance on yourownserver.com. And connect web server on customersdomain.com to CSP Gateway on customersdomain.com.Advantage of this approach is that static would be served directly from customersdomain.com server.
go to post Eduard Lebedyuk · Mar 11, 2019 If you already have HL7 message inside Ensemble you can use Caché SQL Gateway which provides access from Caché to external databases via JDBC and ODBC. You can use SQL Gateway (probably in ODBC mode) to update SQL Server table(s).
go to post Eduard Lebedyuk · Mar 10, 2019 Cache is officially supported on Ubuntu 16.04 LTS according to Supported Platforms table.If you're just starting I recommend using InterSystems IRIS (which is supported on Ubuntu 16.04 LTS and 18.04 LTS among other platforms).You can download all kits from WRC:
go to post Eduard Lebedyuk · Mar 9, 2019 You can try to write to a TCP device with SSL. Doesn't require additional permissions: ClassMethod Exists(ssl As %String) As %Boolean { #dim exists As %Boolean = $$$YES set host = "google.com" set port = 443 set timeout = 1 set io = $io set device = "|TCP|" _ ##class(%PopulateUtils).Integer(5000, 10000) try { open device:(host:port:/SSL=ssl):timeout use device // real check write "GET /" _ $c(10),*-3 // real check - end // should be HTTP/1.0 200 OK but we don't really care //read response:timeout //write response } catch ex { set exists = $$$NO } use io close device quit exists } It's slower than direct global check but if you want to do it rarely, I think it could be okay. Doesn't require additional permissions. Code to compare times: ClassMethod ExistGlobal(ssl) [ CodeMode = expression ] { $d(^|"%SYS"|SYS("Security","SSLConfigsD",ssl))#10 } /// do ##class().Compare() ClassMethod Compare(count = 1, ssl = "GitHub") { Write "Iterations: ", count,! Write "Config exists: ", ..Exists(ssl),! set start = $zh for i=1:1:count { set exists = ..Exists(ssl) } set end = $zh set time = end - start Write "Device check: ", time,! set start = $zh for i=1:1:count { set exists = ..ExistGlobal(ssl) } set end = $zh set time2 = end - start write "Global check: ", time2,! } Results: Iterations: 1 Config exists: 1 Device check: .054983 Global check: .000032 Iterations: 1 Config exists: 0 Device check: .017351 Global check: .00001 Iterations: 50 Config exists: 1 Device check: 2.804497 Global check: .000097 Iterations: 50 Config exists: 0 Device check: .906424 Global check: .000078
go to post Eduard Lebedyuk · Mar 9, 2019 I can use ($ztimestamp) to get UTC time and then convert it into local time i am using the below way is this correct? SET stamp=$ZTIMESTAMPw !,stampSET localutc=$ZDATETIMEH(stamp,-3)w $ZDATETIME(localutc,3,1,2)Yes, sure.My Question is how i can program this task in the below wayYou heed to add three hours. Use DATEADD method for this: write $SYSTEM.SQL.DATEADD("hour", 3, yourDate)
go to post Eduard Lebedyuk · Mar 7, 2019 The code looks good. What error are you getting?Try replacing stream2 %Stream.FileCharacter with %Stream.FileBinary.Try replacing stream1 %Stream.FileCharacter with %Stream.TmpBinary.If you have message sample less than 3,5 mb in size try to write a test without intermediate stream.You probably should write to a pdf file and not a txt one.If you can, get a sample original/decoded file. Compare original file and your stream2 file using hex editor to spot differences.
go to post Eduard Lebedyuk · Mar 7, 2019 Use methods from %CSP.Portal.Utils class: set pageID = "" //page url, URL encoded via $zconvert(url,"O","URL") set currentResource = ##class(%CSP.Portal.Utils).%GetCustomResource(pageID) set sc = ##class(%CSP.Portal.Utils).%SetCustomResource(pageID, newResource)
go to post Eduard Lebedyuk · Mar 7, 2019 I' do it in 2 steps.Iterate over data array and build a temp local structure to hold all additional items you needIterate over this new structure and add these items to data array.You can add to array using %Push method: do Obj.data.%Push(newItem) If you want to push at a specific posiiton, use %Set do Obj.data.%Set(position, newItem) That said your later structure contains data which does not exist in the original structure (text values for projects and sub-projects) so you need to get it from somewhere. Also is project - subproject hierarchy one-level, or there could be an arbitrary number of sub-project levels (i.e. 10 → 10-1 → 10-1-1 → 10-1-1-1)?
go to post Eduard Lebedyuk · Mar 7, 2019 Enable ODBC log. Maybe there would be errors pointing to the root of the issue?Maybe something to do with INFORMATION_SCHEMA.
go to post Eduard Lebedyuk · Mar 5, 2019 Some ideas.1. The problem is isc.rabbitmq.API class was imported with an error. Delete this class and try this code (post output): Set class = "isc.rabbitmq.API" Set classPath = ##class(%ListOfDataTypes).%New() Do classPath.Insert(PATH-TO-JAR) Set gateway = ##class(%Net.Remote.Gateway).%New() Set sc = gateway.%Connect("localhost", PORT, $Namespace, 2, classPath) Zwrite sc Set sc = gateway.%Import(class) Zwrite sc Write ##class(%Dictionary.CompiledClass).%ExistsId(class) 2. Try recompiling isc.rabbitmq.API class. 3. Maybe have 2 amqp jars with com.rabbitmq.tools.jsonrpc.JsonRpcException class. The only class you should import is isc.rabbitmq.API class. It shouldn't pull many additional ones. 4. What version of AMQP are you using? I'm using amqp-5.0.0. Try the same verison?
go to post Eduard Lebedyuk · Mar 5, 2019 I think the easier solution would be to map classes and data to a target namespace and just execute the query in the same namespace. Documentation.
go to post Eduard Lebedyuk · Mar 1, 2019 I suppose you can solve this problem by separating your persistent class into abstract definition and persistent "storage only" class.It could look like this: Class test.Abstract.Order [ Abstract ] { Property a; Method doStuff() { } } and persistent class: Class test.Order Extends (test.Abstract.Order, %Persistent) { /*Generated Storage */ } And only map test.Abstract package. This way you'll need to: Copy test.Order class manually (but only once, as it does not change).Recompile test.Order class in each namespace if Abstract realization changes. But in this setup persistent class could be tuned, etc.. Also you can automate deployment steps with CI/CD tools.
go to post Eduard Lebedyuk · Feb 28, 2019 I should read the docs again. Removing M option helped.Thank you, @Nick Zhokhov.
go to post Eduard Lebedyuk · Feb 25, 2019 Here's how you can do it:Download CSPGateway kit from WRC for 2017.2.1Install it on a new serverConnect it to IISOpen csp/bin/Systems/Module.cxw and add required application(s)I think this documentation page describes exactly what you want to do.
go to post Eduard Lebedyuk · Feb 24, 2019 You get this error (Datatype value '2019-02-01' is not a valid number) because %Date stores data in horolog format, so you need to do one of:(Recommended approach) Convert date value from external format (2019-02-01) into internal format (horolog) using $zdh function: Set consumerRecord.ActivePeriod.StartDate = $zdh(obj.activePeriod.startDate, 3) Use datatype for which this value is valid, i.e. %TimeStamp. To check, all datatype classes offer IsValid method, you can use it to check value validity zw ##class(%TimeStamp).IsValid("2019-02-01") If you're using InterSystems IRIS you can store dates as %PosixTime. Regarding Atelier, I use it to debug REST services and it shows variable values. You can try to reinstall it. If you're on Windows you can also use Studio.