go to post Lorenzo Scalese · Nov 22, 2024 Hi @Davi Massaru Teixeira Muta , As far as i know, there is no lock log history. This is understandable, as there would be a lot of them on heavily used systems. If you can modify the application code, may be you can add log trace when this error happens. With ^$LOCK you can retrieve the owner of a lock. Example: Lock +^my.global(1) Write "Owner is : ", ^$LOCK($Name(^my.global(1)),"OWNER") ;Owner is : 5216 Even if you recover the PID, analysis can be difficult if the process no longer exists at the time you perform the analysis. Maybe add something like this for logging (executed with a job): /// Start this method in job ex: /// Job ##class(pkg.ClassName).TraceLock($Name(^my.global)) ClassMethod TraceLock(lockname As %String) As %Status { Set sc = $$$OK Set pid = ^$LOCK(lockname, "OWNER") If pid = "", $QLength(lockname)>0 { ; check if the node is fully locked Set pid = ^$LOCK($QSubscript(lockname,0), "OWNER") } If pid = "" { ; no data ... Return sc } Set key = $Increment(^debug.locktrace) Set ^debug.locktrace(key, "from pid") = $ZParent ; Just to keep a trace of the pid started this job Set ^debug.locktrace(key, "info") = $ZDateTime($Horolog, 3, 1) _ " The lock " _ lockname _ " owner is "_pid Set process = ##CLASS(%SYS.ProcessQuery).Open(pid) If $IsObject(process) { Set ^debug.locktrace(key, "owner-UserName") = process.UserName Set ^debug.locktrace(key, "owner-StartupClientIPAddress") = process.StartupClientIPAddress Set ^debug.locktrace(key, "owner-StartupClientNodeName") = process.StartupClientNodeName Set ^debug.locktrace(key, "owner-CurrentLineAndRoutine") = process.CurrentLineAndRoutine Set ^debug.locktrace(key, "owner-Routine") = process.Routine } Return $$$OK ; Exemple of result: ;^debug.locktrace=1 ;^debug.locktrace(1,"from pid")=12964 ;^debug.locktrace(1,"info")="2024-11-22 12:25:25 The lock ^my.global owner is 5216" ;^debug.locktrace(1,"owner-CurrentLineAndRoutine")="" ;^debug.locktrace(1,"owner-Routine")="shell" ;^debug.locktrace(1,"owner-StartupClientIPAddress")="127.0.0.1" ;^debug.locktrace(1,"owner-StartupClientNodeName")="TRM:" ;^debug.locktrace(1,"owner-UserName")="_SYSTEM" } Hope this help. Lorenzo.
go to post Lorenzo Scalese · Oct 10, 2023 Hi @Dmitry Maslennikov , Yesterday I experienced this kind of problem with web socket.To limit the license usage, I did this : Class dc.journalindexer.WebSocket Extends %CSP.WebSocket { Method OnPreServer() As %Status { Do %session.Login("wsuser",,1) Set ..SharedConnection = 1 ; ... some lines of code Quit sc } Method OnClientMessage( data As %String = "", close As %Integer) As %Status { ; force logout and EndSession on disconnect from client If $Get(close) = 1 { Do %session.Logout() Set %session.EndSession = 1 Do ..EndServer() } Quit 0 } }
go to post Lorenzo Scalese · Aug 11, 2023 Hello @Michael Davidovich , Did you try to override OnPreDispatch ?Also you can configure your web application to use a subclass of %CSP.SessionEvents and override OnStartRequest, OnEndRequest . Set Application = "/csp/YourWebApp" Do ##class(Security.Applications).Get(Application, .p) Set p("EventClass") = "YourCSPEventsClassName" Set sc = ##class(Security.Applications).Modify(Application, .p)
go to post Lorenzo Scalese · Jun 20, 2023 Hello, following the documentation of the argument yearopt , you can do : Write $ZDATE($ZDATEH("13/Jun/23",8,,6),8) 6 Represent all dates in the current century with two-digit years and all other dates with four-digit years.
go to post Lorenzo Scalese · Jun 18, 2023 Hello @Nildo Torres , If the collation to install is identified, you can use the following classmethod : Set $Namespace = "%SYS" ; Change fraw by the locale you need. Set sc = ##class(Config.NLS.Locales).Install("fraw")
go to post Lorenzo Scalese · Jun 14, 2023 Finally, I found the solution : $SYSTEM.OBJ.IsUpToDate("classname")
go to post Lorenzo Scalese · Mar 15, 2023 Hi @Robert Cemper , I already do this with an environment variable passed in the docker-compose file. I don't know if smarter solution exists.
go to post Lorenzo Scalese · Mar 8, 2023 Hi @Scott Roth , Ten years ago, I implement %ZSTOP routine to execute code when a job process exits or when the instance shutdown. I removed my code, but the routine looks like this: %ZSTOP ; User shutdown routine. Quit SYSTEM ; Cache stopping Set oldNs = $Namespace Try { Set $Namespace = "MYAPPNAMESPACE" ; Do something when stopping the instance. }Catch(ex) {} Set $Namespace = oldNS Quit LOGIN ; a user logs out of Cache (user account or telnet) Quit JOB ; JOB'd process exits. If $Namespace = "MYAPPNAMESPACE" { ; do something when job process exits } Quit CALLIN ; process exits via CALLIN interface. Quit Logit(entrypoint, caller) PRIVATE ; Quit
go to post Lorenzo Scalese · Feb 26, 2023 Hi @Evgeny Shvarov I think the created resource id is in the header response. I don't remember the header name 🤔
go to post Lorenzo Scalese · Feb 25, 2023 Hello @Pietro Montorfano , You can try to write your own export method.Using %Library.RoutineIndex looks good. Example to export all ".MAC" : set tRes = ##class(%SQL.Statement).%ExecDirect(.tStmt,"select name||'.'||type as itemName from %Library.RoutineIndex where type = ? and $Extract(name,1) <> '%'","MAC") While tRes.%Next() { Do $SYSTEM.OBJ.ExportUDL(tRes.%Get("itemName"),"<dir>/"_tRes.%Get("itemName")) }
go to post Lorenzo Scalese · Feb 21, 2023 For adding a member, this is the IP of the first member (primary). It's correct.No matter the virtual IP, it's the role of the arbiter\agent to communicate who is primary in case of a switch. However, a virtual IP is convenient for access to your applications. For example, with web applications: If the system switches from node A to node B, it is more convenient to use a virtual IP address. You can use this in your web server configuration so that it always points to the primary node.
go to post Lorenzo Scalese · Feb 2, 2023 Hi, I never tested myself, but in Python, there is pdfkit library. Maybe the support of Python with IRIS could be useful for your case.
go to post Lorenzo Scalese · Sep 22, 2022 Hello @David Hockenbroch I tested this simple method using CodeMode = Objectgenerator : Method test() [ CodeMode = objectgenerator ] { Write Quit 1 } Do $SYSTEM.OBJ.Compile("User.NewClass1","ck") We can see a lot of variable values at compile time : .... %qstruct="ck" .... %qstruct contains compile flags and qualifiers
go to post Lorenzo Scalese · Jul 5, 2022 Hi, Two years ago, I analyzed the behaviours using stream and %Persistent class. Class Test.Stream1 Extends %Persistent { Property st As %GlobalBinaryStream; ClassMethod add1() As %Status { ; write stream in ^Test.Stream1S Set o = ..%New() Do o.st.Write("azeruiop") Quit o.%Save() } ClassMethod add2() As %Status { ; write stream in ^CacheStream Set o = ..%New() Set st = ##class(%GlobalBinaryStream).%New() Do st.Write("azeruiop") Set o.st = st Quit o.%Save() } Storage Default { <Data name="Stream1DefaultData"> <Value name="1"> <Value>%%CLASSNAME</Value> </Value> <Value name="2"> <Value>st</Value> </Value> </Data> <DataLocation>^Test.Stream1D</DataLocation> <DefaultData>Stream1DefaultData</DefaultData> <IdLocation>^Test.Stream1D</IdLocation> <IndexLocation>^Test.Stream1I</IndexLocation> <StreamLocation>^Test.Stream1S</StreamLocation> <Type>%Storage.Persistent</Type> } } The method add2 use ^CacheStream due to the default storage usage (as described by @Robert Cemper ). However, We can force the storage in ^Test.Stream1S with :Do st.%LocationSet("^Test.Stream1S")
go to post Lorenzo Scalese · Jul 2, 2022 Hi @Robert Cemper ! Good Idea for the table.In french : English French Data Donnée F Value Valeur F Database Base de données F File Fichier M Directory Répertoire M
go to post Lorenzo Scalese · Apr 18, 2022 Hi @Robert Cemper, @Vitaliy.Serdtsev Thank you for your replies! I found a solution to do this without any change to an existing code, not simple but It works and could be useful in a critical situation. I read the code of ^%ETN and see these lines : UserError() s $zt="UserErrorE" i $d(^rOBJ("%ZERROR")) d . n %00000 d ^%ZERROR So, If we create a "%ZERROR" routine, we have an entry point : ROUTINE %ZERROR %ZERROR If $Data(^zForceCommit($Job)) { ; to avoid do this for all processes... While $TLEVEL { TCOMMIT } } Quit And then, we must terminate the process like that: Set pid = "1234" ; pid to terminate Set ^zForceCommit(pid)="" Zn "%SYS" Set process = ##class(SYS.Process).%OpenId(pid) Set sc = process.Terminate(1) It's important to use the SYS.Process class and the Terminate method with argument 1 to use ^%ETN.
go to post Lorenzo Scalese · Apr 5, 2022 Hi @Harshdeep Acharya , You should take a look to this repository : iris-healthtoolkit-service OEX Link : iris-healthtoolkit-service This is a solution provided by @Guillaume Rongier
go to post Lorenzo Scalese · Sep 29, 2021 Code snipet to expose the problem. Class ZUser.NewClass1 Extends %Persistent [ Not ProcedureBlock ] { ClassMethod Demo() { Do ..TestLock() ; This class is Not ProcedureBlock the record still locked ; If the class is ProcedureBlock the record is released. ; try by yourself :-) } ClassMethod TestLock() As %Status { Set id = $Order(^ZUser.NewClass1D("")) If id = "" { Set obj = ##class(ZUser.NewClass1).%New() Do obj.%Save() Kill obj } Set id = $Order(^ZUser.NewClass1D("")) Set obj = ##class(ZUser.NewClass1).%OpenId(id, 4) ; in case of usage Not ProcedureBlock you should ; kill obj or set obj="" (and all others variables with this object reference) to release the lock Return $$$OK } }
go to post Lorenzo Scalese · May 6, 2021 Solved. Finally, It was simple. The routine has been installed after the switch, but before my investigation. So, I thought the routine was there and not performed.