Skip to content

Instantly share code, notes, and snippets.

@suriyasv
Created November 12, 2016 13:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save suriyasv/2ed7f2dbcfd8c79f3b9938762c17c0b5 to your computer and use it in GitHub Desktop.
Save suriyasv/2ed7f2dbcfd8c79f3b9938762c17c0b5 to your computer and use it in GitHub Desktop.
Ensemble Orphaned Messages Purge Routine
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25" zv="Cache for Windows (x86-64) 2013.1.4 (Build 801U)" ts="2014-05-12 13:24:27">
<Class name="zEnsSupport.Msgs">
<IncludeCode>Ensemble,EnsHL7</IncludeCode>
<Super>%RegisteredObject</Super>
<TimeChanged>63319,48173.215985</TimeChanged>
<TimeCreated>62962,32987.669526</TimeCreated>
<UDLText name="T">
<Content><![CDATA[
/*
Changes:
05/12/2014 RCK - Removed 'Hidden' from the class definition.
*/
]]></Content>
</UDLText>
<UDLText name="T">
<Content><![CDATA[
/*
tMsgBodies(MessageBodyClassName) = $List
1 - Min(MessageBodyId) from Ens.MessageHeader
2 - TimeCreated for MessageBodyClassName Min(MessageBodyId)
3 - Table corresponding to MessageBodyClassName (i.e. EnsLib.HL7.Message = EnsLib_HL7.Message)
4 - Count(ID) from SQL Table (#3)
5 - Min(ID) from SQL Table (#3)
6 - Known global storage locations for instances of MessageBodyClassName - $ListBuild(DataLocation,IndexLocation,SreamLocation,...)
7 - Total size of globals (#6) before running DeleteMsgBodiesUpToId()
8 - Number of deleted messages (populated by DeleteMsgBodiesUpToId())
9 - Total size of globals (#6) after running DeleteMsgBodiesUpToId()
10 - Super (Extends ...) from SQL Table (#3)
*/
]]></Content>
</UDLText>
<Method name="Menu">
<Description>
D ##class(zEnsSupport.Msgs).Menu()</Description>
<ClassMethod>1</ClassMethod>
<Implementation><![CDATA[
Do {
Set tSC=$$$OK
Kill ary,cnt
Write #,!,"zEnsSupport.Msgs Menu:"
Write !,"================================================================================",!
Write !,"PURGE CLEANUP/MESSAGE REPORT OPTIONS"
Write !," 1. Run Complete Ensemble Message Body Report"
Write !," 2. Run Ensemble Message Body Report w/o Global Info"
Write !," 3. Delete ALL MessageBodies < Min(MessageBodyId) in Ens.MessageHeader"
Write !," 4. Delete ONLY EnsLib.HL7.Messages < Min(MessageBodyId) in Ens.MessageHeader"
Write !," 5. Delete ONLY Ens.Response messages < Min(MessageBodyId) in Ens.MessageHeader"
Write !," 6. Show Summary Count of MessageBodies < Min(MessageBodyId)"
Write !," 7. Show Summary Count of EnsLib.HL7.Messages < Min(MessageBodyId)"
Write !," 8. Show Summary Count of Ens.Responses < Min(MessageBodyId)"
Write !," 9. Gather HL7 related Global information"
Write !,"10. Quick Check for Orphaned Message Bodies (Top 1 Not Min, No Counts)"
Write !,"11. Find HL7 Segment Mismatches"
Write !,"12. Fix HL7 Segment Mismatches"
//Write !!,"MISC OPTIONS"
//Write !,"90. CleanProduction"
//Write !,"91. SQL Shell"
Read !!,"Selection: ",x
Write !
If x=1 { Set tSC=..MessageBodyReport(.ary,1) }
ElseIf x=2 { Set tSC=..MessageBodyReport(.ary,1,0) }
ElseIf x=3 { Set tSC=..DeleteMsgBodiesUpToId(.ary,1,0) }
ElseIf x=4 { Set tSC=..DeleteHL7MsgsNotRefByMsgHeader(.cnt,1) }
ElseIf x=5 { Set tSC=..DeleteEnsResponseNotRefByMsgHeader(.cnt,1) }
ElseIf x=6 { Set tSC=..DeleteMsgBodiesUpToId(.ary,1,0,1,0) }
ElseIf x=7 { Set tSC=..DeleteHL7MsgsNotRefByMsgHeader(.cnt,1,0) }
ElseIf x=8 { Set tSC=..DeleteEnsResponseNotRefByMsgHeader(.cnt,1,0) }
ElseIf x=9 { Set tSC=..BasicHL7GlobalInfo() }
ElseIf x=10 { Set tSC=..QuickMessageBodyReport(.ary,1) }
ElseIf x=11 { Set tSC=..FindHL7SegMismatch(1,0) }
ElseIf x=12 { Set tSC=..FindHL7SegMismatch(1,1)}
ElseIf x=90 {
Read "CleanProduction? <No> ",tYN
If ..YES(tYN) {
Write !,"Running CleanProduction!",!
Set tSC=##class(Ens.Director).CleanProduction(1)
}
}
ElseIf x=91 { Do $System.SQL.Shell() }
ElseIf '..QUIT(x) { Write !,"Invalid Option!",! }
//Some functions will return known errors (i.e. storage defined but not yet used = Global not found)
If ('tSC) Do $System.OBJ.DisplayError(tSC) Write !
} While ('..QUIT(x))
Quit
]]></Implementation>
</Method>
<Method name="MessageBodyReport">
<Description><![CDATA[
Complete analysis of the Ens.MessageHeader table. Finds each unique MessageBodyClassName in the Ens.MessageHeader table,
the number of references to each class (Hdr Count), number of unique MessageBodyIds for each MessageBodyClassName (Unq Count), and
minimum Id for each MessageBodyClassName in the Ens.MessageHeader table. Also looks at the SQL table for each MessageBodyClassName
and finds the Count() and Min(Id). <br><br>
It can be generally assumed that the Min Id from the Ens.MessageHeader table for each MessageBodyClassName should equal the Min Id
from the MessageBodyClassName table. This can depend on how classes are extended and if %Persistent data is being kept for other purposes.<br><br>
This method Outputs a pMsgBodies array which can be used to call DeleteMsgBodiesUpToId(). It will take considerably longer to run if
the option to pCheckGlobalSizes is true. <br><br>
pMsgBodies(MessageBodyClassName) = $List<br>
&nbsp;&nbsp;&nbsp;1 - Min(MessageBodyId) from Ens.MessageHeader<br>
&nbsp;&nbsp;&nbsp;2 - TimeCreated for MessageBodyClassName Min(MessageBodyId) from Ens.MessageHeader<br>
&nbsp;&nbsp;&nbsp;3 - Table corresponding to MessageBodyClassName (i.e. EnsLib.HL7.Message = EnsLib_HL7.Message)<br>
&nbsp;&nbsp;&nbsp;4 - Count(ID) from SQL Table (#3)<br>
&nbsp;&nbsp;&nbsp;5 - Min(ID) from SQL Table (#3)<br>
&nbsp;&nbsp;&nbsp;6 - Known global storage locations for instances of MessageBodyClassName - $ListBuild(DataLocation,IndexLocation,SreamLocation,...)<br>
&nbsp;&nbsp;&nbsp;7 - Total size of globals (#6) before running DeleteMsgBodiesUpToId()<br>]]></Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>*pMsgBodies,pVerbose:%Boolean=0,pCheckGlobalSizes:%Boolean=1</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tSC=$$$OK,tTotalHdrCount=0,tTotalHdrUnique=0,tTotalTblCount=0
&SQL(DECLARE cur3 CURSOR FOR
SELECT %Exact(MessageBodyClassName), COUNT(ID), COUNT(DISTINCT MessageBodyId), MIN(MessageBodyId), TimeCreated
INTO :tMsgBody,:tHdrCount,:tUniqueMsgBodies,:tMinMessageBodyId,:tTimeCreated
FROM Ens.MessageHeader
GROUP BY MessageBodyClassName)
&SQL(OPEN cur3)
Write:pVerbose !,?25,"Message Header",?62,"SQL Table"
Write:pVerbose !,?12,"========================================",?54,"=========================="
Write:pVerbose !,"Class Name",?12," Hdr Count",?26," Unq Count",?40," Min Id",?54," Count",?68," Min Id"
Write:pVerbose !,"==========",?12,"============",?26,"============",?40,"============",?54,"============",?68,"============"
For {
&SQL(FETCH cur3)
Quit:(SQLCODE'=0)
If tMsgBody="" {
Set tTotalHdrCount = tTotalHdrCount + tHdrCount
Write:pVerbose !,"No Message Body"
Write:pVerbose !?12,##class(Ens.Util.FunctionSet).Pad($FN(tHdrCount,","),-12),!
Continue
}
Set $List(pMsgBodies(tMsgBody),1,2)=$ListBuild(tMinMessageBodyId,tTimeCreated)
Write:pVerbose !,tMsgBody
Set tSC1 = ..GetSQLTableName(tMsgBody,.tSQLTableName,.tSuperClass)
If 'tSC1 {
Set tSC = $$$ADDSC(tSC,tSC1)
Continue
}
Set $List(pMsgBodies(tMsgBody),3)=tSQLTableName
Set $List(pMsgBodies(tMsgBody),10)=tSuperClass
//If it Extends %Persistent first, don't bother showing all the other classes - it will have its own storage
Write:pVerbose !,?3,"Extends: ",$S($P(tSuperClass,",")="%Library.Persistent":"%Library.Persistent",1:tSuperClass)
Write:pVerbose !,?3,"SQL Table Name: ",tSQLTableName
Write:pVerbose !,?12,##class(Ens.Util.FunctionSet).Pad($FN(tHdrCount,","),-12)
Write:pVerbose ?26,##class(Ens.Util.FunctionSet).Pad($FN(tUniqueMsgBodies,","),-12)
Write:pVerbose ?40,##class(Ens.Util.FunctionSet).Pad(tMinMessageBodyId,-12)
Set tSC1 = ..GetCountMinIdMaxIdFromSQLTable(tSQLTableName,.tTblCount,.tMinTblId)
If 'tSC1 {
Set tSC = $$$ADDSC(tSC,tSC1)
Continue
}
Set $List(pMsgBodies(tMsgBody),4)=tTblCount
Set $List(pMsgBodies(tMsgBody),5)=tMinTblId
Set tTotalHdrCount = tTotalHdrCount + tHdrCount
Set tTotalHdrUnique = tTotalHdrUnique + tUniqueMsgBodies
Set tTotalTblCount = tTotalTblCount + tTblCount
Write:pVerbose ?54,##class(Ens.Util.FunctionSet).Pad($FN(tTblCount,","),-12)
Write:pVerbose ?68,##class(Ens.Util.FunctionSet).Pad(tMinTblId,-12),!
}
Write:pVerbose !?12,"============",?26,"============",?54,"============"
Write:pVerbose !,"TOTALS",?12,##class(Ens.Util.FunctionSet).Pad($FN(tTotalHdrCount,","),-12),?26,##class(Ens.Util.FunctionSet).Pad($FN(tTotalHdrUnique,","),-12),?54,##class(Ens.Util.FunctionSet).Pad($FN(tTotalTblCount,","),-12),!
&SQL(CLOSE cur3)
Set tMsgBody=""
For {
Set tMsgBody = $Order(pMsgBodies(tMsgBody)) Quit:tMsgBody=""
Set tSC1 = ..GetGlobalsByClassName(.tMsgBody,.tListOfGlobals)
If 'tSC1 Set tSC = $$$ADDSC(tSC,tSC1)
Set $LIST(pMsgBodies(tMsgBody),6)=tListOfGlobals
If pCheckGlobalSizes {
Set tSC1 = ..GetTotalGlobalSizes(tListOfGlobals,.tTotal,,pVerbose,tMsgBody,$ListGet(pMsgBodies(tMsgBody),4))
If 'tSC1 Set tSC = $$$ADDSC(tSC,tSC1) //Some Globals may not be found resulting in an ERROR
Set $LIST(pMsgBodies(tMsgBody),7)=tTotal
}
}
Quit tSC
]]></Implementation>
</Method>
<Method name="DeleteMsgBodiesUpToId">
<Description><![CDATA[
If pMsgBodies is empty, deletes persistent objects (MessageBodyClassName) found in Ens.MessageHeader with an Id (MessageBodyId) less than the minimum MessageBodyId stored in the Ens.MessageHeader table.
Otherwise, this method will delete objects less than the Id specified: pMsgBodies(ClassName)=$ListBuild(StopAtId).
Orphaned message bodies arise mostly due to purging without including Message Bodies.
To be asked whether to turn journaling off, do not pass a value for pNoJrn and set pVerbose=1.<br><br>
If $D(pMsgBodies)<10 MessageBodyReport() is called to build array
<br><br>Do ##(zEnsSupport.Msgs).DeleteMsgBodiesUpToId(.tMsgBodies,1)]]></Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>*pMsgBodies,pVerbose:%Boolean=0,pShowDetail:%Boolean=0,pNoJrn:%Boolean,pDelete:%Boolean=1,pCheckGlobalSizes:%Boolean=1</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tSC=$$$OK
If ($Data(pMsgBodies)<10) {
Write:pVerbose !,"Gathering data..."
Set tSC1 = ..MessageBodyReport(.pMsgBodies,0,0)
//Expect errors because some Globals are defined but not yet used
//ERROR #308: Global EnsLib.H.MessageS not found.
//If 'tSC1 Set tSC = $$$ADDSC(tSC,tSC1) Quit tSC
}
If pDelete {
Set tJournalingWasOn = $$CURRENT^%NOJRN()
Set pNoJrn=$G(pNoJrn)
If pVerbose {
Write !
Set tMsgBody=""
For {
Set tMsgBody = $Order(pMsgBodies(tMsgBody)) Quit:tMsgBody=""
Set tStopAtId = +$ListGet(pMsgBodies(tMsgBody),1) Continue:'tStopAtId
Write !,"Delete all ",tMsgBody," where Id < ",tStopAtId
}
Read !,"Delete message bodies? <No> ",tYN
Quit:'..YES(tYN) $$$ERROR(5001,"Delete then No Delete - Nothing Deleted!")
Read:(pNoJrn="") !,"Turn off Journaling? <No> ",tYN //Vague, must ask specifically Yes/No
Set:..YES(tYN) pNoJrn=1
}
If pNoJrn {
Do DISABLE^%NOJRN
}
Else {
Do ENABLE^%NOJRN
}
}
Set tMsgBody="",tTotalCount=0,tGrandTotalIn=0,tGrandTotalOut=0
For {
Set tMsgBody = $Order(pMsgBodies(tMsgBody)) Quit:tMsgBody=""
Set tStopAtId = +$ListGet(pMsgBodies(tMsgBody),1) Continue:'tStopAtId
Set tSC1 = ..GetSQLTableName(tMsgBody,.tSQLName)
If 'tSC1 {
Do:pVerbose $System.OBJ.DisplayError(tSC1)
Set tSC = $$$ADDSC(tSC,tSC1)
Continue
}
Set tSQL = "SELECT ID FROM "_tSQLName_" WHERE ID < "_tStopAtId
Set tStatement = ##class(%SQL.Statement).%New()
Set tSC1 = tStatement.%Prepare(tSQL)
If 'tSC1 {
Do:pVerbose $System.OBJ.DisplayError(tSC1)
Set tSC = $$$ADDSC(tSC,tSC1)
Continue
}
Set tRS = tStatement.%Execute()
Set (tCount,tUsedIn,tAlloc)=0
//Set the size of the Globals before deleting
If pCheckGlobalSizes&&pDelete {
Set tTotalIn=0
Set tListOfGlobals = $ListGet(pMsgBodies(tMsgBody),6)
If tListOfGlobals="" {
Set tSC1 = ..GetGlobalsByClassName(.tMsgBody,.tListOfGlobals)
If 'tSC1 {
Do:pVerbose $System.OBJ.DisplayError(tSC1)
Set tSC = $$$ADDSC(tSC,tSC1)
Continue
}
Else {
Set $List(pMsgBodies(tMsgBody),6)=tListOfGlobals
}
}
Set tSC1 = ..GetTotalGlobalSizes(tListOfGlobals,.tTotalIn)
If tSC1 {
Set $LIST(pMsgBodies(tMsgBody),7) = tTotalIn
Set tGrandTotalIn = tGrandTotalIn + tTotalIn
}
Else {
//Expect errors because some Globals are defined but not yet used
//ERROR #308: Global EnsLib.H.MessageS not found.
//Set tSC = $$$ADDSC(tSC,tSC1) Quit tSC
}
}
While (tRS.%Next()) {
Set tSC1=$$$OK
Set:pDelete tSC1=$CLASSMETHOD(tMsgBody,"%DeleteId",tRS.ID)
If tSC1 {
Set tCount = tCount + 1
If pVerbose&&pShowDetail {
Write !?2
Write:'pDelete "Found "
Write:pDelete "Deleted "
Write tMsgBody," with ID ",tRS.ID
}
} Else {
Do:pVerbose $System.OBJ.DisplayError(tSC1)
Set tSC = $$$ADDSC(tSC,tSC1)
}
}
Set $List(pMsgBodies(tMsgBody),8)=tCount
Set tTotalCount = tTotalCount + tCount
//Check the size of the Global after deleting
If pCheckGlobalSizes&&pDelete {
Set tTotalOut=0
Set tSC1 = ..GetTotalGlobalSizes(tListOfGlobals,.tTotalOut)
If tSC1 {
Set $LIST(pMsgBodies(tMsgBody),9) = tTotalOut
Set tGrandTotalOut = tGrandTotalOut + tTotalOut
}
Else {
Do:pVerbose $System.OBJ.DisplayError(tSC1)
Set tSC = $$$ADDSC(tSC,tSC1)
}
}
If pVerbose {
Write !
Write:'pDelete "Found "
Write:pDelete "Deleted "
Write tCount," msg bodies of type ",tMsgBody
Write:pDelete&&pCheckGlobalSizes " (",tTotalIn-tTotalOut," MB)"
}
}
If pVerbose {
Write !!
Write:'pDelete "Found "
Write:pDelete "Deleted "
Write tTotalCount," TOTAL Message Bodies"
Write:pDelete&&pCheckGlobalSizes " (",tGrandTotalIn-tGrandTotalOut," MB)"
Write !
}
If pDelete Do:tJournalingWasOn ENABLE^%NOJRN
Quit tSC
]]></Implementation>
</Method>
<Method name="DeleteHL7MsgsNotRefByMsgHeader">
<Description>
Deletes all EnsLib.HL7.Messages with an Id less than the minimum MessageBodyId stored in the Ens.MessageHeader table.
This situation arises mostly due to purging without including Message Bodies. </Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>*pCount,pVerbose:%Boolean=0,pDelete:%Boolean=1,*pMsgBodies,pCheckGlobalSizes:%Boolean=1</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tSC=$$$OK,pCount=0
&SQL(SELECT MIN(MessageBodyId), TimeCreated INTO :tMsgId, :tTimeCreated
FROM Ens.MessageHeader
WHERE MessageBodyClassName ='EnsLib.HL7.Message')
Quit:(SQLCODE'=0) $$$ERROR(5001,"SQLCODE: "_SQLCODE)
Set $List(pMsgBodies("EnsLib.HL7.Message"),1,2)=$ListBuild(tMsgId,tTimeCreated)
Set tSC = ..DeleteMsgBodiesUpToId(.pMsgBodies,pVerbose,0,,pDelete,pCheckGlobalSizes)
Set pCount = +$ListGet(pMsgBodies("EnsLib.HL7.Message"),8)
Quit tSC
]]></Implementation>
</Method>
<Method name="DeleteEnsResponseNotRefByMsgHeader">
<Description>
Deletes all Ens.Response messages with an Id less than the minimum MessageBodyId stored in the Ens.MessageHeader table.
Orphaned Ens.Response messages can happen for many reasons, but oftentimes happens when a BPL is configured with Ens.Response
as the response (default) but called Async. </Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>*pCount,pVerbose:%Boolean=0,pDelete:%Boolean=1,*pMsgBodies,pCheckGlobalSizes:%Boolean=1</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tSC=$$$OK, pCount=0
&SQL(SELECT MIN(MessageBodyId), TimeCreated INTO :tMsgId, :tTimeCreated
FROM Ens.MessageHeader
WHERE MessageBodyClassName ='Ens.Response')
Quit:(SQLCODE'=0) $$$ERROR(5001,"SQLCODE: "_SQLCODE_" returned trying to SELECT from Ens.Response")
Set $List(tMsgBodies("Ens.Response"),1,2)=$ListBuild(tMsgId,tTimeCreated)
Set tSC = ..DeleteMsgBodiesUpToId(.tMsgBodies,pVerbose,0,,pDelete,pCheckGlobalSizes)
Set pCount = +$ListGet(tMsgBodies("Ens.Response"),8)
Quit tSC
]]></Implementation>
</Method>
<Method name="BasicHL7GlobalInfo">
<Description>
HL7 related Globals and their size in MB</Description>
<ClassMethod>1</ClassMethod>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tSC=$$$OK
&SQL(SELECT COUNT(ID) INTO :tCount
FROM EnsLib_HL7.Message)
Quit:(SQLCODE'=0) $$$ERROR(5001,"SQLCODE: "_SQLCODE_" returned trying to find COUNT() of HL7 Messages.")
Set tGlobalList = $ListFromString("^Ens.MessageHeaderD,^Ens.MessageHeaderI,^Ens.Rule.LogD,^EnsHL7.Segment,^EnsLib.H.MessageD,^EnsLib.H.MessageI,^EnsLib.H.MessageS,^EnsLib.HL7.SearchTableD,^EnsLib.HL7.SearchTableI",",")
Set tSC=..GetTotalGlobalSizes(tGlobalList,,,1,"HL7 Related Globals",tCount)
Write !,$FN(tCount,",")," Unique HL7 Messages",!
Quit tSC
]]></Implementation>
</Method>
<Method name="GetSQLTableName">
<ClassMethod>1</ClassMethod>
<FormalSpec>pClassName:%String="",*pTableName:%String,*pSuper:%String</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tSC = $$$OK
If pClassName'="" {
&SQL(SELECT SqlQualifiedNameQ, Super INTO :pTableName, :pSuper
FROM %Dictionary.CompiledClass
WHERE ID = :pClassName)
Set:SQLCODE'=0 tSC = $$$ERROR(5001,"SQLCODE: "_SQLCODE_" returned querying %Dictionary.CompiledClass for "_tMsgBody)
}
Else {
Set tSC = $$$ERROR(5001,"ClassName NULL calling GetSQLTableName")
}
Quit tSC
]]></Implementation>
</Method>
<Method name="GetCountMinIdMaxIdFromSQLTable">
<ClassMethod>1</ClassMethod>
<FormalSpec>pSQLTable:%String="",*pCount:%Integer="",*pMinId="",*pMaxId</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tSC = $$$OK, pCount=0
If pSQLTable'="" {
Set tSQL = "SELECT COUNT(ID) AS MsgCount, MIN(ID) AS MinId, MAX(ID) AS MaxId FROM "_pSQLTable
Set tStatement = ##class(%SQL.Statement).%New()
Set tSC = tStatement.%Prepare(tSQL)
Quit:'tSC tSC
Set tRS = tStatement.%Execute()
If tRS.%Next() {
Set pCount = tRS.MsgCount
Set pMinId = tRS.MinId
Set pMaxId = tRS.MaxId
}
}
Else {
Set tSC = $$$ERROR(5001,"pSQLTable NULL calling GetCountMinIdMaxIdFromSQLTable")
}
Quit tSC
]]></Implementation>
</Method>
<Method name="GetGlobalsByClassName">
<ClassMethod>1</ClassMethod>
<FormalSpec>pClassName:%String="",*pListOfGlobals</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tSC=$$$OK
If pClassName = "" Quit $$$ERROR(5001,"Invalid ClassName passed to GetGlobalsByClassName")
&SQL(SELECT DataLocation,IndexLocation,StreamLocation
INTO :tDataLocation,:tIndexLocation,:tStreamLocation
FROM %Dictionary.CompiledStorage
WHERE Parent = :pClassName)
Quit:SQLCODE'=0 $$$ERROR(5001,"SQLCODE: "_SQLCODE_" returned querying %Dictionary.CompiledStorage for "_pClassName)
Set pListOfGlobals=""
For tI = tDataLocation,tIndexLocation,tStreamLocation Set:tI'="" $List(pListOfGlobals,$ListLength(pListOfGlobals)+1)=tI
//Special consideration for certain well-known message bodies
If pClassName = "EnsLib.HL7.Message" {
For tI="^EnsHL7.Segment","^EnsLib.HL7.SearchTableD","^EnsLib.HL7.SearchTableI" Set:tI'="" $List(pListOfGlobals,$ListLength(pListOfGlobals)+1)=tI
}
Quit tSC
]]></Implementation>
</Method>
<Method name="GetTotalGlobalSizes">
<ClassMethod>1</ClassMethod>
<FormalSpec>pListOfGlobals,*pTotalUsed,*pTotalAlloc,pVerbose:%Boolean=0,pHeader:%String="Global",pMsgCount:%Integer=""</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tSC=$$$OK, (pTotalUsed,pTotalAlloc)=0
Write:pVerbose !,$E(pHeader,1,50),?52," Used Storage",?67,"Alloc Storage"
Write:pVerbose !,"==================================================",?52,"=============",?67,"============="
For tI=1:1:$ListLength(pListOfGlobals) {
Set (tUsed,tAlloc)=0
Set tGlobal = $ListGet(pListOfGlobals,tI)
If tGlobal'="" {
Set tSC1 = ##class(%GlobalEdit).GetGlobalSize($zu(12,""),tGlobal,.tAlloc,.tUsed)
If tSC1 {
Set pTotalUsed = pTotalUsed + tUsed
Set pTotalAlloc = pTotalAlloc + tAlloc
Write:pVerbose !,tGlobal
Write:+pMsgCount&&pVerbose " (",$FN((tUsed/pMsgCount)*100000,",",1)," per 100K)"
Write:pVerbose ?52,##class(Ens.Util.FunctionSet).Pad($FN(tUsed,",",1),-13)
Write:pVerbose ?67,##class(Ens.Util.FunctionSet).Pad($FN(tAlloc,",",1),-13)
}
Else {
//Set tSC=$$$ADDSC(tSC,tSC1)
//Very common to have globals defined that are not yet used.
}
}
}
Write:pVerbose !," TOTAL: "
Write:pVerbose ?52,##class(Ens.Util.FunctionSet).Pad($FN(pTotalUsed,",",1),-13)
Write:pVerbose ?67,##class(Ens.Util.FunctionSet).Pad($FN(pTotalAlloc,",",1),-13),!
Quit tSC
]]></Implementation>
</Method>
<Method name="QuickCheckForMinIds">
<ClassMethod>1</ClassMethod>
<FormalSpec>*pMsgBodies,pMsgBody:%String</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tSC=$$$OK
&SQL(SELECT TOP 1 MessageBodyId, TimeCreated INTO :tMinMessageBodyId,:tTimeCreated FROM Ens.MessageHeader WHERE MessageBodyClassName = :pMsgBody)
Set tSC = ..GetSQLTableName(pMsgBody,.tSQLTableName,.tSuperClass)
Quit:'tSC tSC
Set $List(pMsgBodies(pMsgBody),1,3)=$ListBuild(tMinMessageBodyId,tTimeCreated,tSQLTableName)
Set $List(pMsgBodies(pMsgBody),10)=tSuperClass
Set tSQL = "SELECT Top 1 ID FROM "_tSQLTableName
Set tStatement = ##class(%SQL.Statement).%New()
Set tSC = tStatement.%Prepare(tSQL)
Quit:'tSC tSC
Set tRS = tStatement.%Execute()
If tRS.%Next() {
Set $LIST(pMsgBodies(pMsgBody),5)=tRS.ID //tMinTblId
}
Else {
Set tSC = $$$ERROR(5001,"Failed to find Top 1 ID in SQL Table "_tSQLTableName)
}
Quit tSC
]]></Implementation>
</Method>
<Method name="QuickMessageBodyReport">
<ClassMethod>1</ClassMethod>
<FormalSpec>*pMsgBodies,pVerbose:%Boolean=0</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tSC=$$$OK,tTotalHdrCount=0,tTotalHdrUnique=0,tTotalTblCount=0
&SQL(DECLARE cur5 CURSOR FOR
SELECT %Exact(MessageBodyClassName)
INTO :tMsgBody
FROM Ens.MessageHeader
GROUP BY MessageBodyClassName)
&SQL(OPEN cur5)
Write:pVerbose !,"Class Name",?54," MinHdrBdyId",?68," MinMsgBdyId"
Write:pVerbose !,"====================================================",?54,"============",?68,"============"
For {
&SQL(FETCH cur5)
Quit:(SQLCODE'=0)
Continue:tMsgBody=""
Set tSC1 = ..QuickCheckForMinIds(.pMsgBodies,tMsgBody)
If 'tSC1 {
Set tSC = $$$ADDSC(tSC,tSC1)
Continue
}
Write:pVerbose !,tMsgBody
Write:pVerbose !,?3,"Extends: ",$S($P($ListGet(pMsgBodies(tMsgBody),10),",")="%Library.Persistent":"%Library.Persistent",1:$ListGet(pMsgBodies(tMsgBody),10))
Write:pVerbose ?54,##class(Ens.Util.FunctionSet).Pad($ListGet(pMsgBodies(tMsgBody),1),-12),?68,##class(Ens.Util.FunctionSet).Pad($ListGet(pMsgBodies(tMsgBody),5),-12),!
}
&SQL(CLOSE cur5)
Quit tSC
]]></Implementation>
</Method>
<Method name="FindHL7SegMismatch">
<ClassMethod>1</ClassMethod>
<FormalSpec>pVerbose:%Boolean=0,pFix:%Boolean=0</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tSC=$$$OK
Set tId=""
If pFix {
Read !,"Fix HL7 Segment Mismatches? <No> ",tYN
Quit:'..YES(tYN) $$$ERROR(5001,"Selected option to Fix HL7 Segment Mismatches, but answered 'No' to confirm.")
}
For { Set tId=$O(^EnsLib.H.MessageD(tId)) Q:tId=""
Set segcount=+$G(^EnsLib.H.MessageD(tId,"segs"))
For tI=1:1:segcount {
Continue:$G(^EnsLib.H.MessageD(tId,"segs",tI))'=""
If 'pFix {
Write:pVerbose !,"Found mismatch at ^EnsLib.H.MessageD(",tId,")"
Quit
}
Set nextId = $O(^EnsLib.H.MessageD(tId,"segs",tI))
If nextId'="" {
Write:pVerbose !,"Setting ^EnsLib.H.MessageD(",tId,",""segs"",",tI,")=^EnsLib.H.MessageD(",tId,",""segs"",",nextId,")"
Set ^EnsLib.H.MessageD(tId,"segs",tI)=^EnsLib.H.MessageD(tId,"segs",nextId)
Write:pVerbose !,"Killing ^EnsLib.H.MessageD(",tId,",""segs"",",nextId,")"
Kill ^EnsLib.H.MessageD(tId,"segs",nextId)
}
Else {
Write:pVerbose !,"Setting ^EnsLib.H.MessageD(",tId,",""segs"")=",tI-1
Set ^EnsLib.H.MessageD(tId,"segs")=tI-1
Quit
}
}
}
Quit tSC
]]></Implementation>
</Method>
<Method name="YES">
<ClassMethod>1</ClassMethod>
<FormalSpec>pYN:%String=""</FormalSpec>
<ReturnType>%Boolean</ReturnType>
<Implementation><![CDATA[ Quit ("Y"=$E($TR($ZStrip(pYN,"<>W"),"y","Y")))
]]></Implementation>
</Method>
<Method name="QUIT">
<ClassMethod>1</ClassMethod>
<FormalSpec>pQuit:%String=""</FormalSpec>
<ReturnType>%Boolean</ReturnType>
<Implementation><![CDATA[ Quit ("QUIT"=$TR($ZStrip(pQuit,"<>W"),"quit","QUIT"))||("EXIT"=$TR($ZStrip(pQuit,"<>W"),"exit","EXIT"))||($ZStrip(pQuit,"<>W")="")
]]></Implementation>
</Method>
</Class>
</Export>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment