Home   Package List   Routine Alphabetical List   Global Alphabetical List   FileMan Files List   FileMan Sub-Files List   Package Component Lists   Package-Namespace Mapping  
Routine: HLTP3

HLTP3.m

Go to the documentation of this file.
  1. HLTP3 ;SFIRMFO/RSD - Transaction Processor for TCP ;07/29/2009 14:51
  1. ;;1.6;HEALTH LEVEL SEVEN;**19,43,57,58,59,66,69,109,115,108,116,117,125,120,133,122,140,142,145**;Oct 13, 1995;Build 4
  1. ;Per VHA Directive 2004-038, this routine should not be modified.
  1. ;
  1. Q
  1. NEW(X) ;process new msg. ien in 773^ien in 772
  1. ;HLMTIENS=ien in #773; HLMTIEN=ien in #772
  1. ;HLHDRO=original header; HLHDR=response header
  1. ;set error trap
  1. N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLTP3"
  1. N HL,HLEID,HLEIDS,HLERR,HLHDR,HLHDRO,HLMTIEN,HLMTIENS,HLJ,HLMSA,HLQUIT,HLNODE,HLNEXT,HLRESLTA,HLDONE1,HLASTRSP,HLRESLT
  1. S HLRESLT=""
  1. D INIT^HLTP3A
  1. ;error with header, return commit/app reject
  1. I $G(HLRESLT) D Q
  1. . ;set status & unlock record
  1. . D STATUS^HLTF0(HLMTIENS,4,,,1),EXIT
  1. . ;quit if no commit or app ack
  1. . I $G(HL("ACAT"))="NE",$G(HL("APAT"))="NE" Q
  1. . S X=$S($G(HL("ACAT"))="AL":"CR",1:"AR")
  1. . ;HLTCP=ien of acknowledgment msg. from ACK^HLTP4
  1. . D ACK^HLTP4(X,$P(HLRESLT,U,2)) Q:'$G(HLTCP)
  1. . ;write ack back
  1. . S X=$$WRITE^HLCSTCP2(HLTCP)
  1. . ;update counter to sent
  1. . D LLCNT^HLCSTCP(HLDP,4)
  1. . ;update status of ack
  1. . D STATUS^HLTF0(HLTCP,3,,,1)
  1. ;
  1. ;check for duplicate msg., use rec. app and msg. id x-ref
  1. ; patch HL*1.6*142 start
  1. ; HL("HDR FLDS:3-6") extracted from field 3 to field 6 of header
  1. ; defined in HLDIE routine
  1. ; I $G(HL("MID"))]"",$G(HL("RAP")) S X=$O(^HLMA("AH",HL("RAP"),HL("MID"),0)) D Q:'$D(HLMTIENS)
  1. I ($G(HL("MID"))]""),($G(HL("HDR FLDS:3-6"))]"") D Q:'$D(HLMTIENS)
  1. . S X=$O(^HLMA("AH-NEW",HL("HDR FLDS:3-6"),HL("MID"),0))
  1. . ; patch HL*1.6*142 end
  1. . ;HLASTMSG=last ien received during this connection
  1. . ;if no duplicate, save msg. ien and quit
  1. . I X=HLMTIENS!'X S HLASTMSG=HLMTIENS Q
  1. . N MSH,OIENS
  1. . S (OIENS,Y)=X D S Y=HLMTIENS D
  1. .. ;combine MSH into single string
  1. .. S MSH(Y)="",I=0 F S I=$O(^HLMA(Y,"MSH",I)) Q:'I S MSH(Y)=MSH(Y)_$G(^(I,0))
  1. .; patch 117 & 125, check if identical
  1. .I MSH(HLMTIENS)'=MSH(OIENS) S HLASTMSG=HLMTIENS Q
  1. .;
  1. . ;msg is duplicate, set status
  1. . D STATUS^HLTF0(HLMTIENS,4,109,"Duplicate with ien "_OIENS,1),EXIT
  1. . ;msg was resent, ignore it.
  1. . I HLASTMSG=HLMTIENS K HLMTIENS Q
  1. . ;find original response and send back
  1. . S HLASTRSP=$O(^HLMA("AF",OIENS,OIENS))
  1. . ; patch HL*1.6*142 start
  1. . ; the original msg may need to be updated again if 1st time
  1. . ; update failed
  1. . S HLASTMSG("OIENS")=OIENS
  1. . ;
  1. . ; the original message and its commit ACK were purged, OIENS is
  1. . ; duplicate and needs to create its own commit ACK (happened
  1. . ; between MPI and VIE in 9/2008), the OIENS will be processed
  1. . ; by the application routine again.
  1. . I $G(HL("ACAT"))="AL",'$G(HL("ACK")),'HLASTRSP D
  1. .. N HLTCP,HLMTIENS
  1. .. S HLMTIENS=OIENS
  1. .. D ACK^HLTP4("CA")
  1. .. D LLCNT^HLCSTCP(HLDP,3,1) ; decreament and will be added later
  1. .. S HLASTRSP=HLTCP
  1. . ; patch HL*1.6*142 end
  1. ;
  1. ; patch HL*1.6*145 start
  1. ; Quit if this is application ack to application ack
  1. I $G(HL("ACK")) D Q
  1. . N HLERRMG,X
  1. . S HLERRMG="Received application acknowledgement to an application acknowledgement"
  1. . ;msg is a resend, HLASTRSP=ien of original response (commit ACK)
  1. . I $G(HLASTRSP) D
  1. .. S HLTCP=HLASTRSP
  1. .. D STATUS^HLTF0(HLTCP,8)
  1. .. S ^HLMA(+HLTCP,"S")=$$NOW^XLFDT
  1. .. D LLCNT^HLCSTCP(HLDP,3)
  1. . E D Q:'$G(HLTCP)
  1. .. ;Send CR and update status of original and current ack messages
  1. .. D ACK^HLTP4("CR",HLERRMG)
  1. . ;
  1. . ; write commit ACK (original commit ACK)
  1. . S X=$$WRITE^HLCSTCP2(HLTCP)
  1. . D STATUS^HLTF0(HLTCP,3,,"'Reject' commit ACK: "_HLERRMG,1)
  1. . S ^HLMA(+HLTCP,"S")=$$NOW^XLFDT
  1. . D LLCNT^HLCSTCP(HLDP,4)
  1. . S HLTCP=""
  1. . ; D STATUS^HLTF0(HL("MTIENS"),3,,,1),STATUS^HLTF0(HLMTIENS,3,,,1)
  1. . D STATUS^HLTF0(HL("MTIENS"),3,,,1)
  1. . D STATUS^HLTF0(HLMTIENS,4,,HLERRMG,1)
  1. . ;unlock record
  1. . D EXIT
  1. ; patch HL*1.6*145 end
  1. ;
  1. ; enhance ack., send commit, quit if not an ack, msg will be
  1. ; processed by filer
  1. I $G(HL("ACAT"))="AL" D Q:'$G(HL("MTIENS"))
  1. . ;msg is a resend, HLASTRSP=ien of original response (commit ACK)
  1. .I $G(HLASTRSP) D
  1. ..S HLTCP=HLASTRSP
  1. ..D LLCNT^HLCSTCP(HLDP,3)
  1. . E D Q:'$G(HLTCP)
  1. ..D ACK^HLTP4("CA") ;**109** LLCNT^HLCSTCP(HLDP,3) called in ACK^HLTP4
  1. . ;
  1. . ; write commit ACK (original commit ACK)
  1. . S X=$$WRITE^HLCSTCP2(HLTCP)
  1. . ; patch HL*1.6*142
  1. . ; D LLCNT^HLCSTCP(HLDP,4),STATUS^HLTF0(HLTCP,3,,,1):'$G(HLASTRSP)
  1. . D LLCNT^HLCSTCP(HLDP,4)
  1. . I '$G(HLASTRSP) D
  1. .. D STATUS^HLTF0(HLTCP,3,,,1)
  1. . S HLTCP=""
  1. . ;if not an ack, set status to awaiting processing **109** and put on in queue
  1. . I '$G(HL("MTIENS")),'$G(HLASTRSP) D STATUS^HLTF0(HLMTIENS,9),EXIT,SETINQUE^HLTP31
  1. . ;
  1. . ; patch HL*1.6*142 start
  1. . ;if the original msg failed to en-queue and update status
  1. . ; it may happen when COTS disconnect the listener during
  1. . ; writing the commit ACK
  1. . ; deal with a non-application ACK duplicate message
  1. . I '$G(HL("MTIENS")),$G(HLASTRSP) D
  1. .. N STATUS
  1. .. S STATUS=+$G(^HLMA(HLASTRSP,"P"))
  1. .. I STATUS,(STATUS'=3) D
  1. ... ; update the original messsage, ien=HLASTMSG("OIENS")
  1. ... D STATUS^HLTF0(HLASTMSG("OIENS"),9)
  1. ... D EXIT
  1. ... N HLMTIENS
  1. ... S HLMTIENS=HLASTMSG("OIENS")
  1. ... D SETINQUE^HLTP31
  1. ... D STATUS^HLTF0(HLASTRSP,3,,,1)
  1. . ; patch HL*1.6*142 end
  1. ;
  1. ;enhance ack., no commit & no app ack
  1. I $G(HL("ACAT"))="NE",$G(HL("APAT"))="NE" D Q
  1. . ;set status to awaiting processing, **109** and put on in queue
  1. . I '$G(HLASTRSP) D STATUS^HLTF0(HLMTIENS,9),EXIT,SETINQUE^HLTP31
  1. ;
  1. ; patch HL*1.6*120 start
  1. ;resending old response, msg is a resend
  1. ; do not re-send duplicate when $G(HL("ACAT"))="AL"
  1. ; the following resend is for original mode application ACK
  1. I $G(HLASTRSP),$G(HL("ACAT"))'="AL" S HLTCP=HLASTRSP G ACK
  1. ; patch HL*1.6*120 end
  1. ;
  1. ; patch HL*1.6*142 start
  1. ; to handle duplicate when the original message encountered
  1. ; a write error of commit ACK
  1. ; quit if duplicate
  1. ; Q:$G(HLASTRSP)
  1. S HLASTRSP("FLAG")=0
  1. I $G(HLASTRSP),$G(HL("ACAT"))="AL" D
  1. . I +$G(^HLMA(+$G(HLASTRSP),"P")),(+$P($G(^HLMA(+$G(HLASTRSP),"P")),"^")'=3) D
  1. .. S HLASTRSP("FLAG")=1
  1. ; don't quit if this is duplicate application ACK msg with accept
  1. ; ACK type="AL", and its original commit ACK is not done.
  1. I $G(HLASTRSP),('HLASTRSP("FLAG")) Q
  1. ;
  1. ; if duplicate, change ien to orginal msg ien
  1. I $G(HLASTRSP) D
  1. . S HLMTIENS=+$G(HLASTMSG("OIENS"))
  1. . S HLMTIEN=+$G(^HLMA(HLMTIENS,0))
  1. ; patch HL*1.6*142 end
  1. ;
  1. CONT ;continue processing an enhance ack msg. called from DEFACK
  1. ;Set special HL variables for processing rtn
  1. S HLQUIT=0,HLNODE="",HLNEXT="D HLNEXT^HLCSUTL"
  1. ;
  1. ; message is an acknowledgement, HLMSA=ack code^id^text
  1. I ($G(HLMSA)]"") D Q
  1. . ;X=1 if ack ok, 0=reject of error
  1. . S X=$E(HLMSA,2)="A"
  1. . ;Update status of original message and remove it from the queue
  1. . D STATUS^HLTF0(HL("MTIENS"),$S(X:3,1:4),"",$S(X:"",1:$P(HLMSA,HL("FS"),3)),1)
  1. . ; patch HL*1.6*142
  1. . ; time: original message receives the application ACK
  1. . S $P(^HLMA(HL("MTIENS"),"S"),"^",5)=$$NOW^XLFDT
  1. . D DEQUE^HLCSREP($P($G(^HLMA(HL("MTIENS"),0)),"^",7),"O",HL("MTIENS"))
  1. . D
  1. .. N HLTCP ;variable to update status in file #772.
  1. ..;
  1. ..;**108**
  1. .. N TEMP
  1. .. S TEMP=HLMTIENS
  1. .. N HLMTIENS
  1. .. S HLMTIENS=TEMP
  1. ..;**END 108**
  1. ..;
  1. .. ; patch HL*1.6*142 start
  1. .. ; time: starts to process the incoming message
  1. .. S $P(^HLMA(HLMTIENS,"S"),"^",6)=$$NOW^XLFDT
  1. .. D PROCACK^HLTP2(HLMTIEN,HL("EID"),.HLRESLT,.HL)
  1. .. ; time: ends processing the incoming message
  1. .. S $P(^HLMA(HLMTIENS,"S"),"^",7)=$$NOW^XLFDT
  1. . ; if duplicate, and the original msg failed to
  1. . ; complete the processing
  1. . I $G(HLASTRSP) D STATUS^HLTF0(HLASTRSP,3,,,1)
  1. . ; patch HL*1.6*142 end
  1. . ;update status of incoming & unlock
  1. . D STATUS^HLTF0(HLMTIENS,$S($G(HLRESLT):4,1:3),$S($G(HLRESLT):+$G(HLRESLT),1:""),$S($G(HLRESLT):$P(HLRESLT,U,2),1:""),1),EXIT
  1. ;
  1. ;get entry action, exit action and processing routine
  1. K HLHDR,HLLD0,HLLD1,HLMSA
  1. I HL("EIDS")="",$G(HLEIDS)]"" S HL("EIDS")=HLEIDS ;**CIRN**
  1. D EVENT^HLUTIL1(HL("EIDS"),"15,20,771",.HLN)
  1. S HLENROU=$G(HLN(20)),HLEXROU=$G(HLN(15)),HLPROU=$G(HLN(771))
  1. ;quit if no processing routine,update status and quit
  1. I HLPROU']"" S HLRESLT="10^"_$G(^HL(771.7,10,0)) D STATUS^HLTF0(HLMTIENS,3,,,1),EXIT Q
  1. ;HLORNOD=subscriber protocol for Fileman auditing, ien;global ref
  1. N HLORNODD S HLORNOD=HL("EIDS")_";ORD(101,"
  1. ;Execute entry action of client protocol
  1. X:HLENROU]"" HLENROU K HLENROU,HLDONE1
  1. ;
  1. ; patch HL*1.6*142 start
  1. ; time: starts to process the incoming message
  1. S $P(^HLMA(HLMTIENS,"S"),"^",6)=$$NOW^XLFDT
  1. ;Execute processing routine
  1. X HLPROU S HLRESLT=0 S:($D(HLERR)) HLRESLT="9^"_HLERR
  1. ; time: ends processing the incoming message
  1. S $P(^HLMA(HLMTIENS,"S"),"^",7)=$$NOW^XLFDT
  1. ; if duplicate, and the original msg failed to
  1. ; complete the processing
  1. I $G(HLASTRSP) D STATUS^HLTF0(HLASTRSP,3,,,1)
  1. ; patch HL*1.6*142 end
  1. ;update status of incoming to complete & unlock
  1. D STATUS^HLTF0(HLMTIENS,$S(HLRESLT:4,1:3),$S(HLRESLT:+HLRESLT,1:""),$S(HLRESLT:$P(HLRESLT,U,2),1:""),1,$S($G(HLERR("SKIP_EVENT"))=1:1,1:0)),EXIT
  1. ;HLTCPO=link open, HLTCP=ien of ack msg. from GENACK
  1. ACK I $G(HLTCPO),$G(HLTCP) D Q
  1. . D LLCNT^HLCSTCP(HLDP,3)
  1. . ;write ack back over open tcp link
  1. . S X=$$WRITE^HLCSTCP2(HLTCP)
  1. . ;update status of ack to complete
  1. . D:'$G(HLASTRSP) STATUS^HLTF0(HLTCP,3,,,1)
  1. . D LLCNT^HLCSTCP(HLDP,4)
  1. Q
  1. ;
  1. DEFACK(HLDP,X) ;process the deferred application ack, called from HLCSIN
  1. ;HLDP=logical link, X=ien in file 773
  1. ;
  1. ; patch HL*1.6*120 start
  1. ; clean non-Kernel variables
  1. D
  1. . ; protect variables defined in STARTIN^HLCSIN
  1. . N HLFLG,HLEXIT,HLPTRFLR
  1. . ; protect variables defined in DEFACK^HLCSIN
  1. . N HLXX,HLD0,HLPCT
  1. . ; protect input parameters of this sub-routine
  1. . N HLDP,X
  1. . D KILL^XUSCLEAN
  1. ; patch HL*1.6*120 end
  1. ;
  1. ;set error trap
  1. N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLTP3"
  1. N HLERR ;patch HL*1.6*109
  1. Q:'$G(HLDP)!'$G(X) Q:'$G(^HLMA(X,0))
  1. Q:'$D(^HLMA("AC","I",HLDP,X))
  1. ;
  1. N HL,HLA,HLD0,HLEID,HLEIDS,HLHDR,HLHDRO,HLMTIEN,HLMTIENS,HLJ,HLMSA,HLN,HLQUIT,HLNODE,HLNEXT,HLRESLT,HLRESLTA,HLTCP,HLXX,Z,HLDONE1
  1. S HLMTIENS=X,X=^HLMA(HLMTIENS,0),HLMTIEN=+$P(X,U),HL("MID")=$P(X,U,2),HL("MTIENS")=$P(X,U,10),HL("LL")=$P(X,U,7),HLTCP="",HL("Q")=""""""
  1. S HL("EIDS")=$P(X,U,8),HL("SAP")=$P(X,U,11),HL("RAP")=$P(X,U,12),HL("MTP")=$P(X,U,13),HL("ETP")=$P(X,U,14)
  1. S:$P(X,U,15) HL("MTP_ETP")=$P(X,U,15)
  1. S:HL("SAP") HL("SAN")=$P($G(^HL(771,HL("SAP"),0)),U) S:HL("RAP") HL("RAN")=$P($G(^HL(771,HL("RAP"),0)),U)
  1. S:HL("MTP") HL("MTN")=$P($G(^HL(771.2,HL("MTP"),0)),U) S:HL("ETP") HL("ETN")=$P($G(^HL(779.001,HL("ETP"),0)),U)
  1. S:$G(HL("MTP_ETP")) HL("MTN_ETN")=$P($G(^HL(779.005,HL("MTP_ETP"),0)),U)
  1. S HL("EID")=$P($G(^HL(772,HLMTIEN,0)),U,10)
  1. M HLHDRO=^HLMA(HLMTIENS,"MSH")
  1. ; if no header quit
  1. Q:'$O(HLHDRO(0))
  1. ;
  1. S HL("FS")=$E(HLHDRO(1,0),4),HL("ECH")=$$P^HLTPCK2(.HLHDRO,2),HL("SFN")=$$P^HLTPCK2(.HLHDRO,4),HL("RFN")=$$P^HLTPCK2(.HLHDRO,6),HL("DTM")=$$P^HLTPCK2(.HLHDRO,7)
  1. ;
  1. ; quit if ien of #772 is not defined
  1. Q:'HLMTIEN
  1. ; quit if field separator is not defined
  1. Q:HL("FS")=""
  1. ;
  1. S X=$$P^HLTPCK2(.HLHDRO,1)
  1. ;
  1. ; patch HL*1.6*120 start
  1. I X="MSH" D
  1. . S HL("PID")=$$P^HLTPCK2(.HLHDRO,11),HL("VER")=$$P^HLTPCK2(.HLHDRO,12),HL("APAT")=$$P^HLTPCK2(.HLHDRO,16),HL("CC")=$$P^HLTPCK2(.HLHDRO,17)
  1. . ;
  1. . ; 2nd component is Processing mode
  1. . S HL("PMOD")=$P(HL("PID"),$E(HL("ECH"),1),2)
  1. . ; first component is Processing id
  1. . S HL("PID")=$P(HL("PID"),$E(HL("ECH"),1))
  1. ;
  1. I X'="MSH" D
  1. . S X=$$P^HLTPCK2(.HLHDRO,9),Z=$E(HL("ECH")),HL("PID")=$P(X,Z,2),HL("VER")=$P(X,Z,4)
  1. . ;
  1. . ; original code incorrectly treats repetition separator as
  1. . ; subcomponent separator
  1. . I $E(HL("ECH"),2)]"",X[$E(HL("ECH"),2) D
  1. .. S HL("SUB-COMPONENT")=$E(HL("ECH"),2)
  1. . ; if subcomponent separator is correctly applied
  1. . I $E(HL("ECH"),4)]"",X[$E(HL("ECH"),4) D
  1. .. S HL("SUB-COMPONENT")=$E(HL("ECH"),4)
  1. . ;
  1. . I $D(HL("SUB-COMPONENT")),HL("PID")[HL("SUB-COMPONENT") D
  1. .. ; 2nd sub-component is Processing mode
  1. .. S HL("PMOD")=$P(HL("PID"),HL("SUB-COMPONENT"),2)
  1. .. ; first sub-component is Processing id
  1. .. S HL("PID")=$P(HL("PID"),HL("SUB-COMPONENT"))
  1. . ; patch HL*1.6*120 end
  1. . ;
  1. . Q:$$P^HLTPCK2(.HLHDRO,10)=""
  1. . ;HLMSA=ack code^id^text
  1. . S HLMSA=$P($$P^HLTPCK2(.HLHDRO,10),$E(HL("ECH")),1),$P(HLMSA,HL("FS"),2)=$$P^HLTPCK2(.HLHDRO,12),$P(HLMSA,HL("FS"),3)=$P($$P^HLTPCK2(.HLHDRO,10),$E(HL("ECH")),2),HL("MSAID")=$P(HLMSA,HL("FS"),2)
  1. ;
  1. ; quit if this is a commit ack
  1. I $P($G(^HL(772,HLMTIEN,"IN",1,0)),HL("FS"),1)="MSA",$E($P($G(^HL(772,HLMTIEN,"IN",1,0)),HL("FS"),2))="C" Q
  1. ;
  1. ;** HL*1.6*117 **
  1. K HLL("SET FOR APP ACK"),HLL("LINKS")
  1. ;
  1. D CONT
  1. Q
  1. ;
  1. MSA(Y) ;Y=ien in 772, returns MSA segment
  1. ;ack code^msg being ack id^text
  1. ; patch HL*1.6*122
  1. ; for HL7 v2.5 and beyond with MSA as 3rd segment
  1. N X,SUBIEN,DATA,DONE
  1. S X=$G(^HL(772,Y,"IN",1,0)),X=$S($E(X,1,3)="MSA":$E(X,5,999),1:"")
  1. Q:X]"" X
  1. ;
  1. S DONE=0
  1. S SUBIEN=1
  1. F S SUBIEN=$O(^HL(772,Y,"IN",SUBIEN)) Q:'SUBIEN D Q:DONE
  1. . S DATA=$G(^HL(772,Y,"IN",SUBIEN,0)) I DATA="" D
  1. .. S DONE=1
  1. .. S SUBIEN=$O(^HL(772,Y,"IN",SUBIEN)) Q:'SUBIEN
  1. .. S X=$G(^HL(772,Y,"IN",SUBIEN,0)),X=$S($E(X,1,3)="MSA":$E(X,5,999),1:"")
  1. ; patch HL*1.6*122 end
  1. ;
  1. Q X
  1. ;
  1. ERROR ;error trap
  1. D ^%ZTER
  1. I $G(HLMTIENS),$D(^HLMA(HLMTIENS,0)) D STATUS^HLTF0(HLMTIENS,4,,,1),EXIT
  1. ; release locks created by inbound filer
  1. ; patch HL*1.6*140
  1. ; L -^HLMA("AC","I",+$G(HLXX))
  1. L -^HLMA("IN-FILER","AC","I",+$G(HLXX))
  1. G UNWIND^%ZTER
  1. ;
  1. ;
  1. EXIT ;unlock
  1. I $G(HLMTIENS) L -^HLMA(HLMTIENS)
  1. Q
  1. ;
  1. ONAC(IEN773) ;
  1. ;Returns 1 if the message is on the "AC","I" xref
  1. ;Returns 0 otherwise
  1. ;
  1. N LINK
  1. S LINK=$P($G(^HLMA(IEN773,0)),"^",17)
  1. Q:'LINK 0
  1. Q $D(^HLMA("AC","I",LINK,IEN773))