Changeset 623 for WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL
- Timestamp:
- Dec 4, 2009, 12:11:15 AM (15 years ago)
- Location:
- WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL
- Files:
-
- 49 edited
Legend:
- Unmodified
- Added
- Removed
-
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCS.m
r613 r623 1 HLCS ;ALB/RJS,MTC,JRP - COMMUNICATIONS SERVER - ;10/04/2007 14:34 2 ;;1.6;HEALTH LEVEL SEVEN;**2,9,14,19,43,57,109,132,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ;The SEND function is invoked by the transaction processor. 6 ;It's function is to $O through the ITEM multiple of the Event Driver 7 ;Protocol and create child entries in the Message Text file (#772) 8 ;for the message at HLMTIEN. These child messages point back 9 ;to the parent message so that message text does not need to 10 ;be duplicated when a message is sent to multiple applications. 11 ; 12 ;The SENDACK function is also invoked by the transaction processor. 13 ;It's function is to create a child entry in the Message Text file 14 ;for the message at HLMTIENA and deliver the message to the 15 ;application the requested/sent information. 16 ; 17 ;For DHCP to DHCP messaging (i.e. internal to internal), an incoming 18 ;message is created in the Message Text file which is a duplication 19 ;of the outgoing message. The incoming message is then processed by 20 ;calling the transaction processor. 21 ; 22 ;For DHCP to COTS messaging (i.e. internal to external), the message 23 ;is filed in the Message Text file with the Logical Link defined and 24 ;a status of PENDING TRANSMISSION. These entries are picked up by 25 ;the background filer and transmitted to the appropriate COTS system. 26 ; 27 SEND(HLMTIEN,HLEID,HLRESULT) ;Send an HL7 message 28 ;HLMTIEN=The IEN of the parent message in file # 772 29 ;HLEID=The IEN of the Event Driver protocol in file #101 30 ;HLRESULT=Variable for any error text (pass by reference) 31 ; 32 ;Declare variables 33 N HLARY,HLERROR,HLEIDS,HLCLIENT,HLOGLINK,HLMTIENS,HLMSGPTR 34 S HLERROR="" 35 ;Direct connect 36 I HLPRIO="I" D Q 37 . D DC^HLMA2 38 . S HLRESULT=HLERROR 39 ;Get all subscribers to the message 40 D ITEM^HLUTIL2(HLEID,"PTR") 41 ;Quit if no subscribers (considered successful delivery) 42 G:($G(HLARY(0))'>0) EXIT 43 ;Deliver message to each subscriber 44 S HLEIDS=0 45 F S HLEIDS=$O(HLARY(HLEIDS)) Q:(HLEIDS'>0) D 46 .; 47 .;**132 excluded subscribers ** 48 .N I,EXCLUDE 49 .S (EXCLUDE,I)=0 50 . ; 51 . ; patch HL*1.6*122 52 . ; F S I=$O(HLP("EXCLUDE SUBSCRIBER",I)) Q:'I I $G(HLP("EXCLUDE SUBSCRIBER",I))=HLEIDS S EXCLUDE=1 Q 53 . F S I=$O(HLP("EXCLUDE SUBSCRIBER",I)) Q:'I D Q:EXCLUDE 54 .. N TEMP 55 .. S TEMP=HLP("EXCLUDE SUBSCRIBER",I) 56 .. I 'TEMP,TEMP]"" S TEMP=$O(^ORD(101,"B",TEMP,0)) 57 .. I TEMP=HLEIDS S EXCLUDE=1 58 . ; patch HL*1.6*122 59 . ; 60 .Q:EXCLUDE 61 .;** 132 end ** 62 .; 63 .;Get pointer to receiving application 64 .S HLCLIENT=+HLARY(HLEIDS),HL("EIDS")=HLEIDS,HLERROR="" 65 .Q:(HLCLIENT'>0) 66 .;Check and execute ROUTING LOGIC **CIRN** 67 .S HLX=$G(^ORD(101,HLEIDS,774)) 68 .I HLX]"" D Q 69 ..N HLQUIT,HLNODE,HLNEXT 70 ..S HLQUIT=0,HLNODE="",HLNEXT="D HLNEXT^HLCSUTL" 71 ..X HLX I $D(HLL("LINKS")) D FWD^HLCS2 K HLL ;**CIRN** 72 .;Get pointer to logical link 73 .S HLOGLINK=$P(HLARY(HLEIDS),"^",2) 74 .;Determine if receiving application is internal or external 75 .; Logical link has a value for external applications 76 .; Logical link is NULL for internal applications 77 .I (HLOGLINK) D COTS Q 78 .;Create 'incoming' message based on 'outgoing' message (internal) 79 .D DHCP(HLMTIEN,HLEIDS,HLCLIENT) 80 .Q:(HLERROR) 81 .;Process the 'incoming' message 82 .S HLERROR="" 83 .D PROCESS^HLTP0(HLMSGPTR,"DHCP","",.HLERROR) 84 .;Update Status of 'incoming' message to SUCCESSFULLY COMPLETED 85 .; or ERROR DURING TRANSMISSION 86 .D STATUS^HLTF0(HLMSGPTR,$S(HLERROR:4,1:3),$S(HLERROR:+HLERROR,1:""),$S(HLERROR:$P(HLERROR,"^",2),1:""),,$S($G(HLERR("SKIP_EVENT"))=1:1,1:0)) 87 .I $D(HLL("LINKS")) D FWD^HLCS2 K HLL ;**CIRN** 88 D ADD^HLCS2 ;**CIRN** 89 EXIT S HLRESULT=HLERROR 90 Q 91 COTS ;Internal to external communication 92 ;Create child entry in Message Text file 93 N HLTCP,HLTCPI,HLTCPO 94 D SEND^HLMA2(HLEIDS,HLMTIEN,HLCLIENT,"D",.HLMTIENS,HLOGLINK) 95 I ((+HLMTIENS)'>0) S HLERROR=HLMTIENS Q 96 ;'Pass' message to background filer by setting status of child 97 ; to PENDING TRANSMISSION 98 D STATUS^HLTF0(HLMTIENS,1) 99 Q 100 DHCP(HLMTIEN,HLEIDS,HLCLIENT) ;Internal to internal communication 101 ; 102 ;Input : HLMTIEN - Pointer to parent outgoing message (file #772) 103 ; HLEIDS - Pointer to subscribing protocol (file #101) 104 ; HLCLIENT - Pointer to receiving application (file # 771) 105 ; 106 ;Output : HLMTIENS - Pointer to child outgoing message (file #772) 107 ; HLMSGPTR - Pointer to [parent] incoming message (file #772) 108 ; HLERROR - ErrorCode ^ ErrorText 109 ; 110 ;Notes : This module only copies the outgoing message into an incoming 111 ; message. Delivery of the message (i.e. processing of it) 112 ; must be done by the calling application. 113 ; : Message/batch header (MSH/BSH) is built and placed in the 114 ; incoming message 115 ; : HLMTIENS, HLMSGPTR, and HLERROR will be initialized 116 ; : Existance and validity of input is assumed 117 ; 118 ;Declare variables 119 N MSGID,MSGDT,MSGDTH,HDR2BLD,TMP,HLHDR,BHSHDR 120 S HLERROR="" 121 S HLMTIENS=0 122 S HLMSGPTR=0 123 ;Create child entry in Message Text file 124 D SEND^HLMA2(HLEIDS,HLMTIEN,HLCLIENT,"D",.HLMTIENS) 125 I ((+HLMTIENS)'>0) S HLERROR=HLMTIENS Q 126 ;'Receive' message by making an incoming message 127 ;Determine type of header to build 128 S TMP=$G(^HL(772,HLMTIEN,0)) 129 S HDR2BLD=$P(TMP,"^",14) 130 ;Build message header (MSH) 131 I (HDR2BLD="M") D Q:(HLERROR) 132 .S TMP="" 133 .D HEADER^HLCSHDR(HLMTIENS,.TMP) 134 .Q:(TMP="") 135 .;Error building header 136 .S HLERROR="4^Unable to build message header => "_TMP 137 .D STATUS^HLTF0(HLMTIENS,4,0,$P(HLERROR,"^",2)) 138 ;Build batch header (BHS or FHS) 139 I (HDR2BLD'="M") D Q:(HLERROR) 140 .S TMP="" 141 .D BHSHDR^HLCSHDR(HLMTIENS) 142 .S:($E(HLHDR(1),1)="-") TMP=$P(HLHDR(1),"^",2) 143 .Q:(TMP="") 144 .;Error building header 145 .S HLERROR="4^Unable to build batch header => "_TMP 146 .D STATUS^HLTF0(HLMTIENS,4,0,$P(HLERROR,"^",2)) 147 ;Create entry for 'incoming' message 148 D CREATE^HLTF(.MSGID,.HLMSGPTR,.MSGDT,.MSGDTH) 149 ;Move header and rest of message into 'incoming' message 150 I (HDR2BLD="M") D 151 .;Use MSH as header 152 .D MRGINT^HLTF1(HLMTIEN,HLMSGPTR,"HLHDR") 153 I (HDR2BLD'="M") D 154 .;Use BHS or FHS as header 155 .D MRGINT^HLTF1(HLMTIEN,HLMSGPTR,"BHSHDR") 156 ;Set status of outgoing message to AWAITING ACKNOWLEDGEMENT 157 D STATUS^HLTF0(HLMTIENS,$S($P(^HL(772,HLMTIEN,0),U,7):3,1:2)) 158 ;Set status of 'incoming' message to AWAITING PROCESSING 159 D STATUS^HLTF0(HLMSGPTR,9) 160 Q 161 SENDACK(HLMTIENA,HLEID,HLEIDS,HLRESULT) ;Send an HL7 acknowledgement/response 162 ;HLMTIENA=The IEN of the parent acknowledgment/response message in 163 ; file # 772 164 ;HLEIDS=The IEN of the Subscribing protocol in file # 101 165 ;HLEID=The IEN of the Event Driver protocol in file #101 166 ;HLRESULT=Variable for any error text (pass by reference) 167 ; 168 N HLERROR,HLOGLINK,HLCLIENT,HLMTIENS,HLMSGPTR,HLCLNODE 169 I $G(HLMTIENA)=""!($G(HLEID)="")!($G(HLEIDS)="") S HLERROR="0^7^"_$G(^HL(771.7,7,0))_"at SENDACK^HLCS entry point" G EXIT2 170 S HLCLNODE=$G(^ORD(101,HLEID,770)) 171 ;Get pointers to Logical Link & receiving application 172 S HLOGLINK=$P($G(^ORD(101,HLEIDS,770)),U,7) 173 ;Application needed to dynamically address the ACK (tcp/ip) 174 ;(set HLL("LINKS") array before calling GENACK) 175 I $D(HLL("LINKS")) D Q:'HLOGLINK 176 .S HLOGLINK=$P(HLL("LINKS",1),"^",2) Q:HLOGLINK="" 177 .K HLL("LINKS") 178 .I +HLOGLINK'=HLOGLINK S HLOGLINK=$O(^HLCS(870,"B",HLOGLINK,0)) 179 S HLCLIENT=$P(HLCLNODE,U,1) 180 Q:('HLCLIENT) 181 ;Determine if receiving application is internal or external 182 ; Logical link has a value for external applications 183 ; Logical link is NULL for internal applications 184 I (HLOGLINK) D COTSACK Q 185 ;Create 'incoming' message based on 'outgoing' message (internal) 186 D DHCP(HLMTIENA,HLEID,HLCLIENT) 187 ;Process the 'incoming' message 188 I (HLMSGPTR) D 189 .S HLERROR="" 190 .D PROCESS^HLTP0(HLMSGPTR,"DHCP","",.HLERROR) 191 ;Update Status of 'incoming' message to SUCCESSFULLY COMPLETED 192 ; or ERROR DURING TRANSMISSION 193 D STATUS^HLTF0(HLMSGPTR,$S(HLERROR:4,1:3),$S(HLERROR:+HLERROR,1:""),$S(HLERROR:$P(HLERROR,"^",2),1:"")) 194 EXIT2 ; 195 S HLRESULT=$G(HLERROR) 196 Q 197 COTSACK ;Internal to external communication of acknowledgements/responses 198 ;Create child entry in Message Text file 199 D SEND^HLMA2(HLEID,HLMTIENA,HLCLIENT,"D",.HLMTIENS,HLOGLINK) 200 ;'Pass' message to background filer by setting status of child 201 ; to PENDING TRANSMISSION 202 D STATUS^HLTF0(HLMTIENS,1) 203 Q 1 HLCS ;ALB/RJS,MTC,JRP - COMMUNICATIONS SERVER - ;10/31/2006 2 ;;1.6;HEALTH LEVEL SEVEN;**2,9,14,19,43,57,109,132**;Oct 13, 1995;Build 6 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ;The SEND function is invoked by the transaction processor. 6 ;It's function is to $O through the ITEM multiple of the Event Driver 7 ;Protocol and create child entries in the Message Text file (#772) 8 ;for the message at HLMTIEN. These child messages point back 9 ;to the parent message so that message text does not need to 10 ;be duplicated when a message is sent to multiple applications. 11 ; 12 ;The SENDACK function is also invoked by the transaction processor. 13 ;It's function is to create a child entry in the Message Text file 14 ;for the message at HLMTIENA and deliver the message to the 15 ;application the requested/sent information. 16 ; 17 ;For DHCP to DHCP messaging (i.e. internal to internal), an incoming 18 ;message is created in the Message Text file which is a duplication 19 ;of the outgoing message. The incoming message is then processed by 20 ;calling the transaction processor. 21 ; 22 ;For DHCP to COTS messaging (i.e. internal to external), the message 23 ;is filed in the Message Text file with the Logical Link defined and 24 ;a status of PENDING TRANSMISSION. These entries are picked up by 25 ;the background filer and transmitted to the appropriate COTS system. 26 ; 27 SEND(HLMTIEN,HLEID,HLRESULT) ;Send an HL7 message 28 ;HLMTIEN=The IEN of the parent message in file # 772 29 ;HLEID=The IEN of the Event Driver protocol in file #101 30 ;HLRESULT=Variable for any error text (pass by reference) 31 ; 32 ;Declare variables 33 N HLARY,HLERROR,HLEIDS,HLCLIENT,HLOGLINK,HLMTIENS,HLMSGPTR 34 S HLERROR="" 35 ;Direct connect 36 I HLPRIO="I" D Q 37 . D DC^HLMA2 38 . S HLRESULT=HLERROR 39 ;Get all subscribers to the message 40 D ITEM^HLUTIL2(HLEID,"PTR") 41 ;Quit if no subscribers (considered successful delivery) 42 G:($G(HLARY(0))'>0) EXIT 43 ;Deliver message to each subscriber 44 S HLEIDS=0 45 F S HLEIDS=$O(HLARY(HLEIDS)) Q:(HLEIDS'>0) D 46 .; 47 .;**132 excluded subscribers ** 48 .N I,EXCLUDE 49 .S (EXCLUDE,I)=0 50 .F S I=$O(HLP("EXCLUDE SUBSCRIBER",I)) Q:'I I $G(HLP("EXCLUDE SUBSCRIBER",I))=HLEIDS S EXCLUDE=1 Q 51 .Q:EXCLUDE 52 .;** 132 end ** 53 .; 54 .;Get pointer to receiving application 55 .S HLCLIENT=+HLARY(HLEIDS),HL("EIDS")=HLEIDS,HLERROR="" 56 .Q:(HLCLIENT'>0) 57 .;Check and execute ROUTING LOGIC **CIRN** 58 .S HLX=$G(^ORD(101,HLEIDS,774)) 59 .I HLX]"" D Q 60 ..N HLQUIT,HLNODE,HLNEXT 61 ..S HLQUIT=0,HLNODE="",HLNEXT="D HLNEXT^HLCSUTL" 62 ..X HLX I $D(HLL("LINKS")) D FWD^HLCS2 K HLL ;**CIRN** 63 .;Get pointer to logical link 64 .S HLOGLINK=$P(HLARY(HLEIDS),"^",2) 65 .;Determine if receiving application is internal or external 66 .; Logical link has a value for external applications 67 .; Logical link is NULL for internal applications 68 .I (HLOGLINK) D COTS Q 69 .;Create 'incoming' message based on 'outgoing' message (internal) 70 .D DHCP(HLMTIEN,HLEIDS,HLCLIENT) 71 .Q:(HLERROR) 72 .;Process the 'incoming' message 73 .S HLERROR="" 74 .D PROCESS^HLTP0(HLMSGPTR,"DHCP","",.HLERROR) 75 .;Update Status of 'incoming' message to SUCCESSFULLY COMPLETED 76 .; or ERROR DURING TRANSMISSION 77 .D STATUS^HLTF0(HLMSGPTR,$S(HLERROR:4,1:3),$S(HLERROR:+HLERROR,1:""),$S(HLERROR:$P(HLERROR,"^",2),1:""),,$S($G(HLERR("SKIP_EVENT"))=1:1,1:0)) 78 .I $D(HLL("LINKS")) D FWD^HLCS2 K HLL ;**CIRN** 79 D ADD^HLCS2 ;**CIRN** 80 EXIT S HLRESULT=HLERROR 81 Q 82 COTS ;Internal to external communication 83 ;Create child entry in Message Text file 84 N HLTCP,HLTCPI,HLTCPO 85 D SEND^HLMA2(HLEIDS,HLMTIEN,HLCLIENT,"D",.HLMTIENS,HLOGLINK) 86 I ((+HLMTIENS)'>0) S HLERROR=HLMTIENS Q 87 ;'Pass' message to background filer by setting status of child 88 ; to PENDING TRANSMISSION 89 D STATUS^HLTF0(HLMTIENS,1) 90 Q 91 DHCP(HLMTIEN,HLEIDS,HLCLIENT) ;Internal to internal communication 92 ; 93 ;Input : HLMTIEN - Pointer to parent outgoing message (file #772) 94 ; HLEIDS - Pointer to subscribing protocol (file #101) 95 ; HLCLIENT - Pointer to receiving application (file # 771) 96 ; 97 ;Output : HLMTIENS - Pointer to child outgoing message (file #772) 98 ; HLMSGPTR - Pointer to [parent] incoming message (file #772) 99 ; HLERROR - ErrorCode ^ ErrorText 100 ; 101 ;Notes : This module only copies the outgoing message into an incoming 102 ; message. Delivery of the message (i.e. processing of it) 103 ; must be done by the calling application. 104 ; : Message/batch header (MSH/BSH) is built and placed in the 105 ; incoming message 106 ; : HLMTIENS, HLMSGPTR, and HLERROR will be initialized 107 ; : Existance and validity of input is assumed 108 ; 109 ;Declare variables 110 N MSGID,MSGDT,MSGDTH,HDR2BLD,TMP,HLHDR,BHSHDR 111 S HLERROR="" 112 S HLMTIENS=0 113 S HLMSGPTR=0 114 ;Create child entry in Message Text file 115 D SEND^HLMA2(HLEIDS,HLMTIEN,HLCLIENT,"D",.HLMTIENS) 116 I ((+HLMTIENS)'>0) S HLERROR=HLMTIENS Q 117 ;'Receive' message by making an incoming message 118 ;Determine type of header to build 119 S TMP=$G(^HL(772,HLMTIEN,0)) 120 S HDR2BLD=$P(TMP,"^",14) 121 ;Build message header (MSH) 122 I (HDR2BLD="M") D Q:(HLERROR) 123 .S TMP="" 124 .D HEADER^HLCSHDR(HLMTIENS,.TMP) 125 .Q:(TMP="") 126 .;Error building header 127 .S HLERROR="4^Unable to build message header => "_TMP 128 .D STATUS^HLTF0(HLMTIENS,4,0,$P(HLERROR,"^",2)) 129 ;Build batch header (BHS or FHS) 130 I (HDR2BLD'="M") D Q:(HLERROR) 131 .S TMP="" 132 .D BHSHDR^HLCSHDR(HLMTIENS) 133 .S:($E(HLHDR(1),1)="-") TMP=$P(HLHDR(1),"^",2) 134 .Q:(TMP="") 135 .;Error building header 136 .S HLERROR="4^Unable to build batch header => "_TMP 137 .D STATUS^HLTF0(HLMTIENS,4,0,$P(HLERROR,"^",2)) 138 ;Create entry for 'incoming' message 139 D CREATE^HLTF(.MSGID,.HLMSGPTR,.MSGDT,.MSGDTH) 140 ;Move header and rest of message into 'incoming' message 141 I (HDR2BLD="M") D 142 .;Use MSH as header 143 .D MRGINT^HLTF1(HLMTIEN,HLMSGPTR,"HLHDR") 144 I (HDR2BLD'="M") D 145 .;Use BHS or FHS as header 146 .D MRGINT^HLTF1(HLMTIEN,HLMSGPTR,"BHSHDR") 147 ;Set status of outgoing message to AWAITING ACKNOWLEDGEMENT 148 D STATUS^HLTF0(HLMTIENS,$S($P(^HL(772,HLMTIEN,0),U,7):3,1:2)) 149 ;Set status of 'incoming' message to AWAITING PROCESSING 150 D STATUS^HLTF0(HLMSGPTR,9) 151 Q 152 SENDACK(HLMTIENA,HLEID,HLEIDS,HLRESULT) ;Send an HL7 acknowledgement/response 153 ;HLMTIENA=The IEN of the parent acknowledgment/response message in 154 ; file # 772 155 ;HLEIDS=The IEN of the Subscribing protocol in file # 101 156 ;HLEID=The IEN of the Event Driver protocol in file #101 157 ;HLRESULT=Variable for any error text (pass by reference) 158 ; 159 N HLERROR,HLOGLINK,HLCLIENT,HLMTIENS,HLMSGPTR,HLCLNODE 160 I $G(HLMTIENA)=""!($G(HLEID)="")!($G(HLEIDS)="") S HLERROR="0^7^"_$G(^HL(771.7,7,0))_"at SENDACK^HLCS entry point" G EXIT2 161 S HLCLNODE=$G(^ORD(101,HLEID,770)) 162 ;Get pointers to Logical Link & receiving application 163 S HLOGLINK=$P($G(^ORD(101,HLEIDS,770)),U,7) 164 ;Application needed to dynamically address the ACK (tcp/ip) 165 ;(set HLL("LINKS") array before calling GENACK) 166 I $D(HLL("LINKS")) D Q:'HLOGLINK 167 .S HLOGLINK=$P(HLL("LINKS",1),"^",2) Q:HLOGLINK="" 168 .K HLL("LINKS") 169 .I +HLOGLINK'=HLOGLINK S HLOGLINK=$O(^HLCS(870,"B",HLOGLINK,0)) 170 S HLCLIENT=$P(HLCLNODE,U,1) 171 Q:('HLCLIENT) 172 ;Determine if receiving application is internal or external 173 ; Logical link has a value for external applications 174 ; Logical link is NULL for internal applications 175 I (HLOGLINK) D COTSACK Q 176 ;Create 'incoming' message based on 'outgoing' message (internal) 177 D DHCP(HLMTIENA,HLEID,HLCLIENT) 178 ;Process the 'incoming' message 179 I (HLMSGPTR) D 180 .S HLERROR="" 181 .D PROCESS^HLTP0(HLMSGPTR,"DHCP","",.HLERROR) 182 ;Update Status of 'incoming' message to SUCCESSFULLY COMPLETED 183 ; or ERROR DURING TRANSMISSION 184 D STATUS^HLTF0(HLMSGPTR,$S(HLERROR:4,1:3),$S(HLERROR:+HLERROR,1:""),$S(HLERROR:$P(HLERROR,"^",2),1:"")) 185 EXIT2 ; 186 S HLRESULT=$G(HLERROR) 187 Q 188 COTSACK ;Internal to external communication of acknowledgements/responses 189 ;Create child entry in Message Text file 190 D SEND^HLMA2(HLEID,HLMTIENA,HLCLIENT,"D",.HLMTIENS,HLOGLINK) 191 ;'Pass' message to background filer by setting status of child 192 ; to PENDING TRANSMISSION 193 D STATUS^HLTF0(HLMTIENS,1) 194 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCS2.m
r613 r623 1 HLCS2 ;SF/JC - More Communication Server utilities ; 10/04/2007 14:31 2 ;;1.6;HEALTH LEVEL SEVEN;**14,40,43,49,57,58,82,84,109,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 FWD ; Add supplemental clients from HLL("LINKS") to HLSUP array 5 ;This enhancement also supports distribution of a message to 6 ;the same client over multiple logical links. 7 Q:'$D(HLL("LINKS")) 8 N CNT,LNK,CLIAP 9 S CNT=0,ROUTINE=1 F S CNT=$O(HLL("LINKS",CNT)) Q:CNT<1 D 10 . S PTR=$P(HLL("LINKS",CNT),"^"),LNK=$P(HLL("LINKS",CNT),"^",2) 11 . Q:PTR="" I +PTR<1 S PTR=$O(^ORD(101,"B",PTR,0)) Q:PTR<1 12 . ; 13 . ; patch HL*1.6*122: excluding subscribers defined in 14 . ; HLP("EXCLUDE SUBSCRIBER",I) = ien of subscriber 15 . N I,EXCLUDE 16 . S (EXCLUDE,I)=0 17 . F S I=$O(HLP("EXCLUDE SUBSCRIBER",I)) Q:'I D Q:EXCLUDE 18 .. N TEMP 19 .. S TEMP=HLP("EXCLUDE SUBSCRIBER",I) 20 .. I 'TEMP,TEMP]"" S TEMP=$O(^ORD(101,"B",TEMP,0)) 21 .. I TEMP=PTR S EXCLUDE=1 22 . Q:EXCLUDE 23 . ; 24 . Q:LNK="" I +LNK<1 S LNK=$O(^HLCS(870,"B",LNK,0)) Q:LNK<1 25 . Q:'$D(^HLCS(870,LNK)) 26 . S CLIAP=$$PTR^HLUTIL2(PTR) 27 . ; patch HL*1.6*122: add the 3rd component as receiving facility 28 . ; S HLSUP("S",PTR,+LNK)=CLIAP_$S(CLIAP<1:U_HLL("LINKS",CNT),1:"") 29 . S HLSUP("S",PTR,+LNK)=CLIAP_U_$S(CLIAP<1:HLL("LINKS",CNT),1:$P(HLL("LINKS",CNT),"^",3)) 30 Q 31 ADD ;Deliver message to supplemental client list. 32 ;Invoked by HLTP before and after processing normal clients 33 ;Only processes remote links. Local clients must be subscribing 34 ;protocols. 35 Q:'$D(HLSUP("S")) 36 N HLTCP,HLTCPI,HLTCPO,ZHLEIDS,ZLCLIENT,ZLOGLINK,ZMTIENS 37 S ZHLEIDS=0 F S ZHLEIDS=$O(HLSUP("S",ZHLEIDS)) Q:ZHLEIDS<1 D 38 .S ZLOGLINK=0 F S ZLOGLINK=$O(HLSUP("S",ZHLEIDS,ZLOGLINK)) Q:ZLOGLINK<1 D 39 ..S ZLCLIENT=+HLSUP("S",ZHLEIDS,ZLOGLINK) 40 ..I ZLCLIENT<1 S:$G(HLERROR)="" HLERROR="15^Invalid Subscriber Protocol in HLL('LINKS'): "_$P(HLSUP("S",ZHLEIDS,ZLOGLINK),U,2,9) Q 41 .. ; patch HL*1.6*122 start 42 .. ; S HLOGLINK=ZLOGLINK D SEND^HLMA2(ZHLEIDS,HLMTIEN,ZLCLIENT,"D",.ZMTIENS,ZLOGLINK),STATUS^HLTF0(+ZMTIENS,1) 43 .. S HLOGLINK=ZLOGLINK 44 .. ; 3rd component for receiving facility 45 .. S ZMTIENS("REC-FACILITY")=$P(HLSUP("S",ZHLEIDS,ZLOGLINK),U,3) 46 .. D SEND^HLMA2(ZHLEIDS,HLMTIEN,ZLCLIENT,"D",.ZMTIENS,ZLOGLINK) 47 .. D STATUS^HLTF0(+ZMTIENS,1) 48 .. ; patch HL*1.6*122 end 49 .. ; 50 K HLL("LINKS"),HLSUP 51 Q 52 STALL ;STOP ALL LINKS AND FILERS 53 N DIR,Y 54 W ! S DIR(0)="Y",DIR("A")="Okay to shut down all Links and Filers" 55 D ^DIR 56 I 'Y!($D(DIRUT))!($D(DUOUT)) W !!,"Shutdown Aborted!" Q 57 W !,"Shutting down all Links and Filers..." 58 D CLEAR 59 D LLP(1) 60 Q 61 QUE ;Restart Filers and AUTOSTART Logical Links after system re-boot 62 N DIR,Y 63 I '$D(ZTQUEUED) D Q:'Y!($D(DIRUT))!($D(DUOUT)) 64 .W ! S DIR(0)="Y",DIR("A")="Shutdown and restart ALL AUTOSTART links and filers. Okay" 65 .D ^DIR 66 .I 'Y!($D(DIRUT))!($D(DUOUT)) W !!,"RESTART Aborted!" Q 67 .W !,"Restarting all Autostart-Enabled Links and Filers..." 68 D CLEAR 69 D STARTF 70 D LLP(0) 71 D STRT 72 Q 73 CLEAR ;Reset state of 869.3 74 S DA(1)=1,DA=0,DIK="^HLCS(869.3,1,2," 75 F S DA=$O(^HLCS(869.3,DA(1),2,DA)) Q:DA<1 D ^DIK 76 S DA=0,DIK="^HLCS(869.3,1,3," 77 F S DA=$O(^HLCS(869.3,DA(1),3,DA)) Q:DA<1 D ^DIK 78 Q 79 STARTF ;Start filers 80 ;Get Defaults 81 N TMP,PTR,DEFCNT,DA,HLCNT,HLNODE1 82 S PTR=+$O(^HLCS(869.3,0)) Q:'PTR 83 ;default # of incoming filers 84 S HLNODE1=$G(^HLCS(869.3,PTR,1)),DEFCNT=+$P(HLNODE1,U) S:'DEFCNT DEFCNT=1 85 F HLCNT=1:1:DEFCNT S TMP=$$TASKFLR^HLCS1("IN") 86 ;default # of outgoing filers 87 S DEFCNT=+$P(HLNODE1,U,2) S:'DEFCNT DEFCNT=1 88 F HLCNT=1:1:DEFCNT S TMP=$$TASKFLR^HLCS1("OUT") 89 Q 90 LLP(ALL) ;Stop Logical Links 91 ;ALL=1 OR 0 IF zero, only AUTOSTART LINKS get stopped 92 N HLDP,HLDP0,HLPARM0,HLPARM4,HLJ,X,Y S HLDP=0 93 F S HLDP=$O(^HLCS(870,HLDP)) Q:'HLDP S HLDP0=$G(^(HLDP,0)),X=+$P(HLDP0,U,3) D:X 94 .;skip this link if not stopping all and Autostart not enabled 95 . I 'ALL&('$P(HLDP0,U,6)) Q 96 . S HLPARM4=$G(^HLCS(870,HLDP,400)) 97 . ; patch HL*1.6*122 98 . ; TCP Multi listener: quit if TCP service as GT.M, DSM, 99 . ; or Cache/VMS 100 . I $P(HLPARM4,U,3)="M" Q:^%ZOSF("OS")'["OpenM" Q:$$OS^%ZOSV["VMS" 101 . ; 102 . ;4=status,10=Time Stopped,9=Time Started,11=Task Number,3=Device Type,14=shutdown? 103 . S X="HLJ(870,"""_HLDP_","")",@X@(10)=$$NOW^XLFDT,(@X@(11),@X@(9))="@",@X@(14)=1 104 . I "Shutdown,SHUTDOWN"'[$P(HLDP0,U,5) S @X@(4)="Halting" 105 . I $P(HLPARM4,U,3)="C"&("N"[$P(HLPARM4,U,4)),'$P(HLDP0,U,12) S @X@(4)="Shutdown" 106 . D FILE^HLDIE("","HLJ","","LLP","HLCS2") ;HL*1.6*109 107 . I ^%ZOSF("OS")["OpenM",($P(HLPARM4,U,3)="M"!($P(HLPARM4,U,3)="S")) D 108 .. ; pass task number to stop listener 109 .. S:$P(HLDP0,U,12) X=$$ASKSTOP^%ZTLOAD(+$P(HLDP0,U,12)) 110 ; patch HL*1.6*122 start 111 ; .. D CALL^%ZISTCP($P(HLPARM4,U),$P(HLPARM4,U,2),10) 112 ; .. I POP D HOME^%ZIS Q 113 ; .. D CLOSE^%ZISTCP 114 ; patch HL*1.6*122 end 115 Q 116 STRT ;Start Links 117 N HLDP,HLDP0,HLDAPP,HLTYPTR,HLBGR,HLENV,HLPARAM0,HLPARM4,HLQUIT,ZTRTN,ZTDESC,ZTSK,ZTCPU 118 S HLDP=0 119 F S HLDP=$O(^HLCS(870,HLDP)) Q:HLDP<1 S HLDP0=$G(^(HLDP,0)) D 120 . S HLPARM4=$G(^HLCS(870,HLDP,400)) 121 . ;quit if no parameters or AUTOSTART is disabled 122 . Q:'$P(HLDP0,U,6) 123 . ;HLDAPP=LL name, HLTYPTR=LL type, HLBGR=routine, HLENV=environment check 124 . S HLDAPP=$P(HLDP0,U),HLTYPTR=+$P(HLDP0,U,3),HLBGR=$G(^HLCS(869.1,HLTYPTR,100)),HLENV=$G(^(200)) 125 . ;quit if no LL type or no routine 126 . Q:'HLTYPTR!(HLBGR="") 127 . I HLENV'="" K HLQUIT X HLENV Q:$D(HLQUIT) 128 . ; patch HL*1.6*122 129 . ; TCP Multi listener: quit if TCP service as GT.M, DSM, 130 . ; or Cache/VMS 131 . I $P(HLPARM4,U,3)="M" Q:^%ZOSF("OS")'["OpenM" Q:$$OS^%ZOSV["VMS" 132 . ; 133 . I $P(HLPARM4,U,3)="C"&("N"[$P(HLPARM4,U,4)) D Q 134 .. ;4=status 9=Time Started, 10=Time Stopped, 11=Task Number 135 .. ;14=Shutdown LLP, 3=Device Type, 18=Gross Errors 136 .. N HLJ,X 137 .. I $P(HLDP0,U,15)=0 Q 138 .. L +^HLCS(870,HLDP,0):2 139 .. E Q 140 .. S X="HLJ(870,"""_HLDP_","")" 141 .. S @X@(4)="Enabled",@X@(9)=$$NOW^XLFDT,@X@(14)=0 142 .. D FILE^HLDIE("","HLJ","","STRT","HLCS2") ; HL*1.6*109 143 .. L -^HLCS(870,HLDP,0) 144 .. Q 145 . S ZTRTN=$P(HLBGR," ",2),ZTIO="",ZTDTH=$H,HLTRACE="" 146 . S ZTDESC=HLDAPP_" Low Level Protocol",ZTSAVE("HLDP")="" 147 . ;get startup node 148 . I $P(HLPARM4,U,6),$D(^%ZIS(14.7,+$P(HLPARM4,U,6),0)) S ZTCPU=$P(^(0),U) 149 . D ^%ZTLOAD 150 Q 151 SITEP ;Edit Site Parameters 152 S DDSFILE=869.3,DA=1,DR="[HL SITE PARAMETERS]" D ^DDS 153 Q 154 PARAM() ;Return HL7 site parameters 155 ;HLPARAM=domain ien^domain name^production or test^institution ien^ 156 ;institution name^institution number^mail group ien^mail group name^ 157 ;purge completed messages^purge awaiting ack messages^purge all msgs^ 158 ;default retention 159 N HLX,HLX4,HLX5,HLDOMP,HLDOMN,HLPROD,HLINSP,HLINSN,HLINSNM,HLMAILP,HLMAILN,HLPARAM,HLPRGAA,HLPRGALL,HLPRGCMP,HLDEFRET 160 S HLX=$G(^HLCS(869.3,1,0)) 161 S HLX4=$G(^HLCS(869.3,1,4)) 162 S HLX5=$G(^HLCS(869.3,1,5)) 163 S HLDOMP=$P(HLX,U,2) I HLDOMP S HLDOMN=$P(^DIC(4.2,HLDOMP,0),U) 164 S HLPROD=$P(HLX,U,3) 165 S HLINSP=$P(HLX,U,4) I HLINSP S HLINSN=$P(^DIC(4,HLINSP,0),U),HLINSNM=$P($G(^DIC(4,HLINSP,99)),U) 166 S HLMAILP=$P(HLX,U,5) I HLMAILP S HLMAILN=$P(^XMB(3.8,HLMAILP,0),U) 167 S HLPRGCMP=$P(HLX4,U),HLPRGAA=$P(HLX4,U,2),HLPRGALL=$P(HLX4,U,3) 168 S HLDEFRET=$P(HLX5,U) 169 S HLPARAM=HLDOMP_U_$G(HLDOMN)_U_$G(HLPROD)_U_HLINSP_U_$G(HLINSN)_U_$G(HLINSNM)_U_HLMAILP_U_$G(HLMAILN)_U_HLPRGCMP_U_HLPRGAA_U_HLPRGALL_U_HLDEFRET 170 Q HLPARAM 171 ; 172 GETAPP(HLAPP) ;Function to Retrieve parameters pertaining to a specific sending or receiving application 173 ;HLAPP=APPLICATION NAME OR IEN OF FILE 771 174 ;Returns MAIL GROUP NAME^'a' or 'i' (active or inactive) 175 S HLAPP=$G(HLAPP) 176 I HLAPP]"",'HLAPP S HLAPP=$O(^HL(771,"B",$E(HLAPP,1,30),0)) 177 I 'HLAPP Q "" 178 I HLAPP S HLM=$P(^HL(771,HLAPP,0),U,4) 179 I HLM S HLM=$P($G(^XMB(3.8,HLM,0)),U) 180 Q $G(HLM)_U_$P(^HL(771,HLAPP,0),U,2) 1 HLCS2 ;SF/JC - More Communication Server utilities ; 12/31/2003 17:50 2 ;;1.6;HEALTH LEVEL SEVEN;**14,40,43,49,57,58,82,84,109**;Oct 13, 1995 3 FWD ; Add supplemental clients from HLL("LINKS") to HLSUP array 4 ;This enhancement also supports distribution of a message to 5 ;the same client over multiple logical links. 6 Q:'$D(HLL("LINKS")) 7 N CNT,LNK,CLIAP 8 S CNT=0,ROUTINE=1 F S CNT=$O(HLL("LINKS",CNT)) Q:CNT<1 D 9 . S PTR=$P(HLL("LINKS",CNT),"^"),LNK=$P(HLL("LINKS",CNT),"^",2) 10 . Q:PTR="" I +PTR<1 S PTR=$O(^ORD(101,"B",PTR,0)) Q:PTR<1 11 . Q:LNK="" I +LNK<1 S LNK=$O(^HLCS(870,"B",LNK,0)) Q:LNK<1 12 . Q:'$D(^HLCS(870,LNK)) 13 . S CLIAP=$$PTR^HLUTIL2(PTR) 14 . S HLSUP("S",PTR,+LNK)=CLIAP_$S(CLIAP<1:U_HLL("LINKS",CNT),1:"") 15 Q 16 ADD ;Deliver message to supplemental client list. 17 ;Invoked by HLTP before and after processing normal clients 18 ;Only processes remote links. Local clients must be subscribing 19 ;protocols. 20 Q:'$D(HLSUP("S")) 21 N HLTCP,HLTCPI,HLTCPO,ZHLEIDS,ZLCLIENT,ZLOGLINK,ZMTIENS 22 S ZHLEIDS=0 F S ZHLEIDS=$O(HLSUP("S",ZHLEIDS)) Q:ZHLEIDS<1 D 23 .S ZLOGLINK=0 F S ZLOGLINK=$O(HLSUP("S",ZHLEIDS,ZLOGLINK)) Q:ZLOGLINK<1 D 24 ..S ZLCLIENT=+HLSUP("S",ZHLEIDS,ZLOGLINK) 25 ..I ZLCLIENT<1 S:$G(HLERROR)="" HLERROR="15^Invalid Subscriber Protocol in HLL('LINKS'): "_$P(HLSUP("S",ZHLEIDS,ZLOGLINK),U,2,9) Q 26 ..S HLOGLINK=ZLOGLINK D SEND^HLMA2(ZHLEIDS,HLMTIEN,ZLCLIENT,"D",.ZMTIENS,ZLOGLINK),STATUS^HLTF0(+ZMTIENS,1) 27 K HLL("LINKS"),HLSUP 28 Q 29 STALL ;STOP ALL LINKS AND FILERS 30 N DIR,Y 31 W ! S DIR(0)="Y",DIR("A")="Okay to shut down all Links and Filers" 32 D ^DIR 33 I 'Y!($D(DIRUT))!($D(DUOUT)) W !!,"Shutdown Aborted!" Q 34 W !,"Shutting down all Links and Filers..." 35 D CLEAR 36 D LLP(1) 37 Q 38 QUE ;Restart Filers and AUTOSTART Logical Links after system re-boot 39 N DIR,Y 40 I '$D(ZTQUEUED) D Q:'Y!($D(DIRUT))!($D(DUOUT)) 41 .W ! S DIR(0)="Y",DIR("A")="Shutdown and restart ALL AUTOSTART links and filers. Okay" 42 .D ^DIR 43 .I 'Y!($D(DIRUT))!($D(DUOUT)) W !!,"RESTART Aborted!" Q 44 .W !,"Restarting all Autostart-Enabled Links and Filers..." 45 D CLEAR 46 D STARTF 47 D LLP(0) 48 D STRT 49 Q 50 CLEAR ;Reset state of 869.3 51 S DA(1)=1,DA=0,DIK="^HLCS(869.3,1,2," 52 F S DA=$O(^HLCS(869.3,DA(1),2,DA)) Q:DA<1 D ^DIK 53 S DA=0,DIK="^HLCS(869.3,1,3," 54 F S DA=$O(^HLCS(869.3,DA(1),3,DA)) Q:DA<1 D ^DIK 55 Q 56 STARTF ;Start filers 57 ;Get Defaults 58 N TMP,PTR,DEFCNT,DA,HLCNT,HLNODE1 59 S PTR=+$O(^HLCS(869.3,0)) Q:'PTR 60 ;default # of incoming filers 61 S HLNODE1=$G(^HLCS(869.3,PTR,1)),DEFCNT=+$P(HLNODE1,U) S:'DEFCNT DEFCNT=1 62 F HLCNT=1:1:DEFCNT S TMP=$$TASKFLR^HLCS1("IN") 63 ;default # of outgoing filers 64 S DEFCNT=+$P(HLNODE1,U,2) S:'DEFCNT DEFCNT=1 65 F HLCNT=1:1:DEFCNT S TMP=$$TASKFLR^HLCS1("OUT") 66 Q 67 LLP(ALL) ;Stop Logical Links 68 ;ALL=1 OR 0 IF zero, only AUTOSTART LINKS get stopped 69 N HLDP,HLDP0,HLPARM0,HLPARM4,HLJ,X,Y S HLDP=0 70 F S HLDP=$O(^HLCS(870,HLDP)) Q:'HLDP S HLDP0=$G(^(HLDP,0)),X=+$P(HLDP0,U,3) D:X 71 .;skip this link if not stopping all and Autostart not enabled 72 . I 'ALL&('$P(HLDP0,U,6)) Q 73 . S HLPARM4=$G(^HLCS(870,HLDP,400)) 74 . ;TCP Multi listener for non-Cache uses UCX 75 . I $P(HLPARM4,U,3)="M" Q:^%ZOSF("OS")'["OpenM" Q:$$OS^%ZOSV["VMS" 76 . ;4=status,10=Time Stopped,9=Time Started,11=Task Number,3=Device Type,14=shutdown? 77 . S X="HLJ(870,"""_HLDP_","")",@X@(4)="Halting",@X@(10)=$$NOW^XLFDT,(@X@(11),@X@(9))="@",@X@(14)=1 78 . I $P(HLPARM4,U,3)="C"&("N"[$P(HLPARM4,U,4)),'$P(HLDP0,U,12) S @X@(4)="Shutdown" 79 . D FILE^HLDIE("","HLJ","","LLP","HLCS2") ;HL*1.6*109 80 . ;Cache system, need to open TCP port to release job 81 . I ^%ZOSF("OS")["OpenM",($P(HLPARM4,U,3)="M"!($P(HLPARM4,U,3)="S")) D 82 .. ;pass task number to stop listener 83 .. S:$P(HLDP0,U,12) X=$$ASKSTOP^%ZTLOAD(+$P(HLDP0,U,12)) 84 .. D CALL^%ZISTCP($P(HLPARM4,U),$P(HLPARM4,U,2),10) 85 .. I POP D HOME^%ZIS Q 86 .. D CLOSE^%ZISTCP 87 Q 88 STRT ;Start Links 89 N HLDP,HLDP0,HLDAPP,HLTYPTR,HLBGR,HLENV,HLPARAM0,HLPARM4,HLQUIT,ZTRTN,ZTDESC,ZTSK,ZTCPU 90 S HLDP=0 91 F S HLDP=$O(^HLCS(870,HLDP)) Q:HLDP<1 S HLDP0=$G(^(HLDP,0)) D 92 . S HLPARM4=$G(^HLCS(870,HLDP,400)) 93 . ;quit if no parameters or AUTOSTART is disabled 94 . Q:'$P(HLDP0,U,6) 95 . ;HLDAPP=LL name, HLTYPTR=LL type, HLBGR=routine, HLENV=environment check 96 . S HLDAPP=$P(HLDP0,U),HLTYPTR=+$P(HLDP0,U,3),HLBGR=$G(^HLCS(869.1,HLTYPTR,100)),HLENV=$G(^(200)) 97 . ;quit if no LL type or no routine 98 . Q:'HLTYPTR!(HLBGR="") 99 . I HLENV'="" K HLQUIT X HLENV Q:$D(HLQUIT) 100 . ;TCP Multi listener for non-Cache uses UCX 101 . I $P(HLPARM4,U,3)="M" Q:^%ZOSF("OS")'["OpenM" Q:$$OS^%ZOSV["VMS" 102 . I $P(HLPARM4,U,3)="C"&("N"[$P(HLPARM4,U,4)) D Q 103 .. ;4=status 9=Time Started, 10=Time Stopped, 11=Task Number 104 .. ;14=Shutdown LLP, 3=Device Type, 18=Gross Errors 105 .. N HLJ,X 106 .. I $P(HLDP0,U,15)=0 Q 107 .. L +^HLCS(870,HLDP,0):2 108 .. E Q 109 .. S X="HLJ(870,"""_HLDP_","")" 110 .. S @X@(4)="Enabled",@X@(9)=$$NOW^XLFDT,@X@(14)=0 111 .. D FILE^HLDIE("","HLJ","","STRT","HLCS2") ; HL*1.6*109 112 .. L -^HLCS(870,HLDP,0) 113 .. Q 114 . S ZTRTN=$P(HLBGR," ",2),ZTIO="",ZTDTH=$H,HLTRACE="" 115 . S ZTDESC=HLDAPP_" Low Level Protocol",ZTSAVE("HLDP")="" 116 . ;get startup node 117 . I $P(HLPARM4,U,6),$D(^%ZIS(14.7,+$P(HLPARM4,U,6),0)) S ZTCPU=$P(^(0),U) 118 . D ^%ZTLOAD 119 Q 120 SITEP ;Edit Site Parameters 121 S DDSFILE=869.3,DA=1,DR="[HL SITE PARAMETERS]" D ^DDS 122 Q 123 PARAM() ;Return HL7 site parameters 124 ;HLPARAM=domain ien^domain name^production or test^institution ien^ 125 ;institution name^institution number^mail group ien^mail group name^ 126 ;purge completed messages^purge awaiting ack messages^purge all msgs^ 127 ;default retention 128 N HLX,HLX4,HLX5,HLDOMP,HLDOMN,HLPROD,HLINSP,HLINSN,HLINSNM,HLMAILP,HLMAILN,HLPARAM,HLPRGAA,HLPRGALL,HLPRGCMP,HLDEFRET 129 S HLX=$G(^HLCS(869.3,1,0)) 130 S HLX4=$G(^HLCS(869.3,1,4)) 131 S HLX5=$G(^HLCS(869.3,1,5)) 132 S HLDOMP=$P(HLX,U,2) I HLDOMP S HLDOMN=$P(^DIC(4.2,HLDOMP,0),U) 133 S HLPROD=$P(HLX,U,3) 134 S HLINSP=$P(HLX,U,4) I HLINSP S HLINSN=$P(^DIC(4,HLINSP,0),U),HLINSNM=$P($G(^DIC(4,HLINSP,99)),U) 135 S HLMAILP=$P(HLX,U,5) I HLMAILP S HLMAILN=$P(^XMB(3.8,HLMAILP,0),U) 136 S HLPRGCMP=$P(HLX4,U),HLPRGAA=$P(HLX4,U,2),HLPRGALL=$P(HLX4,U,3) 137 S HLDEFRET=$P(HLX5,U) 138 S HLPARAM=HLDOMP_U_$G(HLDOMN)_U_$G(HLPROD)_U_HLINSP_U_$G(HLINSN)_U_$G(HLINSNM)_U_HLMAILP_U_$G(HLMAILN)_U_HLPRGCMP_U_HLPRGAA_U_HLPRGALL_U_HLDEFRET 139 Q HLPARAM 140 ; 141 GETAPP(HLAPP) ;Function to Retrieve parameters pertaining to a specific sending or receiving application 142 ;HLAPP=APPLICATION NAME OR IEN OF FILE 771 143 ;Returns MAIL GROUP NAME^'a' or 'i' (active or inactive) 144 S HLAPP=$G(HLAPP) 145 I HLAPP]"",'HLAPP S HLAPP=$O(^HL(771,"B",$E(HLAPP,1,30),0)) 146 I 'HLAPP Q "" 147 I HLAPP S HLM=$P(^HL(771,HLAPP,0),U,4) 148 I HLM S HLM=$P($G(^XMB(3.8,HLM,0)),U) 149 Q $G(HLM)_U_$P(^HL(771,HLAPP,0),U,2) -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSGTM.m
r613 r623 1 HLCSGTM ;OIFO-O/RWF - (TCP/IP) GT.M Linux ;08/13/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ; 1. port number is input from VMS COM file, such as HLSxxxxDSM.COM, 6 ; HLSxxxxCACHE.COM, or HLSxxxxGTM.COM file, where xxxx is port 7 ; number. 8 ; 2. find the ien of #870(logical link file) for the multi-listener 9 Q 10 ; 11 IEN(HLPORT) ; 12 ; HLIEN870: ien in #870 (logical link file) 13 ; HLPRTS: port number in entry to be tested 14 ; 15 N HLPRTS,HLIEN870 16 I '$G(HLPORT) D ^%ZTER Q 17 S HLIEN870=0 18 F S HLIEN870=$O(^HLCS(870,"E","M",HLIEN870)) Q:'HLIEN870 D Q:(HLPRTS=HLPORT) 19 . S HLPRTS=$P(^HLCS(870,HLIEN870,400),"^",2) 20 I 'HLIEN870 D ^%ZTER Q 21 ; 22 Q HLIEN870 23 ; 24 GTMLNX ; From Linux xinetd script 25 ;Get port from ZSHOW "D" 26 S U="^",$ZT="",$ET="D ^%ZTER HALT" ;Setup the error trap 27 ; GTM specific code 28 S IO=$P X "U IO:(nowrap:nodelimiter:IOERROR=""TRAP"")" ;Setup device 29 S @("$ZINTERRUPT=""I $$JOBEXAM^ZU($ZPOSITION)""") 30 K ^TMP($J) ZSHOW "D":^TMP($J) 31 F %=1:1 Q:'$D(^TMP($J,"D",%)) S X=^(%) Q:X["LOCAL" 32 S IO("IP")=$P($P(X,"REMOTE=",2),"@"),IO("PORT")=+$P($P(X,"LOCAL=",2),"@",2) 33 S %=$P($ZTRNLNM("SSH_CLIENT")," ") S:%="" %=$ZTRNLNM("REMOTEHOST") 34 S HLDP=$$IEN(IO("PORT")) 35 ; 36 D LISTEN^HLCSTCP 37 Q 38 ; 39 ;Sample Linux script 40 ;#!/bin/bash 41 ;#HL7 Listener 42 ;cd /home/vista/dev/ 43 ;. ./gtmprofile 44 ;#env > hl7log.txt 45 ;$gtm_dist/mumps -r GTMLNX^HLCSGTM 46 ;exit 0 47 ; 48 ;Sample xinetd config file 49 ;service hl7tcp 50 ;{ 51 ; socket_type = stream 52 ; user = gtmuser 53 ; wait = no 54 ; disable = no 55 ; server = /bin/bash 56 ; server_args = -l /home/vista/dev/hl7tcp.sh 57 ; passenv = REMOTE_HOST 58 ;} 1 HLCSGTM ;OIFO-O/RWF - (TCP/IP) GT.M Linux ;08/13/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**122**;Oct 13, 1995;Build 4;WorldVistA 30-Jan-08 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ; 1. port number is input from VMS COM file, such as HLSxxxxDSM.COM, 6 ; HLSxxxxCACHE.COM, or HLSxxxxGTM.COM file, where xxxx is port 7 ; number. 8 ; 2. find the ien of #870(logical link file) for the multi-listener 9 ;Modified from FOIA VISTA, 10 ;Copyright 2008 WorldVistA. Licensed under the terms of the GNU 11 ;General Public License See attached copy of the License. 12 ; 13 ;This program is free software; you can redistribute it and/or modify 14 ;it under the terms of the GNU General Public License as published by 15 ;the Free Software Foundation; either version 2 of the License, or 16 ;(at your option) any later version. 17 ; 18 ;This program is distributed in the hope that it will be useful, 19 ;but WITHOUT ANY WARRANTY; without even the implied warranty of 20 ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 ;GNU General Public License for more details. 22 ; 23 ;You should have received a copy of the GNU General Public License along 24 ;with this program; if not, write to the Free Software Foundation, Inc., 25 ;51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 26 Q 27 ; 28 IEN(HLPORT) ; 29 ; HLIEN870: ien in #870 (logical link file) 30 ; HLPRTS: port number in entry to be tested 31 ; 32 N HLPRTS,HLIEN870 33 I '$G(HLPORT) D ^%ZTER Q 34 S HLIEN870=0 35 F S HLIEN870=$O(^HLCS(870,"E","M",HLIEN870)) Q:'HLIEN870 D Q:(HLPRTS=HLPORT) 36 . S HLPRTS=$P(^HLCS(870,HLIEN870,400),"^",2) 37 I 'HLIEN870 D ^%ZTER Q 38 ; 39 Q HLIEN870 40 ; 41 GTMLNX ; From Linux xinetd script 42 ;Get port from ZSHOW "D" 43 S U="^",$ZT="",$ET="D ^%ZTER HALT" ;Setup the error trap 44 ; GTM specific code 45 S IO=$P X "U IO:(nowrap:nodelimiter:IOERROR=""TRAP"")" ;Setup device 46 S @("$ZINTERRUPT=""I $$JOBEXAM^ZU($ZPOSITION)""") 47 K ^TMP($J) ZSHOW "D":^TMP($J) 48 F %=1:1 Q:'$D(^TMP($J,"D",%)) S X=^(%) Q:X["LOCAL" 49 S IO("IP")=$P($P(X,"REMOTE=",2),"@"),IO("PORT")=+$P($P(X,"LOCAL=",2),"@",2) 50 S %=$P($ZTRNLNM("SSH_CLIENT")," ") S:%="" %=$ZTRNLNM("REMOTEHOST") 51 S HLDP=$$IEN(IO("PORT")) 52 ; 53 D LISTEN^HLCSTCP 54 Q 55 ; 56 ;Sample Linux script 57 ;#!/bin/bash 58 ;#HL7 Listener 59 ;cd /home/vista/dev/ 60 ;. ./gtmprofile 61 ;#env > hl7log.txt 62 ;$gtm_dist/mumps -r GTMLNX^HLCSGTM 63 ;exit 0 64 ; 65 ;Sample xinetd config file 66 ;service hl7tcp 67 ;{ 68 ; socket_type = stream 69 ; user = gtmuser 70 ; wait = no 71 ; disable = no 72 ; server = /bin/bash 73 ; server_args = -l /home/vista/dev/hl7tcp.sh 74 ; passenv = REMOTE_HOST 75 ;} -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSHDR1.m
r613 r623 1 HLCSHDR1 ;SFIRMFO/RSD - Make HL7 header for TCP ;04/17/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**19,57,59,72,80,93,120,133,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 HEADER(IEN,CLIENT,HLERROR) ; Create an HL7 MSH segment 5 ; 6 ;Input : IEN - Pointer to entry in Message Administration file (#773) 7 ; that HL7 MSH segment is being built for 8 ; CLIENT - IEN of the receiving application 9 ; HLERROR - Variable to return possible error text in 10 ; (pass by reference - only used when needed) 11 ; 12 ;Output : HLHDR(1) - HL7 MSH segment 13 ; HLHDR(2) - Continuation of HL7 MSH segment (if needed) 14 ; HLHDR(3) - Continuation of HL7 MSH segment (if needed) 15 ; 16 ;Notes : HLERROR will only be defined [on output] if an error occurs 17 ; : HLHDR() will not be defined [on output] if an error occurs 18 ; : HLHDR(2) & HLHDR(3) are continuation [or roll-over] nodes 19 ; and will only be used/defined when needed 20 ; 21 N ACKTO,ACCACK,APPACK,CHILD,CLNTAPP,CLNTFAC,CNTRY,EC,EVNTYPE,FS,HLDATE,HLHDRI,HLHDRL,HLID,HLPID,MSGTYPE,PROT,PROTS,SECURITY,SEND,SERAPP,SERFAC,TXTP,TXTP0,X,MSGEVN 22 N COMFLAG ; patch HL*1.6*120 23 S HLERROR="" 24 S HLPARAM=$$PARAM^HLCS2 25 D VAR Q:$G(HLERROR)]"" 26 ; The following line commented by HL*1.6*72 27 ;I $D(^HLMA(IEN)) S $P(^HLMA(IEN,0),U,13)=MSGTYPE,$P(^HLMA(IEN,0),U,14)=$G(EVNTYPE) 28 ;Append event type 29 I $G(EVNTYPE)]"" S MSGTYPE=MSGTYPE_$E(EC,1)_EVNTYPE 30 ;Append message structure component 31 I $G(EVNTYPE)]"",$G(MSGEVN)]"" S MSGTYPE=MSGTYPE_$E(EC,1)_MSGEVN 32 ;Build MSH array 33 D RESET^HLCSHDR3 ;HL*1.6*93 34 ; 35 ; patch HL*1.6*120 start 36 ; escape delimiters for SERAPP and CLNTAPP 37 ; escape component separator if the field is not consisted 38 ; of 3 components 39 S EC(1)=$E(EC,1) 40 S EC(2)=$E(EC,2) 41 S EC(3)=$E(EC,3) 42 S EC(4)=$E(EC,4) 43 S COMFLAG=1 44 I $L(SERAPP,$E(EC,1))=3 S COMFLAG=0 45 I (SERAPP[FS)!(SERAPP[EC(1))!(SERAPP[EC(2))!(SERAPP[EC(3))!(SERAPP[EC(4)) D 46 . S SERAPP=$$ESCAPE(SERAPP,COMFLAG) 47 S COMFLAG=1 48 I $L(CLNTAPP,$E(EC,1))=3 S COMFLAG=0 49 I (CLNTAPP[FS)!(CLNTAPP[EC(1))!(CLNTAPP[EC(2))!(CLNTAPP[EC(3))!(CLNTAPP[EC(4)) D 50 . S CLNTAPP=$$ESCAPE(CLNTAPP,COMFLAG) 51 ; patch HL*1.6*120 end 52 ; 53 S HLHDRI=1,HLHDR(1)="MSH"_FS_EC_FS_SERAPP,HLHDRL=$L(HLHDR(1)) 54 F X=SERFAC,CLNTAPP,CLNTFAC,HLDATE,SECURITY,MSGTYPE,HLID,HLPID,$P(PROT,U,9),"",$G(^HL(772,TXTP,1)),ACCACK,APPACK,CNTRY D MSH(X) 55 ;in preceeding line, "" is for sequence number - not supported 56 Q 57 ; 58 MSH(X) ;add X to HLHDR 59 S:HLHDRL+$L(X)>245 HLHDRI=HLHDRI+1,HLHDR(HLHDRI)="" 60 S HLHDR(HLHDRI)=HLHDR(HLHDRI)_FS_X,HLHDRL=$L(HLHDR(HLHDRI)) 61 Q 62 BHSHDR(IEN,CLIENT,HLERROR) ; Create Batch Header Segment 63 ; The BHS has 12 segments, of which 4 are blank. 64 ; INPUT: IEN - IEN of entry in file #772 65 ; OUTPUT: HLHDR(1) and HLHDR(2) - the two lines with the 12 segs. 66 ; ready for adding to a message directly. 67 N ACKTO,ACCACK,ACKMID,APPACK,BNAME,BSTATUS,BTACK,CHILD,CLNTAPP ;HL*1.6*80 68 N CLNTFAC,CNTRY,EC,EVNTYPE,FS,HLDATE,HLHDRI,HLHDRL,HLID,HLPID ;HL*1.6*80 - added HLPID 69 N PROT,PROTS,SECURITY,SEND,SERAPP,SERFAC,TXTP,TXTP0,X ;HL*1.6*80 70 N COMFLAG ; patch HL*1.6*120 71 S HLERROR="" 72 ; 73 S HLPARAM=$$PARAM^HLCS2 74 D VAR Q:$G(HLERROR)]"" 75 ; The following line commented by HL*1.6*72 76 ;I $D(^HLMA(IEN)) S $P(^HLMA(IEN,0),U,13)=MSGTYPE,$P(^HLMA(IEN,0),U,14)=$G(EVNTYPE) 77 ; 78 ;Append event type 79 I $G(EVNTYPE)]"" S MSGTYPE=MSGTYPE_$E(EC,2)_EVNTYPE,(ACKMID,BTACK)="" 80 ;batch/name/id/type(#9)=null~process ID~msg type|evnt type~version~CA~AA 81 S BNAME=$E(EC,1)_HLPID_$E(EC,1)_MSGTYPE_$E(EC,1)_$P(PROT,U,9)_$E(EC,1)_ACCACK_$E(EC,1)_APPACK ;HL*1.6*80 82 ;for batch ACK 83 I ACKTO D S BTACK=X_$E(EC,1)_$P(BSTATUS,U,3) 84 . ;get msg id and status of message that is being ACKed 85 . S ACKMID=$P($G(^HLMA(ACKTO,0)),U,2),BSTATUS=$G(^HLMA(ACKTO,"P")) ;HL*1.6*80 86 . ;set type of ACK based on status 87 . S X=$S(ACKMID="":"AR",(BSTATUS>3)&(BSTATUS<8):"AE",1:"AA") 88 ; 89 D RESET^HLCSHDR3 ;HL*1.6*93 90 ; 91 ; patch HL*1.6*120 start 92 ; escape delimiters for SERAPP and CLNTAPP 93 ; escape component separator if the field is not consisted 94 ; of 3 components 95 S EC(1)=$E(EC,1) 96 S EC(2)=$E(EC,2) 97 S EC(3)=$E(EC,3) 98 S EC(4)=$E(EC,4) 99 S COMFLAG=1 100 I $L(SERAPP,$E(EC,1))=3 S COMFLAG=0 101 I (SERAPP[FS)!(SERAPP[EC(1))!(SERAPP[EC(2))!(SERAPP[EC(3))!(SERAPP[EC(4)) D 102 . S SERAPP=$$ESCAPE(SERAPP,COMFLAG) 103 S COMFLAG=1 104 I $L(CLNTAPP,$E(EC,1))=3 S COMFLAG=0 105 I (CLNTAPP[FS)!(CLNTAPP[EC(1))!(CLNTAPP[EC(2))!(CLNTAPP[EC(3))!(CLNTAPP[EC(4)) D 106 . S CLNTAPP=$$ESCAPE(CLNTAPP,COMFLAG) 107 ; patch HL*1.6*120 end 108 ; 109 S HLHDRI=1,HLHDR(1)="BHS"_FS_EC_FS_SERAPP,HLHDRL=$L(HLHDR(1)) 110 F X=SERFAC,CLNTAPP,CLNTFAC,HLDATE,SECURITY,BNAME,BTACK,HLID,ACKMID D MSH(X) 111 Q 112 VAR ;Check input 113 N APPPRM,HLPROTS,HLPROT 114 S IEN=+$G(IEN) 115 I '$G(^HLMA(IEN,0)) S HLERROR="Valid pointer to Message Administration file (#772) not passed" Q 116 I '$G(CLIENT) S HLERROR="Could not determine receiving application" Q 117 ;Get child, text pointer,text entry, and sending app. 118 S CHILD=$G(^HLMA(IEN,0)),SEND=+$P($G(^(0)),U,11),TXTP=+CHILD,TXTP0=$G(^HL(772,TXTP,0)) 119 I ('SEND) S HLERROR="Could not determine sending application" Q 120 ;Get info for sending & receiving applications 121 D APPPRM^HLUTIL2(CLIENT),APPPRM^HLUTIL2(SEND) 122 ;Get name of sending application, facility, and country 123 S SERAPP=$P(APPPRM(SEND,0),U),SERFAC=$P(APPPRM(SEND,0),U,2),CNTRY=$P(APPPRM(SEND,0),U,3) 124 ;Get name of receiving application and facility 125 S CLNTAPP=$P(APPPRM(CLIENT,0),U),CLNTFAC=$P(APPPRM(CLIENT,0),U,2) 126 ; 127 ; patch HL*1.6*120 128 ; for dynamic addressing, overide the receiving facility from the 129 ; 3rd component of HLL("LINKS") array 130 I $G(HLP("REC-FACILITY"))]"" S CLNTFAC=HLP("REC-FACILITY") 131 ; 132 ;Get field separator & encoding characters 133 S FS=APPPRM(SEND,"FS"),EC=APPPRM(SEND,"EC") 134 S:(EC="") EC="~|\&" S:(FS="") FS="^" 135 ;Determine if it's a response/ACK to another message 136 S ACKTO=+$P(CHILD,U,10) 137 ;subscriber protocol is from child (file 773) 138 ;If response, get MType from subscriber 139 S HLPROTS=+$P(CHILD,U,8) 140 S PROTS=$$TYPE^HLUTIL2(HLPROTS) 141 I ACKTO S MSGTYPE=$P(PROTS,U,10),EVNTYPE=$P(PROTS,U,3),MSGEVN=$P(PROTS,U,4) 142 ;Get accept ack & application ack type (based on server protocol) it 143 ; is always in file 772, TXPT0 144 ;If original message, get MT from Event Driver Protocol 145 S HLPROT=+$P(TXTP0,U,10) 146 S PROT=$$TYPE^HLUTIL2(HLPROT) 147 S:'ACKTO MSGTYPE=$P(PROT,U,2),EVNTYPE=$P(PROT,U,3),MSGEVN=$P(PROT,U,4) 148 S ACCACK=$P(PROT,U,7),APPACK=$P(PROT,U,8) 149 ; 150 ; patch HL*1.6*122 151 ; setting the MSH-15 and MSH-16 from subscriber protocol 152 I HLPROTS,$P($G(^ORD(101,HLPROTS,773)),"^",5) D 153 . S ACCACK=$P(PROTS,U,7) 154 . S APPACK=$P(PROTS,U,8) 155 ; 156 PID ;Processing ID 157 ;I PID not 'debug' get from site params 158 ;If event driver set to 'debug' get from protocol 159 ;'production' or 'training' comes from site params 160 S HLPID=$P(PROT,U,5) 161 I $G(HLPID)'="D" S HLPID=$P(HLPARAM,U,3) 162 ; 163 ; patch HL*1.6*120: to include processing mode 164 I $G(HLP("PMOD"))]"",($G(HLTYPE)="M") D 165 . S HLPID=HLPID_$E($G(EC),1)_HLP("PMOD") 166 ; 167 I $G(HLPID)="" S HLERROR="Missing processing ID Site parameter." 168 ;acknowledgements have no application ack, link open no commit ack 169 I ACKTO S:APPACK]"" APPACK="NE" S:ACCACK]""&$G(HLTCPO) ACCACK="NE" 170 ;Get date/time, Message ID, and security 171 S HLDATE=+TXTP0,HLDATE=$$FMTHL7^XLFDT(HLDATE),HLID=$P(CHILD,U,2),SECURITY=$P(CHILD,U,9) 172 HDR23 ;generate extended facility field info based on 'facility required' 173 ;default format is INSTITUTION_HLCS_DOMAIN_HLCS_'DNS' 174 ;application parameter entry overrides default 175 N HLEP773,HLS773 176 S SERFAC=$G(SERFAC),CLNTFAC=$G(CLNTFAC) 177 S HLEP773=+$G(^ORD(101,HLPROTS,773)) 178 S HLS773=+$P($G(^ORD(101,HLPROTS,773)),U,2) 179 Q:'HLEP773&('HLS773) 180 D GEN^HLCSHDR2 181 I ACKTO D Q 182 .;Find original message 183 .S X=$G(^HLMA(ACKTO,"MSH",1,0)) ;Find header in TCP nodes 184 .I X["MSH" D 185 ..; 186 ..; patch HL*1.6*120 start 187 .. N HLEC 188 ..S HLFS=$E(X,4),HLEC=$E(X,5) 189 ..S SENDFAC=$P(X,HLFS,4),RECFAC=$P(X,HLFS,6) ;from original msg 190 ..S CLNTFAC=SENDFAC,SERFAC=RECFAC ;reverse facility info 191 ..S EC("COMPONENT")=$E($G(EC),1) 192 ..I $L(EC("COMPONENT"))=1,$L(HLEC)=1,EC("COMPONENT")'=HLEC D 193 ... ; change the the component separator in the sending and 194 ... ; receiving facilities for the outgoing message 195 ... S CLNTFAC=$TR(CLNTFAC,HLEC,EC("COMPONENT")) 196 ... S SERFAC=$TR(SERFAC,HLEC,EC("COMPONENT")) 197 ; patch HL*1.6*120 end 198 ; 199 I HLEP773,SERFAC="" D EP^HLCSHDR2 200 I HLS773,CLNTFAC="" D S^HLCSHDR2 201 Q 202 ; 203 ESCAPE(INPUT,COMPONET) ; 204 ; patch HL*1.6*120 - escape delimiters: 205 ; - field separator 206 ; - component separator 207 ; - repetition separator 208 ; - escape character 209 ; - subcomponent separator 210 ; 211 ; input: 212 ; INPUT - string data to be escaped 213 ; COMPONET - if 1, escape component separator 214 ; if 0, do not escape component separator 215 ; FS - field separator character 216 ; EC - encoding characters 217 ; result: return the escaped string 218 ; 219 N HLDATA,HLESCAPE,HLI,HLCHAR,HLEN,HLOUT,COMFLAG 220 S HLDATA=$G(INPUT) 221 S COMFLAG=$G(COMPONET) 222 Q:$L($G(FS))'=1 HLDATA 223 ; 224 ; patch HL*1.6*133 225 ; Q:$L($G(EC))'=4 HLDATA 226 Q:($L($G(EC))<3) HLDATA 227 Q:HLDATA']"" HLDATA 228 ; 229 S HLESCAPE=FS_EC 230 S HLESCAPE("F")=FS 231 S HLESCAPE("S")=$E(EC,1) 232 S HLESCAPE("R")=$E(EC,2) 233 S HLESCAPE("E")=$E(EC,3) 234 S HLESCAPE("T")=$E(EC,4) 235 S HLEN=$L(HLDATA) 236 S HLOUT="" 237 F HLI=1:1:HLEN D 238 . S HLCHAR=$E(HLDATA,HLI) 239 . I HLESCAPE[HLCHAR D Q 240 .. I HLCHAR=HLESCAPE("F") S HLOUT=HLOUT_HLESCAPE("E")_"F"_HLESCAPE("E") Q 241 .. I HLCHAR=HLESCAPE("S") D Q 242 ... I COMFLAG=1 S HLOUT=HLOUT_HLESCAPE("E")_"S"_HLESCAPE("E") Q 243 ... S HLOUT=HLOUT_HLCHAR 244 .. I HLCHAR=HLESCAPE("R") S HLOUT=HLOUT_HLESCAPE("E")_"R"_HLESCAPE("E") Q 245 .. I HLCHAR=HLESCAPE("E") S HLOUT=HLOUT_HLESCAPE("E")_"E"_HLESCAPE("E") Q 246 .. I HLCHAR=HLESCAPE("T") S HLOUT=HLOUT_HLESCAPE("E")_"T"_HLESCAPE("E") Q 247 . ; 248 . S HLOUT=HLOUT_HLCHAR 249 Q HLOUT 1 HLCSHDR1 ;SFIRMFO/RSD - Make HL7 header for TCP ;09/13/2006 2 ;;1.6;HEALTH LEVEL SEVEN;**19,57,59,72,80,93,120,133**;Oct 13, 1995;Build 13 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 HEADER(IEN,CLIENT,HLERROR) ; Create an HL7 MSH segment 5 ; 6 ;Input : IEN - Pointer to entry in Message Administration file (#773) 7 ; that HL7 MSH segment is being built for 8 ; CLIENT - IEN of the receiving application 9 ; HLERROR - Variable to return possible error text in 10 ; (pass by reference - only used when needed) 11 ; 12 ;Output : HLHDR(1) - HL7 MSH segment 13 ; HLHDR(2) - Continuation of HL7 MSH segment (if needed) 14 ; HLHDR(3) - Continuation of HL7 MSH segment (if needed) 15 ; 16 ;Notes : HLERROR will only be defined [on output] if an error occurs 17 ; : HLHDR() will not be defined [on output] if an error occurs 18 ; : HLHDR(2) & HLHDR(3) are continuation [or roll-over] nodes 19 ; and will only be used/defined when needed 20 ; 21 N ACKTO,ACCACK,APPACK,CHILD,CLNTAPP,CLNTFAC,CNTRY,EC,EVNTYPE,FS,HLDATE,HLHDRI,HLHDRL,HLID,HLPID,MSGTYPE,PROT,PROTS,SECURITY,SEND,SERAPP,SERFAC,TXTP,TXTP0,X,MSGEVN 22 N COMFLAG ; patch HL*1.6*120 23 S HLERROR="" 24 S HLPARAM=$$PARAM^HLCS2 25 D VAR Q:$G(HLERROR)]"" 26 ; The following line commented by HL*1.6*72 27 ;I $D(^HLMA(IEN)) S $P(^HLMA(IEN,0),U,13)=MSGTYPE,$P(^HLMA(IEN,0),U,14)=$G(EVNTYPE) 28 ;Append event type 29 I $G(EVNTYPE)]"" S MSGTYPE=MSGTYPE_$E(EC,1)_EVNTYPE 30 ;Append message structure component 31 I $G(EVNTYPE)]"",$G(MSGEVN)]"" S MSGTYPE=MSGTYPE_$E(EC,1)_MSGEVN 32 ;Build MSH array 33 D RESET^HLCSHDR3 ;HL*1.6*93 34 ; 35 ; patch HL*1.6*120 start 36 ; escape delimiters for SERAPP and CLNTAPP 37 ; escape component separator if the field is not consisted 38 ; of 3 components 39 S EC(1)=$E(EC,1) 40 S EC(2)=$E(EC,2) 41 S EC(3)=$E(EC,3) 42 S EC(4)=$E(EC,4) 43 S COMFLAG=1 44 I $L(SERAPP,$E(EC,1))=3 S COMFLAG=0 45 I (SERAPP[FS)!(SERAPP[EC(1))!(SERAPP[EC(2))!(SERAPP[EC(3))!(SERAPP[EC(4)) D 46 . S SERAPP=$$ESCAPE(SERAPP,COMFLAG) 47 S COMFLAG=1 48 I $L(CLNTAPP,$E(EC,1))=3 S COMFLAG=0 49 I (CLNTAPP[FS)!(CLNTAPP[EC(1))!(CLNTAPP[EC(2))!(CLNTAPP[EC(3))!(CLNTAPP[EC(4)) D 50 . S CLNTAPP=$$ESCAPE(CLNTAPP,COMFLAG) 51 ; patch HL*1.6*120 end 52 ; 53 S HLHDRI=1,HLHDR(1)="MSH"_FS_EC_FS_SERAPP,HLHDRL=$L(HLHDR(1)) 54 F X=SERFAC,CLNTAPP,CLNTFAC,HLDATE,SECURITY,MSGTYPE,HLID,HLPID,$P(PROT,U,9),"",$G(^HL(772,TXTP,1)),ACCACK,APPACK,CNTRY D MSH(X) 55 ;in preceeding line, "" is for sequence number - not supported 56 Q 57 ; 58 MSH(X) ;add X to HLHDR 59 S:HLHDRL+$L(X)>245 HLHDRI=HLHDRI+1,HLHDR(HLHDRI)="" 60 S HLHDR(HLHDRI)=HLHDR(HLHDRI)_FS_X,HLHDRL=$L(HLHDR(HLHDRI)) 61 Q 62 BHSHDR(IEN,CLIENT,HLERROR) ; Create Batch Header Segment 63 ; The BHS has 12 segments, of which 4 are blank. 64 ; INPUT: IEN - IEN of entry in file #772 65 ; OUTPUT: HLHDR(1) and HLHDR(2) - the two lines with the 12 segs. 66 ; ready for adding to a message directly. 67 N ACKTO,ACCACK,ACKMID,APPACK,BNAME,BSTATUS,BTACK,CHILD,CLNTAPP ;HL*1.6*80 68 N CLNTFAC,CNTRY,EC,EVNTYPE,FS,HLDATE,HLHDRI,HLHDRL,HLID,HLPID ;HL*1.6*80 - added HLPID 69 N PROT,PROTS,SECURITY,SEND,SERAPP,SERFAC,TXTP,TXTP0,X ;HL*1.6*80 70 N COMFLAG ; patch HL*1.6*120 71 S HLERROR="" 72 ; 73 S HLPARAM=$$PARAM^HLCS2 74 D VAR Q:$G(HLERROR)]"" 75 ; The following line commented by HL*1.6*72 76 ;I $D(^HLMA(IEN)) S $P(^HLMA(IEN,0),U,13)=MSGTYPE,$P(^HLMA(IEN,0),U,14)=$G(EVNTYPE) 77 ; 78 ;Append event type 79 I $G(EVNTYPE)]"" S MSGTYPE=MSGTYPE_$E(EC,2)_EVNTYPE,(ACKMID,BTACK)="" 80 ;batch/name/id/type(#9)=null~process ID~msg type|evnt type~version~CA~AA 81 S BNAME=$E(EC,1)_HLPID_$E(EC,1)_MSGTYPE_$E(EC,1)_$P(PROT,U,9)_$E(EC,1)_ACCACK_$E(EC,1)_APPACK ;HL*1.6*80 82 ;for batch ACK 83 I ACKTO D S BTACK=X_$E(EC,1)_$P(BSTATUS,U,3) 84 . ;get msg id and status of message that is being ACKed 85 . S ACKMID=$P($G(^HLMA(ACKTO,0)),U,2),BSTATUS=$G(^HLMA(ACKTO,"P")) ;HL*1.6*80 86 . ;set type of ACK based on status 87 . S X=$S(ACKMID="":"AR",(BSTATUS>3)&(BSTATUS<8):"AE",1:"AA") 88 ; 89 D RESET^HLCSHDR3 ;HL*1.6*93 90 ; 91 ; patch HL*1.6*120 start 92 ; escape delimiters for SERAPP and CLNTAPP 93 ; escape component separator if the field is not consisted 94 ; of 3 components 95 S EC(1)=$E(EC,1) 96 S EC(2)=$E(EC,2) 97 S EC(3)=$E(EC,3) 98 S EC(4)=$E(EC,4) 99 S COMFLAG=1 100 I $L(SERAPP,$E(EC,1))=3 S COMFLAG=0 101 I (SERAPP[FS)!(SERAPP[EC(1))!(SERAPP[EC(2))!(SERAPP[EC(3))!(SERAPP[EC(4)) D 102 . S SERAPP=$$ESCAPE(SERAPP,COMFLAG) 103 S COMFLAG=1 104 I $L(CLNTAPP,$E(EC,1))=3 S COMFLAG=0 105 I (CLNTAPP[FS)!(CLNTAPP[EC(1))!(CLNTAPP[EC(2))!(CLNTAPP[EC(3))!(CLNTAPP[EC(4)) D 106 . S CLNTAPP=$$ESCAPE(CLNTAPP,COMFLAG) 107 ; patch HL*1.6*120 end 108 ; 109 S HLHDRI=1,HLHDR(1)="BHS"_FS_EC_FS_SERAPP,HLHDRL=$L(HLHDR(1)) 110 F X=SERFAC,CLNTAPP,CLNTFAC,HLDATE,SECURITY,BNAME,BTACK,HLID,ACKMID D MSH(X) 111 Q 112 VAR ;Check input 113 N APPPRM,HLPROTS,HLPROT 114 S IEN=+$G(IEN) 115 I '$G(^HLMA(IEN,0)) S HLERROR="Valid pointer to Message Administration file (#772) not passed" Q 116 I '$G(CLIENT) S HLERROR="Could not determine receiving application" Q 117 ;Get child, text pointer,text entry, and sending app. 118 S CHILD=$G(^HLMA(IEN,0)),SEND=+$P($G(^(0)),U,11),TXTP=+CHILD,TXTP0=$G(^HL(772,TXTP,0)) 119 I ('SEND) S HLERROR="Could not determine sending application" Q 120 ;Get info for sending & receiving applications 121 D APPPRM^HLUTIL2(CLIENT),APPPRM^HLUTIL2(SEND) 122 ;Get name of sending application, facility, and country 123 S SERAPP=$P(APPPRM(SEND,0),U),SERFAC=$P(APPPRM(SEND,0),U,2),CNTRY=$P(APPPRM(SEND,0),U,3) 124 ;Get name of receiving application and facility 125 S CLNTAPP=$P(APPPRM(CLIENT,0),U),CLNTFAC=$P(APPPRM(CLIENT,0),U,2) 126 ; 127 ; patch HL*1.6*120 128 ; for dynamic addressing, overide the receiving facility from the 129 ; 3rd component of HLL("LINKS") array 130 I $G(HLP("REC-FACILITY"))]"" S CLNTFAC=HLP("REC-FACILITY") 131 ; 132 ;Get field separator & encoding characters 133 S FS=APPPRM(SEND,"FS"),EC=APPPRM(SEND,"EC") 134 S:(EC="") EC="~|\&" S:(FS="") FS="^" 135 ;Determine if it's a response/ACK to another message 136 S ACKTO=+$P(CHILD,U,10) 137 ;subscriber protocol is from child (file 773) 138 ;If response, get MType from subscriber 139 S HLPROTS=+$P(CHILD,U,8) 140 S PROTS=$$TYPE^HLUTIL2(HLPROTS) 141 I ACKTO S MSGTYPE=$P(PROTS,U,10),EVNTYPE=$P(PROTS,U,3),MSGEVN=$P(PROTS,U,4) 142 ;Get accept ack & application ack type (based on server protocol) it 143 ; is always in file 772, TXPT0 144 ;If original message, get MT from Event Driver Protocol 145 S HLPROT=+$P(TXTP0,U,10) 146 S PROT=$$TYPE^HLUTIL2(HLPROT) 147 S:'ACKTO MSGTYPE=$P(PROT,U,2),EVNTYPE=$P(PROT,U,3),MSGEVN=$P(PROT,U,4) 148 S ACCACK=$P(PROT,U,7),APPACK=$P(PROT,U,8) 149 PID ;Processing ID 150 ;I PID not 'debug' get from site params 151 ;If event driver set to 'debug' get from protocol 152 ;'production' or 'training' comes from site params 153 S HLPID=$P(PROT,U,5) 154 I $G(HLPID)'="D" S HLPID=$P(HLPARAM,U,3) 155 ; 156 ; patch HL*1.6*120: to include processing mode 157 I $G(HLP("PMOD"))]"",($G(HLTYPE)="M") D 158 . S HLPID=HLPID_$E($G(EC),1)_HLP("PMOD") 159 ; 160 I $G(HLPID)="" S HLERROR="Missing processing ID Site parameter." 161 ;acknowledgements have no application ack, link open no commit ack 162 I ACKTO S:APPACK]"" APPACK="NE" S:ACCACK]""&$G(HLTCPO) ACCACK="NE" 163 ;Get date/time, Message ID, and security 164 S HLDATE=+TXTP0,HLDATE=$$FMTHL7^XLFDT(HLDATE),HLID=$P(CHILD,U,2),SECURITY=$P(CHILD,U,9) 165 HDR23 ;generate extended facility field info based on 'facility required' 166 ;default format is INSTITUTION_HLCS_DOMAIN_HLCS_'DNS' 167 ;application parameter entry overrides default 168 N HLEP773,HLS773 169 S SERFAC=$G(SERFAC),CLNTFAC=$G(CLNTFAC) 170 S HLEP773=+$G(^ORD(101,HLPROTS,773)) 171 S HLS773=+$P($G(^ORD(101,HLPROTS,773)),U,2) 172 Q:'HLEP773&('HLS773) 173 D GEN^HLCSHDR2 174 I ACKTO D Q 175 .;Find original message 176 .S X=$G(^HLMA(ACKTO,"MSH",1,0)) ;Find header in TCP nodes 177 .I X["MSH" D 178 ..; 179 ..; patch HL*1.6*120 start 180 .. N HLEC 181 ..S HLFS=$E(X,4),HLEC=$E(X,5) 182 ..S SENDFAC=$P(X,HLFS,4),RECFAC=$P(X,HLFS,6) ;from original msg 183 ..S CLNTFAC=SENDFAC,SERFAC=RECFAC ;reverse facility info 184 ..S EC("COMPONENT")=$E($G(EC),1) 185 ..I $L(EC("COMPONENT"))=1,$L(HLEC)=1,EC("COMPONENT")'=HLEC D 186 ... ; change the the component separator in the sending and 187 ... ; receiving facilities for the outgoing message 188 ... S CLNTFAC=$TR(CLNTFAC,HLEC,EC("COMPONENT")) 189 ... S SERFAC=$TR(SERFAC,HLEC,EC("COMPONENT")) 190 ; patch HL*1.6*120 end 191 ; 192 I HLEP773,SERFAC="" D EP^HLCSHDR2 193 I HLS773,CLNTFAC="" D S^HLCSHDR2 194 Q 195 ; 196 ESCAPE(INPUT,COMPONET) ; 197 ; patch HL*1.6*120 - escape delimiters: 198 ; - field separator 199 ; - component separator 200 ; - repetition separator 201 ; - escape character 202 ; - subcomponent separator 203 ; 204 ; input: 205 ; INPUT - string data to be escaped 206 ; COMPONET - if 1, escape component separator 207 ; if 0, do not escape component separator 208 ; FS - field separator character 209 ; EC - encoding characters 210 ; result: return the escaped string 211 ; 212 N HLDATA,HLESCAPE,HLI,HLCHAR,HLEN,HLOUT,COMFLAG 213 S HLDATA=$G(INPUT) 214 S COMFLAG=$G(COMPONET) 215 Q:$L($G(FS))'=1 HLDATA 216 ; 217 ; patch HL*1.6*133 218 ; Q:$L($G(EC))'=4 HLDATA 219 Q:($L($G(EC))<3) HLDATA 220 Q:HLDATA']"" HLDATA 221 ; 222 S HLESCAPE=FS_EC 223 S HLESCAPE("F")=FS 224 S HLESCAPE("S")=$E(EC,1) 225 S HLESCAPE("R")=$E(EC,2) 226 S HLESCAPE("E")=$E(EC,3) 227 S HLESCAPE("T")=$E(EC,4) 228 S HLEN=$L(HLDATA) 229 S HLOUT="" 230 F HLI=1:1:HLEN D 231 . S HLCHAR=$E(HLDATA,HLI) 232 . I HLESCAPE[HLCHAR D Q 233 .. I HLCHAR=HLESCAPE("F") S HLOUT=HLOUT_HLESCAPE("E")_"F"_HLESCAPE("E") Q 234 .. I HLCHAR=HLESCAPE("S") D Q 235 ... I COMFLAG=1 S HLOUT=HLOUT_HLESCAPE("E")_"S"_HLESCAPE("E") Q 236 ... S HLOUT=HLOUT_HLCHAR 237 .. I HLCHAR=HLESCAPE("R") S HLOUT=HLOUT_HLESCAPE("E")_"R"_HLESCAPE("E") Q 238 .. I HLCHAR=HLESCAPE("E") S HLOUT=HLOUT_HLESCAPE("E")_"E"_HLESCAPE("E") Q 239 .. I HLCHAR=HLESCAPE("T") S HLOUT=HLOUT_HLESCAPE("E")_"T"_HLESCAPE("E") Q 240 . ; 241 . S HLOUT=HLOUT_HLCHAR 242 Q HLOUT -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSHDR4.m
r613 r623 1 HLCSHDR4 ;SFIRMFO/LJA - Reset MSH Segment Fields ;10/09/2007 15:05 2 ;;1.6;HEALTH LEVEL SEVEN;**93,108,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified 4 ; 5 DEBUG(STORE) ; If HLP set up for debugging, capture VIEW... 6 ; HLMSH773 -- req 7 ; 8 N NOW,NUM,VAR,VARS,X,XTMP 9 ; 10 ; 1=some, 2=all 11 S STORE=$S(STORE=1:1,STORE=2:2,1:0) QUIT:'STORE ;-> 12 ; 13 S NOW=$$NOW^XLFDT 14 ; 15 S XTMP="HLCSHDR3 "_HLMSH773 16 S:'$D(^XTMP(XTMP,0)) ^XTMP(XTMP,0)=$$FMADD^XLFDT(NOW,0,4)_U_NOW_U_"Debug data created by DEBUG~HLCSHDR4" 17 ; 18 S NUM=$O(^XTMP(XTMP,":"),-1)+1 19 ; 20 ; Grab only critical (some) variables? 21 I STORE=1 D 22 . 23 . ; Sending information... 24 . S ^XTMP(XTMP,NUM,"SA")=HLMSHSAO_U_HLSAN_U_HLMSHSAN 25 . S ^XTMP(XTMP,NUM,"SF")=HLMSHSFO_U_HLSFN_U_HLMSHSFN 26 . 27 . ; Receiving information... 28 . S ^XTMP(XTMP,NUM,"RA")=HLMSHRAO_U_HLRAN_U_HLMSHRAN 29 . S ^XTMP(XTMP,NUM,"RF")=HLMSHRFO_U_HLRFN_U_HLMSHRFN 30 . 31 . ; Other information... (HLMSHPRE and HLMSHPRS hold 2 pieces!) 32 . S ^XTMP(XTMP,NUM,0)=NOW_U_HLMSH772_U_HLMSHPRE_U_HLMSHPRS 33 . S ^XTMP(XTMP,NUM,1)=HLMSHPRO 34 ; 35 ; Grab all variables? 36 I STORE=2 D 37 . S X="^XTMP("""_XTMP_""","_NUM_"," 38 . D DOLRO^%ZOSV 39 ; 40 QUIT 41 ; 42 SHOW N I773 43 F R !!,"Enter 773 IEN: ",I773:60 Q:I773'>0 D 44 . D SHOW773(I773) 45 QUIT 46 ; 47 SHOW773(I773) ; Show Dynamic Routing MSH Field Reset Details 48 N DIV,MSH,N90,N91 49 ; 50 S N90=$G(^HLMA(+I773,90)),N91=$G(^HLMA(+I773,91)) 51 I (N90_N91)']"" D QUIT ;-> 52 . W " no debug data found..." 53 ; 54 S MSH=$G(^HLMA(+I773,"MSH",1,0)) QUIT:MSH']"" ;-> 55 S DIV=$E(MSH,4) 56 ; 57 W !!,$$CJ^XLFSTR(" 773 # "_I773_" ",IOM,"=") 58 ; 59 D HDR(90,N90) 60 ; 61 W ! 62 D HDR(91,N91) 63 ; 64 W !!,$E(MSH,1,IOM) 65 ; 66 S C1=10,C2=30,C3=50 67 W !!,?C1,"Original (91)",?2,"Array (90)",?3,"MSH-Segment" 68 W !,$$REPEAT^XLFSTR("-",IOM) 69 D LINE("snd app",1,2,3) 70 D LINE("snd fac",3,3,4) 71 D LINE("rec app",5,4,5) 72 D LINE("rec fac",7,5,6) 73 ; 74 QUIT 75 ; 76 LINE(HDR,PCE1,PCE2,PCE3) ; Print one comparison line... 77 N P1,P2,P3,P4 78 S P1=$P(N91,U,PCE1),P2=$P(N90,U,PCE2),P3=$P(MSH,DIV,PCE3),P4=$P(N91,U,PCE1+1) 79 W !,HDR,":",?C1,P1,?2,P2,?3,P3,$S(P4]"":" ["_P4_"]",1:"") 80 QUIT 81 ; 82 HDR(NUM,DATA) N TXT 83 S TXT=$S(NUM=90:"Array (90)",NUM=91:"Original (91)",1:"") 84 W !,$$CJ^XLFSTR("---------- "_TXT_" ----------",IOM) 85 W $$CJ^XLFSTR(DATA,IOM) 86 QUIT 87 ; 88 SET(NEW,VAR,PCE) ; This subroutine performs these actions: 89 ; (1) Resets variables used in MSH segment 90 ; (2) Resets SERAPP and CLNTAPP in ^HLMA(#,0) 91 ; (3) Sets HLMSH91 nodes if overwrite occurs by ARRAY value. 92 ; If overwrite occurs by M code, the overwrite has already 93 ; been recorded in HLMSH91. (An overwrite produced by M code 94 ; is never overwritten by ARRAY data.) 95 ; 96 N IEN771N,IEN771O,HLTCP 97 ; 98 ; VAR is the name of the variable, and not it's value... 99 S PRE=@VAR ; PRE is now the value of the VAR (pre-overwrite) variable... 100 ; 101 ; Tests whether anything was changed... 102 QUIT:NEW']"" ;-> No new value exists to change to... 103 QUIT:NEW=PRE ;-> New value = Original value. Nothing changed... 104 ; 105 ; THIS IS THE EPICENTER!! This is where the variables used in 106 ; the MSH segment is overwritten. 107 S @VAR=NEW 108 ; 109 ; If PRE exists at this point, it was done by M code... 110 QUIT:$P(HLMSH91,U,PCE)]"" ;-> 111 ; 112 ; Change was made, but not by M code. Must be by array... 113 S $P(HLMSH91,U,PCE)=PRE,$P(HLMSH91,U,PCE+1)="A" 114 ; 115 ; patch HL*1.6*122: for "^" as component separater 116 S $P(HLMSH91,U,PCE+2,999)="" 117 ; 118 ; Upgrade ^HLMA(#,0)... 119 QUIT:PCE'=1&(PCE'=5) ;-> 120 ; 121 ; patch HL*1.6*108 start 122 ;S IEN771O=$O(^HL(771,"B",PRE,0)) QUIT:IEN771O'>0 ;-> Orig IEN 123 ;S IEN771N=$O(^HL(771,"B",NEW,0)) QUIT:IEN771N'>0 ;-> New IEN 124 S IEN771O=$O(^HL(771,"B",$E(PRE,1,30),0)) QUIT:IEN771O'>0 ;-> Orig IEN 125 S IEN771N=$O(^HL(771,"B",$E(NEW,1,30),0)) QUIT:IEN771N'>0 ;-> New IEN 126 ; patch HL*1.6*108 end 127 ; 128 QUIT:'IEN771O!('IEN771N)!(IEN771O=IEN771N) ;-> 129 S HLTCP=1 ; So 773 is updated... 130 I PCE=1 D UPDATE^HLTF0(MTIENS,"","O","","",IEN771N) 131 I PCE=5 D UPDATE^HLTF0(MTIENS,"","O","",IEN771N) 132 ; 133 QUIT 134 ; 135 FIELDS ; Display the Protocol file fields used by the VistA HL7 package, 136 ; when messages are received, to find the event and subscriber 137 ; protocols. 138 N BY,DIC,DIOEND,L 139 ; 140 D HD 141 ; 142 W ! 143 ; 144 S L="",DIC="^ORD(101,",BY="[HL PROTOCOL MESSAGING FIELDS]" 145 S DIOEND="D EXPL^HLCSHDR4" 146 D EN1^DIP 147 ; 148 Q 149 ; 150 HD W @IOF,$$CJ^XLFSTR("HL7 Protocol Messaging Fields",IOM) 151 W !,$$REPEAT^XLFSTR("=",IOM) 152 W !,"This 'HL7 Protocol Messaging Fields' report holds information that will help" 153 W !,"you determine the effects from changes to routing-related fields in the MSH" 154 W !,"segment when messages are sent between or within VistA HL7 systems." 155 W !,"Additional explanation is included at the bottom of the report." 156 Q 157 ; 158 EXPL N I,T QUIT:'$$EXPL1("Press RETURN for 'printout help', or '^' to exit... ") X "F I=1:1 S T=$T(EXPL+I) QUIT:T'["";;"" W !,$P(T,"";;"",2,99)" S I=$$EXPL1("Press RETURN to exit... ",1) 159 ;; 160 ;;When messages are received, their SENDING APPLICATION (MSH-3), MESSAGE 161 ;;TYPE (MSH-9), EVENT TYPE (MSH-9), and HL7 VERSION (MSH-12) fields are used to 162 ;;find the event driver protocol to be used in processing the just-received 163 ;;message. After the event protocol is found, that protocol's subscriber 164 ;;protocols are evaluated. The subscriber protocol with a RECEIVING 165 ;;APPLICATION value that matches the RECEIVING APPLICATION field in the MSH 166 ;;segment (MSH-5) is used. 167 ;; 168 ;;The first line for every "section" in the printout is the event driver 169 ;;protocol. Lines preceded by dashes, are related subscriber protocols. An 170 ;;example is shown below. 171 ;; 172 ;;Snd/Rec App's mTYP eTYP Ver Protocol Link 173 ;;------------------------------------------------------------------------------ 174 ;;AC-VOICERAD ORU R01 2.3 | AC ORU SERVER 175 ;;-AC-RADIOLOGY ORU R01 2.3 | AC ORU CLIENT NC TCP 176 ;; 177 ;;In this example, the 'AC-VOICERAD' line holds information for the 'AC ORU 178 ;;SERVER' event protocol. And, the '-AC-RADIOLOGY' line holds information for 179 ;;the 'AC ORU CLIENT' subscriber protocol. 180 Q 181 ; 182 EXPL1(PMT,FF) ; 183 N DIR,DIRUT,DTOUT,DUOUT,X,Y 184 QUIT:$E($G(IOST),1,2)'="C-" 1 ;-> 185 F X=1:1:$G(FF) W ! 186 S DIR(0)="EA",DIR("A")=PMT 187 D ^DIR 188 QUIT $S(Y=1:1,1:"") 189 ; 190 M ; Covered by Integration Agreement #3988 191 ; Application developers may call here when creating new messages, 192 ; when experimenting with M code to evaluate and conditionally change 193 ; routing-related fields. 194 ; 195 ; This API is called immediately before the MSH segment is created. 196 N IOINHI,IOINORM,MSHOLD,MSHNEW,MSHPRE,X 197 ; 198 S X="IOINHI;IOINORM" D ENDR^%ZISS 199 ; 200 S MSHOLD=$$MSHBUILD(0),MSHPRE=$$MSHBUILD(1) 201 W !!,"The original MSH segment is...",!!,IOINHI,MSHOLD,IOINORM 202 I MSHPRE'=MSHOLD D 203 . W !!,"The MSH segment, after modification by passed-in data, is..." 204 . W !!,IOINHI,MSHPRE,IOINORM 205 ; 206 D MVAR("SENDING APPLICATION","HLMSHSAN","SERAPP") 207 D MVAR("SENDING FACILITY","HLMSHSFN","SERFAC") 208 D MVAR("RECEIVING APPLICATION","HLMSHRAN","CLNTAPP") 209 D MVAR("RECEIVING FACILITY","HLMSHRFN","CLNTFAC") 210 ; 211 S MSHNEW=$$MSHBUILD 212 I MSHNEW'=MSHPRE D 213 . W !!,"Before your changes above, the modified MSH segment was..." 214 . W !!,IOINHI,MSHPRE,IOINORM 215 . W !!,"After your changes, the MSH segment is..." 216 . W !!,IOINHI,MSHNEW,IOINORM 217 W !!,$$REPEAT^XLFSTR("-",IOM) 218 W !!,"Message being sent..." 219 W ! 220 ; 221 Q 222 ; 223 MVAR(FLD,VAR,VARO) ; Generic resetting of variable... 224 ;IOINHI,IOINORM -- req 225 N ANS 226 W !!,?4,"Protocol-derived value of ",FLD,": " 227 W IOINHI,@VARO,IOINORM 228 W !,"Passed-in value of ",FLD," (",VAR,"): " 229 W IOINHI,@VAR,IOINORM 230 W !,?10,"Enter new value for ",FLD,": " 231 R ANS:60 Q:'$T ;-> 232 I ANS[U!(ANS']"") D 233 . W !!,?10,"No changes will be made..." 234 I ANS'[U&(ANS]"") D 235 . S @VAR=ANS 236 . W !!,?10,"The variable ",IOINHI,VAR,IOINORM 237 . W " will be changed to '",IOINHI,ANS,IOINORM,"'." 238 . W !,?10,"This value will be stored in the ",FLD 239 . W !,?10,"field in the MSH segment..." 240 . W !!,$$REPEAT^XLFSTR("-",IOM) 241 Q 242 ; 243 MSHBUILD(TYPE) ; Build MSH using current variables... 244 N MSH,PCE,RAN,RFN,SAN,SFN 245 S MSH="MSH"_FS_EC 246 I $G(TYPE)=0 F PCE=SERAPP,SERFAC,CLNTAPP,CLNTFAC,HLDATE,SECURITY,MSGTYPE,HLID,HLPID,$P(PROT,U,9),"",$G(^HL(772,TXTP,1)),ACCACK,APPACK,CNTRY D 247 . S MSH=MSH_FS_PCE 248 I $G(TYPE)'=0 D 249 . S SAN=HLMSHSAN,SAN=$S(SAN]"":SAN,1:SERAPP) 250 . S SFN=HLMSHSFN,SFN=$S(SFN]"":SFN,1:SERFAC) 251 . S RAN=HLMSHRAN,RAN=$S(RAN]"":RAN,1:CLNTAPP) 252 . S RFN=HLMSHRFN,RFN=$S(RFN]"":RFN,1:CLNTFAC) 253 . F PCE=SAN,SFN,RAN,RFN,HLDATE,SECURITY,MSGTYPE,HLID,HLPID,$P(PROT,U,9),"",$G(^HL(772,TXTP,1)),ACCACK,APPACK,CNTRY D 254 . . S MSH=MSH_FS_PCE 255 QUIT MSH 256 ; 257 EOR ;HLCSHDR4 - Reset MSH Segment Fields ;9/12/02 11:50 1 HLCSHDR4 ;SFIRMFO/LJA - Reset MSH Segment Fields ;3/24/2004 14:27 2 ;;1.6;HEALTH LEVEL SEVEN;**93,108**;Oct 13, 1995 3 ; 4 DEBUG(STORE) ; If HLP set up for debugging, capture VIEW... 5 ; HLMSH773 -- req 6 ; 7 N NOW,NUM,VAR,VARS,X,XTMP 8 ; 9 ; 1=some, 2=all 10 S STORE=$S(STORE=1:1,STORE=2:2,1:0) QUIT:'STORE ;-> 11 ; 12 S NOW=$$NOW^XLFDT 13 ; 14 S XTMP="HLCSHDR3 "_HLMSH773 15 S:'$D(^XTMP(XTMP,0)) ^XTMP(XTMP,0)=$$FMADD^XLFDT(NOW,0,4)_U_NOW_U_"Debug data created by DEBUG~HLCSHDR4" 16 ; 17 S NUM=$O(^XTMP(XTMP,":"),-1)+1 18 ; 19 ; Grab only critical (some) variables? 20 I STORE=1 D 21 . 22 . ; Sending information... 23 . S ^XTMP(XTMP,NUM,"SA")=HLMSHSAO_U_HLSAN_U_HLMSHSAN 24 . S ^XTMP(XTMP,NUM,"SF")=HLMSHSFO_U_HLSFN_U_HLMSHSFN 25 . 26 . ; Receiving information... 27 . S ^XTMP(XTMP,NUM,"RA")=HLMSHRAO_U_HLRAN_U_HLMSHRAN 28 . S ^XTMP(XTMP,NUM,"RF")=HLMSHRFO_U_HLRFN_U_HLMSHRFN 29 . 30 . ; Other information... (HLMSHPRE and HLMSHPRS hold 2 pieces!) 31 . S ^XTMP(XTMP,NUM,0)=NOW_U_HLMSH772_U_HLMSHPRE_U_HLMSHPRS 32 . S ^XTMP(XTMP,NUM,1)=HLMSHPRO 33 ; 34 ; Grab all variables? 35 I STORE=2 D 36 . S X="^XTMP("""_XTMP_""","_NUM_"," 37 . D DOLRO^%ZOSV 38 ; 39 QUIT 40 ; 41 SHOW N I773 42 F R !!,"Enter 773 IEN: ",I773:60 Q:I773'>0 D 43 . D SHOW773(I773) 44 QUIT 45 ; 46 SHOW773(I773) ; Show Dynamic Routing MSH Field Reset Details 47 N DIV,MSH,N90,N91 48 ; 49 S N90=$G(^HLMA(+I773,90)),N91=$G(^HLMA(+I773,91)) 50 I (N90_N91)']"" D QUIT ;-> 51 . W " no debug data found..." 52 ; 53 S MSH=$G(^HLMA(+I773,"MSH",1,0)) QUIT:MSH']"" ;-> 54 S DIV=$E(MSH,4) 55 ; 56 W !!,$$CJ^XLFSTR(" 773 # "_I773_" ",IOM,"=") 57 ; 58 D HDR(90,N90) 59 ; 60 W ! 61 D HDR(91,N91) 62 ; 63 W !!,$E(MSH,1,IOM) 64 ; 65 S C1=10,C2=30,C3=50 66 W !!,?C1,"Original (91)",?2,"Array (90)",?3,"MSH-Segment" 67 W !,$$REPEAT^XLFSTR("-",IOM) 68 D LINE("snd app",1,2,3) 69 D LINE("snd fac",3,3,4) 70 D LINE("rec app",5,4,5) 71 D LINE("rec fac",7,5,6) 72 ; 73 QUIT 74 ; 75 LINE(HDR,PCE1,PCE2,PCE3) ; Print one comparison line... 76 N P1,P2,P3,P4 77 S P1=$P(N91,U,PCE1),P2=$P(N90,U,PCE2),P3=$P(MSH,DIV,PCE3),P4=$P(N91,U,PCE1+1) 78 W !,HDR,":",?C1,P1,?2,P2,?3,P3,$S(P4]"":" ["_P4_"]",1:"") 79 QUIT 80 ; 81 HDR(NUM,DATA) N TXT 82 S TXT=$S(NUM=90:"Array (90)",NUM=91:"Original (91)",1:"") 83 W !,$$CJ^XLFSTR("---------- "_TXT_" ----------",IOM) 84 W $$CJ^XLFSTR(DATA,IOM) 85 QUIT 86 ; 87 SET(NEW,VAR,PCE) ; This subroutine performs these actions: 88 ; (1) Resets variables used in MSH segment 89 ; (2) Resets SERAPP and CLNTAPP in ^HLMA(#,0) 90 ; (3) Sets HLMSH91 nodes if overwrite occurs by ARRAY value. 91 ; If overwrite occurs by M code, the overwrite has already 92 ; been recorded in HLMSH91. (An overwrite produced by M code 93 ; is never overwritten by ARRAY data.) 94 ; 95 N IEN771N,IEN771O,HLTCP 96 ; 97 ; VAR is the name of the variable, and not it's value... 98 S PRE=@VAR ; PRE is now the value of the VAR (pre-overwrite) variable... 99 ; 100 ; Tests whether anything was changed... 101 QUIT:NEW']"" ;-> No new value exists to change to... 102 QUIT:NEW=PRE ;-> New value = Original value. Nothing changed... 103 ; 104 ; THIS IS THE EPICENTER!! This is where the variables used in 105 ; the MSH segment is overwritten. 106 S @VAR=NEW 107 ; 108 ; If PRE exists at this point, it was done by M code... 109 QUIT:$P(HLMSH91,U,PCE)]"" ;-> 110 ; 111 ; Change was made, but not by M code. Must be by array... 112 S $P(HLMSH91,U,PCE)=PRE,$P(HLMSH91,U,PCE+1)="A" 113 ; 114 ; Upgrade ^HLMA(#,0)... 115 QUIT:PCE'=1&(PCE'=5) ;-> 116 ; 117 ; patch HL*1.6*108 start 118 ;S IEN771O=$O(^HL(771,"B",PRE,0)) QUIT:IEN771O'>0 ;-> Orig IEN 119 ;S IEN771N=$O(^HL(771,"B",NEW,0)) QUIT:IEN771N'>0 ;-> New IEN 120 S IEN771O=$O(^HL(771,"B",$E(PRE,1,30),0)) QUIT:IEN771O'>0 ;-> Orig IEN 121 S IEN771N=$O(^HL(771,"B",$E(NEW,1,30),0)) QUIT:IEN771N'>0 ;-> New IEN 122 ; patch HL*1.6*108 end 123 ; 124 QUIT:'IEN771O!('IEN771N)!(IEN771O=IEN771N) ;-> 125 S HLTCP=1 ; So 773 is updated... 126 I PCE=1 D UPDATE^HLTF0(MTIENS,"","O","","",IEN771N) 127 I PCE=5 D UPDATE^HLTF0(MTIENS,"","O","",IEN771N) 128 ; 129 QUIT 130 ; 131 FIELDS ; Display the Protocol file fields used by the VistA HL7 package, 132 ; when messages are received, to find the event and subscriber 133 ; protocols. 134 N BY,DIC,DIOEND,L 135 ; 136 D HD 137 ; 138 W ! 139 ; 140 S L="",DIC="^ORD(101,",BY="[HL PROTOCOL MESSAGING FIELDS]" 141 S DIOEND="D EXPL^HLCSHDR4" 142 D EN1^DIP 143 ; 144 Q 145 ; 146 HD W @IOF,$$CJ^XLFSTR("HL7 Protocol Messaging Fields",IOM) 147 W !,$$REPEAT^XLFSTR("=",IOM) 148 W !,"This 'HL7 Protocol Messaging Fields' report holds information that will help" 149 W !,"you determine the effects from changes to routing-related fields in the MSH" 150 W !,"segment when messages are sent between or within VistA HL7 systems." 151 W !,"Additional explanation is included at the bottom of the report." 152 Q 153 ; 154 EXPL N I,T QUIT:'$$EXPL1("Press RETURN for 'printout help', or '^' to exit... ") X "F I=1:1 S T=$T(EXPL+I) QUIT:T'["";;"" W !,$P(T,"";;"",2,99)" S I=$$EXPL1("Press RETURN to exit... ",1) 155 ;; 156 ;;When messages are received, their SENDING APPLICATION (MSH-3), MESSAGE 157 ;;TYPE (MSH-9), EVENT TYPE (MSH-9), and HL7 VERSION (MSH-12) fields are used to 158 ;;find the event driver protocol to be used in processing the just-received 159 ;;message. After the event protocol is found, that protocol's subscriber 160 ;;protocols are evaluated. The subscriber protocol with a RECEIVING 161 ;;APPLICATION value that matches the RECEIVING APPLICATION field in the MSH 162 ;;segment (MSH-5) is used. 163 ;; 164 ;;The first line for every "section" in the printout is the event driver 165 ;;protocol. Lines preceded by dashes, are related subscriber protocols. An 166 ;;example is shown below. 167 ;; 168 ;;Snd/Rec App's mTYP eTYP Ver Protocol Link 169 ;;------------------------------------------------------------------------------ 170 ;;AC-VOICERAD ORU R01 2.3 | AC ORU SERVER 171 ;;-AC-RADIOLOGY ORU R01 2.3 | AC ORU CLIENT NC TCP 172 ;; 173 ;;In this example, the 'AC-VOICERAD' line holds information for the 'AC ORU 174 ;;SERVER' event protocol. And, the '-AC-RADIOLOGY' line holds information for 175 ;;the 'AC ORU CLIENT' subscriber protocol. 176 Q 177 ; 178 EXPL1(PMT,FF) ; 179 N DIR,DIRUT,DTOUT,DUOUT,X,Y 180 QUIT:$E($G(IOST),1,2)'="C-" 1 ;-> 181 F X=1:1:$G(FF) W ! 182 S DIR(0)="EA",DIR("A")=PMT 183 D ^DIR 184 QUIT $S(Y=1:1,1:"") 185 ; 186 M ; Covered by Integration Agreement #3988 187 ; Application developers may call here when creating new messages, 188 ; when experimenting with M code to evaluate and conditionally change 189 ; routing-related fields. 190 ; 191 ; This API is called immediately before the MSH segment is created. 192 N IOINHI,IOINORM,MSHOLD,MSHNEW,MSHPRE,X 193 ; 194 S X="IOINHI;IOINORM" D ENDR^%ZISS 195 ; 196 S MSHOLD=$$MSHBUILD(0),MSHPRE=$$MSHBUILD(1) 197 W !!,"The original MSH segment is...",!!,IOINHI,MSHOLD,IOINORM 198 I MSHPRE'=MSHOLD D 199 . W !!,"The MSH segment, after modification by passed-in data, is..." 200 . W !!,IOINHI,MSHPRE,IOINORM 201 ; 202 D MVAR("SENDING APPLICATION","HLMSHSAN","SERAPP") 203 D MVAR("SENDING FACILITY","HLMSHSFN","SERFAC") 204 D MVAR("RECEIVING APPLICATION","HLMSHRAN","CLNTAPP") 205 D MVAR("RECEIVING FACILITY","HLMSHRFN","CLNTFAC") 206 ; 207 S MSHNEW=$$MSHBUILD 208 I MSHNEW'=MSHPRE D 209 . W !!,"Before your changes above, the modified MSH segment was..." 210 . W !!,IOINHI,MSHPRE,IOINORM 211 . W !!,"After your changes, the MSH segment is..." 212 . W !!,IOINHI,MSHNEW,IOINORM 213 W !!,$$REPEAT^XLFSTR("-",IOM) 214 W !!,"Message being sent..." 215 W ! 216 ; 217 Q 218 ; 219 MVAR(FLD,VAR,VARO) ; Generic resetting of variable... 220 ;IOINHI,IOINORM -- req 221 N ANS 222 W !!,?4,"Protocol-derived value of ",FLD,": " 223 W IOINHI,@VARO,IOINORM 224 W !,"Passed-in value of ",FLD," (",VAR,"): " 225 W IOINHI,@VAR,IOINORM 226 W !,?10,"Enter new value for ",FLD,": " 227 R ANS:60 Q:'$T ;-> 228 I ANS[U!(ANS']"") D 229 . W !!,?10,"No changes will be made..." 230 I ANS'[U&(ANS]"") D 231 . S @VAR=ANS 232 . W !!,?10,"The variable ",IOINHI,VAR,IOINORM 233 . W " will be changed to '",IOINHI,ANS,IOINORM,"'." 234 . W !,?10,"This value will be stored in the ",FLD 235 . W !,?10,"field in the MSH segment..." 236 . W !!,$$REPEAT^XLFSTR("-",IOM) 237 Q 238 ; 239 MSHBUILD(TYPE) ; Build MSH using current variables... 240 N MSH,PCE,RAN,RFN,SAN,SFN 241 S MSH="MSH"_FS_EC 242 I $G(TYPE)=0 F PCE=SERAPP,SERFAC,CLNTAPP,CLNTFAC,HLDATE,SECURITY,MSGTYPE,HLID,HLPID,$P(PROT,U,9),"",$G(^HL(772,TXTP,1)),ACCACK,APPACK,CNTRY D 243 . S MSH=MSH_FS_PCE 244 I $G(TYPE)'=0 D 245 . S SAN=HLMSHSAN,SAN=$S(SAN]"":SAN,1:SERAPP) 246 . S SFN=HLMSHSFN,SFN=$S(SFN]"":SFN,1:SERFAC) 247 . S RAN=HLMSHRAN,RAN=$S(RAN]"":RAN,1:CLNTAPP) 248 . S RFN=HLMSHRFN,RFN=$S(RFN]"":RFN,1:CLNTFAC) 249 . F PCE=SAN,SFN,RAN,RFN,HLDATE,SECURITY,MSGTYPE,HLID,HLPID,$P(PROT,U,9),"",$G(^HL(772,TXTP,1)),ACCACK,APPACK,CNTRY D 250 . . S MSH=MSH_FS_PCE 251 QUIT MSH 252 ; 253 EOR ;HLCSHDR4 - Reset MSH Segment Fields ;9/12/02 11:50 -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSIN.m
r613 r623 1 HLCSIN ;ALB/JRP - INCOMING FILER;01-MAY-95 ;03/17/2008 17:15 2 ;;1.6;HEALTH LEVEL SEVEN;**2,30,14,19,62,109,115,122,140**;Oct 13, 1995;Build 5 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 STARTIN ;Main entry point for incoming background filer 5 ;Create/find entry denoting this filer in the INCOMING FILER TASK 6 ; NUMBER multiple (field #20) of the HL COMMUNICATION SERVER PARAMETER 7 ; file (#869.3) 8 N HLFLG,HLEXIT,HLPTRFLR 9 ; 10 ; patch HL*1.6*122 11 ;; N HLDUZ,DUZ ; patch HL*1.6*122 TEST v2: DUZ code removed 12 N HLDUZ 13 S HLDUZ=+$G(DUZ) 14 ; 15 S HLPTRFLR=+$$CRTFLR^HLCSUTL1(ZTSK,"IN") 16 ;Loop through Logical Links and check for incoming messages 17 S HLEXIT=0 18 ; patch HL*1.6*122 TEST v2: DUZ code removed 19 ; patch HL*1.6*122, set DUZ for application proxy user 20 ;; D PROXY^HLCSTCP4 21 S HLPTRFLR("$J")=$J 22 F D Q:HLEXIT 23 . S HLFLG=0 24 . D DEFACK(.HLPTRFLR,.HLFLG,.HLEXIT) Q:HLEXIT 25 . D ACKNOW(.HLPTRFLR,.HLFLG,.HLEXIT) Q:HLEXIT 26 . Q:HLFLG 27 . I $$HDIFF^XLFDT($H,$G(HLPTRFLR("LASTDEL")),2)>3600 D Q 28 . . S HLPTRFLR("LASTDEL")=$H ; maintain queue sizes 29 . . D DELQUE(.HLPTRFLR,.HLEXIT) ; no more than once an hour. 30 . ; patch HL*1.6*122 31 . ; H 5 32 . H 1 33 . D CHKUPD(.HLPTRFLR,.HLEXIT) Q:HLEXIT 34 S ZTSTOP=1 ;Asked to stop 35 D DELFLR^HLCSUTL1(HLPTRFLR,"IN") ;Delete entry denoting this filer 36 S ZTREQ="@" 37 Q 38 DEFACK(HLPTRFLR,HLFLG,HLEXIT) ; Process TCP links with a deferred response 39 N HLXX,HLD0,HLPCT 40 S HLXX=0 41 F S HLXX=$O(^HLMA("AC","I",HLXX)) Q:'HLXX D Q:HLEXIT 42 . ; HL*1.6*122, check the in-queue stop flag 43 . Q:$P($G(^HLCS(870,HLXX,0)),"^",9) 44 . D CHKUPD(.HLPTRFLR,.HLEXIT) Q:HLEXIT 45 . ; patch HL*1.6*109: Does another filer have this? 46 . ; L +^HLMA("AC","I",HLXX):0 Q:'$T 47 . ; patch HL*1.6*140 - change the lock node, it conflicts with 48 . ; lock defined in routine, HLCSREP. 49 . ; L +^HLMA("AC","I",HLXX):2 Q:'$T ; patch HL*1.6*122 50 . L +^HLMA("IN-FILER","AC","I",HLXX):2 Q:'$T ; patch HL*1.6*122 51 . S HLD0=0,HLFLG=1 52 . ; HL*1.6*109 changes in for loop below, and post-quit code placed 53 . ; on following lines. 54 . S HLPCT=0 ; Counter whether filer should stop every 100th entry. 55 .;**109 - insure queue last processed at least 2 seconds ago 56 . ; patch HL*1.6*140 57 . ; I ($$HDIFF^XLFDT($H,$G(^XTMP("HL7-AC","I",HLXX)),2)<2) L -^HLMA("AC","I",HLXX) Q 58 . I ($$HDIFF^XLFDT($H,$G(^XTMP("HL7-AC","I",HLXX)),2)<2) L -^HLMA("IN-FILER","AC","I",HLXX) Q 59 . F S HLD0=$O(^HLMA("AC","I",HLXX,HLD0)) Q:'HLD0!(HLEXIT) D 60 .. ; patch HL*1.6*122 start 61 .. ; patch HL*1.6*122 TEST v2: DUZ code removed 62 .. ; DUZ comparison/reset for application proxy user 63 .. ;; D HLDUZ^HLCSTCP4 64 .. D HLDUZ2^HLCSTCP4 65 .. ; protect HLDUZ 66 .. N HLDUZ 67 .. S HLPCT=HLPCT+1 68 .. I '(HLPCT#100) D CHKUPD(.HLPTRFLR,.HLEXIT) Q:HLEXIT 69 .. ; L +^HLMA(HLD0):0 Q:'$T 70 .. F L +^HLMA(HLD0):30 Q:$T H 1 71 .. I '$$CHECKAC("I",HLXX,HLD0) L -^HLMA(HLD0) Q ;-> Quit if not a valid AC xref 72 .. D DEFACK^HLTP3(HLXX,HLD0) 73 .. D DEQUE^HLCSREP(HLXX,"I",HLD0) 74 .. L -^HLMA(HLD0) 75 . ; patch HL*1.6*122 end 76 . ;**109 -add dt/tm stamp to time queue last processed 77 . S ^XTMP("HL7-AC","I",HLXX)=$H 78 . ;**109 -unlock the queue 79 . ; patch HL*1.6*140 80 . ; L -^HLMA("AC","I",HLXX) 81 . L -^HLMA("IN-FILER","AC","I",HLXX) 82 Q 83 ; 84 CHECKAC(WAY,IEN870,IEN773) ; If AC xref shouldn't exist, kill it... 85 ; 86 ; Check status and if 3 (processed) kill XREF... 87 I $P($G(^HLMA(+IEN773,"P")),U)=3 D QUIT "" ;-> 88 . D DEQUE^HLCSREP(IEN870,WAY,IEN773) 89 ; 90 ; Add other checks here in the future... 91 ; 92 Q 1 93 ; 94 ACKNOW(HLPTRFLR,HLFLG,HLEXIT) ; Process Logical Link's IN-queue for received message 95 N HLXX,HLD0,HLD1 96 S HLXX=0 97 F S HLXX=$O(^HLCS(870,"AISTAT","P",HLXX)) Q:'HLXX D Q:HLEXIT 98 . ; HL*1.6*122, check the in-queue stop flag 99 . Q:$P($G(^HLCS(870,HLXX,0)),"^",9) 100 . D CHKUPD(.HLPTRFLR,.HLEXIT) Q:HLEXIT 101 . ; HL*1.6*109: Does another filer have this? 102 . ; L +^HLCS(870,HLXX,"INFILER"):0 Q:'$T 103 . L +^HLCS(870,HLXX,"INFILER"):2 Q:'$T ; patch HL*1.6*122 104 . F D CHKUPD(.HLPTRFLR,.HLEXIT) Q:HLEXIT S HLD0=$$DEQUEUE^HLCSQUE(HLXX,"IN") Q:+HLD0<0 D 105 .. ; 106 .. ; patch HL*1.6*122 start 107 .. ; clean variables except Kernel related variables 108 .. D 109 ... ; protect variables defined in STARTIN^HLCSIN 110 ... N HLFLG,HLEXIT,HLPTRFLR 111 ... N HLDUZ 112 ... ; protect variables defined in ACKNOW^HLCSIN 113 ... N HLXX,HLD0,HLD1 114 ... D KILL^XUSCLEAN 115 .. ; 116 .. ; patch HL*1.6*122 TEST v2: DUZ code removed 117 .. ; DUZ comparison/reset for application proxy user 118 .. ;; D HLDUZ^HLCSTCP4 119 .. D HLDUZ2^HLCSTCP4 120 .. ; protect HLDUZ 121 .. N HLDUZ 122 .. ;Make sure message is ready to be received 123 .. S HLFLG=1 124 .. S HLD1=$P(HLD0,"^",2) 125 .. S HLD0=+HLD0 ; At this point, HLD0=HLXX 126 .. I $P($G(^HLCS(870,HLD0,1,HLD1,0)),"^",3)'="A" D Q 127 ... D MONITOR^HLCSDR2("D",2,HLD0,HLD1,"IN") ;Set status to DONE 128 .. D RECEIVE^HLMA0(HLD0,HLD1) ;Process received message 129 .. D MONITOR^HLCSDR2("D",2,HLD0,HLD1,"IN") ;Set status to DONE 130 . ; patch HL*1.6*122 end 131 . I HLD0<0,$D(^HLCS(870,"AISTAT","P",HLXX)) D 132 . . S HLD1=0 ; Make sure there aren't any loose xrefs hanging around. 133 . . F S HLD1=$O(^HLCS(870,"AISTAT","P",HLXX,HLD1)) Q:'HLD1 D 134 . . . ;I '$D(^HLCS(870,HLXX,1,HLD1,0)) K ^HLCS(870,"AISTAT","P",HLXX,HLD1) 135 . . . I $P($G(^HLCS(870,HLXX,1,HLD1,0)),U,2)'="P" K ^HLCS(870,"AISTAT","P",HLXX,HLD1) 136 . L -^HLCS(870,HLXX,"INFILER") 137 Q 138 DELQUE(HLPTRFLR,HLEXIT) ; Delete messages outside the 'queue size' window. 139 N HLDIR,HLXX,HLFRONT 140 S HLDIR=1,HLXX=0 141 F S HLXX=$O(^HLCS(870,HLXX)) Q:'HLXX D Q:HLEXIT 142 . D CHKUPD(.HLPTRFLR,.HLEXIT) Q:HLEXIT 143 . ; patch HL*1.6*122, comment out, no need to lock 144 . ; L +^HLCS(870,HLXX,"IN QUEUE FRONT POINTER"):0 Q:'$T 145 . S HLFRONT=$G(^HLCS(870,HLXX,"IN QUEUE FRONT POINTER")) 146 . ; patch HL*1.6*122, comment out 147 . ; L -^HLCS(870,HLXX,"IN QUEUE FRONT POINTER") 148 . D DELETE^HLCSQUE1(HLXX,HLDIR,HLFRONT) 149 Q 150 CHKUPD(HLPTRFLR,HLEXIT) ; 151 Q:$$HDIFF^XLFDT($H,$G(HLPTRFLR("LASTUP")),2)<15 152 D SETFLRDH^HLCSUTL1(HLPTRFLR,"IN") ; Update LAST KNOWN $H (field #.03) for filer 153 S HLPTRFLR("LASTUP")=$H 154 D CHK4STOP^HLCSUTL2(HLPTRFLR,"IN",.HLEXIT) Q:HLEXIT 155 Q 1 HLCSIN ;ALB/JRP - INCOMING FILER;01-MAY-95 ;11/15/2000 09:37 2 ;;1.6;HEALTH LEVEL SEVEN;**2,30,14,19,62,109,115**;Oct 13, 1995 3 STARTIN ;Main entry point for incoming background filer 4 ;Create/find entry denoting this filer in the INCOMING FILER TASK 5 ; NUMBER multiple (field #20) of the HL COMMUNICATION SERVER PARAMETER 6 ; file (#869.3) 7 ;N HLOGLINK,HLNODE,HLPARENT,HLST1,TMP ; These vbls aren't used! 8 N HLFLG,HLEXIT,HLPTRFLR 9 S HLPTRFLR=+$$CRTFLR^HLCSUTL1(ZTSK,"IN") 10 ;Loop through Logical Links and check for incoming messages 11 S HLEXIT=0 12 F D Q:HLEXIT 13 . S HLFLG=0 14 . D DEFACK(.HLPTRFLR,.HLFLG,.HLEXIT) Q:HLEXIT 15 . D ACKNOW(.HLPTRFLR,.HLFLG,.HLEXIT) Q:HLEXIT 16 . Q:HLFLG 17 . I $$HDIFF^XLFDT($H,$G(HLPTRFLR("LASTDEL")),2)>3600 D Q 18 . . S HLPTRFLR("LASTDEL")=$H ; maintain queue sizes 19 . . D DELQUE(.HLPTRFLR,.HLEXIT) ; no more than once an hour. 20 . H 5 21 . D CHKUPD(.HLPTRFLR,.HLEXIT) Q:HLEXIT 22 S ZTSTOP=1 ;Asked to stop 23 D DELFLR^HLCSUTL1(HLPTRFLR,"IN") ;Delete entry denoting this filer 24 S ZTREQ="@" 25 Q 26 DEFACK(HLPTRFLR,HLFLG,HLEXIT) ; Process TCP links with a deferred response 27 N HLXX,HLD0,HLPCT 28 S HLXX=0 29 F S HLXX=$O(^HLMA("AC","I",HLXX)) Q:'HLXX D Q:HLEXIT 30 . D CHKUPD(.HLPTRFLR,.HLEXIT) Q:HLEXIT 31 . ; HL*1.6*109 32 . L +^HLMA("AC","I",HLXX):0 Q:'$T ;*109*Does another filer have this? 33 . S HLD0=0,HLFLG=1 34 . ; HL*1.6*109 changes in for loop below, and post-quit code placed 35 . ; on following lines. 36 . S HLPCT=0 ; Counter whether filer should stop every 100th entry. 37 .;**109 - insure queue last processed at least 2 seconds ago 38 . I ($$HDIFF^XLFDT($H,$G(^XTMP("HL7-AC","I",HLXX)),2)<2) L -^HLMA("AC","I",HLXX) Q 39 . F S HLD0=$O(^HLMA("AC","I",HLXX,HLD0)) Q:'HLD0!(HLEXIT) D 40 . . S HLPCT=HLPCT+1 41 . . I '(HLPCT#100) D CHKUPD(.HLPTRFLR,.HLEXIT) Q:HLEXIT 42 . . L +^HLMA(HLD0):0 Q:'$T 43 . . I '$$CHECKAC("I",HLXX,HLD0) L -^HLMA(HLD0) Q ;-> Quit if not a valid AC xref 44 . . D DEFACK^HLTP3(HLXX,HLD0) 45 . . D DEQUE^HLCSREP(HLXX,"I",HLD0) 46 . . L -^HLMA(HLD0) 47 . ;**109 -add dt/tm stamp to time queue last processed 48 . S ^XTMP("HL7-AC","I",HLXX)=$H 49 . ;**109 -unlock the queue 50 . L -^HLMA("AC","I",HLXX) 51 Q 52 ; 53 CHECKAC(WAY,IEN870,IEN773) ; If AC xref shouldn't exist, kill it... 54 ; 55 ; Check status and if 3 (processed) kill XREF... 56 I $P($G(^HLMA(+IEN773,"P")),U)=3 D QUIT "" ;-> 57 . D DEQUE^HLCSREP(IEN870,WAY,IEN773) 58 ; 59 ; Add other checks here in the future... 60 ; 61 Q 1 62 ; 63 ACKNOW(HLPTRFLR,HLFLG,HLEXIT) ; Process Logical Link's IN-queue for received message 64 N HLXX,HLD0,HLD1 65 S HLXX=0 66 F S HLXX=$O(^HLCS(870,"AISTAT","P",HLXX)) Q:'HLXX D Q:HLEXIT 67 . D CHKUPD(.HLPTRFLR,.HLEXIT) Q:HLEXIT 68 .; HL*1.6*109 69 . L +^HLCS(870,HLXX,"INFILER"):0 Q:'$T ;Does another filer have this? 70 . F D CHKUPD(.HLPTRFLR,.HLEXIT) Q:HLEXIT S HLD0=$$DEQUEUE^HLCSQUE(HLXX,"IN") Q:+HLD0<0 D 71 . . ;Make sure message is ready to be received 72 . . S HLFLG=1 73 . . S HLD1=$P(HLD0,"^",2) 74 . . S HLD0=+HLD0 ; At this point, HLD0=HLXX 75 . . I $P($G(^HLCS(870,HLD0,1,HLD1,0)),"^",3)'="A" D Q 76 . . . D MONITOR^HLCSDR2("D",2,HLD0,HLD1,"IN") ;Set status to DONE 77 . . D RECEIVE^HLMA0(HLD0,HLD1) ;Process received message 78 . . D MONITOR^HLCSDR2("D",2,HLD0,HLD1,"IN") ;Set status to DONE 79 . I HLD0<0,$D(^HLCS(870,"AISTAT","P",HLXX)) D 80 . . S HLD1=0 ; Make sure there aren't any loose xrefs hanging around. 81 . . F S HLD1=$O(^HLCS(870,"AISTAT","P",HLXX,HLD1)) Q:'HLD1 D 82 . . . ;I '$D(^HLCS(870,HLXX,1,HLD1,0)) K ^HLCS(870,"AISTAT","P",HLXX,HLD1) 83 . . . I $P($G(^HLCS(870,HLXX,1,HLD1,0)),U,2)'="P" K ^HLCS(870,"AISTAT","P",HLXX,HLD1) 84 . L -^HLCS(870,HLXX,"INFILER") 85 Q 86 DELQUE(HLPTRFLR,HLEXIT) ; Delete messages outside the 'queue size' window. 87 N HLDIR,HLXX,HLFRONT 88 S HLDIR=1,HLXX=0 89 F S HLXX=$O(^HLCS(870,HLXX)) Q:'HLXX D Q:HLEXIT 90 . D CHKUPD(.HLPTRFLR,.HLEXIT) Q:HLEXIT 91 . L +^HLCS(870,HLXX,"IN QUEUE FRONT POINTER"):0 Q:'$T 92 . S HLFRONT=$G(^HLCS(870,HLXX,"IN QUEUE FRONT POINTER")) 93 . L -^HLCS(870,HLXX,"IN QUEUE FRONT POINTER") 94 . D DELETE^HLCSQUE1(HLXX,HLDIR,HLFRONT) 95 Q 96 CHKUPD(HLPTRFLR,HLEXIT) ; 97 Q:$$HDIFF^XLFDT($H,$G(HLPTRFLR("LASTUP")),2)<15 98 D SETFLRDH^HLCSUTL1(HLPTRFLR,"IN") ; Update LAST KNOWN $H (field #.03) for filer 99 S HLPTRFLR("LASTUP")=$H 100 D CHK4STOP^HLCSUTL2(HLPTRFLR,"IN",.HLEXIT) Q:HLEXIT 101 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSLM.m
r613 r623 1 HLCSLM ;SFCIOFO/AC - HL7 LINK MANAGER ;03/19/2008 10:01 2 ;;1.6;HEALTH LEVEL SEVEN;**49,57,109,123,140**;Oct 13, 1995;Build 5 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 EN ;Entry point for start up task 6 N %,HLEVLCHK,HLTSKCNT 7 F %=1:1:10 L +^HLCS("HLCSLM"):2 Q:$T 8 E Q 9 I $G(ZTQUEUED) S Y=$$PSET^%ZTLOAD(ZTQUEUED) 10 D INIT,SAVDOLRH 11 D SETNM^%ZOSV($E("HLmgr:"_$G(ZTQUEUED),1,15)) 12 ; 13 LOOP ; 14 D CHKQUE 15 I $$CKLMSTOP G EXIT 16 D SAVDOLRH 17 D CHECKMST^HLEVMST ;HL*1.6*109 - Make sure event monitor current 18 ; patch HL*1.6*140 19 ; H 10 20 H 5 21 G LOOP 22 ; 23 EXIT N HLJ,X 24 S X=1 25 F L +^HLCS(869.3,X,5):2 Q:$T 26 ;52=Link Manager task number 27 S HLJ(869.3,X_",",52)="@" 28 D FILE^HLDIE("","HLJ","","EXIT","HLCSLM") ;HL*1.6*109 29 L -^HLCS(869.3,X,5) 30 L -^HLCS("HLCSLM") 31 Q 32 ; 33 SAVDOLRH ;Save Last Known $H 34 N HLJ,X 35 S X=1 36 F L +^HLCS(869.3,X,5):2 Q:$T 37 ;54=LM LAST KNOWN $H 38 S HLJ(869.3,X_",",54)=$H 39 D FILE^HLDIE("","HLJ","","SAVDOLRH","HLCSLM") ;HL*1.6*109 40 L -^HLCS(869.3,X,5) 41 Q 42 ; 43 CHKQUE ;Check queues for messages to send 44 ;HLTSKCNT(logical link)=task #^$H 45 N HLDA,HLDP,HLMSG,HLTSK,Y 46 S (HLDA,HLMSG)="" 47 F HLDP=0:0 S HLDP=+$O(^HLMA("AC","O",HLDP)) Q:HLDP'>0 S HLMSG=+$O(^(HLDP,0)) I HLMSG D L -^HLCS("HLCSLSM",HLDP) 48 .;quit if persistent link 49 .Q:$P($G(^HLCS(870,HLDP,400)),U,4)="Y" 50 .L +^HLCS("HLCSLSM",HLDP):0 E K HLTSKCNT(HLDP) Q 51 .Q:'$$LLOK(+HLDP) 52 .;get tasknumber from file 870 and HLTSKCNT array 53 .S Y=$$TASKNUM(HLDP),HLTSK=$G(HLTSKCNT(HLDP)) 54 . ; 55 . ;patch HL*1.6*123 start 56 . S HLDP("TASK-ACTIVE")=0 57 . ; 58 . I Y D 59 .. N ZTSK 60 .. S ZTSK=Y 61 .. ; Check status of task 62 .. D STAT^%ZTLOAD 63 .. I "12"[ZTSK(1) S HLDP("TASK-ACTIVE")=1 64 . Q:HLDP("TASK-ACTIVE") 65 . ; 66 . I HLTSK D 67 .. N ZTSK 68 .. S ZTSK=+HLTSK 69 .. ; Check status of task 70 .. D STAT^%ZTLOAD 71 .. I "12"[ZTSK(1) S HLDP("TASK-ACTIVE")=1 72 . Q:HLDP("TASK-ACTIVE") 73 . ; 74 . ;no tasknumber, link not running nor queued, task it 75 . I 'HLTSK!'Y D TASKLSUB(HLDP),SAVTSK(HLDP) Q 76 ; comment out the following lines 77 ; .;link was tasked, check time 78 ; .S Y=$P(HLTSK,U,2) 79 ; .;check that time task is less than 30 minutes 80 ; .Q:$$HDIFF^XLFDT($H,Y,2)<1800 81 ; .;shutdown and send alert 82 ; .D SDFLD^HLCSTCP,EXITS^HLCSTCP("Shutdown"),SNDALERT 83 ; loop through links that have been tasked 84 ; F HLDP=0:0 S HLDP=$O(HLTSKCNT(HLDP)) Q:HLDP'>0 K:'$D(^HLMA("AC","O",HLDP)) HLTSKCNT(HLDP) 85 F HLDP=0:0 S HLDP=$O(HLTSKCNT(HLDP)) Q:HLDP'>0 D 86 . N ZTSK 87 . S ZTSK=+HLTSKCNT(HLDP) 88 . ; Check status of task 89 . D STAT^%ZTLOAD 90 . ; kill HLTSKCNT(HLDP) if process is not active 91 . I "12"'[ZTSK(1) K HLTSKCNT(HLDP) 92 ; patch HL*1.6*123 end 93 Q 94 ; 95 INIT ;Create Task number and clear Stop flag. 96 N HLJ,X 97 S X=1 98 F L +^HLCS(869.3,X,5):2 Q:$T 99 ;52=Link Manager task number,53=Stop Link Manager 100 S HLJ(869.3,X_",",52)=$G(ZTQUEUED) 101 S HLJ(869.3,X_",",53)="@" 102 D FILE^HLDIE("","HLJ","","INIT","HLCSLM") ;HL*1.6*109 103 L -^HLCS(869.3,X,5) 104 Q 105 TASKNUM(X) ;Look-up task number 106 N %,DA,Y 107 S DA=X 108 ; 109 ;**109** 110 ;F L +^HLCS(870,+DA,0):2 Q:$T 111 ; 112 S Y=$$GET1^DIQ(870,DA_",",11) 113 ; 114 ;**109 115 ;L -^HLCS(870,+DA,0) 116 ; 117 Q Y 118 STATUS(X) ;Status of task 119 N Y,ZTSK 120 S ZTSK=X 121 D STAT^%ZTLOAD 122 S Y=ZTSK(1) 123 Q Y 124 ; 125 LLOK(X) ;Function to check whether LL ok. 126 ;return value 1 = ok, 0 = not ok. 127 Q:'$G(X) 128 N HLDP,HLDP0,HLPARM4,HLTYPTR 129 S HLDP=+X,HLDP0=$G(^HLCS(870,HLDP,0)),HLPARM4=$G(^(400)) Q:HLDP0="" 0 130 ;must be a client 131 Q:$P(HLPARM4,U,3)'="C" 0 132 ; 133 ; patch HL*1.6*123 134 ;shutdown LLP must be 0 135 ; Q:$P(HLDP0,U,15)'=0 0 136 ; change to 1, in case the data is empty 137 Q:$P(HLDP0,U,15)=1 0 138 ; 139 ;must have LLP Type of TCP 140 S HLTYPTR=+$P(HLDP0,U,3) Q:$P($G(^HLCS(869.1,HLTYPTR,0)),U)'="TCP" 0 141 Q 1 142 ; 143 SAVTSK(X) ; 144 N HLDP,HLJ 145 S HLDP=X 146 ; 147 ;**109** 148 F L +^HLCS(870,HLDP,0):2 Q:$T 149 ; 150 ;4=status,10=Time Stopped,9=Time Started,11=Task Number,3=Online ? 151 S X=$NA(HLJ(870,HLDP_",")),@X@(11)=$G(ZTSK) 152 ;S HLJ(870,HLDP_",",11)=$G(ZTSK) 153 D FILE^HLDIE("","HLJ","","SAVTSK","HLCSLM") ; HL*1.6*109 154 S HLTSKCNT(HLDP)=$G(ZTSK)_"^"_$H 155 ; 156 ;**109** 157 L -^HLCS(870,HLDP,0) 158 ; 159 Q 160 ; 161 STRTSTOP ;ENTRY POINT TO START/STOP TCP LINK MANAGER 162 N DIR,DIRUT,Y 163 L +^HLCS("HLCSLM"):3 E D Q 164 .W !,*7,"Link Manager already running!" 165 .W ! S DIR(0)="YO",DIR("A")="Would you like to stop the Link Manager now",DIR("B")="NO" D ^DIR K DIR 166 .I $D(DIRUT)!'Y Q 167 .D STOPLM 168 W !,*7,"Link Manager is NOT currently running!" 169 W ! S DIR(0)="YO",DIR("A")="Would you like to start the Link Manager now",DIR("B")="YES" D ^DIR K DIR 170 I '$D(DIRUT)&Y D TASKLM 171 L -^HLCS("HLCSLM") 172 Q 173 ; 174 STOPLM ;ENTRY POINT TO STOP LINK MANAGER 175 N DIC,X,Y,DTOUT,DUOUT,DLAYGO,DIE,DA,DR 176 S DIC="^HLCS(869.3," 177 S X=1 178 D ^DIC 179 S DA=+Y,DIE=DIC 180 S DR="53////1" 181 D ^DIE 182 W !,"Link Manager has been asked to stop" 183 Q 184 STAT() ;Status of LINK MANAGER--up, down or unable to determine. 185 N %,DA,X,Y 186 S DA=1 187 S X=$$GET1^DIQ(869.3,DA_",",52) 188 Q:X']"" 0 189 S X=$$GET1^DIQ(869.3,DA_",",54) 190 Q:X']"" 0 191 I $$HDIFF^XLFDT($H,X,2)>500 Q 0 192 Q 1 193 ; 194 TASKLSUB(X) ;Task LINK SUB-MANAGER. 195 ;This may be a place to log the time which the LINK SUBMANAGER is tasked. 196 N HLDP,HLDP0,HLDAPP,HLTYPTR,HLBGR,HLENV,HLPARM,HLPARM4,HLQUIT,ZTRTN,ZTDESC,ZTCPU,ZTSAVE 197 ;ZTSK is not Newed here because it will be needed by SAVTSK. 198 S HLDP=X,HLDP0=$G(^HLCS(870,HLDP,0)),HLPARM4=$G(^(400)) 199 ; Q:"N"'[$P(HLPARM4,U,4) ; patch HL*1.6*123: comment out 200 ;quit if no LLP TYPE 201 S HLDAPP=$P(HLDP0,U),HLTYPTR=$P(HLDP0,U,3) Q:'HLTYPTR 202 S HLBGR=$G(^HLCS(869.1,HLTYPTR,100)),HLENV=$G(^(200)) 203 I HLENV'="" K HLQUIT X HLENV Q:$D(HLQUIT) 204 S ZTRTN="^HLCSLSM",HLBGR=$P(HLBGR," ",2) 205 S ZTDESC=HLDAPP_" Low Level Protocol",ZTSAVE("HLDP")="",ZTSAVE("HLBGR")="" 206 S ZTIO="",ZTDTH=$H 207 ;get startup node 208 I $P(HLPARM4,U,6),$D(^%ZIS(14.7,+$P(HLPARM4,U,6),0)) S ZTCPU=$P(^(0),U) 209 D ^%ZTLOAD 210 D MON^HLCSTCP("Tasked") ;HL*1.6*123 211 Q 212 ; 213 TASKLM ;Task Link Manager 214 ;Declare variables 215 N ZTRTN,ZTDESC,ZTIO,ZTDTH,ZTSK,TMP 216 S ZTIO="" 217 S ZTDTH=$H 218 ;Task Link Manager 219 S ZTRTN="EN^HLCSLM" 220 S ZTDESC="HL7 Link Manager" 221 ;Call TaskMan 222 D ^%ZTLOAD 223 I $G(ZTSK) W !,"Link Manager queued as task number ",ZTSK 224 E W $C(7),!!,"Unable to start/restart Link Manager" 225 Q 226 ; 227 CKLMSTOP() ;Check whether Link Manager should stop 228 N PTRMAIN,NODE5,STOP 229 S PTRMAIN=+$O(^HLCS(869.3,0)) 230 L +^HLCS(869.3,PTRMAIN,5):1 231 I $T L -^HLCS(869.3,PTRMAIN,5) 232 S NODE5=$G(^HLCS(869.3,PTRMAIN,5)) 233 S STOP=+$P(NODE5,"^",3) 234 Q:STOP STOP 235 S STOP=$$S^%ZTLOAD 236 Q STOP 237 ; 238 SNDALERT ;Send Alert 239 N XQA,XQAMSG,XQAOPT,XQAROU,XQAID,Z 240 S Z=$P($$PARAM^HLCS2,U,8) Q:Z="" 241 S XQA("G."_Z)="",XQAMSG="HL7 Logical Link "_$P(^HLCS(870,HLDP,0),U)_" shutdown due to TaskMan unable to process task request" 242 D SETUP^XQALERT 243 Q 1 HLCSLM ;SFCIOFO/AC - HL7 LINK MANAGER ;06/14/2005 10:29 2 ;;1.6;HEALTH LEVEL SEVEN;**49,57,109,123**;Oct 13, 1995 3 ; 4 EN ;Entry point for start up task 5 N %,HLEVLCHK,HLTSKCNT 6 F %=1:1:10 L +^HLCS("HLCSLM"):2 Q:$T 7 E Q 8 I $G(ZTQUEUED) S Y=$$PSET^%ZTLOAD(ZTQUEUED) 9 D INIT,SAVDOLRH 10 D SETNM^%ZOSV($E("HLmgr:"_$G(ZTQUEUED),1,15)) 11 ; 12 LOOP ; 13 D CHKQUE 14 I $$CKLMSTOP G EXIT 15 D SAVDOLRH 16 D CHECKMST^HLEVMST ;HL*1.6*109 - Make sure event monitor current 17 H 10 18 G LOOP 19 ; 20 EXIT N HLJ,X 21 S X=1 22 F L +^HLCS(869.3,X,5):2 Q:$T 23 ;52=Link Manager task number 24 S HLJ(869.3,X_",",52)="@" 25 D FILE^HLDIE("","HLJ","","EXIT","HLCSLM") ;HL*1.6*109 26 L -^HLCS(869.3,X,5) 27 L -^HLCS("HLCSLM") 28 Q 29 ; 30 SAVDOLRH ;Save Last Known $H 31 N HLJ,X 32 S X=1 33 F L +^HLCS(869.3,X,5):2 Q:$T 34 ;54=LM LAST KNOWN $H 35 S HLJ(869.3,X_",",54)=$H 36 D FILE^HLDIE("","HLJ","","SAVDOLRH","HLCSLM") ;HL*1.6*109 37 L -^HLCS(869.3,X,5) 38 Q 39 ; 40 CHKQUE ;Check queues for messages to send 41 ;HLTSKCNT(logical link)=task #^$H 42 N HLDA,HLDP,HLMSG,HLTSK,Y 43 S (HLDA,HLMSG)="" 44 F HLDP=0:0 S HLDP=+$O(^HLMA("AC","O",HLDP)) Q:HLDP'>0 S HLMSG=+$O(^(HLDP,0)) I HLMSG D L -^HLCS("HLCSLSM",HLDP) 45 .;quit if persistent link 46 .Q:$P($G(^HLCS(870,HLDP,400)),U,4)="Y" 47 .L +^HLCS("HLCSLSM",HLDP):0 E K HLTSKCNT(HLDP) Q 48 .Q:'$$LLOK(+HLDP) 49 .;get tasknumber from file 870 and HLTSKCNT array 50 .S Y=$$TASKNUM(HLDP),HLTSK=$G(HLTSKCNT(HLDP)) 51 . ; 52 . ;patch HL*1.6*123 start 53 . S HLDP("TASK-ACTIVE")=0 54 . ; 55 . I Y D 56 .. N ZTSK 57 .. S ZTSK=Y 58 .. ; Check status of task 59 .. D STAT^%ZTLOAD 60 .. I "12"[ZTSK(1) S HLDP("TASK-ACTIVE")=1 61 . Q:HLDP("TASK-ACTIVE") 62 . ; 63 . I HLTSK D 64 .. N ZTSK 65 .. S ZTSK=+HLTSK 66 .. ; Check status of task 67 .. D STAT^%ZTLOAD 68 .. I "12"[ZTSK(1) S HLDP("TASK-ACTIVE")=1 69 . Q:HLDP("TASK-ACTIVE") 70 . ; 71 . ;no tasknumber, link not running nor queued, task it 72 . I 'HLTSK!'Y D TASKLSUB(HLDP),SAVTSK(HLDP) Q 73 ; comment out the following lines 74 ; .;link was tasked, check time 75 ; .S Y=$P(HLTSK,U,2) 76 ; .;check that time task is less than 30 minutes 77 ; .Q:$$HDIFF^XLFDT($H,Y,2)<1800 78 ; .;shutdown and send alert 79 ; .D SDFLD^HLCSTCP,EXITS^HLCSTCP("Shutdown"),SNDALERT 80 ; loop through links that have been tasked 81 ; F HLDP=0:0 S HLDP=$O(HLTSKCNT(HLDP)) Q:HLDP'>0 K:'$D(^HLMA("AC","O",HLDP)) HLTSKCNT(HLDP) 82 F HLDP=0:0 S HLDP=$O(HLTSKCNT(HLDP)) Q:HLDP'>0 D 83 . N ZTSK 84 . S ZTSK=+HLTSKCNT(HLDP) 85 . ; Check status of task 86 . D STAT^%ZTLOAD 87 . ; kill HLTSKCNT(HLDP) if process is not active 88 . I "12"'[ZTSK(1) K HLTSKCNT(HLDP) 89 ; patch HL*1.6*123 end 90 Q 91 ; 92 INIT ;Create Task number and clear Stop flag. 93 N HLJ,X 94 S X=1 95 F L +^HLCS(869.3,X,5):2 Q:$T 96 ;52=Link Manager task number,53=Stop Link Manager 97 S HLJ(869.3,X_",",52)=$G(ZTQUEUED) 98 S HLJ(869.3,X_",",53)="@" 99 D FILE^HLDIE("","HLJ","","INIT","HLCSLM") ;HL*1.6*109 100 L -^HLCS(869.3,X,5) 101 Q 102 TASKNUM(X) ;Look-up task number 103 N %,DA,Y 104 S DA=X 105 ; 106 ;**109** 107 ;F L +^HLCS(870,+DA,0):2 Q:$T 108 ; 109 S Y=$$GET1^DIQ(870,DA_",",11) 110 ; 111 ;**109 112 ;L -^HLCS(870,+DA,0) 113 ; 114 Q Y 115 STATUS(X) ;Status of task 116 N Y,ZTSK 117 S ZTSK=X 118 D STAT^%ZTLOAD 119 S Y=ZTSK(1) 120 Q Y 121 ; 122 LLOK(X) ;Function to check whether LL ok. 123 ;return value 1 = ok, 0 = not ok. 124 Q:'$G(X) 125 N HLDP,HLDP0,HLPARM4,HLTYPTR 126 S HLDP=+X,HLDP0=$G(^HLCS(870,HLDP,0)),HLPARM4=$G(^(400)) Q:HLDP0="" 0 127 ;must be a client 128 Q:$P(HLPARM4,U,3)'="C" 0 129 ; 130 ; patch HL*1.6*123 131 ;shutdown LLP must be 0 132 ; Q:$P(HLDP0,U,15)'=0 0 133 ; change to 1, in case the data is empty 134 Q:$P(HLDP0,U,15)=1 0 135 ; 136 ;must have LLP Type of TCP 137 S HLTYPTR=+$P(HLDP0,U,3) Q:$P($G(^HLCS(869.1,HLTYPTR,0)),U)'="TCP" 0 138 Q 1 139 ; 140 SAVTSK(X) ; 141 N HLDP,HLJ 142 S HLDP=X 143 ; 144 ;**109** 145 F L +^HLCS(870,HLDP,0):2 Q:$T 146 ; 147 ;4=status,10=Time Stopped,9=Time Started,11=Task Number,3=Online ? 148 S X=$NA(HLJ(870,HLDP_",")),@X@(11)=$G(ZTSK) 149 ;S HLJ(870,HLDP_",",11)=$G(ZTSK) 150 D FILE^HLDIE("","HLJ","","SAVTSK","HLCSLM") ; HL*1.6*109 151 S HLTSKCNT(HLDP)=$G(ZTSK)_"^"_$H 152 ; 153 ;**109** 154 L -^HLCS(870,HLDP,0) 155 ; 156 Q 157 ; 158 STRTSTOP ;ENTRY POINT TO START/STOP TCP LINK MANAGER 159 N DIR,DIRUT,Y 160 L +^HLCS("HLCSLM"):3 E D Q 161 .W !,*7,"Link Manager already running!" 162 .W ! S DIR(0)="YO",DIR("A")="Would you like to stop the Link Manager now",DIR("B")="NO" D ^DIR K DIR 163 .I $D(DIRUT)!'Y Q 164 .D STOPLM 165 W !,*7,"Link Manager is NOT currently running!" 166 W ! S DIR(0)="YO",DIR("A")="Would you like to start the Link Manager now",DIR("B")="YES" D ^DIR K DIR 167 I '$D(DIRUT)&Y D TASKLM 168 L -^HLCS("HLCSLM") 169 Q 170 ; 171 STOPLM ;ENTRY POINT TO STOP LINK MANAGER 172 N DIC,X,Y,DTOUT,DUOUT,DLAYGO,DIE,DA,DR 173 S DIC="^HLCS(869.3," 174 S X=1 175 D ^DIC 176 S DA=+Y,DIE=DIC 177 S DR="53////1" 178 D ^DIE 179 W !,"Link Manager has been asked to stop" 180 Q 181 STAT() ;Status of LINK MANAGER--up, down or unable to determine. 182 N %,DA,X,Y 183 S DA=1 184 S X=$$GET1^DIQ(869.3,DA_",",52) 185 Q:X']"" 0 186 S X=$$GET1^DIQ(869.3,DA_",",54) 187 Q:X']"" 0 188 I $$HDIFF^XLFDT($H,X,2)>500 Q 0 189 Q 1 190 ; 191 TASKLSUB(X) ;Task LINK SUB-MANAGER. 192 ;This may be a place to log the time which the LINK SUBMANAGER is tasked. 193 N HLDP,HLDP0,HLDAPP,HLTYPTR,HLBGR,HLENV,HLPARM,HLPARM4,HLQUIT,ZTRTN,ZTDESC,ZTCPU,ZTSAVE 194 ;ZTSK is not Newed here because it will be needed by SAVTSK. 195 S HLDP=X,HLDP0=$G(^HLCS(870,HLDP,0)),HLPARM4=$G(^(400)) 196 ; Q:"N"'[$P(HLPARM4,U,4) ; patch HL*1.6*123: comment out 197 ;quit if no LLP TYPE 198 S HLDAPP=$P(HLDP0,U),HLTYPTR=$P(HLDP0,U,3) Q:'HLTYPTR 199 S HLBGR=$G(^HLCS(869.1,HLTYPTR,100)),HLENV=$G(^(200)) 200 I HLENV'="" K HLQUIT X HLENV Q:$D(HLQUIT) 201 S ZTRTN="^HLCSLSM",HLBGR=$P(HLBGR," ",2) 202 S ZTDESC=HLDAPP_" Low Level Protocol",ZTSAVE("HLDP")="",ZTSAVE("HLBGR")="" 203 S ZTIO="",ZTDTH=$H 204 ;get startup node 205 I $P(HLPARM4,U,6),$D(^%ZIS(14.7,+$P(HLPARM4,U,6),0)) S ZTCPU=$P(^(0),U) 206 D ^%ZTLOAD 207 D MON^HLCSTCP("Tasked") ;HL*1.6*123 208 Q 209 ; 210 TASKLM ;Task Link Manager 211 ;Declare variables 212 N ZTRTN,ZTDESC,ZTIO,ZTDTH,ZTSK,TMP 213 S ZTIO="" 214 S ZTDTH=$H 215 ;Task Link Manager 216 S ZTRTN="EN^HLCSLM" 217 S ZTDESC="HL7 Link Manager" 218 ;Call TaskMan 219 D ^%ZTLOAD 220 I $G(ZTSK) W !,"Link Manager queued as task number ",ZTSK 221 E W $C(7),!!,"Unable to start/restart Link Manager" 222 Q 223 ; 224 CKLMSTOP() ;Check whether Link Manager should stop 225 N PTRMAIN,NODE5,STOP 226 S PTRMAIN=+$O(^HLCS(869.3,0)) 227 L +^HLCS(869.3,PTRMAIN,5):1 228 I $T L -^HLCS(869.3,PTRMAIN,5) 229 S NODE5=$G(^HLCS(869.3,PTRMAIN,5)) 230 S STOP=+$P(NODE5,"^",3) 231 Q:STOP STOP 232 S STOP=$$S^%ZTLOAD 233 Q STOP 234 ; 235 SNDALERT ;Send Alert 236 N XQA,XQAMSG,XQAOPT,XQAROU,XQAID,Z 237 S Z=$P($$PARAM^HLCS2,U,8) Q:Z="" 238 S XQA("G."_Z)="",XQAMSG="HL7 Logical Link "_$P(^HLCS(870,HLDP,0),U)_" shutdown due to TaskMan unable to process task request" 239 D SETUP^XQALERT 240 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSLNCH.m
r613 r623 1 HLCSLNCH ;ALB/MTC/JC - START AND STOP THE LLP ;07/26/2007 17:10 2 ;;1.6;HEALTH LEVEL SEVEN;**6,19,43,49,57,75,84,109,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ;This program is callable from a menu 6 ;It allows the user to Start and Stop the Lower Layer 7 ;Protocol in the Background or in the foreground 8 ; 9 ;Required or Optional INPUT PARAMETERS 10 ; None 11 ; 12 ; 13 ;Output variables 14 ; HLDP=IEN of Logical Link in file #870 15 ;(optional)HLTRACE=if SET it launches the LLP in the Foreground 16 ;(optional) ZTSK=if defined LLP was launched in the 17 ;background 18 ; 19 ; 20 START ; Start up the lower level protocol 21 N DIC,DIRUT,DTOUT,DUOUT,HLDP,HLDAPP,HLJ,HLQUIT,HLTRACE 22 N HLPARM0,HLPARM4,HLTYPTR,HLBGR,X,Y,ZTCPU,ZTSK,ZTRTN,ZTDESC 23 W !!,"This option is used to launch the lower level protocol for the" 24 W !,"appropriate device. Please select the node with which you want" 25 W !,"to communicate",! 26 ; patch HL*1.6*122 27 S POP=0 28 S DIC="^HLCS(870,",DIC(0)="QEAMZ" D ^DIC G:Y<0 STARTQ 29 S HLDP=+Y,HLDAPP=Y(0,0),HLTYPTR=+$P(Y(0),U,3),HLPARM0=Y(0) 30 ;-- check if parameter have been setup 31 ;-- check for LLP type 32 I 'HLTYPTR W !!,$C(7),"A Lower Layer Protocol must be selected before start-up can occur." G STARTQ 33 ;-- get TCP information 34 S HLPARM4=$G(^HLCS(870,HLDP,400)) 35 ;-- get routine (background job for LLP) 36 S HLBGR=$G(^HLCS(869.1,HLTYPTR,100)) 37 ;-- get environment check routine (HLQUIT should be defined in fails) 38 S HLENV=$G(^HLCS(869.1,HLTYPTR,200)) 39 ; 40 I HLBGR="" W !!,$C(7),"No routine has been specified for this LLP." G STARTQ 41 ; 42 ;-- execute environment check routine if HLQUIT is defined then terminate 43 I HLENV'="" X HLENV G:$D(HLQUIT) STARTQ 44 ; patch HL*1.6*122 start 45 ; Multi-Servers: TCP service (GT.M, DSM, and Cache/VMS) is controlled 46 ; by the external service 47 I $P(HLPARM4,U,3)="M",$S(^%ZOSF("OS")'["OpenM":1,1:$$OS^%ZOSV["VMS") D G STARTQ 48 . W !,$C(7),"This LLP is a multi-threaded server. It is controlled by external service, i.e. TCPIP/UCX. You must use the external service to start this LLP." 49 . Q 50 ; patch HL*1.6*122 end 51 ; 52 I $P(HLPARM0,U,10) W !,$C(7),"The LLP was last started on ",$$DAT2^HLUTIL1($P(HLPARM0,U,10)),"." G STP1:$P(HLPARM0,U,5)'="Error" 53 I $P(HLPARM0,U,11) W !,"The LLP was last shutdown on ",$$DAT2^HLUTIL1($P(HLPARM0,U,11)),"." 54 ; patch HL*1.6*122 start 55 ; comment out-should be taken care of by the code 2 line above 56 ; I $P(HLPARM0,U,5)'="Error",'($P(HLPARM4,U,3)="C"&("N"[$P(HLPARM4,U,4))),$P(HLPARM0,U,10)]""&($P(HLPARM0,U,11)=""),$P(HLPARM0,U,12) W !,"The LLP appears to be online already !" 57 ; I $$TASK^HLUTIL1($P(HLPARM0,U,12)) D G STARTQ 58 ; . W !,$C(7),"NOTE: The lower level protocol for this application is already running." 59 N HLTEMP 60 S HLTEMP=0 61 I $P(HLPARM0,U,12) D G:HLTEMP STARTQ 62 . N ZTSK 63 . S ZTSK=$P(HLPARM0,U,12) 64 . D STAT^%ZTLOAD 65 . I "12"[ZTSK(1) D 66 .. W !,$C(7),"NOTE: The lower level protocol for this application is already running." 67 .. I '$P(^HLCS(870,HLDP,0),"^",10) S $P(^HLCS(870,HLDP,0),"^",10)=$$NOW^XLFDT 68 .. S HLTEMP=1 69 ; patch HL*1.6*122 end 70 I $P(HLPARM4,U,3)="C"&("N"[$P(HLPARM4,U,4)) D G STARTQ 71 .;4=status 9=Time Started, 10=Time Stopped, 11=Task Number 72 .;14=Shutdown LLP, 3=Device Type, 18=Gross Errors 73 .N HLJ,X 74 . ; patch HL*1.6*122-comment out 75 . ; I $P(HLPARM0,U,15)=0 W !,"This LLP is already enabled!" Q 76 .L +^HLCS(870,HLDP,0):2 77 .E W !,$C(7),"Unable to enable this LLP !" Q 78 .S X="HLJ(870,"""_HLDP_","")" 79 .S @X@(4)="Enabled",@X@(9)=$$NOW^XLFDT,@X@(14)=0 80 .D FILE^HLDIE("","HLJ","","START","HLCSLNCH") ;HL*1.6*109 81 .L -^HLCS(870,HLDP,0) 82 .W !,"This LLP has been enabled!" 83 .Q 84 I $P(HLPARM4,U,6),$D(^%ZIS(14.7,+$P(HLPARM4,U,6),0)) S ZTCPU=$P(^(0),U) W !,"This LLP will start on node ",ZTCPU," if it is run in the Background.",! 85 ; 86 ; patch HL*1.6*122 start, for tcp link 87 I HLTYPTR=4 D Q 88 . S Y="B" 89 . D STARTJOB 90 ; patch HL*1.6*122 end 91 ; 92 W ! S DIR(0)="SM^F:FOREGROUND;B:BACKGROUND;Q:QUIT" 93 S DIR("A")="Method for running the receiver" 94 S DIR("B")="B" 95 S DIR("?",1)="Enter F for Foreground (and trace)" 96 S DIR("?",2)=" B for Background (normal) or" 97 S DIR("?")=" Q to quit without starting the receiver" 98 D ^DIR K DIR 99 Q:(Y=U)!(Y="Q") 100 ; 101 STARTJOB ; 102 S HLX=$G(^HLCS(870,HLDP,0)) 103 ;-- foreground 104 I Y="F" S HLTRACE=1 D G STARTQ 105 . S $P(^HLCS(870,HLDP,0),"^",10)=$$NOW^XLFDT 106 . D MON^HLCSTCP("Start") 107 . X HLBGR 108 ;-- background 109 I Y="B" D G STARTQ 110 . S ZTRTN=$P(HLBGR," ",2),HLTRACE="",ZTIO="",ZTDTH=$H 111 . S ZTDESC=HLDAPP_" Low Level Protocol",ZTSAVE("HLDP")="" 112 . D ^%ZTLOAD 113 . ; patch HL*1.6*122 start 114 . I $D(ZTSK) D 115 .. K HLTRACE 116 .. D MON^HLCSTCP("Tasked") 117 .. S $P(^HLCS(870,HLDP,0),"^",10)=$$NOW^XLFDT 118 . ; patch HL*1.6*122 end 119 . W !,$S($D(ZTSK):"Job was queued as "_ZTSK_".",1:"Unable to queue job.") 120 ; 121 Q 122 ; 123 STARTQ ; 124 I $G(POP) W !,?5,"-Unable to Open the Device !",!,!,?6,"Check that Port is Logged Out, and that the",!,?6,"Lower Level Protocol is not Already Running." 125 Q 126 ; 127 STOP ; Shut down a lower level protocol.. 128 N DIC,DIRUT,DTOUT,DUOUT,HLDP,HLDAPP,HLJ,HLPARM0,HLPARM4,X,Y 129 W !!,"This option is used to shut down the lower level protocol for the" 130 W !,"appropriate device. Please select the link which you would" 131 W !,"like to shutdown.",! 132 S DIC="^HLCS(870,",DIC(0)="QEAMZ" D ^DIC K DIC Q:Y<0 133 S HLDP=+Y,HLDAPP=Y(0,0),HLPARM0=Y(0),HLPARM4=$G(^HLCS(870,HLDP,400)) 134 ; patch HL*1.6*122 135 ; Multi-Servers: TCP service (GT.M, DSM, and Cache/VMS) is controlled 136 ; by the external service 137 I $P(HLPARM4,U,3)="M",$S(^%ZOSF("OS")'["OpenM":1,1:$$OS^%ZOSV["VMS") D Q 138 . W !,$C(7),"This LLP is a multi-threaded server. It is controlled by external service, i.e. TCPIP/UCX. You must use the external service to disable this LLP." 139 . Q 140 ; 141 I $P(HLPARM0,U,15) W !,$C(7),"The lower level protocol is already ",$P(HLPARM0,U,5),"." Q 142 I $P(HLPARM0,U,10) W !,$C(7),"The lower level protocol was started on ",$$DAT2^HLUTIL1($P(HLPARM0,U,10)),"." 143 STP1 ; 144 W ! S DIR(0)="Y",DIR("A")="Okay to shut down this job" D ^DIR K DIR 145 I 'Y!($D(DIRUT))!($D(DUOUT)) W !!,"The job will not be shut down." Q 146 S ; 147 F L +^HLCS(870,HLDP,0):2 Q:$T 148 ;4=status,10=Time Stopped,9=Time Started,11=Task Number,3=Device Type,14=shutdown 149 S X="HLJ(870,"""_HLDP_","")",@X@(4)="Halting",@X@(10)=$$NOW^XLFDT,(@X@(11),@X@(9))="@",@X@(14)=1 150 I $P(HLPARM4,U,3)="C"&("N"[$P(HLPARM4,U,4)),'$P(HLPARM0,U,12) S @X@(4)="Shutdown" 151 D FILE^HLDIE("","HLJ","","STOP","HLCSLNCH") ; HL*1.6*109 152 ; patch HL*1.6*122 start 153 ; I ^%ZOSF("OS")["OpenM",(($P(HLPARM4,U,3)="M"&($$OS^%ZOSV'["VMS"))!($P(HLPARM4,U,3)="S")) D 154 ; I ^%ZOSF("OS")'["DSM",(($P(HLPARM4,U,3)="M"&($$OS^%ZOSV'["VMS"))!($P(HLPARM4,U,3)="S")) D 155 I ($P(HLPARM4,U,3)="S")!(($P(HLPARM4,U,3)="M")&($S(^%ZOSF("OS")'["OpenM":0,1:$$OS^%ZOSV'["VMS"))) D 156 . ;pass task number to stop listener 157 . S:$P(HLPARM0,U,12) X=$$ASKSTOP^%ZTLOAD(+$P(HLPARM0,U,12)) 158 . ; D CALL^%ZISTCP($P(HLPARM4,U),$P(HLPARM4,U,2),10) 159 . ; I POP D HOME^%ZIS U IO W !,"Unable to shutdown logical link!!!",$C(7),$C(7) Q 160 . ; U IO W "**STOP**" 161 . ; W ! 162 . ; D CLOSE^%ZISTCP 163 . ; patch HL*1.6*122 end 164 L -^HLCS(870,HLDP,0) 165 W !,"The job for the "_HLDAPP_" Lower Level Protocol will be shut down." 166 Q 167 ; 168 STOPQ Q 1 HLCSLNCH ;ALB/MTC/JC - START AND STOP THE LLP ;12/31/2003 17:37 2 ;;1.6;HEALTH LEVEL SEVEN;**6,19,43,49,57,75,84,109**;Oct 13, 1995 3 ; 4 ;This program is callable from a menu 5 ;It allows the user to Start and Stop the Lower Layer 6 ;Protocol in the Background or in the foreground 7 ; 8 ;Required or Optional INPUT PARAMETERS 9 ; None 10 ; 11 ; 12 ;Output variables 13 ; HLDP=IEN of Logical Link in file #870 14 ;(optional)HLTRACE=if SET it launches the LLP in the Foreground 15 ;(optional) ZTSK=if defined LLP was launched in the 16 ;background 17 ; 18 ; 19 START ; Start up the lower level protocol 20 N DIC,DIRUT,DTOUT,DUOUT,HLDP,HLDAPP,HLJ,HLQUIT,HLTRACE 21 N HLPARM0,HLPARM4,HLTYPTR,HLBGR,X,Y,ZTCPU,ZTSK,ZTRTN,ZTDESC 22 W !!,"This option is used to launch the lower level protocol for the" 23 W !,"appropriate device. Please select the node with which you want" 24 W !,"to communicate",! 25 S DIC="^HLCS(870,",DIC(0)="QEAMZ" D ^DIC G:Y<0 STARTQ 26 S HLDP=+Y,HLDAPP=Y(0,0),HLTYPTR=+$P(Y(0),U,3),HLPARM0=Y(0) 27 ;-- check if parameter have been setup 28 ;-- check for LLP type 29 I 'HLTYPTR W !,$C(7),"A Lower Layer Protocol must be selected before start-up can occur." G STARTQ 30 ;-- get TCP information 31 S HLPARM4=$G(^HLCS(870,HLDP,400)) 32 ;-- get routine (background job for LLP) 33 S HLBGR=$G(^HLCS(869.1,HLTYPTR,100)) 34 ;-- get environment check routine (HLQUIT should be defined in fails) 35 S HLENV=$G(^HLCS(869.1,HLTYPTR,200)) 36 ; 37 I HLBGR="" W !,$C(7),"No routine has been specified for this LLP." G STARTQ 38 ; 39 ;-- execute environment check routine if HLQUIT is defined then terminate 40 I HLENV'="" X HLENV G:$D(HLQUIT) STARTQ 41 ;Multi-Servers, only enable the link if not OpenM 42 I $P(HLPARM4,U,3)="M",$S(^%ZOSF("OS")'["OpenM":1,1:$$OS^%ZOSV["VMS") D G STARTQ 43 . W !,$C(7),"This LLP is a multi-threaded server. It is controlled by external service, i.e. TCPIP/UCX. You must use the external service to start this LLP." 44 . Q 45 ; 46 I $P(HLPARM0,U,10) W !,$C(7),"The LLP was last started on ",$$DAT2^HLUTIL1($P(HLPARM0,U,10)),"." G STP1:$P(HLPARM0,U,5)'="Error" 47 I $P(HLPARM0,U,11) W !,"The LLP was last shutdown on ",$$DAT2^HLUTIL1($P(HLPARM0,U,11)),"." 48 I $P(HLPARM0,U,5)'="Error",'($P(HLPARM4,U,3)="C"&("N"[$P(HLPARM4,U,4))),$P(HLPARM0,U,10)]""&($P(HLPARM0,U,11)=""),$P(HLPARM0,U,12) W !,"The LLP appears to be online already !" 49 I $$TASK^HLUTIL1($P(HLPARM0,U,12)) D G STARTQ 50 . W !,$C(7),"NOTE: The lower level protocol for this application is already running." 51 I $P(HLPARM4,U,3)="C"&("N"[$P(HLPARM4,U,4)) D G STARTQ 52 .;4=status 9=Time Started, 10=Time Stopped, 11=Task Number 53 .;14=Shutdown LLP, 3=Device Type, 18=Gross Errors 54 .N HLJ,X 55 .I $P(HLPARM0,U,15)=0 W !,"This LLP is already enabled!" Q 56 .L +^HLCS(870,HLDP,0):2 57 .E W !,$C(7),"Unable to enable this LLP !" Q 58 .S X="HLJ(870,"""_HLDP_","")" 59 .S @X@(4)="Enabled",@X@(9)=$$NOW^XLFDT,@X@(14)=0 60 .D FILE^HLDIE("","HLJ","","START","HLCSLNCH") ;HL*1.6*109 61 .L -^HLCS(870,HLDP,0) 62 .W !,"This LLP has been enabled!" 63 .Q 64 I $P(HLPARM4,U,6),$D(^%ZIS(14.7,+$P(HLPARM4,U,6),0)) S ZTCPU=$P(^(0),U) W !,"This LLP will start on node ",ZTCPU," if it is run in the Background.",! 65 ; 66 W ! S DIR(0)="SM^F:FOREGROUND;B:BACKGROUND;Q:QUIT" 67 S DIR("A")="Method for running the receiver" 68 S DIR("B")="B" 69 S DIR("?",1)="Enter F for Foreground (and trace)" 70 S DIR("?",2)=" B for Background (normal) or" 71 S DIR("?")=" Q to quit without starting the receiver" 72 D ^DIR K DIR 73 Q:(Y=U)!(Y="Q") 74 ; 75 S HLX=$G(^HLCS(870,HLDP,0)) 76 ;-- foreground 77 I Y="F" S HLTRACE=1 D G STARTQ 78 . X HLBGR 79 ;-- background 80 I Y="B" D G STARTQ 81 . S ZTRTN=$P(HLBGR," ",2),HLTRACE="",ZTIO="",ZTDTH=$H 82 . S ZTDESC=HLDAPP_" Low Level Protocol",ZTSAVE("HLDP")="" 83 . D ^%ZTLOAD 84 . W !,$S($D(ZTSK):"Job was queued as "_ZTSK_".",1:"Unable to queue job.") 85 ; 86 Q 87 ; 88 ; 89 STARTQ ; 90 I $G(POP) W !,?5,"-Unable to Open the Device !",!,!,?6,"Check that Port is Logged Out, and that the",!,?6,"Lower Level Protocol is not Already Running." 91 Q 92 ; 93 STOP ; Shut down a lower level protocol.. 94 N DIC,DIRUT,DTOUT,DUOUT,HLDP,HLDAPP,HLJ,HLPARM0,HLPARM4,X,Y 95 W !!,"This option is used to shut down the lower level protocol for the" 96 W !,"appropriate device. Please select the link which you would" 97 W !,"like to shutdown.",! 98 S DIC="^HLCS(870,",DIC(0)="QEAMZ" D ^DIC K DIC Q:Y<0 99 S HLDP=+Y,HLDAPP=Y(0,0),HLPARM0=Y(0),HLPARM4=$G(^HLCS(870,HLDP,400)) 100 I $P(HLPARM4,U,3)="M",$S(^%ZOSF("OS")'["OpenM":1,1:$$OS^%ZOSV["VMS") D Q 101 . W !,$C(7),"This LLP is a multi-threaded server. It is controlled by external service, i.e. UCX. You must use the external service to disable this LLP." 102 . Q 103 ; 104 I $P(HLPARM0,U,15) W !,$C(7),"The lower level protocol is already ",$P(HLPARM0,U,5),"." Q 105 I $P(HLPARM0,U,10) W !,$C(7),"The lower level protocol was started on ",$$DAT2^HLUTIL1($P(HLPARM0,U,10)),"." 106 STP1 ; 107 W ! S DIR(0)="Y",DIR("A")="Okay to shut down this job" D ^DIR K DIR 108 I 'Y!($D(DIRUT))!($D(DUOUT)) W !!,"The job will not be shut down." Q 109 S ; 110 F L +^HLCS(870,HLDP,0):2 Q:$T 111 ;4=status,10=Time Stopped,9=Time Started,11=Task Number,3=Device Type,14=shutdown 112 S X="HLJ(870,"""_HLDP_","")",@X@(4)="Halting",@X@(10)=$$NOW^XLFDT,(@X@(11),@X@(9))="@",@X@(14)=1 113 I $P(HLPARM4,U,3)="C"&("N"[$P(HLPARM4,U,4)),'$P(HLPARM0,U,12) S @X@(4)="Shutdown" 114 D FILE^HLDIE("","HLJ","","STOP","HLCSLNCH") ; HL*1.6*109 115 I ^%ZOSF("OS")["OpenM",(($P(HLPARM4,U,3)="M"&($$OS^%ZOSV'["VMS"))!($P(HLPARM4,U,3)="S")) D 116 . ;pass task number to stop listener 117 . S:$P(HLPARM0,U,12) X=$$ASKSTOP^%ZTLOAD(+$P(HLPARM0,U,12)) 118 . D CALL^%ZISTCP($P(HLPARM4,U),$P(HLPARM4,U,2),10) 119 . I POP D HOME^%ZIS U IO W !,"Unable to shutdown logical link!!!",$C(7),$C(7) Q 120 . U IO W "**STOP**" 121 . W ! 122 . D CLOSE^%ZISTCP 123 L -^HLCS(870,HLDP,0) 124 W !,"The job for the "_HLDAPP_" Lower Level Protocol will be shut down." 125 Q 126 ; 127 STOPQ Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSMON.m
r613 r623 1 HLCSMON ;SF-DISPLAY DRIVER PROGRAM ;12/11/2007 17:07 2 ;;1.6;HEALTH LEVEL SEVEN;**34,40,48,49,65,66,73,109,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ;This Program drives a real-time display monitor for the HL7 6 ;Package. All the data used by this display is stored in file 7 ;# 870. Several callable entry points were broken 8 ;out of this routine and placed into HLCSMON1 9 ; 10 ;This routine has no required input parameters other than require that 11 ;U be defined, it does not instantiate any parameters either. 12 ; 13 ; 14 ;HLARY=array of all,HLARYD=array of display,HLARYO=array of old values 15 ;HLPTR1=top of display,HLPTR2=bottom of display,HLPTR3=last in HLVARY 16 INIT N HLARY,HLARYD,HLARYO,HLCOFF,HLCON,HLDISP,HLPTR1,HLPTR2,HLPTR3,HLRESP 17 N HLDEV,HLERR,HLEVL,HLHDR,HLNODE,HLOCK 18 N HLPARAM,HLPROC,HLPROD,HLSEND,HLSENT,HLSITE 19 N HLI,HLREC,HLRUNCNT,HLSTAT,HLTMSTAT,HLLMSTAT,HLVIEW,HLXX,HLYY,X,Y,DX,DY 20 ; 21 ; patch HL*1.6*122 start 22 D HOME^%ZIS 23 W @IOF 24 ; patch HL*1.6*122 end 25 ; 26 D ^HLCSTERM ;Sets up variables to control display attributes 27 INIT1 ; 28 ; Next 4 lines copied here from top of START by patch 73... 29 ;HLRUNCNT=number of in filers^out filers, HLDISP=display mode 30 S HLRUNCNT="-1^-1",HLPTR1=1 S:'$D(HLDISP) HLDISP="S" 31 D BUILDARY ;Build an array for display 32 QUIT:$$LOCKED(.HLOCK) ;-> Anything locked? 33 ; 34 W HLCOFF ;Shut Cursor off 35 D HEADER^HLCSTERM ;Write header 36 D WDATA^HLCSMON1(5,17,"","","Incoming filers running => ") 37 D WDATA^HLCSMON1(5,18,"","","Outgoing filers running => ") 38 D WDATA^HLCSMON1(5,20,"","","Select a Command:") 39 D WDATA^HLCSMON1(1,21,"","","(N)EXT (B)ACKUP (A)LL LINKS (S)CREENED (V)IEWS (Q)UIT (?) HELP: ") 40 ;HLRUNCNT=number of in filers^out filers, HLDISP=display mode 41 S HLRUNCNT="-1^-1",HLPTR1=1 S:'$D(HLDISP) HLDISP="S" 42 START ; 43 D BUILDARY ;Build an array for display 44 D DISPLAY^HLCSMON1 ;Display the array just built 45 D READ 46 ;HLRESP=user response 47 I '$L(HLRESP) G START 48 G:HLRESP="Q" EXIT 49 ;any of following commands, kill old values 50 K HLARYO,HLTMSTAT,HLLMSTAT 51 I HLRESP="?" D HELP G INIT1 52 I HLRESP="V" D VIEW G INIT1 53 I "AS"[HLRESP K HLARY,HLEVL S HLDISP=HLRESP G INIT1 54 I "NB"[HLRESP D NEXT 55 G START 56 ; 57 READ ;Prompt the user for the next action 58 D WDATA^HLCSMON1(71,21,"","","",1) 59 W HLCON 60 R X#1:3 61 W HLCOFF 62 S HLRESP=$S(X="":X,"Qq^"[X:"Q","Bb"[X:"B","Nn"[X:"N","Aa"[X:"A","Vv"[X:"V",X="?":"?","Ss"[X:"S",1:"") 63 Q 64 ; 65 VIEW ;select new view 66 W HLCON,!! 67 N DIC 68 S DIC="^HLCS(869.3,1,6,",DIC(0)="QEA" 69 D ^DIC Q:Y<0 70 S HLVIEW=+Y,HLDISP="V" 71 W HLCOFF 72 Q 73 ; 74 NEXT ; 75 ;Next page 76 I HLRESP="N" D 77 . ;no more 78 . I HLPTR2=HLPTR3 D EOB Q 79 . S Y=HLPTR2+10,HLEVL(HLPTR1)="" 80 . ;exceed list, get last 10 81 . I Y>HLPTR3 S HLPTR2=HLPTR3,HLPTR1=HLPTR2-9 Q 82 . S HLPTR1=HLPTR2,HLPTR2=Y 83 ; 84 ;Backup a page 85 I HLRESP="B" D 86 . ;top of list 87 . I HLPTR1=1 D EOB Q 88 . I HLDISP="S" S HLPTR1=$O(HLEVL(HLPTR1),-1) Q 89 . S Y=HLPTR1-9 90 . ;can't go back 10, reset to top 91 . I Y'>0 S HLPTR1=1,HLPTR2=10 Q 92 . S HLPTR2=HLPTR1,HLPTR1=Y 93 ; 94 ;Erase what might be displayed on line 22 95 D WDATA^HLCSMON1(1,22,IOELALL,"","") 96 Q 97 EOB D WDATA^HLCSMON1(5,22,IORVON,IORVOFF,"CANNOT "_$S(HLRESP="N":"ADVANCE",1:"BACKUP")_" BEYOND END OF BUFFER") 98 W $C(7) H 2 99 Q 100 ; 101 BUILDARY ; 102 K HLARYD 103 ; 104 ;if view is defined, get links 105 I $G(HLVIEW) D S HLVIEW=0,HLDISP="V" 106 . N HLTMP 107 . K HLARY,HLEVL S HLI=0 108 . F S HLI=$O(^HLCS(869.3,1,6,HLVIEW,1,HLI)) Q:'HLI S HLYY=+$P($G(^(HLI,0)),U,2) D 109 .. S Y=$P($G(^HLCS(870,HLI,0)),U) Q:Y="" 110 .. ;build array by DISPLAY ORDER and then by NAME 111 .. I HLYY S HLTMP(HLYY,HLI)="" Q 112 .. S HLTMP(Y,HLI)="" 113 . S (HLI,HLYY)=0 114 . ;rebuild array to put in proper order 115 . F S HLI=$O(HLTMP(HLI)),HLXX=0 Q:HLI="" D 116 .. F S HLXX=$O(HLTMP(HLI,HLXX)) Q:'HLXX S HLYY=HLYY+1,HLARY(HLYY,HLXX)="" 117 . S HLPTR3=HLYY 118 ; 119 I '$D(HLARY) S HLYY=0,HLXX="" D 120 . ;build array in alphabetical order 121 . F S HLXX=$O(^HLCS(870,"B",HLXX)) Q:HLXX="" S Y=$O(^(HLXX,0)),HLYY=HLYY+1,HLARY(HLYY,Y)="" 122 . S HLPTR3=HLYY 123 ; 124 S HLI=HLPTR1,HLYY=6 ;HLYY=6TH Line of display 125 ;HLARYD(6) through HLARYD(15) with 6 through 15 also representing line 126 ;numbers on the display 127 F HLI=HLI:1 S HLXX=$O(HLARY(HLI,0)) Q:HLYY=16!'HLXX D COPY 128 S HLPTR2=HLI-1 129 ;Set all HLARY elements not defined on this pass to null 130 F HLYY=HLYY:1:15 S HLARYD(HLYY)="" 131 Q 132 COPY ; 133 Q:'$D(^HLCS(870,HLXX)) 134 ; 135 ;These lock tags lock nodes in the global so that the screen is 136 ;refreshed in real-time. The lock forces the buffer to be refreshed, 137 ;so that the display is up to date. 138 ; 139 ;**109** 140 ;L +^HLCS(870,HLXX,0):0 L -^HLCS(870,HLXX,0) D CHKLOCK 141 ; 142 ; Set, even if not able to lock... 143 S Y=$G(^HLCS(870,HLXX,0)) 144 ; 145 ;name^rec^proc^send^sent^device^state^error 146 S HLARYD(HLYY)=$P(Y,U)_"^^^^^"_$P(Y,U,4)_"^"_$P(Y,U,5)_"^"_$P(Y,U,19) 147 ; 148 ;**109** 149 ;L +^HLCS(870,HLXX,"IN QUEUE BACK POINTER"):0 D CHKLOCK 150 ;L -^HLCS(870,HLXX,"IN QUEUE BACK POINTER") 151 ; 152 S $P(HLARYD(HLYY),U,2)=$G(^HLCS(870,HLXX,"IN QUEUE BACK POINTER")) 153 ; 154 ;**109** 155 ;L +^HLCS(870,HLXX,"IN QUEUE FRONT POINTER"):0 D CHKLOCK 156 ;L -^HLCS(870,HLXX,"IN QUEUE FRONT POINTER") 157 ; 158 S $P(HLARYD(HLYY),U,3)=$G(^HLCS(870,HLXX,"IN QUEUE FRONT POINTER")) 159 ; 160 ;**109** 161 ;L +^HLCS(870,HLXX,"OUT QUEUE BACK POINTER"):0 D CHKLOCK 162 ;L -^HLCS(870,HLXX,"OUT QUEUE BACK POINTER") 163 ; 164 S $P(HLARYD(HLYY),U,4)=$G(^HLCS(870,HLXX,"OUT QUEUE BACK POINTER")) 165 ; 166 ;**109** 167 ;L +^HLCS(870,HLXX,"OUT QUEUE FRONT POINTER"):0 D CHKLOCK 168 ;L -^HLCS(870,HLXX,"OUT QUEUE FRONT POINTER") 169 ; 170 S $P(HLARYD(HLYY),U,5)=$G(^HLCS(870,HLXX,"OUT QUEUE FRONT POINTER")) 171 ; 172 S X=HLARYD(HLYY),Y=$P(X,U,2)+$P(X,U,3)+$P(X,U,4)+$P(X,U,5) 173 ;if Select and the Y=0, nothing to report 174 I 'Y,HLDISP="S" S HLARYD(HLYY)="" Q 175 S HLYY=HLYY+1 176 Q 177 ; 178 CHKLOCK ; Call here immediately after trying to lock. And, BE SURE that 179 ; nothing might occur that would change $T after the lock attempt!! 180 ; $T,HLXX -- req 181 N NM870 182 QUIT:$T ;-> Lock obtained... 183 S NM870=$P($G(^HLCS(870,+HLXX,0)),U) 184 S NM870=$S(NM870]"":NM870_" (IEN #"_HLXX_")",1:"IEN #"_HLXX) 185 S HLOCK(NM870)="" 186 QUIT 187 ; 188 HELP ; 189 W HLCON,@IOF 190 W !,"You have the following options when monitoring the Messaging System:" 191 W !,"Enter the command letter parentheses: N,B,Q,A,S,V or ?" 192 W !!,"(N) takes you to the next page of the display of Logical Links." 193 W !!,"(B) takes you back one page." 194 W !!,"(Q) terminates the monitor." 195 W !!,"(A) provides a display of all links defined on your system." 196 W !!,"(S) displays only those links that have had message traffic." 197 W !!,"(V) prompts for a view name and displays links defined in view." 198 W !!," Note that (S) is the default display at startup." 199 W !!,"**PRESS <RET> TO CONTINUE**" 200 R X:DTIME 201 W @IOF 202 W !,?25,"Device Types and corresponding prefixes:" 203 W !!,?30,"PC -- Persistent TCP/IP Client" 204 W !!,?30,"NC -- Non-Persistent TCP/IP Client" 205 W !!,?30,"SS -- Single-threaded TCP/IP Server" 206 W !!,?30,"MS -- Multi-threaded TCP/IP Server" 207 W !!,?30,"SH -- Serial HLLP" 208 W !!,?30,"SX -- Serial X3.28" 209 W !!,?30,"MM -- MailMan" 210 W !!,"**PRESS <RET> TO CONTINUE**" 211 R X:DTIME 212 W HLCOFF 213 Q 214 EXIT ; 215 ;Turn Cursor back on 216 W HLCON 217 D KVAR^HLCSTERM 218 Q 219 ; 220 LOCKED(HLOCK) ; Anything locked? 221 ; 222 ; 223 ; Nothing locked... 224 I '$D(HLOCK) QUIT "" ;-> 225 ; 226 W !!,"Editing of logical link data is occurring right now. For this reason, some of" 227 W !,"the information on the 'System Link Monitor' report might not be accurate for" 228 W !,"the following node(s)..." 229 W ! 230 ; 231 S HLOCK="" 232 F S HLOCK=$O(HLOCK(HLOCK)) Q:HLOCK']"" D 233 . W !,?5,HLOCK 234 ; 235 S ACTION=$$BTE("Press RETURN to print report or '^' to exit... ",1) 236 ; 237 QUIT $S(ACTION=1:1,1:"") 238 ; 239 BTE(PMT,FF) ; 240 N DIR,DIRUT,DTOUT,DUOUT,X,Y 241 F X=1:1:$G(FF) W ! 242 S DIR(0)="EA",DIR("A")=PMT 243 D ^DIR 244 QUIT $S(Y=1:"",1:1) 245 ; 1 HLCSMON ;SF-DISPLAY DRIVER PROGRAM ;07/10/2000 12:18 2 ;;1.6;HEALTH LEVEL SEVEN;**34,40,48,49,65,66,73,109**;Oct 13, 1995 3 ; 4 ;This Program drives a real-time display monitor for the HL7 5 ;Package. All the data used by this display is stored in file 6 ;# 870. Several callable entry points were broken 7 ;out of this routine and placed into HLCSMON1 8 ; 9 ;This routine has no required input parameters other than require that 10 ;U be defined, it does not instantiate any parameters either. 11 ; 12 ; 13 ;HLARY=array of all,HLARYD=array of display,HLARYO=array of old values 14 ;HLPTR1=top of display,HLPTR2=bottom of display,HLPTR3=last in HLVARY 15 INIT N HLARY,HLARYD,HLARYO,HLCOFF,HLCON,HLDISP,HLPTR1,HLPTR2,HLPTR3,HLRESP 16 N HLDEV,HLERR,HLEVL,HLHDR,HLNODE,HLOCK 17 N HLPARAM,HLPROC,HLPROD,HLSEND,HLSENT,HLSITE 18 N HLI,HLREC,HLRUNCNT,HLSTAT,HLTMSTAT,HLLMSTAT,HLVIEW,HLXX,HLYY,X,Y,DX,DY 19 ; 20 D ^HLCSTERM ;Sets up variables to control display attributes 21 INIT1 ; 22 ; Next 4 lines copied here from top of START by patch 73... 23 ;HLRUNCNT=number of in filers^out filers, HLDISP=display mode 24 S HLRUNCNT="-1^-1",HLPTR1=1 S:'$D(HLDISP) HLDISP="S" 25 D BUILDARY ;Build an array for display 26 QUIT:$$LOCKED(.HLOCK) ;-> Anything locked? 27 ; 28 W HLCOFF ;Shut Cursor off 29 D HEADER^HLCSTERM ;Write header 30 D WDATA^HLCSMON1(5,17,"","","Incoming filers running => ") 31 D WDATA^HLCSMON1(5,18,"","","Outgoing filers running => ") 32 D WDATA^HLCSMON1(5,20,"","","Select a Command:") 33 D WDATA^HLCSMON1(1,21,"","","(N)EXT (B)ACKUP (A)LL LINKS (S)CREENED (V)IEWS (Q)UIT (?) HELP: ") 34 ;HLRUNCNT=number of in filers^out filers, HLDISP=display mode 35 S HLRUNCNT="-1^-1",HLPTR1=1 S:'$D(HLDISP) HLDISP="S" 36 START ; 37 D BUILDARY ;Build an array for display 38 D DISPLAY^HLCSMON1 ;Display the array just built 39 D READ 40 ;HLRESP=user response 41 I '$L(HLRESP) G START 42 G:HLRESP="Q" EXIT 43 ;any of following commands, kill old values 44 K HLARYO,HLTMSTAT,HLLMSTAT 45 I HLRESP="?" D HELP G INIT1 46 I HLRESP="V" D VIEW G INIT1 47 I "AS"[HLRESP K HLARY,HLEVL S HLDISP=HLRESP G INIT1 48 I "NB"[HLRESP D NEXT 49 G START 50 ; 51 READ ;Prompt the user for the next action 52 D WDATA^HLCSMON1(71,21,"","","",1) 53 W HLCON 54 R X#1:3 55 W HLCOFF 56 S HLRESP=$S(X="":X,"Qq^"[X:"Q","Bb"[X:"B","Nn"[X:"N","Aa"[X:"A","Vv"[X:"V",X="?":"?","Ss"[X:"S",1:"") 57 Q 58 ; 59 VIEW ;select new view 60 W HLCON,!! 61 N DIC 62 S DIC="^HLCS(869.3,1,6,",DIC(0)="QEA" 63 D ^DIC Q:Y<0 64 S HLVIEW=+Y,HLDISP="V" 65 W HLCOFF 66 Q 67 ; 68 NEXT ; 69 ;Next page 70 I HLRESP="N" D 71 . ;no more 72 . I HLPTR2=HLPTR3 D EOB Q 73 . S Y=HLPTR2+10,HLEVL(HLPTR1)="" 74 . ;exceed list, get last 10 75 . I Y>HLPTR3 S HLPTR2=HLPTR3,HLPTR1=HLPTR2-9 Q 76 . S HLPTR1=HLPTR2,HLPTR2=Y 77 ; 78 ;Backup a page 79 I HLRESP="B" D 80 . ;top of list 81 . I HLPTR1=1 D EOB Q 82 . I HLDISP="S" S HLPTR1=$O(HLEVL(HLPTR1),-1) Q 83 . S Y=HLPTR1-9 84 . ;can't go back 10, reset to top 85 . I Y'>0 S HLPTR1=1,HLPTR2=10 Q 86 . S HLPTR2=HLPTR1,HLPTR1=Y 87 ; 88 ;Erase what might be displayed on line 22 89 D WDATA^HLCSMON1(1,22,IOELALL,"","") 90 Q 91 EOB D WDATA^HLCSMON1(5,22,IORVON,IORVOFF,"CANNOT "_$S(HLRESP="N":"ADVANCE",1:"BACKUP")_" BEYOND END OF BUFFER") 92 W $C(7) H 2 93 Q 94 ; 95 BUILDARY ; 96 K HLARYD 97 ; 98 ;if view is defined, get links 99 I $G(HLVIEW) D S HLVIEW=0,HLDISP="V" 100 . N HLTMP 101 . K HLARY,HLEVL S HLI=0 102 . F S HLI=$O(^HLCS(869.3,1,6,HLVIEW,1,HLI)) Q:'HLI S HLYY=+$P($G(^(HLI,0)),U,2) D 103 .. S Y=$P($G(^HLCS(870,HLI,0)),U) Q:Y="" 104 .. ;build array by DISPLAY ORDER and then by NAME 105 .. I HLYY S HLTMP(HLYY,HLI)="" Q 106 .. S HLTMP(Y,HLI)="" 107 . S (HLI,HLYY)=0 108 . ;rebuild array to put in proper order 109 . F S HLI=$O(HLTMP(HLI)),HLXX=0 Q:HLI="" D 110 .. F S HLXX=$O(HLTMP(HLI,HLXX)) Q:'HLXX S HLYY=HLYY+1,HLARY(HLYY,HLXX)="" 111 . S HLPTR3=HLYY 112 ; 113 I '$D(HLARY) S HLYY=0,HLXX="" D 114 . ;build array in alphabetical order 115 . F S HLXX=$O(^HLCS(870,"B",HLXX)) Q:HLXX="" S Y=$O(^(HLXX,0)),HLYY=HLYY+1,HLARY(HLYY,Y)="" 116 . S HLPTR3=HLYY 117 ; 118 S HLI=HLPTR1,HLYY=6 ;HLYY=6TH Line of display 119 ;HLARYD(6) through HLARYD(15) with 6 through 15 also representing line 120 ;numbers on the display 121 F HLI=HLI:1 S HLXX=$O(HLARY(HLI,0)) Q:HLYY=16!'HLXX D COPY 122 S HLPTR2=HLI-1 123 ;Set all HLARY elements not defined on this pass to null 124 F HLYY=HLYY:1:15 S HLARYD(HLYY)="" 125 Q 126 COPY ; 127 Q:'$D(^HLCS(870,HLXX)) 128 ; 129 ;These lock tags lock nodes in the global so that the screen is 130 ;refreshed in real-time. The lock forces the buffer to be refreshed, 131 ;so that the display is up to date. 132 ; 133 ;**109** 134 ;L +^HLCS(870,HLXX,0):0 L -^HLCS(870,HLXX,0) D CHKLOCK 135 ; 136 ; Set, even if not able to lock... 137 S Y=$G(^HLCS(870,HLXX,0)) 138 ; 139 ;name^rec^proc^send^sent^device^state^error 140 S HLARYD(HLYY)=$P(Y,U)_"^^^^^"_$P(Y,U,4)_"^"_$P(Y,U,5)_"^"_$P(Y,U,19) 141 ; 142 ;**109** 143 ;L +^HLCS(870,HLXX,"IN QUEUE BACK POINTER"):0 D CHKLOCK 144 ;L -^HLCS(870,HLXX,"IN QUEUE BACK POINTER") 145 ; 146 S $P(HLARYD(HLYY),U,2)=$G(^HLCS(870,HLXX,"IN QUEUE BACK POINTER")) 147 ; 148 ;**109** 149 ;L +^HLCS(870,HLXX,"IN QUEUE FRONT POINTER"):0 D CHKLOCK 150 ;L -^HLCS(870,HLXX,"IN QUEUE FRONT POINTER") 151 ; 152 S $P(HLARYD(HLYY),U,3)=$G(^HLCS(870,HLXX,"IN QUEUE FRONT POINTER")) 153 ; 154 ;**109** 155 ;L +^HLCS(870,HLXX,"OUT QUEUE BACK POINTER"):0 D CHKLOCK 156 ;L -^HLCS(870,HLXX,"OUT QUEUE BACK POINTER") 157 ; 158 S $P(HLARYD(HLYY),U,4)=$G(^HLCS(870,HLXX,"OUT QUEUE BACK POINTER")) 159 ; 160 ;**109** 161 ;L +^HLCS(870,HLXX,"OUT QUEUE FRONT POINTER"):0 D CHKLOCK 162 ;L -^HLCS(870,HLXX,"OUT QUEUE FRONT POINTER") 163 ; 164 S $P(HLARYD(HLYY),U,5)=$G(^HLCS(870,HLXX,"OUT QUEUE FRONT POINTER")) 165 ; 166 S X=HLARYD(HLYY),Y=$P(X,U,2)+$P(X,U,3)+$P(X,U,4)+$P(X,U,5) 167 ;if Select and the Y=0, nothing to report 168 I 'Y,HLDISP="S" S HLARYD(HLYY)="" Q 169 S HLYY=HLYY+1 170 Q 171 ; 172 CHKLOCK ; Call here immediately after trying to lock. And, BE SURE that 173 ; nothing might occur that would change $T after the lock attempt!! 174 ; $T,HLXX -- req 175 N NM870 176 QUIT:$T ;-> Lock obtained... 177 S NM870=$P($G(^HLCS(870,+HLXX,0)),U) 178 S NM870=$S(NM870]"":NM870_" (IEN #"_HLXX_")",1:"IEN #"_HLXX) 179 S HLOCK(NM870)="" 180 QUIT 181 ; 182 HELP ; 183 W HLCON,@IOF 184 W !,"You have the following options when monitoring the Messaging System:" 185 W !,"Enter the command letter parentheses: N,B,Q,A,S,V or ?" 186 W !!,"(N) takes you to the next page of the display of Logical Links." 187 W !!,"(B) takes you back one page." 188 W !!,"(Q) terminates the monitor." 189 W !!,"(A) provides a display of all links defined on your system." 190 W !!,"(S) displays only those links that have had message traffic." 191 W !!,"(V) prompts for a view name and displays links defined in view." 192 W !!," Note that (S) is the default display at startup." 193 W !!,"**PRESS <RET> TO CONTINUE**" 194 R X:DTIME 195 W @IOF 196 W !,?25,"Device Types and corresponding prefixes:" 197 W !!,?30,"PC -- Persistent TCP/IP Client" 198 W !!,?30,"NC -- Non-Persistent TCP/IP Client" 199 W !!,?30,"SS -- Single-threaded TCP/IP Server" 200 W !!,?30,"MS -- Multi-threaded TCP/IP Server" 201 W !!,?30,"SH -- Serial HLLP" 202 W !!,?30,"SX -- Serial X3.28" 203 W !!,?30,"MM -- MailMan" 204 W !!,"**PRESS <RET> TO CONTINUE**" 205 R X:DTIME 206 W HLCOFF 207 Q 208 EXIT ; 209 ;Turn Cursor back on 210 W HLCON 211 D KVAR^HLCSTERM 212 Q 213 ; 214 LOCKED(HLOCK) ; Anything locked? 215 ; 216 ; 217 ; Nothing locked... 218 I '$D(HLOCK) QUIT "" ;-> 219 ; 220 W !!,"Editing of logical link data is occurring right now. For this reason, some of" 221 W !,"the information on the 'System Link Monitor' report might not be accurate for" 222 W !,"the following node(s)..." 223 W ! 224 ; 225 S HLOCK="" 226 F S HLOCK=$O(HLOCK(HLOCK)) Q:HLOCK']"" D 227 . W !,?5,HLOCK 228 ; 229 S ACTION=$$BTE("Press RETURN to print report or '^' to exit... ",1) 230 ; 231 QUIT $S(ACTION=1:1,1:"") 232 ; 233 BTE(PMT,FF) ; 234 N DIR,DIRUT,DTOUT,DUOUT,X,Y 235 F X=1:1:$G(FF) W ! 236 S DIR(0)="EA",DIR("A")=PMT 237 D ^DIR 238 QUIT $S(Y=1:"",1:1) 239 ; -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSMON1.m
r613 r623 1 HLCSMON1 ;SF-Utilities for Driver Program ;07/17/2007 17:05 2 ;;1.6;HEALTH LEVEL SEVEN;**15,40,49,65,109,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ;This routine contains several entry points called from HLCSMON 6 ;no input parameters are required. All variables used which are 7 ;not newed here are newed in HLCSMON 8 ; 9 DISPLAY ;display link info 10 ;turn of line wrap 11 S HLXX=0,X=0 X ^%ZOSF("RM") 12 F S HLXX=$O(HLARYD(HLXX)) Q:(HLXX'>0) D WLINE(HLXX) 13 ;DISPLAY INCOMING FILER STATUS 14 ; patch HL*1.6*122 15 S HLXX=$P(HLRUNCNT,"^",1) 16 ; S HLXX=$$CNTFLR^HLCSUTL2("IN") 17 I (+HLXX)=-1 S HLXX=$$CNTFLR^HLCSUTL2("IN") 18 ; 19 ;ONLY UPDATE SCREEN IF COUNT HAS CHANGED 20 I (HLXX'=+HLRUNCNT) D 21 .D WDATA(5,17,"","",$J(" ",31)),WDATA^HLCSMON1(5,17,"","","Incoming filers running => ",35) 22 .I (HLXX) D WDATA(32,17,"","",HLXX) 23 .I ('HLXX) D WDATA(32,17,IOINHI,IOINORM,"Zero") 24 .S $P(HLRUNCNT,"^",1)=HLXX 25 ;DISPLAY OUTGOING FILER STATUS 26 ; patch HL*1.6*122 27 S HLXX=$P(HLRUNCNT,"^",2) 28 ; S HLXX=$$CNTFLR^HLCSUTL2("OUT") 29 I (+HLXX)=-1 S HLXX=$$CNTFLR^HLCSUTL2("OUT") 30 ; 31 ;ONLY UPDATE SCREEN IF COUNT HAS CHANGED 32 I (HLXX'=+$P(HLRUNCNT,"^",2)) D 33 .D WDATA(5,18,"","",$J(" ",31)),WDATA^HLCSMON1(5,18,"","","Outgoing filers running => ",35) 34 .I (HLXX) D WDATA(32,18,"","",HLXX) 35 .I ('HLXX) D WDATA(32,18,IOINHI,IOINORM,"Zero") 36 .S $P(HLRUNCNT,"^",2)=HLXX 37 S X=$$TM^%ZTLOAD 38 I X'=$G(HLTMSTAT) D 39 .S HLTMSTAT=X 40 .S HLXX=$S('HLTMSTAT:"***TASKMAN NOT RUNNING!!!***",1:"") 41 .I 'HLTMSTAT D WDATA^HLCSMON1(45,17,IOELEOL_IOBON_IORVON,IOBOFF_IORVOFF,HLXX) I 1 42 .E D WDATA(45,17,IOELEOL,"",$J("TaskMan running ",16)) ;D WDATA(5,19,IOELALL,"","") 43 S X=$$STAT^HLCSLM 44 I X'=$G(HLLMSTAT) D 45 .S HLLMSTAT=X Q:HLLMSTAT=3 46 .S HLXX=$S('HLLMSTAT:"***LINK MANAGER NOT RUNNING!!!***",1:"") 47 .I 'HLLMSTAT D WDATA^HLCSMON1(45,18,IOELEOL_IOBON_IORVON,IOBOFF_IORVOFF,HLXX) I 1 48 .E D WDATA^HLCSMON1(45,18,IOELEOL,"",$J("Link Manager running",18)) 49 ;Turn terminal line wrap back on 50 D WDATA(45,19,IOELEOL,"",$$SLM^HLEVUTIL) ; HL*1.6*109 51 S X=IOM X ^%ZOSF("RM") 52 Q 53 ; 54 WLINE(HLXX) ;write line from HLARYD=current values, HLARYO=old values 55 ;if values haven't changed, don't do anything 56 I HLARYD(HLXX)]"",HLARYD(HLXX)=$G(HLARYO(HLXX)) Q 57 S HLARYO(HLXX)=HLARYD(HLXX),HLERR=$P(HLARYD(HLXX),U,8),DX=1 58 ; patch HL*1.6*122 59 ; F X=1:1:7 S @$P("HLNODE^HLREC^HLPROC^HLSEND^HLSENT^HLDEV^HLSTAT",U,X)=$E($P(HLARYD(HLXX),U,X)_" ",1,8) 60 F X=1,7 S @$P("HLNODE^HLREC^HLPROC^HLSEND^HLSENT^HLDEV^HLSTAT",U,X)=$E($P(HLARYD(HLXX),U,X)_" ",1,10) 61 F X=2:1:5 S @$P("HLNODE^HLREC^HLPROC^HLSEND^HLSENT^HLDEV^HLSTAT",U,X)=$E($P(HLARYD(HLXX),U,X)_" ",1,8) 62 S X=6,@$P("HLNODE^HLREC^HLPROC^HLSEND^HLSENT^HLDEV^HLSTAT",U,X)=$E($P(HLARYD(HLXX),U,X)_" ",1,7) 63 ; 64 ;if link is in error, write node in rev. video 65 I HLERR]"" D WDATA(5,HLXX,IOBON_IORVON,IOBOFF_IORVOFF,HLNODE,8) S DX=14 66 ;Turn off terminal line wrap & inform O/S where cursor is located 67 S DY=HLXX X IOXY,^%ZOSF("XY") 68 ; patch HL*1.6*122 69 W:HLERR="" ?4,HLNODE 70 W ?16,HLREC,?26,HLPROC,?37,HLSEND,?47,HLSENT,?58,HLDEV,?63,HLSTAT 71 ; 72 Q 73 ; 74 WDATA(DX,DY,IO1,IO2,HLDATA,HLENGTH) ; 75 ; 76 ;First erase the data block then write to it. Attributes are 77 ;contained in IO1 & IO2 78 ; 79 N X S X=0 X ^%ZOSF("RM") X ^%ZOSF("XY") 80 ;Turn off terminal line wrap & inform O/S where cursor is located 81 I '$D(HLENGTH) S HLENGTH=$L(HLDATA) 82 X IOXY W IOSC,$E($J(" ",79),1,HLENGTH),IORC W IO1,$E(HLDATA,1,HLENGTH),IO2 83 S X=IOM X ^%ZOSF("RM") 84 ;Turn terminal line wrap back on 85 Q 1 HLCSMON1 ;SF-Utilities for Driver Program ;02/04/2004 10:25 2 ;;1.6;HEALTH LEVEL SEVEN;**15,40,49,65,109**;Oct 13, 1995 3 ; 4 ;This routine contains several entry points called from HLCSMON 5 ;no input parameters are required. All variables used which are 6 ;not newed here are newed in HLCSMON 7 ; 8 DISPLAY ;display link info 9 ;turn of line wrap 10 S HLXX=0,X=0 X ^%ZOSF("RM") 11 F S HLXX=$O(HLARYD(HLXX)) Q:(HLXX'>0) D WLINE(HLXX) 12 ;DISPLAY INCOMING FILER STATUS 13 S HLXX=$$CNTFLR^HLCSUTL2("IN") 14 ;ONLY UPDATE SCREEN IF COUNT HAS CHANGED 15 I (HLXX'=+HLRUNCNT) D 16 .D WDATA(5,17,"","",$J(" ",31)),WDATA^HLCSMON1(5,17,"","","Incoming filers running => ",35) 17 .I (HLXX) D WDATA(32,17,"","",HLXX) 18 .I ('HLXX) D WDATA(32,17,IOINHI,IOINORM,"Zero") 19 .S $P(HLRUNCNT,"^",1)=HLXX 20 ;DISPLAY OUTGOING FILER STATUS 21 S HLXX=$$CNTFLR^HLCSUTL2("OUT") 22 ;ONLY UPDATE SCREEN IF COUNT HAS CHANGED 23 I (HLXX'=+$P(HLRUNCNT,"^",2)) D 24 .D WDATA(5,18,"","",$J(" ",31)),WDATA^HLCSMON1(5,18,"","","Outgoing filers running => ",35) 25 .I (HLXX) D WDATA(32,18,"","",HLXX) 26 .I ('HLXX) D WDATA(32,18,IOINHI,IOINORM,"Zero") 27 .S $P(HLRUNCNT,"^",2)=HLXX 28 S X=$$TM^%ZTLOAD 29 I X'=$G(HLTMSTAT) D 30 .S HLTMSTAT=X 31 .S HLXX=$S('HLTMSTAT:"***TASKMAN NOT RUNNING!!!***",1:"") 32 .I 'HLTMSTAT D WDATA^HLCSMON1(45,17,IOELEOL_IOBON_IORVON,IOBOFF_IORVOFF,HLXX) I 1 33 .E D WDATA(45,17,IOELEOL,"",$J("TaskMan running ",16)) ;D WDATA(5,19,IOELALL,"","") 34 S X=$$STAT^HLCSLM 35 I X'=$G(HLLMSTAT) D 36 .S HLLMSTAT=X Q:HLLMSTAT=3 37 .S HLXX=$S('HLLMSTAT:"***LINK MANAGER NOT RUNNING!!!***",1:"") 38 .I 'HLLMSTAT D WDATA^HLCSMON1(45,18,IOELEOL_IOBON_IORVON,IOBOFF_IORVOFF,HLXX) I 1 39 .E D WDATA^HLCSMON1(45,18,IOELEOL,"",$J("Link Manager running",18)) 40 ;Turn terminal line wrap back on 41 D WDATA(45,19,IOELEOL,"",$$SLM^HLEVUTIL) ; HL*1.6*109 42 S X=IOM X ^%ZOSF("RM") 43 Q 44 ; 45 WLINE(HLXX) ;write line from HLARYD=current values, HLARYO=old values 46 ;if values haven't changed, don't do anything 47 I HLARYD(HLXX)]"",HLARYD(HLXX)=$G(HLARYO(HLXX)) Q 48 S HLARYO(HLXX)=HLARYD(HLXX),HLERR=$P(HLARYD(HLXX),U,8),DX=1 49 F X=1:1:7 S @$P("HLNODE^HLREC^HLPROC^HLSEND^HLSENT^HLDEV^HLSTAT",U,X)=$E($P(HLARYD(HLXX),U,X)_" ",1,8) 50 ;if link is in error, write node in rev. video 51 I HLERR]"" D WDATA(5,HLXX,IOBON_IORVON,IOBOFF_IORVOFF,HLNODE,8) S DX=14 52 ;Turn off terminal line wrap & inform O/S where cursor is located 53 S DY=HLXX X IOXY,^%ZOSF("XY") 54 W:HLERR="" ?5,HLNODE 55 W ?16,HLREC,?26,HLPROC,?37,HLSEND,?47,HLSENT,?58,HLDEV,?64,HLSTAT 56 Q 57 ; 58 WDATA(DX,DY,IO1,IO2,HLDATA,HLENGTH) ; 59 ; 60 ;First erase the data block then write to it. Attributes are 61 ;contained in IO1 & IO2 62 ; 63 N X S X=0 X ^%ZOSF("RM") X ^%ZOSF("XY") 64 ;Turn off terminal line wrap & inform O/S where cursor is located 65 I '$D(HLENGTH) S HLENGTH=$L(HLDATA) 66 X IOXY W IOSC,$E($J(" ",79),1,HLENGTH),IORC W IO1,$E(HLDATA,1,HLENGTH),IO2 67 S X=IOM X ^%ZOSF("RM") 68 ;Turn terminal line wrap back on 69 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSREP.m
r613 r623 1 HLCSREP ;ALB/MFK - HL7 QUEUE MANAGEMENT ;10/17/2007 08:56 2 ;;1.6;HEALTH LEVEL SEVEN;**109,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 REPMSG ;Duplicate messages on a queue 6 ; INPUT: MSG - Array which contains the queue and the 7 ; message numbers for msgs to be re-queued 8 ; MSG(QUEUE,NUMBER) 9 ; OUTPUT: NONE 10 N DIC,LLE,X,Y,DA,ERROR,FROMID,MSGID 11 N TOID,ENTRY,LLE 12 Q:('$D(MSG)) 13 ; create new entries 14 S (LLE,ERROR)="" 15 F S LLE=$O(MSG(LLE)) Q:(LLE="")!(ERROR) D 16 .S ENTRY="" 17 .F S ENTRY=$O(MSG(LLE,ENTRY)) Q:(ENTRY="")!(ERROR) D 18 ..S MSGID=$$ENQUEUE^HLCSQUE(LLE,"OUT") 19 ..I +MSGID'>0 S ERROR=1 Q 20 ..S TOID=$P(MSGID,"^",2) 21 ..M ^HLCS(870,LLE,2,TOID)=^HLCS(870,LLE,2,ENTRY) 22 ..; Change .01 of new record to be IEN 23 ..S $P(^HLCS(870,LLE,2,TOID,0),"^",1)=TOID 24 ..S $P(^HLCS(870,LLE,2,TOID,0),"^",2)="P" 25 EXIT ; 26 Q 27 ; 28 ENQUE(LINK,DIR,IEN773) ; 29 ;This routine will place the message=IEN773 on the "AC" xref of file 773. 30 ;Input: 31 ; DIR = "I" or "O", denoting the direction that the message is going in 32 ; LINK = the ien of the logical link 33 ; IEN773 = ien of the message in file 773 34 ; 35 Q:'$G(LINK) 36 I DIR'="I",DIR'="O" Q 37 Q:'$G(IEN773) 38 ; 39 ; patch HL*1.6*122: MPI-client/server 40 F L +^HLMA("AC",DIR,LINK,IEN773):10 Q:$T H 1 41 S ^HLMA("AC",DIR,LINK,IEN773)="" 42 L -^HLMA("AC",DIR,LINK,IEN773) 43 ; 44 S $P(^HLMA(+IEN773,0),U,17)=+LINK ; HL*1.6*109 - lja 45 I DIR="O" D LLCNT^HLCSTCP(LINK,3) 46 Q 47 ; 48 DEQUE(LINK,DIR,IEN773) ; 49 ;This routine will remove the message=IEN773 on the "AC" xref of file 773. 50 ;Input: 51 ; DIR = "I" or "O", denoting the direction that the message is going in 52 ; LINK = the ien of the logical link 53 ; IEN773 = ien of the message in file 773 54 ; 55 Q:'$G(LINK) 56 I DIR'="I",DIR'="O" Q 57 Q:'$G(IEN773) 58 ; 59 ; patch HL*1.6*122: MPI-client/server 60 F L +^HLMA("AC",DIR,LINK,IEN773):10 Q:$T H 1 61 K ^HLMA("AC",DIR,LINK,IEN773) 62 L -^HLMA("AC",DIR,LINK,IEN773) 63 ; 64 Q 1 HLCSREP ;ALB/MFK - HL7 QUEUE MANAGEMENT - 10/4/94 1pm 2 ;;1.6;HEALTH LEVEL SEVEN;**109**;Oct 13, 1995 3 REPMSG ;Duplicate messages on a queue 4 ; INPUT: MSG - Array which contains the queue and the 5 ; message numbers for msgs to be re-queued 6 ; MSG(QUEUE,NUMBER) 7 ; OUTPUT: NONE 8 N DIC,LLE,X,Y,DA,ERROR,FROMID,MSGID 9 N TOID,ENTRY,LLE 10 Q:('$D(MSG)) 11 ; create new entries 12 S (LLE,ERROR)="" 13 F S LLE=$O(MSG(LLE)) Q:(LLE="")!(ERROR) D 14 .S ENTRY="" 15 .F S ENTRY=$O(MSG(LLE,ENTRY)) Q:(ENTRY="")!(ERROR) D 16 ..S MSGID=$$ENQUEUE^HLCSQUE(LLE,"OUT") 17 ..I +MSGID'>0 S ERROR=1 Q 18 ..S TOID=$P(MSGID,"^",2) 19 ..M ^HLCS(870,LLE,2,TOID)=^HLCS(870,LLE,2,ENTRY) 20 ..; Change .01 of new record to be IEN 21 ..S $P(^HLCS(870,LLE,2,TOID,0),"^",1)=TOID 22 ..S $P(^HLCS(870,LLE,2,TOID,0),"^",2)="P" 23 EXIT ; 24 Q 25 ; 26 ENQUE(LINK,DIR,IEN773) ; 27 ;This routine will place the message=IEN773 on the "AC" xref of file 773. 28 ;Input: 29 ; DIR = "I" or "O", denoting the direction that the message is going in 30 ; LINK = the ien of the logical link 31 ; IEN773 = ien of the message in file 773 32 ; 33 Q:'$G(LINK) 34 I DIR'="I",DIR'="O" Q 35 Q:'$G(IEN773) 36 S ^HLMA("AC",DIR,LINK,IEN773)="" 37 S $P(^HLMA(+IEN773,0),U,17)=+LINK ; HL*1.6*109 - lja 38 I DIR="O" D LLCNT^HLCSTCP(LINK,3) 39 Q 40 ; 41 DEQUE(LINK,DIR,IEN773) ; 42 ;This routine will remove the message=IEN773 on the "AC" xref of file 773. 43 ;Input: 44 ; DIR = "I" or "O", denoting the direction that the message is going in 45 ; LINK = the ien of the logical link 46 ; IEN773 = ien of the message in file 773 47 ; 48 Q:'$G(LINK) 49 I DIR'="I",DIR'="O" Q 50 Q:'$G(IEN773) 51 K ^HLMA("AC",DIR,LINK,IEN773) 52 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSTCP.m
r613 r623 1 HLCSTCP ;SFIRMFO/TNV-ALB/JFP,PKE - (TCP/IP) MLLP ;04/15/2008 10:58 2 ;;1.6;HEALTH LEVEL SEVEN;**19,43,49,57,58,64,84,109,133,122,140**;Oct 13, 1995;Build 5 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ; This is an implementation of the HL7 Minimal Lower Layer Protocol 6 ; taskman entry/startup option, HLDP defined in menu entry. 7 ; 8 Q:'$D(HLDP) 9 ; patch HL*1.6*122 start 10 L +^HLCS("HLTCPLINK",HLDP):5 I '$T D Q 11 . D MON^HLCSTCP("TskLcked") 12 N HLCSOUT,HLDBACK,HLDBSIZE,HLDREAD,HLDRETR,HLRETRA,HLDWAIT,HLOS,HLTCPADD,HLTCPCS,HLTCPLNK,HLTCPORT,HLTCPRET 13 N HLZRULE 14 ;HLCSOUT= 1-error 15 I '$$INIT D EXITS("Init Error") Q 16 S HLDP("$J")=$J 17 S HLDP("$J",0,"LENGTH")=$L(HLDP("$J")) 18 ; Start the client 19 I $G(HLTCPCS)="C" D Q 20 . S HLDP("$J",0,"START")=HLDP("$J",0,"LENGTH")-8+$L(HLTCPORT)+$L(HLDP) 21 . I HLDP("$J",0,"START")<1 S HLDP("$J",0,"START")=1 22 . S HLDP("$J",0)=$E(HLDP("$J"),HLDP("$J",0,"START"),HLDP("$J",0,"LENGTH")) 23 . ; identify process for ^%SY 24 . ; D SETNM^%ZOSV($E("HLClnt:"_HLDP,1,15)) 25 . D SETNM^%ZOSV($E("HLc:"_HLTCPORT_"-"_HLDP_"-"_HLDP("$J",0),1,15)) 26 . K HLDP("$J",0) 27 . D ST1 28 . F D ^HLCSTCP2 Q:$$STOP!$G(HLCSOUT) 29 . ; I $G(HLCSOUT)=1 D MON("Error") H 1 Q 30 . I $G(HLCSOUT)=1 D Q 31 .. D MON("Error") H 1 32 .. L -^HLCS("HLTCPLINK",HLDP) 33 . I $G(HLCSOUT)=2 D EXITS("Inactive") Q 34 . D EXITS("Shutdown") 35 ; 36 S HLDP("$J",0,"START")=HLDP("$J",0,"LENGTH")-9+$L(HLTCPORT) 37 I HLDP("$J",0,"START")<1 S HLDP("$J",0,"START")=1 38 S HLDP("$J",0)=$E(HLDP("$J"),HLDP("$J",0,"START"),HLDP("$J",0,"LENGTH")) 39 ; identify process for ^%SY 40 ; D SETNM^%ZOSV($E("HLSrv:"_HLDP,1,15)) 41 D SETNM^%ZOSV($E("HLs:"_HLTCPORT_"-"_HLDP("$J",0),1,15)) 42 K HLDP("$J",0) 43 ; to stop the listener via updated Kernel API, need to pass the 44 ; listener logical link (HLDP) 45 S HLZRULE="S HLDP="_HLDP_" S ZISQUIT=$$STOP^HLCSTCP" 46 ;single threaded listener 47 I $G(HLTCPCS)="S" D Q 48 . D ST1,MON("Listen"),LISTEN^%ZISTCP(HLTCPORT,"SERVER^HLCSTCP("""_HLDP_""")",HLZRULE) 49 . I $$STOP D EXITS("Shutdown") Q 50 . D EXITS("Openfail") 51 ; 52 ;multi-threaded listener (for OpenM/NT) 53 I ($G(HLTCPCS)'="M")!(^%ZOSF("OS")'["OpenM") D Q 54 . L -^HLCS("HLTCPLINK",HLDP) 55 I $$OS^%ZOSV["VMS" L -^HLCS("HLTCPLINK",HLDP) Q 56 D ST1,MON("Listen"),LISTEN^%ZISTCPS(HLTCPORT,"SERVERS^HLCSTCP("""_HLDP_""")",HLZRULE) 57 ; update status of listener 58 I $$STOP D EXITS("Shutdown") Q 59 D EXITS("Openfail") 60 ; HL*1.6*122 end 61 Q 62 ; 63 SERVER(HLDP) ; single server using Taskman 64 I '$$INIT D EXITS("Init error") Q 65 D ^HLCSTCP1 66 I $$STOP D CLOSE^%ZISTCP,EXITS("Shutdown") S IO("C")="" Q 67 Q:$G(HLCSOUT)=1 68 D MON("Idle") 69 Q 70 ; 71 SERVERS(HLDP) ; Multi-threaded server using Taskman 72 I '$$INIT D EXITS("Init error") Q 73 G LISTEN 74 ; 75 ;multiple process servers, called from an external utility 76 MSM ;MSM entry point, called from User-Defined Services 77 ;HLDP=ien in the HL LOWER LEVEL PROTOCOL PARAMETER file for the 78 ;HL7 Multi-Threaded SERVER 79 S (IO,IO(0))=$P 80 G LISTEN 81 ; 82 LISTEN ; 83 N HLLSTN,HLCSOUT,HLDBACK,HLDBSIZE,HLDREAD,HLDRETR,HLRETRA,HLDWAIT,HLOS,HLTCPADD,HLTCPCS,HLTCPLNK,HLTCPORT,HLTCPRET 84 I '$$INIT D ^%ZTER Q 85 ; patch HL*1.6*122 start 86 S HLDP("$J")=$J 87 S HLDP("$J",0,"LENGTH")=$L(HLDP("$J")) 88 S HLDP("$J",0,"START")=HLDP("$J",0,"LENGTH")-9+$L(HLTCPORT) 89 I HLDP("$J",0,"START")<1 S HLDP("$J",0,"START")=1 90 S HLDP("$J",0)=$E(HLDP("$J"),HLDP("$J",0,"START"),HLDP("$J",0,"LENGTH")) 91 ; identify process for ^%SY 92 ; D SETNM^%ZOSV($E("HLSrv:"_HLDP,1,15)) 93 D SETNM^%ZOSV($E("HLs:"_HLTCPORT_"-"_HLDP("$J",0),1,15)) 94 K HLDP("$J",0) 95 ; patch HL*1.6*122 end 96 ;HLLSTN used to identify a listener to tag MON 97 S HLLSTN=1 98 ;increment job count, run server 99 D UPDT(1),^HLCSTCP1,EXITM 100 Q 101 ; 102 DCOPEN(HLDP) ;open direct connect - called from HLMA2 103 Q:'$$INIT 0 104 Q:HLTCPADD=""!(HLTCPORT="") 0 105 Q:'$$OPEN^HLCSTCP2 0 106 Q 1 107 ; 108 INIT() ; Initialize Variables 109 ; HLDP should be set to the IEN or name of Logical Link, file 870 110 S HLOS=$P($G(^%ZOSF("OS")),"^") 111 N DA,DIQUIET,DR,TMP,X,Y 112 ; patch HL*1.6*140 113 ; S IOF=$$FLUSHCHR^%ZISTCP ; HL*1.6*122 set device flush character 114 S HLTCPLNK("IOF")=$$FLUSHCHR^%ZISTCP 115 S DIQUIET=1 116 D DT^DICRW 117 I 'HLDP S HLDP=$O(^HLCS(870,"B",HLDP,0)) I 'HLDP Q 0 118 S DA=HLDP 119 ; patch HL*1.6*122 for field 400.09 120 S DR="200.02;200.021;200.022;200.03;200.04;200.05;200.09;400.01;400.02;400.03;400.04;400.05;400.09" 121 D GETS^DIQ(870,DA,DR,"IN","TMP","TMP") 122 ; 123 I $D(TMP("DIERR")) QUIT 0 124 ; -- re-transmit attempts 125 S HLDRETR=+$G(TMP(870,DA_",",200.02,"I")) 126 S HLDRETR("CLOSE")=+$G(TMP(870,DA_",",200.022,"I")) 127 ; -- exceed re-transmit action 128 S HLRETRA=$G(TMP(870,DA_",",200.021,"I")) 129 ; -- block size 130 S HLDBSIZE=+$G(TMP(870,DA_",",200.03,"I")) 131 ; -- read timeout 132 S HLDREAD=+$G(TMP(870,DA_",",200.04,"I")) 133 ; -- ack timeout 134 S HLDBACK=+$G(TMP(870,DA_",",200.05,"I")) 135 ; -- uni-directional wait 136 S HLDWAIT=$G(TMP(870,DA_",",200.09,"I")) 137 ; -- tcp address 138 S HLTCPADD=$G(TMP(870,DA_",",400.01,"I")) 139 ; -- tcp port 140 S HLTCPORT=$G(TMP(870,DA_",",400.02,"I")) 141 ; -- tcp/ip service type 142 S HLTCPCS=$G(TMP(870,DA_",",400.03,"I")) 143 ; -- link persistence 144 S HLTCPLNK=$G(TMP(870,DA_",",400.04,"I")) 145 ; -- retention 146 S HLTCPRET=$G(TMP(870,DA_",",400.05,"I")) 147 ; 148 ; patch HL*1.6*140 149 ; patch HL*1.6*122 for field 400.09 150 ; -- tcp/ip openfail timeout 151 ; S HLTCPLNK("TIMEOUT")=$G(TMP(870,DA_",",400.09,"I")) 152 S HLTCPLNK("TIMEOUT")=+$G(TMP(870,DA_",",400.09,"I")) 153 ; 154 ; -- set defaults in case something's not set 155 S:HLDREAD=0 HLDREAD=10 156 S:HLDBACK=0 HLDBACK=60 157 ; patch HL*1.6*122 158 ; S:HLDBSIZE=0 HLDBSIZE=245 159 S:HLDBSIZE<245 HLDBSIZE=245 160 S:HLDRETR=0 HLDRETR=5 161 S:HLTCPRET="" X=$P($$PARAM^HLCS2,U,12),HLTCPRET=$S(X:X,1:15) 162 ; 163 ; patch HL*1.6*140, the defaut is 30 164 ; patch HL*1.6*122 for field 400.09 165 ; S:HLTCPLNK("TIMEOUT")=0 HLTCPLNK("TIMEOUT")=5 166 S:(HLTCPLNK("TIMEOUT")<1) HLTCPLNK("TIMEOUT")=30 167 ; 168 Q 1 169 ; 170 ST1 ;record startup in 870 for single server 171 ;4=status 9=Time Started, 10=Time Stopped, 11=Task Number 172 ;14=Shutdown LLP, 3=LLP Online, 18=Gross Errors 173 N HLJ,X 174 ; HL*1.6*122 remove unnecessary locks 175 ;F L +^HLCS(870,HLDP,0):2 Q:$T 176 S X="HLJ(870,"""_HLDP_","")" 177 S @X@(4)="Init",(@X@(10),@X@(18))="@",@X@(14)=0 178 I HLTCPCS["C" S @X@(3)=$S(HLTCPLNK["Y":"PC",1:"NC") 179 E S @X@(3)=$S(HLTCPCS["S":"SS",HLTCPCS["M":"MS",1:"") 180 I @X@(3)'="NC" S @X@(9)=$$NOW^XLFDT 181 S:$G(ZTSK) @X@(11)=ZTSK 182 D FILE^HLDIE("","HLJ","","ST1","HLCSTCP") ;HL*1.6*109 183 ;L -^HLCS(870,HLDP,0) 184 Q 185 ; 186 MON(Y) ;Display current state & check for shutdown 187 ;don't display for multiple server 188 Q:$G(HLLSTN) 189 ; HL*1.6*122 remove unnecessary locks 190 ;F L +^HLCS(870,HLDP,0):2 Q:$T 191 S $P(^HLCS(870,HLDP,0),U,5)=Y 192 ;L -^HLCS(870,HLDP,0) 193 Q:'$D(HLTRACE) 194 N X U IO(0) 195 W !,"IN State: ",Y 196 I '$$STOP D 197 . ; patch HL*1.6*122 198 . ; R !,"Type Q to Quit: ",X#1:1 199 . R !,"Type Q to Quit: ",X:1 200 . ; I $L(X),"Qq"[X S $P(^HLCS(870,HLDP,0),U,15)=1 201 . I $L(X),"Qq"[$E(X) S $P(^HLCS(870,HLDP,0),U,15)=1 202 . ; patch HL*1.6*122 end 203 U IO 204 Q 205 UPDT(Y) ;update job count for multiple servers,X=1 increment 206 N HLJ,X 207 ; 208 ; HL*1.6*122 start 209 ; F L +^HLCS(870,HLDP,0):2 Q:$T 210 Q:'$G(HLDP) 211 Q:'$D(^HLCS(870,"E","M",HLDP)) 212 F L +^HLCS(870,HLDP,0):10 Q:$T H 1 213 ; S X=+$P(^HLCS(870,HLDP,0),U,5),$P(^(0),U,5)=$S(Y:X+1,1:X-1)_" server" 214 S X=+$P(^HLCS(870,HLDP,0),U,5) 215 I X<0 S X=0 216 S $P(^HLCS(870,HLDP,0),U,5)=$S(Y:(X+1),X<1:0,1:X-1)_" server" 217 ;if incrementing, set the Device Type field to Multi-Server 218 ; I X S HLJ(870,HLDP_",",3)="MS" D FILE^HLDIE("","HLJ","","UPDT","HLCSTCP") 219 I $P(^HLCS(870,HLDP,0),"^",4)']"" S $P(^HLCS(870,HLDP,0),"^",4)="MS" 220 ; HL*1.6*122 end 221 ; 222 L -^HLCS(870,HLDP,0) 223 Q 224 STOP() ;stop flag set 225 N X 226 F L +^HLCS(870,HLDP,0):2 Q:$T 227 S X=+$P(^HLCS(870,HLDP,0),U,15) 228 L -^HLCS(870,HLDP,0) 229 Q X 230 ; 231 LLCNT(DP,Y,Z) ;update Logical Link counters 232 ;DP=ien of Logical Link in file 870 233 ;Y: 1=msg rec, 2=msg proc, 3=msg to send, 4=msg sent 234 ;Z: ""=add to counter, 1=subtract from counter 235 Q:'$D(^HLCS(870,+$G(DP),0))!('$G(Y)) 236 N P,X 237 S P=$S(Y<3:"IN",1:"OUT")_" QUEUE "_$S(Y#2:"BACK",1:"FRONT")_" POINTER" 238 ; patch HL*1.6*122 start 239 ; F L +^HLCS(870,DP,P):2 Q:$T 240 ; S X=+$G(^HLCS(870,DP,P)),^(P)=X+$S($G(Z):-1,1:1) 241 I '$L($G(OS)) N OS S OS=$G(^%ZOSF("OS")) 242 I OS'["DSM",OS'["OpenM" D 243 . F L +^HLCS(870,DP,P):10 Q:$T H 1 244 . S X=+$G(^HLCS(870,DP,P)),^(P)=X+$S($G(Z):-1,1:1) 245 . L -^HLCS(870,DP,P) 246 E D 247 . S X=$I(^HLCS(870,DP,P),$S($G(Z):-1,1:1)) 248 ; L -^HLCS(870,DP,P) 249 ; patch HL*1.6*122 end 250 Q 251 SDFLD ; set Shutdown? field to yes 252 Q:'$G(HLDP) 253 ; HL*1.6*122 remove unnecessary lock and call to FM 254 S $P(^HLCS(870,HLDP,0),U,15)=1 255 ;N HLJ,X 256 ;F L +^HLCS(870,HLDP,0):2 Q:$T 257 ;14=Shutdown LLP? 258 ;S HLJ(870,HLDP_",",14)=1 259 ;D FILE^HLDIE("","HLJ","","SDFLD","HLCSTCP") ;HL*1.6*109 260 ;L -^HLCS(870,HLDP,0) 261 Q 262 ; 263 EXITS(Y) ; shutdown and clean up the listener process for either 264 ; single-threaded or multi-threaded 265 N HLJ,X 266 F L +^HLCS(870,HLDP,0):2 Q:$T 267 ;4=status,10=Time Stopped,9=Time Started,11=Task Number 268 S X="HLJ(870,"""_HLDP_","")" 269 S @X@(4)=Y,@X@(11)="@" 270 S:$G(HLCSOUT)'=2 @X@(10)=$$NOW^XLFDT,@X@(9)="@" 271 D FILE^HLDIE("","HLJ","","EXITS","HLCSTCP") ; HL*1.6*109 272 L -^HLCS(870,HLDP,0) 273 I $D(ZTQUEUED) S ZTREQ="@" 274 ; HL*1.6*122 275 L -^HLCS("HLTCPLINK",HLDP) 276 Q 277 ; 278 EXITM ;Multiple service shutdown and clean up 279 ; shutdown and clean up a connection spawned by the listener 280 ; process for a multi-threaded listener 281 D UPDT(0) 282 I $D(ZTQUEUED) S ZTREQ="@" 283 Q 1 HLCSTCP ;SFIRMFO/TNV-ALB/JFP,PKE - (TCP/IP) MLLP ;09/13/2006 2 ;;1.6;HEALTH LEVEL SEVEN;**19,43,49,57,58,64,84,109,133**;Oct 13, 1995;Build 13 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ; This is an implementation of the HL7 Minimal Lower Layer Protocol 6 ; 7 ;taskman entry/startup option, HLDP defined in menu entry, 8 Q:'$D(HLDP) 9 N HLCSOUT,HLDBACK,HLDBSIZE,HLDREAD,HLDRETR,HLRETRA,HLDWAIT,HLOS,HLTCPADD,HLTCPCS,HLTCPLNK,HLTCPORT,HLTCPRET,HLCSFAIL 10 ;HLCSOUT= 1-error 11 I '$$INIT D EXITS("Init Error") Q 12 ; Start the client 13 I $G(HLTCPCS)="C" D Q 14 . ; identify process for ^%SY 15 . D SETNM^%ZOSV($E("HLClnt:"_HLDP,1,15)) 16 . D ST1 17 . F D ^HLCSTCP2 Q:$$STOP!$G(HLCSOUT) 18 . I $G(HLCSOUT)=1 D MON("Error") H 1 Q 19 . I $G(HLCSOUT)=2 D EXITS("Inactive") Q 20 . D EXITS("Shutdown") 21 ; 22 ; identify process for ^%SY 23 D SETNM^%ZOSV($E("HLSrv:"_HLDP,1,15)) 24 ;HLCSFAIL=1 port failed to open 25 S HLCSFAIL=1 26 ;single threaded listener 27 I $G(HLTCPCS)="S" D Q 28 . D ST1,MON("Listen"),LISTEN^%ZISTCP(HLTCPORT,"SERVER^HLCSTCP("""_HLDP_""")") 29 . ;couldn't open listener port 30 . I HLCSFAIL D EXITS("Openfail") Q 31 ; 32 ;multi-threaded listener (OpenM) 33 I $G(HLTCPCS)="M",^%ZOSF("OS")["OpenM" D Q 34 . D ST1,MON("Listen"),LISTEN^%ZISTCPS(HLTCPORT,"SERVERS^HLCSTCP("""_HLDP_""")") 35 Q 36 ; 37 SERVER(HLDP) ; single server using Taskman 38 S HLCSFAIL=0 39 I '$$INIT D EXITS("Init error") Q 40 D ^HLCSTCP1 41 I $$STOP D CLOSE^%ZISTCP,EXITS("Shutdown") S IO("C")="" Q 42 Q:$G(HLCSOUT)=1 43 D MON("Idle") 44 Q 45 ; 46 SERVERS(HLDP) ; Multi-threaded server using Taskman 47 I '$$INIT D EXITS("Init error") Q 48 G LISTEN 49 ; 50 ;multiple process servers, called from an external utility 51 MSM ;MSM entry point, called from User-Defined Services 52 ;HLDP=ien in the HL LOWER LEVEL PROTOCOL PARAMETER file for the 53 ;HL7 Multi-Threaded SERVER 54 S (IO,IO(0))=$P 55 G LISTEN 56 ; 57 CACHEVMS(%) ;Cache'/VMS tcpip/ucx entry point, called from HLSEVEN.COM file, 58 ;listener, % = HLDP 59 I $G(%)="" D ^%ZTER Q 60 S IO="SYS$NET",HLDP=% 61 S IO(0)="_NLA0:" O IO(0) ;Setup null device 62 ; **Cache'/VMS specific code** 63 O IO::5 E D MON("Openfail") Q 64 X "U IO:(::""-M"")" ;Packet mode like DSM 65 D LISTEN C IO Q 66 ; 67 EN ;vms ucx entry point, called from HLSEVEN.COM file, 68 ;listener, % = device^HLDP 69 I $G(%)="" D ^%ZTER Q 70 S IO="SYS$NET",U="^",HLDP=$P(%,U,2) 71 S IO(0)="_NLA0:" O IO(0) ;Setup null device 72 ; **VMS specific code, need to share device** 73 O IO:(TCPDEV):60 E D MON("Openfail") Q 74 LISTEN ; 75 N HLLSTN,HLCSOUT,HLDBACK,HLDBSIZE,HLDREAD,HLDRETR,HLRETRA,HLDWAIT,HLOS,HLTCPADD,HLTCPCS,HLTCPLNK,HLTCPORT,HLTCPRET,HLCSFAIL 76 I '$$INIT D ^%ZTER Q 77 ; identify process for ^%SY 78 D SETNM^%ZOSV($E("HLSrv:"_HLDP,1,15)) 79 ;HLLSTN used to identify a listener to tag MON 80 S HLLSTN=1 81 ;increment job count, run server 82 D UPDT(1),^HLCSTCP1,EXITM 83 Q 84 ; 85 DCOPEN(HLDP) ;open direct connect - called from HLMA2 86 Q:'$$INIT 0 87 Q:HLTCPADD=""!(HLTCPORT="") 0 88 Q:'$$OPEN^HLCSTCP2 0 89 Q 1 90 ; 91 INIT() ; Initialize Variables 92 ; HLDP should be set to the IEN or name of Logical Link, file 870 93 S HLOS=$P($G(^%ZOSF("OS")),"^") 94 N DA,DIQUIET,DR,TMP,X,Y 95 S DIQUIET=1 96 D DT^DICRW 97 I 'HLDP S HLDP=$O(^HLCS(870,"B",HLDP,0)) I 'HLDP Q 0 98 S DA=HLDP 99 S DR="200.02;200.021;200.022;200.03;200.04;200.05;200.09;400.01;400.02;400.03;400.04;400.05" 100 D GETS^DIQ(870,DA,DR,"IN","TMP","TMP") 101 ; 102 I $D(TMP("DIERR")) QUIT 0 103 ; -- re-transmit attempts 104 S HLDRETR=+$G(TMP(870,DA_",",200.02,"I")) 105 S HLDRETR("CLOSE")=+$G(TMP(870,DA_",",200.022,"I")) 106 ; -- exceed re-transmit action 107 S HLRETRA=$G(TMP(870,DA_",",200.021,"I")) 108 ; -- block size 109 S HLDBSIZE=+$G(TMP(870,DA_",",200.03,"I")) 110 ; -- read timeout 111 S HLDREAD=+$G(TMP(870,DA_",",200.04,"I")) 112 ; -- ack timeout 113 S HLDBACK=+$G(TMP(870,DA_",",200.05,"I")) 114 ; -- uni-directional wait 115 S HLDWAIT=$G(TMP(870,DA_",",200.09,"I")) 116 ; -- tcp address 117 S HLTCPADD=$G(TMP(870,DA_",",400.01,"I")) 118 ; -- tcp port 119 S HLTCPORT=$G(TMP(870,DA_",",400.02,"I")) 120 ; -- tcp/ip service type 121 S HLTCPCS=$G(TMP(870,DA_",",400.03,"I")) 122 ; -- link persistence 123 S HLTCPLNK=$G(TMP(870,DA_",",400.04,"I")) 124 ; -- retention 125 S HLTCPRET=$G(TMP(870,DA_",",400.05,"I")) 126 ; 127 ; -- set defaults in case something's not set 128 S:HLDREAD=0 HLDREAD=10 129 S:HLDBACK=0 HLDBACK=60 130 S:HLDBSIZE=0 HLDBSIZE=245 131 S:HLDRETR=0 HLDRETR=5 132 S:HLTCPRET="" X=$P($$PARAM^HLCS2,U,12),HLTCPRET=$S(X:X,1:15) 133 ; 134 Q 1 135 ; 136 ST1 ;record startup in 870 for single server 137 ;4=status 9=Time Started, 10=Time Stopped, 11=Task Number 138 ;14=Shutdown LLP, 3=LLP Online, 18=Gross Errors 139 N HLJ,X 140 F L +^HLCS(870,HLDP,0):2 Q:$T 141 S X="HLJ(870,"""_HLDP_","")" 142 S @X@(4)="Init",(@X@(10),@X@(18))="@",@X@(14)=0 143 I HLTCPCS["C" S @X@(3)=$S(HLTCPLNK["Y":"PC",1:"NC") 144 E S @X@(3)=$S(HLTCPCS["S":"SS",HLTCPCS["M":"MS",1:"") 145 I @X@(3)'="NC" S @X@(9)=$$NOW^XLFDT 146 S:$G(ZTSK) @X@(11)=ZTSK 147 D FILE^HLDIE("","HLJ","","ST1","HLCSTCP") ;HL*1.6*109 148 L -^HLCS(870,HLDP,0) 149 Q 150 ; 151 MON(Y) ;Display current state & check for shutdown 152 ;don't display for multiple server 153 Q:$G(HLLSTN) 154 F L +^HLCS(870,HLDP,0):2 Q:$T 155 S $P(^HLCS(870,HLDP,0),U,5)=Y 156 L -^HLCS(870,HLDP,0) 157 Q:'$D(HLTRACE) 158 N X U IO(0) 159 W !,"IN State: ",Y 160 I '$$STOP D 161 . R !,"Type Q to Quit: ",X#1:1 162 . I $L(X),"Qq"[X S $P(^HLCS(870,HLDP,0),U,15)=1 163 U IO 164 Q 165 UPDT(Y) ;update job count for multiple servers,X=1 increment 166 N HLJ,X 167 F L +^HLCS(870,HLDP,0):2 Q:$T 168 S X=+$P(^HLCS(870,HLDP,0),U,5),$P(^(0),U,5)=$S(Y:X+1,1:X-1)_" server" 169 ;if incrementing, set the Device Type field to Multi-Server 170 I X S HLJ(870,HLDP_",",3)="MS" D FILE^HLDIE("","HLJ","","UPDT","HLCSTCP") ;HL*1.6*109 171 L -^HLCS(870,HLDP,0) 172 Q 173 STOP() ;stop flag set 174 N X 175 F L +^HLCS(870,HLDP,0):2 Q:$T 176 S X=+$P(^HLCS(870,HLDP,0),U,15) 177 L -^HLCS(870,HLDP,0) 178 Q X 179 ; 180 LLCNT(DP,Y,Z) ;update Logical Link counters 181 ;DP=ien of Logical Link in file 870 182 ;Y: 1=msg rec, 2=msg proc, 3=msg to send, 4=msg sent 183 ;Z: ""=add to counter, 1=subtract from counter 184 Q:'$D(^HLCS(870,+$G(DP),0))!('$G(Y)) 185 N P,X 186 S P=$S(Y<3:"IN",1:"OUT")_" QUEUE "_$S(Y#2:"BACK",1:"FRONT")_" POINTER" 187 F L +^HLCS(870,DP,P):2 Q:$T 188 S X=+$G(^HLCS(870,DP,P)),^(P)=X+$S($G(Z):-1,1:1) 189 L -^HLCS(870,DP,P) 190 Q 191 SDFLD ; set Shutdown? field to yes 192 Q:'$G(HLDP) 193 N HLJ,X 194 F L +^HLCS(870,HLDP,0):2 Q:$T 195 ;14=Shutdown LLP? 196 S HLJ(870,HLDP_",",14)=1 197 D FILE^HLDIE("","HLJ","","SDFLD","HLCSTCP") ;HL*1.6*109 198 L -^HLCS(870,HLDP,0) 199 Q 200 ; 201 EXITS(Y) ; Single service shutdown and cleans up 202 N HLJ,X 203 F L +^HLCS(870,HLDP,0):2 Q:$T 204 ;4=status,10=Time Stopped,9=Time Started,11=Task Number 205 S X="HLJ(870,"""_HLDP_","")" 206 S @X@(4)=Y,@X@(11)="@" 207 S:$G(HLCSOUT)'=2 @X@(10)=$$NOW^XLFDT,@X@(9)="@" 208 D FILE^HLDIE("","HLJ","","EXITS","HLCSTCP") ; HL*1.6*109 209 L -^HLCS(870,HLDP,0) 210 I $D(ZTQUEUED) S ZTREQ="@" 211 Q 212 ; 213 EXITM ;Multiple service shutdown and clean up 214 D UPDT(0) 215 I $D(ZTQUEUED) S ZTREQ="@" 216 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSTCP1.m
r613 r623 1 HLCSTCP1 ;SFIRMFO/RSD - BI-DIRECTIONAL TCP ;04/15/08 11:11 2 ;;1.6;HEALTH LEVEL SEVEN;**19,43,57,64,71,133,132,122,140**;OCT 13,1995;Build 5 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ;Receiver 5 ;connection is initiated by sender and listener accepts connection 6 ;and calls this routine 7 ; 8 N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP1" 9 N HLMIEN,HLASTMSG 10 ; 11 ; patch HL*1.6*140, save IO 12 S HLTCPORT("IO")=IO ;RWF 13 ; patch HL*1.6*122 start 14 ; variable to replace ^TMP 15 N HLTMBUF 16 ; 17 ; for HL7 application proxy user 18 ;; N HLDUZ,DUZ ; patch HL*1.6*122 TEST v2: DUZ code removed 19 N HLDUZ 20 S HLDUZ=+$G(DUZ) 21 ; 22 D MON^HLCSTCP("Open") 23 ; K ^TMP("HLCSTCP",$J,0) 24 S HLMIEN=0,HLASTMSG="" 25 ; 26 ; patch HL*1.6*122 TEST v2: DUZ code removed 27 ; set DUZ for application proxy user 28 ;; D PROXY^HLCSTCP4 29 ; 30 F D Q:$$STOP^HLCSTCP I 'HLMIEN D MON^HLCSTCP("Idle") H 3 31 . ; clean variables 32 . D CLEANVAR^HLCSTCP4 33 . ; patch HL*1.6*140, restore the saved IO 34 . S IO=HLTCPORT("IO") ;RWF 35 . S HLMIEN=$$READ 36 . Q:'HLMIEN 37 . ; 38 . ; patch HL*1.6*122 TEST v2: DUZ code removed 39 . ; DUZ comparison/reset for application proxy user 40 . ;; D HLDUZ^HLCSTCP4 41 . D HLDUZ2^HLCSTCP4 42 . ; protect HLDUZ 43 . N HLDUZ 44 . D PROCESS 45 ; patch HL*1.6*122 end 46 Q 47 ; 48 PROCESS ;check message and reply 49 ;HLDP=LL in 870 50 N HLTCP,HLTCPI,HLTCPO 51 S HLTCP="",HLTCPO=HLDP,HLTCPI=+HLMIEN 52 ;update monitor, msg. received 53 D LLCNT^HLCSTCP(HLDP,1) 54 D NEW^HLTP3(HLMIEN) 55 ;I IO'=HLTCPORT("IO") D ^%ZTER ;RWF 56 ;update monitor, msg. processed 57 D LLCNT^HLCSTCP(HLDP,2) 58 Q 59 ; 60 READ() ;read 1 message, returns ien in 773^ien in 772 for message 61 D MON^HLCSTCP("Reading") 62 N HLDB,HLDT,HLDEND,HLACKWT,HLDSTRT,HLHDR,HLIND1,HLINE,HLMSG,HLRDOUT,HLRS,HLX,X 63 ;HLDSTRT=start char., HLDEND=end char., HLRS=record separator 64 S HLDSTRT=$C(11),HLDEND=$C(28),HLRS=$C(13) 65 ;HLRDOUT=exit read loop, HLINE=line count, HLIND1=ien 773^ien 772 66 ;HLHDR=have a header, HLTMBUF()=excess from last read, HLACKWT=wait for ack 67 ; HL*1.6*122 start 68 ; S (HLRDOUT,HLINE,HLIND1,HLHDR)=0,HLX=$G(^TMP("HLCSTCP",$J,0)),HLACKWT=HLDBACK 69 S (HLRDOUT,HLINE,HLIND1,HLHDR)=0,HLX=$G(HLTMBUF(0)),HLACKWT=HLDBACK 70 N HLBUFF,HLXX,MAXWAIT 71 ; based on patch 132 for readtime 72 S MAXWAIT=$S((HLACKWT>HLDREAD):HLACKWT,1:HLDREAD) 73 S HLRS("START-FLAG")=0 74 S HLTMBUF(0)="" 75 ; variable used to store data in HLBUFF 76 S HLX(1)=$G(HLTMBUF(1)) 77 S HLTMBUF(1)="" 78 S HLBUFF("START")=0 79 S HLBUFF("END")=0 80 I (HLX]"")!(HLX(1)]"") D 81 . I (HLX[HLDSTRT)!(HLX(1)[HLDSTRT) D 82 .. S HLBUFF("START")=1 83 . I (HLX[HLDEND)!(HLX(1)[HLDEND) D 84 .. S HLBUFF("END")=1 85 F D RDBLK Q:HLRDOUT 86 ;**132** 87 ;switch to null device if opened to prevent 'leakage' 88 I $G(IO(0))]"",IO(0)'=IO U IO(0) 89 ; 90 ;save any excess for next time 91 S:HLX]"" HLTMBUF(0)=HLX 92 S:HLX(1)]"" HLTMBUF(1)=HLX(1) 93 I +HLIND1,'$P(HLIND1,U,3) D DELMSG(HLIND1) S HLIND1=0 94 Q HLIND1 95 ; 96 RDBLK ; 97 ; initialize 98 S HLBUFF="" 99 ; 100 ;S HLDB=HLDBSIZE-$L(HLX) 101 ; store the total length of HLX and HLX(1) in HLDB(1) 102 S HLDB(1)=$L(HLX)+$L(HLX(1)) 103 ; 104 ;**132 ** 105 ;U IO R X#HLDB:HLDREAD 106 ; U IO R X#HLDB:MAXWAIT 107 ; 108 ; remove the readcount to speedup GT.M 109 U IO 110 R:(HLDB(1)<HLDBSIZE) HLBUFF:MAXWAIT 111 ; 112 I HLBUFF]"" D 113 . I HLBUFF[HLDSTRT,(HLBUFF("START")=0) D 114 .. ; remove the extraneous text prefixing the "START" char 115 .. I $P(HLBUFF,HLDSTRT)]"" S HLBUFF=HLDSTRT_$P(HLBUFF,HLDSTRT,2,99) 116 .. S HLBUFF("START")=1 117 . ; 118 . I HLBUFF[HLDEND,(HLBUFF("END")=0) S HLBUFF("END")=1 119 ; detect disconnect for GT.M 120 I $G(^%ZOSF("OS"))["GT.M",$DEVICE S $ECODE=",UREAD," 121 ; timedout, <clean up>, quit 122 ;I '$T,X="",HLX="" S HLACKWT=HLACKWT-HLDREAD D:HLACKWT<0&'HLHDR CLEAN Q 123 ;I '$T,X="",HLX="" D:'HLHDR CLEAN Q 124 ; patch HL*1.6*140 125 ; I '$T,HLBUFF="",HLX="",HLX(1)="" D Q 126 I HLBUFF="",HLX="",HLX(1)="" D Q 127 . D:('HLHDR)&('HLIND1) CLEAN 128 ;add incoming line to what wasn't processed in last read 129 ;S HLX=$G(HLX)_X 130 ; get block of characters from read buffer HLBUFF 131 ; every 'for-loop' deal with one read at most, and one message at most 132 ; if HLX is not empty, loop continues even no data is read 133 ; quit, if both HLDBUFF and HLX(1) are empty, means one read is done 134 ; quit, when HLRDOUT is set to 1, means one message is encountered 135 ; an "end" 136 ; F D Q:HLXX=""!(HLRDOUT) 137 F D Q:(HLRDOUT)!(HLBUFF=""&(HLX(1)="")) 138 . ; 139 . ; if HLX(1) is not empty 140 . I HLX(1)]"" D 141 .. ; hldb(2) is the number of characters extracted from hlx(1) 142 .. ; to be concatenated with hlx 143 .. S HLDB(2)=HLDBSIZE-$L(HLX) 144 .. ; hlx(2) stores the first hldb(2) characters extracted 145 .. ; from hlx(1) 146 .. S HLX(2)=$E(HLX(1),1,HLDB(2)) 147 .. S HLX(1)=$E(HLX(1),HLDB(2)+1,$L(HLX(1))) 148 .. S HLX=$G(HLX)_HLX(2) 149 . ; 150 . ; if HLX(1) is empty, and HLBUFF contains data 151 . ; all the data in hlx(1) need to be extracted first 152 . I HLX(1)="",HLBUFF]"" D 153 .. S HLDB=HLDBSIZE-$L(HLX) 154 .. S HLXX=$E(HLBUFF,1,HLDB) 155 .. S HLBUFF=$E(HLBUFF,HLDB+1,$L(HLBUFF)) 156 .. S HLX=$G(HLX)_HLXX 157 . ; quit when HLX is empty 158 . Q:(HLX="") 159 . ; ** 132 ** 160 . ; if no segment end, HLX not full, go back for more 161 . I $L(HLX)<HLDBSIZE,HLX'[HLRS,HLX'[HLDEND Q 162 . ;add incoming line to what wasn't processed 163 . D RDBLK2 164 ; 165 ; it is possible one message is encountered an "end" and other 166 ; messages left in buffer,HLBUFF, save it in HLX for next run 167 I HLBUFF]"" D 168 . ; variable HLBUFF may remain data with size more than HLDBSIZE 169 . ; variable HLBUFF is not empty, only if the total length of 170 . ; HLX and HLX(1) is less than HLDBSIZE and HLX(1) should be 171 . ; empty when the command s hlx(1)=$g(hlx(1))_hlbuff is executed 172 . ; use hlx(1) to store the data of hlbuff to avoid "MAXTRING" error 173 . S HLX(1)=$G(HLX(1))_HLBUFF 174 . S HLBUFF="" 175 Q 176 ; 177 RDBLK2 ;data stream: <sb>dddd<cr><eb><cr> 178 ; HL*1.6*122 end 179 ; look for segment= <CR> 180 F Q:HLX'[HLRS D Q:HLRDOUT 181 . ; Get the first piece, save the rest of the line 182 . S HLINE=HLINE+1,HLMSG(HLINE,0)=$P(HLX,HLRS),HLX=$P(HLX,HLRS,2,999) 183 . ; check for start block, Quit if no ien 184 . I HLMSG(HLINE,0)[HLDSTRT!HLHDR D Q 185 .. S HLRS("START-FLAG")=1 ; HL*1.6*122 186 .. D:HLMSG(HLINE,0)[HLDSTRT 187 ... S X=$L(HLMSG(HLINE,0),HLDSTRT) 188 ... S:X>2 HLMSG(HLINE,0)=HLDSTRT_$P(HLMSG(HLINE,0),HLDSTRT,X) 189 ... S HLMSG(HLINE,0)=$P(HLMSG(HLINE,0),HLDSTRT,2) 190 ... D RESET:(HLINE>1) 191 .. ; 192 .. ; patch HL*1.6*122 193 .. ; if the first line less than 10 characters 194 .. I HLHDR,$L(HLMSG(1,0))<10,$D(HLMSG(2,0)) D 195 ... S HLMSG(1,0)=HLMSG(1,0)_$E(HLMSG(2,0),1,10) 196 ... S HLMSG(2,0)=$E(HLMSG(2,0),11,9999999) 197 .. ; 198 .. ;ping message 199 .. I $E(HLMSG(1,0),1,9)="MSH^PING^" D PING Q 200 .. ; get next ien to store 201 .. D MIEN^HLCSTCP4 202 .. K HLMSG 203 .. S (HLINE,HLHDR)=0 204 . ; check for end block; <eb><cr> 205 . I HLMSG(HLINE,0)[HLDEND D 206 .. ; patch HL*1.6*122 start 207 .. ;no msg. ien 208 .. ; Q:'HLIND1 209 .. I 'HLIND1 D CLEAN Q 210 .. ; Kill just the last line if no data before HLDEND 211 .. I $P(HLMSG(HLINE,0),HLDEND)']"" D 212 ... K HLMSG(HLINE,0) S HLINE=HLINE-1 213 .. E S HLMSG(HLINE,0)=$P(HLMSG(HLINE,0),HLDEND) 214 .. ; patch HL*1.6*122 end 215 .. ; 216 .. ; move into 772 217 .. D SAVE(.HLMSG,"^HL(772,"_+$P(HLIND1,U,2)_",""IN"")") 218 .. ;mark that end block has been received 219 .. ;HLIND1=ien in 773^ien in 772^1 if end block was received 220 .. S $P(HLIND1,U,3)=1 221 .. S HLBUFF("HLIND1")=HLIND1 222 .. ;reset variables for next message 223 .. D CLEAN 224 . ;add blank line for carriage return 225 . I HLINE'=0,HLMSG(HLINE,0)]"" S HLINE=HLINE+1,HLMSG(HLINE,0)="" 226 Q:HLRDOUT 227 ;If the line is long and no <CR> move it into the array. 228 I ($L(HLX)=HLDBSIZE),(HLX'[HLRS),(HLX'[HLDEND),(HLX'[HLDSTRT) D Q 229 . S HLINE=HLINE+1,HLMSG(HLINE,0)=HLX,HLX="" 230 ;have start block but no record separator 231 I HLX[HLDSTRT D Q 232 . ;check for more than 1 start block 233 . S X=$L(HLX,HLDSTRT) S:X>2 HLX=HLDSTRT_$P(HLX,HLDSTRT,X) 234 . ; 235 . ; patch HL*1.6*122 236 . ; S:$L($P(HLX,HLDSTRT,2))>8 HLINE=HLINE+1,HLMSG(HLINE,0)=$P(HLX,HLDSTRT,2),HLX="",HLHDR=1 237 . S HLINE=HLINE+1,HLMSG(HLINE,0)=$P(HLX,HLDSTRT,2),HLX="",HLHDR=1 238 . ; 239 . D RESET:(HLHDR&(HLINE>1)) 240 ;if no ien, reset 241 ; patch HL*1.6*122 242 ; I 'HLIND1 D CLEAN Q 243 I (HLRS("START-FLAG")=1),'HLIND1 D CLEAN Q 244 ; big message-merge from local to global every 100 lines 245 I (HLINE-$O(HLMSG(0)))>100 D 246 . M ^HL(772,+$P(HLIND1,U,2),"IN")=HLMSG 247 . ; reset working array 248 . K HLMSG 249 Q 250 ; 251 SAVE(SRC,DEST) ;save into global & set top node 252 ;SRC=source array (passed by ref.), DEST=destination global 253 ; 254 ; patch HL*1.6*122: MPI-client/server 255 I DEST["HLMA" D 256 . F L +^HLMA(+HLIND1):10 Q:$T H 1 257 E D 258 . F L +^HL(772,+$P(HLIND1,U,2)):10 Q:$T H 1 259 ; 260 M @DEST=SRC 261 S @DEST@(0)="^^"_HLINE_"^"_HLINE_"^"_DT_"^" 262 ; 263 I DEST["HLMA" L -^HLMA(+HLIND1) 264 E L -^HL(772,+$P(HLIND1,U,2)) 265 ; 266 Q 267 ; 268 DELMSG(HLMAMT) ;delete message from Message Administration/Message Text files. 269 N DIK,DA 270 S DA=+HLMAMT,DIK="^HLMA(" 271 D ^DIK 272 S DA=$P(HLMAMT,U,2),DIK="^HL(772," 273 D ^DIK 274 Q 275 PING ;process PING message 276 S X=HLMSG(1,0) 277 ; patch HL*1.6*140, flush character- HLTCPLNK("IOF") 278 ; I X[HLDEND U IO W X,! D 279 I X[HLDEND U IO W X,HLTCPLNK("IOF") D 280 . ; switch to null device if opened to prevent 'leakage' 281 . I $G(IO(0))]"",$G(IO(0))'=IO U IO(0) 282 CLEAN ;reset var. for next message 283 K HLMSG 284 S HLINE=0,HLRDOUT=1 285 Q 286 ; 287 ERROR ; Error trap for disconnect error and return back to the read loop. 288 ; patch HL*1.6*122 289 ; move to routine HLCSTCP4 (splitted-size over 10000) 290 D ERROR1^HLCSTCP4 291 Q 292 ; 293 CC(X) ;cleanup and close 294 D MON^HLCSTCP(X) 295 H 2 296 Q 297 RESET ;reset info as a result of no end block 298 N % 299 S HLMSG(1,0)=HLMSG(HLINE,0) 300 F %=2:1:HLINE K HLMSG(%,0) 301 S HLINE=1 302 Q 1 HLCSTCP1 ;SFIRMFO/RSD - BI-DIRECTIONAL TCP ;7/28/07 08:58 2 ;;1.6;HEALTH LEVEL SEVEN;**19,43,57,64,71,133,132,122**;OCT 13,1995;Build 4 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ;Receiver 5 ;connection is initiated by sender and listener accepts connection 6 ;and calls this routine 7 ; 8 N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP1" 9 N HLMIEN,HLASTMSG 10 ; 11 ; patch HL*1.6*122 start 12 ; variable to replace ^TMP 13 N HLTMBUF 14 ; for HL7 application proxy user 15 N HLDUZ,DUZ 16 D MON^HLCSTCP("Open") 17 ; K ^TMP("HLCSTCP",$J,0) 18 S HLMIEN=0,HLASTMSG="" 19 ; set DUZ for application proxy user 20 D PROXY^HLCSTCP4 21 F D Q:$$STOP^HLCSTCP I 'HLMIEN D MON^HLCSTCP("Idle") H 3 22 . ; clean variables 23 . D CLEANVAR^HLCSTCP4 24 . S HLMIEN=$$READ 25 . Q:'HLMIEN 26 . ; DUZ comparison/reset for application proxy user 27 . D HLDUZ^HLCSTCP4 28 . ; protect HLDUZ 29 . N HLDUZ 30 . D PROCESS 31 ; patch HL*1.6*122 end 32 Q 33 ; 34 PROCESS ;check message and reply 35 ;HLDP=LL in 870 36 N HLTCP,HLTCPI,HLTCPO 37 S HLTCP="",HLTCPO=HLDP,HLTCPI=+HLMIEN 38 ;update monitor, msg. received 39 D LLCNT^HLCSTCP(HLDP,1) 40 D NEW^HLTP3(HLMIEN) 41 ;update monitor, msg. processed 42 D LLCNT^HLCSTCP(HLDP,2) 43 Q 44 ; 45 READ() ;read 1 message, returns ien in 773^ien in 772 for message 46 D MON^HLCSTCP("Reading") 47 N HLDB,HLDT,HLDEND,HLACKWT,HLDSTRT,HLHDR,HLIND1,HLINE,HLMSG,HLRDOUT,HLRS,HLX,X 48 ;HLDSTRT=start char., HLDEND=end char., HLRS=record seperator 49 S HLDSTRT=$C(11),HLDEND=$C(28),HLRS=$C(13) 50 ;HLRDOUT=exit read loop, HLINE=line count, HLIND1=ien 773^ien 772 51 ;HLHDR=have a header, HLTMBUF()=excess from last read, HLACKWT=wait for ack 52 ; HL*1.6*122 start 53 ; S (HLRDOUT,HLINE,HLIND1,HLHDR)=0,HLX=$G(^TMP("HLCSTCP",$J,0)),HLACKWT=HLDBACK 54 S (HLRDOUT,HLINE,HLIND1,HLHDR)=0,HLX=$G(HLTMBUF(0)),HLACKWT=HLDBACK 55 N HLBUFF,HLXX,MAXWAIT 56 ; based on patch 132 for readtime 57 S MAXWAIT=$S((HLACKWT>HLDREAD):HLACKWT,1:HLDREAD) 58 S HLRS("START-FLAG")=0 59 S HLTMBUF(0)="" 60 ; variable used to store data in HLBUFF 61 S HLX(1)=$G(HLTMBUF(1)) 62 S HLTMBUF(1)="" 63 S HLBUFF("START")=0 64 S HLBUFF("END")=0 65 I (HLX]"")!(HLX(1)]"") D 66 . I (HLX[HLDSTRT)!(HLX(1)[HLDSTRT) D 67 .. S HLBUFF("START")=1 68 . I (HLX[HLDEND)!(HLX(1)[HLDEND) D 69 .. S HLBUFF("END")=1 70 F D RDBLK Q:HLRDOUT 71 ;**132** 72 ;switch to null device if opened to prevent 'leakage' 73 I $G(IO(0))]"",IO(0)'=IO U IO(0) 74 ; 75 ;save any excess for next time 76 S:HLX]"" HLTMBUF(0)=HLX 77 S:HLX(1)]"" HLTMBUF(1)=HLX(1) 78 I +HLIND1,'$P(HLIND1,U,3) D DELMSG(HLIND1) S HLIND1=0 79 Q HLIND1 80 ; 81 RDBLK ; 82 ; initialize 83 S HLBUFF="" 84 ; 85 ;S HLDB=HLDBSIZE-$L(HLX) 86 ; store the total length of HLX and HLX(1) in HLDB(1) 87 S HLDB(1)=$L(HLX)+$L(HLX(1)) 88 ; 89 ;**132 ** 90 ;U IO R X#HLDB:HLDREAD 91 ; U IO R X#HLDB:MAXWAIT 92 ; 93 ; remove the readcount to speedup GT.M 94 U IO 95 R:(HLDB(1)<HLDBSIZE) HLBUFF:MAXWAIT 96 I HLBUFF]"" D 97 . I HLBUFF[HLDSTRT,(HLBUFF("START")=0) D 98 .. ; remove the extraneous text prefixing the "START" char 99 .. I $P(HLBUFF,HLDSTRT)]"" S HLBUFF=HLDSTRT_$P(HLBUFF,HLDSTRT,2,99) 100 .. S HLBUFF("START")=1 101 . ; 102 . I HLBUFF[HLDEND,(HLBUFF("END")=0) S HLBUFF("END")=1 103 ; detect disconnect for GT.M 104 I $G(^%ZOSF("OS"))["GT.M",$DEVICE S $ECODE="" 105 ; timedout, <clean up>, quit 106 ;I '$T,X="",HLX="" S HLACKWT=HLACKWT-HLDREAD D:HLACKWT<0&'HLHDR CLEAN Q 107 ;I '$T,X="",HLX="" D:'HLHDR CLEAN Q 108 I '$T,HLBUFF="",HLX="",HLX(1)="" D Q 109 . D:('HLHDR)&('HLIND1) CLEAN 110 ;add incoming line to what wasn't processed in last read 111 ;S HLX=$G(HLX)_X 112 ; 113 ; get block of characters from read buffer HLBUFF 114 ; every 'for-loop' deal with one read at most, and one message at most 115 ; if HLX is not empty, loop continues even no data is read 116 ; quit, if both HLDBUFF and HLX(1) are empty, means one read is done 117 ; quit, when HLRDOUT is set to 1, means one message is encountered 118 ; an "end" 119 ; F D Q:HLXX=""!(HLRDOUT) 120 F D Q:(HLRDOUT)!(HLBUFF=""&(HLX(1)="")) 121 . ; 122 . ; if HLX(1) is not empty 123 . I HLX(1)]"" D 124 .. ; hldb(2) is the number of characters extracted from hlx(1) 125 .. ; to be concatenated with hlx 126 .. S HLDB(2)=HLDBSIZE-$L(HLX) 127 .. ; hlx(2) stores the first hldb(2) characters extracted 128 .. ; from hlx(1) 129 .. S HLX(2)=$E(HLX(1),1,HLDB(2)) 130 .. S HLX(1)=$E(HLX(1),HLDB(2)+1,$L(HLX(1))) 131 .. S HLX=$G(HLX)_HLX(2) 132 . ; 133 . ; if HLX(1) is empty, and HLBUFF contains data 134 . ; all the data in hlx(1) need to be extracted first 135 . I HLX(1)="",HLBUFF]"" D 136 .. S HLDB=HLDBSIZE-$L(HLX) 137 .. S HLXX=$E(HLBUFF,1,HLDB) 138 .. S HLBUFF=$E(HLBUFF,HLDB+1,$L(HLBUFF)) 139 .. S HLX=$G(HLX)_HLXX 140 . ; quit when HLX is empty 141 . Q:(HLX="") 142 . ; ** 132 ** 143 . ; if no segment end, HLX not full, go back for more 144 . I $L(HLX)<HLDBSIZE,HLX'[HLRS,HLX'[HLDEND Q 145 . ;add incoming line to what wasn't processed 146 . D RDBLK2 147 ; 148 ; it is possible one message is encountered an "end" and other 149 ; messages left in buffer,HLBUFF, save it in HLX for next run 150 I HLBUFF]"" D 151 . ; variable HLBUFF may remain data with size more than HLDBSIZE 152 . ; variable HLBUFF is not empty, only if the total length of 153 . ; HLX and HLX(1) is less than HLDBSIZE and HLX(1) should be 154 . ; empty when the command s hlx(1)=$g(hlx(1))_hlbuff is executed 155 . ; use hlx(1) to store the data of hlbuff to avoid "MAXTRING" error 156 . S HLX(1)=$G(HLX(1))_HLBUFF 157 . S HLBUFF="" 158 Q 159 ; 160 RDBLK2 ;data stream: <sb>dddd<cr><eb><cr> 161 ; HL*1.6*122 end 162 ; look for segment= <CR> 163 F Q:HLX'[HLRS D Q:HLRDOUT 164 . ; Get the first piece, save the rest of the line 165 . S HLINE=HLINE+1,HLMSG(HLINE,0)=$P(HLX,HLRS),HLX=$P(HLX,HLRS,2,999) 166 . ; check for start block, Quit if no ien 167 . I HLMSG(HLINE,0)[HLDSTRT!HLHDR D Q 168 .. S HLRS("START-FLAG")=1 ; HL*1.6*122 169 .. D:HLMSG(HLINE,0)[HLDSTRT 170 ... S X=$L(HLMSG(HLINE,0),HLDSTRT) 171 ... S:X>2 HLMSG(HLINE,0)=HLDSTRT_$P(HLMSG(HLINE,0),HLDSTRT,X) 172 ... S HLMSG(HLINE,0)=$P(HLMSG(HLINE,0),HLDSTRT,2) 173 ... D RESET:(HLINE>1) 174 .. ; 175 .. ; patch HL*1.6*122 176 .. ; if the first line less than 10 characters 177 .. I HLHDR,$L(HLMSG(1,0))<10,$D(HLMSG(2,0)) D 178 ... S HLMSG(1,0)=HLMSG(1,0)_$E(HLMSG(2,0),1,10) 179 ... S HLMSG(2,0)=$E(HLMSG(2,0),11,9999999) 180 .. ; 181 .. ;ping message 182 .. I $E(HLMSG(1,0),1,9)="MSH^PING^" D PING Q 183 .. ; get next ien to store 184 .. D MIEN^HLCSTCP4 185 .. K HLMSG 186 .. S (HLINE,HLHDR)=0 187 . ; check for end block; <eb><cr> 188 . I HLMSG(HLINE,0)[HLDEND D 189 .. ; patch HL*1.6*122 start 190 .. ;no msg. ien 191 .. ; Q:'HLIND1 192 .. I 'HLIND1 D CLEAN Q 193 .. ; Kill just the last line if no data before HLDEND 194 .. I $P(HLMSG(HLINE,0),HLDEND)']"" D 195 ... K HLMSG(HLINE,0) S HLINE=HLINE-1 196 .. E S HLMSG(HLINE,0)=$P(HLMSG(HLINE,0),HLDEND) 197 .. ; patch HL*1.6*122 end 198 .. ; 199 .. ; move into 772 200 .. D SAVE(.HLMSG,"^HL(772,"_+$P(HLIND1,U,2)_",""IN"")") 201 .. ;mark that end block has been received 202 .. ;HLIND1=ien in 773^ien in 772^1 if end block was received 203 .. S $P(HLIND1,U,3)=1 204 .. S HLBUFF("HLIND1")=HLIND1 205 .. ;reset variables for next message 206 .. D CLEAN 207 . ;add blank line for carriage return 208 . I HLINE'=0,HLMSG(HLINE,0)]"" S HLINE=HLINE+1,HLMSG(HLINE,0)="" 209 Q:HLRDOUT 210 ;If the line is long and no <CR> move it into the array. 211 I ($L(HLX)=HLDBSIZE),(HLX'[HLRS),(HLX'[HLDEND),(HLX'[HLDSTRT) D Q 212 . S HLINE=HLINE+1,HLMSG(HLINE,0)=HLX,HLX="" 213 ;have start block but no record seperator 214 I HLX[HLDSTRT D Q 215 . ;check for more than 1 start block 216 . S X=$L(HLX,HLDSTRT) S:X>2 HLX=HLDSTRT_$P(HLX,HLDSTRT,X) 217 . ; 218 . ; patch HL*1.6*122 219 . ; S:$L($P(HLX,HLDSTRT,2))>8 HLINE=HLINE+1,HLMSG(HLINE,0)=$P(HLX,HLDSTRT,2),HLX="",HLHDR=1 220 . S HLINE=HLINE+1,HLMSG(HLINE,0)=$P(HLX,HLDSTRT,2),HLX="",HLHDR=1 221 . ; 222 . D RESET:(HLHDR&(HLINE>1)) 223 ;if no ien, reset 224 ; patch HL*1.6*122 225 ; I 'HLIND1 D CLEAN Q 226 I (HLRS("START-FLAG")=1),'HLIND1 D CLEAN Q 227 ; big message-merge from local to global every 100 lines 228 I (HLINE-$O(HLMSG(0)))>100 D 229 . M ^HL(772,+$P(HLIND1,U,2),"IN")=HLMSG 230 . ; reset working array 231 . K HLMSG 232 Q 233 ; 234 SAVE(SRC,DEST) ;save into global & set top node 235 ;SRC=source array (passed by ref.), DEST=destination global 236 M @DEST=SRC 237 S @DEST@(0)="^^"_HLINE_"^"_HLINE_"^"_DT_"^" 238 Q 239 ; 240 DELMSG(HLMAMT) ;delete message from Message Administration/Message Text files. 241 N DIK,DA 242 S DA=+HLMAMT,DIK="^HLMA(" 243 D ^DIK 244 S DA=$P(HLMAMT,U,2),DIK="^HL(772," 245 D ^DIK 246 Q 247 PING ;process PING message 248 S X=HLMSG(1,0) 249 I X[HLDEND U IO W X,! D 250 . ; switch to null device if opened to prevent 'leakage' 251 . I $G(IO(0))]"",$G(IO(0))'=IO U IO(0) 252 CLEAN ;reset var. for next message 253 K HLMSG 254 S HLINE=0,HLRDOUT=1 255 Q 256 ; 257 ERROR ; Error trap for disconnect error and return back to the read loop. 258 S $ETRAP="D UNWIND^%ZTER" 259 I $$EC^%ZOSV["IOEOF" D UNWIND^%ZTER Q ;VOE change for GT.M 260 I $$EC^%ZOSV["READ"!($$EC^%ZOSV["NOTOPEN")!($$EC^%ZOSV["DEVNOTOPN") D UNWIND^%ZTER Q 261 I $$EC^%ZOSV["WRITE" D CC("Wr-err") D UNWIND^%ZTER Q 262 I $ECODE["UREAD" D UNWIND^%ZTER Q ; HL*1.6*122 GT.M 263 S HLCSOUT=1 D ^%ZTER,CC("Error") 264 D UNWIND^%ZTER 265 Q 266 ; 267 CC(X) ;cleanup and close 268 D MON^HLCSTCP(X) 269 H 2 270 Q 271 RESET ;reset info as a result of no end block 272 N % 273 S HLMSG(1,0)=HLMSG(HLINE,0) 274 F %=2:1:HLINE K HLMSG(%,0) 275 S HLINE=1 276 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSTCP2.m
r613 r623 1 HLCSTCP2 ;SFIRMFO/RSD - BI-DIRECTIONAL TCP ;04/16/2008 16:20 2 ;;1.6;HEALTH LEVEL SEVEN;**19,43,49,57,63,64,66,67,76,77,87,109,133,122,140**;Oct 13,1995;Build 5 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ;Sender 5 ;Request connection, send outbound message(s) delimited by MLLP 6 ;Input : HLDP=Logical Link to use 7 ; Set up error trap 8 N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP2" 9 N HLMSG,HLPORT,HLRETRY,HLRETMG,HLTCPO,POP 10 ;HLRETRY=number of retranmission for this link,HLRETMG=alert sent 11 S HLTCPO=HLDP,HLMSG="",(HLRETRY,HLRETMG)=0 12 ; 13 ; patch 122 14 ; patch 133 15 ; set IO(0) to the null device 16 I $G(^%ZOSF("OS"))]"",^%ZOSF("OS")'["GT.M" D 17 . S IO(0)=$S(^%ZOSF("OS")["OpenM":$S($$OS^%ZOSV()["VMS":"_NLA0:",$$OS^%ZOSV()["UNIX":"/dev/null",1:$P),^%ZOSF("OS")["DSM":"_NLA0:",1:$P) 18 . O IO(0) U IO(0) 19 ; 20 ;persistent conection, open connection first, HLPORT=open port 21 I $G(HLTCPLNK)["Y" F Q:$$OPEN G EXIT:$$STOP^HLCSTCP H 1 22 F D QUE Q:$$STOP^HLCSTCP D:'HLMSG Q:$G(HLCSOUT) 23 . ;no messages to send 24 . D MON^HLCSTCP("Idle") H 3 25 . ;persistent connection, no retention 26 . Q:$G(HLTCPLNK)["Y" 27 . D MON^HLCSTCP("Retention") 28 . N % I 0 29 . ;if message comes in or ask to stop 30 . F %=1:1:HLTCPRET H 1 I $$STOP^HLCSTCP!$O(^HLMA("AC","O",HLDP,0)) Q 31 . E S HLCSOUT=2 Q 32 . Q:$$STOP^HLCSTCP 33 . D MON^HLCSTCP("Idle") 34 ;Close port 35 I $D(HLPORT) D CLOSE^%ZISTCP K HLPORT 36 EXIT Q 37 ; 38 QUE ; -- Check "OUT" queue for processing IF there is a message do it 39 ; and then check the link if it open or not 40 N HL,HLN,HLARR,HLHDR,HLI,HLJ,HLMSA,HLRESP,HLRESLT,HLRETRM,HLTCP,HLTCPI,X,Z,HLREREAD 41 N HLTMBUF 42 D MON^HLCSTCP("CheckOut") 43 ;HLMSG=next msg, set at tag DONE 44 I 'HLMSG S HLMSG=+$O(^HLMA("AC","O",HLDP,0)),HLRETRY=0 Q:'HLMSG 45 ; 46 S HLI=+$G(^HLMA(HLMSG,0)),HLJ=$O(^("MSH",0)),HLTCP="" 47 ;don't have message text or MSH, kill x-ref and decrement 'to send' 48 ; 49 ; patch HL*1.6*122: MPI-client/server 50 ; I 'HLI!'HLJ K ^HLMA("AC","O",HLDP,HLMSG) D LLCNT^HLCSTCP(HLDP,3,1) S HLMSG=0 Q 51 I 'HLI!'HLJ D Q 52 . F L +^HLMA("AC","O",HLDP,HLMSG):10 Q:$T H 1 53 . K ^HLMA("AC","O",HLDP,HLMSG) 54 . L -^HLMA("AC","O",HLDP,HLMSG) 55 . D LLCNT^HLCSTCP(HLDP,3,1) 56 . S HLMSG=0 57 ; 58 ;update msg status to 'being transmitted'; if cancelled decrement link and quit 59 I '$$CHKMSG(1.5) D LLCNT^HLCSTCP(HLDP,3,1) S HLMSG=0 Q 60 ;number of retransmissions for message 61 S HLRETRM=+$P(^HLMA(HLMSG,"P"),U,5) 62 ;retries exceeded, HLRETRA:action i=ignore, r=restart, s=shutdown 63 ;quit if restart or shutdown, link is going down 64 I HLRETRY>HLDRETR D Q:"I"'[HLRETRA 65 . D MON^HLCSTCP("Error") 66 . ;only 1 alert per link up time, don't send if restart 67 . D:'HLRETMG&(HLRETRA'="R") 68 .. ;send alert 69 .. N XQA,XQAMSG,XQAOPT,XQAROU,XQAID,Z 70 .. ;get mailgroup from file 869.3 71 .. S HLRETMG=1,Z=$P($$PARAM^HLCS2,U,8) Q:Z="" 72 .. S XQA("G."_Z)="",XQAMSG=$$HTE^XLFDT($H,2)_" HL7 LL "_$P(^HLCS(870,HLDP,0),U)_" exceeded retries. LL will "_$S(HLRETRA="S":"shutdown.",HLRETRA="R":"restart.",1:"keep trying.") 73 .. D SETUP^XQALERT 74 . ;quit if action is ignore 75 . Q:"I"[HLRETRA 76 . ;this will shutdown this link 77 . S HLCSOUT=1 78 . ;action is shutdown, set shutdown flag so LM won't restart 79 . S:HLRETRA="S" $P(^HLCS(870,HLDP,0),U,15)=1 80 . D STATUS^HLTF0(HLMSG,4,103,"LLP Exceeded Retry Param") 81 I '$$OPEN Q 82 D MON^HLCSTCP("Send") 83 ; -- data passed in global array, success=1 84 I $$WRITE(HLMSG)<0 Q 85 S (HLTCP,HLTCPI)=HLMSG,HLRETRY=HLRETRY+1,HLRETRM=HLRETRM+1 86 ;update status to awaiting response, decrement link if cancelled 87 I '$$CHKMSG(1.7) D LLCNT^HLCSTCP(HLDP,3,1) S HLMSG=0 Q 88 ;set transmission count, get ACKTIMEOUT override 89 S $P(^HLMA(HLMSG,"P"),U,5)=HLRETRM I $P(^("P"),U,7) S HLN("ACKTIME")=+$P(^("P"),U,7) 90 ;get header of message just sent 91 K HLJ M HLJ=^HLMA(HLMSG,"MSH") 92 ;first component of sending app. 93 S HLN("ECH")=$$P^HLTPCK2(.HLJ,2),HLN("SAN")=$P($$P^HLTPCK2(.HLJ,3),$E(HLN("ECH"))) 94 ;msg type, msg. id, commit ack, and app. ack parameter 95 S HLN("TYPE")=$$P^HLTPCK2(.HLJ,1),HLN("MID")=$$P^HLTPCK2(.HLJ,10),HLN("ACAT")=$$P^HLTPCK2(.HLJ,15),HLN("APAT")=$$P^HLTPCK2(.HLJ,16) 96 ;MSA segment, message is a response, can't have an a. ack. 97 S Z=$$MSA^HLTP3(+^HLMA(HLMSG,0)) I Z]"" S:HLN("ACAT")="" HLN("ACAT")="NE" S HLN("APAT")="NE" 98 ;for batch/file with commit ack, reset c. ack and a. ack variables 99 I "BHS,FHS"[HLN("TYPE") S Z=$E(HLJ(1,0),5),X=$$P^HLTPCK2(.HLJ,9),HLN("ACAT")=$P(X,Z,5),HLN("APAT")=$P(X,Z,6),HLN("MID")=$$P^HLTPCK2(.HLJ,11) 100 ;get event protocol 101 S HLN("EID")=+$P(^HLMA(HLMSG,0),U,8),X=$G(^ORD(101,HLN("EID"),770)) 102 ;set link counter to msg sent 103 D LLCNT^HLCSTCP(HLDP,4) 104 ;commit and app. ack is never, update status to complete and hang UNI-DIRECTIONAL WAIT 105 I HLN("ACAT")="NE",HLN("APAT")="NE" D Q 106 .D DONE(3) 107 .; 108 .; 109 .H $G(HLDWAIT) 110 ; 111 ;do structure is to stack error 112 D 113 . N $ETRAP,$ESTACK S $ETRAP="D RDERR^HLCSTCP2" 114 . ;HL*1.6*87: Read acknowledgement. 115 . ;Loop to re-read from buffer when receiving incorrect ack. 116 . F D Q:'+$G(HLREREAD) 117 .. S HLREREAD=1 118 .. ;override ack timeout 119 .. I $G(HLN("ACKTIME")) N HLDBACK S HLDBACK=HLN("ACKTIME") 120 .. ;check for response, quit if no-response, msg will be resent 121 .. ;HLRESP=ien 773^ien 772 for response message 122 .. S HLRESP=$$READ^HLCSTCP1() 123 .. ;if no response, decrement counter and quit 124 .. I 'HLRESP D Q 125 ...D LLCNT^HLCSTCP(HLDP,4,1) 126 ...S HLREREAD="0^No Response" 127 ...;check if the port needs to be closed and re-opened before the next re-transmission attempt 128 ...I $G(HLDRETRY("CLOSE")) D CLOSE^%ZISTCP K HLPORT 129 .. ;X 0=re-read msg, 1=commit ack, 3=app ack success, 4=error 130 .. S X=$$RSP^HLTP31(HLRESP,.HLN) 131 .. ;X=0, re-read msg. Incorrect ack (bad MSH,MSA,msg id,or sending app) 132 .. Q:'X 133 .. ;commit ack - done 134 .. I X=1 D S HLREREAD="0^Commit Ack" Q 135 ... ;don't need app. ack, set status to complete 136 ... I "NE"[HLN("APAT") D Q 137 ....D DONE(3) 138 ....; 139 ... ;response is deferred, set status to awaiting ack 140 ... D DONE(2) 141 ...; 142 .. ;Error, HLRESLT=error number^error message from HLTP3 143 .. I X=4 D Q 144 ... D DONE(4,+$G(HLRESLT),$P($G(HLRESLT),U,2)) 145 ...; 146 ... S HLREREAD="0^Error" 147 .. ;app ack was successful 148 .. D DONE(3) S HLREREAD="0^App Ack" 149 ..; 150 Q 151 ; 152 DCSEND ;direct connect 153 ; Set up error trap 154 N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP2" 155 ; patch HL*1.6*122 156 N HLTMBUF 157 ;override ack timeout 158 I $G(HLP("ACKTIME")) N HLDBACK S HLDBACK=HLP("ACKTIME") 159 I $$WRITE(HLMSG)<0 D:$G(HLERROR)]"" Q ;HL*1.6*77 160 . D STATUS^HLTF0(HLMSG,4,$P(HLERROR,"^"),$P(HLERROR,"^",2),1) ;HL*1.6*77 161 . D LLCNT^HLCSTCP(HLDP,3,1) 162 D LLCNT^HLCSTCP(HLDP,4) 163 ;do structure is to stack error 164 D 165 . N $ETRAP,$ESTACK S $ETRAP="D RDERR^HLCSTCP2" 166 . ;HLRESP=ien 773^ien 772 for response message 167 . S HLRESP=$$READ^HLCSTCP1() 168 ; 169 D DONE(3):$G(HLRESP),DONE(4,108,$S($G(HLERROR)]"":$P(HLERROR,"^",2),1:"No response")):'$G(HLRESP) 170 I $G(HLERROR)']"" D 171 .D MON^HLCSTCP("Idle") 172 .I '$G(HLRESP) S HLERROR="108^No response" 173 ;Close port 174 I $D(HLPORT) D CLOSE^%ZISTCP K HLPORT 175 Q 176 ; 177 DONE(ST,ERR,ERRMSG) ;set status to complete 178 ;ST=status, ERR=error ien, ERRMSG=error msg 179 D STATUS^HLTF0(HLMSG,ST,$G(ERR),$G(ERRMSG),1) 180 ; 181 D DEQUE^HLCSREP(HLDP,"O",HLMSG) 182 ; 183 ;check for more msg. 184 I $G(HLPRIO)'="I" S HLMSG=+$O(^HLMA("AC","O",HLDP,0)),HLRETRY=0 185 Q 186 ; 187 CHKMSG(HLI) ;check status of message and update if not cancelled 188 ;input: HLI=new status, HLMSG=ien of msg in 773 189 ;returns 1=msg was updated, 0=msg has been canceled 190 N X 191 ; 192 ; New HL*1.6*77 code starting here... 193 I '$D(^HLMA(HLMSG,"P")) D Q 0 194 . S HLERROR="2^Missing status field" 195 . D STATUS^HLTF0(HLMSG,4,$P(HLERROR,U),$P(HLERROR,U,2),1) 196 .; 197 . D DEQUE^HLCSREP(HLDP,"O",HLMSG) 198 ; 199 ; End of HL*1.6*77 200 ; 201 ;get status, quit if msg was cancelled 202 ; 203 S X=+^HLMA(HLMSG,"P") Q:X=3 0 204 ; 205 ;update status if it is different 206 I $G(HLI),HLI'=X D STATUS^HLTF0(HLMSG,HLI) 207 ; 208 Q 1 209 ; 210 WRITE(HLDA) ; write message in HL7 format 211 ; HLDA - ien of message in 773 212 ; - start block $C(11) 213 ; - end block $C(28) 214 ; - record separator $C(13) 215 ;Output(s): 1 - Successful 216 ; -1 - Unsuccessful 217 ; 218 N HLDA2,HLAR,HLI,LINENO,X,CRCOUNT 219 S CRCOUNT=0 220 ;set error trap, used when called from HLTP3 221 ; 222 ; New HL*1.6*77 code starts here... 223 N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP2" 224 I $G(^HLMA(HLDA,0))'>0 D Q -1 225 . S HLERROR="2^Message Text pointer missing" 226 S HLDA2=+$G(^HLMA(HLDA,0)) 227 ; End of HL*1.6*77 modifications... 228 ; 229 Q:'$G(^HLMA(HLDA,0)) -1 ;HL*1.6*77 230 ; header is in ^HLMA(, message is in ^HL(772, 231 S LINENO=1,HLI=0,HLAR="^HLMA(HLDA,""MSH"")" 232 U IO 233 D W $C(13) S HLAR="^HL(772,HLDA2,""IN"")",HLI=0 D 234 . F S HLI=$O(@HLAR@(HLI)) Q:'HLI S X=$G(^(HLI,0)) D 235 .. ;first line, need start block char. 236 .. S:LINENO=1 X=$C(11)_X 237 .. ; HL*1.6*122 238 .. ; I X]"" W X,! 239 .. N LENGTH 240 .. S LENGTH=$L(X) 241 .. ; buffer should be limited to 512 242 .. I LENGTH>512 D 243 ... N X1 244 ... F Q:LENGTH<512 D 245 .... S X1=$E(X,1,512),X=$E(X,513,999999) 246 .... S LENGTH=$L(X) 247 .... ; patch HL*1.6*140 248 .... ; W X1,@IOF 249 .... W X1,@HLTCPLNK("IOF") 250 .. ; 251 .. ; @HLTCPLNK("IOF") (! or #) for flush character 252 .. I X]"" W X,@HLTCPLNK("IOF") S CRCOUNT=0 253 .. ;send CR 254 .. I X="" W $C(13) S CRCOUNT=CRCOUNT+1 255 .. ; prevent from maxstring error 256 .. I CRCOUNT>200 W @HLTCPLNK("IOF") S CRCOUNT=0 257 .. S LINENO=LINENO+1 258 ; Sends end block for this message 259 S X=$C(28)_$C(13) 260 ; U IO W X,! 261 U IO W X,@HLTCPLNK("IOF") 262 ;switch to null device 263 I $G(IO(0))'="",$G(IO(0))'=IO U IO(0) 264 Q 1 265 ; 266 OPEN() ; -- Open TCP/IP device (Client) 267 ;HLPORT=port, defined only if port is open 268 ;HLPORTA=number of attempted opens 269 I $D(HLPORT) S IO=HLPORT D Q 1 270 . U IO 271 . I HLOS["OpenM" X "U IO:(::""-M"")" ;use packet mode on Cache' 272 N HLDOM,HLI,HLIP,HLPORTA 273 G OPENA^HLCSTCP3 274 ; 275 RDERR D RDERR^HLCSTCP4 Q 276 ERROR D ERROR^HLCSTCP4 Q 277 ; 278 CC(X) ;cleanup and close 279 D MON^HLCSTCP(X) 280 I $D(HLPORT) D CLOSE^%ZISTCP K HLPORT 281 ; patch HL*1.6*140 282 ; H 2 283 H 1 284 Q 1 HLCSTCP2 ;SFIRMFO/RSD - BI-DIRECTIONAL TCP ;09/13/2006 2 ;;1.6;HEALTH LEVEL SEVEN;**19,43,49,57,63,64,66,67,76,77,87,109,133**;Oct 13,1995;Build 13 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ;Sender 5 ;Request connection, send outbound message(s) delimited by MLLP 6 ;Input : HLDP=Logical Link to use 7 ; Set up error trap 8 N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP2" 9 N HLMSG,HLPORT,HLRETRY,HLRETMG,HLTCPO,POP 10 ;HLRETRY=number of retranmission for this link,HLRETMG=alert sent 11 S HLTCPO=HLDP,HLMSG="",(HLRETRY,HLRETMG)=0 12 ; 13 ;set IO(0) to the null device 14 S IO(0)=$S(^%ZOSF("OS")["OpenM":$S($$OS^%ZOSV()["VMS":"_NLA0:",$$OS^%ZOSV()["UNIX":"/dev/null",1:$P),^%ZOSF("OS")["DSM":"_NLA0:",1:$P) 15 O IO(0) U IO(0) 16 ; 17 ;persistent conection, open connection first, HLPORT=open port 18 I $G(HLTCPLNK)["Y" F Q:$$OPEN G EXIT:$$STOP^HLCSTCP H 1 19 F D QUE Q:$$STOP^HLCSTCP D:'HLMSG Q:$G(HLCSOUT) 20 . ;no messages to send 21 . D MON^HLCSTCP("Idle") H 3 22 . ;persistent connection, no retention 23 . Q:$G(HLTCPLNK)["Y" 24 . D MON^HLCSTCP("Retention") 25 . N % I 0 26 . ;if message comes in or ask to stop 27 . F %=1:1:HLTCPRET H 1 I $$STOP^HLCSTCP!$O(^HLMA("AC","O",HLDP,0)) Q 28 . E S HLCSOUT=2 Q 29 . Q:$$STOP^HLCSTCP 30 . D MON^HLCSTCP("Idle") 31 ;Close port 32 I $D(HLPORT) D CLOSE^%ZISTCP K HLPORT 33 EXIT Q 34 ; 35 QUE ; -- Check "OUT" queue for processing IF there is a message do it 36 ; and then check the link if it open or not 37 N HL,HLN,HLARR,HLHDR,HLI,HLJ,HLMSA,HLRESP,HLRESLT,HLRETRM,HLTCP,HLTCPI,X,Z,HLREREAD 38 D MON^HLCSTCP("Check out") 39 ;HLMSG=next msg, set at tag DONE 40 I 'HLMSG S HLMSG=+$O(^HLMA("AC","O",HLDP,0)),HLRETRY=0 Q:'HLMSG 41 ; 42 ;**109** 43 ;Temporarily lock ^HLMA to flush buffer and ensure edits are complete 44 ;L +^HLMA(HLMSG):1 I '$T S HLMSG=0 Q 45 ;L -^HLMA(HLMSG) 46 ; 47 S HLI=+$G(^HLMA(HLMSG,0)),HLJ=$O(^("MSH",0)),HLTCP="" 48 ;don't have message text or MSH, kill x-ref and decrement 'to send' 49 I 'HLI!'HLJ K ^HLMA("AC","O",HLDP,HLMSG) D LLCNT^HLCSTCP(HLDP,3,1) S HLMSG=0 Q 50 ;update msg status to 'being transmitted'; if cancelled decrement link and quit 51 I '$$CHKMSG(1.5) D LLCNT^HLCSTCP(HLDP,3,1) S HLMSG=0 Q 52 ;number of retransmissions for message 53 S HLRETRM=+$P(^HLMA(HLMSG,"P"),U,5) 54 ;retries exceeded, HLRETRA:action i=ignore, r=restart, s=shutdown 55 ;quit if restart or shutdown, link is going down 56 I HLRETRY>HLDRETR D Q:"I"'[HLRETRA 57 . D MON^HLCSTCP("Error") 58 . ;only 1 alert per link up time, don't send if restart 59 . D:'HLRETMG&(HLRETRA'="R") 60 .. ;send alert 61 .. N XQA,XQAMSG,XQAOPT,XQAROU,XQAID,Z 62 .. ;get mailgroup from file 869.3 63 .. S HLRETMG=1,Z=$P($$PARAM^HLCS2,U,8) Q:Z="" 64 .. S XQA("G."_Z)="",XQAMSG=$$HTE^XLFDT($H,2)_" HL7 LL "_$P(^HLCS(870,HLDP,0),U)_" exceeded retries. LL will "_$S(HLRETRA="S":"shutdown.",HLRETRA="R":"restart.",1:"keep trying.") 65 .. D SETUP^XQALERT 66 . ;quit if action is ignore 67 . Q:"I"[HLRETRA 68 . ;this will shutdown this link 69 . S HLCSOUT=1 70 . ;action is shutdown, set shutdown flag so LM won't restart 71 . S:HLRETRA="S" $P(^HLCS(870,HLDP,0),U,15)=1 72 . D STATUS^HLTF0(HLMSG,4,103,"LLP Exceeded Retry Param") 73 I '$$OPEN Q 74 D MON^HLCSTCP("Send") 75 ; -- data passed in global array, success=1 76 I $$WRITE(HLMSG)<0 Q 77 S (HLTCP,HLTCPI)=HLMSG,HLRETRY=HLRETRY+1,HLRETRM=HLRETRM+1 78 ;update status to awaiting response, decrement link if cancelled 79 I '$$CHKMSG(1.7) D LLCNT^HLCSTCP(HLDP,3,1) S HLMSG=0 Q 80 ;set transmission count, get ACKTIMEOUT override 81 S $P(^HLMA(HLMSG,"P"),U,5)=HLRETRM I $P(^("P"),U,7) S HLN("ACKTIME")=+$P(^("P"),U,7) 82 ;get header of message just sent 83 K HLJ M HLJ=^HLMA(HLMSG,"MSH") 84 ;first component of sending app. 85 S HLN("ECH")=$$P^HLTPCK2(.HLJ,2),HLN("SAN")=$P($$P^HLTPCK2(.HLJ,3),$E(HLN("ECH"))) 86 ;msg type, msg. id, commit ack, and app. ack parameter 87 S HLN("TYPE")=$$P^HLTPCK2(.HLJ,1),HLN("MID")=$$P^HLTPCK2(.HLJ,10),HLN("ACAT")=$$P^HLTPCK2(.HLJ,15),HLN("APAT")=$$P^HLTPCK2(.HLJ,16) 88 ;MSA segment, message is a response, can't have an a. ack. 89 S Z=$$MSA^HLTP3(+^HLMA(HLMSG,0)) I Z]"" S:HLN("ACAT")="" HLN("ACAT")="NE" S HLN("APAT")="NE" 90 ;for batch/file with commit ack, reset c. ack and a. ack variables 91 I "BHS,FHS"[HLN("TYPE") S Z=$E(HLJ(1,0),5),X=$$P^HLTPCK2(.HLJ,9),HLN("ACAT")=$P(X,Z,5),HLN("APAT")=$P(X,Z,6),HLN("MID")=$$P^HLTPCK2(.HLJ,11) 92 ;get event protocol 93 S HLN("EID")=+$P(^HLMA(HLMSG,0),U,8),X=$G(^ORD(101,HLN("EID"),770)) 94 ;set link counter to msg sent 95 D LLCNT^HLCSTCP(HLDP,4) 96 ;commit and app. ack is never, update status to complete and hang UNI-DIRECTIONAL WAIT 97 I HLN("ACAT")="NE",HLN("APAT")="NE" D Q 98 .D DONE(3) 99 .; 100 .; 101 .H $G(HLDWAIT) 102 ; 103 ;do structure is to stack error 104 D 105 . N $ETRAP,$ESTACK S $ETRAP="D RDERR^HLCSTCP2" 106 . ;HL*1.6*87: Read acknowledgement. 107 . ;Loop to re-read from buffer when receiving incorrect ack. 108 . F D Q:'+$G(HLREREAD) 109 .. S HLREREAD=1 110 .. ;override ack timeout 111 .. I $G(HLN("ACKTIME")) N HLDBACK S HLDBACK=HLN("ACKTIME") 112 .. ;check for response, quit if no-response, msg will be resent 113 .. ;HLRESP=ien 773^ien 772 for response message 114 .. S HLRESP=$$READ^HLCSTCP1() 115 .. ;if no response, decrement counter and quit 116 .. I 'HLRESP D Q 117 ...D LLCNT^HLCSTCP(HLDP,4,1) 118 ...S HLREREAD="0^No Response" 119 ...;check if the port needs to be closed and re-opened before the next re-transmission attempt 120 ...I $G(HLDRETRY("CLOSE")) D CLOSE^%ZISTCP K HLPORT 121 .. ;X 0=re-read msg, 1=commit ack, 3=app ack success, 4=error 122 .. S X=$$RSP^HLTP31(HLRESP,.HLN) 123 .. ;X=0, re-read msg. Incorrect ack (bad MSH,MSA,msg id,or sending app) 124 .. Q:'X 125 .. ;commit ack - done 126 .. I X=1 D S HLREREAD="0^Commit Ack" Q 127 ... ;don't need app. ack, set status to complete 128 ... I "NE"[HLN("APAT") D Q 129 ....D DONE(3) 130 ....; 131 ... ;response is deferred, set status to awaiting ack 132 ... D DONE(2) 133 ...; 134 .. ;Error, HLRESLT=error number^error message from HLTP3 135 .. I X=4 D Q 136 ... D DONE(4,+$G(HLRESLT),$P($G(HLRESLT),U,2)) 137 ...; 138 ... S HLREREAD="0^Error" 139 .. ;app ack was successful 140 .. D DONE(3) S HLREREAD="0^App Ack" 141 ..; 142 Q 143 ; 144 DCSEND ;direct connect 145 ; Set up error trap 146 N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP2" 147 ;override ack timeout 148 I $G(HLP("ACKTIME")) N HLDBACK S HLDBACK=HLP("ACKTIME") 149 I $$WRITE(HLMSG)<0 D:$G(HLERROR)]"" Q ;HL*1.6*77 150 . D STATUS^HLTF0(HLMSG,4,$P(HLERROR,"^"),$P(HLERROR,"^",2),1) ;HL*1.6*77 151 . D LLCNT^HLCSTCP(HLDP,3,1) 152 D LLCNT^HLCSTCP(HLDP,4) 153 ;do structure is to stack error 154 D 155 . N $ETRAP,$ESTACK S $ETRAP="D RDERR^HLCSTCP2" 156 . ;HLRESP=ien 773^ien 772 for response message 157 . S HLRESP=$$READ^HLCSTCP1() 158 ; 159 D DONE(3):$G(HLRESP),DONE(4,108,$S($G(HLERROR)]"":$P(HLERROR,"^",2),1:"No response")):'$G(HLRESP) 160 I $G(HLERROR)']"" D 161 .D MON^HLCSTCP("Idle") 162 .I '$G(HLRESP) S HLERROR="108^No response" 163 ;Close port 164 I $D(HLPORT) D CLOSE^%ZISTCP K HLPORT 165 Q 166 ; 167 DONE(ST,ERR,ERRMSG) ;set status to complete 168 ;ST=status, ERR=error ien, ERRMSG=error msg 169 D STATUS^HLTF0(HLMSG,ST,$G(ERR),$G(ERRMSG),1) 170 ; 171 ;**109** 172 D DEQUE^HLCSREP(HLDP,"O",HLMSG) 173 ; 174 ;check for more msg. 175 I $G(HLPRIO)'="I" S HLMSG=+$O(^HLMA("AC","O",HLDP,0)),HLRETRY=0 176 Q 177 ; 178 CHKMSG(HLI) ;check status of message and update if not cancelled 179 ;input: HLI=new status, HLMSG=ien of msg in 773 180 ;returns 1=msg was updated, 0=msg has been canceled 181 N X 182 ; 183 ;**109** 184 ;F L +^HLMA(HLMSG,"P"):1 Q:$T H 1 185 ; 186 ; 187 ; New HL*1.6*77 code starting here... 188 I '$D(^HLMA(HLMSG,"P")) D Q 0 189 . S HLERROR="2^Missing status field" 190 . D STATUS^HLTF0(HLMSG,4,$P(HLERROR,U),$P(HLERROR,U,2),1) 191 .; 192 .;**109** 193 . D DEQUE^HLCSREP(HLDP,"O",HLMSG) 194 .;L -^HLMA(HLMSG,"P") 195 ;**end 109** 196 ; 197 ; End of HL*1.6*77 modifications 198 ; 199 ;get status, quit if msg was cancelled 200 ; 201 ;**109** 202 ;S X=+^HLMA(HLMSG,"P") I X=3 L -^HLMA(HLMSG,"P") Q 0 203 S X=+^HLMA(HLMSG,"P") Q:X=3 0 204 ; 205 ;update status if it is different 206 I $G(HLI),HLI'=X D STATUS^HLTF0(HLMSG,HLI) 207 ; 208 ;**109** 209 ;L -^HLMA(HLMSG,"P") 210 ; 211 Q 1 212 ; 213 WRITE(HLDA) ; write message in HL7 format 214 ; HLDA - ien of message in 773 215 ; - start block $C(11) 216 ; - end block $C(28) 217 ; - record separator $C(13) 218 ;Output(s): 1 - Successful 219 ; -1 - Unsuccessful 220 ; 221 N HLDA2,HLAR,HLI,LINENO,X 222 ;set error trap, used when called from HLTP3 223 ; 224 ; New HL*1.6*77 code starts here... 225 N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP2" 226 I $G(^HLMA(HLDA,0))'>0 D Q -1 227 . S HLERROR="2^Message Text pointer missing" 228 S HLDA2=+$G(^HLMA(HLDA,0)) 229 ; End of HL*1.6*77 modifications... 230 ; 231 Q:'$G(^HLMA(HLDA,0)) -1 ;HL*1.6*77 232 ; header is in ^HLMA(, message is in ^HL(772, 233 S LINENO=1,HLI=0,HLAR="^HLMA(HLDA,""MSH"")" 234 U IO 235 D W $C(13) S HLAR="^HL(772,HLDA2,""IN"")",HLI=0 D 236 . F S HLI=$O(@HLAR@(HLI)) Q:'HLI S X=$G(^(HLI,0)) D 237 .. ;first line, need start block char. 238 .. S:LINENO=1 X=$C(11)_X 239 .. I X]"" W X,! 240 .. ;send CR for blank lines 241 .. I X="" W $C(13) 242 .. S LINENO=LINENO+1 243 ; Sends end block for this message 244 S X=$C(28)_$C(13) 245 U IO W X,! 246 I $G(IO(0))'="",$G(IO(0))'=IO U IO(0) ;switch to null device if opened to prevent 'leakage' 247 Q 1 248 ; 249 OPEN() ; -- Open TCP/IP device (Client) 250 ;HLPORT=port, defined only if port is open 251 ;HLPORTA=number of attempted opens 252 I $D(HLPORT) S IO=HLPORT D Q 1 253 . U IO 254 . I HLOS["OpenM" X "U IO:(::""-M"")" ;use packet mode on Cache' 255 N HLDOM,HLI,HLIP,HLPORTA 256 G OPENA^HLCSTCP3 257 ; 258 RDERR D RDERR^HLCSTCP4 Q ; Exceeded 10,000 bytes, so split on 12/2/03-LJA 259 ERROR D ERROR^HLCSTCP4 Q ; Exceeded 10,000 bytes, so split on 12/2/03-LJA 260 ; 261 CC(X) ;cleanup and close 262 D MON^HLCSTCP(X) 263 I $D(HLPORT) D CLOSE^%ZISTCP K HLPORT 264 H 2 265 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSTCP3.m
r613 r623 1 HLCSTCP3 ;SFIRMFO/RSD - BI-DIRECTIONAL TCP ; 09/13/2006 15:36 2 ;;1.6;HEALTH LEVEL SEVEN;**76,77,133,122**;OCT 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 OPENA ; 6 ; called from $$OPEN^HLCSTCP2 and this sub-routine OPENA 7 ; 8 I $G(HLMSG),$D(^HLMA(HLMSG,"P")) S HLPORTA=+$P(^("P"),U,6) 9 S POP=1 10 ; 11 ; patch HL*1.6*122 start 12 ; variable HLDRETR=re-transmit attemps (#870,200.02) 13 ; variable HLTCPLNK("TIMEOUT")=timeout for 3rd parameter of CALL^%ZISTCP() 14 ; defined in HLCSTCP routine 15 ; 16 I '$G(HLDRETR("COUNT")) S HLDRETR("COUNT")=1 17 I '$G(HLTCPLNK("TIMEOUT")) S HLTCPLNK("TIMEOUT")=5 18 S HLDRETR("COUNT-2")=HLDRETR("COUNT")+HLDRETR 19 ; patch 133 20 ; I $G(HLDIRECT("OPEN TIMEOUT")) D 21 ; .S HLI=1 22 ; .D CALL^%ZISTCP(HLTCPADD,HLTCPORT,HLDIRECT("OPEN TIMEOUT")) 23 ; E D 24 ; .F HLI=1:1:HLDRETR D CALL^%ZISTCP(HLTCPADD,HLTCPORT) Q:'POP 25 I $G(HLDIRECT("OPEN TIMEOUT")) D 26 . D MON^HLCSTCP("Open") 27 . D CALL^%ZISTCP(HLTCPADD,HLTCPORT,HLDIRECT("OPEN TIMEOUT")) 28 . ; give site one more chance to override the application setup 29 . I $G(POP),(HLTCPLNK("TIMEOUT")>HLDIRECT("OPEN TIMEOUT")) D 30 .. D CALL^%ZISTCP(HLTCPADD,HLTCPORT,HLTCPLNK("TIMEOUT")) 31 E D 32 . N COUNT 33 . ; try to connect HLDRETR times 34 . F HLDRETR("COUNT")=HLDRETR("COUNT"):1:HLDRETR("COUNT-2") D Q:('POP)!($$STOP^HLCSTCP) 35 .. D MON^HLCSTCP("Open") 36 .. ; D CALL^%ZISTCP(HLTCPADD,HLTCPORT) 37 .. D CALL^%ZISTCP(HLTCPADD,HLTCPORT,HLTCPLNK("TIMEOUT")) 38 .. ;open error 39 .. I POP D 40 ... D CC^HLCSTCP2("Openfail") 41 ... H $S(HLDRETR("COUNT")=1:0,HLDRETR("COUNT")<10:1,1:8) 42 ... I '$D(^XTMP("HL7-Openfail",$J)) D 43 .... S ^XTMP("HL7-Openfail",0)=$$FMADD^XLFDT($$NOW^XLFDT,3)_"^"_$$NOW^XLFDT 44 .... S ^XTMP("HL7-Openfail",$J,"COUNT","FIRST")=HLDRETR("COUNT")_"^"_$$NOW^XLFDT 45 ... S COUNT=$P($G(^XTMP("HL7-Openfail",$J,"COUNT","LAST")),"^")+1 46 ... S ^XTMP("HL7-Openfail",$J,"COUNT","LAST")=COUNT_"^"_$$NOW^XLFDT 47 ; 48 ;set # of opens back in msg 49 ; I $G(HLMSG),$D(^HLMA(HLMSG,"P")) S $P(^("P"),U,6)=HLPORTA+HLI 50 I $G(HLMSG),$D(^HLMA(HLMSG,"P")) S $P(^("P"),U,6)=HLDRETR("COUNT") 51 ; patch HL*1.6*122 end 52 ; 53 ;device open 54 I 'POP S HLPORT=IO D Q $S($G(HLERROR)]"":0,1:1) 55 . N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP2" ;HL*1.6*77 56 . ;if address came from DNS, set back into LL 57 . I $D(HLIP) S $P(^HLCS(870,HLDP,400),U)=HLTCPADD 58 . ; write and read to check if still open 59 . Q:HLOS'["OpenM" X "U IO:(::""-M"")" ; must be Cache/NT + use packet mode 60 . Q:$P(^HLCS(870,HLDP,400),U,7)'="Y" ; must want to SAY HELO 61 . U IO W "HELO "_$$KSP^XUPARAM("WHERE"),! R X:1 62 ;openfail-try DNS lookup 63 ; 64 ; patch HL*1.6*122 start 65 ;I '$D(HLDOM) S HLDOM=+$P(^HLCS(870,HLDP,0),U,7),HLDOM=$P($G(^DIC(4.2,HLDOM,0)),U) D:HLDOM]"" DNS 66 I '$D(HLDOM) D 67 . S HLDOM=+$P(^HLCS(870,HLDP,0),U,7),HLDOM=$P($G(^DIC(4.2,HLDOM,0)),U) 68 . S HLDOM("DNS")=$P($G(^HLCS(870,+$G(HLDP),0)),"^",8) 69 . D:HLDOM]""!($L(HLDOM("DNS"),".")>2) DNS 70 ; 71 Q:$$STOP^HLCSTCP 0 72 ;HLIP=ip add. from DNS call, get first one and try open again 73 I $D(HLIP) S HLTCPADD=$P(HLIP,","),HLIP=$P(HLIP,",",2,99) G:HLTCPADD OPENA 74 ; open error 75 ;cleanup and close 76 ; patch 133 77 I $G(HLDIRECT("OPEN TIMEOUT")) D 78 . D MON^HLCSTCP("Openfail") 79 . I $D(HLPORT) D CLOSE^%ZISTCP K HLPORT 80 E D 81 . D CC^HLCSTCP2("Openfail") 82 Q 0 83 ; patch HL*1.6*122 end 84 ; 85 ; 86 ;following code was removed, site's complained of to many alerts 87 ;couldn't open, send 1 alert 88 ;I '$G(HLPORTA) D 89 ;. ;send alert 90 ;. N XQA,XQAMSG,XQAOPT,XQAROU,XQAID,Z 91 ;. ;get mailgroup from file 869.3 92 ;. S Z=$P($$PARAM^HLCS2,U,8),HLPORTA="" Q:Z="" 93 ;. S XQA("G."_Z)="",XQAMSG=$$HTE^XLFDT($H,2)_" Logical Link "_$P(^HLCS(870,HLDP,0),U)_" exceeded Open Retries." 94 ;. D SETUP^XQALERT 95 ;open error 96 ;D CC("Openfail") H 3 97 ;Q 0 98 ; 99 ; 100 DNS ;VA domains must have "med" inserted. 101 ;All domains must use port 5000 and are prepended with "HL7" 102 ;non-VA DNS lookups will succeed if site uses port 5000 and 103 ;configure their local DNS with "HL7.yourdomain.com" and entries 104 ;are created in the logical link file and domain file. 105 D MON^HLCSTCP("DNS Lkup") 106 I HLDOM["VA.GOV"&(HLDOM'[".MED.") S HLDOM=$P(HLDOM,".VA.GOV")_".MED.VA.GOV" 107 I HLTCPORT=5000 S HLDOM="HL7."_HLDOM 108 I HLTCPORT=5500 S HLDOM="MPI."_HLDOM 109 ; 110 ; patch HL*1.6*122 start 111 I $L($G(HLDOM("DNS")),".")>2 D 112 . S HLDOM=HLDOM("DNS") 113 ; patch HL*1.6*122 end 114 ; 115 S HLIP=$$ADDRESS^XLFNSLK(HLDOM) 116 K:HLIP="" HLIP 117 Q 118 ; 1 HLCSTCP3 ;SFIRMFO/RSD - BI-DIRECTIONAL TCP ;09/13/2006 2 ;;1.6;HEALTH LEVEL SEVEN;**76,77,133**;OCT 13, 1995;Build 13 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 OPENA I $G(HLMSG),$D(^HLMA(HLMSG,"P")) S HLPORTA=+$P(^("P"),U,6) 6 D MON^HLCSTCP("Open") 7 S POP=1 8 I $G(HLDIRECT("OPEN TIMEOUT")) D 9 .S HLI=1 10 .D CALL^%ZISTCP(HLTCPADD,HLTCPORT,HLDIRECT("OPEN TIMEOUT")) 11 E D 12 .F HLI=1:1:HLDRETR D CALL^%ZISTCP(HLTCPADD,HLTCPORT) Q:'POP 13 ;set # of opens back in msg 14 I $G(HLMSG),$D(^HLMA(HLMSG,"P")) S $P(^("P"),U,6)=HLPORTA+HLI 15 ;device open 16 I 'POP S HLPORT=IO D Q $S($G(HLERROR)]"":0,1:1) 17 . N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLCSTCP2" ;HL*1.6*77 18 . ;if address came from DNS, set back into LL 19 . I $D(HLIP) S $P(^HLCS(870,HLDP,400),U)=HLTCPADD 20 . ; write and read to check if still open 21 . Q:HLOS'["OpenM" X "U IO:(::""-M"")" ; must be Cache/NT + use packet mode 22 . Q:$P(^HLCS(870,HLDP,400),U,7)'="Y" ; must want to SAY HELO 23 . U IO W "HELO "_$$KSP^XUPARAM("WHERE"),! R X:1 24 ;openfail-try DNS lookup 25 I '$D(HLDOM) S HLDOM=+$P(^HLCS(870,HLDP,0),U,7),HLDOM=$P($G(^DIC(4.2,HLDOM,0)),U) D:HLDOM]"" DNS 26 ;HLIP=ip add. from DNS call, get first one and try open again 27 I $D(HLIP) S HLTCPADD=$P(HLIP,","),HLIP=$P(HLIP,",",2,99) G:HLTCPADD OPENA 28 ;open error 29 I $G(HLDIRECT("OPEN TIMEOUT")) D 30 .D MON^HLCSTCP("Openfail") 31 .I $D(HLPORT) D CLOSE^%ZISTCP K HLPORT 32 E D 33 .D CC^HLCSTCP2("Openfail") H 3 34 Q 0 35 ; 36 ;following code was removed, site's complained of to many alerts 37 ;couldn't open, send 1 alert 38 ;I '$G(HLPORTA) D 39 ;. ;send alert 40 ;. N XQA,XQAMSG,XQAOPT,XQAROU,XQAID,Z 41 ;. ;get mailgroup from file 869.3 42 ;. S Z=$P($$PARAM^HLCS2,U,8),HLPORTA="" Q:Z="" 43 ;. S XQA("G."_Z)="",XQAMSG=$$HTE^XLFDT($H,2)_" Logical Link "_$P(^HLCS(870,HLDP,0),U)_" exceeded Open Retries." 44 ;. D SETUP^XQALERT 45 ;open error 46 ;D CC("Openfail") H 3 47 ;Q 0 48 ; 49 ; 50 DNS ;VA domains must have "med" inserted. 51 ;All domains must use port 5000 and are prepended with "HL7" 52 ;non-VA DNS lookups will succeed if site uses port 5000 and 53 ;configure their local DNS with "HL7.yourdomain.com" and entries 54 ;are created in the logical link file and domain file. 55 D MON^HLCSTCP("DNS Lkup") 56 I HLDOM["VA.GOV"&(HLDOM'[".MED.") S HLDOM=$P(HLDOM,".VA.GOV")_".MED.VA.GOV" 57 I HLTCPORT=5000 S HLDOM="HL7."_HLDOM 58 I HLTCPORT=5500 S HLDOM="MPI."_HLDOM 59 S HLIP=$$ADDRESS^XLFNSLK(HLDOM) 60 K:HLIP="" HLIP 61 Q 62 ; -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSTCP4.m
r613 r623 1 HLCSTCP4 ;SFIRMFO/RSD - BI-DIRECTIONAL TCP ;04/16/08 14:20 2 ;;1.6;HEALTH LEVEL SEVEN;**109,122,140**;Oct 13,1995;Build 5 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 Q 6 ; RDERR & ERROR moved from HLCSTCP2 on 12/2/2003 - LJA 7 ; 8 RDERR ; Error during read process, decrement counter 9 D LLCNT^HLCSTCP(HLDP,4,1) 10 ERROR ; Error trap 11 ; OPEN ERROR-retry. 12 ; WRITE ERROR (SERVER DISCONNECT)-close channel, retry 13 ; 14 ;**109** 15 ;I $G(HLMSG) L -^HLMA(HLMSG) 16 ; 17 ; patch HL*1.6*122 start 18 N STOP 19 S STOP=0 20 I $G(HLDP) S STOP=$$STOP^HLCSTCP 21 ; patch HL*1.6*140 22 S $ETRAP="D HALT^ZU" ;RWF 23 S HLTCP("$ZA\8192#2")="" 24 I (^%ZOSF("OS")["OpenM") D 25 . S HLTCP("$ZA")=$ZA 26 . ; For TCP devices $ZA\8192#2: the device is currently in the 27 . ; Connected state talking to a remote host. 28 . S HLTCP("$ZA\8192#2")=$ZA\8192#2 29 ; 30 S HLTCPERR("ERR-$ZE")=$$EC^%ZOSV 31 ; I $$EC^%ZOSV["OPENERR"!($$EC^%ZOSV["NOTOPEN")!($$EC^%ZOSV["DEVNOTOPN") D CC^HLCSTCP2("Op-err") S:$G(HLPRIO)="I" HLERROR="15^Open Related Error" D UNWIND^%ZTER Q 32 I $$EC^%ZOSV["OPENERR"!($$EC^%ZOSV["NOTOPEN")!($$EC^%ZOSV["DEVNOTOPN") D G:STOP H2^XUSCLEAN Q 33 . D CC^HLCSTCP2("Op-err") 34 . S:$G(HLPRIO)="I" HLERROR="15^Open Related Error" 35 . I STOP D Q 36 .. D CC^HLCSTCP2("Shutdown: (with 'Op-err')") 37 . I 'STOP D UNWIND^%ZTER 38 ; patch HL*1.6*140 start 39 ; I $$EC^%ZOSV["WRITE" D G:STOP!(HLTCP("$ZA\8192#2")=0) H2^XUSCLEAN Q 40 I $$EC^%ZOSV["WRITE" D G:STOP!(HLTCP("$ZA\8192#2")) H2^XUSCLEAN Q 41 . ; S:$G(HLPRIO)="I" HLERROR="108^Write Error" 42 . I $G(HLPRIO)="I" D Q 43 .. S HLERROR="108^Write Error" 44 .. D CC^HLCSTCP2("Wr-err") 45 .. D UNWIND^%ZTER 46 . ; 47 . I STOP D Q 48 .. D ^%ZTER,CC^HLCSTCP2("Shutdown: (with 'Wr-err')") 49 . E D Q 50 .. I HLTCP("$ZA\8192#2") D ^%ZTER,CC^HLCSTCP2("Wr-err") Q 51 .. E D Q 52 ... D CC^HLCSTCP2("Halt (Wr): (Disconnected with 'Wr-err')") 53 ... D UNWIND^%ZTER 54 ; 55 ; I $$EC^%ZOSV["READ" D CC^HLCSTCP2("Rd-err") S:$G(HLPRIO)="I" HLERROR="108^Read Error" D UNWIND^%ZTER Q 56 ; I $$EC^%ZOSV["READ" D G:STOP!(HLTCP("$ZA\8192#2")=0) H2^XUSCLEAN Q 57 I $$EC^%ZOSV["READ" D G:STOP!(HLTCP("$ZA\8192#2")) H2^XUSCLEAN Q 58 . ; S:$G(HLPRIO)="I" HLERROR="108^Read Error" 59 . I $G(HLPRIO)="I" D Q 60 .. S HLERROR="108^Read Error" 61 .. D CC^HLCSTCP2("Rd-err") 62 .. D UNWIND^%ZTER 63 . ; 64 . I STOP D Q 65 .. D ^%ZTER,CC^HLCSTCP2("Shutdown: (with 'Rd-err')") 66 . E D Q 67 .. I HLTCP("$ZA\8192#2") D ^%ZTER,CC^HLCSTCP2("Rd-err") Q 68 .. E D Q 69 ... D CC^HLCSTCP2("Halt (Rd): (Disconnected with 'Rd-err')") 70 ... D UNWIND^%ZTER 71 ; 72 ; S HLCSOUT=1 D ^%ZTER,CC^HLCSTCP2("Error"),SDFLD^HLCSTCP 73 ; S:$G(HLPRIO)="I" HLERROR="9^Error" 74 D ^%ZTER 75 I $G(HLPRIO)="I" D Q 76 . S HLERROR="9^Error" 77 . D CC^HLCSTCP2("Error") 78 . D UNWIND^%ZTER 79 ; 80 I STOP D Q 81 . D CC^HLCSTCP2("Shutdown: (with 'Error')") 82 . D H2^XUSCLEAN 83 ; 84 D CC^HLCSTCP2("Error") 85 ; patch HL*1.6*122 end 86 D H2^XUSCLEAN 87 ; patch HL*1.6*140 end 88 Q 89 ; 90 PROXY ; set DUZ for application proxy user 91 ; 92 ; removed the execution: patch 122 TEST v2 93 Q 94 ; 95 ;; S HLDUZ=+$$APFIND^XUSAP("HLSEVEN,APPLICATION PROXY") 96 ;; S DUZ=HLDUZ 97 ;; D DUZ^XUP(DUZ) 98 ;; Q 99 ; 100 HLDUZ ; compare DUZ and set DUZ to application proxy user 101 ; 102 ; removed the execution: patch 122 TEST v2 103 Q 104 ; 105 ;; I '$G(HLDUZ) D PROXY 106 ; 107 HLDUZ2 ; compare DUZ and HLDUZ 108 I $G(DUZ)'=HLDUZ D 109 . S DUZ=HLDUZ 110 . D DUZ^XUP(DUZ) 111 Q 112 ; 113 CLEANVAR ; clean variables for server, called from HLCSTCP1 114 ; 115 ; clean variables except Kernel related variables 116 ; protect variables defined in HLCSTCP 117 N HLDP 118 N HLCSOUT,HLDBACK,HLDBSIZE,HLDREAD,HLDRETR,HLRETRA,HLDWAIT,HLOS 119 N HLTCPADD,HLTCPCS,HLTCPLNK,HLTCPORT,HLTCPRET,HLCSFAIL,HLZRULE 120 ; 121 ; protect variables defined in LISTEN^HLCSTCP 122 ; N HLLSTN,HLCSOUT,HLDBACK,HLDBSIZE,HLDREAD,HLDRETR,HLRETRA,HLDWAIT 123 ; N HLOS,HLTCPADD,HLTCPCS,HLTCPLNK,HLTCPORT,HLTCPRET,HLCSFAIL 124 N HLLSTN 125 ; 126 ; protect variables defined in CACHEVMS^HLCSTCP and EN^HLCSTCP 127 N % 128 ; protect variables defined in this routine HLCSTCP1 129 N $ETRAP,$ESTACK 130 N HLMIEN,HLASTMSG 131 N HLTMBUF 132 N HLDUZ,DUZ 133 ; Kernel variables for single listener 134 N ZISOS,ZRULE 135 ; 136 D KILL^XUSCLEAN 137 Q 138 MIEN ; sets HLIND1=ien in 773^ien in 772 for message 139 N HLMID,X 140 I HLIND1 D 141 . S:'$G(^HLMA(+HLIND1,0)) HLIND1=0 142 . S:'$G(^HL(772,+$P(HLIND1,U,2),0)) HLIND1=0 143 ;msg. id is 10th of MSH & 11th for BSH or FSH 144 S X=10+($E(HLMSG(1,0),1,3)'="MSH"),HLMID=$$PMSH(.HLMSG,X) 145 ;if HLIND1 is set, kill old message, use HLIND1 for new 146 ;message, it means we never got end block for 1st msg. 147 I HLIND1 D Q 148 . ;get pointer to 772, kill header 149 . ; 150 . ; patch HL*1.6*122: MPI-client/server 151 . F L +^HLMA(+HLIND1):10 Q:$T H 1 152 . K ^HLMA(+HLIND1,"MSH") 153 . L -^HLMA(+HLIND1) 154 . ; 155 . I $D(^HL(772,+$P(HLIND1,U,2),"IN")) K ^("IN") 156 . S X=$$MAID^HLTF(+HLIND1,HLMID) 157 . D SAVE^HLCSTCP1(.HLMSG,"^HLMA("_+HLIND1_",""MSH"")") 158 . S:$P(HLIND1,U,3) $P(HLIND1,U,3)="" 159 D TCP^HLTF(.HLMID,.X,.HLDT) 160 S HLBUFF("IEN773")=X 161 I 'X D Q 162 . ;error - record and reset array 163 . ;killing HLLSTN will allow MON^HLCSTCP to work with multi-server 164 . D CLEAN^HLCSTCP1 K HLLSTN 165 . ;error 100=LLP could not en-queue the message, reset array 166 . D MONITOR^HLCSDR2(100,19,HLDP),MON^HLCSTCP("ERROR") H 30 167 ;HLIND1=ien in 773^ien in 772 168 S HLIND1=X_U_+$G(^HLMA(X,0)) 169 S HLBUFF("HLIND1")=HLIND1 170 ;save MSH into 773 171 D SAVE^HLCSTCP1(.HLMSG,"^HLMA("_+HLIND1_",""MSH"")") 172 Q 173 ; 174 PMSH(MSH,P) ;get piece P from MSH array (passed by ref.) 175 N FS,I,L,L1,L2,X,Y 176 S FS=$E(MSH(1,0),4),(L2,Y)=0,X="" 177 F I=1:1 S L1=$L($G(MSH(I,0)),FS),L=L1+Y-1 D Q:$L(X)!'$D(MSH(I,0)) 178 . S:L1=1 L=L+1 179 . S:P'>L X=$P($G(MSH(I-1,0)),FS,P-L2)_$P($G(MSH(I,0)),FS,(P-Y)) 180 . S L2=Y,Y=L 181 Q X 182 ; 183 ERROR1 ; 184 ; moved from ERROR^HLCSTCP1 185 ; Error trap for disconnect error and return back to the read loop. 186 ; patch HL*1.6*122 start 187 ; patch HL*1.6*140 188 ; S $ETRAP="D HALT^ZU" ;RWF 189 S $ETRAP="H 1 D HALT^ZU" ;RWF 190 I (^%ZOSF("OS")["OpenM") D 191 . S HLTCP("$ZA")=$ZA 192 . ; For TCP devices $ZA\8192#2: the device is currently in the 193 . ; Connected state talking to a remote host. 194 . S HLTCP("$ZA\8192#2")=$ZA\8192#2 195 . I HLTCP("$ZA\8192#2")=0 D 196 .. ; decrement counter of multi-listener 197 .. I $D(^HLCS(870,"E","M",+$G(HLDP))) D EXITM^HLCSTCP 198 .. ; process terminated 199 .. D H2^XUSCLEAN 200 ; patch HL*1.6*140 201 ;S $ETRAP="D UNWIND^%ZTER" ;RWF 202 ; I $$EC^%ZOSV["READ"!($$EC^%ZOSV["NOTOPEN")!($$EC^%ZOSV["DEVNOTOPN") D UNWIND^%ZTER Q 203 I ($$EC^%ZOSV["NOTOPEN")!($$EC^%ZOSV["DEVNOTOPN") D Q 204 . ; if it is not a multi-listener 205 . I '$D(^HLCS(870,"E","M",+$G(HLDP))) D CC^HLCSTCP1("Open-err") 206 . D UNWIND^%ZTER 207 I $$EC^%ZOSV["READ" D Q 208 . ; if it is not a multi-listener 209 . I '$D(^HLCS(870,"E","M",+$G(HLDP))) D CC^HLCSTCP1("Rd-err") 210 . D UNWIND^%ZTER 211 ; 212 ; I $$EC^%ZOSV["WRITE" D CC("Wr-err") D UNWIND^%ZTER Q 213 I $$EC^%ZOSV["WRITE" D Q 214 . ; if it is not a multi-listener 215 . I '$D(^HLCS(870,"E","M",+$G(HLDP))) D CC^HLCSTCP1("Wr-err") 216 . D UNWIND^%ZTER 217 ; 218 ; for GT.M 219 I $ECODE["UREAD" D Q 220 . ; if it is not a multi-listener 221 . I '$D(^HLCS(870,"E","M",+$G(HLDP))) D CC^HLCSTCP1("Rd-err") 222 . D UNWIND^%ZTER 223 ; 224 ; S HLCSOUT=1 D ^%ZTER,CC("Error") 225 S HLCSOUT=1 226 D ^%ZTER 227 ; if it is not a multi-listener 228 I '$D(^HLCS(870,"E","M",+$G(HLDP))) D CC^HLCSTCP1("Error") 229 ; patch HL*1.6*122 end 230 ; 231 D UNWIND^%ZTER 232 Q 233 ; 234 CLRMCNTR ; 235 ; clear the counter to set as "0 server" for multi-listener 236 ; HL*1.6*122 start 237 Q:'$G(HLDP) 238 Q:'$D(^HLCS(870,"E","M",HLDP)) 239 S $P(^HLCS(870,HLDP,0),"^",4)="MS" 240 S $P(^HLCS(870,HLDP,0),U,5)="0 server" 241 Q 242 ; 243 CREATUSR ; 244 ; patch HL*1.6*122 TEST v2: DUZ code removed 245 ; create application proxy users for listeners and incoming filer 246 ;; N HLTEMP 247 ;; S HLTEMP=$$CREATE^XUSAP("HLSEVEN,APPLICATION PROXY","#") 248 Q 1 HLCSTCP4 ;SFIRMFO/RSD - BI-DIRECTIONAL TCP ;11/03/2006 13:31 2 ;;1.6;HEALTH LEVEL SEVEN;**109,122**;Oct 13,1995;Build 4 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 Q 6 ; RDERR & ERROR moved from HLCSTCP2 on 12/2/2003 - LJA 7 ; 8 RDERR ; Error during read process, decrement counter 9 D LLCNT^HLCSTCP(HLDP,4,1) 10 ERROR ; Error trap 11 ; OPEN ERROR-retry. 12 ; WRITE ERROR (SERVER DISCONNECT)-close channel, retry 13 ; 14 ;**109** 15 ;I $G(HLMSG) L -^HLMA(HLMSG) 16 ; 17 S $ETRAP="D UNWIND^%ZTER" 18 ; patch HL*1.6*122 19 S HLTCPERR("$P")=$P 20 S HLTCPERR("ERR-$ZE")=$$EC^%ZOSV 21 ; I $$EC^%ZOSV["OPENERR"!($$EC^%ZOSV["NOTOPEN")!($$EC^%ZOSV["DEVNOTOPN") D CC^HLCSTCP2("Op-err") S:$G(HLPRIO)="I" HLERROR="15^Open Related Error" D UNWIND^%ZTER Q 22 I $$EC^%ZOSV["OPENERR"!($$EC^%ZOSV["NOTOPEN")!($$EC^%ZOSV["DEVNOTOPN") D Q 23 . D CC^HLCSTCP2("Op-err") 24 . S:$G(HLPRIO)="I" HLERROR="15^Open Related Error" 25 . D UNWIND^%ZTER 26 I $$EC^%ZOSV["WRITE" D Q ;HL*1.6*77 modifications start here 27 . D CC^HLCSTCP2("Wr-err") 28 . S:$G(HLPRIO)="I" HLERROR="108^Write Error" 29 . D UNWIND^%ZTER ;HL*1.6*77 modifications end here 30 ; I $$EC^%ZOSV["READ" D CC^HLCSTCP2("Rd-err") S:$G(HLPRIO)="I" HLERROR="108^Read Error" D UNWIND^%ZTER Q 31 I $$EC^%ZOSV["READ" D Q 32 . D CC^HLCSTCP2("Rd-err") 33 . S:$G(HLPRIO)="I" HLERROR="108^Read Error" 34 . D UNWIND^%ZTER 35 S HLCSOUT=1 D ^%ZTER,CC^HLCSTCP2("Error"),SDFLD^HLCSTCP 36 S:$G(HLPRIO)="I" HLERROR="9^Error" 37 D UNWIND^%ZTER 38 Q 39 ; 40 PROXY ; set DUZ for application proxy user 41 S HLDUZ=+$$APFIND^XUSAP("HLSEVEN,APPLICATION PROXY") 42 S DUZ=HLDUZ 43 D DUZ^XUP(DUZ) 44 Q 45 ; 46 HLDUZ ; compare DUZ and set DUZ to application proxy user 47 I '$G(HLDUZ) D PROXY 48 I $G(DUZ)'=HLDUZ D 49 . S DUZ=HLDUZ 50 . D DUZ^XUP(DUZ) 51 Q 52 ; 53 CLEANVAR ; clean variables for server, called from HLCSTCP1 54 ; 55 ; clean variables except Kernel related variables 56 ; protect variables defined in HLCSTCP 57 N HLDP 58 N HLCSOUT,HLDBACK,HLDBSIZE,HLDREAD,HLDRETR,HLRETRA,HLDWAIT,HLOS 59 N HLTCPADD,HLTCPCS,HLTCPLNK,HLTCPORT,HLTCPRET,HLCSFAIL,HLZRULE 60 ; 61 ; protect variables defined in LISTEN^HLCSTCP 62 ; N HLLSTN,HLCSOUT,HLDBACK,HLDBSIZE,HLDREAD,HLDRETR,HLRETRA,HLDWAIT 63 ; N HLOS,HLTCPADD,HLTCPCS,HLTCPLNK,HLTCPORT,HLTCPRET,HLCSFAIL 64 N HLLSTN 65 ; 66 ; protect variables defined in CACHEVMS^HLCSTCP and EN^HLCSTCP 67 N % 68 ; protect variables defined in this routine HLCSTCP1 69 N $ETRAP,$ESTACK 70 N HLMIEN,HLASTMSG 71 N HLTMBUF 72 N HLDUZ,DUZ 73 ; Kernel variables for single listener 74 N ZISOS,ZRULE 75 ; 76 D KILL^XUSCLEAN 77 Q 78 MIEN ; sets HLIND1=ien in 773^ien in 772 for message 79 N HLMID,X 80 I HLIND1 D 81 . S:'$G(^HLMA(+HLIND1,0)) HLIND1=0 82 . S:'$G(^HL(772,+$P(HLIND1,U,2),0)) HLIND1=0 83 ;msg. id is 10th of MSH & 11th for BSH or FSH 84 S X=10+($E(HLMSG(1,0),1,3)'="MSH"),HLMID=$$PMSH(.HLMSG,X) 85 ;if HLIND1 is set, kill old message, use HLIND1 for new 86 ;message, it means we never got end block for 1st msg. 87 I HLIND1 D Q 88 . ;get pointer to 772, kill header 89 . K ^HLMA(+HLIND1,"MSH") 90 . I $D(^HL(772,+$P(HLIND1,U,2),"IN")) K ^("IN") 91 . S X=$$MAID^HLTF(+HLIND1,HLMID) 92 . D SAVE^HLCSTCP1(.HLMSG,"^HLMA("_+HLIND1_",""MSH"")") 93 . S:$P(HLIND1,U,3) $P(HLIND1,U,3)="" 94 D TCP^HLTF(.HLMID,.X,.HLDT) 95 S HLBUFF("IEN773")=X 96 I 'X D Q 97 . ;error - record and reset array 98 . ;killing HLLSTN will allow MON^HLCSTCP to work with multi-server 99 . D CLEAN^HLCSTCP1 K HLLSTN 100 . ;error 100=LLP Could not Enqueue the Message, reset array 101 . D MONITOR^HLCSDR2(100,19,HLDP),MON^HLCSTCP("ERROR") H 30 102 ;HLIND1=ien in 773^ien in 772 103 S HLIND1=X_U_+$G(^HLMA(X,0)) 104 S HLBUFF("HLIND1")=HLIND1 105 ;save MSH into 773 106 D SAVE^HLCSTCP1(.HLMSG,"^HLMA("_+HLIND1_",""MSH"")") 107 Q 108 ; 109 PMSH(MSH,P) ;get piece P from MSH array (passed by ref.) 110 N FS,I,L,L1,L2,X,Y 111 S FS=$E(MSH(1,0),4),(L2,Y)=0,X="" 112 F I=1:1 S L1=$L($G(MSH(I,0)),FS),L=L1+Y-1 D Q:$L(X)!'$D(MSH(I,0)) 113 . S:L1=1 L=L+1 114 . S:P'>L X=$P($G(MSH(I-1,0)),FS,P-L2)_$P($G(MSH(I,0)),FS,(P-Y)) 115 . S L2=Y,Y=L 116 Q X 117 ; -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSTCPA.m
r613 r623 1 HLCSTCPA ;OIFO-O/RJH - (TCP/IP) VMS ;07/26/2007 10:29 2 ;;1.6;HEALTH LEVEL SEVEN;**84,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ; 1. port number is input from VMS COM file, such as HLSxxxxDSM.COM, 6 ; HLSxxxxCACHE.COM, or HLSxxxxGTM.COM file, where xxxx is port 7 ; number. 8 ; 2. find the ien of #870(logical link file) for the multi-listener 9 Q 10 ; 11 GTMPORT(%) ; From tcpip ZFOO for GT.M 12 ; %: device^port number 13 N HLPORT 14 S HLPORT=$P($G(%),"^",2) 15 I $G(^%ZOSF("OS"))'["GT.M" D ^%ZTER Q 16 D IEN 17 Q 18 ; 19 PORT ; 20 ; HLPORT: port number of multi-listener 21 ; input of DSM: % = device^port number of multi-listener 22 ; input of Cache: port number of TCPIP 23 ; 24 N HLPORT 25 S HLPORT=0 26 I ^%ZOSF("OS")["OpenM" D 27 . S HLPORT=$ZF("GETSYM","PORT") 28 I ^%ZOSF("OS")["DSM" D 29 . S HLPORT=$P(%,"^",2) 30 ; 31 IEN ; 32 ; HLIEN870: ien in #870 (logical link file) 33 ; HLPRTS: port number in entry to be tested 34 ; 35 N HLIEN870 36 I 'HLPORT D ^%ZTER Q 37 S HLIEN870=0 38 F S HLIEN870=$O(^HLCS(870,"E","M",HLIEN870)) Q:'HLIEN870 D Q:(HLPRTS=HLPORT) 39 . S HLPRTS=$P(^HLCS(870,HLIEN870,400),"^",2) 40 I 'HLIEN870 D ^%ZTER Q 41 ; 42 K HLPORT,HLPRTS 43 ; patch 122 44 S U="^" 45 ; 46 ;for Cache/VMS 47 I ^%ZOSF("OS")["OpenM" D Q 48 . D CACHEVMS(HLIEN870) 49 ; 50 ;for DSM 51 I ^%ZOSF("OS")["DSM" D Q 52 . S $P(%,"^",2)=HLIEN870 ;set % = device^ien of #870 53 . K HLIEN870 54 . D EN 55 ; 56 ;for GT.M 57 I ^%ZOSF("OS")["GT.M" D Q 58 . S HLDP=HLIEN870 ;set HLDP = ien of #870 59 . K HLIEN870 60 . D GTMUCX 61 ; 62 D ^%ZTER 63 Q 64 GTMUCX ; GT.M /VMS tcpip 65 ;listener, % = device^port 66 S U="^",IO=$P(%,U) 67 ; S IO(0)=$P O IO(0) ;Setup null device 68 ; GTM specific code 69 S @("$ZINTERRUPT=""I $$JOBEXAM^ZU($ZPOSITION)""") 70 X "O IO:(RECORDSIZE=512)" 71 D LISTEN^HLCSTCP 72 C IO 73 Q 74 ; 75 ; $ x=f$trnlnm("sys$net") !This is our MBX device 76 ; $! 77 ; $! for GT.M 78 ; $ assign 'f$trnlnm("SYS$NET")' SYS$NET 79 ; $! Depending on how your command files are set up, you may need to 80 ; $! run the GT.M profile file. 81 ; $ @<user$:[gtmmgr]>gtmprofile.com 82 ; $ forfoo="$" + f$parse("user$:[gtmmgr.r]ZFOO.exe") 83 ; $ PORT=5000 84 ; $ data="''x'^''PORT'" 85 ; $ forfoo GTMPORT^HLCSTCPA("''data'") 86 ; 87 CACHEVMS(%) ;Cache'/VMS tcpip 88 ;listener, % = HLDP 89 I $G(%)="" D ^%ZTER Q 90 ; patch 133 91 S IO="SYS$NET",U="^",HLDP=% 92 S IO(0)="_NLA0:" O IO(0) ;Setup null device 93 ; **Cache'/VMS specific code** 94 O IO::5 E D MON^HLCSTCP("Openfail") Q 95 X "U IO:(::""-M"")" ;Packet mode like DSM 96 D LISTEN^HLCSTCP 97 C IO 98 Q 99 ; 100 EN ; DSM/VMS tcpip 101 ;listener, % = device^HLDP 102 I $G(%)="" D ^%ZTER Q 103 ; patch 122 104 ; S IO="SYS$NET",U="^",HLDP=$P(%,U,2) 105 S U="^",IO=$P(%,U),HLDP=$P(%,U,2) 106 ; patch 133 107 S IO(0)="_NLA0:" O IO(0) ;Setup null device 108 ; **VMS specific code, need to share device** 109 O IO:(TCPDEV):60 E D MON^HLCSTCP("Openfail") Q 110 ; patch 122 111 D LISTEN^HLCSTCP 112 C IO 113 Q 1 HLCSTCPA ;OIFO-O/RJH - (TCP/IP) VMS ;07/10/2003 10:12 2 ;;1.6;HEALTH LEVEL SEVEN;**84**;Oct 13, 1995 3 ; 4 ; 1. port number is input from VMS HLSxxxxDSM.COM or HLSxxxxCACHE.COM 5 ; file, where xxxx is port number. 6 ; 2. find the ien of #870(logical link file) for the HL7 multi-listener 7 ; 3. call the appropriate entry: 8 ; for Cache: CACHEVMS^HLCSTCP(ien of #870) 9 ; for DSM: EN^HLCSTCP 10 Q 11 PORT ; 12 ;HLIEN870: ien in #870 (logical link file) 13 ;HLPORT: port number of multi-listener 14 ;HLPRTS: port number in entry to be tested 15 ;input of DSM: % = device^port number of multi-listener 16 ;input of Cache: port number of TCPIP 17 ; 18 I ^%ZOSF("OS")["OpenM" D 19 . S HLPORT=$ZF("GETSYM","PORT") 20 I ^%ZOSF("OS")["DSM" D 21 . S HLPORT=$P(%,"^",2) 22 I 'HLPORT D ^%ZTER Q 23 S HLIEN870=0 24 F S HLIEN870=$O(^HLCS(870,"E","M",HLIEN870)) Q:'HLIEN870 D Q:(HLPRTS=HLPORT) 25 . S HLPRTS=$P(^HLCS(870,HLIEN870,400),"^",2) 26 I 'HLIEN870 D ^%ZTER Q 27 ; 28 K HLPORT,HLPRTS 29 ; 30 ;for Cache/VMS 31 I ^%ZOSF("OS")["OpenM" D Q 32 .D CACHEVMS^HLCSTCP(HLIEN870) 33 ; 34 ;for DSM 35 I ^%ZOSF("OS")["DSM" D Q 36 . S $P(%,"^",2)=HLIEN870 ;set % = device^ien of #870 37 . K HLIEN870 38 . D EN^HLCSTCP 39 ; 40 D ^%ZTER 41 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLCSTERM.m
r613 r623 1 HLCSTERM ;ALB/RJS - SET UP VIDEO ATTRIBUTES ;06/27/2007 17:04 2 ;;1.6;HEALTH LEVEL SEVEN;**40,49,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 TERM ; -- set up term characteristics 6 N X 7 I '$D(IOST(0)) D HOME^%ZIS 8 S X=$$IO D ENDR^%ZISS 9 S (HLCON,HLCOFF)="" 10 I $E(IOST,1,4)="C-VT" S HLCOFF=$C(13,27,91)_"?25l"_$C(13),HLCON=$C(27,91)_"?25h" 11 Q 12 HEADER ; 13 ;Write out Header 14 ; 15 N HLMIDDLE,HLLNGTH,HLJUST 16 W @IOF,! 17 S HLPARAM=$$PARAM^HLCS2 18 S HLSITE=$P(HLPARAM,U,5),HLPROD=$P(HLPARAM,U,3) 19 S HLHDR="SYSTEM LINK MONITOR for "_HLSITE_" ("_HLPROD_" System)" 20 S HLMIDDLE=IOM\2,HLLNGTH=$L(HLHDR)\2,HLJUST=HLMIDDLE-HLLNGTH 21 D WDATA^HLCSMON1(HLJUST,1,IORVON,IORVOFF,HLHDR,75) 22 D WDATA^HLCSMON1(5,4,IOUON,IOUOFF,"NODE",8) 23 D WDATA^HLCSMON1(16,3,"","","MESSAGES",8),WDATA^HLCSMON1(16,4,IOUON,IOUOFF,"RECEIVED",8) 24 D WDATA^HLCSMON1(26,3,"","","MESSAGES",8),WDATA^HLCSMON1(26,4,IOUON,IOUOFF,"PROCESSED",9) 25 D WDATA^HLCSMON1(37,3,"","","MESSAGES",8),WDATA^HLCSMON1(37,4,IOUON,IOUOFF,"TO SEND ",8) 26 D WDATA^HLCSMON1(47,3,"","","MESSAGES",8),WDATA^HLCSMON1(47,4,IOUON,IOUOFF,"SENT ",8) 27 ; patch HL*1.6*122 28 ; D WDATA^HLCSMON1(57,3,"","","DEVICE",8),WDATA^HLCSMON1(57,4,IOUON,IOUOFF,"TYPE ",8) 29 D WDATA^HLCSMON1(57,3,"","","DEVICE",8),WDATA^HLCSMON1(57,4,IOUON,IOUOFF,"TYPE ",6) 30 ; 31 D WDATA^HLCSMON1(66,4,IOUON,IOUOFF,"STATE",8) 32 Q 33 KVAR ; 34 D KILL^%ZISS 35 K HLCON,HLCOFF 36 Q 37 IO() ; -- what device params 38 Q "IOELALL;IOELEOL;IORESET;IORVON;IORVOFF;IOIL;IOSTBM;IOSC;IORC;IOEDEOP;IOINHI;IOINORM;IOUON;IOUOFF;IOBOFF;IOBON" 39 Q 1 HLCSTERM ;ALB/RJS - SET UP VIDEO ATTRIBUTES - 8/1/94 ;07/28/98 09:43 2 ;;1.6;HEALTH LEVEL SEVEN;**40,49**;Oct 13, 1995 3 TERM ; -- set up term characteristics 4 N X 5 I '$D(IOST(0)) D HOME^%ZIS 6 S X=$$IO D ENDR^%ZISS 7 S (HLCON,HLCOFF)="" 8 I $E(IOST,1,4)="C-VT" S HLCOFF=$C(13,27,91)_"?25l"_$C(13),HLCON=$C(27,91)_"?25h" 9 Q 10 HEADER ; 11 ;Write out Header 12 ; 13 N HLMIDDLE,HLLNGTH,HLJUST 14 W @IOF,! 15 S HLPARAM=$$PARAM^HLCS2 16 S HLSITE=$P(HLPARAM,U,5),HLPROD=$P(HLPARAM,U,3) 17 S HLHDR="SYSTEM LINK MONITOR for "_HLSITE_" ("_HLPROD_" System)" 18 S HLMIDDLE=IOM\2,HLLNGTH=$L(HLHDR)\2,HLJUST=HLMIDDLE-HLLNGTH 19 D WDATA^HLCSMON1(HLJUST,1,IORVON,IORVOFF,HLHDR,75) 20 D WDATA^HLCSMON1(5,4,IOUON,IOUOFF,"NODE",8) 21 D WDATA^HLCSMON1(16,3,"","","MESSAGES",8),WDATA^HLCSMON1(16,4,IOUON,IOUOFF,"RECEIVED",8) 22 D WDATA^HLCSMON1(26,3,"","","MESSAGES",8),WDATA^HLCSMON1(26,4,IOUON,IOUOFF,"PROCESSED",9) 23 D WDATA^HLCSMON1(37,3,"","","MESSAGES",8),WDATA^HLCSMON1(37,4,IOUON,IOUOFF,"TO SEND ",8) 24 D WDATA^HLCSMON1(47,3,"","","MESSAGES",8),WDATA^HLCSMON1(47,4,IOUON,IOUOFF,"SENT ",8) 25 D WDATA^HLCSMON1(57,3,"","","DEVICE",8),WDATA^HLCSMON1(57,4,IOUON,IOUOFF,"TYPE ",8) 26 D WDATA^HLCSMON1(66,4,IOUON,IOUOFF,"STATE",8) 27 Q 28 KVAR ; 29 D KILL^%ZISS 30 K HLCON,HLCOFF 31 Q 32 IO() ; -- what device params 33 Q "IOELALL;IOELEOL;IORESET;IORVON;IORVOFF;IOIL;IOSTBM;IOSC;IORC;IOEDEOP;IOINHI;IOINORM;IOUON;IOUOFF;IOBOFF;IOBON" 34 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLDIE.m
r613 r623 1 HLDIE ;CIOFO-O/LJA - Direct 772 & 773 Sets ; 10/19/2007 11:15 2 ;;1.6;HEALTH LEVEL SEVEN;**109,122**;Oct 13,1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 Q 5 ; 6 ; Rules: if any of these rules is broken, FILE^DIE is called instead 7 ; 8 ; * Can't edit files other than 772,773 9 ; * Don't pass IENS value with multiples IENs. You can only 10 ; edit one IEN at a time! 11 ; * Only flag "S" is honored. Flag "K" is ignored. Other 12 ; flags result in FILE^DIE being called. 13 ; * Can't edit ^HLMA(IEN,90) data. 14 ; * Can't edit ^HLMA(IEN,91) data. 15 ; * Can't edit ^HL(772,IEN,"IN") data (field #200, MESSAGE TEXT) 16 ; * No checking of data performed! (Data format MUST be OK.) 17 ; * No locking of records in files 772 or 773. (Locks on queues.) 18 ; 19 FILE(FLAGS,ROOT,ERR,SUB,RTN) ; FILE^DIE functional equivalent... 20 ; This call has similar parameters to FILE^DIE, but changes data 21 ; using hard sets. The first two parameters of this API are the 22 ; same as FILE^DIE. So, if any file other than 772 or 773 is being 23 ; edited, this API just passes on the FLAGS,ROOT,ERR parameters to 24 ; FILE^DIE and quits. If file 772 or 773 is being edited, the hard 25 ; set code in HLDIE772 and HLDIE773 is called. 26 ; 27 N DEBUG,FILE,HLEDITOR,LERR,IEN,X,XECMCODE 28 ; 29 S DT=$$NOW^XLFDT\1 30 ; 31 D BEGIN ; Debug call at beginning or process 32 ; 33 ; Check FILE, IEN, FIELDs passed, etc... 34 I '$$CHECKS D QUIT ;-> 35 . 36 . S HLEDITOR="FILE^DIE" 37 . 38 . ; Call FILEMAN... 39 . D FILE^DIE($G(FLAGS),$G(ROOT),$G(ERR)) 40 . 41 . ; Debug call made even with Fileman... 42 . D END 43 ; 44 S HLEDITOR="FILE^HLDIE" 45 ; 46 ; If this point is reached, file 772 or 773 is being edited, data 47 ; in ROOT() has been checked, and data is being hard set... 48 ; 49 ; 50 ; Make sure ERR is defined... 51 I $G(ERR)']"" N HLERR S ERR="HLERR" 52 ; 53 ; All editing occurs in this call... 54 D EDITALL(.ROOT,FILE,IEN) 55 ; 56 ; Store debug data if XTMP debug string set... 57 D END 58 ; 59 ;check if ROOT needs to be retained 60 I FLAGS'["S" K @ROOT,FLAGS 61 ; 62 Q 63 ; 64 EDITALL(ROOT,FILE,IEN) ; Edit 772 or 773 by direct sets... 65 ; 66 ; FILE,IEN -- optional (parsed from ROOT()) 67 ; 68 N ERRNO,FIELD,GBL,NODE,ROUTINE,TAG,VALUE,XRF 69 ; 70 S GBL=$$GBL(FILE,+IEN) 71 ; 72 ;check if .01="@" for deletion of record... 73 I $G(@ROOT@(FILE,IEN,.01))="@" D Q 74 .I FILE=773 D DEL773^HLUOPT3(+IEN) Q 75 .I FILE=772 D DEL772^HLUOPT3(+IEN) 76 ; 77 ; patch HL*1.6*122: MPI-client/server 78 ; If no data in record passed in, log an error and quit... 79 ; I '$D(@GBL) D Q ; Remember. GBL contains IEN... 80 N HLDGBL 81 F L +@GBL:10 Q:$T H 1 82 S HLDGBL=$D(@GBL) 83 L -@GBL 84 I 'HLDGBL D Q ; Remember. GBL contains IEN... 85 . S ERRNO=$$ERRNO(601,"The entry does not exist.",FILE,2) 86 . S @ERR@("DIERR",+ERRNO,"PARAM","IENS")=IEN_$S(IEN'[",":",",1:"") 87 ; 88 ; 89 ; What routine holds the file-specific field/xref set code? 90 S ROUTINE=$S(FILE=772:"HLDIE772",FILE=773:"HLDIE773",1:"") 91 ; 92 ; Load NODEs... 93 D GETNODES(FILE,+IEN,.NODE) 94 ; 95 ; When a field is edited, the NODE(1) is changed 96 ; 97 ; Edit NODE(1), adding new values, and set XRF(XREF) nodes... 98 S FIELD=0 99 F S FIELD=$O(@ROOT@(FILE,IEN,FIELD)) Q:FIELD'>0 D 100 . ; VALUE = value passed in by process that is to be stored in file 101 . S VALUE=$G(@ROOT@(FILE,IEN,FIELD)) 102 . 103 . ; If field should be deleted, VALUE will equal @... 104 . I VALUE="@" S VALUE="" 105 . 106 . ; Get and check tag... 107 . S TAG="F"_(FILE-770)_$TR(FIELD,".","")_U_ROUTINE 108 . S TAG(1)=$T(@TAG) I TAG(1)']"" D QUIT ;-> 109 . . S ERRNO=$$ERRNO(501,"No set logic for file #"_FILE_"'s field# "_FIELD,FILE,3) 110 . . S @ERR@("DIERR",+ERRNO,"PARAM",1)=FIELD 111 . . S @ERR@("DIERR",+ERRNO,"PARAM","FIELD")=FIELD 112 . 113 . ; Call the subroutine below that is for the specific field... 114 . ; (No editing of xrefs or global data occurs in these calls.) 115 . D @("F"_(FILE-770)_$TR(FIELD,".","")_U_ROUTINE) 116 ; 117 ; If no data actually changed, quit... 118 QUIT:'$D(NODE("CHG")) ;-> 119 ; 120 ; patch HL*1.6*122: MPI-client/server 121 I FILE=773 D 122 . F L +^HLMA(IEN):10 Q:$T H 1 123 E D 124 . F L +^HL(772,IEN):10 Q:$T H 1 125 ; 126 ; Store changes in the global now... 127 D STORE(FILE,IEN,.NODE) 128 ; 129 ; Set xrefs to correspond to the just-stored data... 130 S XRF="" 131 F S XRF=$O(XRF(XRF)) Q:XRF']"" D 132 . D @("XRF"_XRF_U_ROUTINE) 133 ; 134 ; patch HL*1.6*122: MPI-client/server 135 I FILE=773 L -^HLMA(IEN) 136 E L -^HL(772,IEN) 137 ; 138 Q 139 ; 140 GETNODES(FILE,IEN,NODE) ; Load pre-change data for each node in 141 ; NODE(node,0), and load node to be changed in NODE(node,1). 142 ; GBL -- req 143 F NODE=0,1,2,"P","S" D 144 . ; After setting, NODE(NODE,0) will equal each other. 145 . ; However, after each edited field is processed, the pieces of 146 . ; data in NODE(NODE,1) will be changed. The pre and post nodes 147 . ; then are of comparison value. 148 . S NODE(NODE,0)=$G(@GBL@(NODE)) ; Pre-change node 149 . S NODE(NODE,1)=NODE(NODE,0) ; Node that is changed 150 Q 151 ; 152 STORE(FILE,IEN,NODE) ; Store changes in file... 153 N DATA,ND 154 ; 155 ; Loop thru change nodes, get changed data, and store it... 156 S ND="" 157 F S ND=$O(NODE("CHG",ND)) Q:ND']"" D 158 . S DATA=$G(NODE(ND,1)) 159 . ; Even if no data no node, store it. (Will be removed by purge.) 160 . I FILE=772 S ^HL(772,+IEN,ND)=DATA 161 . I FILE=773 S ^HLMA(+IEN,ND)=DATA 162 ; 163 QUIT 164 ; 165 GBL(FILE,IEN) QUIT $S(FILE=772:"^HL(772,"_+IEN_")",1:"^HLMA("_+IEN_")") 166 ; 167 CHKFLD(FILE,FIELD) ; Does passed-in field exist? 168 ; Returns -- @ERR@(...) -> 169 ; 170 ; Quit if field exists... 171 QUIT:$D(^DD(+FILE,+FIELD)) 1 ;-> 172 ; 173 ; Field doesn't exist. Log error... 174 S ERRNO=$$ERRNO(501,"File #"_FILE_" does not contain a field "_FIELD_".",FILE,3) 175 S @ERR@("DIERR",+ERRNO,"PARAM",1)=FIELD 176 S @ERR@("DIERR",+ERRNO,"PARAM","FIELD")=FIELD 177 ; 178 Q "" 179 ; 180 ERRNO(NUM,TXT,FILE,PNO) ; Return next ERROR number and create general data... 181 N NO 182 S NO=$G(@ERR@("DIERR"))+1,@ERR@("DIERR")=+NO_U_+NO 183 S @ERR@("DIERR",NO)=NUM 184 S @ERR@("DIERR",NO,"PARAM",0)=PNO 185 S @ERR@("DIERR",NO,"PARAM","FILE")=FILE 186 S @ERR@("DIERR",NO,"TEXT",1)=TXT 187 S @ERR@("DIERR","E",NUM,NO)="" 188 Q NO 189 ; 190 GENLERR(ETXT) ; Store GENERAL (and fatal) error... 191 ; ERR -- req 192 N NO 193 S NO=$G(@ERR@("DIERR"))+1,@ERR@("DIERR")=+NO_U_+NO 194 S @ERR@("DIERR",NO)=999_U_ETXT ; Made up error number 195 Q 196 ; 197 CHECKS() ; Check ROOT() for file and validity of data... 198 ; FLAGS, ROOT() -- req --> FILE,IEN 199 N I,OK,FIELD 200 ; 201 ;check the file & ien 202 S FILE=$O(@ROOT@(0)) 203 I FILE'=772,FILE'=773 D QUIT "" ;-> 204 . S IEN=$S(FILE:$O(@ROOT@(FILE,0)),1:0) ; Set for debugging 205 ; 206 ; ;shouldn't be more than 1 file! 207 QUIT:$O(@ROOT@(FILE)) "" ;-> 208 ; 209 ;check the ien structure, and that only ien passed... 210 S IEN=$O(@ROOT@(FILE,0)) 211 ; Structure check... 212 QUIT:$P(IEN,",")'=+IEN_"," "" ;-> 213 ; Is it numeric? 214 QUIT:'(+IEN) "" ;-> 215 ; Has more than one IEN been passed? 216 QUIT:($O(@ROOT@(FILE,IEN))'="") "" ;-> 217 ; 218 ;check the flags. Only K and S flags allowed... 219 I $L(FLAGS) D QUIT:'OK "" ;-> 220 . S OK=1 221 . F I=0:1:$L(FLAGS) I $E(FLAGS,I)'="K",$E(FLAGS,I)'="S" S OK=0 222 ; 223 ; Check for existence of FIELD in FILE's DD & if an excluded field. 224 ; (See rules for fields which cannot be updated by FILE^HLDIE.) 225 S FIELD=0,OK=1 226 F S FIELD=$O(@ROOT@(FILE,IEN,FIELD)) Q:FIELD="" D Q:'OK 227 . I '$$CHKFLD(FILE,FIELD) S OK=0 Q 228 . I FILE=773,FIELD\1=90 S OK=0 Q 229 . I FILE=773,FIELD\1=91 S OK=0 Q 230 . I FILE=772,FIELD=200 S OK=0 Q 231 ; 232 ; If not OK to use FILE^HLDIE, skip any further testing... 233 QUIT:'OK "" ;-> 234 ; 235 ; *** WARNING *** 236 ; The following check **MUST** be removed after FILE^HLDIE is working. 237 ; 238 ; Final check for whether FILE^HLDIE should be used... 239 I $G(^XTMP("HLDIE-DEBUG","CALL"))]"" QUIT "" ;-> 240 ; If this node exists and follows null, FILE^DIE will be used. 241 ; Otherwise, execution defaults to using FILE^HLDIE. 242 ; 243 Q OK 244 ; 245 BEGIN ; Always call here before any ^HLDIE or ^DIE calls... 246 D DEBUG(1) 247 Q 248 ; 249 END ; Always call here after all ^HLDIE or ^DIE actions... 250 D DEBUG(2) 251 Q 252 ; 253 DEBUG(LOC) ; Debug presets and setup... 254 ; Most variables created here should be left around. These variables 255 ; are newed above. 256 N STORE 257 ; 258 S RTN=$G(RTN),SUB=$G(SUB) 259 ; 260 ; First-time (beginning) call setups... 261 I LOC=1 D 262 . S RTN=$S(RTN]"":RTN,1:"HLDIE")_"~"_$S(RTN="HLDIE":"FILE",1:SUB) 263 . S DEBUG=$G(^XTMP("HLDIE-DEBUG","STATUS")) 264 . S XECMCODE=$P(DEBUG,U,3) 265 ; DEBUG is always called at beginning (LOC=1) and end (LOC=2) or 266 ; FILE^HLDIE. So, set up variables only once, at beginning... 267 ; 268 ; Setup that is individual to each (1 or 2) call... 269 S STORE=$P(DEBUG,U,LOC),STORE=$S(STORE=1:1,STORE=2:2,1:"") 270 ; Some, All, or no data stored? 271 ; 272 ; If no STORE instructions, and no M code to specify STORE, quit... 273 QUIT:'STORE&($G(XECMCODE)'=1) ;-> 274 ; 275 ; Call DEBUG to STORE data... 276 D DEBUG^HLDIEDBG(RTN,LOC,STORE,XECMCODE) 277 ; 278 Q 279 ; 280 EOR ;HLDIE - Direct 772 & 773 Sets ; 11/18/2003 11:17 1 HLDIE ;CIOFO-O/LJA - Direct 772 & 773 Sets ; 11/18/2003 11:17 2 ;;1.6;HEALTH LEVEL SEVEN;**109**;Oct 13,1995 3 ; 4 ; Rules: if any of these rules is broken, FILE^DIE is called instead 5 ; 6 ; * Can't edit files other than 772,773 7 ; * Don't pass IENS value with multiples IENs. You can only 8 ; edit one IEN at a time! 9 ; * Only flag "S" is honored. Flag "K" is ignored. Other 10 ; flags result in FILE^DIE being called. 11 ; * Can't edit ^HLMA(IEN,90) data. 12 ; * Can't edit ^HLMA(IEN,91) data. 13 ; * Can't edit ^HL(772,IEN,"IN") data (field #200, MESSAGE TEXT) 14 ; * No checking of data performed! (Data format MUST be OK.) 15 ; * No locking of records in files 772 or 773. (Locks on queues.) 16 ; 17 FILE(FLAGS,ROOT,ERR,SUB,RTN) ; FILE^DIE functional equivalent... 18 ; This call has similar parameters to FILE^DIE, but changes data 19 ; using hard sets. The first two parameters of this API are the 20 ; same as FILE^DIE. So, if any file other than 772 or 773 is being 21 ; edited, this API just passes on the FLAGS,ROOT,ERR parameters to 22 ; FILE^DIE and quits. If file 772 or 773 is being edited, the hard 23 ; set code in HLDIE772 and HLDIE773 is called. 24 ; 25 N DEBUG,FILE,HLEDITOR,LERR,IEN,X,XECMCODE 26 ; 27 S DT=$$NOW^XLFDT\1 28 ; 29 D BEGIN ; Debug call at beginning or process 30 ; 31 ; Check FILE, IEN, FIELDs passed, etc... 32 I '$$CHECKS D QUIT ;-> 33 . 34 . S HLEDITOR="FILE^DIE" 35 . 36 . ; Call FILEMAN... 37 . D FILE^DIE($G(FLAGS),$G(ROOT),$G(ERR)) 38 . 39 . ; Debug call made even with Fileman... 40 . D END 41 ; 42 S HLEDITOR="FILE^HLDIE" 43 ; 44 ; If this point is reached, file 772 or 773 is being edited, data 45 ; in ROOT() has been checked, and data is being hard set... 46 ; 47 ; 48 ; Make sure ERR is defined... 49 I $G(ERR)']"" N HLERR S ERR="HLERR" 50 ; 51 ; All editing occurs in this call... 52 D EDITALL(.ROOT,FILE,IEN) 53 ; 54 ; Store debug data if XTMP debug string set... 55 D END 56 ; 57 ;check if ROOT needs to be retained 58 I FLAGS'["S" K @ROOT,FLAGS 59 ; 60 Q 61 ; 62 EDITALL(ROOT,FILE,IEN) ; Edit 772 or 773 by direct sets... 63 ; 64 ; FILE,IEN -- optional (parsed from ROOT()) 65 ; 66 N ERRNO,FIELD,GBL,NODE,ROUTINE,TAG,VALUE,XRF 67 ; 68 S GBL=$$GBL(FILE,+IEN) 69 ; 70 ;check if .01="@" for deletion of record... 71 I $G(@ROOT@(FILE,IEN,.01))="@" D Q 72 .I FILE=773 D DEL773^HLUOPT3(+IEN) Q 73 .I FILE=772 D DEL772^HLUOPT3(+IEN) 74 ; 75 ; If no data in record passed in, log an error and quit... 76 I '$D(@GBL) D Q ; Remember. GBL contains IEN... 77 . S ERRNO=$$ERRNO(601,"The entry does not exist.",FILE,2) 78 . S @ERR@("DIERR",+ERRNO,"PARAM","IENS")=IEN_$S(IEN'[",":",",1:"") 79 ; 80 ; 81 ; What routine holds the file-specific field/xref set code? 82 S ROUTINE=$S(FILE=772:"HLDIE772",FILE=773:"HLDIE773",1:"") 83 ; 84 ; Load NODEs... 85 D GETNODES(FILE,+IEN,.NODE) 86 ; 87 ; When a field is edited, the NODE(1) is changed 88 ; 89 ; Edit NODE(1), adding new values, and set XRF(XREF) nodes... 90 S FIELD=0 91 F S FIELD=$O(@ROOT@(FILE,IEN,FIELD)) Q:FIELD'>0 D 92 . ; VALUE = value passed in by process that is to be stored in file 93 . S VALUE=$G(@ROOT@(FILE,IEN,FIELD)) 94 . 95 . ; If field should be deleted, VALUE will equal @... 96 . I VALUE="@" S VALUE="" 97 . 98 . ; Get and check tag... 99 . S TAG="F"_(FILE-770)_$TR(FIELD,".","")_U_ROUTINE 100 . S TAG(1)=$T(@TAG) I TAG(1)']"" D QUIT ;-> 101 . . S ERRNO=$$ERRNO(501,"No set logic for file #"_FILE_"'s field# "_FIELD,FILE,3) 102 . . S @ERR@("DIERR",+ERRNO,"PARAM",1)=FIELD 103 . . S @ERR@("DIERR",+ERRNO,"PARAM","FIELD")=FIELD 104 . 105 . ; Call the subroutine below that is for the specific field... 106 . ; (No editing of xrefs or global data occurs in these calls.) 107 . D @("F"_(FILE-770)_$TR(FIELD,".","")_U_ROUTINE) 108 ; 109 ; If no data actually changed, quit... 110 QUIT:'$D(NODE("CHG")) ;-> 111 ; 112 ; Store changes in the global now... 113 D STORE(FILE,IEN,.NODE) 114 ; 115 ; Set xrefs to correspond to the just-stored data... 116 S XRF="" 117 F S XRF=$O(XRF(XRF)) Q:XRF']"" D 118 . D @("XRF"_XRF_U_ROUTINE) 119 ; 120 Q 121 ; 122 GETNODES(FILE,IEN,NODE) ; Load pre-change data for each node in 123 ; NODE(node,0), and load node to be changed in NODE(node,1). 124 ; GBL -- req 125 F NODE=0,1,2,"P","S" D 126 . ; After setting, NODE(NODE,0) will equal each other. 127 . ; However, after each edited field is processed, the pieces of 128 . ; data in NODE(NODE,1) will be changed. The pre and post nodes 129 . ; then are of comparison value. 130 . S NODE(NODE,0)=$G(@GBL@(NODE)) ; Pre-change node 131 . S NODE(NODE,1)=NODE(NODE,0) ; Node that is changed 132 Q 133 ; 134 STORE(FILE,IEN,NODE) ; Store changes in file... 135 N DATA,ND 136 ; 137 ; Loop thru change nodes, get changed data, and store it... 138 S ND="" 139 F S ND=$O(NODE("CHG",ND)) Q:ND']"" D 140 . S DATA=$G(NODE(ND,1)) 141 . ; Even if no data no node, store it. (Will be removed by purge.) 142 . I FILE=772 S ^HL(772,+IEN,ND)=DATA 143 . I FILE=773 S ^HLMA(+IEN,ND)=DATA 144 ; 145 QUIT 146 ; 147 GBL(FILE,IEN) QUIT $S(FILE=772:"^HL(772,"_+IEN_")",1:"^HLMA("_+IEN_")") 148 ; 149 CHKFLD(FILE,FIELD) ; Does passed-in field exist? 150 ; Returns -- @ERR@(...) -> 151 ; 152 ; Quit if field exists... 153 QUIT:$D(^DD(+FILE,+FIELD)) 1 ;-> 154 ; 155 ; Field doesn't exist. Log error... 156 S ERRNO=$$ERRNO(501,"File #"_FILE_" does not contain a field "_FIELD_".",FILE,3) 157 S @ERR@("DIERR",+ERRNO,"PARAM",1)=FIELD 158 S @ERR@("DIERR",+ERRNO,"PARAM","FIELD")=FIELD 159 ; 160 Q "" 161 ; 162 ERRNO(NUM,TXT,FILE,PNO) ; Return next ERROR number and create general data... 163 N NO 164 S NO=$G(@ERR@("DIERR"))+1,@ERR@("DIERR")=+NO_U_+NO 165 S @ERR@("DIERR",NO)=NUM 166 S @ERR@("DIERR",NO,"PARAM",0)=PNO 167 S @ERR@("DIERR",NO,"PARAM","FILE")=FILE 168 S @ERR@("DIERR",NO,"TEXT",1)=TXT 169 S @ERR@("DIERR","E",NUM,NO)="" 170 Q NO 171 ; 172 GENLERR(ETXT) ; Store GENERAL (and fatal) error... 173 ; ERR -- req 174 N NO 175 S NO=$G(@ERR@("DIERR"))+1,@ERR@("DIERR")=+NO_U_+NO 176 S @ERR@("DIERR",NO)=999_U_ETXT ; Made up error number 177 Q 178 ; 179 CHECKS() ; Check ROOT() for file and validity of data... 180 ; FLAGS, ROOT() -- req --> FILE,IEN 181 N I,OK,FIELD 182 ; 183 ;check the file & ien 184 S FILE=$O(@ROOT@(0)) 185 I FILE'=772,FILE'=773 D QUIT "" ;-> 186 . S IEN=$S(FILE:$O(@ROOT@(FILE,0)),1:0) ; Set for debugging 187 ; 188 ; ;shouldn't be more than 1 file! 189 QUIT:$O(@ROOT@(FILE)) "" ;-> 190 ; 191 ;check the ien structure, and that only ien passed... 192 S IEN=$O(@ROOT@(FILE,0)) 193 ; Structure check... 194 QUIT:$P(IEN,",")'=+IEN_"," "" ;-> 195 ; Is it numeric? 196 QUIT:'(+IEN) "" ;-> 197 ; Has more than one IEN been passed? 198 QUIT:($O(@ROOT@(FILE,IEN))'="") "" ;-> 199 ; 200 ;check the flags. Only K and S flags allowed... 201 I $L(FLAGS) D QUIT:'OK "" ;-> 202 . S OK=1 203 . F I=0:1:$L(FLAGS) I $E(FLAGS,I)'="K",$E(FLAGS,I)'="S" S OK=0 204 ; 205 ; Check for existence of FIELD in FILE's DD & if an excluded field. 206 ; (See rules for fields which cannot be updated by FILE^HLDIE.) 207 S FIELD=0,OK=1 208 F S FIELD=$O(@ROOT@(FILE,IEN,FIELD)) Q:FIELD="" D Q:'OK 209 . I '$$CHKFLD(FILE,FIELD) S OK=0 Q 210 . I FILE=773,FIELD\1=90 S OK=0 Q 211 . I FILE=773,FIELD\1=91 S OK=0 Q 212 . I FILE=772,FIELD=200 S OK=0 Q 213 ; 214 ; If not OK to use FILE^HLDIE, skip any further testing... 215 QUIT:'OK "" ;-> 216 ; 217 ; *** WARNING *** 218 ; The following check **MUST** be removed after FILE^HLDIE is working. 219 ; 220 ; Final check for whether FILE^HLDIE should be used... 221 I $G(^XTMP("HLDIE-DEBUG","CALL"))]"" QUIT "" ;-> 222 ; If this node exists and follows null, FILE^DIE will be used. 223 ; Otherwise, execution defaults to using FILE^HLDIE. 224 ; 225 Q OK 226 ; 227 BEGIN ; Always call here before any ^HLDIE or ^DIE calls... 228 D DEBUG(1) 229 Q 230 ; 231 END ; Always call here after all ^HLDIE or ^DIE actions... 232 D DEBUG(2) 233 Q 234 ; 235 DEBUG(LOC) ; Debug presets and setup... 236 ; Most variables created here should be left around. These variables 237 ; are newed above. 238 N STORE 239 ; 240 S RTN=$G(RTN),SUB=$G(SUB) 241 ; 242 ; First-time (beginning) call setups... 243 I LOC=1 D 244 . S RTN=$S(RTN]"":RTN,1:"HLDIE")_"~"_$S(RTN="HLDIE":"FILE",1:SUB) 245 . S DEBUG=$G(^XTMP("HLDIE-DEBUG","STATUS")) 246 . S XECMCODE=$P(DEBUG,U,3) 247 ; DEBUG is always called at beginning (LOC=1) and end (LOC=2) or 248 ; FILE^HLDIE. So, set up variables only once, at beginning... 249 ; 250 ; Setup that is individual to each (1 or 2) call... 251 S STORE=$P(DEBUG,U,LOC),STORE=$S(STORE=1:1,STORE=2:2,1:"") 252 ; Some, All, or no data stored? 253 ; 254 ; If no STORE instructions, and no M code to specify STORE, quit... 255 QUIT:'STORE&($G(XECMCODE)'=1) ;-> 256 ; 257 ; Call DEBUG to STORE data... 258 D DEBUG^HLDIEDBG(RTN,LOC,STORE,XECMCODE) 259 ; 260 Q 261 ; 262 EOR ;HLDIE - Direct 772 & 773 Sets ; 11/18/2003 11:17 -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLFNC.m
r613 r623 1 HLFNC ;AISC/SAW/OAK-OIFO/RBN-Routine of Functions and Other Calls Used for HL7 Messages ;03/26/2008 11:34 2 ;;1.6;HEALTH LEVEL SEVEN;**38,42,51,66,141**;Oct 13, 1995;Build 11 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 HLNAME(X,HLECDE) ;Convert a name in DHCP format to HL7 format 6 ; INPUT: X - Name in DHCP format 7 ; Optional - HLECDE - HL7 encoding chars 8 ;**** NOTE: **** 9 ;If this function is called without HLECDE as parameter than HLECH 10 ;must be define. 11 ; 12 Q:'$D(X) "" Q:X="" "" 13 I '$D(HLECH),'$D(HLECDE) Q "" 14 I $D(HLECDE) N HLECH S HLECH=HLECDE 15 I '$D(HLECH) Q "" 16 N %,X1,X2,Y 17 S X1=$P(X,",",2),X2=$L(X1," "),Y=$P(X,",")_$E(HLECH)_$P(X1," ") I X2 F %=2:1:X2 Q:$P(X1," ",%)']"" S Y=Y_$E(HLECH)_$P(X1," ",%) 18 Q Y 19 ; 20 FMNAME(X,HLECDE) ;Convert a name in HL7 format to DHCP format 21 ; INPUT: X - Name in HL7 format 22 ; Optional - HLECDE - HL7 encoding chars 23 ;**** NOTE: **** 24 ;If this function is called without HLECDE as parameter than HLECH 25 ;must be define. 26 ; 27 Q:'$D(X) "" Q:X="" "" 28 I '$D(HLECH),'$D(HLECDE) Q "" 29 I $D(HLECDE) N HLECH S HLECH=HLECDE 30 I '$D(HLECH) Q "" 31 N %,X1 S X1=$L(X,$E(HLECH)),Y="" F %=1:1:X1 D 32 .I $P(X,$E(HLECH),%)]"",$P(X,$E(HLECH),%)'="""""" D 33 ..;Only last name,first name. 34 ..I %<3 S Y=Y_$P(X,$E(HLECH),%)_$S(%=1:",",1:"") Q 35 ..S Y=Y_" "_$P(X,$E(HLECH),%) 36 Q Y 37 ; 38 HLDATE(X,Y) ;Convert date, date/time or time only in FM format to HL7 format 39 ;Optional Variables: 40 ;Y = The type of format to be returned if you want to force return of a 41 ; specific format. Y must be equal to one of the following: 42 ; DT - Date only 43 ; TM - Time only 44 ; TS - Date and time 45 I X="" Q "" 46 S Y=$G(Y) 47 N %,Z 48 I $L(X)<7 D Q % ;Time input 49 . S %=$S(X=2400:"0000",$L(X)<4:$E(X_"000",1,4),1:X) S:$L(%)=5 %=%_0 50 . Q 51 I Y="TM" D Q % ;Only time 52 . S %=$P(X,".",2),%=$S(%="":"",$E(%,1,2)=24:"0000",$L(%)<4:$E(%_"000",1,4),1:%) S:$L(%)=5 %=%_0 53 . Q 54 S %=$$FMTHL7^XLFDT(X) 55 Q $S(Y="DT":$E(%,1,8),1:%) 56 ; 57 FMDATE(X) ; Convert a date, date/time or time only in HL7 format to FM format 58 I X="" Q "" 59 N % 60 S %=$P($TR(X,"+-","^"),"^") 61 I $L(X)<7 Q % 62 Q $$HL7TFM^XLFDT(X) 63 ; 64 M10(X,HLECDE) ; M10 check digit scheme 65 ; INPUT : X - ID number 66 ; Optional HLECDE - Encoding chars 67 ;**** NOTE: **** 68 ;If this function is called without HLECDE as parameter then HLECH 69 ;must be defined. 70 ;Return X if encoding character is not defined 71 ;Return X with encoding characters concatenated if X is alphanumeric 72 ; 73 N HLCNT,HLODD,HLEVEN,HLX1,HLDIGIT 74 Q:'$D(X) "" 75 I $D(HLECDE) N HLECH S HLECH=HLECDE 76 ;Return X if encoding character is not defined 77 I '$D(HLECH) Q X 78 ;Return X with encoding characters concatenated if X is alphanumeric 79 I '(X?1.N) Q X_$E(HLECH)_$E(HLECH) 80 ; 81 S HLX1=+X 82 S HLODD="" 83 F HLCNT=$L(HLX1):-2:1 S HLODD=HLODD_$E(HLX1,HLCNT) 84 S HLODD=HLODD*2 85 S HLEVEN="" 86 F HLCNT=($L(HLX1)-1):-2:1 S HLEVEN=HLEVEN_$E(HLX1,HLCNT) 87 S HLX1=HLEVEN_HLODD 88 S HLDIGIT=0 89 F HLCNT=1:1:$L(HLX1) S HLDIGIT=HLDIGIT+$E(HLX1,HLCNT) 90 S HLDIGIT=((HLDIGIT\10+1)*10-HLDIGIT)#10 91 Q X_$E(HLECH)_HLDIGIT_$E(HLECH)_"M10" 92 ; 93 M11(X,HLECDE) ; M11 check digit scheme 94 ; INPUT : X - ID number 95 ; Optional HLECDE - Encoding chars 96 ;**** NOTE: **** 97 ;If this function is called without HLECDE as parameter then HLECH 98 ;must be defined. 99 ;Return X if encoding character is not defined 100 ;Return X with encoding characters concatenated if X is alphanumeric 101 ; 102 N HLX1,HLCNT,HLWT,HLDIGIT 103 Q:'$D(X) "" 104 I $D(HLECDE) N HLECH S HLECH=HLECDE 105 ;Return X if encoding character is not defined 106 I '$D(HLECH) Q X 107 ;Return X with encoding characters concatenated if X is alphanumeric 108 I '(X?1N.N) Q X_$E(HLECH)_$E(HLECH) 109 ; 110 S HLX1=+X 111 S HLDIGIT=0,HLWT=2 112 F HLCNT=$L(HLX1):-1:1 D 113 . I HLWT>7 S HLWT=2 114 . S HLDIGIT=HLDIGIT+($E(HLX1,HLCNT)*HLWT) 115 . S HLWT=HLWT+1 116 S HLDIGIT=HLDIGIT#11 117 I HLDIGIT=0 S HLDIGIT=1 118 S HLDIGIT=(11-HLDIGIT)#10 119 Q X_$E(HLECH)_HLDIGIT_$E(HLECH)_"M11" 120 ; 121 OLDM10(X,HLECDE) ;Calculate M10 checksum 122 ; INPUT : X - String to calc checksum 123 ; Optional HLECDE - Encoding chars 124 ;**** NOTE: **** 125 ;If this function is called without HLECDE as parameter than HLECH 126 ;must be define. 127 ; 128 Q:'$D(X) "" 129 I '$D(HLECH),'$D(HLECDE) Q "" 130 I $D(HLECDE) N HLECH S HLECH=HLECDE 131 I '$D(HLECH) Q "" 132 N %,Y 133 S Y=0 F %=1:1:$L(X) S Y=Y+$E(X,%) 134 Q X_$E(HLECH)_(Y#10)_$E(HLECH)_"M10" 135 ; 136 OLDM11(X,HLECDE) ;Calculate M11 checksum 137 ; INPUT : X - String to calc checksum 138 ; Optional HLECDE - Encoding chars 139 ;**** NOTE: **** 140 ;If this function is called without HLECDE as parameter than HLECH 141 ;must be define. 142 ; 143 Q:'$D(X) "" 144 I '$D(HLECH),'$D(HLECDE) Q "" 145 I $D(HLECDE) N HLECH S HLECH=HLECDE 146 I '$D(HLECH) Q "" 147 N %,Y S Y=0 F %=1:1:$L(X) S Y=Y+$E(X,%) 148 Q X_$E(HLECH)_(Y#11)_$E(HLECH)_"M11" 149 UPPER(X) ;Convert lowercase letters to uppercase 150 Q:'$D(X) "" 151 Q $TR(X,"abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ") 152 HLPHONE(X,B,C) ;Convert DHCP Phone Number to HL7 Format 153 ;Required parameters: 154 ;X = Seven digit phone number at a minimum. Optionally, in addition, 155 ; a three digit area code, two digit country code and other 156 ; formatting characters (e.g., dashes) 157 ;Optional Variables: 158 ;B = Beeper number 159 ;C = Comments 160 Q:'$D(X) "" Q:$L(X)<7 "" 161 N I,Y,Y1,Z S B=$S('$D(B):"",1:"B"_B),C=$S('$D(C):"",1:"C"_C) 162 ; 163 ; patch HL*1.6*141 start 164 ; S Y="" F I=1:1:$L(X) S Y=Y_$S($E(X,I)?1N:$E(X,I),"X,x"[$E(X,I)&('$D(Z)):"X",1:"") I "X,x"[$E(X,I) S Z="" 165 N CH 166 S Y="" 167 F I=1:1:$L(X) D 168 . S CH=$E(X,I) 169 . ; Next line modified by RBN 170 . ;S Y=Y_$S(CH?1N:CH,"Xx"[CH&('$D(Z)):"X",1:"") 171 . S Y=Y_$S(CH?1N:CH,"Xx,*"[CH&('$D(Z)):"X",1:"") 172 . I "Xx"[CH S Z="" 173 ; 174 ; the number, following "X" character, should be greater than 0 175 I Y["X",+$P(Y,"X",2)<1 S Y=$P(Y,"X") 176 ; patch HL*1.6*141 end 177 ; 178 I $L(Y)<7 Q "" 179 S Y1=$S(Y["X":"X"_$P(Y,"X",2),1:""),Y=$P(Y,"X") I $L(Y)<7 Q "" 180 I $L(Y)=8,189[$E(Y) S Y=$E(Y,2,8) 181 I $L(Y)=11,189[$E(Y) S Y=$E(Y,2,11) 182 I $L(Y)=7 Q $E($E(Y,1,3)_"-"_$E(Y,4,7)_Y1_B_C,1,40) 183 I $L(Y)=10 Q $E("("_$E(Y,1,3)_")"_$E(Y,4,6)_"-"_$E(Y,7,10)_Y1_B_C,1,40) 184 I $L(Y)=12 Q $E($E(Y,1,2)_" ("_$E(Y,3,5)_")"_$E(Y,6,8)_"-"_$E(Y,9,12)_Y1_B_C,1,40) 185 Q "" 186 HLADDR(AD,GL,HLECDE) ;Convert DHCP address fields to HL7 address format 187 ;Required parameters: 188 ;AD = One to four street address lines separated by uparrows (^). 189 ;GL = Three to four geographic location components separated by 190 ; uparrows (^). City^State or Province^Zip Code^Country Code. 191 ; If the fourth component is not defined, it will be set to 'USA'. 192 ; The second component must be null or an IEN in the 193 ; State file (#5). The third component must be null or pattern 194 ; match 5N, 9N or 5N1"-"4N. 195 ; 196 ; Optional HLECDE - Encoding chars 197 ;**** NOTE: **** 198 ;If this function is called without HLECDE as parameter than HLECH 199 ;must be define. 200 ; 201 ; 202 ;A string will be returned with six components separated by the HL7 203 ;component separator. The length of the string (including separators) 204 ;may exceed 106 characters. 205 ; 206 Q:'$D(AD) "" Q:'$D(GL) "" 207 I '$D(HLECH),'$D(HLECDE) Q "" 208 I $D(HLECDE) N HLECH S HLECH=HLECDE 209 I '$D(HLECH) Q "" 210 I $D(XRTL) D T0^%ZOSV 211 N I,X,Y 212 I $P(GL,"^",4)="" S $P(GL,"^",4)="USA" 213 I $P(GL,"^",4)="USA" S X=$P(GL,"^",3) S:X?9N X=$E(X,1,5)_"-"_$E(X,6,9) S $P(GL,"^",3)=$S(X?5N!(X?5N1"-"4N):X,1:"") 214 S X=+$P(GL,"^",2) S $P(GL,"^",2)=$S('X:"",$P($G(^DIC(5,X,0)),"^",2)]"":$E($P(^(0),"^",2),1,2),1:"") 215 S Y=$E(HLECH)_$P(GL,"^")_$E(HLECH)_$P(GL,"^",2)_$E(HLECH)_$P(GL,"^",3)_$E(HLECH)_$P(GL,"^",4) 216 S X=$P(AD,"^",1,4) F I=1,2 I X["^^" S X=$P(X,"^^")_"^"_$P(X,"^^",2,3) 217 I $E(X,$L(X))="^" S X=$E(X,1,($L(X)-1)) 218 I $D(XRT0) S XRTN="HLFNC" D T1^%ZOSV 219 I $L(X,"^")=1 Q $P(X,"^")_$E(HLECH)_Y 220 I $L(X,"^")=2 Q $P(X,"^")_$E(HLECH)_$P(X,"^",2)_Y 221 I $L(X,"^")=3 Q $P(X,"^")_", "_$P(X,"^",2)_$E(HLECH)_$P(X,"^",3)_Y 222 I $L(X,"^")=4 Q $P(X,"^")_", "_$P(X,"^",2)_$E(HLECH)_$P(X,"^",3)_", "_$P(X,"^",4)_Y 1 HLFNC ;AISC/SAW-Routine of Functions and Other Calls Used for HL7 Messages ;08/03/2000 15:45 2 ;;1.6;HEALTH LEVEL SEVEN;**38,42,51,66**;Oct 13, 1995 3 HLNAME(X,HLECDE) ;Convert a name in DHCP format to HL7 format 4 ; INPUT: X - Name in DHCP format 5 ; Optional - HLECDE - HL7 encoding chars 6 ;**** NOTE: **** 7 ;If this function is called without HLECDE as parameter than HLECH 8 ;must be define. 9 ; 10 Q:'$D(X) "" Q:X="" "" 11 I '$D(HLECH),'$D(HLECDE) Q "" 12 I $D(HLECDE) N HLECH S HLECH=HLECDE 13 I '$D(HLECH) Q "" 14 N %,X1,X2,Y 15 S X1=$P(X,",",2),X2=$L(X1," "),Y=$P(X,",")_$E(HLECH)_$P(X1," ") I X2 F %=2:1:X2 Q:$P(X1," ",%)']"" S Y=Y_$E(HLECH)_$P(X1," ",%) 16 Q Y 17 ; 18 FMNAME(X,HLECDE) ;Convert a name in HL7 format to DHCP format 19 ; INPUT: X - Name in HL7 format 20 ; Optional - HLECDE - HL7 encoding chars 21 ;**** NOTE: **** 22 ;If this function is called without HLECDE as parameter than HLECH 23 ;must be define. 24 ; 25 Q:'$D(X) "" Q:X="" "" 26 I '$D(HLECH),'$D(HLECDE) Q "" 27 I $D(HLECDE) N HLECH S HLECH=HLECDE 28 I '$D(HLECH) Q "" 29 N %,X1 S X1=$L(X,$E(HLECH)),Y="" F %=1:1:X1 D 30 .I $P(X,$E(HLECH),%)]"",$P(X,$E(HLECH),%)'="""""" D 31 ..;Only last name,first name. 32 ..I %<3 S Y=Y_$P(X,$E(HLECH),%)_$S(%=1:",",1:"") Q 33 ..S Y=Y_" "_$P(X,$E(HLECH),%) 34 Q Y 35 ; 36 HLDATE(X,Y) ;Convert date, date/time or time only in FM format to HL7 format 37 ;Optional Variables: 38 ;Y = The type of format to be returned if you want to force return of a 39 ; specific format. Y must be equal to one of the following: 40 ; DT - Date only 41 ; TM - Time only 42 ; TS - Date and time 43 I X="" Q "" 44 S Y=$G(Y) 45 N %,Z 46 I $L(X)<7 D Q % ;Time input 47 . S %=$S(X=2400:"0000",$L(X)<4:$E(X_"000",1,4),1:X) S:$L(%)=5 %=%_0 48 . Q 49 I Y="TM" D Q % ;Only time 50 . S %=$P(X,".",2),%=$S(%="":"",$E(%,1,2)=24:"0000",$L(%)<4:$E(%_"000",1,4),1:%) S:$L(%)=5 %=%_0 51 . Q 52 S %=$$FMTHL7^XLFDT(X) 53 Q $S(Y="DT":$E(%,1,8),1:%) 54 ; 55 FMDATE(X) ;Convert a date, date/time or time only in HL7 format to FM format 56 I X="" Q "" 57 N % 58 S %=$P($TR(X,"+-","^"),"^") 59 I $L(X)<7 Q % 60 Q $$HL7TFM^XLFDT(X) 61 ; 62 M10(X,HLECDE) ; M10 check digit scheme 63 ; INPUT : X - ID number 64 ; Optional HLECDE - Encoding chars 65 ;**** NOTE: **** 66 ;If this function is called without HLECDE as parameter then HLECH 67 ;must be defined. 68 ;Return X if encoding character is not defined 69 ;Return X with encoding characters concatenated if X is alphanumeric 70 ; 71 N HLCNT,HLODD,HLEVEN,HLX1,HLDIGIT 72 Q:'$D(X) "" 73 I $D(HLECDE) N HLECH S HLECH=HLECDE 74 ;Return X if encoding character is not defined 75 I '$D(HLECH) Q X 76 ;Return X with encoding characters concatenated if X is alphanumeric 77 I '(X?1.N) Q X_$E(HLECH)_$E(HLECH) 78 ; 79 S HLX1=+X 80 S HLODD="" 81 F HLCNT=$L(HLX1):-2:1 S HLODD=HLODD_$E(HLX1,HLCNT) 82 S HLODD=HLODD*2 83 S HLEVEN="" 84 F HLCNT=($L(HLX1)-1):-2:1 S HLEVEN=HLEVEN_$E(HLX1,HLCNT) 85 S HLX1=HLEVEN_HLODD 86 S HLDIGIT=0 87 F HLCNT=1:1:$L(HLX1) S HLDIGIT=HLDIGIT+$E(HLX1,HLCNT) 88 S HLDIGIT=((HLDIGIT\10+1)*10-HLDIGIT)#10 89 Q X_$E(HLECH)_HLDIGIT_$E(HLECH)_"M10" 90 ; 91 M11(X,HLECDE) ; M11 check digit scheme 92 ; INPUT : X - ID number 93 ; Optional HLECDE - Encoding chars 94 ;**** NOTE: **** 95 ;If this function is called without HLECDE as parameter then HLECH 96 ;must be defined. 97 ;Return X if encoding character is not defined 98 ;Return X with encoding characters concatenated if X is alphanumeric 99 ; 100 N HLX1,HLCNT,HLWT,HLDIGIT 101 Q:'$D(X) "" 102 I $D(HLECDE) N HLECH S HLECH=HLECDE 103 ;Return X if encoding character is not defined 104 I '$D(HLECH) Q X 105 ;Return X with encoding characters concatenated if X is alphanumeric 106 I '(X?1N.N) Q X_$E(HLECH)_$E(HLECH) 107 ; 108 S HLX1=+X 109 S HLDIGIT=0,HLWT=2 110 F HLCNT=$L(HLX1):-1:1 D 111 . I HLWT>7 S HLWT=2 112 . S HLDIGIT=HLDIGIT+($E(HLX1,HLCNT)*HLWT) 113 . S HLWT=HLWT+1 114 S HLDIGIT=HLDIGIT#11 115 I HLDIGIT=0 S HLDIGIT=1 116 S HLDIGIT=(11-HLDIGIT)#10 117 Q X_$E(HLECH)_HLDIGIT_$E(HLECH)_"M11" 118 ; 119 OLDM10(X,HLECDE) ;Calculate M10 checksum 120 ; INPUT : X - String to calc checksum 121 ; Optional HLECDE - Encoding chars 122 ;**** NOTE: **** 123 ;If this function is called without HLECDE as parameter than HLECH 124 ;must be define. 125 ; 126 Q:'$D(X) "" 127 I '$D(HLECH),'$D(HLECDE) Q "" 128 I $D(HLECDE) N HLECH S HLECH=HLECDE 129 I '$D(HLECH) Q "" 130 N %,Y 131 S Y=0 F %=1:1:$L(X) S Y=Y+$E(X,%) 132 Q X_$E(HLECH)_(Y#10)_$E(HLECH)_"M10" 133 ; 134 OLDM11(X,HLECDE) ;Calculate M11 checksum 135 ; INPUT : X - String to calc checksum 136 ; Optional HLECDE - Encoding chars 137 ;**** NOTE: **** 138 ;If this function is called without HLECDE as parameter than HLECH 139 ;must be define. 140 ; 141 Q:'$D(X) "" 142 I '$D(HLECH),'$D(HLECDE) Q "" 143 I $D(HLECDE) N HLECH S HLECH=HLECDE 144 I '$D(HLECH) Q "" 145 N %,Y S Y=0 F %=1:1:$L(X) S Y=Y+$E(X,%) 146 Q X_$E(HLECH)_(Y#11)_$E(HLECH)_"M11" 147 UPPER(X) ;Convert lowercase letters to uppercase 148 Q:'$D(X) "" 149 Q $TR(X,"abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ") 150 HLPHONE(X,B,C) ;Convert DHCP Phone Number to HL7 Format 151 ;Required parameters: 152 ;X = Seven digit phone number at a minimum. Optionally, in addition, 153 ; a three digit area code, two digit country code and other 154 ; formatting characters (e.g., dashes) 155 ;Optional Variables: 156 ;B = Beeper number 157 ;C = Comments 158 Q:'$D(X) "" Q:$L(X)<7 "" 159 N I,Y,Y1,Z S B=$S('$D(B):"",1:"B"_B),C=$S('$D(C):"",1:"C"_C) 160 S Y="" F I=1:1:$L(X) S Y=Y_$S($E(X,I)?1N:$E(X,I),"X,x"[$E(X,I)&('$D(Z)):"X",1:"") I "X,x"[$E(X,I) S Z="" 161 I $L(Y)<7 Q "" 162 S Y1=$S(Y["X":"X"_$P(Y,"X",2),1:""),Y=$P(Y,"X") I $L(Y)<7 Q "" 163 I $L(Y)=8,189[$E(Y) S Y=$E(Y,2,8) 164 I $L(Y)=11,189[$E(Y) S Y=$E(Y,2,11) 165 I $L(Y)=7 Q $E($E(Y,1,3)_"-"_$E(Y,4,7)_Y1_B_C,1,40) 166 I $L(Y)=10 Q $E("("_$E(Y,1,3)_")"_$E(Y,4,6)_"-"_$E(Y,7,10)_Y1_B_C,1,40) 167 I $L(Y)=12 Q $E($E(Y,1,2)_" ("_$E(Y,3,5)_")"_$E(Y,6,8)_"-"_$E(Y,9,12)_Y1_B_C,1,40) 168 Q "" 169 HLADDR(AD,GL,HLECDE) ;Convert DHCP address fields to HL7 address format 170 ;Required parameters: 171 ;AD = One to four street address lines separated by uparrows (^). 172 ;GL = Three to four geographic location components separated by 173 ; uparrows (^). City^State or Province^Zip Code^Country Code. 174 ; If the fourth component is not defined, it will be set to 'USA'. 175 ; The second component must be null or an IEN in the 176 ; State file (#5). The third component must be null or pattern 177 ; match 5N, 9N or 5N1"-"4N. 178 ; 179 ; Optional HLECDE - Encoding chars 180 ;**** NOTE: **** 181 ;If this function is called without HLECDE as parameter than HLECH 182 ;must be define. 183 ; 184 ; 185 ;A string will be returned with six components separated by the HL7 186 ;component separator. The length of the string (including separators) 187 ;may exceed 106 characters. 188 ; 189 Q:'$D(AD) "" Q:'$D(GL) "" 190 I '$D(HLECH),'$D(HLECDE) Q "" 191 I $D(HLECDE) N HLECH S HLECH=HLECDE 192 I '$D(HLECH) Q "" 193 I $D(XRTL) D T0^%ZOSV 194 N I,X,Y 195 I $P(GL,"^",4)="" S $P(GL,"^",4)="USA" 196 I $P(GL,"^",4)="USA" S X=$P(GL,"^",3) S:X?9N X=$E(X,1,5)_"-"_$E(X,6,9) S $P(GL,"^",3)=$S(X?5N!(X?5N1"-"4N):X,1:"") 197 S X=+$P(GL,"^",2) S $P(GL,"^",2)=$S('X:"",$P($G(^DIC(5,X,0)),"^",2)]"":$E($P(^(0),"^",2),1,2),1:"") 198 S Y=$E(HLECH)_$P(GL,"^")_$E(HLECH)_$P(GL,"^",2)_$E(HLECH)_$P(GL,"^",3)_$E(HLECH)_$P(GL,"^",4) 199 S X=$P(AD,"^",1,4) F I=1,2 I X["^^" S X=$P(X,"^^")_"^"_$P(X,"^^",2,3) 200 I $E(X,$L(X))="^" S X=$E(X,1,($L(X)-1)) 201 I $D(XRT0) S XRTN="HLFNC" D T1^%ZOSV 202 I $L(X,"^")=1 Q $P(X,"^")_$E(HLECH)_Y 203 I $L(X,"^")=2 Q $P(X,"^")_$E(HLECH)_$P(X,"^",2)_Y 204 I $L(X,"^")=3 Q $P(X,"^")_", "_$P(X,"^",2)_$E(HLECH)_$P(X,"^",3)_Y 205 I $L(X,"^")=4 Q $P(X,"^")_", "_$P(X,"^",2)_$E(HLECH)_$P(X,"^",3)_", "_$P(X,"^",4)_Y -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLMA.m
r613 r623 1 HLMA ;AISC/SAW-Message Administration Module ;05/02/2008 10:27 2 ;;1.6;HEALTH LEVEL SEVEN;**19,43,58,63,66,82,91,109,115,133,132,122,140**;Oct 13, 1995;Build 5 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 GENERATE(HLEID,HLARYTYP,HLFORMAT,HLRESLT,HLMTIEN,HLP) ; 5 ;Entry point to generate a deferred message 6 ; 7 ;This is a subroutine call with parameter passing. It returns a 8 ;value in the variable HLRESLT with 1 to 3 pieces separated by uparrows 9 ;as follows: 1st message ID^error code^error description 10 ;If no error occurs, only the first piece is returned equal to a unique 11 ;ID for the 1st message. If message was sent to more than 1 subscriber 12 ;than the other message IDs will be in the array HLRESLT(n)=ID 13 ;Otherwise, three pieces are returned with the 14 ;first piece equal to the message ID, if one was assigned, otherwise 0 15 ; 16 ;Required Input Parameters 17 ; HLEID = Name or IEN of event driver protocol in the Protocol file 18 ; HLARYTYP = Array type. One of the following codes: 19 ; LM = local array containing a single message 20 ; LB = local array containig a batch of messages 21 ; GM = global array containing a single message 22 ; GB = global array containing a batch of messages 23 ; HLFORMAT = Format of array, 1 for pre-formatted in HL7 format, 24 ; otherwise 0 25 ;NOTE: The parameter HLRESLT must be passed by reference 26 ; HLRESLT = The variable that will be returned to the calling 27 ; application as descibed above 28 ;Optional Parameters 29 ; HLMTIEN = IEN of entry in Message Text file where the message 30 ; being generated is to be stored. This parameter is 31 ; only passed for a batch type message 32 ;NOTE: The parameter HLP used for the following parameters must be 33 ; passed by reference 34 ; HLP("SECURITY") = A 1 to 40 character string 35 ; HLP("CONTPTR") = Continuation pointer, a 1 to 180 character string 36 ; HLP("NAMESPACE") = Passed in by application namespace - HL*1.6*91 37 ; HLP("EXCLUDE SUBSCRIBER",<n=1,2,3...>)=<subscriber protocol ien> or 38 ; <subscriber protocol name> - A list of protocols to dynamically 39 ; drop from the event protocol's subscriber multiple. 40 ; 41 ;can't have link open when generating new message 42 N HLTCP,HLTCPO,HLPRIO,HLMIDAR 43 S HLPRIO="D" 44 S HLRESLT="" 45 ;Check for required parameters 46 CONT ; 47 I $G(HLEID)']""!($G(HLARYTYP)']"")!($G(HLFORMAT)']"") D G EXIT 48 . S HLRESLT="0^7^"_$G(^HL(771.7,7,0))_" at GENERATE^HLMA entry point" 49 I 'HLEID S HLEID=$O(^ORD(101,"B",HLEID,0)) I 'HLEID S HLRESLT="0^1^"_$G(^HL(771.7,1,0)) G EXIT 50 N HLRESLT1,HLRESLTA S (HLRESLTA,HLRESLT1)="" 51 I "GL"'[$E(HLARYTYP) S HLRESLT="0^4^"_$G(^HL(771.7,4,0)) G EXIT 52 I $L($G(HLP("SECURITY")))>40 S HLRESLT="0^6^"_$G(^HL(771.7,6,0)) G EXIT 53 I $L($G(HLP("CONTPTR")))>180 S HLRESLT="0^11^"_$G(^HL(771.7,11,0)) G EXIT 54 I $D(HLL("LINKS")) D G:$G(HLRESLT)]"" EXIT 55 . N I,HLPNAM,HLPIEN,HLLNAM,HLLIEN 56 . S I=0 57 . F S I=$O(HLL("LINKS",I)) Q:'I D Q:$G(HLRESLT)]"" 58 . . S HLPNAM=$P(HLL("LINKS",I),U) 59 . . S HLPIEN=+$O(^ORD(101,"B",HLPNAM,0)) 60 . . I $P($G(^ORD(101,HLPIEN,0)),U,4)'="S" S HLRESLT="0^15^Invalid Subscriber Protocol in HLL('LINKS'): "_HLL("LINKS",I) Q 61 . . S HLLNAM=$P(HLL("LINKS",I),U,2) 62 . . S HLLIEN=+$O(^HLCS(870,"B",HLLNAM,0)) 63 . . I '$D(^HLCS(870,HLLIEN,0)) S HLRESLT="0^15^Invalid HL Node in HLL('LINKS'): "_HLL("LINKS",I) Q 64 ;Extract data from Protocol file 65 D EVENT^HLUTIL1(HLEID,"15,20,771",.HLN) 66 S HLENROU=$G(HLN(20)),HLEXROU=$G(HLN(15)) 67 S HLP("GROUTINE")=$G(HLN(771)) K HLN I HLP("GROUTINE")']"",'HLFORMAT S HLRESLT="0^3^"_$G(^HL(771.7,3,0)) G EXIT 68 ;Create message ID and Message Text IEN if Message Text IEN not 69 ;previously created ('$G(HLMTIEN)) 70 I '$G(HLMTIEN) D CREATE^HLTF(.HLMID,.HLMTIEN,.HLDT,.HLDT1) 71 ;Get message ID if Message Text IEN already created 72 I '$G(HLMID) D 73 .S HLDT=$G(^HL(772,HLMTIEN,0)),HLMID=$P(HLDT,"^",6),HLDT=+HLDT 74 .S HLDT1=$$HLDATE^HLFNC(HLDT) 75 S HLMIDAR=0,HLRESLT=HLMID,HLP("DT")=HLDT,HLP("DTM")=HLDT1 76 ;Execute entry action for event driver protocol 77 I HLENROU]"" X HLENROU 78 ;Invoke transaction processor 79 K HLDT,HLDT1,HLENROU 80 D GENERATE^HLTP(HLMID,HLMTIEN,HLEID,HLARYTYP,HLFORMAT,.HLRESLT1,.HLP) 81 ;HLMIDAR is array of message IDs, only set for broadcast messages 82 I HLMIDAR K HLMIDAR("N") M HLRESLT=HLMIDAR 83 S HLRESLT=HLRESLT_"^"_HLRESLT1 84 ; 85 ; patch HL*1.6*122 86 S HLRESLT("HLMID")=$G(HLMIDAR("HLMID")) 87 S HLRESLT("IEN773")=$G(HLMIDAR("IEN773")) 88 ; 89 ;Execute exit action for event driver protocol 90 I HLEXROU]"" X HLEXROU 91 EXIT ;Update status if Message Text file entry has been created 92 K HLTCP 93 I $D(HLMTIEN) D STATUS^HLTF0(HLMTIEN,$S($P(HLRESLT,"^",2):4,1:3),$S($P(HLRESLT,"^",2):$P(HLRESLT,"^",2),1:""),$S($P(HLRESLT,"^",2):$P(HLRESLT,"^",3),1:"")) 94 K HLDT,HLDT1,HLMID,HLRESLT1,HLENROU,HLEXROU 95 Q 96 DIRECT(HLEID,HLARYTYP,HLFORMAT,HLRESLT,HLMTIENO,HLP) ; 97 ;Entry point to generate an immediate message, must be TCP Logical Link 98 ;Input: 99 ; The same as GENERATE,with one additional subscript to the HLP input 100 ; array: 101 ; 102 ; HLP("OPEN TIMEOUT") (optional, pass by reference) a number between 103 ; 1 and 120 that specifies how many seconds the DIRECT CONNECT should 104 ; try to open a connection before failing. It is killed upon 105 ; completion. 106 ; 107 N HLTCP,HLTCPO,HLPRIO,HLSAN,HLN,HLMIDAR,HLMTIENR,ZMID,HLDIRECT 108 ; patch HL*1.6*140- to protect application who call this entry 109 N IO,IOF,ION,IOT,IOST,POP 110 S HLRESLT="" 111 ;HLMTIENO=ien passed in, batch message 112 S HLMTIEN=$G(HLMTIENO) 113 I $G(HLP("OPEN TIMEOUT")),((HLP("OPEN TIMEOUT")\1)'=+HLP("OPEN TIMEOUT"))!HLP("OPEN TIMEOUT")>120 Q "0^4^INVALID OPEN TIMEOUT PARAMETER" 114 I $G(HLP("OPEN TIMEOUT")) D 115 .S HLDIRECT("OPEN TIMEOUT")=HLP("OPEN TIMEOUT") 116 .K HLP("OPEN TIMEOUT") 117 K HL,HLMTIENO 118 D INIT^HLFNC2(HLEID,.HL) 119 I $G(HL) S HLRESLT="0^"_HL Q 120 S HLPRIO="I" D CONT 121 ;HLMTIENO=original msg. ien in file 772, HLMTIENR=response ien set in HLMA2 122 S HLMTIENO=HLMTIEN,HLMTIEN=$G(HLMTIENR) 123 ;Set special HL variables 124 S HLQUIT=0,HLNODE="",HLNEXT="D HLNEXT^HLCSUTL" 125 Q 126 ; 127 CLOSE(LOGLINK) ;close connection that was open in tag DIRECT 128 Q 129 PING ;ping another VAMC to test Link 130 ;set HLQUIET =1 to skip writes 131 ;look for HLTPUT to get turnaround time over network. 132 N DA,DIC,HLDP,HLDPNM,HLDPDM,HLCSOUT,HLDBSIZE,HLDREAD,HLOS,HLTCPADD,HLTCPCS,HLTCPLNK,HLTCPORT,HLTCPRET,HLCSFAIL,HLPARAM 133 N HCS,HCSCMD,HLCS,HCSDAT,HCSER,HCSEXIT,HCSTRACE,HLDT1,HLDRETR,HLRETRA,HLDBACK,HLDWAIT,HLTCPCS,INPUT,OUTPUT,POP,X,Y,HLX1,HLX2 134 S HLQUIET=$G(HLQUIET) 135 S HLCS="",HCSTRACE="C: ",POP=1,INPUT="INPUT",OUTPUT="OUTPUT" 136 S DIC="^HLCS(870,",DIC(0)="QEAMZ" 137 D ^DIC Q:Y<0 138 S HLDP=+Y,HLDPNM=Y(0,0),HLDPDM=$P($$PARAM^HLCS2,U,2) 139 ;I $P($G(^HLCS(870,HLDP,400)),U)="" W !,"Missing IP Address" Q 140 D SETUP^HLCSAC G:HLCS PINGQ 141 ; patch HL*1.6*122 142 G:$$DONTPING^HLMA4 PINGQ 143 ;PING header=MSH^PING^domain^PING^logical link^datetime 144 S INPUT(1)="MSH^PING^"_HLDPDM_"^PING^"_HLDPNM_"^"_$$HTE^XLFDT($H) 145 D OPEN^HLCSAC 146 I HLCS D DNS G:HLCS PINGQ 147 D 148 . N $ETRAP,$ESTACK S $ETRAP="D PINGERR^HLMA" 149 . ;non-standard HL7 header; start block,header,end block 150 . S HLX1=$H 151 . ; 152 . ; HL*1.6*122 start 153 . ; replace flush character '!' with @IOF (! or #) 154 . ; W $C(11)_INPUT(1)_$C(28)_$C(13),! ;HL*1.6*115, restored ! char 155 . ; patch HL*1.6*140, flush character- HLTCPLNK("IOF") 156 . ; W $C(11)_INPUT(1)_$C(28)_$C(13),@IOF 157 . W $C(11)_INPUT(1)_$C(28)_$C(13),@HLTCPLNK("IOF") 158 . ; HL*1.6*122 end 159 . ; 160 . ;read response 161 . R X:HLDREAD 162 . S HLX2=$H 163 . S X=$P(X,$C(28)),HLCS=$S(X=INPUT(1):"PING worked",X="":"No response",1:"Incorrect response") 164 . ;Get roundtrip time 165 . K HLTPUT I X]"" S HLTPUT=$$HDIFF^XLFDT(HLX2,HLX1,2) 166 D CLOSE^%ZISTCP 167 PINGQ ;write back status and quit 168 I 'HLQUIET W !,HLCS,! 169 Q 170 PINGERR ;process errors from PING 171 S $ETRAP="G UNWIND^%ZTER",HLCS="-1^Error" 172 ;I $ZE["READ" S HLCS="-1^Error during read" 173 ;I $ZE["WRITE" S HLCS="-1^Error during write" 174 ; HL*1.6*115, SACC compliance 175 I $$EC^%ZOSV["READ" S HLCS="-1^Error during read" 176 I $$EC^%ZOSV["WRITE" S HLCS="-1^Error during write" 177 G UNWIND^%ZTER 178 DNS ; 179 ;openfail-try DNS lookup-Link must contain point to Domain Name 180 S POP=$G(POP) 181 S HLQUIET=$G(HLQUIET) 182 I 'HLQUIET W !,"Calling DNS" 183 N HLDOM,HLIP S HLCS="" 184 S HLDOM=$P(^HLCS(870,HLDP,0),U,7) 185 ; patch HL*1.6*122 start 186 S HLDOM("DNS")=$P($G(^HLCS(870,+$G(HLDP),0)),"^",8) 187 ; I 'HLDOM,'HLQUIET W !,"Domain Unknown" Q 188 I 'HLDOM,($L(HLDOM("DNS"),".")<3) D Q 189 . I 'HLQUIET W !,"Domain Unknown" 190 . S HLCS="-1^Connection Fail" 191 ; patch HL*1.6*122 end 192 I HLDOM S HLDOM=$P(^DIC(4.2,HLDOM,0),U) 193 ; patch HL*1.6*122 194 ; I HLDOM]"" D Q:'POP 195 I HLDOM]""!($L(HLDOM("DNS"),".")>2) D Q:'POP 196 . I HLDOM["VA.GOV"&(HLDOM'[".MED.") S HLDOM=$P(HLDOM,".VA.GOV")_".MED.VA.GOV" 197 . I HLTCPORT=5000 S HLDOM="HL7."_HLDOM 198 . I HLTCPORT=5500 S HLDOM="MPI."_HLDOM 199 . ; patch HL*1.6*122 200 . I ($L(HLDOM("DNS"),".")>2) S HLDOM=HLDOM("DNS") 201 . I 'HLQUIET W !,"Domain, "_HLDOM 202 . I 'HLQUIET W !,"Port: ",HLTCPORT 203 . S HLIP=$$ADDRESS^XLFNSLK(HLDOM) 204 . I HLIP]"",'HLQUIET W !,"DNS Returned: ",HLIP 205 . I HLIP]"" D 206 . . ;If more than one IP returned, try each, cache successful open 207 . . N HLI,HLJ,HLIP1 208 . . F HLJ=1:1:$L(HLIP,",") D Q:'POP 209 . . . S HLIP1=$P(HLIP,",",HLJ) 210 . . . F HLI=1:1:HLDRETR W:'HLQUIET !,"Trying ",HLIP1 D CALL^%ZISTCP(HLIP1,HLTCPORT,1) Q:'POP 211 . . . I 'POP S $P(^HLCS(870,HLDP,400),U)=HLIP1 212 . . . U IO 213 I POP S HLCS="-1^DNS Lookup Failed" 1 HLMA ;AISC/SAW-Message Administration Module ;10/25/2006 2 ;;1.6;HEALTH LEVEL SEVEN;**19,43,58,63,66,82,91,109,115,133,132**;Oct 13, 1995;Build 6 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 GENERATE(HLEID,HLARYTYP,HLFORMAT,HLRESLT,HLMTIEN,HLP) ; 5 ;Entry point to generate a deferred message 6 ; 7 ;This is a subroutine call with parameter passing. It returns a 8 ;value in the variable HLRESLT with 1 to 3 pieces separated by uparrows 9 ;as follows: 1st message ID^error code^error description 10 ;If no error occurs, only the first piece is returned equal to a unique 11 ;ID for the 1st message. If message was sent to more than 1 subscriber 12 ;than the other message IDs will be in the array HLRESLT(n)=ID 13 ;Otherwise, three pieces are returned with the 14 ;first piece equal to the message ID, if one was assigned, otherwise 0 15 ; 16 ;Required Input Parameters 17 ; HLEID = Name or IEN of event driver protocol in the Protocol file 18 ; HLARYTYP = Array type. One of the following codes: 19 ; LM = local array containing a single message 20 ; LB = local array containig a batch of messages 21 ; GM = global array containing a single message 22 ; GB = global array containing a batch of messages 23 ; HLFORMAT = Format of array, 1 for pre-formatted in HL7 format, 24 ; otherwise 0 25 ;NOTE: The parameter HLRESLT must be passed by reference 26 ; HLRESLT = The variable that will be returned to the calling 27 ; application as descibed above 28 ;Optional Parameters 29 ; HLMTIEN = IEN of entry in Message Text file where the message 30 ; being generated is to be stored. This parameter is 31 ; only passed for a batch type message 32 ;NOTE: The parameter HLP used for the following parameters must be 33 ; passed by reference 34 ; HLP("SECURITY") = A 1 to 40 character string 35 ; HLP("CONTPTR") = Continuation pointer, a 1 to 180 character string 36 ; HLP("NAMESPACE") = Passed in by application namespace - HL*1.6*91 37 ; HLP("EXLCLUDE SUBSCRIBER",<n=1,2,3...>)=<subsciber protocol ien> - A list of protocols to dynamically drop from the event protocol's subscriber multiple. 38 ; 39 ;can't have link open when generating new message 40 N HLTCP,HLTCPO,HLPRIO,HLMIDAR 41 S HLPRIO="D" 42 S HLRESLT="" 43 ;Check for required parameters 44 CONT I $G(HLEID)']""!($G(HLARYTYP)']"")!($G(HLFORMAT)']"") S HLRESLT="0^7^"_$G(^HL(771.7,7,0))_" at GENERATE^HLMA entry point" G EXIT 45 I 'HLEID S HLEID=$O(^ORD(101,"B",HLEID,0)) I 'HLEID S HLRESLT="0^1^"_$G(^HL(771.7,1,0)) G EXIT 46 N HLRESLT1,HLRESLTA S (HLRESLTA,HLRESLT1)="" 47 I "GL"'[$E(HLARYTYP) S HLRESLT="0^4^"_$G(^HL(771.7,4,0)) G EXIT 48 I $L($G(HLP("SECURITY")))>40 S HLRESLT="0^6^"_$G(^HL(771.7,6,0)) G EXIT 49 I $L($G(HLP("CONTPTR")))>180 S HLRESLT="0^11^"_$G(^HL(771.7,11,0)) G EXIT 50 I $D(HLL("LINKS")) D G:$G(HLRESLT)]"" EXIT 51 . N I,HLPNAM,HLPIEN,HLLNAM,HLLIEN 52 . S I=0 53 . F S I=$O(HLL("LINKS",I)) Q:'I D Q:$G(HLRESLT)]"" 54 . . S HLPNAM=$P(HLL("LINKS",I),U) 55 . . S HLPIEN=+$O(^ORD(101,"B",HLPNAM,0)) 56 . . I $P($G(^ORD(101,HLPIEN,0)),U,4)'="S" S HLRESLT="0^15^Invalid Subscriber Protocol in HLL('LINKS'): "_HLL("LINKS",I) Q 57 . . S HLLNAM=$P(HLL("LINKS",I),U,2) 58 . . S HLLIEN=+$O(^HLCS(870,"B",HLLNAM,0)) 59 . . I '$D(^HLCS(870,HLLIEN,0)) S HLRESLT="0^15^Invalid HL Node in HLL('LINKS'): "_HLL("LINKS",I) Q 60 ;Extract data from Protocol file 61 D EVENT^HLUTIL1(HLEID,"15,20,771",.HLN) 62 S HLENROU=$G(HLN(20)),HLEXROU=$G(HLN(15)) 63 S HLP("GROUTINE")=$G(HLN(771)) K HLN I HLP("GROUTINE")']"",'HLFORMAT S HLRESLT="0^3^"_$G(^HL(771.7,3,0)) G EXIT 64 ;Create message ID and Message Text IEN if Message Text IEN not 65 ;previously created ('$G(HLMTIEN)) 66 I '$G(HLMTIEN) D CREATE^HLTF(.HLMID,.HLMTIEN,.HLDT,.HLDT1) 67 ;Get message ID if Message Text IEN already created 68 I '$G(HLMID) D 69 .S HLDT=$G(^HL(772,HLMTIEN,0)),HLMID=$P(HLDT,"^",6),HLDT=+HLDT 70 .S HLDT1=$$HLDATE^HLFNC(HLDT) 71 S HLMIDAR=0,HLRESLT=HLMID,HLP("DT")=HLDT,HLP("DTM")=HLDT1 72 ;Execute entry action for event driver protocol 73 I HLENROU]"" X HLENROU 74 ;Invoke transaction processor 75 K HLDT,HLDT1,HLENROU 76 D GENERATE^HLTP(HLMID,HLMTIEN,HLEID,HLARYTYP,HLFORMAT,.HLRESLT1,.HLP) 77 ;HLMIDAR is array of message IDs, only set for broadcast messages 78 I HLMIDAR K HLMIDAR("N") M HLRESLT=HLMIDAR 79 S HLRESLT=HLRESLT_"^"_HLRESLT1 80 ;Execute exit action for event driver protocol 81 I HLEXROU]"" X HLEXROU 82 EXIT ;Update status if Message Text file entry has been created 83 K HLTCP 84 I $D(HLMTIEN) D STATUS^HLTF0(HLMTIEN,$S($P(HLRESLT,"^",2):4,1:3),$S($P(HLRESLT,"^",2):$P(HLRESLT,"^",2),1:""),$S($P(HLRESLT,"^",2):$P(HLRESLT,"^",3),1:"")) 85 K HLDT,HLDT1,HLMID,HLRESLT1,HLENROU,HLEXROU 86 Q 87 DIRECT(HLEID,HLARYTYP,HLFORMAT,HLRESLT,HLMTIENO,HLP) ; 88 ;Entry point to generate an immediate message, must be TCP Logical Link 89 ;Input: 90 ; The same as GENERATE,with one additional subscript to the HLP input array: 91 ; 92 ; HLP("OPEN TIMEOUT") (optional, pass by reference) a number between 93 ; 1 and 120 that specifies how many seconds the DIRECT CONNECT should 94 ; try to open a connection before failing. It is killed upon completion. 95 ; 96 N HLTCP,HLTCPO,HLPRIO,HLSAN,HLN,HLMIDAR,HLMTIENR,ZMID,HLDIRECT 97 S HLRESLT="" 98 ;HLMTIENO=ien passed in, batch message 99 S HLMTIEN=$G(HLMTIENO) 100 I $G(HLP("OPEN TIMEOUT")),((HLP("OPEN TIMEOUT")\1)'=+HLP("OPEN TIMEOUT"))!HLP("OPEN TIMEOUT")>120 Q "0^4^INVALID OPEN TIMEOUT PARAMETER" 101 I $G(HLP("OPEN TIMEOUT")) D 102 .S HLDIRECT("OPEN TIMEOUT")=HLP("OPEN TIMEOUT") 103 .K HLP("OPEN TIMEOUT") 104 K HL,HLMTIENO 105 D INIT^HLFNC2(HLEID,.HL) 106 I $G(HL) S HLRESLT="0^"_HL Q 107 S HLPRIO="I" D CONT 108 ;HLMTIENO=original msg. ien in file 772, HLMTIENR=response ien set in HLMA2 109 S HLMTIENO=HLMTIEN,HLMTIEN=$G(HLMTIENR) 110 ;Set special HL variables 111 S HLQUIT=0,HLNODE="",HLNEXT="D HLNEXT^HLCSUTL" 112 Q 113 ; 114 CLOSE(LOGLINK) ;close connection that was open in tag DIRECT 115 Q 116 PING ;ping another VAMC to test Link 117 ;set HLQUIET =1 to skip writes 118 ;look for HLTPUT to get turnaround time over network. 119 N DA,DIC,HLDP,HLDPNM,HLDPDM,HLCSOUT,HLDBSIZE,HLDREAD,HLOS,HLTCPADD,HLTCPCS,HLTCPLNK,HLTCPORT,HLTCPRET,HLCSFAIL,HLPARAM 120 N HCS,HCSCMD,HLCS,HCSDAT,HCSER,HCSEXIT,HCSTRACE,HLDT1,HLDRETR,HLRETRA,HLDBACK,HLDWAIT,HLTCPCS,INPUT,OUTPUT,POP,X,Y,HLX1,HLX2 121 S HLQUIET=$G(HLQUIET) 122 S HLCS="",HCSTRACE="C: ",POP=1,INPUT="INPUT",OUTPUT="OUTPUT" 123 S DIC="^HLCS(870,",DIC(0)="QEAMZ" 124 D ^DIC Q:Y<0 125 S HLDP=+Y,HLDPNM=Y(0,0),HLDPDM=$P($$PARAM^HLCS2,U,2) 126 ;I $P($G(^HLCS(870,HLDP,400)),U)="" W !,"Missing IP Address" Q 127 D SETUP^HLCSAC G:HLCS PINGQ 128 ;PING header=MSH^PING^domain^PING^logical link^datetime 129 S INPUT(1)="MSH^PING^"_HLDPDM_"^PING^"_HLDPNM_"^"_$$HTE^XLFDT($H) 130 D OPEN^HLCSAC 131 I HLCS D DNS G:HLCS PINGQ 132 D 133 . N $ETRAP,$ESTACK S $ETRAP="D PINGERR^HLMA" 134 . ;non-standard HL7 header; start block,header,end block 135 . S HLX1=$H 136 . W $C(11)_INPUT(1)_$C(28)_$C(13),! ;HL*1.6*115, restored ! char 137 . ;read response 138 . R X:HLDREAD 139 . S HLX2=$H 140 . S X=$P(X,$C(28)),HLCS=$S(X=INPUT(1):"PING worked",X="":"No response",1:"Incorrect response") 141 . ;Get roundtrip time 142 . K HLTPUT I X]"" S HLTPUT=$$HDIFF^XLFDT(HLX2,HLX1,2) 143 D CLOSE^%ZISTCP 144 PINGQ ;write back status and quit 145 I 'HLQUIET W !,HLCS,! 146 Q 147 PINGERR ;process errors from PING 148 S $ETRAP="G UNWIND^%ZTER",HLCS="-1^Error" 149 ;I $ZE["READ" S HLCS="-1^Error during read" 150 ;I $ZE["WRITE" S HLCS="-1^Error during write" 151 ; HL*1.6*115, SACC compliance 152 I $$EC^%ZOSV["READ" S HLCS="-1^Error during read" 153 I $$EC^%ZOSV["WRITE" S HLCS="-1^Error during write" 154 G UNWIND^%ZTER 155 DNS ; 156 ;openfail-try DNS lookup-Link must contain point to Domain Name 157 S POP=$G(POP) 158 S HLQUIET=$G(HLQUIET) 159 I 'HLQUIET W !,"Calling DNS" 160 N HLDOM,HLIP S HLCS="" 161 S HLDOM=$P(^HLCS(870,HLDP,0),U,7) 162 I 'HLDOM,'HLQUIET W !,"Domain Unknown" Q 163 I HLDOM S HLDOM=$P(^DIC(4.2,HLDOM,0),U) 164 I HLDOM]"" D Q:'POP 165 . I HLDOM["VA.GOV"&(HLDOM'[".MED.") S HLDOM=$P(HLDOM,".VA.GOV")_".MED.VA.GOV" 166 . I HLTCPORT=5000 S HLDOM="HL7."_HLDOM 167 . I HLTCPORT=5500 S HLDOM="MPI."_HLDOM 168 . I 'HLQUIET W !,"Domain, "_HLDOM 169 . I 'HLQUIET W !,"Port: ",HLTCPORT 170 . S HLIP=$$ADDRESS^XLFNSLK(HLDOM) 171 . I HLIP]"",'HLQUIET W !,"DNS Returned: ",HLIP 172 . I HLIP]"" D 173 . . ;If more than one IP returned, try each, cache successful open 174 . . N HLI,HLJ,HLIP1 175 . . F HLJ=1:1:$L(HLIP,",") D Q:'POP 176 . . . S HLIP1=$P(HLIP,",",HLJ) 177 . . . F HLI=1:1:HLDRETR W:'HLQUIET !,"Trying ",HLIP1 D CALL^%ZISTCP(HLIP1,HLTCPORT,1) Q:'POP 178 . . . I 'POP S $P(^HLCS(870,HLDP,400),U)=HLIP1 179 . . . U IO 180 I POP S HLCS="-1^DNS Lookup Failed" -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOAPI1.m
r613 r623 1 HLOAPI1 ;ALB/CJM-HL7 - Developer API's for sending & receiving messages(continued) ;07/18/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,132,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 SENDONE(HLMSTATE,PARMS,WHOTO,ERROR) ; 6 ;Sends the message to a single receiving application. 7 ; 8 ;Input: 9 ;HLMSTATE() - (pass by reference, required) This array is used by the HL7 package to track the progress of the message. The application MUST NOT touch it 10 ;PARMS( *pass by reference* 11 ; "APP ACK RESPONSE")=<tag^routine> to call when the app ack is received (optional) 12 ; (NOTE: For batch messages, HLO best supports returning application 13 ; acknowledgments via a batch response. However, non-VistA systems 14 ; may return individual messages as application acknowledgments to 15 ; messages within the original batch message, so for applications 16 ; sending batch messages might best code the "APP ACK RESPONSE" 17 ; routine to first check whether the response message is a batch. 18 ; 19 ; "ACCEPT ACK RESPONSE")=<tag^routine> to call when the commit ack is received (optional) 20 ; "ACCEPT ACK TYPE") = <AL,NE> (optional, defaults to AL) 21 ; "APP ACK TYPE") = <AL,NE> (optional, defaults to NE) 22 ; "FAILURE RESPONSE" - <tag>^<routine> (optional) The sending application routine to execute when the transmission of the message fails, i.e., the message can not be sent or no commit ack is received. 23 ; "QUEUE" - (optional) An application can name its own private queue - just a string up to 20 characters, it should be namespaced. 24 ; "SECURITY")=security information to include in the header segment, SEQ 8 (optional) 25 ; "SENDING APPLICATION")=name of sending app (required, 60 maximum length) 26 ; 27 ; WHOTO (required,pass by reference) an array specifying a single recipient. These subscripts are allowed: 28 ; 29 ; "RECEIVING APPLICATION" - (string, 60 char max, required) 30 ; 31 ; EXACTLY ONE of these parameters must be provided to identify the Receiving Facility: 32 ; 33 ; "FACILITY LINK IEN" - ien of the logical link 34 ; "FACILITY LINK NAME" - name of the logical link 35 ; "INSTITUTION IEN" - ptr to the INSTITUTION file 36 ; "STATION NUMBER" - station # with suffix 37 ; 38 ; EXACTLY ONE of these MAY be provided - optionally - to identify the interface engine to route the message through: 39 ; 40 ; "IE LINK IEN" - ptr to a logical link for the interface engine 41 ; "IE LINK NAME" - name of the logical link for the interface engine 42 ; 43 ;Output: 44 ; Function returns the ien of the message in file 778 on success, 0 on failure 45 ; HLMSTATE() - (pass by reference, required) This array is used by the HL7 package to track the progress of the message. The application MUST NOT touch it! 46 ; ERROR (pass by reference, optional) - on failure, will contain an error message 47 ; PARMS - left undefined when the function returns 48 ; WHOTO - left undefined when the function returns 49 ; 50 ; 51 N SUCCESS,ERR1,ERR2 52 S SUCCESS=0 53 D 54 .I '$G(HLMSTATE("BODY")),'$G(HLMSTATE("UNSTORED LINES")) S ERROR="MESSAGE NOT YET CREATED" Q 55 .; 56 .I $$CHKPARMS^HLOAPI2(.HLMSTATE,.PARMS,.ERR1)&$$CHKWHO^HLOAPI2(.HLMSTATE,.WHOTO,.ERR2) D 57 ..I $$SEND(.HLMSTATE,.ERROR) S SUCCESS=1 58 .E D 59 ..S ERROR=$G(ERR1)_": "_$G(ERR2) 60 ..D DONTSEND(.HLMSTATE,ERROR) 61 K PARMS,WHOTO 62 Q $S(SUCCESS:HLMSTATE("IEN"),1:0) 63 ; 64 SENDMANY(HLMSTATE,PARMS,WHOTO) ; 65 ;Sends the message to a list of receiving applications 66 ; 67 ;Input: Same as for $$SENDONE, except WHOTO is a list. 68 ; WHOTO (pass by reference) 69 ; Specifies a list of recipients. Each recipient should be on the 70 ; list as WHOTO(i), where i=1,2,3,4, etc. for as many messages as to 71 ; send. At each subscript WHOTO(i), the same lower level subscripts 72 ; may be defined as in the $$SENDONE API. For example: 73 ; 74 ; WHOTO(1,"LINK NAME")="VAALB" 75 ; WHOTO(1,"RECEIVING APPLICATION")="MPI" 76 ; WHOTO(2,"STATION NUMBER")=500 77 ; WHOTO(2,"RECEIVING APPLICATION")="MPI" 78 ; 79 ; 80 ;Output: 81 ; Function returns 1 if a message is queued to be sent to each intended recipient, 0 otherwise 82 ; PARMS - left undefined when the function returns 83 ; WHOTO (pass by reference) returns the status of each message to be sent in the format: 84 ; (<i>,"QUEUED")= <1 if queued to be sent, 0 otherwise) 85 ; (<i>,"IEN")=<ien, file 778> 86 ; (<i>,"ERROR")= error message if an error was encountered (status=0), not defined otherwise 87 ; 88 ; 89 N ERROR,RETURN,WHO,STATE,I 90 S RETURN=1 91 I '$G(HLMSTATE("BODY")),'$G(HLMSTATE("UNSTORED LINES")) D K PARMS Q 0 92 .S ERROR="MESSAGE NOT YET CREATED" 93 .S I=0 F S I=$O(WHOTO(I)) Q:'I S WHOTO(I,"QUEUED")=0,WHOTO(I,"IEN")=0,WHOTO(I,"ERROR")=ERROR 94 ; 95 I '$$CHKPARMS^HLOAPI2(.HLMSTATE,.PARMS,.ERROR) D K PARMS Q 0 96 .S I=0 F S I=$O(WHOTO(I)) Q:'I D 97 ..K WHO M WHO=WHOTO(I) 98 ..K STATE M STATE=HLMSTATE S STATE("IEN")="" 99 ..S WHOTO(I,"QUEUED")=0 100 ..D DONTSEND(.STATE,$G(ERROR)) 101 ..S WHOTO(I,"IEN")=$G(STATE("IEN")) 102 ..S WHOTO(I,"ERROR")=ERROR 103 ; 104 S I=0 F S I=$O(WHOTO(I)) Q:'I D 105 .K WHO M WHO=WHOTO(I) 106 .K STATE M STATE=HLMSTATE S STATE("IEN")="" 107 .S ERROR="" 108 .I $$CHKWHO^HLOAPI2(.STATE,.WHO,.ERROR) D 109 ..I $$SEND(.STATE,.ERROR) D 110 ...S WHOTO(I,"QUEUED")=1 111 ...S WHOTO(I,"IEN")=STATE("IEN") 112 ...S WHOTO(I,"ERROR")="" 113 ..E D 114 ...S WHOTO(I,"QUEUED")=0 115 ...S WHOTO(I,"IEN")=$G(STATE("IEN")) 116 ...S WHOTO(I,"ERROR")=$G(ERROR) 117 ...S RETURN=0 118 .E D ;who not adequately determined 119 ..S WHOTO(I,"QUEUED")=0,RETURN=0 120 ..D DONTSEND(.STATE,$G(ERROR)) 121 ..S WHOTO(I,"IEN")=$G(STATE("IEN")),WHOTO(I,"ERROR")=$G(ERROR) 122 K PARMS 123 Q RETURN 124 ; 125 SENDSUB(HLMSTATE,PARMS,MESSAGES) ; 126 ;Sends the message to a list of receiving applications based on the HL7 Subscription Registry 127 ; 128 ;Input: 129 ; HLMSTATE (pass by reference, required) same as $$SENDMANY 130 ; PARMS (pass by reference, required) same as $$SENDMANY, with one additional subscript: 131 ; "SUBSCRIPTION IEN" - the ien of an entry in the HL7 Subscription Registry, defining the intended recipients of this message 132 ; 133 ;Output: 134 ; Function returns 1 if a message is queued to be sent to each intended recipient, 0 otherwise 135 ; PARMS - left undefined when the function returns 136 ; MESSAGES (pass by reference) returns the status of each message to be sent in this format, where subien is the ien of the recipient in the RECIPEINTS subfile of the HL7 Subscription Registry 137 ; (<subien>,"QUEUED")= <1 if queued to be sent, 0 otherwise) 138 ; (<subien>,"IEN")=<ien, file 778> 139 ; (<subien>,"ERROR")= error message if an error was encountered (status=0), not defined otherwise 140 ; 141 ; 142 K MESSAGES 143 N ERROR,RETURN,STATE,SUBIEN,WHO 144 ; 145 S RETURN=1 146 ; 147 ; 148 I '$G(HLMSTATE("BODY")),'$G(HLMSTATE("UNSTORED LINES")) S ERROR="MESSAGE NOT YET CREATED" K PARMS Q 0 149 I '$G(PARMS("SUBSCRIPTION IEN")) S ERROR="SUBSCRIPTION REGISTRY IEN NOT PROVIDED" K PARMS Q 0 150 ; 151 I '$$CHKPARMS^HLOAPI2(.HLMSTATE,.PARMS,.ERROR) D K PARMS Q 0 152 .S SUBIEN=0 F S SUBIEN=$$NEXT^HLOASUB(PARMS("SUBSCRIPTION IEN"),.WHO) Q:'SUBIEN D 153 ..N SARY,HARY 154 ..S HARY="STATE(""HDR"")" 155 ..S SARY="STATE(""STATUS"")" 156 ..K STATE M STATE=HLMSTATE S STATE("IEN")="" 157 ..;move parameters into HLMSTATE 158 ..S @SARY@("LINK IEN")=WHO("LINK IEN") 159 ..S @SARY@("LINK NAME")=WHO("LINK NAME") 160 ..S @HARY@("RECEIVING APPLICATION")=WHO("RECEIVING APPLICATION") 161 ..M @HARY@("RECEIVING FACILITY")=WHO("RECEIVING FACILITY") 162 ..D DONTSEND(.STATE,$G(ERROR)) 163 ..S MESSAGES(SUBIEN,"QUEUED")=0 164 ..S MESSAGES(SUBIEN,"IEN")=$G(STATE("IEN")) 165 ..S MESSAGES(SUBIEN,"ERROR")=$G(ERROR) 166 ; 167 F S SUBIEN=$$NEXT^HLOASUB(PARMS("SUBSCRIPTION IEN"),.WHO) Q:'SUBIEN D 168 .N SARY,HARY 169 .S HARY="STATE(""HDR"")" 170 .S SARY="STATE(""STATUS"")" 171 .K STATE M STATE=HLMSTATE S STATE("IEN")="" 172 .;move parameters into HLMSTATE 173 .S @SARY@("LINK IEN")=WHO("LINK IEN") 174 .S @SARY@("LINK NAME")=WHO("LINK NAME") 175 .S @HARY@("RECEIVING APPLICATION")=WHO("RECEIVING APPLICATION") 176 .M @HARY@("RECEIVING FACILITY")=WHO("RECEIVING FACILITY") 177 .S ERROR="" 178 .I $$SEND(.STATE,.ERROR) D 179 ..S MESSAGES(SUBIEN,"QUEUED")=1 180 .E D 181 ..S MESSAGES(SUBIEN,"QUEUED")=0,RETURN=0 182 .S MESSAGES(SUBIEN,"IEN")=$G(STATE("IEN")),MESSAGES(SUBIEN,"ERROR")=$G(ERROR) 183 K PARMS 184 Q RETURN 185 ; 186 SEND(HLMSTATE,ERROR) ; 187 ; 188 K ERROR 189 I HLMSTATE("UNSTORED LINES"),'$$SAVEMSG^HLOF777(.HLMSTATE) S ERROR="$$SAVE^HLOF777 FAILED!" Q 0 190 ; 191 I '$$SAVEMSG^HLOF778(.HLMSTATE) S ERROR="$$SAVE^HLOF778 FAILED!" Q 0 192 I HLMSTATE("BATCH"),$L($G(HLMSTATE("STATUS","SEQUENCE QUEUE"))) S ERROR="SEQUENCE QUEUES NOT SUPPORTED FOR BATCH MESSAGES" Q 0 193 I $L($G(HLMSTATE("STATUS","SEQUENCE QUEUE"))) D 194 .S HLMSTATE("STATUS","MOVED TO OUT QUEUE")=$$SQUE^HLOQUE(HLMSTATE("STATUS","SEQUENCE QUEUE"),HLMSTATE("STATUS","LINK NAME"),$G(HLMSTATE("STATUS","PORT")),HLMSTATE("STATUS","QUEUE"),HLMSTATE("IEN")) D:HLMSTATE("STATUS","MOVED TO OUT QUEUE") 195 ..S $P(^HLB(HLMSTATE("IEN"),5),"^",2)=1 196 E D 197 .D OUTQUE^HLOQUE(HLMSTATE("STATUS","LINK NAME"),$G(HLMSTATE("STATUS","PORT")),HLMSTATE("STATUS","QUEUE"),HLMSTATE("IEN")) 198 Q HLMSTATE("IEN") 199 ; 200 DONTSEND(HLMSTATE,ERROR) ; 201 ;This procedure does NOT send a message. Rather, it creates an entry in file 778 with the status ER. 202 ;Input: 203 ; HLMSTATE - pass-by-reference 204 ; ERROR (optional, pass-by-value) error text to store with the message 205 ;Output: none 206 ; 207 I HLMSTATE("UNSTORED LINES"),'$$SAVEMSG^HLOF777(.HLMSTATE) ; just continue 208 ; 209 S HLMSTATE("STATUS")="ER" 210 S HLMSTATE("STATUS","PURGE")=$$FMADD^XLFDT(HLMSTATE("DT/TM CREATED"),HLMSTATE("SYSTEM","ERROR PURGE")) 211 S HLMSTATE("STATUS","ERROR TEXT")=$G(ERROR) 212 I '$$SAVEMSG^HLOF778(.HLMSTATE) ;already reported an error to the app 213 Q 1 HLOAPI1 ;ALB/CJM-HL7 - Developer API's for sending & receiving messages(continued) ;02/06/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,132,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 SENDONE(HLMSTATE,PARMS,WHOTO,ERROR) ; 6 ;Sends the message to a single receiving application. 7 ; 8 ;Input: 9 ;HLMSTATE() - (pass by reference, required) This array is used by the HL7 package to track the progress of the message. The application MUST NOT touch it 10 ;PARMS( *pass by reference* 11 ; "APP ACK RESPONSE")=<tag^routine> to call when the app ack is received (optional) 12 ; (NOTE: For batch messages, HLO best supports returning application 13 ; acknowledgments via a batch response. However, non-VistA systems 14 ; may return individual messages as application acknowledgments to 15 ; messages within the original batch message, so for applications 16 ; sending batch messages might best code the "APP ACK RESPONSE" 17 ; routine to first check whether the response message is a batch. 18 ; 19 ; "ACCEPT ACK RESPONSE")=<tag^routine> to call when the commit ack is received (optional) 20 ; "ACCEPT ACK TYPE") = <AL,NE> (optional, defaults to AL) 21 ; "APP ACK TYPE") = <AL,NE> (optional, defaults to NE) 22 ; "FAILURE RESPONSE" - <tag>^<routine> (optional) The sending application routine to execute when the transmission of the message fails, i.e., the message can not be sent or no commit ack is received. 23 ; "QUEUE" - (optional) An application can name its own private queue - just a string up to 20 characters, it should be namespaced. 24 ; "SECURITY")=security information to include in the header segment, SEQ 8 (optional) 25 ; "SENDING APPLICATION")=name of sending app (required, 60 maximum length) 26 ; 27 ; WHOTO (required,pass by reference) an array specifying a single recipient. These subscripts are allowed: 28 ; 29 ; "RECEIVING APPLICATION" - (string, 60 char max, required) 30 ; 31 ; EXACTLY ONE of these parameters must be provided to identify the Receiving Facility: 32 ; 33 ; "FACILITY LINK IEN" - ien of the logical link 34 ; "FACILITY LINK NAME" - name of the logical link 35 ; "INSTITUTION IEN" - ptr to the INSTITUTION file 36 ; "STATION NUMBER" - station # with suffix 37 ; 38 ; EXACTLY ONE of these MAY be provided - optionally - to identify the interface engine to route the message through: 39 ; 40 ; "IE LINK IEN" - ptr to a logical link for the interface engine 41 ; "IE LINK NAME" - name of the logical link for the interface engine 42 ; 43 ;Output: 44 ; Function returns the ien of the message in file 778 on success, 0 on failure 45 ; HLMSTATE() - (pass by reference, required) This array is used by the HL7 package to track the progress of the message. The application MUST NOT touch it! 46 ; ERROR (pass by reference, optional) - on failure, will contain an error message 47 ; PARMS - left undefined when the function returns 48 ; WHOTO - left undefined when the function returns 49 ; 50 ; 51 N SUCCESS,ERR1,ERR2 52 S SUCCESS=0 53 D 54 .I '$G(HLMSTATE("BODY")),'$G(HLMSTATE("UNSTORED LINES")) S ERROR="MESSAGE NOT YET CREATED" Q 55 .; 56 .I $$CHKPARMS^HLOAPI2(.HLMSTATE,.PARMS,.ERR1)&$$CHKWHO(.HLMSTATE,.WHOTO,.ERR2) D 57 ..I $$SEND(.HLMSTATE,.ERROR) S SUCCESS=1 58 .E D 59 .S ERROR=$G(ERR1)_": "_$G(ERR2) 60 .D DONTSEND(.HLMSTATE,ERROR) 61 K PARMS,WHOTO 62 Q $S(SUCCESS:HLMSTATE("IEN"),1:0) 63 ; 64 SENDMANY(HLMSTATE,PARMS,WHOTO) ; 65 ;Sends the message to a list of receiving applications 66 ; 67 ;Input: Same as for $$SENDONE, except WHOTO is a list. 68 ; WHOTO (pass by reference) 69 ; Specifies a list of recipients. Each recipient should be on the 70 ; list as WHOTO(i), where i=1,2,3,4, etc. for as many messages as to 71 ; send. At each subscript WHOTO(i), the same lower level subscripts 72 ; may be defined as in the $$SENDONE API. For example: 73 ; 74 ; WHOTO(1,"LINK NAME")="VAALB" 75 ; WHOTO(1,"RECEIVING APPLICATION")="MPI" 76 ; WHOTO(2,"STATION NUMBER")=500 77 ; WHOTO(2,"RECEIVING APPLICATION")="MPI" 78 ; 79 ; 80 ;Output: 81 ; Function returns 1 if a message is queued to be sent to each intended recipient, 0 otherwise 82 ; PARMS - left undefined when the function returns 83 ; WHOTO (pass by reference) returns the status of each message to be sent in the format: 84 ; (<i>,"QUEUED")= <1 if queued to be sent, 0 otherwise) 85 ; (<i>,"IEN")=<ien, file 778> 86 ; (<i>,"ERROR")= error message if an error was encountered (status=0), not defined otherwise 87 ; 88 ; 89 N ERROR,RETURN,WHO,STATE,I 90 S RETURN=1 91 I '$G(HLMSTATE("BODY")),'$G(HLMSTATE("UNSTORED LINES")) D K PARMS Q 0 92 .S ERROR="MESSAGE NOT YET CREATED" 93 .S I=0 F S I=$O(WHOTO(I)) Q:'I S WHOTO(I,"QUEUED")=0,WHOTO(I,"IEN")=0,WHOTO(I,"ERROR")=ERROR 94 ; 95 I '$$CHKPARMS^HLOAPI2(.HLMSTATE,.PARMS,.ERROR) D K PARMS Q 0 96 .S I=0 F S I=$O(WHOTO(I)) Q:'I D 97 ..K WHO M WHO=WHOTO(I) 98 ..K STATE M STATE=HLMSTATE S STATE("IEN")="" 99 ..S WHOTO(I,"QUEUED")=0 100 ..D DONTSEND(.STATE,$G(ERROR)) 101 ..S WHOTO(I,"IEN")=$G(STATE("IEN")) 102 ..S WHOTO(I,"ERROR")=ERROR 103 ; 104 S I=0 F S I=$O(WHOTO(I)) Q:'I D 105 .K WHO M WHO=WHOTO(I) 106 .K STATE M STATE=HLMSTATE S STATE("IEN")="" 107 .S ERROR="" 108 .I $$CHKWHO(.STATE,.WHO,.ERROR) D 109 ..I $$SEND(.STATE,.ERROR) D 110 ...S WHOTO(I,"QUEUED")=1 111 ...S WHOTO(I,"IEN")=STATE("IEN") 112 ...S WHOTO(I,"ERROR")="" 113 ..E D 114 ...S WHOTO(I,"QUEUED")=0 115 ...S WHOTO(I,"IEN")=$G(STATE("IEN")) 116 ...S WHOTO(I,"ERROR")=$G(ERROR) 117 ...S RETURN=0 118 .E D ;who not adequately determined 119 ..S WHOTO(I,"QUEUED")=0,RETURN=0 120 ..D DONTSEND(.STATE,$G(ERROR)) 121 ..S WHOTO(I,"IEN")=$G(STATE("IEN")),WHOTO(I,"ERROR")=$G(ERROR) 122 K PARMS 123 Q RETURN 124 ; 125 SENDSUB(HLMSTATE,PARMS,MESSAGES) ; 126 ;Sends the message to a list of receiving applications based on the HL7 Subscription Registry 127 ; 128 ;Input: 129 ; HLMSTATE (pass by reference, required) same as $$SENDMANY 130 ; PARMS (pass by reference, required) same as $$SENDMANY, with one additional subscript: 131 ; "SUBSCRIPTION IEN" - the ien of an entry in the HL7 Subscription Registry, defining the intended recipients of this message 132 ; 133 ;Output: 134 ; Function returns 1 if a message is queued to be sent to each intended recipient, 0 otherwise 135 ; PARMS - left undefined when the function returns 136 ; MESSAGES (pass by reference) returns the status of each message to be sent in this format, where subien is the ien of the recipient in the RECIPEINTS subfile of the HL7 Subscription Registry 137 ; (<subien>,"QUEUED")= <1 if queued to be sent, 0 otherwise) 138 ; (<subien>,"IEN")=<ien, file 778> 139 ; (<subien>,"ERROR")= error message if an error was encountered (status=0), not defined otherwise 140 ; 141 ; 142 K MESSAGES 143 N ERROR,RETURN,STATE,SUBIEN,WHO 144 ; 145 S RETURN=1 146 ; 147 ; 148 I '$G(HLMSTATE("BODY")),'$G(HLMSTATE("UNSTORED LINES")) S ERROR="MESSAGE NOT YET CREATED" K PARMS Q 0 149 I '$G(PARMS("SUBSCRIPTION IEN")) S ERROR="SUBSCRIPTION REGISTRY IEN NOT PROVIDED" K PARMS Q 0 150 ; 151 I '$$CHKPARMS^HLOAPI2(.HLMSTATE,.PARMS,.ERROR) D K PARMS Q 0 152 .S SUBIEN=0 F S SUBIEN=$$NEXT^HLOASUB(PARMS("SUBSCRIPTION IEN"),.WHO) Q:'SUBIEN D 153 ..N SARY,HARY 154 ..S HARY="STATE(""HDR"")" 155 ..S SARY="STATE(""STATUS"")" 156 ..K STATE M STATE=HLMSTATE S STATE("IEN")="" 157 ..;move parameters into HLMSTATE 158 ..S @SARY@("LINK IEN")=WHO("LINK IEN") 159 ..S @SARY@("LINK NAME")=WHO("LINK NAME") 160 ..S @HARY@("RECEIVING APPLICATION")=WHO("RECEIVING APPLICATION") 161 ..M @HARY@("RECEIVING FACILITY")=WHO("RECEIVING FACILITY") 162 ..D DONTSEND(.STATE,$G(ERROR)) 163 ..S MESSAGES(SUBIEN,"QUEUED")=0 164 ..S MESSAGES(SUBIEN,"IEN")=$G(STATE("IEN")) 165 ..S MESSAGES(SUBIEN,"ERROR")=$G(ERROR) 166 ; 167 F S SUBIEN=$$NEXT^HLOASUB(PARMS("SUBSCRIPTION IEN"),.WHO) Q:'SUBIEN D 168 .N SARY,HARY 169 .S HARY="STATE(""HDR"")" 170 .S SARY="STATE(""STATUS"")" 171 .K STATE M STATE=HLMSTATE S STATE("IEN")="" 172 .;move parameters into HLMSTATE 173 .S @SARY@("LINK IEN")=WHO("LINK IEN") 174 .S @SARY@("LINK NAME")=WHO("LINK NAME") 175 .S @HARY@("RECEIVING APPLICATION")=WHO("RECEIVING APPLICATION") 176 .M @HARY@("RECEIVING FACILITY")=WHO("RECEIVING FACILITY") 177 .S ERROR="" 178 .I $$SEND(.STATE,.ERROR) D 179 ..S MESSAGES(SUBIEN,"QUEUED")=1 180 .E D 181 ..S MESSAGES(SUBIEN,"QUEUED")=0,RETURN=0 182 .S MESSAGES(SUBIEN,"IEN")=$G(STATE("IEN")),MESSAGES(SUBIEN,"ERROR")=$G(ERROR) 183 K PARMS 184 Q RETURN 185 ; 186 SEND(HLMSTATE,ERROR) ; 187 ; 188 K ERROR 189 I HLMSTATE("UNSTORED LINES"),'$$SAVEMSG^HLOF777(.HLMSTATE) S ERROR="$$SAVE^HLOF777 FAILED!" Q 0 190 ; 191 I '$$SAVEMSG^HLOF778(.HLMSTATE) S ERROR="$$SAVE^HLOF778 FAILED!" Q 0 192 D OUTQUE^HLOQUE(HLMSTATE("STATUS","LINK NAME"),$G(HLMSTATE("STATUS","PORT")),HLMSTATE("STATUS","QUEUE"),HLMSTATE("IEN")) 193 Q HLMSTATE("IEN") 194 ; 195 DONTSEND(HLMSTATE,ERROR) ; 196 ;This procedure does NOT send a message. Rather, it creates an entry in file 778 with the 197 ;of "SE". 198 ;Input: 199 ; HLMSTATE - pass-by-reference 200 ; ERROR (optional, pass-by-value) error text to store with the message 201 ;Output: none 202 ; 203 I HLMSTATE("UNSTORED LINES"),'$$SAVEMSG^HLOF777(.HLMSTATE) ; just continue 204 ; 205 S HLMSTATE("STATUS")="SE" 206 S HLMSTATE("STATUS","PURGE")=$$FMADD^XLFDT(HLMSTATE("DT/TM CREATED"),HLMSTATE("SYSTEM","ERROR PURGE")) 207 S HLMSTATE("STATUS","ERROR TEXT")=$G(ERROR) 208 I '$$SAVEMSG^HLOF778(.HLMSTATE) ;already reported an error to the app 209 Q 210 ; 211 CHKWHO(HLMSTATE,WHOTO,ERROR) ; 212 N RETURN,I 213 S RETURN=1 214 I '$$CHECKWHO^HLOASUB1(.WHOTO,.RETURN,.ERROR) S RETURN=0 215 ; 216 ;move parameters into HLMSTATE 217 S HLMSTATE("STATUS","LINK IEN")=$G(RETURN("LINK IEN")) 218 S HLMSTATE("STATUS","LINK NAME")=$G(RETURN("LINK NAME")) 219 S HLMSTATE("STATUS","PORT")=$P($G(RETURN("RECEIVING FACILITY",2)),":",2) 220 S HLMSTATE("HDR","RECEIVING APPLICATION")=$G(RETURN("RECEIVING APPLICATION")) 221 F I=1:1:3 S HLMSTATE("HDR","RECEIVING FACILITY",I)=$G(RETURN("RECEIVING FACILITY",I)) 222 Q RETURN -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOAPI2.m
r613 r623 1 HLOAPI2 ;ALB/CJM-HL7 - Developer API's for sending application acks ;07/30/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,131,133,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ACK(HLMSTATE,PARMS,ACK,ERROR) ;Default behavior is to return a general 6 ;application ack. The application may optionally specify the message 7 ;type and event or call $$ADDSEG^HLOAPI to add segments. 8 ;A generic MSA segment (components 1-3) is added automatically IF the 9 ;application doesn't call $$ADDSEG^HLOAPI to add an MSA segment as the 10 ;FIRST segment following the header. 11 ;$$SENDACK must be called when the ack is completed. The return 12 ;destination is determined automatically from the original message 13 ; 14 ;This API should NOT be called for batch messages, use $$BATCHACK instead. 15 ;Input: 16 ; HLMSTATE (pass by reference, required) the array obtained by calling $$STARTMSG^HLOPRS when parsing the original message 17 ; PARMS (pass by reference) These subscripts may be defined: 18 ; "ACK CODE" (required) MSA1[ {AA,AE,AR} 19 ; "ERROR MESSAGE" - MSA3, should be used only if AE or AR 20 ; "ACCEPT ACK RESPONSE" - the <tag^routine> to call when the commit ack is received (optional) 21 ; "ACCEPT ACK TYPE" - {AL,NE} (optional, defaults to AL) 22 ; "CONTINUATION POINTER" (optional)indicates a fragmented message 23 ; "COUNTRY" - the 3 character country code (optional) 24 ; "EVENT" - the 3 character event type (optional, defaults to the event code of the original message) 25 ; "ENCODING CHARACTERS" - the four HL7 encoding characters (optional,defaults to "^~\&" 26 ; "FAILURE RESPONSE" (optional) the <tag>^<routine> that the sending application routine should execute if the transmission of the message fails, i.e., the message can not be sent or a requested commit ack is not received. 27 ; "FIELD SEPARATOR" - field separator (optional, defaults to "|") 28 ; "MESSAGE TYPE" - if not defined, ACK is used 29 ; "MESSAGE STRUCTURE" (optional) 30 ; "QUEUE" - (optional) An application can name its own private queue (a string under 20 characters,namespaced). The default is the name of the queue of the original message 31 ; "SECURITY" (optional) security information to include in the header segment, SEQ 8 (optional) 32 ; "VERSION" - the HL7 Version ID (optional, defaults to 2.4) 33 ;Output: 34 ; Function returns 1 on success, 0 on failure 35 ; PARMS - left undefined when the function returns 36 ; ACK (pass by reference, required) the acknowledgment message being built. 37 ; ERROR (pass by reference) error msg 38 N I,SEG,TOLINK,SUCCESS 39 S SUCCESS=0,ERROR="" 40 ; 41 D 42 .N PORT 43 .I $G(PARMS("ACK CODE"))'="AA",$G(PARMS("ACK CODE"))'="AE",$G(PARMS("ACK CODE"))'="AR" S ERROR="INVALID ACK CODE" Q 44 .; 45 .I '$G(HLMSTATE("IEN")) S ERROR="ORIGINAL MESSAGE TO ACKNOWLEDGE IS NOT IDENTIFIED" Q 46 .I $G(HLMSTATE("BATCH")) S ERROR="BATCH ACKNOWLEDGMENTS MUST USE $$BATCHACK^HLOAPI3" Q 47 .; 48 .I $G(HLMSTATE("HDR","MESSAGE CONTROL ID"))="" S ERROR="MESSAGE CONTROL ID MUST EXIST TO RETURN AN APPLICATION ACK" Q 49 .S PARMS("MESSAGE TYPE")=$G(PARMS("MESSAGE TYPE"),"ACK") 50 .S:PARMS("MESSAGE TYPE")="ACK" PARMS("MESSAGE STRUCTURE")="ACK" 51 .S PARMS("EVENT")=$G(PARMS("EVENT"),$G(HLMSTATE("HDR","EVENT"))) 52 .I $$NEWMSG^HLOAPI(.PARMS,.ACK) ;can't fail! 53 .; 54 .;if the return link can not be determined, the HL Logical Link file has a problem that must be fixed at the site 55 .S PORT=$P(HLMSTATE("HDR","SENDING FACILITY",2),":",2) 56 .S TOLINK=$$ACKLINK(.HLMSTATE) 57 .I TOLINK="" S ERROR="TRANSMISSION LINK FOR APPLICATION ACK CANNOT BE DETERMINED" Q 58 .I 'PORT S PORT=$$PORT2^HLOTLNK(TOLINK) 59 .; 60 .S ACK("HDR","APP ACK TYPE")="NE" 61 .S ACK("HDR","ACCEPT ACK TYPE")=$G(PARMS("ACCEPT ACK TYPE"),"AL") 62 .S ACK("STATUS","QUEUE")=$G(PARMS("QUEUE"),$G(HLMSTATE("STATUS","QUEUE"))) 63 .S ACK("STATUS","PORT")=PORT 64 .S ACK("HDR","SECURITY")=$G(PARMS("SECURITY")) 65 .S ACK("HDR","SENDING APPLICATION")=$G(HLMSTATE("HDR","RECEIVING APPLICATION")) 66 .S ACK("HDR","RECEIVING APPLICATION")=$G(HLMSTATE("HDR","SENDING APPLICATION")) 67 .F I=1:1:3 S ACK("HDR","RECEIVING FACILITY",I)=$G(HLMSTATE("HDR","SENDING FACILITY",I)) 68 .S ACK("ACK TO","STATUS")=$S(PARMS("ACK CODE")="AA":"SU",1:"ER") 69 .S ACK("ACK TO")=$G(HLMSTATE("HDR","MESSAGE CONTROL ID")) 70 .S ACK("ACK TO","IEN")=HLMSTATE("IEN") 71 .S ACK("STATUS","LINK NAME")=TOLINK 72 .S ACK("LINE COUNT")=0 73 .S ACK("MSA")="MSA"_ACK("HDR","FIELD SEPARATOR")_PARMS("ACK CODE")_ACK("HDR","FIELD SEPARATOR")_$G(HLMSTATE("HDR","MESSAGE CONTROL ID"))_ACK("HDR","FIELD SEPARATOR")_$G(PARMS("ERROR MESSAGE")) 74 .S SUCCESS=1 75 K PARMS 76 K:'SUCCESS ACK 77 Q SUCCESS 78 ; 79 SENDACK(ACK,ERROR) ;This is used to signal that an application acknowledgment is complete. 80 ;Input: 81 ; ACK (pass by reference,required) An array that contains the acknowledgment msg 82 ;Output: 83 ; Function returns 1 on success, 0 on failure 84 ; ERROR (pass by reference) error msg 85 ; 86 N SEG 87 ;if the application added its own MSA, then the ACK("MSA") node was killed 88 I $D(ACK("MSA")) S SEG(1)=ACK("MSA") D ADDSEG^HLOMSG(.ACK,.SEG) 89 ; 90 I $$SEND^HLOAPI1(.ACK,.ERROR) Q 1 91 Q 0 92 ; 93 ACKLINK(HLMSTATE) ; 94 ;Finds the link to return the application ack to. 95 N LINK 96 S LINK=$$RTRNLNK^HLOAPP($G(HLMSTATE("HDR","RECEIVING APPLICATION"))) 97 Q:LINK]"" LINK 98 S LINK=$$RTRNLNK^HLOTLNK($G(HLMSTATE("HDR","SENDING FACILITY",1)),$G(HLMSTATE("HDR","SENDING FACILITY",2)),$G(HLMSTATE("HDR","SENDING FACILITY",3))) 99 Q LINK 100 ; 101 CHKPARMS(HLMSTATE,PARMS,ERROR) ; 102 N LEN,SARY,HARY 103 ; 104 ;shortcut to reference the header sub-array 105 S HARY="HLMSTATE(""HDR"")" 106 ; 107 ;shortcut to reference the status sub-array 108 S SARY="HLMSTATE(""STATUS"")" 109 ; 110 S ERROR="" 111 I $G(PARMS("ACCEPT ACK TYPE"))="" S PARMS("ACCEPT ACK TYPE")="AL" 112 I $G(PARMS("APP ACK TYPE"))="" S PARMS("APP ACK TYPE")="NE" 113 I PARMS("ACCEPT ACK TYPE")'="NE",PARMS("ACCEPT ACK TYPE")'="AL" S ERROR="INVALID ACCEPT ACKNOWLEDGMENT TYPE" 114 I PARMS("APP ACK TYPE")'="NE",PARMS("APP ACK TYPE")'="AL" S ERROR="INVALID APPLICATION ACKNOWLEDGMENT TYPE" 115 S LEN=$L($G(PARMS("QUEUE"))) 116 I $G(PARMS("QUEUE"))["^" S ERROR="QUEUE NAME MAY NOT CONTAIN '^'" 117 I LEN>20 S ERROR="QUEUE PARAMETER IS MAX 20 LENGTH",PARMS("QUEUE")=$E(PARMS("QUEUE"),1,20) 118 I 'LEN S PARMS("QUEUE")="DEFAULT" 119 D 120 .N APPIEN 121 .I $G(PARMS("SENDING APPLICATION"))="" D Q 122 ..S ERROR="SENDING APPLICATION IS REQUIRED" 123 ..S PARMS("SENDING APPLICATION")="" 124 .E D Q:'APPIEN 125 ..S APPIEN=$$GETIEN^HLOAPP(PARMS("SENDING APPLICATION")) 126 ..I 'APPIEN S ERROR="SENDING APPLICATION NOT FOUND IN THE HLO APPLICATION REGISTRY" 127 .I $L($G(PARMS("SEQUENCE QUEUE"))) D 128 ..I ($L(PARMS("SEQUENCE QUEUE"))>30) S ERROR="SEQUENCE QUEUE NAME > 30 CHARACTERS" Q 129 ..I PARMS("SEQUENCE QUEUE")["^" S ERROR="SEQUENCE QUEUE NAME MAY NOT CONTAIN '^'" Q 130 ..I $G(PARMS("APP ACK TYPE"))'="AL" S ERROR="SEQUENCE QUEUES REQUIRE AN APPLICATION ACKNOWLEDGMENT" Q 131 ..I $G(PARMS("ACCEPT ACK TYPE"))'="AL" S ERROR="SEQUENCE QUEUES REQUIRE AN ACCEPT ACKNOWLEDGMENT" Q 132 ; 133 ;move parameters into HLMSTATE 134 S @HARY@("ACCEPT ACK TYPE")=PARMS("ACCEPT ACK TYPE") 135 S @HARY@("APP ACK TYPE")=PARMS("APP ACK TYPE") 136 S @HARY@("SENDING APPLICATION")=$E(PARMS("SENDING APPLICATION"),1,60) 137 S @HARY@("SECURITY")=$G(PARMS("SECURITY")) 138 S @SARY@("APP ACK RESPONSE")=$G(PARMS("APP ACK RESPONSE")) 139 S @SARY@("ACCEPT ACK RESPONSE")=$G(PARMS("ACCEPT ACK RESPONSE")) 140 S @SARY@("FAILURE RESPONSE")=$G(PARMS("FAILURE RESPONSE")) 141 S @SARY@("QUEUE")=PARMS("QUEUE") 142 S @SARY@("SEQUENCE QUEUE")=$G(PARMS("SEQUENCE QUEUE")) 143 Q:$L(ERROR) 0 144 Q 1 145 ; 146 ; 147 SETCODE(SEG,VALUE,FIELD,COMP,REP) ; 148 ;Implements SETCNE and SETCWE 149 ; 150 N SUB,VAR 151 Q:'$G(FIELD) 152 S:'$G(REP) REP=1 153 I '$G(COMP) D 154 .S VAR="COMP",SUB=1 155 E D 156 .S VAR="SUB" 157 S @VAR=1,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("ID")) 158 S @VAR=2,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("TEXT")) 159 S @VAR=3,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("SYSTEM")) 160 S @VAR=4,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("ALTERNATE ID")) 161 S @VAR=5,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("ALTERNATE TEXT")) 162 S @VAR=6,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("ALTERNATE SYSTEM")) 163 S @VAR=7,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("SYSTEM VERSION")) 164 S @VAR=8,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("ALTERNATE SYSTEM VERSION")) 165 S @VAR=9,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("ORIGINAL TEXT")) 166 Q 167 ; 168 CHKWHO(HLMSTATE,WHOTO,ERROR) ; 169 N RETURN,I 170 S RETURN=1 171 I '$$CHECKWHO^HLOASUB1(.WHOTO,.RETURN,.ERROR) S RETURN=0 172 ; 173 ;move parameters into HLMSTATE 174 S HLMSTATE("STATUS","LINK IEN")=$G(RETURN("LINK IEN")) 175 S HLMSTATE("STATUS","LINK NAME")=$G(RETURN("LINK NAME")) 176 S HLMSTATE("STATUS","PORT")=$P($G(RETURN("RECEIVING FACILITY",2)),":",2) 177 S HLMSTATE("HDR","RECEIVING APPLICATION")=$G(RETURN("RECEIVING APPLICATION")) 178 F I=1:1:3 S HLMSTATE("HDR","RECEIVING FACILITY",I)=$G(RETURN("RECEIVING FACILITY",I)) 179 Q RETURN 1 HLOAPI2 ;ALB/CJM-HL7 - Developer API's for sending application acks ;12/11/2006 2 ;;1.6;HEALTH LEVEL SEVEN;**126,131,133,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ACK(HLMSTATE,PARMS,ACK,ERROR) ;Default behavior is to return a general 6 ;application ack. The application may optionally specify the message 7 ;type and event or call $$ADDSEG^HLOAPI to add segments. 8 ;A generic MSA segment (components 1-3) is added automatically IF the 9 ;application doesn't call $$ADDSEG^HLOAPI to add an MSA segment as the 10 ;FIRST segment following the header. 11 ;$$SENDACK must be called when the ack is completed. The return 12 ;destination is determined automatically from the original message 13 ; 14 ;This API should NOT be called for batch messages, use $$BATCHACK instead. 15 ;Input: 16 ; HLMSTATE (pass by reference, required) the array obtained by calling $$STARTMSG^HLOPRS when parsing the original message 17 ; PARMS (pass by reference) These subscripts may be defined: 18 ; "ACK CODE" (required) MSA1[ {AA,AE,AR} 19 ; "ERROR MESSAGE" - MSA3, should be used only if AE or AR 20 ; "ACCEPT ACK RESPONSE" - the <tag^routine> to call when the commit ack is received (optional) 21 ; "ACCEPT ACK TYPE" - {AL,NE} (optional, defaults to AL) 22 ; "CONTINUATION POINTER" (optional)indicates a fragmented message 23 ; "COUNTRY" - the 3 character country code (optional) 24 ; "EVENT" - the 3 character event type (optional, defaults to the event code of the original message) 25 ; "ENCODING CHARACTERS" - the four HL7 encoding characters (optional,defaults to "^~\&" 26 ; "FAILURE RESPONSE" (optional) the <tag>^<routine> that the sending application routine should execute if the transmission of the message fails, i.e., the message can not be sent or a requested commit ack is not received. 27 ; "FIELD SEPARATOR" - field separator (optional, defaults to "|") 28 ; "MESSAGE TYPE" - if not defined, ACK is used 29 ; "MESSAGE STRUCTURE" (optional) 30 ; "QUEUE" - (optional) An application can name its own private queue (a string under 20 characters,namespaced). The default is the name of the queue of the original message 31 ; "SECURITY" (optional) security information to include in the header segment, SEQ 8 (optional) 32 ; "VERSION" - the HL7 Version ID (optional, defaults to 2.4) 33 ;Output: 34 ; Function returns 1 on success, 0 on failure 35 ; PARMS - left undefined when the function returns 36 ; ACK (pass by reference, required) the acknowledgment message being built. 37 ; ERROR (pass by reference) error msg 38 N I,SEG,TOLINK,SUCCESS 39 S SUCCESS=0,ERROR="" 40 ; 41 D 42 .N PORT 43 .I $G(PARMS("ACK CODE"))'="AA",$G(PARMS("ACK CODE"))'="AE",$G(PARMS("ACK CODE"))'="AR" S ERROR="INVALID ACK CODE" Q 44 .; 45 .I '$G(HLMSTATE("IEN")) S ERROR="ORIGINAL MESSAGE TO ACKNOWLEDGE IS NOT IDENTIFIED" Q 46 .I $G(HLMSTATE("BATCH")) S ERROR="BATCH ACKNOWLEDGMENTS MUST USE $$BATCHACK^HLOAPI3" Q 47 .; 48 .I $G(HLMSTATE("HDR","MESSAGE CONTROL ID"))="" S ERROR="MESSAGE CONTROL ID MUST EXIST TO RETURN AN APPLICATION ACK" Q 49 .S PARMS("MESSAGE TYPE")=$G(PARMS("MESSAGE TYPE"),"ACK") 50 .S:PARMS("MESSAGE TYPE")="ACK" PARMS("MESSAGE STRUCTURE")="ACK" 51 .S PARMS("EVENT")=$G(PARMS("EVENT"),$G(HLMSTATE("HDR","EVENT"))) 52 .I $$NEWMSG^HLOAPI(.PARMS,.ACK) ;can't fail! 53 .; 54 .;if the return link can not be determined, the HL Logical Link file has a problem that must be fixed at the site 55 .S PORT=$P(HLMSTATE("HDR","SENDING FACILITY",2),":",2) 56 .S TOLINK=$$ACKLINK(.HLMSTATE) 57 .I TOLINK="" S ERROR="TRANSMISSION LINK FOR APPLICATION ACK CANNOT BE DETERMINED" Q 58 .I 'PORT S PORT=$$PORT2^HLOTLNK(TOLINK) 59 .; 60 .S ACK("HDR","APP ACK TYPE")="NE" 61 .S ACK("HDR","ACCEPT ACK TYPE")=$G(PARMS("ACCEPT ACK TYPE"),"AL") 62 .S ACK("STATUS","QUEUE")=$G(PARMS("QUEUE"),$G(HLMSTATE("STATUS","QUEUE"))) 63 .S ACK("STATUS","PORT")=PORT 64 .S ACK("HDR","SECURITY")=$G(PARMS("SECURITY")) 65 .S ACK("HDR","SENDING APPLICATION")=$G(HLMSTATE("HDR","RECEIVING APPLICATION")) 66 .S ACK("HDR","RECEIVING APPLICATION")=$G(HLMSTATE("HDR","SENDING APPLICATION")) 67 .F I=1:1:3 S ACK("HDR","RECEIVING FACILITY",I)=$G(HLMSTATE("HDR","SENDING FACILITY",I)) 68 .S ACK("ACK TO","STATUS")=$S(PARMS("ACK CODE")="AA":"SU",1:"AE") 69 .S ACK("ACK TO")=$G(HLMSTATE("HDR","MESSAGE CONTROL ID")) 70 .S ACK("ACK TO","IEN")=HLMSTATE("IEN") 71 .S ACK("STATUS","LINK NAME")=TOLINK 72 .S ACK("LINE COUNT")=0 73 .S ACK("MSA")="MSA"_ACK("HDR","FIELD SEPARATOR")_PARMS("ACK CODE")_ACK("HDR","FIELD SEPARATOR")_$G(HLMSTATE("HDR","MESSAGE CONTROL ID"))_ACK("HDR","FIELD SEPARATOR")_$G(PARMS("ERROR MESSAGE")) 74 .S SUCCESS=1 75 K PARMS 76 K:'SUCCESS ACK 77 Q SUCCESS 78 ; 79 SENDACK(ACK,ERROR) ;This is used to signal that an application acknowledgment is complete. 80 ;Input: 81 ; ACK (pass by reference,required) An array that contains the acknowledgment msg 82 ;Output: 83 ; Function returns 1 on success, 0 on failure 84 ; ERROR (pass by reference) error msg 85 ; 86 N SEG 87 ;if the application added its own MSA, then the ACK("MSA") node was killed 88 I $D(ACK("MSA")) S SEG(1)=ACK("MSA") D ADDSEG^HLOMSG(.ACK,.SEG) 89 ; 90 I $$SEND^HLOAPI1(.ACK,.ERROR) Q 1 91 Q 0 92 ; 93 ACKLINK(HLMSTATE) ; 94 ;Finds the link to return the application ack to. 95 N LINK 96 S LINK=$$RTRNLNK^HLOAPP($G(HLMSTATE("HDR","RECEIVING APPLICATION"))) 97 Q:LINK]"" LINK 98 S LINK=$$RTRNLNK^HLOTLNK($G(HLMSTATE("HDR","SENDING FACILITY",1)),$G(HLMSTATE("HDR","SENDING FACILITY",2)),$G(HLMSTATE("HDR","SENDING FACILITY",3))) 99 Q LINK 100 ; 101 CHKPARMS(HLMSTATE,PARMS,ERROR) ; 102 N LEN,SARY,HARY 103 ; 104 ;shortcut to reference the header sub-array 105 S HARY="HLMSTATE(""HDR"")" 106 ; 107 ;shortcut to reference the status sub-array 108 S SARY="HLMSTATE(""STATUS"")" 109 ; 110 S ERROR="" 111 I $G(PARMS("ACCEPT ACK TYPE"))="" S PARMS("ACCEPT ACK TYPE")="AL" 112 I $G(PARMS("APP ACK TYPE"))="" S PARMS("APP ACK TYPE")="NE" 113 I PARMS("ACCEPT ACK TYPE")'="NE",PARMS("ACCEPT ACK TYPE")'="AL" S ERROR="INVALID ACCEPT ACKNOWLEDGMENT TYPE" 114 I PARMS("APP ACK TYPE")'="NE",PARMS("APP ACK TYPE")'="AL" S ERROR="INVALID APPLICATION ACKNOWLEDGMENT TYPE" 115 S LEN=$L($G(PARMS("QUEUE"))) 116 I $G(PARMS("QUEUE"))["^" S ERROR="QUEUE NAME MAY NOT CONTAIN '^'" 117 I LEN>20 S ERROR="QUEUE PARAMETER IS MAX 20 LENGTH",PARMS("QUEUE")=$E(PARMS("QUEUE"),1,20) 118 I 'LEN S PARMS("QUEUE")="DEFAULT" 119 I $G(PARMS("SENDING APPLICATION"))="" D 120 .S ERROR="SENDING APPLICATION IS REQUIRED" 121 .S PARMS("SENDING APPLICATION")="" 122 E D 123 .I '$D(^HLD(779.2,"C",PARMS("SENDING APPLICATION"))) S ERROR="SENDING APPLICATION NOT FOUND IN THE HLO APPLICATION REGISTRY" 124 ; 125 ;move parameters into HLMSTATE 126 S @HARY@("ACCEPT ACK TYPE")=PARMS("ACCEPT ACK TYPE") 127 S @HARY@("APP ACK TYPE")=PARMS("APP ACK TYPE") 128 S @HARY@("SENDING APPLICATION")=$E(PARMS("SENDING APPLICATION"),1,60) 129 S @HARY@("SECURITY")=$G(PARMS("SECURITY")) 130 S @SARY@("APP ACK RESPONSE")=$G(PARMS("APP ACK RESPONSE")) 131 S @SARY@("ACCEPT ACK RESPONSE")=$G(PARMS("ACCEPT ACK RESPONSE")) 132 S @SARY@("FAILURE RESPONSE")=$G(PARMS("FAILURE RESPONSE")) 133 S @SARY@("QUEUE")=PARMS("QUEUE") 134 Q:$L(ERROR) 0 135 Q 1 136 ; 137 SETCODE(SEG,VALUE,FIELD,COMP,REP) ; 138 ;Implements SETCNE and SETCWE 139 ; 140 N SUB,VAR 141 Q:'$G(FIELD) 142 S:'$G(REP) REP=1 143 I '$G(COMP) D 144 .S VAR="COMP",SUB=1 145 E D 146 .S VAR="SUB" 147 S @VAR=1,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("ID")) 148 S @VAR=2,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("TEXT")) 149 S @VAR=3,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("SYSTEM")) 150 S @VAR=4,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("ALTERNATE ID")) 151 S @VAR=5,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("ALTERNATE TEXT")) 152 S @VAR=6,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("ALTERNATE SYSTEM")) 153 S @VAR=7,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("SYSTEM VERSION")) 154 S @VAR=8,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("ALTERNATE SYSTEM VERSION")) 155 S @VAR=9,SEG(FIELD,REP,COMP,SUB)=$G(VALUE("ORIGINAL TEXT")) 156 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOAPI3.m
r613 r623 1 HLOAPI3 ;ALB/CJM-HL7 - Developer API's for sending application acks ;07/10/20072 ;;1.6;HEALTH LEVEL SEVEN;**126,133,134,137**;Oct 13, 1995;Build 21 3 4 5 BATCHACK(HLMSTATE,PARMS,ACK,ERROR) 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 ADDACK(ACK,PARMS,ERROR) 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 .S PARMS("ACK TO","STATUS")=$S(PARMS("ACK CODE")="AA":"SU",1:"ER")95 96 97 98 99 100 101 RESEND(MSGIEN,ERROR) 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 SETPURGE(MSGIEN,TIME) 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 REPROC(MSGIEN,ERROR) 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 PROCNOW(MSGIEN,PURGE,ERROR) 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 1 HLOAPI3 ;ALB/CJM-HL7 - Developer API's for sending application acks ;03/13/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,133,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 BATCHACK(HLMSTATE,PARMS,ACK,ERROR) ;Starts a batch message that is the response to a batch message. Individual acks are placed in the batch by calling $$ADDACK. 6 ;$$SENDACK^HLOAPI2 must be called when the batch of acks is complete. The return destination is determined automatically from the original message. 7 ; 8 ;Input: 9 ; HLMSTATE (pass by reference, required) the array obtained by calling $$STARTMSG^HLOPRS when parsing the original message 10 ; PARMS (optional, pass by reference) These subscripts may be defined: 11 ; "ACCEPT ACK RESPONSE")=<tag^routine> to call when the commit ack is received (optional) 12 ; "ACCEPT ACK TYPE") = <AL,NE> (optional, defaults to AL) 13 ; "COUNTRY") - a 3 character country code from the HL7 standard table (optional) 14 ; "ENCODING CHARACTERS" - the 4 HL7 encoding characters (optional,defaults to "^~\&" 15 ; "FAILURE RESPONSE" (optional) the <tag>^<routine> that the sending application routine should execute if the transmission of the message fails, i.e., the message can not be sent or a requested commit ack is not received. 16 ; "FIELD SEPARATOR" - the field separator (optional, defaults to "|") 17 ; "QUEUE" (optional) An application can name a private queue (a string under 20 characters, namespaced). The default is the name of the queue of the original message 18 ; "SECURITY" - security information to include in the header segment, SEQ 8 (optional) 19 ; "VERSION" - the HL7 Version ID (optional, defaults to 2.4) 20 ;Output: 21 ; Function returns 1 on success, 0 on failure 22 ; PARMS - left undefined upon completion 23 ; ACK (pass by reference, required) the batch acknowledgment message being built. 24 ; ERROR (pass by reference) error message 25 N I,TOLINK,SUCCESS 26 S SUCCESS=0 27 ; 28 D 29 .N PORT 30 .I '$G(HLMSTATE("IEN")) S ERROR="ORIGINAL MESSAGE TO ACKNOWLEDGMENT IS NOT IDENTIFIED" Q 31 .;if the return link can not be determined, the HL Logical Link file has a problem 32 .S TOLINK=$$ACKLINK^HLOAPI2(.HLMSTATE) 33 .I TOLINK="" S ERROR="TRANSMISSION LINK FOR APPLICATION ACK CANNOT BE DETERMINED" Q 34 .S PORT=$P(HLMSTATE("HDR","SENDING FACILITY",2),":",2) 35 .I 'PORT S PORT=$$PORT2^HLOTLNK(TOLINK) 36 .; 37 .I $$NEWBATCH^HLOAPI(.PARMS,.ACK) ;can't fail! 38 .S ACK("STATUS","QUEUE")=$G(PARMS("QUEUE"),$G(HLMSTATE("STATUS","QUEUE"))) 39 .S ACK("STATUS","PORT")=PORT 40 .S ACK("HDR","SECURITY")=$G(PARMS("SECURITY")) 41 .S ACK("HDR","SENDING APPLICATION")=$G(HLMSTATE("HDR","RECEIVING APPLICATION")) 42 .S ACK("HDR","RECEIVING APPLICATION")=$G(HLMSTATE("HDR","SENDING APPLICATION")) 43 .F I=1:1:3 S ACK("HDR","RECEIVING FACILITY",I)=$G(HLMSTATE("HDR","SENDING FACILITY",I)) 44 .S ACK("HDR","APP ACK TYPE")="NE" 45 .S ACK("HDR","ACCEPT ACK TYPE")=$G(PARMS("ACCEPT ACK TYPE"),"AL") 46 .S ACK("ACK TO")=$G(HLMSTATE("HDR","BATCH CONTROL ID")) 47 .S ACK("ACK TO","IEN")=HLMSTATE("IEN") 48 .S ACK("ACK TO","BODY")=$G(HLMSTATE("BODY")) 49 .S ACK("STATUS","LINK NAME")=TOLINK 50 .S ACK("LINE COUNT")=0 51 .S SUCCESS=1 52 K PARMS 53 Q SUCCESS 54 ; 55 ADDACK(ACK,PARMS,ERROR) ;This API adds an application acknowledgment to a batch 56 ;of acknowledgments that was started by calling $$BATCHACK. 57 ;The Default behavior is to return a general application ack. 58 ;The application may optionally specify the message 59 ;type and event and/or call $$ADDSEG^HLOAPI to add segments. 60 ;A generic MSA segment (components 1-3) will be added automatically 61 ;if the application doesn't call $$ADDSEG^HLOAPI to add an MSA segment 62 ;as the FIRST segment following the MSH segment. 63 ;$$SENDACK^HLOAPI2 must be called when the batch is complete. 64 ; 65 ;Input: 66 ; ACK (pass by reference,required) the batch of acks that is being built 67 ; PARMS (pass by reference) These subscripts may be defined: 68 ; "ACK CODE" (required) MSA1[ {AA,AE,AR} 69 ; "ERROR MESSAGE" (optional) MSA3, should be used only if AE or AR 70 ; "EVENT" - 3 character event type (optional, defaults to the event code of the original message) 71 ; "MESSAGE CONTROL ID" (required) this is the message control id of the original individual message within the batch which is being acknowledged 72 ; "MESSAGE STRUCTURE" (optional) 73 ; "MESSAGE TYPE" (optional, defaults to ACK) 74 ; "SECURITY" (optional) security information to include in the header segment SEQ 8 75 ;Output: 76 ; Function returns 1 on success, 0 on failure 77 ; ACK (pass by reference, required) The batch, updated with another ack 78 ; PARMS - left undefined when this function returns 79 ; ERROR (pass by reference) error msg 80 ; 81 N SUB,SUCCESS 82 S SUCCESS=0 83 D 84 .I $G(PARMS("ACK CODE"))'="AA",$G(PARMS("ACK CODE"))'="AE",$G(PARMS("ACK CODE"))'="AR" S ERROR="INVALID ACK CODE" Q 85 .; 86 .I $G(PARMS("MESSAGE CONTROL ID"))="" S ERROR="MESSAGE CONTROL ID MUST EXIST TO RETURN AN APPLICATION ACK" Q 87 .S SUB="" 88 .F S SUB=$O(^HLB("AE",PARMS("MESSAGE CONTROL ID"),SUB)) Q:SUB="" I $P(SUB,"^")=ACK("ACK TO","IEN"),$P(SUB,"^",2) S PARMS("ACK TO","IEN")=SUB Q 89 .S PARMS("MESSAGE TYPE")=$G(PARMS("MESSAGE TYPE"),"ACK") 90 .S:PARMS("MESSAGE TYPE")="ACK" PARMS("MESSAGE STRUCTURE")="ACK" 91 .S PARMS("EVENT")=$G(PARMS("EVENT")) 92 .I PARMS("EVENT")="",ACK("ACK TO","BODY"),$P(SUB,"^",2) S PARMS("EVENT")=$P($G(^HLA(ACK("ACK TO","BODY"),2,$P(SUB,"^",2),0)),"^",3) 93 .S PARMS("ACK TO")=PARMS("MESSAGE CONTROL ID") 94 .S PARMS("ACK TO","STATUS")=$S(PARMS("ACK CODE")="AA":"SU",1:"AE") 95 .Q:'$$ADDMSG^HLOAPI(.ACK,.PARMS,.ERROR) 96 .S ACK("MSA")="MSA|"_PARMS("ACK CODE")_"|"_PARMS("MESSAGE CONTROL ID")_"|"_$G(PARMS("ERROR MESSAGE")) 97 .S SUCCESS=1 98 K PARMS 99 Q SUCCESS 100 ; 101 RESEND(MSGIEN,ERROR) ; 102 ;This message will re-transmit an out-going message. It copies a copy the message, reusing all the original parameters. Then the message is requeued. 103 ; 104 ;Input: 105 ; MSGIEN - the ien (file #778) of the message that is to be sent 106 ;Output: 107 ; Function returns the ien of the message in file 778 on success, 0 on failure 108 ; ERROR (pass by reference, optional)an error message 109 ; 110 N MSG,SUB,HDR 111 I '$$STARTMSG^HLOPRS(.MSG,MSGIEN) S ERROR="MESSAGE NOT FOUND" Q 0 112 I MSG("DIRECTION")'="OUT" S ERROR="MESSAGE IS NOT OUTGOING" Q 0 113 I MSG("STATUS","LINK NAME")="" S ERROR="LINK NOT DEFINED" Q 0 114 F SUB="ID","IEN","DT/TM","ACK BY","STATUS" S MSG(SUB)="" 115 F SUB="PURGE" K MSG("STATUS",SUB) 116 D GETSYS^HLOAPI(.MSG) 117 I $$SAVEMSG^HLOF778(.MSG) D OUTQUE^HLOQUE(MSG("STATUS","LINK NAME"),$G(MSG("STATUS","PORT")),MSG("STATUS","QUEUE"),MSG("IEN")) Q +MSG("IEN") 118 Q 0 119 ; 120 SETPURGE(MSGIEN,TIME) ; 121 ;Resets the purge date/time. 122 ;Input: 123 ; MSGIEN (required) ien of the message, file #778 124 ; TIME (optional) dt/time to set the purge time to, defaults to NOW 125 ;Output: 126 ; Function returns 1 on success, 0 on failure 127 N NODE,OLDTIME,HLDIR 128 Q:'$G(MSGIEN) 0 129 S NODE=$G(^HLB(MSGIEN,0)) 130 Q:NODE="" 0 131 S OLDTIME=$P(NODE,"^",9) 132 S:'$G(TIME) TIME=$$NOW^XLFDT 133 S HLDIR=$S($E($P(NODE,"^",4))="I":"IN",1:"OUT") 134 K:OLDTIME ^HLB("AD",HLDIR,OLDTIME,MSGIEN) 135 S $P(^HLB(MSGIEN,0),"^",9)=TIME 136 S ^HLB("AD",HLDIR,TIME,MSGIEN)="" 137 Q 1 138 ; 139 REPROC(MSGIEN,ERROR) ; 140 ;This message will re-process an incoming message by placing it on an incoming queue. If successful the message will be purged. 141 ; 142 ;Input: 143 ; MSGIEN - the ien (file #778) of the message that is to be processed 144 ;Output: 145 ; Function returns 1 on success, 0 on failure 146 ; ERROR (pass by reference, optional) an error message 147 ; 148 N MSG,HDR,ACTION,QUEUE,FROM 149 ; 150 I '$$STARTMSG^HLOPRS(.MSG,MSGIEN) S ERROR="MESSAGE NOT FOUND" Q 0 151 I MSG("DIRECTION")'="IN" S ERROR="MESSAGE IS NOT INCOMING" Q 0 152 M HDR=MSG("HDR") 153 I $G(MSG("ACK TO"))]"" S ACTION=MSG("STATUS","APP ACK RESPONSE") 154 I ACTION="",'$$ACTION^HLOAPP(.HDR,.ACTION,.QUEUE),$G(MSG("ACK TO"))="" S ERROR="RECEIVING APPLICATION NOT DEFINED" 155 ;If this message references an earlier message, get the action specified by the original message 156 I ACTION="",$G(MSG("ACK TO"))]"" D 157 .N NODE,IEN 158 .S IEN=$O(^HLB("B",$P(MSG("ACK TO"),"-"),0)) 159 .S:IEN NODE=$G(^HLB(IEN,0)) 160 .I ($P(NODE,"^",11)]"") S ACTION=$P(NODE,"^",10,11),QUEUE=$S($P(NODE,"^",6)]"":$P(NODE,"^",6),1:"DEFAULT") 161 I ACTION="" S ERROR="ORIGINAL MESSAGE NOT FOUND" Q 0 162 S FROM=$S(MSG("HDR","SENDING FACILITY",2)]"":MSG("HDR","SENDING FACILITY",2),1:MSG("HDR","SENDING FACILITY",1)) 163 D INQUE^HLOQUE(FROM,QUEUE,MSGIEN,ACTION,1) 164 Q 1 165 ; 166 PROCNOW(MSGIEN,PURGE,ERROR) ; 167 ;This message will re-process an incoming message immediately. 168 ; 169 ;Input: 170 ; MSGIEN - the ien (file #778) of the message that is to be processed 171 ;Output: 172 ; Function returns 1 on success, 0 on failure 173 ; PURGE (optional) a date/time to purge the message 174 ; ERROR (pass by reference, optional) an error message 175 ; 176 N MSG,HDR,ACTION,MCODE,HLMSGIEN 177 ; 178 S ERROR="" 179 I '$$STARTMSG^HLOPRS(.MSG,MSGIEN) S ERROR="MESSAGE NOT FOUND" Q 0 180 I MSG("DIRECTION")'="IN" S ERROR="MESSAGE IS NOT INCOMING" Q 0 181 M HDR=MSG("HDR") 182 I $G(MSG("ACK TO"))]"" S ACTION=MSG("STATUS","APP ACK RESPONSE") 183 I ACTION="",'$$ACTION^HLOAPP(.HDR,.ACTION,.QUEUE),$G(MSG("ACK TO"))="" S ERROR="RECEIVING APPLICATION NOT DEFINED" Q 0 184 ;If this message references an earlier message, get the action specified by the original message 185 I $G(ACTION)="",$G(MSG("ACK TO IEN")) S ACTION=$P($G(^HLB(+MSG("ACK TO IEN"),0)),"^",10,11) I $P(ACTION,"^",2)="" S ERROR="ORIGINAL MESSAGE NOT FOUND" Q 0 186 D:$G(PURGE) 187 .K:MSG("STATUS","PURGE") ^HLB("AD","IN",MSG("STATUS","PURGE"),MSGIEN) 188 .S $P(^HLB(MSGIEN,0),"^",9)=PURGE 189 .S ^HLB("AD","IN",PURGE,MSGIEN)="" 190 .I $G(MSG("ACK TO IEN")),$D(^HLB(MSG("ACK TO IEN"),0)) K ^HLB("AD","OUT",MSG("STATUS","PURGE"),MSG("ACK TO IEN")) S $P(^HLB(MSG("ACK TO IEN"),0),"^",9)=PURGE,^HLB("AD","OUT",PURGE,MSG("ACK TO IEN"))="" 191 S HLMSGIEN=MSGIEN 192 S $P(^HLB(MSGIEN,0),"^",19)=1 193 S MCODE="D "_ACTION 194 X MCODE 195 Q 1 -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOAPP.m
r613 r623 1 HLOAPP ;ALB/CJM-HL7 -Application Registry ;07/09/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,132,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 GETIEN(NAME) ;given the application name, it finds the ien. Returns 0 on failure 6 Q:'$L($G(NAME)) 0 7 Q +$O(^HLD(779.2,"C",$E(NAME,1,60),0)) 8 ; 9 ACTION(HEADER,ACTION,QUEUE) ;Given the parsed header of a message it returns both the action that should be performed in response to the message and the incoming queue that it should be placed on. 10 ; 11 ;Input: 12 ; HEADER() subscripts are used: "RECEIVING APPLICATION","SEGMENT TYPE", "MESSAGE TYPE", "EVENT", "VERSION" 13 ;Output: 14 ; Function returns 1 on success, 0 on failure 15 ; ACTION (pass by reference) <tag>^<rtn> 16 ; QUEUE (pass by reference) returns the named queue if there is one, else "DEFAULT" 17 ; 18 N IEN 19 S (ACTION,QUEUE)="" 20 S IEN=$$GETIEN(HEADER("RECEIVING APPLICATION")) 21 Q:'$G(IEN) 0 22 I $G(HEADER("SEGMENT TYPE"))="BHS" D 23 .S NODE=$G(^HLD(779.2,IEN,0)) 24 .I $P(NODE,"^",5)]"" D 25 ..S ACTION=$P(NODE,"^",4,5) 26 .E I $P(NODE,"^",7)]"" S ACTION=$P(NODE,"^",6,7) 27 .I $P(NODE,"^",8)]"" D 28 ..S QUEUE=$P(NODE,"^",8) 29 .E I $P(NODE,"^",3)]"" S QUEUE=$P(NODE,"^",3) 30 E I HEADER("SEGMENT TYPE")="MSH" D 31 .I HEADER("MESSAGE TYPE")'="",HEADER("EVENT")'="" D 32 ..N SUBIEN,NODE 33 ..;did the application specify an action for the particular version of this message? 34 ..I HEADER("VERSION")'="" S SUBIEN=$O(^HLD(779.2,IEN,1,"D",HEADER("MESSAGE TYPE"),HEADER("EVENT"),HEADER("VERSION"),0)) 35 ..;if not, look on the "C" index 36 ..S:'$G(SUBIEN) SUBIEN=$O(^HLD(779.2,IEN,1,"C",HEADER("MESSAGE TYPE"),HEADER("EVENT"),0)) 37 ..; 38 ..I SUBIEN D 39 ...S NODE=$G(^HLD(779.2,IEN,1,SUBIEN,0)) 40 ...I $P(NODE,"^",5)]"" S ACTION=$P(NODE,"^",4,5) 41 ...I $P(NODE,"^",3)]"" S QUEUE=$P(NODE,"^",3) 42 ..I ACTION="" S NODE=$G(^HLD(779.2,IEN,0)) I $P(NODE,"^",7)]"" S ACTION=$P(NODE,"^",6,7) 43 ..I QUEUE="" S NODE=$G(^HLD(779.2,IEN,0)) I $P(NODE,"^",3)]"" S QUEUE=$P(NODE,"^",3) 44 I QUEUE="" S QUEUE="DEFAULT" 45 I ACTION="" Q 0 46 Q 1 47 ; 48 RTRNLNK(APPNAME) ; 49 ;given the name of a receiving application, this returns the return 50 ;link for application acks if one is provided. Otherwise, return 51 ;acks are routed based on the information provide in the message hdr 52 ; 53 Q:(APPNAME="") "" 54 N IEN 55 S IEN=$$GETIEN(APPNAME) 56 Q:IEN $P($G(^HLD(779.2,IEN,0)),"^",2) 57 Q "" 58 ; 59 RTRNPORT(APPNAME) ; 60 ;Given the name of the sending application, IF the application has its 61 ;own listener, its port # is returned. Application acks should be 62 ;returned using that port 63 Q:(APPNAME="") "" 64 N IEN,LINK 65 S IEN=$$GETIEN(APPNAME) 66 Q:'IEN "" 67 S LINK=$P($G(^HLD(779.2,IEN,0)),"^",9) 68 Q:'LINK "" 69 Q $$PORT^HLOTLNK(LINK) 70 ; 71 ACTIVE(APP,MSGTYPE,EVENT,VERSION) ; 72 ;Returns 1 if the message's INACTIVE flag has NOT been set. 73 ; 74 ;Input: 75 ; APP (required) the name of the sending application 76 ; MSGTYPE (required) 3 character HL7 message type 77 ; EVENT (required) 3 character HL7 event 78 ; VERSION (optional) HL7 version ID as it appears in the message header 79 ;Output: 80 ; Function returns 1 if the message type specified by the input parameters has not been set to INACTIVE. It returns 0 otherwise. 81 ; 82 N IEN,ACTIVE,SUBIEN 83 S ACTIVE=1 84 S IEN=$$GETIEN($G(APP)) 85 Q:'$G(IEN) ACTIVE 86 Q:$G(MSGTYPE)="" ACTIVE 87 Q:$G(EVENT)="" ACTIVE 88 ;did the application specify an action for the particular version of this message? 89 I $G(VERSION)'="" S SUBIEN=$O(^HLD(779.2,IEN,1,"D",MSGTYPE,EVENT,VERSION,0)) 90 ;if not, look on the "C" index 91 S:'$G(SUBIEN) SUBIEN=$O(^HLD(779.2,IEN,1,"C",MSGTYPE,EVENT,0)) 92 ; 93 S:SUBIEN ACTIVE='(+$P($G(^HLD(779.2,IEN,1,SUBIEN,0)),"^",7)) 94 Q ACTIVE 95 ; 96 EXCEPT(APPNAME) ; 97 ;returns the exception handler (tag^routine) that should be invoked 98 ;when an applicaiton's messages are being sequenced and an app ack 99 ;is not timely received 100 ; 101 N IEN,RTN 102 S IEN=$$GETIEN($G(APPNAME)) 103 I IEN S RTN=$P($G(^HLD(779.2,IEN,0)),"^",10,11) 104 I $L($G(RTN))>1 Q RTN 105 Q "DEFAULT^HLOAPP" 106 ; 107 DEFAULT ;default exception handler if the app doesn't specify one 108 S ^TMP("HLO SEQUENCING EXCEPTION",$J,$$NOW^XLFDT,+$G(HLMSGIEN))="" 109 Q 110 ; 111 TIMEOUT(APPNAME) ; 112 N IEN,TIME 113 S IEN=$$GETIEN($G(APPNAME)) 114 I IEN S TIME=$P($G(^HLD(779.2,IEN,0)),"^",12) 115 Q:'$G(TIME) 10 116 Q TIME 1 HLOAPP ;ALB/CJM-HL7 -Application Registry ;10/31/2006 2 ;;1.6;HEALTH LEVEL SEVEN;**126,132**;Oct 13, 1995;Build 6 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 GETIEN(NAME) ;given the application name, it finds the ien. Returns 0 on failure 6 Q:'$L($G(NAME)) 0 7 N IEN,SUB 8 S SUB=$E(NAME,1,60) 9 S IEN=0 10 F S IEN=$O(^HLD(779.2,"B",SUB,IEN)) Q:'IEN Q:$P($G(^HLD(779.2,IEN,0)),"^")=NAME 11 Q +IEN 12 ; 13 ACTION(HEADER,ACTION,QUEUE) ;Given the parsed header of a message it returns both the action that should be performed in response to the message and the incoming queue that it should be placed on. 14 ; 15 ;Input: 16 ; HEADER() subscripts are used: "RECEIVING APPLICATION","SEGMENT TYPE", "MESSAGE TYPE", "EVENT", "VERSION" 17 ;Output: 18 ; Function returns 1 on success, 0 on failure 19 ; ACTION (pass by reference) <tag>^<rtn> 20 ; QUEUE (pass by reference) returns the named queue if there is one, else "DEFAULT" 21 ; 22 N IEN 23 S (ACTION,QUEUE)="" 24 S IEN=$$GETIEN(HEADER("RECEIVING APPLICATION")) 25 Q:'$G(IEN) 0 26 I $G(HEADER("SEGMENT TYPE"))="BHS" D 27 .S NODE=$G(^HLD(779.2,IEN,0)) 28 .I $P(NODE,"^",5)]"" D 29 ..S ACTION=$P(NODE,"^",4,5) 30 .E I $P(NODE,"^",7)]"" S ACTION=$P(NODE,"^",6,7) 31 .I $P(NODE,"^",8)]"" D 32 ..S QUEUE=$P(NODE,"^",8) 33 .E I $P(NODE,"^",3)]"" S QUEUE=$P(NODE,"^",3) 34 E I HEADER("SEGMENT TYPE")="MSH" D 35 .I HEADER("MESSAGE TYPE")'="",HEADER("EVENT")'="" D 36 ..N SUBIEN,NODE 37 ..;did the application specify an action for the particular version of this message? 38 ..I HEADER("VERSION")'="" S SUBIEN=$O(^HLD(779.2,IEN,1,"D",HEADER("MESSAGE TYPE"),HEADER("EVENT"),HEADER("VERSION"),0)) 39 ..;if not, look on the "C" index 40 ..S:'$G(SUBIEN) SUBIEN=$O(^HLD(779.2,IEN,1,"C",HEADER("MESSAGE TYPE"),HEADER("EVENT"),0)) 41 ..; 42 ..I SUBIEN D 43 ...S NODE=$G(^HLD(779.2,IEN,1,SUBIEN,0)) 44 ...I $P(NODE,"^",5)]"" S ACTION=$P(NODE,"^",4,5) 45 ...I $P(NODE,"^",3)]"" S QUEUE=$P(NODE,"^",3) 46 ..I ACTION="" S NODE=$G(^HLD(779.2,IEN,0)) I $P(NODE,"^",7)]"" S ACTION=$P(NODE,"^",6,7) 47 ..I QUEUE="" S NODE=$G(^HLD(779.2,IEN,0)) I $P(NODE,"^",3)]"" S QUEUE=$P(NODE,"^",3) 48 I QUEUE="" S QUEUE="DEFAULT" 49 I ACTION="" Q 0 50 Q 1 51 ; 52 RTRNLNK(APPNAME) ; 53 ;given the name of a receiving application, this returns the return 54 ;link for application acks if one is provided. Otherwise, return 55 ;acks are routed based on the information provide in the message hdr 56 ; 57 Q:(APPNAME="") "" 58 N IEN 59 S IEN=$$GETIEN(APPNAME) 60 Q:IEN $P($G(^HLD(779.2,IEN,0)),"^",2) 61 Q "" 62 ; 63 RTRNPORT(APPNAME) ; 64 ;Given the name of the sending application, IF the application has its 65 ;own listener, its port # is returned. Application acks should be 66 ;returned using that port 67 Q:(APPNAME="") "" 68 N IEN,LINK 69 S IEN=$$GETIEN(APPNAME) 70 Q:'IEN "" 71 S LINK=$P($G(^HLD(779.2,IEN,0)),"^",9) 72 Q:'LINK "" 73 Q $$PORT^HLOTLNK(LINK) 74 ; 75 ACTIVE(APP,MSGTYPE,EVENT,VERSION) ; 76 ;Returns 1 if the message's INACTIVE flag has NOT been set. 77 ; 78 ;Input: 79 ; APP (required) the name of the sending application 80 ; MSGTYPE (required) 3 character HL7 message type 81 ; EVENT (required) 3 character HL7 event 82 ; VERSION (optional) HL7 version ID as it appears in the message header 83 ;Output: 84 ; Function returns 1 if the message type specified by the input parameters has not been set to INACTIVE. It returns 0 otherwise. 85 ; 86 N IEN,ACTIVE,SUBIEN 87 S ACTIVE=1 88 S IEN=$$GETIEN($G(APP)) 89 Q:'$G(IEN) ACTIVE 90 Q:$G(MSGTYPE)="" ACTIVE 91 Q:$G(EVENT)="" ACTIVE 92 ;did the application specify an action for the particular version of this message? 93 I $G(VERSION)'="" S SUBIEN=$O(^HLD(779.2,IEN,1,"D",MSGTYPE,EVENT,VERSION,0)) 94 ;if not, look on the "C" index 95 S:'$G(SUBIEN) SUBIEN=$O(^HLD(779.2,IEN,1,"C",MSGTYPE,EVENT,0)) 96 ; 97 S:SUBIEN ACTIVE='(+$P($G(^HLD(779.2,IEN,1,SUBIEN,0)),"^",7)) 98 Q ACTIVE -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOCLNT.m
r613 r623 1 HLOCLNT ;ALB/CJM- Client for sending messages - 10/4/94 1pm ;08/15/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,130,131,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ;GET WORK function for the process running under the Process Manager 6 GETWORK(QUE) ; 7 ;Input: 8 ; QUE - (pass by reference) These subscripts are used: 9 ; ("LINK") - <link name>_":"_<port> last obtained 10 ; ("QUEUE") - name of the queue last obtained 11 ;Output: 12 ; Function returns 1 if success, 0 if no more work 13 ; QUE - updated to identify next queue of messages to process. 14 ; ("LINK") - <link name>_":"_<port> 15 ; ("QUEUE") - the named queue on the link 16 ; ("DOWN") - =1 means that the last OPEN attempt failed 17 ; 18 N LINK,QUEUE 19 S LINK=$G(QUE("LINK")),QUEUE=$G(QUE("QUEUE")) 20 I (LINK]""),(QUEUE]"") D 21 .L -^HLB("QUEUE","OUT",LINK,QUEUE) 22 .I '$$CNNCTD(LINK),$$FAILING(.LINK) S QUEUE="" Q 23 .F S QUEUE=$O(^HLB("QUEUE","OUT",LINK,QUEUE)) Q:(QUEUE="") I '$$STOPPED^HLOQUE("OUT",QUEUE) L +^HLB("QUEUE","OUT",LINK,QUEUE):0 Q:$T 24 I (LINK]""),(QUEUE="") D 25 .F S LINK=$O(^HLB("QUEUE","OUT",LINK)) Q:LINK="" D Q:$L(QUEUE) 26 ..I '$$CNNCTD(LINK),$$FAILING(.LINK) Q 27 ..S QUEUE="" F S QUEUE=$O(^HLB("QUEUE","OUT",LINK,QUEUE)) Q:(QUEUE="") I '$$STOPPED^HLOQUE("OUT",QUEUE) L +^HLB("QUEUE","OUT",LINK,QUEUE):0 Q:$T 28 I LINK="" D 29 .F S LINK=$O(^HLB("QUEUE","OUT",LINK)) Q:LINK="" D Q:$L(QUEUE) 30 ..I '$$CNNCTD(LINK),$$FAILING(.LINK) Q 31 ..S QUEUE="" F S QUEUE=$O(^HLB("QUEUE","OUT",LINK,QUEUE)) Q:(QUEUE="") I '$$STOPPED^HLOQUE("OUT",QUEUE) L +^HLB("QUEUE","OUT",LINK,QUEUE):0 Q:$T 32 S QUE("LINK")=LINK,QUE("QUEUE")=QUEUE,QUE("DOWN")=$G(LINK("DOWN")) 33 Q:$L(QUEUE) 1 34 D:$G(HLCSTATE("CONNECTED")) CLOSE^HLOT(.HLCSTATE) 35 Q 0 36 ; 37 FAILING(LINK) ; 38 ;Returns 1 if the link has failed in the last 30 seconds, 0 otherwise 39 ;Also returns LINK("DOWN")=1 if the link was failing > 30 seconds ago, not yet known if its up 40 ; 41 N LASTTIME,SET 42 S LINK("DOWN")=0 43 S LASTTIME=$G(^HLB("QUEUE","OUT",LINK)) 44 S SET=$S(LASTTIME]"":1,1:0) 45 I SET D 46 .I $$HDIFF^XLFDT($H,LASTTIME,2)>30 S ^HLB("QUEUE","OUT",LINK)="",SET=0,LINK("DOWN")=1 47 I $D(^HLTMP("FAILING LINKS",LINK)) S LINK("DOWN")=1 48 Q SET 49 ; 50 LINKDOWN(HLCSTATE) ; 51 D:$G(HLCSTATE("CONNECTED")) CLOSE^HLOT(.HLCSTATE) 52 I $D(HLCSTATE("LINK","NAME")),$D(HLCSTATE("LINK","PORT")) D 53 .S TO=HLCSTATE("LINK","NAME")_":"_HLCSTATE("LINK","PORT") 54 .S ^HLB("QUEUE","OUT",TO)=$H 55 .S:'$D(^HLTMP("FAILING LINKS",TO)) ^HLTMP("FAILING LINKS",TO)=$H 56 Q 57 ; 58 ERROR ;error trap 59 S $ETRAP="Q:$QUIT """" Q" 60 N HOUR 61 S HOUR=$E($$NOW^XLFDT,1,10) 62 S ^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2))=$G(^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2)))+1 63 D END 64 D LINKDOWN(.HLCSTATE) 65 ; 66 I ($ECODE["TOOMANYFILES")!($ECODE["EDITED") Q:$QUIT "" Q 67 ;while debugging quit on all errors - this will return the process to the Process Manager error trap 68 I $G(^HLTMP("LOG ALL ERRORS")) Q:$QUIT "" Q 69 ; 70 ;don't log some common errors 71 I ($ECODE["READ")!($ECODE["NOTOPEN")!($ECODE["DEVNOTOPN")!($ECODE["WRITE")!($ECODE["OPENERR") D 72 .; 73 E D 74 .;but do log all the others 75 .D ^%ZTER 76 ; 77 ;a lot of errors of the same type may indicate an endless loop 78 ;return to the Process Manager error trap 79 I ($G(^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2)))>30) Q:$QUIT "" Q 80 ; 81 ;resume execution of the process manager executing the client 82 D UNWIND^%ZTER 83 Q 84 ; 85 DOWORK(QUEUE) ;sends the messages on the queue 86 N $ETRAP,$ESTACK S $ETRAP="G ERROR^HLOCLNT" 87 N MSGIEN,DEQUE,SUCCESS,MSGCOUNT 88 S DEQUE=0 89 S SUCCESS=1 90 ; 91 I '$$CNNCTD(QUEUE("LINK")),'$$CONNECT^HLOCLNT1($P(QUEUE("LINK"),":"),$P(QUEUE("LINK"),":",2),30,.HLCSTATE) Q 92 ; 93 S (MSGCOUNT,MSGIEN)=0 94 F S MSGIEN=$O(^HLB("QUEUE","OUT",QUEUE("LINK"),QUEUE("QUEUE"),MSGIEN)) Q:'MSGIEN D Q:'SUCCESS Q:MSGCOUNT>1000 95 .N UPDATE 96 .S ^HLB(MSGIEN,"TRIES")=$G(^HLB(MSGIEN,"TRIES"))+1 97 .S SUCCESS=0 98 .S:$$TRANSMIT(.HLCSTATE,MSGIEN,.UPDATE) SUCCESS=1 99 .Q:('SUCCESS)!('$D(UPDATE)) 100 .D DEQUE(.UPDATE) 101 .S MSGCOUNT=MSGCOUNT+1 102 .D:HLCSTATE("COUNTS")>4 SAVECNTS^HLOSTAT(.HLCSTATE) 103 .; 104 .;if the queue was on the down list, and not since shutdown, mark it as up, since a message has been successfully transmitted across it 105 .I $G(QUEUE("DOWN"))!$$FAILING(QUEUE("LINK")),'$$IFSHUT^HLOTLNK(QUEUE("LINK")) S QUEUE("DOWN")=0,^HLB("QUEUE","OUT",QUEUE("LINK"))="" K ^HLTMP("FAILING LINKS",QUEUE("LINK")) 106 ; 107 END D DEQUE() 108 D SAVECNTS^HLOSTAT(.HLCSTATE) 109 Q 110 CNNCTD(LINK) ; 111 ;Connected to LINK? HLCSTATE must be defined, LINK=<link name>:<port> 112 ; 113 I ($G(HLCSTATE("LINK","NAME"))=$P(LINK,":")),($G(HLCSTATE("LINK","PORT"))=$P(LINK,":",2)),$G(HLCSTATE("CONNECTED")) Q 1 114 Q 0 115 ; 116 DEQUE(UPDATE) ; 117 I $D(UPDATE) S DEQUE=DEQUE+1,DEQUE(+UPDATE)=$P(UPDATE,"^",2,99) S:$G(UPDATE("MSA"))]"" DEQUE(+UPDATE,"MSA")=UPDATE("MSA") S:$G(UPDATE("ACTION"))]"" DEQUE(+UPDATE,"ACTION")=UPDATE("ACTION") 118 I '$D(UPDATE)!(DEQUE>15) D 119 .N MSGIEN S MSGIEN=0 120 .F S MSGIEN=$O(DEQUE(MSGIEN)) Q:'MSGIEN D 121 ..N NODE,TIME 122 ..D DEQUE^HLOQUE(QUEUE("LINK"),QUEUE("QUEUE"),"OUT",MSGIEN) 123 ..S TIME=$P(DEQUE(MSGIEN),"^") 124 ..Q:'TIME 125 ..S NODE=QUEUE("LINK")_"^"_QUEUE("QUEUE")_"^"_$P(DEQUE(MSGIEN),"^",2,99) 126 ..S ^HLTMP("CLIENT UPDATES",$J,TIME,MSGIEN)=NODE 127 ..S:$G(DEQUE(MSGIEN,"MSA"))]"" ^HLTMP("CLIENT UPDATES",$J,TIME,MSGIEN,"MSA")=DEQUE(MSGIEN,"MSA") 128 ..S:$G(DEQUE(MSGIEN,"ACTION"))]"" ^HLTMP("CLIENT UPDATES",$J,TIME,MSGIEN,"ACTION")=DEQUE(MSGIEN,"ACTION") 129 .K DEQUE S DEQUE=0 130 Q 131 ; 132 TRANSMIT(HLCSTATE,MSGIEN,UPDATE) ; 133 ;Transmits a single message and if a commit ack was requested reads it. Updates file 778 with the result. Queues for the infiler the application accept action if one was requested. 134 ;Input: 135 ; HLCSTATE (pass by reference) 136 ; MSGIEN - ien, file 778, of message to be transmitted 137 ;Output: 138 ; Function returns 1 on success, 0 on failure 139 ; UPDATE - (pass by reference) to contain updates needed for message 140 ; 141 N HLMSTATE,MSA,HDR,SUCCESS 142 ; 143 S SUCCESS=0 144 S HLCSTATE("ATTEMPT")=0 145 ; 146 ;start saving updates needed after the message is transmitted 147 S UPDATE=MSGIEN 148 Q:'$$GETMSG^HLOCLNT2(MSGIEN,.HLMSTATE) 1 ;returns 1 so the message will be removed from the queue 149 I HLMSTATE("DT/TM"),HLMSTATE("STATUS","ACCEPTED")!(HLMSTATE("HDR","ACCEPT ACK TYPE")="NE") Q 1 ;the message was already transmitted 150 ; 151 S UPDATE=UPDATE_"^"_$$NOW^XLFDT 152 RETRY D 153 .S HLCSTATE("ATTEMPT")=HLCSTATE("ATTEMPT")+1 154 .I 'HLCSTATE("CONNECTED") D OPEN^HLOT(.HLCSTATE) Q:'HLCSTATE("CONNECTED") 155 .; 156 .;try to send the message 157 .; 158 .; 159 .Q:'$$WRITEMSG^HLOCLNT1(.HLCSTATE,.HLMSTATE) 160 .;does the message need an accept ack? 161 .I HLMSTATE("HDR","ACCEPT ACK TYPE")="AL" D 162 ..N FS 163 ..Q:'$$READACK^HLOCLNT1(.HLCSTATE,.HDR,.MSA) 164 ..;does the MSA refer to the correct control id? 165 ..S FS=$E(HDR(1),4) 166 ..Q:$P(MSA,FS,3)'=HLMSTATE("ID") 167 ..N ACKID,ACKCODE 168 ..S ACKCODE=$P(MSA,FS,2) 169 ..S ACKID=$S($E(HDR(1),1,3)="MSH":$P(HDR(2),FS,5),1:$P(HDR(2),FS,6)) 170 ..S $P(UPDATE,"^",5)=1 171 ..S UPDATE("MSA")=ACKID_"^"_MSA 172 ..I '(ACKCODE="CA") S $P(UPDATE,"^",3)="ER",$P(UPDATE,"^",4)=2 173 ..I ACKCODE="CA",HLMSTATE("HDR","APP ACK TYPE")="NE" S $P(UPDATE,"^",3)="SU",$P(UPDATE,"^",4)=$S(HLMSTATE("BATCH"):"2",1:1) 174 ..I ($P(UPDATE,"^",3)="ER") S $P(UPDATE,"^",6)=$P(HLMSTATE("HDR",1),FS,5) ;errors need the application for xref 175 ..; 176 ..;if it's from a sequence queue, timestamp the queue 177 ..I $L($G(HLMSTATE("STATUS","SEQUENCE QUEUE"))) D 178 ...L +^HLB("QUEUE","SEQUENCE",HLMSTATE("STATUS","SEQUENCE QUEUE")):200 179 ...I $P($G(^HLB("QUEUE","SEQUENCE",HLMSTATE("STATUS","SEQUENCE QUEUE"))),"^")'=MSGIEN L -^HLB("QUEUE","SEQUENCE",HLMSTATE("STATUS","SEQUENCE QUEUE")) Q 180 ...I ACKCODE="CA" S $P(^HLB("QUEUE","SEQUENCE",HLMSTATE("STATUS","SEQUENCE QUEUE")),"^",2)=$$FMADD^XLFDT($P(UPDATE,"^",2),,,$$TIMEOUT^HLOAPP($$GETSAP^HLOCLNT2(MSGIEN))) L -^HLB("QUEUE","SEQUENCE",HLMSTATE("STATUS","SEQUENCE QUEUE")) Q 181 ...;if the message wasn't accepted, need to notify without waiting 182 ...S $P(^HLB("QUEUE","SEQUENCE",HLMSTATE("STATUS","SEQUENCE QUEUE")),"^",2)=$P(UPDATE,"^",2) 183 ...L -^HLB("QUEUE","SEQUENCE",HLMSTATE("STATUS","SEQUENCE QUEUE")) 184 ..; 185 ..;does the app need notification of accept ack? 186 ..S UPDATE("ACTION")=HLMSTATE("ACCEPT ACK RESPONSE") 187 ..; 188 ..S SUCCESS=1 189 .E D ;accept ack wasn't requested 190 ..S SUCCESS=1 191 ..I HLMSTATE("HDR","APP ACK TYPE")="NE" S $P(UPDATE,"^",3)="SU",$P(UPDATE,"^",4)=$S(HLMSTATE("BATCH"):2,1:1) 192 ; 193 I 'SUCCESS,'HLCSTATE("CONNECTED"),(HLCSTATE("ATTEMPT")<2) G RETRY 194 I SUCCESS D 195 .D COUNT^HLOSTAT(.HLCSTATE,HLMSTATE("HDR","RECEIVING APPLICATION"),HLMSTATE("HDR","SENDING APPLICATION"),$S(HLMSTATE("BATCH"):"BATCH",1:HLMSTATE("HDR","MESSAGE TYPE")_"~"_HLMSTATE("HDR","EVENT"))) 196 .;if this is an ack to a message need to purge the original message, so store its ien with the purge date 197 .S:$G(HLMSTATE("ACK TO IEN")) $P(UPDATE,"^",4)=$P(UPDATE,"^",4)_"-"_HLMSTATE("ACK TO IEN") 198 I ('HLCSTATE("CONNECTED"))!('SUCCESS) D LINKDOWN(.HLCSTATE) 199 Q SUCCESS 1 HLOCLNT ;ALB/CJM- Client for sending messages - 10/4/94 1pm ;03/22/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,130,131,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ;GET WORK function for the process running under the Process Manager 6 GETWORK(QUE) ; 7 ;Input: 8 ; QUE - (pass by reference) These subscripts are used: 9 ; ("LINK") - <link name>_":"_<port> last obtained 10 ; ("QUEUE") - name of the queue last obtained 11 ;Output: 12 ; Function returns 1 if success, 0 if no more work 13 ; QUE - updated to identify next queue of messages to process. 14 ; ("LINK") - <link name>_":"_<port> 15 ; ("QUEUE") - the named queue on the link 16 ; ("DOWN") - =1 means that the last OPEN attempt failed 17 ; 18 N LINK,QUEUE 19 S LINK=$G(QUE("LINK")),QUEUE=$G(QUE("QUEUE")) 20 I (LINK]""),(QUEUE]"") D 21 .L -^HLB("QUEUE","OUT",LINK,QUEUE) 22 .I '$$CNNCTD(LINK),$$FAILING(.LINK) S QUEUE="" Q 23 .F S QUEUE=$O(^HLB("QUEUE","OUT",LINK,QUEUE)) Q:(QUEUE="") I '$$STOPPED^HLOQUE("OUT",QUEUE) L +^HLB("QUEUE","OUT",LINK,QUEUE):0 Q:$T 24 I (LINK]""),(QUEUE="") D 25 .F S LINK=$O(^HLB("QUEUE","OUT",LINK)) Q:LINK="" D Q:$L(QUEUE) 26 ..I '$$CNNCTD(LINK),$$FAILING(.LINK) Q 27 ..S QUEUE="" F S QUEUE=$O(^HLB("QUEUE","OUT",LINK,QUEUE)) Q:(QUEUE="") I '$$STOPPED^HLOQUE("OUT",QUEUE) L +^HLB("QUEUE","OUT",LINK,QUEUE):0 Q:$T 28 I LINK="" D 29 .F S LINK=$O(^HLB("QUEUE","OUT",LINK)) Q:LINK="" D Q:$L(QUEUE) 30 ..I '$$CNNCTD(LINK),$$FAILING(.LINK) Q 31 ..S QUEUE="" F S QUEUE=$O(^HLB("QUEUE","OUT",LINK,QUEUE)) Q:(QUEUE="") I '$$STOPPED^HLOQUE("OUT",QUEUE) L +^HLB("QUEUE","OUT",LINK,QUEUE):0 Q:$T 32 S QUE("LINK")=LINK,QUE("QUEUE")=QUEUE,QUE("DOWN")=$G(LINK("DOWN")) 33 Q:$L(QUEUE) 1 34 D:$G(HLCSTATE("CONNECTED")) CLOSE^HLOT(.HLCSTATE) 35 Q 0 36 ; 37 FAILING(LINK) ; 38 ;Returns 1 if the link has failed in the last 30 seconds, 0 otherwise 39 ;Also returns LINK("DOWN")=1 if the link was failing > 30 seconds ago, not yet known if its up 40 ; 41 N LASTTIME,SET 42 S LINK("DOWN")=0 43 S LASTTIME=$G(^HLB("QUEUE","OUT",LINK)) 44 S SET=$S(LASTTIME]"":1,1:0) 45 I SET D 46 .I $$HDIFF^XLFDT($H,LASTTIME,2)>30 S ^HLB("QUEUE","OUT",LINK)="",SET=0,LINK("DOWN")=1 47 I $D(^HLTMP("FAILING LINKS",LINK)) S LINK("DOWN")=1 48 Q SET 49 ; 50 LINKDOWN(HLCSTATE) ; 51 D:$G(HLCSTATE("CONNECTED")) CLOSE^HLOT(.HLCSTATE) 52 I $D(HLCSTATE("LINK","NAME")),$D(HLCSTATE("LINK","PORT")) D 53 .S TO=HLCSTATE("LINK","NAME")_":"_HLCSTATE("LINK","PORT") 54 .S ^HLB("QUEUE","OUT",TO)=$H 55 .S:'$D(^HLTMP("FAILING LINKS",TO)) ^HLTMP("FAILING LINKS",TO)=$H 56 Q 57 ; 58 ERROR ;error trap 59 S $ETRAP="Q:$QUIT """" Q" 60 N HOUR 61 S HOUR=$E($$NOW^XLFDT,1,10) 62 S ^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2))=$G(^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2)))+1 63 D END 64 D LINKDOWN(.HLCSTATE) 65 ; 66 I ($ECODE["TOOMANYFILES")!($ECODE["EDITED") Q:$QUIT "" Q 67 ;while debugging quit on all errors - this will return the process to the Process Manager error trap 68 I $G(^HLTMP("LOG ALL ERRORS")) Q:$QUIT "" Q 69 ; 70 ;don't log some common errors 71 I ($ECODE["READ")!($ECODE["NOTOPEN")!($ECODE["DEVNOTOPN")!($ECODE["WRITE")!($ECODE["OPENERR") D 72 .; 73 E D 74 .;but do log all the others 75 .D ^%ZTER 76 ; 77 ;a lot of errors of the same type may indicate an endless loop 78 ;return to the Process Manager error trap 79 I ($G(^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2)))>30) Q:$QUIT "" Q 80 ; 81 ;resume execution of the process manager executing the client 82 D UNWIND^%ZTER 83 Q 84 ; 85 DOWORK(QUEUE) ;sends the messages on the queue 86 N $ETRAP,$ESTACK S $ETRAP="G ERROR^HLOCLNT" 87 N MSGIEN,DEQUE,SUCCESS,MSGCOUNT 88 S DEQUE=0 89 S SUCCESS=1 90 ; 91 I '$$CNNCTD(QUEUE("LINK")),'$$CONNECT^HLOCLNT1($P(QUEUE("LINK"),":"),$P(QUEUE("LINK"),":",2),30,.HLCSTATE) Q 92 ; 93 S (MSGCOUNT,MSGIEN)=0 94 F S MSGIEN=$O(^HLB("QUEUE","OUT",QUEUE("LINK"),QUEUE("QUEUE"),MSGIEN)) Q:'MSGIEN D Q:'SUCCESS Q:MSGCOUNT>1000 95 .N UPDATE 96 .S ^HLB(MSGIEN,"TRIES")=$G(^HLB(MSGIEN,"TRIES"))+1 97 .S SUCCESS=0 98 .S:$$TRANSMIT(.HLCSTATE,MSGIEN,.UPDATE) SUCCESS=1 99 .Q:('SUCCESS)!('$D(UPDATE)) 100 .D DEQUE(.UPDATE) 101 .S MSGCOUNT=MSGCOUNT+1 102 .D:HLCSTATE("COUNTS")>4 SAVECNTS^HLOSTAT(.HLCSTATE) 103 .; 104 .;if the queue was on the down list, and not since shutdown, mark it as up, since a message has been successfully transmitted across it 105 .I $G(QUEUE("DOWN"))!$$FAILING(QUEUE("LINK")),'$$IFSHUT^HLOTLNK(QUEUE("LINK")) S QUEUE("DOWN")=0,^HLB("QUEUE","OUT",QUEUE("LINK"))="" K ^HLTMP("FAILING LINKS",QUEUE("LINK")) 106 ; 107 END D DEQUE() 108 D SAVECNTS^HLOSTAT(.HLCSTATE) 109 Q 110 CNNCTD(LINK) ; 111 ;Connected to LINK? HLCSTATE must be defined, LINK=<link name>:<port> 112 ; 113 I ($G(HLCSTATE("LINK","NAME"))=$P(LINK,":")),($G(HLCSTATE("LINK","PORT"))=$P(LINK,":",2)),$G(HLCSTATE("CONNECTED")) Q 1 114 Q 0 115 ; 116 DEQUE(UPDATE) ; 117 I $D(UPDATE) S DEQUE=DEQUE+1,DEQUE(+UPDATE)=$P(UPDATE,"^",2,99) S:$G(UPDATE("MSA"))]"" DEQUE(+UPDATE,"MSA")=UPDATE("MSA") S:$G(UPDATE("ACTION"))]"" DEQUE(+UPDATE,"ACTION")=UPDATE("ACTION") 118 I '$D(UPDATE)!(DEQUE>15) D 119 .N MSGIEN S MSGIEN=0 120 .F S MSGIEN=$O(DEQUE(MSGIEN)) Q:'MSGIEN D 121 ..N NODE,TIME 122 ..D DEQUE^HLOQUE(QUEUE("LINK"),QUEUE("QUEUE"),"OUT",MSGIEN) 123 ..S TIME=$P(DEQUE(MSGIEN),"^") 124 ..Q:'TIME 125 ..S NODE=QUEUE("LINK")_"^"_QUEUE("QUEUE")_"^"_$P(DEQUE(MSGIEN),"^",2,99) 126 ..S ^HLTMP("CLIENT UPDATES",$J,TIME,MSGIEN)=NODE 127 ..S:$G(DEQUE(MSGIEN,"MSA"))]"" ^HLTMP("CLIENT UPDATES",$J,TIME,MSGIEN,"MSA")=DEQUE(MSGIEN,"MSA") 128 ..S:$G(DEQUE(MSGIEN,"ACTION"))]"" ^HLTMP("CLIENT UPDATES",$J,TIME,MSGIEN,"ACTION")=DEQUE(MSGIEN,"ACTION") 129 .K DEQUE S DEQUE=0 130 Q 131 ; 132 TRANSMIT(HLCSTATE,MSGIEN,UPDATE) ; 133 ;Transmits a single message and if a commit ack was requested reads it. Updates file 778 with the result. Queues for the infiler the application accept action if one was requested. 134 ;Input: 135 ; HLCSTATE (pass by reference) 136 ; MSGIEN - ien, file 778, of message to be transmitted 137 ;Output: 138 ; Function returns 1 on success, 0 on failure 139 ; UPDATE - (pass by reference) to contain updates needed for message 140 ; 141 N HLMSTATE,MSA,HDR,SUCCESS 142 ; 143 S SUCCESS=0 144 S HLCSTATE("ATTEMPT")=0 145 ; 146 ;start saving updates needed after the message is transmitted 147 S UPDATE=MSGIEN 148 Q:'$$GETMSG^HLOCLNT2(MSGIEN,.HLMSTATE) 1 ;returns 1 so the message will be removed from the queue 149 I HLMSTATE("DT/TM"),HLMSTATE("STATUS","ACCEPTED")!(HLMSTATE("HDR","ACCEPT ACK TYPE")="NE") Q 1 ;the message was already transmitted 150 ; 151 S UPDATE=UPDATE_"^"_$$NOW^XLFDT 152 RETRY D 153 .S HLCSTATE("ATTEMPT")=HLCSTATE("ATTEMPT")+1 154 .I 'HLCSTATE("CONNECTED") D OPEN^HLOT(.HLCSTATE) Q:'HLCSTATE("CONNECTED") 155 .; 156 .;try to send the message 157 .Q:'$$WRITEMSG^HLOCLNT1(.HLCSTATE,.HLMSTATE) 158 .;does the message need an accept ack? 159 .I HLMSTATE("HDR","ACCEPT ACK TYPE")="AL" D 160 ..N FS 161 ..Q:'$$READACK^HLOCLNT1(.HLCSTATE,.HDR,.MSA) 162 ..;does the MSA refer to the correct control id? 163 ..S FS=$E(HDR(1),4) 164 ..Q:$P(MSA,FS,3)'=HLMSTATE("ID") 165 ..N ACKID,ACKCODE 166 ..S ACKCODE=$P(MSA,FS,2) 167 ..S ACKID=$S($E(HDR(1),1,3)="MSH":$P(HDR(2),FS,5),1:$P(HDR(2),FS,6)) 168 ..S $P(UPDATE,"^",5)=1 169 ..S UPDATE("MSA")=ACKID_"^"_MSA 170 ..I '(ACKCODE="CA") S $P(UPDATE,"^",3)="SE",$P(UPDATE,"^",4)=2 171 ..I ACKCODE="CA",HLMSTATE("HDR","APP ACK TYPE")="NE" S $P(UPDATE,"^",3)="SU",$P(UPDATE,"^",4)=$S(HLMSTATE("BATCH"):"2",1:1) 172 ..I ($P(UPDATE,"^",3)="SE") S $P(UPDATE,"^",6)=$P(HLMSTATE("HDR",1),FS,5) ;errors need the application for xref 173 ..; 174 ..;did the app request notification of accept ack? 175 ..S UPDATE("ACTION")=HLMSTATE("ACCEPT ACK RESPONSE") 176 ..S SUCCESS=1 177 .E D ;accept ack wasn't requested 178 ..S SUCCESS=1 179 ..I HLMSTATE("HDR","APP ACK TYPE")="NE" S $P(UPDATE,"^",3)="SU",$P(UPDATE,"^",4)=$S(HLMSTATE("BATCH"):2,1:1) 180 ; 181 I 'SUCCESS,'HLCSTATE("CONNECTED"),(HLCSTATE("ATTEMPT")<2) G RETRY 182 I SUCCESS D 183 .D COUNT^HLOSTAT(.HLCSTATE,HLMSTATE("HDR","RECEIVING APPLICATION"),HLMSTATE("HDR","SENDING APPLICATION"),$S(HLMSTATE("BATCH"):"BATCH",1:HLMSTATE("HDR","MESSAGE TYPE")_"~"_HLMSTATE("HDR","EVENT"))) 184 .;if this is an ack to a message need to purge the original message, so store its ien with the purge date 185 .S:$G(HLMSTATE("ACK TO IEN")) $P(UPDATE,"^",4)=$P(UPDATE,"^",4)_"-"_HLMSTATE("ACK TO IEN") 186 I ('HLCSTATE("CONNECTED"))!('SUCCESS) D LINKDOWN(.HLCSTATE) 187 Q SUCCESS -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOCLNT1.m
r613 r623 1 HLOCLNT1 ;IRMFO-ALB/CJM - Writing messages, reading acks;03/24/2004 14:43 ;07/10/20072 ;;1.6;HEALTH LEVEL SEVEN;**126,130,131,134,137**;Oct 13, 1995;Build 21 3 4 5 6 WRITEMSG(HLCSTATE,HLMSTATE) 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 READACK(HLCSTATE,HDR,MSA) 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 CONNECT(LINK,PORT,TIMEOUT,HLCSTATE) 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 BADMSGS(WORK) 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 ...S ^HLB("ERRORS",RAPP,TIME,MSG)=""149 150 151 152 153 154 1 HLOCLNT1 ;IRMFO-ALB/CJM - Writing messages, reading acks;03/24/2004 14:43 ;03/19/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,130,131,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ; 6 WRITEMSG(HLCSTATE,HLMSTATE) ; 7 ;Description: This function uses the services offered by the transport layer to send a message over an open communication channel. 8 ; 9 ;Input: 10 ; HLCSTATE (pass by reference, required) Defines the LLP & its state 11 ; HLMSTATE (pass by reference, required) The message 12 ;Output: 13 ; Function returns 1 on success, 0 on failure 14 ; 15 N SEG,QUIT,HDR 16 S QUIT=0 17 Q:'$G(HLMSTATE("IEN")) 0 18 S HDR(1)=HLMSTATE("HDR",1),HDR(2)=HLMSTATE("HDR",2) 19 Q:'$$WRITEHDR^HLOT(.HLCSTATE,.HDR) 0 20 I HLMSTATE("BATCH") D 21 .N LAST S LAST=0 22 .S HLMSTATE("BATCH","CURRENT MESSAGE")=0 23 .F Q:'$$NEXTMSG^HLOMSG(.HLMSTATE,.SEG) D Q:QUIT 24 ..S LAST=HLMSTATE("BATCH","CURRENT MESSAGE") 25 ..I '$$WRITESEG^HLOT(.HLCSTATE,.SEG) S QUIT=1 Q 26 ..F Q:'$$HLNEXT^HLOMSG(.HLMSTATE,.SEG) D Q:QUIT 27 ...I '$$WRITESEG^HLOT(.HLCSTATE,.SEG) S QUIT=1 Q 28 .K SEG S SEG(1)="BTS"_HLMSTATE("HDR","FIELD SEPARATOR")_LAST 29 .S:'$$WRITESEG^HLOT(.HLCSTATE,.SEG) QUIT=1 30 E D 31 .F Q:'$$HLNEXT^HLOMSG(.HLMSTATE,.SEG) D Q:QUIT 32 ..S:'$$WRITESEG^HLOT(.HLCSTATE,.SEG) QUIT=1 33 S:'$$ENDMSG^HLOT(.HLCSTATE) QUIT=1 34 Q 'QUIT 35 ; 36 READACK(HLCSTATE,HDR,MSA) ; 37 ;Description: This function uses the services offered by the transport layer to read an accept ack. 38 ; 39 ;Input: 40 ; HLCSTATE (pass by reference, required) Defines the communication channel and its state. 41 ;Output: 42 ; Function returns 1 on success, 0 on failure 43 ; HDR (pass by reference) the message header: 44 ; HDR(1) is components 1-6 45 ; HDR(2) is components 7-end 46 ; MSA (pass by reference) the MSA segment as an unsubscripted variable 47 ; 48 N SEG 49 K HDR,MSA,MAX,I 50 S MAX=HLCSTATE("SYSTEM","MAXSTRING")-40 ;MAX is the maximum that can be safely stored on a node, leaving room for the other fields stored with MSA seg 51 Q:'$$READHDR^HLOT(.HLCSTATE,.HDR) 0 52 F Q:'$$READSEG^HLOT(.HLCSTATE,.SEG) D 53 .I $E($E(SEG(1),1,3)_$E($G(SEG(2)),1,3),1,3)="MSA" D 54 ..S MSA="" 55 ..F I=1:1 Q:'$D(SEG(I)) S MSA=MSA_$S((MAX-$L(MSA))<1:"",1:$E(SEG(I),1,MAX)) 56 I $D(MSA),HLCSTATE("MESSAGE ENDED") D Q 1 57 .D SPLITHDR^HLOSRVR1(.HDR) 58 .S HLCSTATE("COUNTS","ACKS")=$G(HLCSTATE("COUNTS","ACKS"))+1 59 Q 0 60 ; 61 CONNECT(LINK,PORT,TIMEOUT,HLCSTATE) ; 62 ;sets up HLCSTATE() and opens a client connection 63 ;Input: 64 ; LINK - name of the link to connect to 65 ; PORT (optional) port # to connect to, defaults to that specified by the link 66 ; TIMEOUT (optional) specifies the open timeout in seconds, defaults to 30 67 ;Output: 68 ; HLCSTATE - array to hold the connection state 69 ; 70 I $G(HLCSTATE("CONNECTED")) D Q:HLCSTATE("CONNECTED") 71 .I $G(HLCSTATE("LINK","NAME"))]"",($G(HLCSTATE("LINK","NAME"))'=LINK) D CLOSE^HLOT(.HLCSTATE) Q 72 .I $G(HLCSTATE("LINK","NAME"))]"",$G(PORT),($G(HLCSTATE("LINK","PORT"))'=PORT) D CLOSE^HLOT(.HLCSTATE) Q 73 .I (HLCSTATE("SYSTEM","OS")="CACHE") D Q 74 ..U HLCSTATE("DEVICE") S HLCSTATE("CONNECTED")=($ZA\8192#2) 75 ..I 'HLCSTATE("CONNECTED") D CLOSE^HLOT(.HLCSTATE) 76 .;D CLOSE^HLOT(.HLCSTATE) 77 K HLCSTATE 78 N ARY,NODE 79 I '$$GETLINK^HLOTLNK(LINK,.ARY) S HLCSTATE("LINK","NAME")=LINK,HLCSTATE("LINK","PORT")=$G(PORT) D LINKDOWN^HLOCLNT(.HLCSTATE) Q 0 80 M HLCSTATE("LINK")=ARY 81 I HLCSTATE("LINK","SHUTDOWN") S HLCSTATE("CONNECTED")=0 D LINKDOWN^HLOCLNT(.HLCSTATE) Q 0 82 ;overlay the port if supplied from the queue 83 S:$G(PORT) HLCSTATE("LINK","PORT")=PORT 84 S HLCSTATE("READ TIMEOUT")=20 85 S HLCSTATE("OPEN TIMEOUT")=$S($G(TIMEOUT):TIMEOUT,1:30) 86 S HLCSTATE("COUNTS")=0 87 S HLCSTATE("READ")="" ;where the reads are stored 88 ; 89 ;HLCSTATE("BUFFER",<seg>,<line>) serves as a write buffer so that a lot can be written all at once 90 S HLCSTATE("BUFFER","BYTE COUNT")=0 ;count of BYTES in buffer 91 S HLCSTATE("BUFFER","SEGMENT COUNT")=0 ;count of segments in buffer 92 ; 93 S HLCSTATE("MESSAGE ENDED")=0 ;end of message flag 94 S NODE=^%ZOSF("OS") 95 S HLCSTATE("SERVER")=0 96 S HLCSTATE("SYSTEM","OS")=$S(NODE["DSM":"DSM",NODE["OpenM":"CACHE",NODE["G.TM":"G.TM",1:"") 97 I HLCSTATE("SYSTEM","OS")="" D LINKDOWN^HLOCLNT(.HLCSTATE) Q 0 98 D 99 .N SYS 100 .D SYSPARMS^HLOSITE(.SYS) 101 .S HLCSTATE("SYSTEM","BUFFER")=SYS("HL7 BUFFER") 102 .S HLCSTATE("SYSTEM","MAXSTRING")=SYS("MAXSTRING") 103 .S HLCSTATE("SYSTEM","NORMAL PURGE")=SYS("NORMAL PURGE") 104 .S HLCSTATE("SYSTEM","ERROR PURGE")=SYS("ERROR PURGE") 105 I HLCSTATE("LINK","LLP")="TCP" D 106 .S HLCSTATE("OPEN")="OPEN^HLOTCP" 107 E ;no other LLP implemented 108 D OPEN^HLOT(.HLCSTATE) 109 ; 110 ;mark the failure time for the link so other processes know not to try for a while 111 I 'HLCSTATE("CONNECTED") D LINKDOWN^HLOCLNT(.HLCSTATE) 112 Q HLCSTATE("CONNECTED") 113 ; 114 BADMSGS(WORK) ; 115 ;finds messages that won't transmit after 8 hours of trying and takes them off the outgoing queue 116 N LINK 117 S LINK="" 118 F S LINK=$O(^HLTMP("FAILING LINKS",LINK)) Q:LINK="" D 119 .N TIME,QUE,COUNT 120 .S TIME=$G(^HLTMP("FAILING LINKS",LINK)) Q:TIME="" 121 .Q:$$HDIFF^XLFDT($H,TIME,2)<28800 ;8 hours 122 .Q:'$$IFOPEN^HLOUSR1(LINK) 123 .L +^HLB("QUEUE","OUT",LINK):0 124 .S QUE="" 125 .F S QUE=$O(^HLB("QUEUE","OUT",LINK,QUE)) Q:QUE="" D 126 ..N MSG S MSG=0 127 ..S MSG=$O(^HLB("QUEUE","OUT",LINK,QUE,MSG)) 128 ..Q:'MSG 129 ..S COUNT=$G(^HLB(MSG,"TRIES")) 130 ..I COUNT>20 D 131 ...N NODE0,NODE1,NODE2,TIME,RAPP,SAPP,FS,CS,ACTION,MTYPE,EVENT 132 ...S NODE0=$G(^HLB(MSG,0)) 133 ...Q:'$P(NODE0,"^",2) 134 ...S TIME=$$NOW^XLFDT 135 ...S NODE1=$G(^HLB(MSG,1)) 136 ...S NODE2=$G(^HLB(MSG,2)) 137 ...S FS=$E(NODE1,4) 138 ...Q:FS="" 139 ...S CS=$E(NODE1,5) 140 ...Q:CS="" 141 ...S SAPP=$P(NODE1,FS,3) 142 ...S:SAPP="" SAPP="UNKNOWN" 143 ...S RAPP=$P(NODE1,FS,5) 144 ...S MTYPE=$P($P(NODE2,FS,4),CS) 145 ...S EVENT=$P($P(NODE2,FS,4),CS,2) 146 ...S $P(^HLB(MSG,0),"^",21)=COUNT_" FAILED TRANSMISSIONS" 147 ...S $P(^HLB(MSG,0),"^",20)="TF" 148 ...S ^HLB("ERRORS","TF",SAPP,TIME,MSG)="" 149 ...D COUNT^HLOESTAT("OUT",RAPP,SAPP,MTYPE,EVENT) 150 ...S ACTION=$P(NODE0,"^",14,15) 151 ...I ACTION'="^",ACTION]"" D INQUE^HLOQUE(LINK,QUE,MSG,ACTION,1) 152 ...D DEQUE^HLOQUE(LINK,QUE,"OUT",MSG) 153 .L -^HLB("QUEUE","OUT",LINK) 154 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOCLNT2.m
r613 r623 1 HLOCLNT2 ;ALB/CJM- Performs message updates for the client - 10/4/94 1pm ;07/10/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,130,131,133,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 GETWORK(WORK) ; 6 ; 7 N OLD,DOLLARJ,SUCCESS,NOW 8 S SUCCESS=0 9 S NOW=$$NOW^XLFDT 10 S (OLD,DOLLARJ)=$G(WORK("DOLLARJ")) 11 F S DOLLARJ=$O(^HLTMP("CLIENT UPDATES",DOLLARJ)) Q:DOLLARJ="" D Q:SUCCESS 12 .L +^HLTMP("CLIENT UPDATES",DOLLARJ):0 13 .Q:'$T 14 .N TIME S TIME=$O(^HLTMP("CLIENT UPDATES",DOLLARJ,"")) 15 .I $$FMDIFF^XLFDT(NOW,TIME,2)<2 L -^HLTMP("CLIENT UPDATES",DOLLARJ) Q 16 .S SUCCESS=1 17 ; 18 I OLD'="",'SUCCESS F S DOLLARJ=$O(^HLTMP("CLIENT UPDATES",DOLLARJ)) Q:DOLLARJ="" Q:DOLLARJ>OLD D Q:SUCCESS 19 .L +^HLTMP("CLIENT UPDATES",DOLLARJ):0 20 .Q:'$T 21 .N TIME S TIME=$O(^HLTMP("CLIENT UPDATES",DOLLARJ,"")) 22 .I $$FMDIFF^XLFDT(NOW,TIME,2)<2 L -^HLTMP("CLIENT UPDATES",DOLLARJ) Q 23 .S SUCCESS=1 24 S WORK("DOLLARJ")=DOLLARJ,WORK("NOW")=NOW 25 Q $S($L(WORK("DOLLARJ")):1,1:0) 26 ; 27 DOWORK(WORK) ; 28 ; 29 N DOLLARJ,TIME,IEN,PARMS,SYSTEM 30 S TIME="" 31 S DOLLARJ=WORK("DOLLARJ") 32 D SYSPARMS^HLOSITE(.SYSTEM) 33 F S TIME=$O(^HLTMP("CLIENT UPDATES",DOLLARJ,TIME)) Q:TIME="" Q:$$FMDIFF^XLFDT(WORK("NOW"),TIME,2)<2 D 34 .S IEN=0 35 .F S IEN=$O(^HLTMP("CLIENT UPDATES",DOLLARJ,TIME,IEN)) Q:'IEN D 36 ..N NODE 37 ..S NODE=$G(^HLTMP("CLIENT UPDATES",DOLLARJ,TIME,IEN)) 38 ..S PARMS("LINK")=$P(NODE,"^") 39 ..S PARMS("QUEUE")=$P(NODE,"^",2) 40 ..S PARMS("STATUS")=$P(NODE,"^",3) 41 ..S PARMS("PURGE TYPE")=$P(NODE,"^",4) 42 ..S PARMS("ACK TO IEN")=+$P($P(NODE,"^",4),"-",2) 43 ..S PARMS("ACCEPT ACK")=$P(NODE,"^",5) 44 ..S PARMS("RECEIVING APP")=$P(NODE,"^",6) 45 ..S:PARMS("RECEIVING APP")="" PARMS("RECEIVING APP")="UNKNOWN RECEIVING APPLICATION" 46 ..S PARMS("MSA")=$G(^HLTMP("CLIENT UPDATES",DOLLARJ,TIME,IEN,"MSA")) 47 ..S PARMS("ACTION")=$G(^HLTMP("CLIENT UPDATES",DOLLARJ,TIME,IEN,"ACTION")) 48 ..D UPDATE(IEN,TIME,.PARMS) 49 ..K ^HLTMP("CLIENT UPDATES",DOLLARJ,TIME,IEN) 50 L -^HLTMP("CLIENT UPDATES",DOLLARJ) 51 Q 52 ; 53 UPDATE(MSGIEN,TIME,PARMS) ; 54 S:PARMS("STATUS")]"" $P(^HLB(MSGIEN,0),"^",20)=PARMS("STATUS") 55 I PARMS("STATUS")="ER" D 56 .S ^HLB("ERRORS",PARMS("RECEIVING APP"),TIME,MSGIEN_"^")="" 57 .D COUNT^HLOESTAT("OUT",PARMS("RECEIVING APP"),$$GETSAP(MSGIEN),$$GETMTYPE(MSGIEN)) 58 S:PARMS("ACCEPT ACK") $P(^HLB(MSGIEN,0),"^",17)=PARMS("ACCEPT ACK") 59 S $P(^HLB(MSGIEN,0),"^",16)=TIME 60 S:PARMS("MSA")]"" ^HLB(MSGIEN,4)=TIME_"^"_PARMS("MSA") 61 I PARMS("PURGE TYPE"),PARMS("ACTION")="" D 62 .;don't set purge if going on the infiler - let infiler do it 63 .N PTIME 64 .S:(PARMS("PURGE TYPE")=2) PTIME=$$FMADD^XLFDT(TIME,SYSTEM("ERROR PURGE")) ;error purge is in days 65 .S:(PARMS("PURGE TYPE")'=2) PTIME=$$FMADD^XLFDT(TIME,,SYSTEM("NORMAL PURGE")) ;normal purge is in hours 66 .S $P(^HLB(MSGIEN,0),"^",9)=PTIME,^HLB("AD","OUT",PTIME,MSGIEN)="" 67 .I PARMS("ACK TO IEN"),$D(^HLB(PARMS("ACK TO IEN"),0)) S $P(^HLB(PARMS("ACK TO IEN"),0),"^",9)=PTIME,^HLB("AD","OUT",PTIME,PARMS("ACK TO IEN"))="" 68 D:PARMS("ACTION")]"" 69 .N PURGE 70 .S PURGE=$S(PARMS("PURGE TYPE"):1,1:0) 71 .S:PARMS("ACK TO IEN") PURGE("ACKTOIEN")=PARMS("ACK TO IEN") 72 .D INQUE^HLOQUE(PARMS("LINK"),PARMS("QUEUE"),MSGIEN,PARMS("ACTION"),.PURGE) 73 Q 74 ; 75 GETMSG(IEN,MSG) ; 76 ; 77 ;Description: given the message ien=MSGIEN (required), it returns the MSG array containing information about the message, defined below. 78 ;Input: 79 ; IEN - the ien of the message in file 778 80 ;Output: 81 ; Function returns 1 on success, 0 on failure 82 ; MSG (pass by reference, required) These are the subscripts returned: 83 ; "ACCEPT ACK RESPONSE" - if the sending app requested notification of the accept ack, this is the routine to perform 84 ; "ACKTOIEN" - if this is an app ack to a message not in a batch, this is the ien of the original message 85 ; "BATCH" = 1 if this is a batch message, 0 if not 86 ; "CURRENT MESSAGE" - defined only for batch messages - a counterused during building and parsing messages to indicate the current message. It will be set to 0 initially. 87 ; "BODY" - ptr to file 778 which contains the body of the message. 88 ; "LINE COUNT" - a counter used during writing of the 89 ; messages to indicate the current line. For 90 ; batch messages where each message within the batch is stored 91 ; separately, this field indicates the position within the current 92 ; individual message 93 ; "HDR" at these lower subscripts: 94 ; 1 - components 1-6 95 ; 2 - components 7-end 96 ; "ACCEPT ACK TYPE" = "AL" or "NE" 97 ; "APP ACK TYPE" = "AL" or "NE" 98 ; "MESSAGE CONTROL ID" - defined if NOT batch 99 ; "BATCH CONTROL ID" - defined if batch 100 ; 101 ; "ID" - message id from the header 102 ; "IEN" - ien, file 778 103 ; "STATUS","SEQUENCE QUEUE")=name of the sequence queue (optional) 104 ; 105 K MSG 106 Q:'$G(IEN) 0 107 N NODE,FS,CS,REP,SUBCOMP,ESCAPE 108 S MSG("IEN")=IEN 109 S NODE=$G(^HLB(IEN,0)) 110 S MSG("BODY")=$P(NODE,"^",2) 111 S MSG("ID")=$P(NODE,"^") 112 Q:'MSG("BODY") 0 113 S MSG("STATUS","ACCEPTED")=$P(NODE,"^",17) 114 S MSG("DT/TM")=$P(NODE,"^",16) 115 S MSG("STATUS","QUEUE")=$P(NODE,"^",6) 116 I MSG("STATUS","QUEUE")="" S MSG("STATUS","QUEUE")="DEFAULT" 117 S MSG("ACCEPT ACK RESPONSE")=$P(NODE,"^",12,13) 118 I MSG("ACCEPT ACK RESPONSE")="^" S MSG("ACCEPT ACK RESPONSE")="" 119 ; 120 S MSG("BATCH")=+$P($G(^HLA(MSG("BODY"),0)),"^",2) 121 I MSG("BATCH") D 122 .S MSG("BATCH","CURRENT MESSAGE")=0 123 E D 124 .N ACKTO 125 .S ACKTO=$P(NODE,"^",3) 126 .I ACKTO]"" S ACKTO=$$ACKTOIEN^HLOMSG1(MSG("ID"),ACKTO) 127 .I ACKTO,+ACKTO=ACKTO S MSG("ACK TO IEN")=ACKTO 128 S MSG("LINE COUNT")=0 129 S MSG("HDR",1)=$G(^HLB(IEN,1)) 130 S MSG("HDR",2)=$G(^HLB(IEN,2)) 131 S FS=$E(MSG("HDR",1),4) 132 S CS=$E(MSG("HDR",1),5) 133 S REP=$E(MSG("HDR",1),6) 134 S ESCAPE=$E(MSG("HDR",1),7) 135 S SUBCOMP=$E(MSG("HDR",1),8) 136 S MSG("HDR","FIELD SEPARATOR")=FS 137 S MSG("HDR","SENDING APPLICATION")=$$DESCAPE^HLOPRS1($P($P(MSG("HDR",1),FS,3),CS),FS,CS,SUBCOMP,REP,ESCAPE) 138 S MSG("HDR","RECEIVING APPLICATION")=$$DESCAPE^HLOPRS1($P($P(MSG("HDR",1),FS,5),CS),FS,CS,SUBCOMP,REP,ESCAPE) 139 I 'MSG("BATCH") D 140 .S MSG("HDR","MESSAGE TYPE")=$P($P(MSG("HDR",2),FS,4),CS) 141 .S MSG("HDR","EVENT")=$P($P(MSG("HDR",2),FS,4),CS,2) 142 .S MSG("HDR","ACCEPT ACK TYPE")=$E($P(MSG("HDR",2),FS,10),1,2) 143 .S MSG("HDR","APP ACK TYPE")=$E($P(MSG("HDR",2),FS,11),1,2) 144 .S MSG("HDR","MESSAGE CONTROL ID")=MSG("ID") 145 E D 146 .S MSG("HDR","BATCH CONTROL ID")=MSG("ID") 147 .S MSG("HDR","ACCEPT ACK TYPE")=$E($P($P(MSG("HDR",2),FS,4),"ACCEPT ACK TYPE=",2),1,2) 148 .S MSG("HDR","APP ACK TYPE")=$E($P($P(MSG("HDR",2),FS,4),"APP ACK TYPE=",2),1,2) 149 S MSG("STATUS","SEQUENCE QUEUE")=$P($G(^HLB(IEN,5)),"^") 150 Q 1 151 ; 152 GETMTYPE(MSGIEN) ;returns <message type>~<event> OR "BATCH" 153 Q:'$G(MSGIEN) "UNKNOWN" 154 N FS,CS,HDR1,HDR2 155 S HDR1=$G(^HLB(IEN,1)) 156 I $E(HDR1,1,3)="BHS" Q "BATCH" 157 S HDR2=$G(^HLB(IEN,2)) 158 S FS=$E(HDR1,4) 159 S CS=$E(HDR1,5) 160 Q $P($P(HDR2,FS,4),CS)_"~"_$P($P(HDR2,FS,4),CS,2) 161 ; 162 GETEVENT(MSGIEN) ; returns event if not a batch message 163 Q:'$G(MSGIEN) "" 164 N FS,CS,HDR1,HDR2 165 S HDR1=$G(^HLB(MSGIEN,1)) 166 I $E(HDR1,1,3)="BHS" Q "" 167 S HDR2=$G(^HLB(MSGIEN,2)) 168 S FS=$E(HDR1,4) 169 S CS=$E(HDR1,5) 170 Q $P($P(HDR2,FS,4),CS,2) 171 ; 172 GETSAP(MSGIEN) ; 173 ; 174 ; 175 Q:'$G(MSGIEN) "UNKNOWN" 176 N FS,CS,HDR1,REP,ESCAPE,SUBCOMP 177 S HDR1=$G(^HLB(MSGIEN,1)) 178 S FS=$E(HDR1,4) 179 S CS=$E(HDR1,5) 180 S REP=$E(HDR1,6) 181 S ESCAPE=$E(HDR1,7) 182 S SUBCOMP=$E(HDR1,8) 183 Q $$DESCAPE^HLOPRS1($P($P(HDR1,FS,3),CS),FS,CS,SUBCOMP,REP,ESCAPE) 1 HLOCLNT2 ;ALB/CJM- Performs message updates for the client - 10/4/94 1pm ;03/09/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,130,131,133,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 GETWORK(WORK) ; 6 ; 7 N OLD,DOLLARJ,SUCCESS,NOW 8 S SUCCESS=0 9 S NOW=$$NOW^XLFDT 10 S (OLD,DOLLARJ)=$G(WORK("DOLLARJ")) 11 F S DOLLARJ=$O(^HLTMP("CLIENT UPDATES",DOLLARJ)) Q:DOLLARJ="" D Q:SUCCESS 12 .L +^HLTMP("CLIENT UPDATES",DOLLARJ):0 13 .Q:'$T 14 .N TIME S TIME=$O(^HLTMP("CLIENT UPDATES",DOLLARJ,"")) 15 .I $$FMDIFF^XLFDT(NOW,TIME,2)<2 L -^HLTMP("CLIENT UPDATES",DOLLARJ) Q 16 .S SUCCESS=1 17 ; 18 I OLD'="",'SUCCESS F S DOLLARJ=$O(^HLTMP("CLIENT UPDATES",DOLLARJ)) Q:DOLLARJ="" Q:DOLLARJ>OLD D Q:SUCCESS 19 .L +^HLTMP("CLIENT UPDATES",DOLLARJ):0 20 .Q:'$T 21 .N TIME S TIME=$O(^HLTMP("CLIENT UPDATES",DOLLARJ,"")) 22 .I $$FMDIFF^XLFDT(NOW,TIME,2)<2 L -^HLTMP("CLIENT UPDATES",DOLLARJ) Q 23 .S SUCCESS=1 24 S WORK("DOLLARJ")=DOLLARJ,WORK("NOW")=NOW 25 Q $S($L(WORK("DOLLARJ")):1,1:0) 26 ; 27 DOWORK(WORK) ; 28 ; 29 N DOLLARJ,TIME,IEN,PARMS,SYSTEM 30 S TIME="" 31 S DOLLARJ=WORK("DOLLARJ") 32 D SYSPARMS^HLOSITE(.SYSTEM) 33 F S TIME=$O(^HLTMP("CLIENT UPDATES",DOLLARJ,TIME)) Q:TIME="" Q:$$FMDIFF^XLFDT(WORK("NOW"),TIME,2)<2 D 34 .S IEN=0 35 .F S IEN=$O(^HLTMP("CLIENT UPDATES",DOLLARJ,TIME,IEN)) Q:'IEN D 36 ..N NODE 37 ..S NODE=$G(^HLTMP("CLIENT UPDATES",DOLLARJ,TIME,IEN)) 38 ..S PARMS("LINK")=$P(NODE,"^") 39 ..S PARMS("QUEUE")=$P(NODE,"^",2) 40 ..S PARMS("STATUS")=$P(NODE,"^",3) 41 ..S PARMS("PURGE TYPE")=$P(NODE,"^",4) 42 ..S PARMS("ACK TO IEN")=+$P($P(NODE,"^",4),"-",2) 43 ..S PARMS("ACCEPT ACK")=$P(NODE,"^",5) 44 ..S PARMS("RECEIVING APP")=$P(NODE,"^",6) 45 ..S:PARMS("RECEIVING APP")="" PARMS("RECEIVING APP")="UNKNOWN RECEIVING APPLICATION" 46 ..S PARMS("MSA")=$G(^HLTMP("CLIENT UPDATES",DOLLARJ,TIME,IEN,"MSA")) 47 ..S PARMS("ACTION")=$G(^HLTMP("CLIENT UPDATES",DOLLARJ,TIME,IEN,"ACTION")) 48 ..D UPDATE(IEN,TIME,.PARMS) 49 ..K ^HLTMP("CLIENT UPDATES",DOLLARJ,TIME,IEN) 50 L -^HLTMP("CLIENT UPDATES",DOLLARJ) 51 Q 52 ; 53 UPDATE(MSGIEN,TIME,PARMS) ; 54 S:PARMS("STATUS")]"" $P(^HLB(MSGIEN,0),"^",20)=PARMS("STATUS") 55 S:PARMS("STATUS")="SE" ^HLB("ERRORS","SE",PARMS("RECEIVING APP"),TIME,MSGIEN)="" 56 S:PARMS("STATUS")="AE" ^HLB("ERRORS","AE",PARMS("RECEIVING APP"),TIME,MSGIEN_"^")="" 57 I PARMS("STATUS")["E" D COUNT^HLOESTAT("OUT",PARMS("RECEIVING APP"),$$GETSAP(MSGIEN),$$GETMTYPE(MSGIEN)) 58 S:PARMS("ACCEPT ACK") $P(^HLB(MSGIEN,0),"^",17)=PARMS("ACCEPT ACK") 59 S $P(^HLB(MSGIEN,0),"^",16)=TIME 60 S:PARMS("MSA")]"" ^HLB(MSGIEN,4)=TIME_"^"_PARMS("MSA") 61 I PARMS("PURGE TYPE"),PARMS("ACTION")="" D 62 .;don't set purge if going on the infiler - let infiler do it 63 .N PTIME 64 .S:(PARMS("PURGE TYPE")=2) PTIME=$$FMADD^XLFDT(TIME,SYSTEM("ERROR PURGE")) ;error purge is in days 65 .S:(PARMS("PURGE TYPE")'=2) PTIME=$$FMADD^XLFDT(TIME,,SYSTEM("NORMAL PURGE")) ;normal purge is in hours 66 .S $P(^HLB(MSGIEN,0),"^",9)=PTIME,^HLB("AD","OUT",PTIME,MSGIEN)="" 67 .I PARMS("ACK TO IEN"),$D(^HLB(PARMS("ACK TO IEN"),0)) S $P(^HLB(PARMS("ACK TO IEN"),0),"^",9)=PTIME,^HLB("AD","OUT",PTIME,PARMS("ACK TO IEN"))="" 68 D:PARMS("ACTION")]"" 69 .N PURGE 70 .S PURGE=$S(PARMS("PURGE TYPE"):1,1:0) 71 .S:PARMS("ACK TO IEN") PURGE("ACKTOIEN")=PARMS("ACK TO IEN") 72 .D INQUE^HLOQUE(PARMS("LINK"),PARMS("QUEUE"),MSGIEN,PARMS("ACTION"),.PURGE) 73 Q 74 ; 75 GETMSG(IEN,MSG) ; 76 ; 77 ;Description: given the message ien=MSGIEN (required), it returns the MSG array containing information about the message, defined below. 78 ;Input: 79 ; IEN - the ien of the message in file 778 80 ;Output: 81 ; Function returns 1 on success, 0 on failure 82 ; MSG (pass by reference, required) These are the subscripts returned: 83 ; "ACCEPT ACK RESPONSE" - if the sending app requested notification of the accept ack, this is the routine to perform 84 ; "ACKTOIEN" - if this is an app ack to a message not in a batch, this is the ien of the original message 85 ; "BATCH" = 1 if this is a batch message, 0 if not 86 ; "CURRENT MESSAGE" - defined only for batch messages - a counterused during building and parsing messages to indicate the current message. It will be set to 0 initially. 87 ; "BODY" - ptr to file 778 which contains the body of the message. 88 ; "LINE COUNT" - a counter used during writing of the 89 ; messages to indicate the current line. For 90 ; batch messages where each message within the batch is stored 91 ; separately, this field indicates the position within the current 92 ; individual message 93 ; "HDR" at these lower subscripts: 94 ; 1 - components 1-6 95 ; 2 - components 7-end 96 ; "ACCEPT ACK TYPE" = "AL" or "NE" 97 ; "APP ACK TYPE" = "AL" or "NE" 98 ; "MESSAGE CONTROL ID" - defined if NOT batch 99 ; "BATCH CONTROL ID" - defined if batch 100 ; 101 ; "ID" - message id from the header 102 ; "IEN" - ien, file 778 103 ; 104 K MSG 105 Q:'$G(IEN) 0 106 N NODE,FS,CS,REP,SUBCOMP,ESCAPE 107 S MSG("IEN")=IEN 108 S NODE=$G(^HLB(IEN,0)) 109 S MSG("BODY")=$P(NODE,"^",2) 110 S MSG("ID")=$P(NODE,"^") 111 Q:'MSG("BODY") 0 112 S MSG("STATUS","ACCEPTED")=$P(NODE,"^",17) 113 S MSG("DT/TM")=$P(NODE,"^",16) 114 S MSG("STATUS","QUEUE")=$P(NODE,"^",6) 115 I MSG("STATUS","QUEUE")="" S MSG("STATUS","QUEUE")="DEFAULT" 116 S MSG("ACCEPT ACK RESPONSE")=$P(NODE,"^",12,13) 117 I MSG("ACCEPT ACK RESPONSE")="^" S MSG("ACCEPT ACK RESPONSE")="" 118 ; 119 S MSG("BATCH")=+$P($G(^HLA(MSG("BODY"),0)),"^",2) 120 I MSG("BATCH") D 121 .S MSG("BATCH","CURRENT MESSAGE")=0 122 E D 123 .N ACKTO 124 .S ACKTO=$P(NODE,"^",3) 125 .I ACKTO]"" S ACKTO=$$ACKTOIEN^HLOMSG1(MSG("ID"),ACKTO) 126 .I ACKTO,+ACKTO=ACKTO S MSG("ACK TO IEN")=ACKTO 127 S MSG("LINE COUNT")=0 128 S MSG("HDR",1)=$G(^HLB(IEN,1)) 129 S MSG("HDR",2)=$G(^HLB(IEN,2)) 130 S FS=$E(MSG("HDR",1),4) 131 S CS=$E(MSG("HDR",1),5) 132 S REP=$E(MSG("HDR",1),6) 133 S ESCAPE=$E(MSG("HDR",1),7) 134 S SUBCOMP=$E(MSG("HDR",1),8) 135 S MSG("HDR","FIELD SEPARATOR")=FS 136 S MSG("HDR","SENDING APPLICATION")=$$DESCAPE^HLOPRS1($P($P(MSG("HDR",1),FS,3),CS),FS,CS,SUBCOMP,REP,ESCAPE) 137 S MSG("HDR","RECEIVING APPLICATION")=$$DESCAPE^HLOPRS1($P($P(MSG("HDR",1),FS,5),CS),FS,CS,SUBCOMP,REP,ESCAPE) 138 I 'MSG("BATCH") D 139 .S MSG("HDR","MESSAGE TYPE")=$P($P(MSG("HDR",2),FS,4),CS) 140 .S MSG("HDR","EVENT")=$P($P(MSG("HDR",2),FS,4),CS,2) 141 .S MSG("HDR","ACCEPT ACK TYPE")=$E($P(MSG("HDR",2),FS,10),1,2) 142 .S MSG("HDR","APP ACK TYPE")=$E($P(MSG("HDR",2),FS,11),1,2) 143 .S MSG("HDR","MESSAGE CONTROL ID")=MSG("ID") 144 E D 145 .S MSG("HDR","BATCH CONTROL ID")=MSG("ID") 146 .S MSG("HDR","ACCEPT ACK TYPE")=$E($P($P(MSG("HDR",2),FS,4),"ACCEPT ACK TYPE=",2),1,2) 147 .S MSG("HDR","APP ACK TYPE")=$E($P($P(MSG("HDR",2),FS,4),"APP ACK TYPE=",2),1,2) 148 Q 1 149 ; 150 GETMTYPE(MSGIEN) ;returns <message type>~<event> OR "BATCH" 151 Q:'$G(MSGIEN) "UNKNOWN" 152 N FS,CS,HDR1,HDR2 153 S HDR1=$G(^HLB(IEN,1)) 154 I $E(HDR1,1,3)="BHS" Q "BATCH" 155 S HDR2=$G(^HLB(IEN,2)) 156 S FS=$E(HDR1,4) 157 S CS=$E(HDR1,5) 158 Q $P($P(HDR2,FS,4),CS)_"~"_$P($P(HDR2,FS,4),CS,2) 159 ; 160 GETEVENT(MSGIEN) ; returns event if not a batch message 161 Q:'$G(MSGIEN) "" 162 N FS,CS,HDR1,HDR2 163 S HDR1=$G(^HLB(MSGIEN,1)) 164 I $E(HDR1,1,3)="BHS" Q "" 165 S HDR2=$G(^HLB(MSGIEN,2)) 166 S FS=$E(HDR1,4) 167 S CS=$E(HDR1,5) 168 Q $P($P(HDR2,FS,4),CS,2) 169 ; 170 GETSAP(MSGIEN) ; 171 ; 172 ; 173 Q:'$G(MSGIEN) "UNKNOWN" 174 N FS,CS,HDR1,REP,ESCAPE,SUBCOMP 175 S HDR1=$G(^HLB(MSGIEN,1)) 176 S FS=$E(HDR1,4) 177 S CS=$E(HDR1,5) 178 S REP=$E(HDR1,6) 179 S ESCAPE=$E(HDR1,7) 180 S SUBCOMP=$E(HDR1,8) 181 Q $$DESCAPE^HLOPRS1($P($P(HDR1,FS,3),CS),FS,CS,SUBCOMP,REP,ESCAPE) -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOCLNT3.m
r613 r623 1 HLOCLNT3 ;ALB/CJM- Updates messages missing application acks - 10/4/94 1pm ;07/10/20072 ;;1.6;HEALTH LEVEL SEVEN;**126,130,134,137**;Oct 13, 1995;Build 21 3 4 5 DOWORK(WORK) 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 .S $P(^HLB(MSGIEN,0),"^",20)="ER"32 33 34 35 .S ^HLB("ERRORS",$S($L(HDR("RECEIVING APPLICATION")):HDR("RECEIVING APPLICATION"),1:"UNKNOWN"),NOW,MSGIEN)=""36 37 38 39 1 HLOCLNT3 ;ALB/CJM- Updates messages missing application acks - 10/4/94 1pm ;03/22/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,130,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 DOWORK(WORK) ; 6 ; 7 N CUTOFF,MSGIEN,QUIT,NOW,SYSTEM 8 S NOW=$$NOW^XLFDT 9 S QUIT=0 10 D SYSPARMS^HLOSITE(.SYSTEM) 11 S PURGE=$$FMADD^XLFDT($$NOW^XLFDT,,24*SYSTEM("ERROR PURGE")) 12 ; 13 ;7 day wait for an application ack is more than reasonable 14 S CUTOFF=$$FMADD^XLFDT(NOW,-3) 15 ; 16 S MSGIEN=+$G(^HLTMP("LAST IEN CHECKED FOR MISSING APPLICATION ACK")) 17 F S MSGIEN=$O(^HLB(MSGIEN)) Q:'MSGIEN Q:MSGIEN>99999999999 D Q:QUIT 18 .N MSG,HDR 19 .Q:'$$GETMSG^HLOMSG(MSGIEN,.MSG) 20 .Q:'MSG("DT/TM") 21 .Q:'MSG("BODY") 22 .I MSG("DT/TM")>CUTOFF S:MSG("DT/TM CREATED")>CUTOFF QUIT=1,MSGIEN=MSGIEN-1 Q 23 .Q:MSG("STATUS")'="" 24 .Q:MSG("DIRECTION")'="OUT" 25 .Q:MSG("BATCH") 26 .Q:MSG("STATUS","APP ACK'D") 27 .;Q:MSG("STATUS","APP ACK RESPONSE")="" 28 .;message has been in a non-complete status for a longtime, pending an application ack - set status to error and schedule for purging 29 .S $P(^HLB(MSGIEN,0),"^",9)=PURGE 30 .S ^HLB("AD","OUT",PURGE,MSGIEN)="" 31 .S $P(^HLB(MSGIEN,0),"^",20)="AE" 32 .S $P(^HLB(MSGIEN,0),"^",21)="MISSING APPLICATION ACKNOWLEDGMENT" 33 .M HDR=MSG("HDR") 34 .Q:'$$PARSEHDR^HLOPRS(.HDR) 35 .S ^HLB("ERRORS","AE",$S($L(HDR("RECEIVING APPLICATION")):HDR("RECEIVING APPLICATION"),1:"UNKNOWN"),NOW,MSGIEN)="" 36 .D COUNT^HLOESTAT("OUT",HDR("RECEIVING APPLICATION"),HDR("SENDING APPLICATION"),$S(MSG("BATCH"):"BATCH",1:$G(HDR("MESSAGE TYPE"))),$G(HDR("EVENT"))) 37 S:MSGIEN>99999999999 MSGIEN=0 38 S ^HLTMP("LAST IEN CHECKED FOR MISSING APPLICATION ACK")=MSGIEN 39 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOCNRT.m
r613 r623 1 HLOCNRT ;DAOU/ALA-Generate HL7 Optimized Message ;07/24/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,132,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ;**Program Description** 6 ; This program takes a current HL7 1.6 message and converts 7 ; it to use the new HL Optimized code if it follows the standard 8 ; 1.6 methodology of protocols. 9 ; 10 ; **If the VistA HL7 Protocol does not exist, calls to HL Optimized 11 ; will have to be coded separately and this program cannot be used** 12 Q 13 ; 14 EN(HLOPRTCL,ARYTYP,HLP,HLL,RESULT) ;Entry Point 15 ; Input Parameters 16 ; HLOPRTCL = Protocol IEN or Protocol Name 17 ; ARYTYP = The array where HL7 message resides 18 ; HLP = Additional HL7 message parameters (optional, pass by reference) 19 ; These optional subscripts to HLP are supported for input: 20 ; "APP ACK RESPONSE" = <tag^routine> to call when the app ack is received 21 ; "CONTPTR" 22 ; "SECURITY" 23 ; "SEQUENCE QUEUE" - queue used to maintain the order of the messages via application acks. If used, the application MUST specify that both an accept ack and application ack be returned. 24 ; 25 ; HLL (optional, pass by reference) Additional message recipients being dynamically added 26 ; 27 ; Output 28 ; RESULT (pass-by-reference)=<subscriber protocol ien>^<link ien>^<message id>^<0 if sucess, error code if failure>^<optional error message> 29 ; If the message was sent to more than 1 destination, 30 ; the addtional mssage ids returned as RESULT(1), RESULT(2), etc. 31 ; ZTSTOP = Stop processing flag (used by HDR) 32 ; Function returns 1 on success, else returns an error message 33 ; 34 NEW HLORESL,HLMSTATE,APPARMS,WHOTO,ERROR,WHO 35 S ZTSTOP=0,HLORESL=1,RESULT="" 36 ; 37 ; Get IEN of protocol if name is passed 38 I '$L(HLOPRTCL) S HLORESL="^99^HL7 1.6 Protocol not found",RESULT="^^"_HLORESL,ZTSTOP=1 Q HLORESL 39 I ('HLOPRTCL)!(HLOPRTCL'=+HLOPRTCL) S HLOPRTCL=+$O(^ORD(101,"B",HLOPRTCL,0)) 40 I 'HLOPRTCL S HLORESL="^99^HL7 1.6 Protocol not found",RESULT="^^"_HLORESL,ZTSTOP=1 Q HLORESL 41 I '$D(^ORD(101,HLOPRTCL)) S HLORESL="^99^HL7 1.6 Protocol not found",RESULT="^^"_HLORESL,ZTSTOP=1 Q HLORESL 42 ; 43 ; If the VistA HL7 Protocol exists, call the Conversion Utility 44 ; to set up the APPARMS, WHOTO arrays from protocol logical link, 45 ; and the optional HLL and HLP arrays 46 D APAR^HLOCVU(HLOPRTCL,.APPARMS,.WHO,.WHOTO,.HLP,.HLL) 47 ; 48 ; If special HLP parameters are defined, convert them 49 I $D(HLP) D 50 . I $G(HLP("SECURITY"))'="" S APPARMS("SECURITY")=HLP("SECURITY") 51 . I $G(HLP("CONTPTR"))'="" S APPARMS("CONTINUATION POINTER")=HLP("CONTPTR") 52 . I $G(HLP("QUEUE"))'="" S APPARMS("QUEUE")=HLP("QUEUE") 53 . I $G(HLP("SEQUENCE QUEUE"))'="" S APPARMS("SEQUENCE QUEUE")=HLP("SEQUENCE QUEUE") 54 . I $G(HLP("APP ACK RESPONSE"))'="" S APPARMS("APP ACK RESPONSE")=HLP("APP ACK RESPONSE") 55 ; 56 ; Create HL Optimized message 57 I '$$NEWMSG^HLOAPI(.APPARMS,.HLMSTATE,.ERROR) S HLORESL="^99^"_ERROR,ZTSTOP=1,RESULT="^^"_HLORESL Q HLORESL 58 I $E(ARYTYP,1)="G" S HLOMESG="^TMP(""HLS"",$J)" 59 I $E(ARYTYP,1)="L" S HLOMESG="HLA(""HLS"")" 60 ; 61 ; Move the existing message from array into HL Optimized 62 D MOVEMSG^HLOAPI(.HLMSTATE,HLOMESG) 63 ; 64 ; Send message via HL Optimized 65 I $D(WHOTO) D 66 .N COUNT 67 .I '$$SENDMANY^HLOAPI1(.HLMSTATE,.APPARMS,.WHOTO) D 68 ..S HLORESL="^99^Unable to send message",ZTSTOP=1 69 .I $G(WHOTO(1,"IEN")) D 70 ..S RESULT=WHO(1)_"^"_$P($G(^HLB(WHOTO(1,"IEN"),0)),"^")_"^"_$S($G(WHOTO(1,"QUEUED")):0,1:1)_"^"_$G(WHOTO(1,"ERROR")) 71 .E D 72 ..S RESULT=WH0(1)_"^^1^"_$G(WHOTO(1,"ERROR")) 73 ..S HLORESL="^99^"_$G(WHOTO(1,"ERROR")),ZTSTOP=1 74 .S COUNT=1 75 .F S COUNT=$O(WHOTO(COUNT)) Q:'COUNT D 76 ..I $G(WHOTO(COUNT,"IEN")) D 77 ...S RESULT(COUNT-1)=WHO(COUNT)_"^"_$P($G(^HLB(WHOTO(COUNT,"IEN"),0)),"^")_"^"_$S($G(WHOTO(COUNT,"QUEUED")):0,1:1)_"^"_$G(WHOTO(COUNT,"ERROR")) 78 ..E D 79 ...S RESULT(COUNT-1)=WH0(COUNT)_"^^1^"_$G(WHOTO(COUNT,"ERROR")) 80 ; 81 E S HLORESL="^99^Unable to send message",ZTSTOP=1,RESULT="^^"_HLORESL 82 Q HLORESL 1 HLOCNRT ;DAOU/ALA-Generate HL7 Optimized Message ;03/15/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,132,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ;**Program Description** 6 ; This program takes a current HL7 1.6 message and converts 7 ; it to use the new HL Optimized code if it follows the standard 8 ; 1.6 methodology of protocols. 9 ; 10 ; **If the VistA HL7 Protocol does not exist, calls to HL Optimized 11 ; will have to be coded separately and this program cannot be used** 12 Q 13 ; 14 EN(HLOPRTCL,ARYTYP,HLP,HLL,RESULT) ;Entry Point 15 ; Input Parameters 16 ; HLOPRTCL = Protocol IEN or Protocol Name 17 ; ARYTYP = The array where HL7 message resides 18 ; HLP = Additional HL7 message parameters (optional, pass by reference) 19 ; These optional subscripts to HLL are supported for input: 20 ; "SECURITY" 21 ; "CONTPTR" 22 ; "APP ACK RESPONSE" = <tag^routine> to call when the app ack is received 23 ; 24 ; HLL (optional, pass by reference) Additional message recipients being dynamically added 25 ; 26 ; Output 27 ; RESULT (pass-by-reference)=<subscriber protocol ien>^<link ien>^<message id>^<0 if sucess, error code if failure>^<optional error message> 28 ; If the message was sent to more than 1 destination, 29 ; the addtional mssage ids returned as RESULT(1), RESULT(2), etc. 30 ; ZTSTOP = Stop processing flag (used by HDR) 31 ; Function returns 1 on success, else returns an error message 32 ; 33 NEW HLORESL,HLMSTATE,APPARMS,WHOTO,ERROR,WHO 34 S ZTSTOP=0,HLORESL=1,RESULT="" 35 ; 36 ; Get IEN of protocol if name is passed 37 I '$L(HLOPRTCL) S HLORESL="^99^HL7 1.6 Protocol not found",RESULT="^^"_HLORESL,ZTSTOP=1 Q HLORESL 38 I ('HLOPRTCL)!(HLOPRTCL'=+HLOPRTCL) S HLOPRTCL=+$O(^ORD(101,"B",HLOPRTCL,0)) 39 I 'HLOPRTCL S HLORESL="^99^HL7 1.6 Protocol not found",RESULT="^^"_HLORESL,ZTSTOP=1 Q HLORESL 40 I '$D(^ORD(101,HLOPRTCL)) S HLORESL="^99^HL7 1.6 Protocol not found",RESULT="^^"_HLORESL,ZTSTOP=1 Q HLORESL 41 ; 42 ; If the VistA HL7 Protocol exists, call the Conversion Utility 43 ; to set up the APPARMS, WHOTO arrays from protocol logical link, 44 ; and the optional HLL and HLP arrays 45 D APAR^HLOCVU(HLOPRTCL,.APPARMS,.WHO,.WHOTO,.HLP,.HLL) 46 ; 47 ; If special HLP parameters are defined, convert them 48 I $D(HLP) D 49 . I $G(HLP("SECURITY"))'="" S APPARMS("SECURITY")=HLP("SECURITY") 50 . I $G(HLP("CONTPTR"))'="" S APPARMS("CONTINUATION POINTER")=HLP("CONTPTR") 51 . I $G(HLP("QUEUE"))'="" S APPARMS("QUEUE")=HLP("QUEUE") 52 . I $G(HLP("APP ACK RESPONSE"))'="" S APPARMS("APP ACK RESPONSE")=HLP("APP ACK RESPONSE") 53 ; 54 ; Create HL Optimized message 55 I '$$NEWMSG^HLOAPI(.APPARMS,.HLMSTATE,.ERROR) S HLORESL="^99^"_ERROR,ZTSTOP=1,RESULT="^^"_HLORESL Q HLORESL 56 I $E(ARYTYP,1)="G" S HLOMESG="^TMP(""HLS"",$J)" 57 I $E(ARYTYP,1)="L" S HLOMESG="HLA(""HLS"")" 58 ; 59 ; Move the existing message from array into HL Optimized 60 D MOVEMSG^HLOAPI(.HLMSTATE,HLOMESG) 61 ; 62 ; Send message via HL Optimized 63 I $D(WHOTO) D 64 .N COUNT 65 .I '$$SENDMANY^HLOAPI1(.HLMSTATE,.APPARMS,.WHOTO) D 66 ..S HLORESL="^99^Unable to send message",ZTSTOP=1 67 .I $G(WHOTO(1,"IEN")) D 68 ..S RESULT=WHO(1)_"^"_$P($G(^HLB(WHOTO(1,"IEN"),0)),"^")_"^"_$S($G(WHOTO(1,"QUEUED")):0,1:1)_"^"_$G(WHOTO(1,"ERROR")) 69 .E D 70 ..S RESULT=WH0(1)_"^^1^"_$G(WHOTO(1,"ERROR")) 71 ..S HLORESL="^99^"_$G(WHOTO(1,"ERROR")),ZTSTOP=1 72 .S COUNT=1 73 .F S COUNT=$O(WHOTO(COUNT)) Q:'COUNT D 74 ..I $G(WHOTO(COUNT,"IEN")) D 75 ...S RESULT(COUNT-1)=WHO(COUNT)_"^"_$P($G(^HLB(WHOTO(COUNT,"IEN"),0)),"^")_"^"_$S($G(WHOTO(COUNT,"QUEUED")):0,1:1)_"^"_$G(WHOTO(COUNT,"ERROR")) 76 ..E D 77 ...S RESULT(COUNT-1)=WH0(COUNT)_"^^1^"_$G(WHOTO(COUNT,"ERROR")) 78 ; 79 E S HLORESL="^99^Unable to send message",ZTSTOP=1,RESULT="^^"_HLORESL 80 Q HLORESL -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOF778.m
r613 r623 1 HLOF778 ;ALB/CJM-HL7 - Saving messages to file 778 ;07/10/20072 ;;1.6;HEALTH LEVEL SEVEN;**126,134,137**;Oct 13, 1995;Build 21 3 4 5 6 SAVEMSG(HLMSTATE) 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 NEXTMSG(HLMSTATE,MSG) 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 ACKTO(HLMSTATE,ACKTO) 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 I (STATUS="ER"),'SKIP D145 146 .S APP=HLMSTATE("HDR","RECEIVING APPLICATION")147 148 .S ^HLB("ERRORS",APP,$$NOW^XLFDT,ACKTO("IEN"))=""149 150 151 1 HLOF778 ;ALB/CJM-HL7 - Saving messages to file 778 ;03/15/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ; 6 SAVEMSG(HLMSTATE) ; 7 ;If a record has not yet been created in file 778, then it will be created. Will file any segments into 777 not yet stored. For batch messages, will store the MSH segments in 778 as the individual messages are stored in 777. 8 ;Input: 9 ; HLMSTATE (pass by reference) - contains information about the message 10 ; These subscripts must be defined: 11 ; ("BATCH")=1 if batch, 0 otherwise 12 ; ("BATCH","BTS")=BTS segment if end of batch reached 13 ; ("BODY")=ien file 777 if stored 14 ; ("DIRECTION")=<"IN" or "OUT"> 15 ; ("IEN")=ien,file 778 if stored 16 ; ("UNSTORED LINES") - count of lines to be stored. The lines are at the a lower subscript level <msg>,<segment>,<line>=<line to be stored> 17 ; ("UNSTORED MSH") For batch messages, set to 1 if there are MSH in cache. Cached MSH at ("UNSTORED MSH",<subfile ien>,<1 & 2>) 18 ; 19 ;Output: 20 ; Function - returns the ien of the msg (file 778) 21 ; HLMSTATE 22 ; ("BODY") - set to ien, file 777 if newly created 23 ; ("IEN") - set to ien, file 778 if newly created 24 ; ("UNSTORED LINES")-set to 0 as this function will store them 25 ; ("UNSTORED MSH")- set to 0 as this function will store it 26 ; 27 ; 28 I '$D(HLMSTATE("DT/TM")) S HLMSTATE("DT/TM")=$S(HLMSTATE("DIRECTION")="IN":$$NOW^XLFDT,1:"") 29 ; 30 ;insure that 777 entry created & all segments stored 31 I ('HLMSTATE("BODY"))!($G(HLMSTATE("UNSTORED LINES")))!($L($G(HLMSTATE("BATCH","BTS")))),'$$SAVEMSG^HLOF777(.HLMSTATE) Q 0 32 ; 33 ;insure 778 entry created 34 I 'HLMSTATE("IEN") Q:'$$NEW^HLOF778A(.HLMSTATE) 0 35 ; 36 ;for batch messages, store MSH segments in 778 37 I HLMSTATE("BATCH") D 38 .N IEN S IEN=HLMSTATE("IEN") 39 .; 40 .;incoming messages cache the MSH segments in memory 41 .I HLMSTATE("DIRECTION")="IN",HLMSTATE("UNSTORED MSH") D 42 ..N ORDER S ORDER=0 43 ..F S ORDER=$O(HLMSTATE("UNSTORED MSH",ORDER)) Q:'ORDER D 44 ...N FS,MSGID 45 ...S FS=$E(HLMSTATE("UNSTORED MSH",ORDER,1),4) 46 ...S MSGID=$P(HLMSTATE("UNSTORED MSH",ORDER,2),FS,5) 47 ...S ^HLB(IEN,3,ORDER,0)=ORDER_"^"_MSGID_"^"_$G(HLMSTATE("BATCH","ACK TO",ORDER)) 48 ...S ^HLB(IEN,3,ORDER,1)=HLMSTATE("UNSTORED MSH",ORDER,1) 49 ...S ^HLB(IEN,3,ORDER,2)=HLMSTATE("UNSTORED MSH",ORDER,2) 50 ...S ^HLB(IEN,3,"B",ORDER,ORDER)="" 51 ...I MSGID]"" S ^HLB("AE",MSGID,IEN_"^"_ORDER)="" ;whole file index for individual message id 52 ..K HLMSTATE("UNSTORED MSH") S HLMSTATE("UNSTORED MSH")=0 53 .; 54 .; 55 .I HLMSTATE("DIRECTION")="OUT" D 56 ..;must build the MSH segments! 57 ..N HDR,FS,MSG,CS 58 ..S FS=HLMSTATE("HDR","FIELD SEPARATOR") 59 ..S CS=$E(HLMSTATE("HDR","ENCODING CHARACTERS"),1) 60 ..S HLMSTATE("HDR","MESSAGE TYPE")=" " 61 ..S HLMSTATE("HDR","EVENT")=" " 62 ..D BUILDHDR^HLOPBLD1(.HLMSTATE,"MSH",.HDR) 63 ..S HLMSTATE("BATCH","CURRENT MESSAGE")=$O(^HLB(HLMSTATE("IEN"),3,"B",";"),-1) 64 ..F Q:'$$NEXTMSG(.HLMSTATE,.MSG) D 65 ...N MSGID,CUR 66 ...S CUR=HLMSTATE("BATCH","CURRENT MESSAGE") 67 ...S MSGID=HLMSTATE("HDR","BATCH CONTROL ID")_"-"_CUR 68 ...S $P(HDR(2),FS,4)=MSG("MESSAGE TYPE")_CS_MSG("EVENT") 69 ...S $P(HDR(2),FS,5)=MSGID 70 ...S ^HLB(IEN,3,CUR,0)=CUR_"^"_MSGID_"^"_$G(HLMSTATE("BATCH","ACK TO",CUR)) 71 ...S ^HLB(IEN,3,CUR,1)=HDR(1) 72 ...S ^HLB(IEN,3,CUR,2)=HDR(2) 73 ...S ^HLB(IEN,3,"B",CUR,CUR)="" 74 ...S ^HLB("AE",MSGID,IEN_"^"_CUR)="" ;whole file index for individual message id 75 ..; 76 .;if the messages are application acks, then update the original message 77 .N SUBIEN S SUBIEN=0 78 .F S SUBIEN=$O(HLMSTATE("BATCH","ACK TO",SUBIEN)) Q:'SUBIEN I $G(HLMSTATE("BATCH","ACK TO",SUBIEN,"IEN"))]"" D 79 ..N ACKTO 80 ..M ACKTO=HLMSTATE("BATCH","ACK TO",SUBIEN) 81 ..; 82 ..;for outgoing msgs, we just created the msgid, for incoming msgs we already had it 83 ..S:HLMSTATE("DIRECTION")="OUT" ACKTO("ACK BY")=HLMSTATE("HDR","BATCH CONTROL ID")_"-"_SUBIEN 84 ..; 85 ..D ACKTO(.HLMSTATE,.ACKTO) 86 .K HLMSTATE("BATCH","ACK TO") 87 ; 88 ;if the msg is an app ack, update the original if not done already 89 I $G(HLMSTATE("ACK TO","IEN"))]"",'$G(HLMSTATE("ACK TO","DONE")) D 90 .N ACKTO 91 .M ACKTO=HLMSTATE("ACK TO") 92 .S ACKTO("ACK BY")=$S(HLMSTATE("BATCH"):HLMSTATE("HDR","BATCH CONTROL ID"),1:HLMSTATE("HDR","MESSAGE CONTROL ID")) 93 .D ACKTO(.HLMSTATE,.ACKTO) 94 .S HLMSTATE("ACK TO","DONE")=1 ;so the update isn't done again 95 ; 96 Q HLMSTATE("IEN") 97 ; 98 NEXTMSG(HLMSTATE,MSG) ; 99 ;Traverses file 777 to return the next message in the batch - as 100 ;indicated by HLMSTATE("BATCH","CURRENT MESSAGE") Set to 0 to start, 101 ;returns 0 when there are no more messages 102 ; 103 ;Input: HLMSTATE (pass by reference,required) 104 ;Output: 105 ; HLMSTATE 106 ; ("BATCH","CURRENT MESSAGE") 107 ; MSG -pass by reference: 108 ; ("EVENT") 109 ; ("MESSAGE TYPE") 110 ; 111 ; 112 N SUBIEN,NODE 113 K MSG 114 Q:'$G(HLMSTATE("BODY")) 0 115 S SUBIEN=$O(^HLA(HLMSTATE("BODY"),2,HLMSTATE("BATCH","CURRENT MESSAGE"))) 116 Q:'SUBIEN 0 117 S NODE=$G(^HLA(HLMSTATE("BODY"),2,SUBIEN,0)) 118 S MSG("MESSAGE TYPE")=$P(NODE,"^",2) 119 S MSG("EVENT")=$P(NODE,"^",3) 120 S HLMSTATE("BATCH","CURRENT MESSAGE")=SUBIEN 121 Q SUBIEN 122 ; 123 ACKTO(HLMSTATE,ACKTO) ;if this is an application ack, update the original message - but do not overlay if already valued 124 ;ACKTO = (msgid of msg being ack'd) 125 ; uses these subscripts ("IEN"=ien^subien),("ACK BY"=msgid of acking msg),("STATUS"=status for the initial msg determined by the ack) 126 ; 127 N STATUS,IEN,SUBIEN,NODE,SKIP 128 S SKIP=0 129 S STATUS=$G(ACKTO("STATUS")) 130 S IEN=+ACKTO("IEN"),SUBIEN=$P(ACKTO("IEN"),"^",2) 131 S NODE=$G(^HLB(IEN,0)) 132 I 'SUBIEN D 133 .;ack is to a message NOT in a batch 134 .I $P(NODE,"^",7)'="",$P(NODE,"^",7)'=ACKTO("ACK BY") S SKIP=1 Q 135 .I STATUS="" S STATUS="SU" 136 .S $P(NODE,"^",7)=ACKTO("ACK BY") 137 .S $P(NODE,"^",20)=STATUS 138 .S $P(NODE,"^",21)=$G(ACKTO("ERROR TEXT")) 139 .S ^HLB(IEN,0)=NODE 140 E D 141 .;ack is to a message that IS in a batch 142 .S $P(^HLB(IEN,3,SUBIEN,0),"^",4)=$G(ACKTO("ACK BY")) 143 .S $P(^HLB(IEN,3,SUBIEN,0),"^",5)=STATUS 144 I (STATUS="AE"),'SKIP D 145 .N APP 146 .S APP=HLMSTATE("HDR","SENDING APPLICATION") 147 .I APP="" S APP="UNKNOWN" 148 .S ^HLB("ERRORS","AE",APP,$$NOW^XLFDT,ACKTO("IEN"))="" 149 .;don't count the error - the app ack was already counted as an error. 150 .D COUNT^HLOESTAT("IN",$G(HLMSTATE("HDR","RECEIVING APPLICATION")),$G(HLMSTATE("HDR","SENDING APPLICATION")),$S(HLMSTATE("BATCH"):"BATCH",1:$G(HLMSTATE("HDR","MESSAGE TYPE"))),$G(HLMSTATE("HDR","EVENT"))) 151 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOF778A.m
r613 r623 1 HLOF778A ;ALB/CJM-HL7 - Saving messages to file 778 (continued) ;07/10/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ; 6 NEW(HLMSTATE) ; 7 ;This function creates a new entry in file 778. 8 ;Input: 9 ; HLMSTATE (required, pass by reference) These subscripts are expected: 10 ; 11 ;Output - the function returns the ien of the newly created record 12 ; 13 N IEN,NODE,ID,STAT 14 S STAT="HLMSTATE(""STATUS"")" 15 S IEN=$$NEWIEN(HLMSTATE("DIRECTION"),$$TCP) 16 Q:'IEN 0 17 S HLMSTATE("IEN")=IEN 18 ; 19 D ;build the message header 20 .N HDR 21 .;for incoming messages the header segment should already exist 22 .;for outgoing messages must build the header segment 23 .I HLMSTATE("DIRECTION")="OUT" D Q 24 ..I HLMSTATE("BATCH"),$G(HLMSTATE("ACK TO"))]"" S HLMSTATE("HDR","REFERENCE BATCH CONTROL ID")=HLMSTATE("ACK TO") 25 ..D BUILDHDR^HLOPBLD1(.HLMSTATE,$S(HLMSTATE("BATCH"):"BHS",1:"MSH"),.HDR) 26 ..S HLMSTATE("HDR",1)=HDR(1),HLMSTATE("HDR",2)=HDR(2) 27 ; 28 K ^HLB(IEN) 29 S ID=$S(HLMSTATE("BATCH"):HLMSTATE("HDR","BATCH CONTROL ID"),1:HLMSTATE("HDR","MESSAGE CONTROL ID")) 30 S NODE=ID_"^"_HLMSTATE("BODY")_"^"_$G(HLMSTATE("ACK TO"))_"^"_$S(HLMSTATE("DIRECTION")="IN":"I",1:"O")_"^" 31 S $P(NODE,"^",5)=$G(@STAT@("LINK NAME")) 32 S $P(NODE,"^",6)=$G(@STAT@("QUEUE")) 33 S $P(NODE,"^",8)=$G(@STAT@("PORT")) 34 S $P(NODE,"^",20)=$G(@STAT) 35 S $P(NODE,"^",21)=$G(@STAT@("ERROR TEXT")) 36 S $P(NODE,"^",16)=HLMSTATE("DT/TM") 37 ; 38 I HLMSTATE("DIRECTION")="OUT" D 39 .S $P(NODE,"^",10)=$P($G(@STAT@("APP ACK RESPONSE")),"^") 40 .S $P(NODE,"^",11)=$P($G(@STAT@("APP ACK RESPONSE")),"^",2) 41 .S $P(NODE,"^",12)=$P($G(@STAT@("ACCEPT ACK RESPONSE")),"^") 42 .S $P(NODE,"^",13)=$P($G(@STAT@("ACCEPT ACK RESPONSE")),"^",2) 43 .S $P(NODE,"^",14)=$P($G(@STAT@("FAILURE RESPONSE")),"^") 44 .S $P(NODE,"^",15)=$P($G(@STAT@("FAILURE RESPONSE")),"^",2) 45 .; 46 .;for outgoing set these x-refs now, for incoming msgs set them later 47 .S ^HLB("B",ID,IEN)="" 48 .S ^HLB("C",HLMSTATE("BODY"),IEN)="" 49 .I ($G(@STAT)="ER") D 50 ..S ^HLB("ERRORS",$S($L($G(HLMSTATE("HDR","RECEIVING APPLICATION"))):HLMSTATE("HDR","RECEIVING APPLICATION"),1:"UNKNOWN"),HLMSTATE("DT/TM CREATED"),IEN)="" 51 ..D COUNT^HLOESTAT("OUT",$G(HLMSTATE("HDR","RECEIVING APPLICATION")),$G(HLMSTATE("HDR","SENDING APPLICATION")),$S(HLMSTATE("BATCH"):"BATCH",1:$G(HLMSTATE("HDR","MESSAGE TYPE"))),$G(HLMSTATE("HDR","EVENT"))) 52 .; 53 .;save some space for the ack 54 .S:($G(HLMSTATE("HDR","ACCEPT ACK TYPE"))="AL") ^HLB(IEN,4)="^^^ " 55 I $G(HLMSTATE("STATUS","PURGE")) S $P(NODE,"^",9)=HLMSTATE("STATUS","PURGE"),^HLB("AD","OUT",HLMSTATE("STATUS","PURGE"),HLMSTATE("IEN"))="" 56 S ^HLB(IEN,0)=NODE 57 ; 58 ;store the message header 59 S ^HLB(IEN,1)=HLMSTATE("HDR",1) 60 S ^HLB(IEN,2)=HLMSTATE("HDR",2) 61 ; 62 ;if the msg is an app ack, update the original msg 63 I $G(HLMSTATE("ACK TO","IEN"))]"" D 64 .N ACKTO 65 .M ACKTO=HLMSTATE("ACK TO") 66 .S ACKTO("ACK BY")=$S(HLMSTATE("BATCH"):HLMSTATE("HDR","BATCH CONTROL ID"),1:HLMSTATE("HDR","MESSAGE CONTROL ID")) 67 .D ACKTO^HLOF778(.HLMSTATE,.ACKTO) 68 .S HLMSTATE("ACK TO","DONE")=1 ;because the update was already done, otherwise it might be done again 69 ; 70 ;The "SEARCH" x-ref will be created asynchronously 71 S ^HLTMP("PENDING SEARCH X-REF",$J,HLMSTATE("DT/TM CREATED"),IEN)="" 72 ; 73 ;sequence q? 74 I HLMSTATE("DIRECTION")="OUT",$G(@STAT@("SEQUENCE QUEUE"))'="" S ^HLB(IEN,5)=@STAT@("SEQUENCE QUEUE") 75 ; 76 Q IEN 77 ; 78 NEWIEN(DIR,TCP) ; 79 ;This function uses a counter to get the next available ien for file 778. There are 4 different counters, each assigned as range of numbers, selected via the input parameters. It does not create a record. 80 ;Inputs: 81 ; DIR = "IN" or "OUT" (required) 82 ; TCP = 1,0 (optional) 83 ;Output - the function returns the next available ien. Several counters are used: 84 ; 85 ; <"OUT","TCP"> 86 ; <"OUT","NOT TCP"> 87 ; <"IN","TCP"> 88 ; <"IN","NOT TCP"> 89 ; 90 N IEN,COUNTER,INC 91 I DIR="OUT" S INC=$S(+$G(TCP):0,1:100000000000) 92 I DIR="IN" S INC=$S(+$G(TCP):200000000000,1:300000000000) 93 S COUNTER=$NA(^HLC("FILE778",DIR,$S(+$G(TCP):"TCP",1:"NOT TCP"))) 94 AGAIN ; 95 S IEN=$$INC^HLOSITE(COUNTER,1) 96 I IEN>100000000000 D 97 .L +@COUNTER:200 98 .I $T,@COUNTER>100000000000 S @COUNTER=1,IEN=1 99 .L -@COUNTER 100 I IEN>100000000000 G AGAIN 101 Q (IEN+INC) 102 ; 103 TCP() ;checks the link to see if its TCP, return 1 if yes, 0 if no or not defined 104 N IEN,TCP 105 S TCP=1 106 S IEN=$G(HLMSTATE("STATUS","LINK IEN")) 107 I IEN,$P($G(^HLCS(869.1,+$P($G(^HLCS(870,IEN,0)),"^",3),0)),"^")'="TCP" S TCP=0 108 Q TCP 109 ; 110 GETWORK(WORK) ; Used by the Process Manager. 111 ;Are there any messages that need the "SEARCH" x-ref set? 112 ;Inputs: 113 ; WORK (required, pass-by-reference) 114 ; ("DOLLARJ") 115 ; ("NOW") (required by the process manager, pass-by-reference) 116 ; 117 L +^HLTMP("PENDING SEARCH X-REF"):0 118 Q:'$T 0 119 N OLD,DOLLARJ,SUCCESS,NOW 120 S SUCCESS=0 121 S NOW=$$SEC^XLFDT($H) 122 S (OLD,DOLLARJ)=$G(WORK("DOLLARJ")) 123 F S DOLLARJ=$O(^HLTMP("PENDING SEARCH X-REF",DOLLARJ)) Q:DOLLARJ="" D Q:SUCCESS 124 .N TIME S TIME=$O(^HLTMP("PENDING SEARCH X-REF",DOLLARJ,"")) 125 .S:(NOW-$$SEC^XLFDT(TIME)>100) SUCCESS=1 126 ; 127 I OLD'="",'SUCCESS F S DOLLARJ=$O(^HLTMP("PENDING SEARCH X-REF",DOLLARJ)) Q:DOLLARJ="" Q:DOLLARJ>OLD D Q:SUCCESS 128 .N TIME S TIME=$O(^HLTMP("PENDING SEARCH X-REF",DOLLARJ,"")) 129 .S:(NOW-$$SEC^XLFDT(TIME)>100) SUCCESS=1 130 S WORK("DOLLARJ")=DOLLARJ,WORK("NOW")=NOW 131 Q:WORK("DOLLARJ")]"" 1 132 L -^HLTMP("PENDING SEARCH X-REF") 133 Q 0 134 ; 135 DOWORK(WORK) ;Used by the Process Manager 136 ;Sets the "SEARCH" x-ref, running 100 seconds behind when the message record was created. 137 ; 138 N MSGIEN,TIME 139 S TIME=0 140 F S TIME=$O(^HLTMP("PENDING SEARCH X-REF",WORK("DOLLARJ"),TIME)) Q:'TIME Q:((WORK("NOW")-$$SEC^XLFDT(TIME))<100) D 141 .S MSGIEN=0 142 .F S MSGIEN=$O(^HLTMP("PENDING SEARCH X-REF",WORK("DOLLARJ"),TIME,MSGIEN)) Q:'MSGIEN D 143 ..N MSG 144 ..I $$GETMSG^HLOMSG(MSGIEN,.MSG) D 145 ...Q:'MSG("DT/TM CREATED") 146 ...I MSG("BATCH") D 147 ....N HDR 148 ....F Q:'$$NEXTMSG^HLOMSG(.MSG,.HDR) S MSG("HDR",1)=HDR(1),MSG("HDR",2)=HDR(2) D SET(.MSG) 149 ...E D 150 ....D SET(.MSG) 151 ..K ^HLTMP("PENDING SEARCH X-REF",WORK("DOLLARJ"),TIME,MSGIEN) 152 L -^HLTMP("PENDING SEARCH X-REF") 153 Q 154 ; 155 SET(MSG) ; 156 ;sets the ^HLB("SEARCH") x-ref 157 ; 158 N APP,FS,CS,IEN 159 I MSG("DIRECTION")'="IN",MSG("DIRECTION")'="OUT" Q 160 S FS=$E(MSG("HDR",1),4) 161 Q:FS="" 162 S CS=$E(MSG("HDR",1),5) 163 S APP=$S(MSG("DIRECTION")="IN":$P($P(MSG("HDR",1),FS,5),CS),1:$P($P(MSG("HDR",1),FS,3),CS)) 164 I APP="" S APP="UNKNOWN" 165 I MSG("BATCH") D 166 .N VALUE 167 .S VALUE=$P(MSG("HDR",2),FS,4) 168 .S MSG("MESSAGE TYPE")=$P(VALUE,CS) 169 .S MSG("EVENT")=$P(VALUE,CS,2) 170 S:MSG("MESSAGE TYPE")="" MSG("MESSAGE TYPE")="<none>" 171 S:MSG("EVENT")="" MSG("EVENT")="<none>" 172 S IEN=MSG("IEN") 173 I MSG("BATCH") S IEN=IEN_"^"_MSG("BATCH","CURRENT MESSAGE") 174 S ^HLB("SEARCH",MSG("DIRECTION"),MSG("DT/TM CREATED"),APP,MSG("MESSAGE TYPE"),MSG("EVENT"),IEN)="" 175 Q 1 HLOF778A ;ALB/CJM-HL7 - Saving messages to file 778 (continued) ;03/07/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ; 6 NEW(HLMSTATE) ; 7 ;This function creates a new entry in file 778. 8 ;Input: 9 ; HLMSTATE (required, pass by reference) These subscripts are expected: 10 ; 11 ;Output - the function returns the ien of the newly created record 12 ; 13 N IEN,NODE,ID,STAT 14 S STAT="HLMSTATE(""STATUS"")" 15 S IEN=$$NEWIEN(HLMSTATE("DIRECTION"),$$TCP) 16 Q:'IEN 0 17 S HLMSTATE("IEN")=IEN 18 ; 19 D ;build the message header 20 .N HDR 21 .;for incoming messages the header segment should already exist 22 .;for outgoing messages must build the header segment 23 .I HLMSTATE("DIRECTION")="OUT" D Q 24 ..I HLMSTATE("BATCH"),$G(HLMSTATE("ACK TO"))]"" S HLMSTATE("HDR","REFERENCE BATCH CONTROL ID")=HLMSTATE("ACK TO") 25 ..D BUILDHDR^HLOPBLD1(.HLMSTATE,$S(HLMSTATE("BATCH"):"BHS",1:"MSH"),.HDR) 26 ..S HLMSTATE("HDR",1)=HDR(1),HLMSTATE("HDR",2)=HDR(2) 27 ; 28 K ^HLB(IEN) 29 S ID=$S(HLMSTATE("BATCH"):HLMSTATE("HDR","BATCH CONTROL ID"),1:HLMSTATE("HDR","MESSAGE CONTROL ID")) 30 S NODE=ID_"^"_HLMSTATE("BODY")_"^"_$G(HLMSTATE("ACK TO"))_"^"_$S(HLMSTATE("DIRECTION")="IN":"I",1:"O")_"^" 31 S $P(NODE,"^",5)=$G(@STAT@("LINK NAME")) 32 S $P(NODE,"^",6)=$G(@STAT@("QUEUE")) 33 S $P(NODE,"^",8)=$G(@STAT@("PORT")) 34 S $P(NODE,"^",20)=$G(@STAT) 35 S $P(NODE,"^",21)=$G(@STAT@("ERROR TEXT")) 36 S $P(NODE,"^",16)=HLMSTATE("DT/TM") 37 ; 38 I HLMSTATE("DIRECTION")="OUT" D 39 .S $P(NODE,"^",10)=$P($G(@STAT@("APP ACK RESPONSE")),"^") 40 .S $P(NODE,"^",11)=$P($G(@STAT@("APP ACK RESPONSE")),"^",2) 41 .S $P(NODE,"^",12)=$P($G(@STAT@("ACCEPT ACK RESPONSE")),"^") 42 .S $P(NODE,"^",13)=$P($G(@STAT@("ACCEPT ACK RESPONSE")),"^",2) 43 .S $P(NODE,"^",14)=$P($G(@STAT@("FAILURE RESPONSE")),"^") 44 .S $P(NODE,"^",15)=$P($G(@STAT@("FAILURE RESPONSE")),"^",2) 45 .; 46 .;for outgoing set these x-refs now, for incoming msgs set them later 47 .S ^HLB("B",ID,IEN)="" 48 .S ^HLB("C",HLMSTATE("BODY"),IEN)="" 49 .I ($G(@STAT)="SE") D 50 ..S ^HLB("ERRORS","SE",$S($L($G(HLMSTATE("HDR","RECEIVING APPLICATION"))):HLMSTATE("HDR","RECEIVING APPLICATION"),1:"UNKNOWN"),HLMSTATE("DT/TM CREATED"),IEN)="" 51 ..D COUNT^HLOESTAT("OUT",$G(HLMSTATE("HDR","RECEIVING APPLICATION")),$G(HLMSTATE("HDR","SENDING APPLICATION")),$S(HLMSTATE("BATCH"):"BATCH",1:$G(HLMSTATE("HDR","MESSAGE TYPE"))),$G(HLMSTATE("HDR","EVENT"))) 52 .; 53 .;save some space for the ack 54 .S:($G(HLMSTATE("HDR","ACCEPT ACK TYPE"))="AL") ^HLB(IEN,4)="^^^ " 55 I $G(HLMSTATE("STATUS","PURGE")) S $P(NODE,"^",9)=HLMSTATE("STATUS","PURGE"),^HLB("AD","OUT",HLMSTATE("STATUS","PURGE"),HLMSTATE("IEN"))="" 56 S ^HLB(IEN,0)=NODE 57 ; 58 ;store the message header 59 S ^HLB(IEN,1)=HLMSTATE("HDR",1) 60 S ^HLB(IEN,2)=HLMSTATE("HDR",2) 61 ; 62 ;if the msg is an app ack, update the original msg 63 I $G(HLMSTATE("ACK TO","IEN"))]"" D 64 .N ACKTO 65 .M ACKTO=HLMSTATE("ACK TO") 66 .S ACKTO("ACK BY")=$S(HLMSTATE("BATCH"):HLMSTATE("HDR","BATCH CONTROL ID"),1:HLMSTATE("HDR","MESSAGE CONTROL ID")) 67 .D ACKTO^HLOF778(.HLMSTATE,.ACKTO) 68 .S HLMSTATE("ACK TO","DONE")=1 ;because the update was already done, otherwise it might be done again 69 ; 70 ;The "SEARCH" x-ref will be created asynchronously 71 S ^HLTMP("PENDING SEARCH X-REF",$J,HLMSTATE("DT/TM CREATED"),IEN)="" 72 ; 73 Q IEN 74 ; 75 NEWIEN(DIR,TCP) ; 76 ;This function uses a counter to get the next available ien for file 778. There are 4 different counters, each assigned as range of numbers, selected via the input parameters. It does not create a record. 77 ;Inputs: 78 ; DIR = "IN" or "OUT" (required) 79 ; TCP = 1,0 (optional) 80 ;Output - the function returns the next available ien. Several counters are used: 81 ; 82 ; <"OUT","TCP"> 83 ; <"OUT","NOT TCP"> 84 ; <"IN","TCP"> 85 ; <"IN","NOT TCP"> 86 ; 87 N IEN,COUNTER,INC 88 I DIR="OUT" S INC=$S(+$G(TCP):0,1:100000000000) 89 I DIR="IN" S INC=$S(+$G(TCP):200000000000,1:300000000000) 90 S COUNTER=$NA(^HLC("FILE778",DIR,$S(+$G(TCP):"TCP",1:"NOT TCP"))) 91 AGAIN ; 92 S IEN=$$INC^HLOSITE(COUNTER,1) 93 I IEN>100000000000 D 94 .L +@COUNTER:200 95 .I $T,@COUNTER>100000000000 S @COUNTER=1,IEN=1 96 .L -@COUNTER 97 I IEN>100000000000 G AGAIN 98 Q (IEN+INC) 99 ; 100 TCP() ;checks the link to see if its TCP, return 1 if yes, 0 if no or not defined 101 N IEN,TCP 102 S TCP=1 103 S IEN=$G(HLMSTATE("STATUS","LINK IEN")) 104 I IEN,$P($G(^HLCS(869.1,+$P($G(^HLCS(870,IEN,0)),"^",3),0)),"^")'="TCP" S TCP=0 105 Q TCP 106 ; 107 GETWORK(WORK) ; Used by the Process Manager. 108 ;Are there any messages that need the "SEARCH" x-ref set? 109 ;Inputs: 110 ; WORK (required, pass-by-reference) 111 ; ("DOLLARJ") 112 ; ("NOW") (required by the process manager, pass-by-reference) 113 ; 114 L +^HLTMP("PENDING SEARCH X-REF"):0 115 Q:'$T 0 116 N OLD,DOLLARJ,SUCCESS,NOW 117 S SUCCESS=0 118 S NOW=$$SEC^XLFDT($H) 119 S (OLD,DOLLARJ)=$G(WORK("DOLLARJ")) 120 F S DOLLARJ=$O(^HLTMP("PENDING SEARCH X-REF",DOLLARJ)) Q:DOLLARJ="" D Q:SUCCESS 121 .N TIME S TIME=$O(^HLTMP("PENDING SEARCH X-REF",DOLLARJ,"")) 122 .S:(NOW-$$SEC^XLFDT(TIME)>100) SUCCESS=1 123 ; 124 I OLD'="",'SUCCESS F S DOLLARJ=$O(^HLTMP("PENDING SEARCH X-REF",DOLLARJ)) Q:DOLLARJ="" Q:DOLLARJ>OLD D Q:SUCCESS 125 .N TIME S TIME=$O(^HLTMP("PENDING SEARCH X-REF",DOLLARJ,"")) 126 .S:(NOW-$$SEC^XLFDT(TIME)>100) SUCCESS=1 127 S WORK("DOLLARJ")=DOLLARJ,WORK("NOW")=NOW 128 Q:WORK("DOLLARJ")]"" 1 129 L -^HLTMP("PENDING SEARCH X-REF") 130 Q 0 131 ; 132 DOWORK(WORK) ;Used by the Process Manager 133 ;Sets the "SEARCH" x-ref, running 100 seconds behind when the message record was created. 134 ; 135 N MSGIEN,TIME 136 S TIME=0 137 F S TIME=$O(^HLTMP("PENDING SEARCH X-REF",WORK("DOLLARJ"),TIME)) Q:'TIME Q:((WORK("NOW")-$$SEC^XLFDT(TIME))<100) D 138 .S MSGIEN=0 139 .F S MSGIEN=$O(^HLTMP("PENDING SEARCH X-REF",WORK("DOLLARJ"),TIME,MSGIEN)) Q:'MSGIEN D 140 ..N MSG 141 ..I $$GETMSG^HLOMSG(MSGIEN,.MSG) D 142 ...Q:'MSG("DT/TM CREATED") 143 ...I MSG("BATCH") D 144 ....N HDR 145 ....F Q:'$$NEXTMSG^HLOMSG(.MSG,.HDR) S MSG("HDR",1)=HDR(1),MSG("HDR",2)=HDR(2) D SET(.MSG) 146 ...E D 147 ....D SET(.MSG) 148 ..K ^HLTMP("PENDING SEARCH X-REF",WORK("DOLLARJ"),TIME,MSGIEN) 149 L -^HLTMP("PENDING SEARCH X-REF") 150 Q 151 ; 152 SET(MSG) ; 153 ;sets the ^HLB("SEARCH") x-ref 154 ; 155 N APP,FS,CS,IEN 156 I MSG("DIRECTION")'="IN",MSG("DIRECTION")'="OUT" Q 157 S FS=$E(MSG("HDR",1),4) 158 Q:FS="" 159 S CS=$E(MSG("HDR",1),5) 160 S APP=$S(MSG("DIRECTION")="IN":$P($P(MSG("HDR",1),FS,5),CS),1:$P($P(MSG("HDR",1),FS,3),CS)) 161 I APP="" S APP="UNKNOWN" 162 I MSG("BATCH") D 163 .N VALUE 164 .S VALUE=$P(MSG("HDR",2),FS,4) 165 .S MSG("MESSAGE TYPE")=$P(VALUE,CS) 166 .S MSG("EVENT")=$P(VALUE,CS,2) 167 S:MSG("MESSAGE TYPE")="" MSG("MESSAGE TYPE")="<none>" 168 S:MSG("EVENT")="" MSG("EVENT")="<none>" 169 S IEN=MSG("IEN") 170 I MSG("BATCH") S IEN=IEN_"^"_MSG("BATCH","CURRENT MESSAGE") 171 S ^HLB("SEARCH",MSG("DIRECTION"),MSG("DT/TM CREATED"),APP,MSG("MESSAGE TYPE"),MSG("EVENT"),IEN)="" 172 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOFILER.m
r613 r623 1 HLOFILER ;ALB/CJM- Passes messages on the incoming queue to the applications - 10/4/94 1pm ;07/10/20072 ;;1.6;HEALTH LEVEL SEVEN;**126,131,134,137**;Oct 13, 1995;Build 21 3 4 5 6 GETWORK(QUE) 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 DOWORK(QUEUE) 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 ENDWORK 65 66 67 68 DEQUE(MSGIEN,PURGE,ACKTOIEN) 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 ERROR 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 ERROR2 113 114 115 116 117 ;may need to change the status toError118 119 120 121 122 123 .Q:$P(NODE,"^",20)="ER"124 .S $P(NODE,"^",20)="ER",$P(NODE,"^",21)="APPLICATION ROUTINE ERROR"125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 .S ^HLB("ERRORS",RAPP,NOW,MSGIEN)=""141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 ERROR3 159 160 161 162 163 164 165 1 HLOFILER ;ALB/CJM- Passes messages on the incoming queue to the applications - 10/4/94 1pm ;03/28/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,131,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ;GET WORK function for the process running under the Process Manager 6 GETWORK(QUE) ; 7 ;Input: 8 ; QUE - (pass by reference) These subscripts are used: 9 ; ("FROM") - sending facility last obtained 10 ; ("QUEUE") - name of the queue last obtained 11 ;Output: 12 ; Function returns 1 if success, 0 if no more work 13 ; QUE- updated to identify next queu of messages to process. 14 ; 15 N FROM,QUEUE 16 I '$D(QUE("SYSTEM")) D 17 .N SYS 18 .D SYSPARMS^HLOSITE(.SYS) 19 .S QUE("SYSTEM","NORMAL PURGE")=SYS("NORMAL PURGE") 20 .S QUE("SYSTEM","ERROR PURGE")=SYS("ERROR PURGE") 21 S FROM=$G(QUE("FROM")),QUEUE=$G(QUE("QUEUE")) 22 I ($G(FROM)]""),($G(QUEUE)]"") D 23 .L -^HLB("QUEUE","IN",FROM,QUEUE) 24 .F S QUEUE=$O(^HLB("QUEUE","IN",FROM,QUEUE)) Q:(QUEUE="") I '$$STOPPED^HLOQUE("IN",QUEUE) L +^HLB("QUEUE","IN",FROM,QUEUE):0 Q:$T 25 I ($G(FROM)]""),($G(QUEUE)="") D 26 .F S FROM=$O(^HLB("QUEUE","IN",FROM)) Q:FROM="" D Q:($G(QUEUE)]"") 27 ..S QUEUE="" F S QUEUE=$O(^HLB("QUEUE","IN",FROM,QUEUE)) Q:(QUEUE="") I '$$STOPPED^HLOQUE("IN",QUEUE) L +^HLB("QUEUE","IN",FROM,QUEUE):0 Q:$T 28 I FROM="" D 29 .F S FROM=$O(^HLB("QUEUE","IN",FROM)) Q:FROM="" D Q:($G(QUEUE)]"") 30 ..S QUEUE="" F S QUEUE=$O(^HLB("QUEUE","IN",FROM,QUEUE)) Q:(QUEUE="") I '$$STOPPED^HLOQUE("IN",QUEUE) L +^HLB("QUEUE","IN",FROM,QUEUE):0 Q:$T 31 S QUE("FROM")=FROM,QUE("QUEUE")=QUEUE 32 Q:(QUEUE]"") 1 33 Q 0 34 ; 35 DOWORK(QUEUE) ;sends the messages on the queue 36 N $ETRAP,$ESTACK S $ETRAP="G ERROR^HLOFILER" 37 ; 38 N MSGIEN,DEQUE,QUE 39 M QUE=QUEUE 40 S DEQUE=0 41 S MSGIEN=0 42 ; 43 F S MSGIEN=$O(^HLB("QUEUE","IN",QUEUE("FROM"),QUEUE("QUEUE"),MSGIEN)) Q:'MSGIEN D M QUEUE=QUE 44 .N MCODE,ACTION,QUE,PURGE,ACKTOIEN,NODE 45 .N $ETRAP,$ESTACK S $ETRAP="G ERROR2^HLOFILER" 46 .S NODE=$G(^HLB("QUEUE","IN",QUEUE("FROM"),QUEUE("QUEUE"),MSGIEN)) 47 .S ACTION=$P(NODE,"^",1,2) 48 .S PURGE=$P(NODE,"^",3) 49 .S ACKTOIEN=$P(NODE,"^",4) 50 .D DEQUE(MSGIEN,PURGE,ACKTOIEN) 51 .I ACTION]"" D 52 ..N HLMSGIEN,MCODE,DEQUE,DUZ 53 ..N $ETRAP,$ESTACK S $ETRAP="G ERROR3^HLOFILER" 54 ..S HLMSGIEN=MSGIEN 55 ..S MCODE="D "_ACTION 56 ..N MSGIEN,X 57 ..D DUZ^XUP(.5) 58 ..X MCODE 59 ..;kill the apps variables 60 ..D 61 ...N ZTSK 62 ...D KILL^XUSCLEAN 63 ; 64 ENDWORK ;where the execution resumes upon an error 65 D DEQUE() 66 Q 67 ; 68 DEQUE(MSGIEN,PURGE,ACKTOIEN) ; 69 ;Dequeues the message. Also sets up the purge dt/tm and the completion status. 70 S:$G(MSGIEN) DEQUE=$G(DEQUE)+1,DEQUE(MSGIEN)=PURGE_"^"_ACKTOIEN 71 I '$G(MSGIEN)!($G(DEQUE)>25) S MSGIEN=0 D 72 .F S MSGIEN=$O(DEQUE(MSGIEN)) Q:'MSGIEN D 73 ..N NODE,PURGE,ACKTOIEN 74 ..S NODE=DEQUE(MSGIEN) 75 ..S PURGE=$P(NODE,"^"),ACKTOIEN=$P(NODE,"^",2) 76 ..D DEQUE^HLOQUE(QUEUE("FROM"),QUEUE("QUEUE"),"IN",MSGIEN) 77 ..S NODE=$G(^HLB(MSGIEN,0)) 78 ..Q:NODE="" 79 ..S $P(NODE,"^",19)=1 ;sets the flag to show that the app handoff was done 80 ..D:PURGE 81 ...N STATUS 82 ...S STATUS=$P(NODE,"^",20) 83 ...S:STATUS="" $P(NODE,"^",20)="SU",STATUS="SU" 84 ...S $P(NODE,"^",9)=$$FMADD^XLFDT($$NOW^XLFDT,,$S(PURGE=2:24*QUEUE("SYSTEM","ERROR PURGE"),$D(^HLB(MSGIEN,3,1,0)):24*QUEUE("SYSTEM","ERROR PURGE"),1:QUEUE("SYSTEM","NORMAL PURGE"))) 85 ...S ^HLB("AD",$S($E($P(NODE,"^",4))="I":"IN",1:"OUT"),$P(NODE,"^",9),MSGIEN)="" 86 ...I ACKTOIEN,$D(^HLB(ACKTOIEN,0)) S $P(^HLB(ACKTOIEN,0),"^",9)=$P(NODE,"^",9),^HLB("AD",$S($E($P(NODE,"^",4))="I":"OUT",1:"IN"),$P(NODE,"^",9),ACKTOIEN)="" 87 ..S ^HLB(MSGIEN,0)=NODE 88 .K DEQUE S DEQUE=0 89 Q 90 ; 91 ERROR ;error trap 92 S $ETRAP="Q:$QUIT """" Q" 93 N HOUR 94 S HOUR=$E($$NOW^XLFDT,1,10) 95 S ^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2))=$G(^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2)))+1 96 ; 97 D DEQUE() 98 ; 99 ;a lot of errors of the same type may indicate an endless loop 100 ;return to the Process Manager error trap 101 I ($G(^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2)))>30) Q:$QUIT "" Q 102 ; 103 ;while debugging quit on all errors - returns to the Process Manager error trap 104 I $G(^HLTMP("LOG ALL ERRORS")) Q:$QUIT "" Q 105 I $ECODE["EDITED" Q:$QUIT "" Q 106 ; 107 D ^%ZTER 108 D UNWIND^%ZTER 109 Q:$QUIT "" 110 Q 111 ; 112 ERROR2 ; 113 S $ETRAP="Q:$QUIT """" Q" 114 ; 115 D DEQUE() 116 ; 117 ;may need to change the status to Application Error 118 D 119 .N NODE,RAPP,SAPP,FS,CS,REP,ESCAPE,SUBCOMP,HDR,DIR,NOW 120 .S NOW=$$NOW^XLFDT 121 .S NODE=$G(^HLB(MSGIEN,0)) 122 .Q:NODE="" 123 .Q:$P(NODE,"^",20)="AE" 124 .S $P(NODE,"^",20)="AE",$P(NODE,"^",21)="APPLICATION ROUTINE ERROR" 125 .S DIR=$S($E($P(NODE,"^",4))="I":"IN",1:"OUT") 126 .I $P(NODE,"^",9) K ^HLB("AD",DIR,$P(NODE,"^",9),MSGIEN) 127 .S $P(NODE,"^",9)=$$FMADD^XLFDT(NOW,,24*QUEUE("SYSTEM","ERROR PURGE")) 128 .S ^HLB(MSGIEN,0)=NODE 129 .S ^HLB("AD",DIR,$P(NODE,"^",9),MSGIEN)="" 130 .S HDR=$G(^HLB(MSGIEN,1)) 131 .S FS=$E(HDR,4) 132 .Q:FS="" 133 .S CS=$E(HDR,5) 134 .S REP=$E(HDR,6) 135 .S ESCAPE=$E(HDR,7) 136 .S SUBCOMP=$E(HDR,8) 137 .S RAPP=$$DESCAPE^HLOPRS1($P($P(HDR,FS,5),CS),FS,CS,SUBCOMP,REP,ESCAPE) 138 .I RAPP="" S RAPP="UNKNOWN" 139 .S SAPP=$$DESCAPE^HLOPRS1($P($P(HDR,FS,3),CS),FS,CS,SUBCOMP,REP,ESCAPE) 140 .S ^HLB("ERRORS","AE",RAPP,NOW,MSGIEN)="" 141 .D COUNT^HLOESTAT(DIR,RAPP,SAPP,"UNKNOWN") 142 ; 143 ;kill the apps variables 144 D 145 .N ZTSK,MSGIEN,QUEUE 146 .D KILL^XUSCLEAN 147 ; 148 ;release all the locks the app may have set, except Taskman lock 149 L:$D(ZTSK) ^%ZTSCH("TASK",ZTSK):1 150 L:'$D(ZTSK) 151 ;reset HLO's lock 152 L +^HLTMP("HL7 RUNNING PROCESSES",$J):0 153 ;return to processing the next message on the queue 154 S $ECODE="" 155 ; 156 Q:$QUIT "" 157 Q 158 ERROR3 ;error trap for application context 159 S $ETRAP="Q:$QUIT """" Q" 160 D ^%ZTER 161 S $ECODE=",UAPPLICATION ERROR," 162 ; 163 ;drop to the ERROR2 error handler 164 Q:$QUIT "" 165 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOMSG.m
r613 r623 1 HLOMSG ;ALB/CJM-HL7 - APIs for files 777/778 ;07/25/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 GETMSG(IEN,MSG) ; 6 ;Description: given the message ien=MSGIEN (required), it returns the MSG array containing information about the message, defined below. 7 ;Input: 8 ; IEN - the ien of the message in file 778 9 ;Output: 10 ; Function returns 1 on success, 0 on failure 11 ; MSG (pass by reference, required) These are the subscripts returned: 12 ; 13 ; "ACK BY" - msg id of msg that acknowledges this one 14 ; "ACK BY IEN" - msg IEN of msg that acknowledges this one. If the message is in the batch, the value is <ien>^<subien> 15 ; "ACK TO" - msg id of msg that this msg acknowledges 16 ; "ACK TO IEN" - msg IEN of msg that this msg acknowledges. If the message is in a batch, the value is <ien>^<subien> 17 ; "BATCH" = 1 if this is a batch message, 0 if not 18 ; "CURRENT MESSAGE" - defined only for batch messages - a counter used during building and parsing messages to indicate the current message. It will be set to 0 initially. 19 ; "BODY" - ptr to file 778 which contains the body of the message. 20 ; "DIRECTION" - "IN" if incoming, "OUT" if outgoing 21 ; "DT/TM" - date/time the message was sent or received 22 ; "DT/TM CREATED" - date/time the record was created (.01 field, file #777) 23 ; "LINE COUNT" - a counter used during building and parsing of 24 ; messages to indicate the current line within the message. For 25 ; batch messages where each message within the batch is stored 26 ; separately, this field indicates the position within the current 27 ; individual message 28 ; "HDR" - the header segment, NOT parsed, as HDR(1) and HDR(2) 29 ; "ID" - Message Control ID for an individual message, Batch Control ID for a batch message 30 ; "IEN" - ien, file 778 31 ; "EVENT" - HL7 event, only defined if NOT batch 32 ; "MESSAGE TYPE" - HL7 message type, only defined if NOT batch 33 ; "STATUS" - the completion status 34 ; 35 ; These are lower level subscripts of "STATUS": 36 ; "ACCEPT ACK RESPONSE" - the application's <tag>^<rtn> to Xecute when the accept ack is received 37 ; "ACCEPT ACK'D" - 1 if an accept ack was sent or received in response to this message 38 ; "APP ACK RESPONSE" - the application's <tag>^<rtn> to Xecute when app ack is received 39 ; "APP ACK'D" - 1 if an application ack was sent or received in response to this message 40 ; "ERROR TEXT" - if in error status, a description of the error 41 ; "LINK NAME" the link the message was transmitted through 42 ; "PORT" - remote port over which the message was transmitted 43 ; "PURGE" - scheduled purge dt/tm 44 ; "QUEUE" - the queue that the message was placed on 45 ; "SEQUENCE QUEUE" - the sequence queue (optional) 46 ; 47 K MSG 48 Q:'$G(IEN) 0 49 N NODE 50 S MSG("IEN")=IEN 51 S NODE=$G(^HLB(IEN,0)) 52 S MSG("ID")=$P(NODE,"^") 53 S MSG("BODY")=$P(NODE,"^",2) 54 S MSG("DIRECTION")=$S($E($P(NODE,"^",4))="O":"OUT",$E($P(NODE,"^",4))="I":"IN",1:"") 55 S MSG("ACK TO")=$P(NODE,"^",3) 56 S MSG("ACK BY")=$P(NODE,"^",7) 57 I MSG("ACK TO")]"" S MSG("ACK TO IEN")=$$ACKTOIEN^HLOMSG1($P(NODE,"^"),MSG("ACK TO")) 58 I MSG("ACK BY")]"" S MSG("ACK BY IEN")=$$ACKBYIEN^HLOMSG1($P(NODE,"^"),MSG("ACK BY")) 59 S MSG("DT/TM")=$P(NODE,"^",16) 60 S MSG("STATUS")=$P(NODE,"^",20) 61 ; 62 D 63 .N NODE4 64 .S NODE4=$G(^HLB(IEN,4)) 65 .S MSG("STATUS","QUEUE")=$P(NODE,"^",6) 66 .S MSG("STATUS","LINK NAME")=$P(NODE,"^",5) 67 .S MSG("STATUS","PORT")=$P(NODE,"^",8) 68 .S MSG("STATUS","PURGE")=$P(NODE,"^",9) 69 .S MSG("STATUS","ERROR TEXT")=$P(NODE,"^",21) 70 .S MSG("STATUS","APP ACK RESPONSE")=$P(NODE,"^",10,11) 71 .I MSG("STATUS","APP ACK RESPONSE")="^" S MSG("STATUS","APP ACK RESPONSE")="" 72 .S MSG("STATUS","ACCEPT ACK RESPONSE")=$P(NODE,"^",12,13) 73 .I MSG("STATUS","ACCEPT ACK RESPONSE")="^" S MSG("STATUS","ACCEPT ACK RESPONSE")="" 74 .S MSG("STATUS","ACCEPT ACK'D")=$P(NODE,"^",17) 75 .S MSG("STATUS","APP ACK'D")=$P(NODE,"^",18) 76 .S MSG("STATUS")=$P(NODE,"^",20) 77 .S MSG("STATUS","APP HANDOFF")=$P(NODE,"^",19) 78 .S MSG("STATUS","ACCEPT ACK DT/TM")=$P(NODE4,"^") 79 .S MSG("STATUS","ACCEPT ACK ID")=$P(NODE4,"^",2) 80 .S MSG("STATUS","ACCEPT ACK MSA")=$P(NODE4,"^",3,99) 81 ; 82 S MSG("LINE COUNT")=0 83 S MSG("HDR",1)=$G(^HLB(IEN,1)) 84 S MSG("HDR",2)=$G(^HLB(IEN,2)) 85 I 'MSG("BODY") D Q 0 86 .S MSG("DT/TM CREATED")="" 87 .S MSG("BATCH")="" 88 .S MSG("MESSAGE TYPE")="" 89 .S MSG("EVENT")="" 90 ; 91 S NODE=$G(^HLA(MSG("BODY"),0)) 92 S MSG("DT/TM CREATED")=+NODE 93 S MSG("BATCH")=+$P(NODE,"^",2) 94 I MSG("BATCH") S MSG("BATCH","CURRENT MESSAGE")=0 95 I 'MSG("BATCH") D 96 .S MSG("MESSAGE TYPE")=$P(NODE,"^",3) 97 .S MSG("EVENT")=$P(NODE,"^",4) 98 I MSG("DIRECTION")="OUT" D 99 .N NODE5 100 .S NODE5=$G(^HLB(IEN,5)) 101 .S MSG("STATUS","SEQUENCE QUEUE")=$P(NODE5,"^") 102 .S MSG("STATUS","MOVED TO OUT QUEUE")=$P(NODE5,"^",2) 103 .S MSG("STATUS","SEQUENCE EXCEPTION RAISED")=$P(NODE5,"^",3) 104 Q 1 105 ; 106 HLNEXT(MSG,SEG) ; 107 ;Description: Returns the next segment as a set of lines stored in SEG. 108 ;Input: 109 ; MSG (pass by reference, required) 110 ;Output: 111 ; Function returns 1 on success, 0 on failure (no more segments) 112 ; SEG (pass by reference, required) 113 ; 114 K SEG 115 Q:MSG("LINE COUNT")=-1 0 116 I 'MSG("BATCH") D 117 .N I,J,NODE,START 118 .S START=0 119 .S J=1,I=MSG("LINE COUNT") 120 .F S I=$O(^HLA(MSG("BODY"),1,I)) Q:'I S NODE=$G(^HLA(MSG("BODY"),1,I,0)) Q:(START&(NODE="")) I NODE'="" S SEG(J)=NODE,J=J+1,START=1 121 .I 'I D 122 ..S MSG("LINE COUNT")=-1 123 .E S MSG("LINE COUNT")=I 124 I MSG("BATCH") D 125 .N I,J,NODE,START 126 .S J=1,I=MSG("LINE COUNT"),START=0 127 .F S I=$O(^HLA(MSG("BODY"),2,MSG("BATCH","CURRENT MESSAGE"),1,I)) Q:'I S NODE=$G(^HLA(MSG("BODY"),2,MSG("BATCH","CURRENT MESSAGE"),1,I,0)) Q:(START&(NODE="")) I NODE'="" S SEG(J)=NODE,J=J+1,START=1 128 .I 'I D 129 ..S MSG("LINE COUNT")=-1 130 .E S MSG("LINE COUNT")=I 131 Q $S($D(SEG):1,1:0) 132 ; 133 NEXTMSG(MSG,HDR) ; 134 ;Advances to the next message in the batch 135 ;Input: 136 ; MSG (pass by reference, required) - defined by $$GETMSG() 137 ;Output: 138 ; Function returns 1 on success, 0 if no more messages 139 ; MSG - updated with current position in the message 140 ; HDR (pass by reference, required) returns the header as an array of lines 141 ; 142 ; 143 K HDR 144 S MSG("LINE COUNT")=0 145 N SUBIEN,I 146 ; 147 ;if completed parsing, don't start over 148 I MSG("BATCH","CURRENT MESSAGE")=-1 Q 0 149 ; 150 S I=$O(^HLB(MSG("IEN"),3,"B",MSG("BATCH","CURRENT MESSAGE"))) 151 I 'I S MSG("BATCH","CURRENT MESSAGE")=-1 Q 0 152 S MSG("BATCH","CURRENT MESSAGE")=I 153 S SUBIEN=$O(^HLB(MSG("IEN"),3,"B",I,0)) 154 S HDR(1)=$G(^HLB(MSG("IEN"),3,SUBIEN,1)) 155 S HDR(2)=$G(^HLB(MSG("IEN"),3,SUBIEN,2)) 156 Q $S($D(HDR):1,1:0) 157 ; 158 ADDSEG(HLMSTATE,SEG) ;Adds a segment to the message. 159 ;Input: 160 ; HLMSTATE() - (pass by reference, required) 161 ; SEG() - (pass by reference, required) The segment as lines SEG(<i>) 162 ; 163 ;Output: 164 ; HLMSTATE() 165 ; 166 N I,J S I=0 167 S J=HLMSTATE("LINE COUNT") 168 ; 169 ;insure a blank line between segments 170 I J S J=J+1,HLMSTATE("UNSTORED LINES",$S(HLMSTATE("BATCH"):HLMSTATE("BATCH","CURRENT MESSAGE"),1:1),HLMSTATE("CURRENT SEGMENT"),J)="" 171 ; 172 S HLMSTATE("CURRENT SEGMENT")=HLMSTATE("CURRENT SEGMENT")+1 173 F S I=$O(SEG(I)) Q:'I D 174 .S J=J+1 175 .S HLMSTATE("UNSTORED LINES",$S(HLMSTATE("BATCH"):HLMSTATE("BATCH","CURRENT MESSAGE"),1:1),HLMSTATE("CURRENT SEGMENT"),J)=SEG(I),HLMSTATE("UNSTORED LINES")=HLMSTATE("UNSTORED LINES")+$L(SEG(I))+50 176 .I HLMSTATE("UNSTORED LINES")>HLMSTATE("SYSTEM","BUFFER") D 177 ..I HLMSTATE("DIRECTION")="IN",$$SAVEMSG^HLOF778(.HLMSTATE) Q 178 ..I HLMSTATE("DIRECTION")="OUT",$$SAVEMSG^HLOF777(.HLMSTATE) 179 ; 180 S HLMSTATE("LINE COUNT")=J 181 Q 182 ; 183 ADDMSG(HLMSTATE,PARMS) ; 184 ;For outgoing messages, adds a message in the batch. There is no MSH yet, just the message type and event. 185 ;Input: 186 ; HLMSTATE() - (pass by reference, required) 187 ; PARMS("EVENT") 188 ; PARMS("MESSAGE TYPE") 189 ; 190 ;Output: 191 ; HLMSTATE() - (pass by reference, required) 192 ; 193 N I 194 S I=HLMSTATE("BATCH","CURRENT MESSAGE")+1,HLMSTATE("BATCH","CURRENT MESSAGE")=I 195 S HLMSTATE("UNSTORED LINES",I)=PARMS("MESSAGE TYPE")_"^"_PARMS("EVENT") 196 M:$G(PARMS("ACK TO"))]"" HLMSTATE("BATCH","ACK TO",I)=PARMS("ACK TO") 197 S HLMSTATE("CURRENT SEGMENT")=0 198 S HLMSTATE("LINE COUNT")=0 199 S HLMSTATE("UNSTORED LINES")=HLMSTATE("UNSTORED LINES")+100 200 Q 201 ; 202 ADDMSG2(HLMSTATE,MSH) ; 203 ;For incoming messages adds a message to the batch. This differs from ADDMSG in that the MSH segment is passed in to be stored in file 778. 204 ;Input: 205 ; HLMSTATE() - (pass by reference, required) 206 ; MSH(<i>) - the MSH segment as a set of lines 207 ; 208 ;Output: 209 ; HLMSTATE() - (pass by reference, required) 210 ; 211 N FS,CS,VALUE 212 S HLMSTATE("BATCH","CURRENT MESSAGE")=HLMSTATE("BATCH","CURRENT MESSAGE")+1 213 S FS=$E(MSH(1),4) 214 S CS=$E(MSH(1),5) 215 S VALUE=$P(MSH(2),FS,4) 216 S HLMSTATE("UNSTORED LINES",HLMSTATE("BATCH","CURRENT MESSAGE"))=$P(VALUE,CS)_"^"_$P(VALUE,CS,2) 217 S HLMSTATE("UNSTORED MSH")=1 218 M HLMSTATE("UNSTORED MSH",HLMSTATE("BATCH","CURRENT MESSAGE"))=MSH 219 S HLMSTATE("CURRENT SEGMENT")=0 220 S HLMSTATE("LINE COUNT")=0 221 S HLMSTATE("UNSTORED LINES")=HLMSTATE("UNSTORED LINES")+200 222 I HLMSTATE("UNSTORED LINES")>HLMSTATE("SYSTEM","BUFFER"),$$SAVEMSG^HLOF778(.HLMSTATE) ;first stores stuff in 777, then headers in file 778 223 Q 1 HLOMSG ;ALB/CJM-HL7 - APIs for files 777/778 ;02/04/2004 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 GETMSG(IEN,MSG) ; 6 ;Description: given the message ien=MSGIEN (required), it returns the MSG array containing information about the message, defined below. 7 ;Input: 8 ; IEN - the ien of the message in file 778 9 ;Output: 10 ; Function returns 1 on success, 0 on failure 11 ; MSG (pass by reference, required) These are the subscripts returned: 12 ; 13 ; "ACK BY" - msg id of msg that acknowledges this one 14 ; "ACK BY IEN" - msg IEN of msg that acknowledges this one. If the message is in the batch, the value is <ien>^<subien> 15 ; "ACK TO" - msg id of msg that this msg acknowledges 16 ; "ACK TO IEN" - msg IEN of msg that this msg acknowledges. If the message is in a batch, the value is <ien>^<subien> 17 ; "BATCH" = 1 if this is a batch message, 0 if not 18 ; "CURRENT MESSAGE" - defined only for batch messages - a counter used during building and parsing messages to indicate the current message. It will be set to 0 initially. 19 ; "BODY" - ptr to file 778 which contains the body of the message. 20 ; "DIRECTION" - "IN" if incoming, "OUT" if outgoing 21 ; "DT/TM" - date/time the message was sent or received 22 ; "DT/TM CREATED" - date/time the record was created (.01 field, file #777) 23 ; "LINE COUNT" - a counter used during building and parsing of 24 ; messages to indicate the current line within the message. For 25 ; batch messages where each message within the batch is stored 26 ; separately, this field indicates the position within the current 27 ; individual message 28 ; "HDR" - the header segment, NOT parsed, as HDR(1) and HDR(2) 29 ; "ID" - Message Control ID for an individual message, Batch Control ID for a batch message 30 ; "IEN" - ien, file 778 31 ; "EVENT" - HL7 event, only defined if NOT batch 32 ; "MESSAGE TYPE" - HL7 message type, only defined if NOT batch 33 ; "STATUS" - the completion status 34 ; 35 ; These are lower level subscripts of "STATUS": 36 ; "ACCEPT ACK RESPONSE" - the application's <tag>^<rtn> to Xecute when the accept ack is received 37 ; "ACCEPT ACK'D" - 1 if an accept ack was sent or received in response to this message 38 ; "APP ACK RESPONSE" - the application's <tag>^<rtn> to Xecute when app ack is received 39 ; "APP ACK'D" - 1 if an application ack was sent or received in response to this message 40 ; "ERROR TEXT" - if in error status, a description of the error 41 ; "LINK NAME" the link the message was transmitted through 42 ; "PORT" - remote port over which the message was transmitted 43 ; "PURGE" - scheduled purge dt/tm 44 ; "QUEUE" - the queue that the message was placed on 45 ; 46 K MSG 47 Q:'$G(IEN) 0 48 N NODE 49 S MSG("IEN")=IEN 50 S NODE=$G(^HLB(IEN,0)) 51 S MSG("ID")=$P(NODE,"^") 52 S MSG("BODY")=$P(NODE,"^",2) 53 S MSG("DIRECTION")=$S($E($P(NODE,"^",4))="O":"OUT",$E($P(NODE,"^",4))="I":"IN",1:"") 54 S MSG("ACK TO")=$P(NODE,"^",3) 55 S MSG("ACK BY")=$P(NODE,"^",7) 56 I MSG("ACK TO")]"" S MSG("ACK TO IEN")=$$ACKTOIEN^HLOMSG1($P(NODE,"^"),MSG("ACK TO")) 57 I MSG("ACK BY")]"" S MSG("ACK BY IEN")=$$ACKBYIEN^HLOMSG1($P(NODE,"^"),MSG("ACK BY")) 58 S MSG("DT/TM")=$P(NODE,"^",16) 59 S MSG("STATUS")=$P(NODE,"^",20) 60 ; 61 D 62 .N NODE4 63 .S NODE4=$G(^HLB(IEN,4)) 64 .S MSG("STATUS","QUEUE")=$P(NODE,"^",6) 65 .S MSG("STATUS","LINK NAME")=$P(NODE,"^",5) 66 .S MSG("STATUS","PORT")=$P(NODE,"^",8) 67 .S MSG("STATUS","PURGE")=$P(NODE,"^",9) 68 .S MSG("STATUS","ERROR TEXT")=$P(NODE,"^",21) 69 .S MSG("STATUS","APP ACK RESPONSE")=$P(NODE,"^",10,11) 70 .I MSG("STATUS","APP ACK RESPONSE")="^" S MSG("STATUS","APP ACK RESPONSE")="" 71 .S MSG("STATUS","ACCEPT ACK RESPONSE")=$P(NODE,"^",12,13) 72 .I MSG("STATUS","ACCEPT ACK RESPONSE")="^" S MSG("STATUS","ACCEPT ACK RESPONSE")="" 73 .S MSG("STATUS","ACCEPT ACK'D")=$P(NODE,"^",17) 74 .S MSG("STATUS","APP ACK'D")=$P(NODE,"^",18) 75 .S MSG("STATUS")=$P(NODE,"^",20) 76 .S MSG("STATUS","APP HANDOFF")=$P(NODE,"^",19) 77 .S MSG("STATUS","ACCEPT ACK DT/TM")=$P(NODE4,"^") 78 .S MSG("STATUS","ACCEPT ACK ID")=$P(NODE4,"^",2) 79 .S MSG("STATUS","ACCEPT ACK MSA")=$P(NODE4,"^",3,99) 80 ; 81 S MSG("LINE COUNT")=0 82 S MSG("HDR",1)=$G(^HLB(IEN,1)) 83 S MSG("HDR",2)=$G(^HLB(IEN,2)) 84 I 'MSG("BODY") D Q 0 85 .S MSG("DT/TM CREATED")="" 86 .S MSG("BATCH")="" 87 .S MSG("MESSAGE TYPE")="" 88 .S MSG("EVENT")="" 89 ; 90 S NODE=$G(^HLA(MSG("BODY"),0)) 91 S MSG("DT/TM CREATED")=+NODE 92 S MSG("BATCH")=+$P(NODE,"^",2) 93 I MSG("BATCH") S MSG("BATCH","CURRENT MESSAGE")=0 94 I 'MSG("BATCH") D 95 .S MSG("MESSAGE TYPE")=$P(NODE,"^",3) 96 .S MSG("EVENT")=$P(NODE,"^",4) 97 Q 1 98 ; 99 HLNEXT(MSG,SEG) ; 100 ;Description: Returns the next segment as a set of lines stored in SEG. 101 ;Input: 102 ; MSG (pass by reference, required) 103 ;Output: 104 ; Function returns 1 on success, 0 on failure (no more segments) 105 ; SEG (pass by reference, required) 106 ; 107 K SEG 108 Q:MSG("LINE COUNT")=-1 0 109 I 'MSG("BATCH") D 110 .N I,J,NODE,START 111 .S START=0 112 .S J=1,I=MSG("LINE COUNT") 113 .F S I=$O(^HLA(MSG("BODY"),1,I)) Q:'I S NODE=$G(^HLA(MSG("BODY"),1,I,0)) Q:(START&(NODE="")) I NODE'="" S SEG(J)=NODE,J=J+1,START=1 114 .I 'I D 115 ..S MSG("LINE COUNT")=-1 116 .E S MSG("LINE COUNT")=I 117 I MSG("BATCH") D 118 .N I,J,NODE,START 119 .S J=1,I=MSG("LINE COUNT"),START=0 120 .F S I=$O(^HLA(MSG("BODY"),2,MSG("BATCH","CURRENT MESSAGE"),1,I)) Q:'I S NODE=$G(^HLA(MSG("BODY"),2,MSG("BATCH","CURRENT MESSAGE"),1,I,0)) Q:(START&(NODE="")) I NODE'="" S SEG(J)=NODE,J=J+1,START=1 121 .I 'I D 122 ..S MSG("LINE COUNT")=-1 123 .E S MSG("LINE COUNT")=I 124 Q $S($D(SEG):1,1:0) 125 ; 126 NEXTMSG(MSG,HDR) ; 127 ;Advances to the next message in the batch 128 ;Input: 129 ; MSG (pass by reference, required) - defined by $$GETMSG() 130 ;Output: 131 ; Function returns 1 on success, 0 if no more messages 132 ; MSG - updated with current position in the message 133 ; HDR (pass by reference, required) returns the header as an array of lines 134 ; 135 ; 136 K HDR 137 S MSG("LINE COUNT")=0 138 N SUBIEN,I 139 ; 140 ;if completed parsing, don't start over 141 I MSG("BATCH","CURRENT MESSAGE")=-1 Q 0 142 ; 143 S I=$O(^HLB(MSG("IEN"),3,"B",MSG("BATCH","CURRENT MESSAGE"))) 144 I 'I S MSG("BATCH","CURRENT MESSAGE")=-1 Q 0 145 S MSG("BATCH","CURRENT MESSAGE")=I 146 S SUBIEN=$O(^HLB(MSG("IEN"),3,"B",I,0)) 147 S HDR(1)=$G(^HLB(MSG("IEN"),3,SUBIEN,1)) 148 S HDR(2)=$G(^HLB(MSG("IEN"),3,SUBIEN,2)) 149 Q $S($D(HDR):1,1:0) 150 ; 151 ADDSEG(HLMSTATE,SEG) ;Adds a segment to the message. 152 ;Input: 153 ; HLMSTATE() - (pass by reference, required) 154 ; SEG() - (pass by reference, required) The segment as lines SEG(<i>) 155 ; 156 ;Output: 157 ; HLMSTATE() 158 ; 159 N I,J S I=0 160 S J=HLMSTATE("LINE COUNT") 161 ; 162 ;insure a blank line between segments 163 I J S J=J+1,HLMSTATE("UNSTORED LINES",$S(HLMSTATE("BATCH"):HLMSTATE("BATCH","CURRENT MESSAGE"),1:1),HLMSTATE("CURRENT SEGMENT"),J)="" 164 ; 165 S HLMSTATE("CURRENT SEGMENT")=HLMSTATE("CURRENT SEGMENT")+1 166 F S I=$O(SEG(I)) Q:'I D 167 .S J=J+1 168 .S HLMSTATE("UNSTORED LINES",$S(HLMSTATE("BATCH"):HLMSTATE("BATCH","CURRENT MESSAGE"),1:1),HLMSTATE("CURRENT SEGMENT"),J)=SEG(I),HLMSTATE("UNSTORED LINES")=HLMSTATE("UNSTORED LINES")+$L(SEG(I))+50 169 .I HLMSTATE("UNSTORED LINES")>HLMSTATE("SYSTEM","BUFFER") D 170 ..I HLMSTATE("DIRECTION")="IN",$$SAVEMSG^HLOF778(.HLMSTATE) Q 171 ..I HLMSTATE("DIRECTION")="OUT",$$SAVEMSG^HLOF777(.HLMSTATE) 172 ; 173 S HLMSTATE("LINE COUNT")=J 174 Q 175 ; 176 ADDMSG(HLMSTATE,PARMS) ; 177 ;For outgoing messages, adds a message in the batch. There is no MSH yet, just the message type and event. 178 ;Input: 179 ; HLMSTATE() - (pass by reference, required) 180 ; PARMS("EVENT") 181 ; PARMS("MESSAGE TYPE") 182 ; 183 ;Output: 184 ; HLMSTATE() - (pass by reference, required) 185 ; 186 N I 187 S I=HLMSTATE("BATCH","CURRENT MESSAGE")+1,HLMSTATE("BATCH","CURRENT MESSAGE")=I 188 S HLMSTATE("UNSTORED LINES",I)=PARMS("MESSAGE TYPE")_"^"_PARMS("EVENT") 189 M:$G(PARMS("ACK TO"))]"" HLMSTATE("BATCH","ACK TO",I)=PARMS("ACK TO") 190 S HLMSTATE("CURRENT SEGMENT")=0 191 S HLMSTATE("LINE COUNT")=0 192 S HLMSTATE("UNSTORED LINES")=HLMSTATE("UNSTORED LINES")+100 193 Q 194 ; 195 ADDMSG2(HLMSTATE,MSH) ; 196 ;For incoming messages adds a message to the batch. This differs from ADDMSG in that the MSH segment is passed in to be stored in file 778. 197 ;Input: 198 ; HLMSTATE() - (pass by reference, required) 199 ; MSH(<i>) - the MSH segment as a set of lines 200 ; 201 ;Output: 202 ; HLMSTATE() - (pass by reference, required) 203 ; 204 N FS,CS,VALUE 205 S HLMSTATE("BATCH","CURRENT MESSAGE")=HLMSTATE("BATCH","CURRENT MESSAGE")+1 206 S FS=$E(MSH(1),4) 207 S CS=$E(MSH(1),5) 208 S VALUE=$P(MSH(2),FS,4) 209 S HLMSTATE("UNSTORED LINES",HLMSTATE("BATCH","CURRENT MESSAGE"))=$P(VALUE,CS)_"^"_$P(VALUE,CS,2) 210 S HLMSTATE("UNSTORED MSH")=1 211 M HLMSTATE("UNSTORED MSH",HLMSTATE("BATCH","CURRENT MESSAGE"))=MSH 212 S HLMSTATE("CURRENT SEGMENT")=0 213 S HLMSTATE("LINE COUNT")=0 214 S HLMSTATE("UNSTORED LINES")=HLMSTATE("UNSTORED LINES")+200 215 I HLMSTATE("UNSTORED LINES")>HLMSTATE("SYSTEM","BUFFER"),$$SAVEMSG^HLOF778(.HLMSTATE) ;first stores stuff in 777, then headers in file 778 216 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOPOST.m
r613 r623 1 HLOPOST ;IRMFO-ALB/CJM -Post-Install routine for HLO;03/24/2004 14:43 ;07/20/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134,136,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 N SYSTEM,DATA,VASITE,OLDSITE 6 D IDXLINKS 7 D SYSPARMS^HLOSITE(.SYSTEM) 8 S VASITE=$$SITE^VASITE 9 S OLDSITE=$G(^HLCS(869.3,1,0)) 10 S DATA(.01)=SYSTEM("DOMAIN") 11 I DATA(.01)="" D 12 .I $P(OLDSITE,"^",2) S DATA(.01)="HL7."_$P($G(^DIC(4.2,$P(OLDSITE,"^",2),0)),"^") 13 I DATA(.01)="" D 14 .N INST,DOMAIN 15 .S INST=$P(VASITE,"^") 16 .Q:'INST 17 .S DOMAIN=$P($G(^DIC(4,INST,6)),"^") 18 .I DOMAIN S DOMAIN=$P($G(^DIC(4.2,DOMAIN,0)),"^") I DOMAIN'="" S DATA(.01)="HL7."_DOMAIN 19 I DATA(.01)="" D BMES^XPDUTL("Post-Install failed, system missing INSTITUTION or DOMAIN file entry") Q 20 S DATA(.02)=SYSTEM("STATION") 21 I DATA(.02)="",$P(OLDSITE,"^",4) S DATA(.02)=$P($G(^DIC(4,$P(OLDSITE,"^",4),99)),"^") 22 I DATA(.02)="" S DATA(.02)=$P(VASITE,"^",3) 23 S DATA(.03)=$P(OLDSITE,"^",3) 24 S DATA(.04)=SYSTEM("MAXSTRING") 25 S DATA(.05)=SYSTEM("HL7 BUFFER") 26 S DATA(.06)=SYSTEM("USER BUFFER") 27 S DATA(.07)=SYSTEM("NORMAL PURGE") 28 S DATA(.08)=SYSTEM("ERROR PURGE") 29 I $D(^HLD(779.1,1,0)) D 30 .N ERROR 31 .I '$$UPD^HLOASUB1(779.1,1,.DATA,.ERROR) D BMES^XPDUTL("Post-Install failed -"_$G(ERROR)) 32 E D 33 .N ERROR 34 .I '$$ADD^HLOASUB1(779.1,,.DATA,.ERROR,1) D BMES^XPDUTL("Post-Install failed -"_$G(ERROR)) 35 Q 36 IDXLINKS ; 37 ;set the "AC" and "AD" indicies on the HL Logical Link file 38 N DIK 39 S DIK="^HLCS(870," 40 S DIK(1)=".01^AC^AD^AD1^AD2" 41 D ENALL^DIK 42 Q 43 ; 44 P134 ; 45 N DAILY,STARTUP,IEN,DATA 46 S DAILY=$O(^DIC(19,"B","HLO DAILY STARTUP",0)) 47 I 'DAILY D BMES^XPDUTL("Failed to schedule the HLO DAILY STARTUP option!") 48 S STARTUP=$O(^DIC(19,"B","HLO SYSTEM STARTUP",0)) 49 I 'STARTUP D BMES^XPDUTL("Failed to schedule the HLO SYSTEM STARTUP option!") 50 I STARTUP D 51 .S IEN=$O(^DIC(19.2,"B",STARTUP,0)) 52 .S DATA(.01)=STARTUP 53 .S DATA(2)="" 54 .S DATA(6)="" 55 .S DATA(9)=$S($P($G(^HLD(779.1,1,0)),"^",3)="P":"S",1:"") 56 .I IEN D 57 ..I '$$UPD^HLOASUB1(19.2,IEN,.DATA) D BMES^XPDUTL("Failed to schedule the HLO SYSTEM STARTUP option!") 58 .E D 59 ..I '$$ADD^HLOASUB1(19.2,,.DATA) D BMES^XPDUTL("Failed to schedule the HLO SYSTEM STARTUP option!") 60 I DAILY D 61 .S IEN=$O(^DIC(19.2,"B",DAILY,0)) 62 .S DATA(.01)=DAILY 63 .S DATA(2)=$$NOW^XLFDT 64 .S DATA(6)="1D" 65 .S DATA(9)="" 66 .I IEN D 67 ..I '$$UPD^HLOASUB1(19.2,IEN,.DATA) D BMES^XPDUTL("Failed to schedule the HLO DAILY STARTUP option!") 68 .E D 69 ..I '$$ADD^HLOASUB1(19.2,,.DATA) D BMES^XPDUTL("Failed to schedule the HLO DAILY STARTUP option!") 70 Q 71 ; 72 P136 ;post-install routine for HL*1.6*136 73 N ERROR,DIFROM,IEN 74 I $P($G(^HLD(779.1,1,0)),"^",3)="P" D 75 .D RESCH^XUTMOPT("HLO DAILY STARTUP",$$FMADD^XLFDT($$NOW^XLFDT,,1),,"1D","L",.ERROR) 76 .I $G(ERROR)<0 D BMES^XPDUTL("Failed to schedule the HLO DAILY STARTUP option! Please do so manually") 77 ; 78 S IEN=$O(^HLD(779.3,"B","PURGE OLD MESSAGES",0)) 79 Q:'IEN 80 S ^HLD(779.3,IEN,0)="PURGE OLD MESSAGES^1^0^2^20^^5^GETWORK^HLOPURGE^DOWORK^HLOPURGE^1^0" 81 Q 82 ; 83 P137 ; 84 ;move the existing errros to the new structure 85 N TYPE 86 K ^TMP($J,"HLO ERRORS") 87 F TYPE="TF","SE","AE" D 88 .M ^TMP($J,"HLO ERRORS",TYPE)=^HLB("ERRORS",TYPE) 89 .M ^HLB("ERRORS")=^TMP($J,"HLO ERRORS",TYPE) 90 .K ^TMP($J,"HLO ERRORS",TYPE) 91 .K ^HLB("ERRORS",TYPE) 92 Q 1 HLOPOST ;IRMFO-ALB/CJM -Post-Install routine for HLO;03/24/2004 14:43 ;05/03/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134,136**;Oct 13, 1995;Build 9 3 ; 4 N SYSTEM,DATA,VASITE,OLDSITE 5 D IDXLINKS 6 D SYSPARMS^HLOSITE(.SYSTEM) 7 S VASITE=$$SITE^VASITE 8 S OLDSITE=$G(^HLCS(869.3,1,0)) 9 S DATA(.01)=SYSTEM("DOMAIN") 10 I DATA(.01)="" D 11 .I $P(OLDSITE,"^",2) S DATA(.01)="HL7."_$P($G(^DIC(4.2,$P(OLDSITE,"^",2),0)),"^") 12 I DATA(.01)="" D 13 .N INST,DOMAIN 14 .S INST=$P(VASITE,"^") 15 .Q:'INST 16 .S DOMAIN=$P($G(^DIC(4,INST,6)),"^") 17 .I DOMAIN S DOMAIN=$P($G(^DIC(4.2,DOMAIN,0)),"^") I DOMAIN'="" S DATA(.01)="HL7."_DOMAIN 18 I DATA(.01)="" D BMES^XPDUTL("Post-Install failed, system missing INSTITUTION or DOMAIN file entry") Q 19 S DATA(.02)=SYSTEM("STATION") 20 I DATA(.02)="",$P(OLDSITE,"^",4) S DATA(.02)=$P($G(^DIC(4,$P(OLDSITE,"^",4),99)),"^") 21 I DATA(.02)="" S DATA(.02)=$P(VASITE,"^",3) 22 S DATA(.03)=$P(OLDSITE,"^",3) 23 S DATA(.04)=SYSTEM("MAXSTRING") 24 S DATA(.05)=SYSTEM("HL7 BUFFER") 25 S DATA(.06)=SYSTEM("USER BUFFER") 26 S DATA(.07)=SYSTEM("NORMAL PURGE") 27 S DATA(.08)=SYSTEM("ERROR PURGE") 28 I $D(^HLD(779.1,1,0)) D 29 .N ERROR 30 .I '$$UPD^HLOASUB1(779.1,1,.DATA,.ERROR) D BMES^XPDUTL("Post-Install failed -"_$G(ERROR)) 31 E D 32 .N ERROR 33 .I '$$ADD^HLOASUB1(779.1,,.DATA,.ERROR,1) D BMES^XPDUTL("Post-Install failed -"_$G(ERROR)) 34 Q 35 IDXLINKS ; 36 ;set the "AC" and "AD" indicies on the HL Logical Link file 37 N DIK 38 S DIK="^HLCS(870," 39 S DIK(1)=".01^AC^AD^AD1^AD2" 40 D ENALL^DIK 41 Q 42 ; 43 P134 ; 44 N DAILY,STARTUP,IEN,DATA 45 S DAILY=$O(^DIC(19,"B","HLO DAILY STARTUP",0)) 46 I 'DAILY D BMES^XPDUTL("Failed to schedule the HLO DAILY STARTUP option!") 47 S STARTUP=$O(^DIC(19,"B","HLO SYSTEM STARTUP",0)) 48 I 'STARTUP D BMES^XPDUTL("Failed to schedule the HLO SYSTEM STARTUP option!") 49 I STARTUP D 50 .S IEN=$O(^DIC(19.2,"B",STARTUP,0)) 51 .S DATA(.01)=STARTUP 52 .S DATA(2)="" 53 .S DATA(6)="" 54 .S DATA(9)=$S($P($G(^HLD(779.1,1,0)),"^",3)="P":"S",1:"") 55 .I IEN D 56 ..I '$$UPD^HLOASUB1(19.2,IEN,.DATA) D BMES^XPDUTL("Failed to schedule the HLO SYSTEM STARTUP option!") 57 .E D 58 ..I '$$ADD^HLOASUB1(19.2,,.DATA) D BMES^XPDUTL("Failed to schedule the HLO SYSTEM STARTUP option!") 59 I DAILY D 60 .S IEN=$O(^DIC(19.2,"B",DAILY,0)) 61 .S DATA(.01)=DAILY 62 .S DATA(2)=$$NOW^XLFDT 63 .S DATA(6)="1D" 64 .S DATA(9)="" 65 .I IEN D 66 ..I '$$UPD^HLOASUB1(19.2,IEN,.DATA) D BMES^XPDUTL("Failed to schedule the HLO DAILY STARTUP option!") 67 .E D 68 ..I '$$ADD^HLOASUB1(19.2,,.DATA) D BMES^XPDUTL("Failed to schedule the HLO DAILY STARTUP option!") 69 Q 70 ; 71 P136 ;post-install routine for HL*1.6*136 72 N ERROR,DIFROM,IEN 73 I $P($G(^HLD(779.1,1,0)),"^",3)="P" D 74 .D RESCH^XUTMOPT("HLO DAILY STARTUP",$$FMADD^XLFDT($$NOW^XLFDT,,1),,"1D","L",.ERROR) 75 .I $G(ERROR)<0 D BMES^XPDUTL("Failed to schedule the HLO DAILY STARTUP option! Please do so manually") 76 ; 77 S IEN=$O(^HLD(779.3,"B","PURGE OLD MESSAGES",0)) 78 Q:'IEN 79 S ^HLD(779.3,IEN,0)="PURGE OLD MESSAGES^1^0^2^20^^5^GETWORK^HLOPURGE^DOWORK^HLOPURGE^1^0" 80 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOPURGE.m
r613 r623 1 HLOPURGE ;IRMFO-ALB/CJM - Purging Old Messages;03/24/2004 14:43 ;07/25/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134,136,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 GETWORK(WORK) ; 6 ; 7 N OK 8 S OK=0 9 I $G(WORK)]"" L -HLPURGE(WORK) 10 F WORK="IN","OUT","OLD778","OLD777" I '$G(WORK("DONE",WORK)) S WORK("DONE",WORK)=1 L +HLPURGE(WORK):0 S OK=$T Q:OK 11 I 'OK K WORK("DONE") S WORK="" 12 Q OK 13 ; 14 DOWORK(WORK) ; 15 I WORK="OLD778" D OLD778 16 I WORK="OLD777" D OLD777 17 I (WORK="IN")!(WORK="OUT") D 18 .N TIME,NOW 19 .S NOW=$$NOW^XLFDT 20 .S TIME=0 21 .F S TIME=$O(^HLB("AD",WORK,TIME)) Q:TIME="" Q:TIME>NOW D 22 ..N MSGIEN 23 ..S MSGIEN=0 24 ..F S MSGIEN=$O(^HLB("AD",WORK,TIME,MSGIEN)) Q:'MSGIEN D 25 ...K ^HLB("AD",WORK,TIME,MSGIEN) 26 ...D DELETE(MSGIEN) 27 L -HLPURGE(WORK) 28 Q 29 OLD778 ; 30 N OLD,START,END,APP,TYPE,TODAY,PARMS 31 S TODAY=$$DT^XLFDT 32 S OLD=$$FMADD^XLFDT(TODAY,-45) 33 F START=0,100000000000,200000000000,300000000000 D 34 .S END=(START+100000000000)-1 35 .N MSGIEN,QUIT 36 .S QUIT=0 37 .S MSGIEN=START 38 .F S MSGIEN=$O(^HLB(MSGIEN)) Q:'MSGIEN Q:(MSGIEN>END) D Q:QUIT 39 ..N WHEN,BODY,NODE 40 ..S NODE=$G(^HLB(MSGIEN,0)) 41 ..S WHEN=$P(NODE,"^",16) 42 ..I WHEN,WHEN<OLD,$P(NODE,"^",9)<TODAY D DELETE(MSGIEN) Q 43 ..I 'WHEN D 44 ...S BODY=$P(NODE,"^",2) 45 ...Q:'BODY 46 ...S WHEN=+$G(^HLA(BODY,0)) 47 ...I WHEN,WHEN<OLD D Q 48 ....;I've seen messages sitting on outgoing queues forever, but it should never happen for incoming 49 ....I $E($P(NODE,"^",4))="O",$P(NODE,"^",5)]"",$P(NODE,"^",6)]"" D 50 .....N FROM 51 .....S FROM=$P(NODE,"^",5) 52 .....I $P(NODE,"^",8) S FROM=FROM_":"_$P(NODE,"^",8) 53 .....Q:'$D(^HLB("QUEUE","OUT",FROM,$P(NODE,"^",6),MSGIEN)) 54 .....D DEQUE^HLOQUE(FROM,$P(NODE,"^",6),"OUT",MSGIEN) 55 ....D DELETE(MSGIEN) Q 56 ...;stop looking for old records? 57 ...I WHEN,WHEN>OLD S QUIT=1 58 ; 59 ;also kill old errors left lying around 60 D SYSPARMS^HLOSITE(.PARMS) 61 S OLD=$$FMADD^XLFDT($$DT^XLFDT,-PARMS("ERROR PURGE")) 62 S APP="" 63 F S APP=$O(^HLB("ERRORS",APP)) Q:APP="" D 64 .N TIME 65 .S TIME=0 66 .F S TIME=$O(^HLB("ERRORS",APP,TIME)) Q:'TIME Q:TIME>OLD K ^HLB("ERRORS",APP,TIME) 67 Q 68 OLD777 ; 69 N OLD,TIME,TODAY 70 S TODAY=$$DT^XLFDT 71 S OLD=$$FMADD^XLFDT(TODAY,-45) 72 S TIME=0 73 F S TIME=$O(^HLA("B",TIME)) Q:'TIME Q:TIME>OLD D 74 .N MSGIEN 75 .S MSGIEN=0 76 .F S MSGIEN=$O(^HLA("B",TIME,MSGIEN)) Q:'MSGIEN D 77 ..N IEN778,STOP 78 ..S (STOP,IEN778)=0 79 ..F S IEN778=$O(^HLB("C",MSGIEN,IEN778)) Q:'IEN778 D 80 ...I $P($G(^HLB(IEN778,0)),"^",9)>TODAY S STOP=1 Q 81 ...D DELETE(IEN778,1) 82 ..K:'STOP ^HLB("C",MSGIEN),^HLA("B",TIME,MSGIEN),^HLA(MSGIEN) 83 Q 84 ; 85 DELETE(MSGIEN,FLAG) ; 86 ;Input: 87 ; MSGIEN - IEN, file 778 88 ; FLAG - if $G(FLAG), will not delete the pointed to record in file 777 89 N AC,SUBIEN,RAPP,SAPP,FS,CS,MSG 90 I '$$GETMSG^HLOMSG(MSGIEN,.MSG) ;MSG is corrupted, but there sill may be nodes to delete 91 S (RAPP,SAPP)="" 92 D 93 .S FS=$E(MSG("HDR",1),4) 94 .Q:FS="" 95 .S CS=$E(MSG("HDR",1),5) 96 .S SAPP=$P($P(MSG("HDR",1),FS,3),CS) 97 .I SAPP="" S SAPP="UNKNOWN" 98 .S RAPP=$P($P(MSG("HDR",1),FS,5),CS) 99 .I RAPP="" S RAPP="UNKNOWN" 100 ; 101 I 'MSG("BATCH") D KSEARCH(.MSG,MSG("MESSAGE TYPE"),MSG("EVENT"),SAPP,RAPP,MSGIEN) 102 ;if an error status,take care of the "ERRORS" x-ref 103 I MSG("STATUS")'="",MSG("STATUS")'="SU",MSG("BODY") D 104 .K ^HLB("ERRORS",RAPP,MSG("DT/TM CREATED"),MSGIEN) 105 .I MSG("STATUS")="ER" D 106 ..N SUB 107 ..S SUB=MSGIEN_"^" 108 ..K ^HLB("ERRORS",RAPP,MSG("DT/TM CREATED"),SUB) 109 ..F S SUB=$O(^HLB("ERRORS",RAPP,MSG("DT/TM CREATED"),SUB)) Q:SUB="" Q:+SUB'=MSGIEN K ^HLB("ERRORS",RAPP,MSG("DT/TM CREATED"),SUB) 110 ; 111 ;kill the whole-file xrefs for the message ien within a batch 112 S SUBIEN=0 113 F S SUBIEN=$O(^HLB(MSGIEN,3,SUBIEN)) Q:'SUBIEN D 114 .N MSGID 115 .I FS]"" D 116 ..N VALUE,HDR2,MSGTYPE,EVENT 117 ..S HDR2=$G(^HLB(MSGIEN,3,SUBIEN,2)) 118 ..S VALUE=$P(HDR2,FS,4) 119 ..S MSGTYPE=$P(VALUE,CS) 120 ..S EVENT=$P(VALUE,CS,2) 121 ..D KSEARCH(.MSG,MSGTYPE,EVENT,SAPP,RAPP,MSGIEN_"^"_SUBIEN) 122 .S MSGID=$P($G(^HLB(MSGIEN,3,SUBIEN,0)),"^",2) 123 .I MSGID]"" K ^HLB("AE",MSGID,MSGIEN_"^"_SUBIEN) 124 ; 125 I MSG("DIRECTION")="IN" D 126 .Q:FS="" 127 .N VALUE,HDR 128 .S HDR("SENDING APPLICATION")=$P(MSG("HDR",1),FS,3) 129 .S VALUE=$P(MSG("HDR",1),FS,4) 130 .S HDR("SENDING FACILITY",1)=$P(VALUE,CS) 131 .S HDR("SENDING FACILITY",2)=$P(VALUE,CS,2) 132 .S HDR("SENDING FACILITY",3)=$P(VALUE,CS,3) 133 .S AC=$S(HDR("SENDING FACILITY",2)]"":HDR("SENDING FACILITY",2),1:HDR("SENDING FACILITY",1))_HDR("SENDING APPLICATION")_MSG("ID") 134 K ^HLB(MSGIEN) 135 I MSG("STATUS","PURGE"),MSG("DIRECTION")'="" K ^HLB("AD",MSG("DIRECTION"),MSG("STATUS","PURGE"),MSGIEN) 136 K:(MSG("ID")]"") ^HLB("B",MSG("ID"),MSGIEN) 137 I MSG("DIRECTION")="IN" D 138 .K:($G(AC)]"") ^HLB("AC",AC,MSGIEN) 139 .I MSG("BODY"),'$G(FLAG) D KILL777(MSG("BODY")) 140 I MSG("DIRECTION")="OUT" D 141 .K ^HLB("C",+MSG("BODY"),MSGIEN) 142 .I '$G(FLAG),'$O(^HLB("C",+MSG("BODY"),0)) D KILL777(MSG("BODY")) 143 Q 144 ; 145 KILL777(BODY) ; 146 Q:'$G(BODY) 147 N TIME 148 S TIME=$P($G(^HLA(BODY,0)),"^") 149 K ^HLA(BODY) 150 K:(TIME]"") ^HLA("B",TIME,BODY) 151 Q 152 ; 153 KSEARCH(MSG,MSGTYPE,EVENT,SAPP,RAPP,IEN) ; 154 ;Kills the ^HLB("SEARCH") x-ref 155 ; 156 N APP 157 S:MSGTYPE="" MSGTYPE="<none>" 158 S:EVENT="" EVENT="<none>" 159 Q:'MSG("DT/TM CREATED") 160 I MSG("DIRECTION")'="IN",MSG("DIRECTION")'="OUT" Q 161 S APP=$S(MSG("DIRECTION")="IN":RAPP,1:SAPP) 162 Q:APP="" 163 K ^HLB("SEARCH",MSG("DIRECTION"),MSG("DT/TM CREATED"),APP,MSGTYPE,EVENT,IEN) 164 Q 1 HLOPURGE ;IRMFO-ALB/CJM - Purging Old Messages;03/24/2004 14:43 ;04/30/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134,136**;Oct 13, 1995;Build 9 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 GETWORK(WORK) ; 6 ; 7 N OK 8 S OK=0 9 I $G(WORK)]"" L -HLPURGE(WORK) 10 F WORK="IN","OUT","OLD778","OLD777" I '$G(WORK("DONE",WORK)) S WORK("DONE",WORK)=1 L +HLPURGE(WORK):0 S OK=$T Q:OK 11 I 'OK K WORK("DONE") S WORK="" 12 Q OK 13 ; 14 DOWORK(WORK) ; 15 I WORK="OLD778" D OLD778 16 I WORK="OLD777" D OLD777 17 I (WORK="IN")!(WORK="OUT") D 18 .N TIME,NOW 19 .S NOW=$$NOW^XLFDT 20 .S TIME=0 21 .F S TIME=$O(^HLB("AD",WORK,TIME)) Q:TIME="" Q:TIME>NOW D 22 ..N MSGIEN 23 ..S MSGIEN=0 24 ..F S MSGIEN=$O(^HLB("AD",WORK,TIME,MSGIEN)) Q:'MSGIEN D 25 ...K ^HLB("AD",WORK,TIME,MSGIEN) 26 ...D DELETE(MSGIEN) 27 L -HLPURGE(WORK) 28 Q 29 OLD778 ; 30 N OLD,START,END,APP,TYPE,TODAY 31 S TODAY=$$DT^XLFDT 32 S OLD=$$FMADD^XLFDT(TODAY,-45) 33 F START=0,100000000000,200000000000,300000000000 D 34 .S END=(START+100000000000)-1 35 .N MSGIEN,QUIT 36 .S QUIT=0 37 .S MSGIEN=START 38 .F S MSGIEN=$O(^HLB(MSGIEN)) Q:'MSGIEN Q:(MSGIEN>END) D Q:QUIT 39 ..N WHEN,BODY,NODE 40 ..S NODE=$G(^HLB(MSGIEN,0)) 41 ..S WHEN=$P(NODE,"^",16) 42 ..I WHEN,WHEN<OLD,$P(NODE,"^",9)<TODAY D DELETE(MSGIEN) Q 43 ..I 'WHEN D 44 ...S BODY=$P(NODE,"^",2) 45 ...Q:'BODY 46 ...S WHEN=+$G(^HLA(BODY,0)) 47 ...I WHEN,WHEN<OLD D Q 48 ....;I've seen messages sitting on outgoing queues forever, but it should never happen for incoming 49 ....I $E($P(NODE,"^",4))="O",$P(NODE,"^",5)]"",$P(NODE,"^",6)]"" D 50 .....N FROM 51 .....S FROM=$P(NODE,"^",5) 52 .....I $P(NODE,"^",8) S FROM=FROM_":"_$P(NODE,"^",8) 53 .....Q:'$D(^HLB("QUEUE","OUT",FROM,$P(NODE,"^",6),MSGIEN)) 54 .....D DEQUE^HLOQUE(FROM,$P(NODE,"^",6),"OUT",MSGIEN) 55 ....D DELETE(MSGIEN) Q 56 ...;stop looking for old records? 57 ...I WHEN,WHEN>OLD S QUIT=1 58 ; 59 ;also kill old errors left lying around 60 F TYPE="TF","AE","SE" S APP="" F S APP=$O(^HLB("ERRORS",TYPE,APP)) Q:APP="" D 61 .N TIME,PARMS 62 .D SYSPARMS^HLOSITE(.PARMS) 63 .S OLD=$$FMADD^XLFDT($$DT^XLFDT,-PARMS("ERROR PURGE")) 64 .S TIME=0 65 .F S TIME=$O(^HLB("ERRORS",TYPE,APP,TIME)) Q:'TIME Q:TIME>OLD K ^HLB("ERRORS",TYPE,APP,TIME) 66 Q 67 OLD777 ; 68 N OLD,TIME,TODAY 69 S TODAY=$$DT^XLFDT 70 S OLD=$$FMADD^XLFDT(TODAY,-45) 71 S TIME=0 72 F S TIME=$O(^HLA("B",TIME)) Q:'TIME Q:TIME>OLD D 73 .N MSGIEN 74 .S MSGIEN=0 75 .F S MSGIEN=$O(^HLA("B",TIME,MSGIEN)) Q:'MSGIEN D 76 ..N IEN778,STOP 77 ..S (STOP,IEN778)=0 78 ..F S IEN778=$O(^HLB("C",MSGIEN,IEN778)) Q:'IEN778 D 79 ...I $P($G(^HLB(IEN778,0)),"^",9)>TODAY S STOP=1 Q 80 ...D DELETE(IEN778,1) 81 ..K:'STOP ^HLB("C",MSGIEN),^HLA("B",TIME,MSGIEN),^HLA(MSGIEN) 82 Q 83 ; 84 DELETE(MSGIEN,FLAG) ; 85 ;Input: 86 ; MSGIEN - IEN, file 778 87 ; FLAG - if $G(FLAG), will not delete the pointed to record in file 777 88 N AC,SUBIEN,RAPP,SAPP,FS,CS,MSG 89 I '$$GETMSG^HLOMSG(MSGIEN,.MSG) ;MSG is corrupted, but there sill may be nodes to delete 90 S (RAPP,SAPP)="" 91 D 92 .S FS=$E(MSG("HDR",1),4) 93 .Q:FS="" 94 .S CS=$E(MSG("HDR",1),5) 95 .S SAPP=$P($P(MSG("HDR",1),FS,3),CS) 96 .I SAPP="" S SAPP="UNKNOWN" 97 .S RAPP=$P($P(MSG("HDR",1),FS,5),CS) 98 .I RAPP="" S RAPP="UNKNOWN" 99 ; 100 I 'MSG("BATCH") D KSEARCH(.MSG,MSG("MESSAGE TYPE"),MSG("EVENT"),SAPP,RAPP,MSGIEN) 101 ;if an error status,take care of the "ERRORS" x-ref 102 I MSG("STATUS")'="",MSG("STATUS")'="SU",MSG("BODY") D 103 .N APP 104 .S APP=$S(MSG("STATUS")="TF":SAPP,1:RAPP) 105 .K ^HLB("ERRORS",MSG("STATUS"),APP,MSG("DT/TM CREATED"),MSGIEN) 106 .I MSG("STATUS")="AE" D 107 ..N SUB 108 ..S SUB=MSGIEN_"^" 109 ..K ^HLB("ERRORS","AE",APP,MSG("DT/TM CREATED"),SUB) 110 ..F S SUB=$O(^HLB("ERRORS","AE",APP,MSG("DT/TM CREATED"),SUB)) Q:SUB="" Q:+SUB'=MSGIEN K ^HLB("ERRORS","AE",APP,MSG("DT/TM CREATED"),SUB) 111 ; 112 ;kill the whole-file xrefs for the message ien within a batch 113 S SUBIEN=0 114 F S SUBIEN=$O(^HLB(MSGIEN,3,SUBIEN)) Q:'SUBIEN D 115 .N MSGID 116 .I FS]"" D 117 ..N VALUE,HDR2,MSGTYPE,EVENT 118 ..S HDR2=$G(^HLB(MSGIEN,3,SUBIEN,2)) 119 ..S VALUE=$P(HDR2,FS,4) 120 ..S MSGTYPE=$P(VALUE,CS) 121 ..S EVENT=$P(VALUE,CS,2) 122 ..D KSEARCH(.MSG,MSGTYPE,EVENT,SAPP,RAPP,MSGIEN_"^"_SUBIEN) 123 .S MSGID=$P($G(^HLB(MSGIEN,3,SUBIEN,0)),"^",2) 124 .I MSGID]"" K ^HLB("AE",MSGID,MSGIEN_"^"_SUBIEN) 125 ; 126 I MSG("DIRECTION")="IN" D 127 .Q:FS="" 128 .N VALUE,HDR 129 .S HDR("SENDING APPLICATION")=$P(MSG("HDR",1),FS,3) 130 .S VALUE=$P(MSG("HDR",1),FS,4) 131 .S HDR("SENDING FACILITY",1)=$P(VALUE,CS) 132 .S HDR("SENDING FACILITY",2)=$P(VALUE,CS,2) 133 .S HDR("SENDING FACILITY",3)=$P(VALUE,CS,3) 134 .S AC=$S(HDR("SENDING FACILITY",2)]"":HDR("SENDING FACILITY",2),1:HDR("SENDING FACILITY",1))_HDR("SENDING APPLICATION")_MSG("ID") 135 K ^HLB(MSGIEN) 136 I MSG("STATUS","PURGE"),MSG("DIRECTION")'="" K ^HLB("AD",MSG("DIRECTION"),MSG("STATUS","PURGE"),MSGIEN) 137 K:(MSG("ID")]"") ^HLB("B",MSG("ID"),MSGIEN) 138 I MSG("DIRECTION")="IN" D 139 .K:($G(AC)]"") ^HLB("AC",AC,MSGIEN) 140 .I MSG("BODY"),'$G(FLAG) D KILL777(MSG("BODY")) 141 I MSG("DIRECTION")="OUT" D 142 .K ^HLB("C",+MSG("BODY"),MSGIEN) 143 .I '$G(FLAG),'$O(^HLB("C",+MSG("BODY"),0)) D KILL777(MSG("BODY")) 144 Q 145 ; 146 KILL777(BODY) ; 147 Q:'$G(BODY) 148 N TIME 149 S TIME=$P($G(^HLA(BODY,0)),"^") 150 K ^HLA(BODY) 151 K:(TIME]"") ^HLA("B",TIME,BODY) 152 Q 153 ; 154 KSEARCH(MSG,MSGTYPE,EVENT,SAPP,RAPP,IEN) ; 155 ;Kills the ^HLB("SEARCH") x-ref 156 ; 157 N APP 158 S:MSGTYPE="" MSGTYPE="<none>" 159 S:EVENT="" EVENT="<none>" 160 Q:'MSG("DT/TM CREATED") 161 I MSG("DIRECTION")'="IN",MSG("DIRECTION")'="OUT" Q 162 S APP=$S(MSG("DIRECTION")="IN":RAPP,1:SAPP) 163 Q:APP="" 164 K ^HLB("SEARCH",MSG("DIRECTION"),MSG("DT/TM CREATED"),APP,MSGTYPE,EVENT,IEN) 165 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOQUE.m
r613 r623 1 HLOQUE ;ALB/CJM- HL7 QUEUE MANAGEMENT - 10/4/94 1pm ;07/31/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,132,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 INQUE(FROM,QNAME,IEN778,ACTION,PURGE) ; 6 ;Will place the message=IEN778 on the IN queue, incoming 7 ;Input: 8 ; FROM - sending facility from message header. 9 ; For actions other than incoming messages, its the specified link. 10 ; QNAME - queue named by the application 11 ; IEN778 = ien of the message in file 778 12 ; ACTION - <tag^routine> that should be executed for the application 13 ; PURGE (optional) - PURGE=1 indicates that the purge dt/tm needs to be set by the infiler 14 ; If PURGE("ACKTOIEN") is set, it indicates that the purge dt/tm of 15 ; the original message to this application ack also needs to be set. 16 ;Output: none 17 ; 18 I $G(FROM)="" S FROM="UNKNOWN" 19 I '$L($G(QNAME)) S QNAME="DEFAULT" 20 S ^HLB("QUEUE","IN",FROM,QNAME,IEN778)=ACTION_"^"_$G(PURGE)_"^"_$G(PURGE("ACKTOIEN")) 21 I $$INC^HLOSITE($NA(^HLC("QUEUECOUNT","IN",FROM,QNAME))) 22 Q 23 ; 24 OUTQUE(LINKNAME,PORT,QNAME,IEN778) ; 25 ;Will place the message=IEN778 on the out-going queue 26 ;Input: 27 ; LINKNAME = name of (.01) the logical link 28 ; PORT (optional) the port to connect to 29 ; QNAME - queue named by the application 30 ; IEN778 = ien of the message in file 778 31 ;Output: none 32 ; 33 N SUB 34 S SUB=LINKNAME 35 I PORT S SUB=SUB_":"_PORT 36 I '$L($G(QNAME)) S QNAME="DEFAULT" 37 S ^HLB("QUEUE","OUT",SUB,QNAME,IEN778)="" 38 I $$INC^HLOSITE($NA(^HLC("QUEUECOUNT","OUT",SUB,QNAME))) 39 Q 40 ; 41 DEQUE(FROMORTO,QNAME,DIR,IEN778) ; 42 ;This routine will remove the message=IEN778 from its queue 43 ;Input: 44 ; DIR = "IN" or "OUT", denoting the direction that the message is going in 45 ; FROMORTO = for outgoing: the .01 field of the logical link 46 ; for incoming: sending facility 47 ; IEN778 = ien of the message in file 778 48 ;Output: none 49 ; 50 Q:(FROMORTO="") 51 I ($G(QNAME)="") S QNAME="DEFAULT" 52 D 53 .I $E(DIR)="I" S DIR="IN" Q 54 .I $E(DIR)="O" S DIR="OUT" Q 55 I DIR'="IN",DIR'="OUT" Q 56 Q:'$G(IEN778) 57 D:$D(^HLB("QUEUE",DIR,FROMORTO,QNAME,IEN778)) 58 .K ^HLB("QUEUE",DIR,FROMORTO,QNAME,IEN778) 59 .;don't let the count become negative 60 .I $$INC^HLOSITE($NA(^HLC("QUEUECOUNT",DIR,FROMORTO,QNAME)),-1)<0,$$INC^HLOSITE($NA(^HLC("QUEUECOUNT",DIR,FROMORTO,QNAME))) 61 Q 62 ; 63 STOPQUE(DIR,QUEUE) ; 64 ;This API is used to set a stop flag on a named queue. 65 ;DIR=<"IN" or "OUT"> 66 ;QUEUE - the name of the queue to be stopped 67 ; 68 Q:$G(DIR)="" 69 Q:$G(QUEUE)="" 70 S ^HLTMP("STOPPED QUEUES",DIR,QUEUE)=1 71 Q 72 STARTQUE(DIR,QUEUE) ; 73 ;This API is used to REMOVE the stop flag on a named queue. 74 ;DIR=<"IN" or "OUT"> 75 ;QUEUE - the name of the queue to be stopped 76 ; 77 Q:$G(DIR)="" 78 Q:$G(QUEUE)="" 79 K ^HLTMP("STOPPED QUEUES",DIR,QUEUE) 80 Q 81 STOPPED(DIR,QUEUE) ; 82 ;This API is used to DETERMINE if the stop flag on a named queue is set. 83 ;Input: 84 ; DIR=<"IN" or "OUT"> 85 ; QUEUE - the name of the queue to be checked 86 ;Output: 87 ; Function returns 1 if the queue is stopped, 0 otherwise 88 Q:$G(DIR)="" 0 89 Q:$G(QUEUE)="" 0 90 I $G(^HLTMP("STOPPED QUEUES",DIR,QUEUE)) Q 1 91 Q 0 92 ; 93 SQUE(SQUE,LINKNAME,PORT,QNAME,IEN778) ; 94 ;Will place the message=IEN778 on the sequencing queue. This is always done in the context of the application calling an HLO API to send a message. 95 ;Input: 96 ; SQUE - name of the sequencing queue 97 ; LINKNAME = name of (.01) the logical link 98 ; PORT (optional) the port to connect to 99 ; QNAME (optional) outgoing queue 100 ; IEN778 = ien of the message in file 778 101 ;Output: 1 if placed on the outgoing queue, 0 if placed on the sequence queue 102 ; 103 N NEXT,MOVED 104 S MOVED=0 105 ; 106 ;keep a count of messages pending on sequence queues for the HLO System Monitor 107 I $$INC^HLOSITE($NA(^HLC("QUEUECOUNT","SEQUENCE"))) 108 ; 109 L +^HLB("QUEUE","SEQUENCE",SQUE):200 110 ; 111 S NEXT=+$G(^HLB("QUEUE","SEQUENCE",SQUE)) 112 Q:NEXT=IEN778 0 ;already queued! 113 ;if the sequence queue is empty and not waiting on a message, then the message can be put directly on the outgoing queue, bypassing the sequence queue 114 I '$O(^HLB("QUEUE","SEQUENCE",SQUE,0)),'NEXT D 115 .S ^HLB("QUEUE","SEQUENCE",SQUE)=IEN778 ;to mean something moved to outgoing but not yet transmitted 116 .L -^HLB("QUEUE","SEQUENCE",SQUE) 117 .D OUTQUE(.LINKNAME,.PORT,.QNAME,IEN778) 118 .S MOVED=1 119 E D 120 .;Put the message on the sequence queue. 121 .S ^HLB("QUEUE","SEQUENCE",SQUE,IEN778)="" 122 .L -^HLB("QUEUE","SEQUENCE",SQUE) 123 Q MOVED 124 ; 125 ADVANCE(SQUE,MSGIEN) ; 126 ;Will move the specified sequencing queue to the next message. 127 ;Input: 128 ; SQUE - name of the sequencing queue 129 ; MSGIEN - the ien of the message upon which the sequence queue was waiting. If it is NOT the correct ien, then the sequence queue will NOT be advance. 130 ;Output: 131 ; Function - 1 if advanced, 0 if not 132 ; 133 N NODE,IEN778,LINKNAME,PORT,QNAME 134 Q:'$L($G(SQUE)) 0 135 Q:'$G(MSGIEN) 0 136 L +^HLB("QUEUE","SEQUENCE",SQUE):200 137 ; 138 ;do not advance if the queue wasn't pending the message=MSGIEN 139 I (MSGIEN'=$P($G(^HLB("QUEUE","SEQUENCE",SQUE)),"^")) L -^HLB("QUEUE","SEQUENCE",SQUE) Q 0 140 ; 141 I $$INC^HLOSITE($NA(^HLC("QUEUECOUNT","SEQUENCE")),-1)<0,$$INC^HLOSITE($NA(^HLC("QUEUECOUNT","SEQUENCE"))) ;decrement the count of messages pending sequence queues 142 ; 143 S IEN778=0 144 ;look for the first message on the sequence que. Make sure its valid, if not remove the invalid entry and keep looking. 145 F S IEN778=$O(^HLB("QUEUE","SEQUENCE",SQUE,0)) Q:'IEN778 S NODE=$G(^HLB(IEN778,0)) Q:$L(NODE) D 146 .;message does not exist! Remove from queue and try again. 147 .K ^HLB("QUEUE","SEQUENCE",SQUE,IEN778) 148 .I $$INC^HLOSITE($NA(^HLC("QUEUECOUNT","SEQUENCE")),-1)<0,$$INC^HLOSITE($NA(^HLC("QUEUECOUNT","SEQUENCE"))) ;decrement the count of messages pending sequence queues 149 ; 150 ;IEN778 is the next pending msg on this sequence queue 151 I IEN778 D 152 .; 153 .;parse out info needed to move to outgoing queue 154 .S LINKNAME=$P(NODE,"^",5),PORT=$P(NODE,"^",8),QNAME=$P(NODE,"^",6) 155 .; 156 .S ^HLB("QUEUE","SEQUENCE",SQUE)=IEN778 ;indicates this sequence queue is now waiting for msg=IEN778 before advancing. The second pieces is the timer, but will not be set until the message=IEN778 is actually transmitted. 157 .K ^HLB("QUEUE","SEQUENCE",SQUE,IEN778) ;remove from sequence queue 158 .L -^HLB("QUEUE","SEQUENCE",SQUE) 159 .S $P(^HLB(IEN778,5),"^",2)=1 160 .D OUTQUE(.LINKNAME,$G(PORT),$G(QNAME),IEN778) ;move to outgoing queue 161 E D 162 .K ^HLB("QUEUE","SEQUENCE",SQUE) ;this sequence queue is currently empty and not needed 163 .L -^HLB("QUEUE","SEQUENCE",SQUE) 164 Q 1 165 ; 166 SEQCHK(WORK) ;functions under the HLO Process Manager 167 ;check sequence queues for timeout 168 N QUE,NOW 169 S NOW=$$NOW^XLFDT 170 S QUE="" 171 F S QUE=$O(^HLB("QUEUE","SEQUENCE",QUE)) Q:QUE="" D 172 .N NODE,MSGIEN,ACTION,NODE 173 .S NODE=$G(^HLB("QUEUE","SEQUENCE",QUE)) 174 .Q:'$P(NODE,"^",2) 175 .Q:$P(NODE,"^",2)>NOW 176 .Q:$P(NODE,"^",3) 177 .L +^HLB("QUEUE","SEQUENCE",QUE):2 178 .;don't report if a lock wasn't obtained 179 .Q:'$T 180 .S NODE=$G(^HLB("QUEUE","SEQUENCE",QUE)) 181 .I '$P(NODE,"^",2) L -^HLB("QUEUE","SEQUENCE",QUE) Q 182 .I ($P(NODE,"^",2)>NOW) L -^HLB("QUEUE","SEQUENCE",QUE) Q 183 .I $P(NODE,"^",3) L -^HLB("QUEUE","SEQUENCE",QUE) Q ;exception already raised 184 .S MSGIEN=$P(NODE,"^") 185 .I 'MSGIEN L -^HLB("QUEUE","SEQUENCE",QUE) Q 186 .S ACTION=$$EXCEPT^HLOAPP($$GETSAP^HLOCLNT2(MSGIEN)) 187 .S $P(^HLB(MSGIEN,5),"^",3)=1 188 .S $P(^HLB("QUEUE","SEQUENCE",QUE),"^",3)=1 ;indicates exception raised 189 .L -^HLB("QUEUE","SEQUENCE",QUE) 190 .D ;call the application to take action 191 ..N HLMSGIEN,MCODE,DUZ,QUE,NOW 192 ..N $ETRAP,$ESTACK S $ETRAP="G ERROR^HLOQUE" 193 ..S HLMSGIEN=MSGIEN 194 ..S MCODE="D "_ACTION 195 ..N MSGIEN,X 196 ..D DUZ^XUP(.5) 197 ..X MCODE 198 ..;kill the apps variables 199 ..D 200 ...N ZTSK 201 ...D KILL^XUSCLEAN 202 Q 203 ERROR ;error trap for application context 204 S $ETRAP="D UNWIND^%ZTER" 205 D ^%ZTER 206 S $ECODE=",UAPPLICATION ERROR," 207 ; 208 ;kill the apps variables 209 D 210 .N ZTSK,MSGIEN,QUEUE 211 .D KILL^XUSCLEAN 212 ; 213 ;release all the locks the app may have set, except Taskman lock 214 L:$D(ZTSK) ^%ZTSCH("TASK",ZTSK):1 215 L:'$D(ZTSK) 216 ;reset HLO's lock 217 L +^HLTMP("HL7 RUNNING PROCESSES",$J):0 218 ;return to processing the next message on the queue 219 D UNWIND^%ZTER 220 Q 1 HLOQUE ;ALB/CJM- HL7 QUEUE MANAGEMENT - 10/4/94 1pm ;01/05/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,132,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 INQUE(FROM,QNAME,IEN778,ACTION,PURGE) ; 6 ;Will place the message=IEN778 on the IN queue, incoming 7 ;Input: 8 ; FROM - sending facility from message header. 9 ; For actions other than incoming messages, its the specified link. 10 ; QNAME - queue named by the application 11 ; IEN778 = ien of the message in file 778 12 ; ACTION - <tag^routine> that should be executed for the application 13 ; PURGE (optional) - PURGE=1 indicates that the purge dt/tm needs to be set by the infiler 14 ; If PURGE("ACKTOIEN") is set, it indicates that the purge dt/tm of 15 ; the original message to this application ack also needs to be set. 16 ;Output: none 17 ; 18 I $G(FROM)="" S FROM="UNKNOWN" 19 I '$L($G(QNAME)) S QNAME="DEFAULT" 20 S ^HLB("QUEUE","IN",FROM,QNAME,IEN778)=ACTION_"^"_$G(PURGE)_"^"_$G(PURGE("ACKTOIEN")) 21 I $$INC^HLOSITE($NA(^HLC("QUEUECOUNT","IN",FROM,QNAME))) 22 Q 23 ; 24 OUTQUE(LINKNAME,PORT,QNAME,IEN778) ; 25 ;Will place the message=IEN778 on the out-going queue 26 ;Input: 27 ; LINKNAME = name of (.01) the logical link 28 ; PORT (optional) the port to connect to 29 ; QNAME - queue named by the application 30 ; IEN778 = ien of the message in file 778 31 ;Output: none 32 ; 33 N SUB 34 S SUB=LINKNAME 35 I PORT S SUB=SUB_":"_PORT 36 I '$L($G(QNAME)) S QNAME="DEFAULT" 37 S ^HLB("QUEUE","OUT",SUB,QNAME,IEN778)="" 38 I $$INC^HLOSITE($NA(^HLC("QUEUECOUNT","OUT",SUB,QNAME))) 39 Q 40 ; 41 DEQUE(FROMORTO,QNAME,DIR,IEN778) ; 42 ;This routine will remove the message=IEN778 from its queue 43 ;Input: 44 ; DIR = "IN" or "OUT", denoting the direction that the message is going in 45 ; FROMORTO = for outgoing: the .01 field of the logical link 46 ; for incoming: sending facility 47 ; IEN778 = ien of the message in file 778 48 ;Output: none 49 ; 50 Q:(FROMORTO="") 51 I ($G(QNAME)="") S QNAME="DEFAULT" 52 D 53 .I $E(DIR)="I" S DIR="IN" Q 54 .I $E(DIR)="O" S DIR="OUT" Q 55 I DIR'="IN",DIR'="OUT" Q 56 Q:'$G(IEN778) 57 D:$D(^HLB("QUEUE",DIR,FROMORTO,QNAME,IEN778)) 58 .K ^HLB("QUEUE",DIR,FROMORTO,QNAME,IEN778) 59 .;don't let the count become negative 60 .I $$INC^HLOSITE($NA(^HLC("QUEUECOUNT",DIR,FROMORTO,QNAME)),-1)<0,$$INC^HLOSITE($NA(^HLC("QUEUECOUNT",DIR,FROMORTO,QNAME))) 61 Q 62 ; 63 STOPQUE(DIR,QUEUE) ; 64 ;This API is used to set a stop flag on a named queue. 65 ;DIR=<"IN" or "OUT"> 66 ;QUEUE - the name of the queue to be stopped 67 ; 68 Q:$G(DIR)="" 69 Q:$G(QUEUE)="" 70 S ^HLTMP("STOPPED QUEUES",DIR,QUEUE)=1 71 Q 72 STARTQUE(DIR,QUEUE) ; 73 ;This API is used to REMOVE the stop flag on a named queue. 74 ;DIR=<"IN" or "OUT"> 75 ;QUEUE - the name of the queue to be stopped 76 ; 77 Q:$G(DIR)="" 78 Q:$G(QUEUE)="" 79 K ^HLTMP("STOPPED QUEUES",DIR,QUEUE) 80 Q 81 STOPPED(DIR,QUEUE) ; 82 ;This API is used to DETERMINE if the stop flag on a named queue is set. 83 ;Input: 84 ; DIR=<"IN" or "OUT"> 85 ; QUEUE - the name of the queue to be checked 86 ;Output: 87 ; Function returns 1 if the queue is stopped, 0 otherwise 88 Q:$G(DIR)="" 0 89 Q:$G(QUEUE)="" 0 90 I $G(^HLTMP("STOPPED QUEUES",DIR,QUEUE)) Q 1 91 Q 0 -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOSRVR.m
r613 r623 1 HLOSRVR ;ALB/CJM- Server for receiving messages - 10/4/94 1pm ;07/19/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,130,131,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 GETWORK(WORK) ; 6 ;GET WORK function for a single server or a Taskman multi-server 7 N LINK 8 I '$$CHKSTOP^HLOPROC,$G(WORK("LINK"))]"",$$GETLINK^HLOTLNK(WORK("LINK"),.LINK),+LINK("SERVER") S WORK("PORT")=LINK("PORT") Q 1 9 Q 0 10 ; 11 DOWORKS(WORK) ; 12 ;DO WORK rtn for a single server (non-concurrent) 13 D SERVER(WORK("LINK")) 14 Q 15 DOWORKM(WORK) ; 16 ;DO WORK rtn for a Taskman multi-server (Cache systems only) 17 D LISTEN^%ZISTCPS(WORK("PORT"),"SERVER^HLOSRVR("""_WORK("LINK")_""")") 18 Q 19 ; 20 VMS2(LINKNAME) ;called from a VMS TCP Service once a connection request has been received. This entry point should be used only if an additional VMS TCPIP Services are being created for HLO. 21 ;Input: 22 ; LINKNAME - only pass it in if an additional service is being created on a different port 23 Q:'$L(LINKNAME) 24 D VMS 25 Q 26 ; 27 VMS ;Called from VMS TCP Service once a connection request has been received. This entry point should be used only by the standard HLO service that runs on the standard HLO port. 28 Q:$$CHKSTOP^HLOPROC 29 D 30 .Q:$L($G(LINKNAME)) 31 .; 32 .N PROC,NODE 33 .S PROC=$O(^HLD(779.3,"B","VMS TCP LISTENER",0)) 34 .I PROC S LINKNAME=$P($G(^HLD(779.3,PROC,0)),"^",14) Q:$L(LINKNAME) 35 .S NODE=$G(^HLD(779.1,1,0)) I $P(NODE,"^",10) S LINKNAME=$P($G(^HLCS(870,$P(NODE,"^",10),0)),"^") Q:$L(LINKNAME) 36 .S LINKNAME="HLO DEFAULT LISTENER" 37 ; 38 D SERVER(LINKNAME,"SYS$NET") 39 Q 40 ; 41 SERVER(LINKNAME,LOGICAL) ; LINKNAME identifies the logical link, which describes the communication channel to be used 42 N $ETRAP,$ESTACK S $ETRAP="G ERROR^HLOSRVR1" 43 N HLCSTATE,INQUE 44 S INQUE=0 45 Q:'$$CONNECT(.HLCSTATE,LINKNAME,.LOGICAL) 46 K LINKNAME 47 F Q:'HLCSTATE("CONNECTED") D Q:$$CHKSTOP^HLOPROC 48 .N HLMSTATE,SENT 49 .; 50 .;read msg and parse the hdr 51 .;HLMSTATE("MSA",1) is set with type of ack to return 52 .I $$READMSG^HLOSRVR1(.HLCSTATE,.HLMSTATE) D 53 ..; 54 ..;send an ack if required and save the MSA segment 55 ..I (HLMSTATE("MSA",1)]"") S SENT=$$WRITEACK(.HLCSTATE,.HLMSTATE) D:HLMSTATE("IEN") SAVEACK(.HLMSTATE,SENT) 56 ..D:HLMSTATE("IEN") UPDATE(.HLMSTATE,.HLCSTATE) 57 ..D:HLCSTATE("COUNTS")>4 SAVECNTS^HLOSTAT(.HLCSTATE) 58 ..I $G(HLMSTATE("ACK TO","IEN")),$L($G(HLMSTATE("ACK TO","SEQUENCE QUEUE"))) D ADVANCE^HLOQUE(HLMSTATE("ACK TO","SEQUENCE QUEUE"),+HLMSTATE("ACK TO","IEN")) 59 .E D INQUE() H:HLCSTATE("CONNECTED") 1 60 ; 61 END D CLOSE^HLOT(.HLCSTATE) 62 D INQUE() 63 D SAVECNTS^HLOSTAT(.HLCSTATE) 64 Q 65 ; 66 CONNECT(HLCSTATE,LINKNAME,LOGICAL) ; 67 ;sets up HLCSTATE() and opens a server connection 68 ; 69 N LINK,NODE 70 S HLCSTATE("CONNECTED")=0 71 Q:'$$GETLINK^HLOTLNK(LINKNAME,.LINK) 0 72 Q:+LINK("SERVER")'=1 0 73 S HLCSTATE("SERVER")=LINK("SERVER") 74 M HLCSTATE("LINK")=LINK 75 S HLCSTATE("READ TIMEOUT")=20 76 S HLCSTATE("OPEN TIMEOUT")=30 77 S HLCSTATE("READ")="" ;buffer for reads 78 ; 79 ;HLCSTATE("BUFFER",<seg>,<line>) write buffer 80 S HLCSTATE("BUFFER","BYTE COUNT")=0 ;count of bytes in buffer 81 S HLCSTATE("BUFFER","SEGMENT COUNT")=0 ;count of segments in buffer 82 ; 83 S HLCSTATE("COUNTS")=0 84 S HLCSTATE("MESSAGE ENDED")=0 ;end of message flag 85 S NODE=^%ZOSF("OS") 86 S HLCSTATE("SYSTEM","OS")=$S(NODE["DSM":"DSM",NODE["OpenM":"CACHE",NODE["G.TM":"G.TM",1:"") 87 Q:HLCSTATE("SYSTEM","OS")="" 0 88 D ;get necessary system parameters 89 .N SYS,SUB 90 .D SYSPARMS^HLOSITE(.SYS) 91 .F SUB="MAXSTRING","DOMAIN","STATION","PROCESSING ID","NORMAL PURGE","ERROR PURGE" S HLCSTATE("SYSTEM",SUB)=SYS(SUB) 92 .S HLCSTATE("SYSTEM","BUFFER")=SYS("HL7 BUFFER") 93 I HLCSTATE("LINK","LLP")="TCP" D 94 .D OPEN^HLOTCP(.HLCSTATE,.LOGICAL) 95 E ;no other LLP implemented 96 ; 97 Q HLCSTATE("CONNECTED") 98 ; 99 INQUE(MSGIEN,PARMS) ; 100 ;puts received messages on the incoming queue and sets the B x-refs 101 I $G(MSGIEN) S INQUE=INQUE+1 M INQUE(MSGIEN)=PARMS 102 I ('$G(MSGIEN))!(INQUE>20) S MSGIEN=0 D 103 .F S MSGIEN=$O(INQUE(MSGIEN)) Q:'MSGIEN D 104 ..S ^HLB("B",INQUE(MSGIEN,"MSGID"),MSGIEN)="" 105 ..S ^HLA("B",INQUE(MSGIEN,"DT/TM"),INQUE(MSGIEN,"BODY"))="" 106 ..D:INQUE(MSGIEN,"PASS") 107 ...N PURGE 108 ...S PURGE=+$G(INQUE(MSGIEN,"PURGE")) 109 ...S PURGE("ACKTOIEN")=$G(INQUE(MSGIEN,"ACKTOIEN")) 110 ...D INQUE^HLOQUE(INQUE(MSGIEN,"FROM"),INQUE(MSGIEN,"QUEUE"),MSGIEN,INQUE(MSGIEN,"ACTION"),.PURGE) 111 .K INQUE S INQUE=0 112 Q 113 ; 114 SAVEACK(HLMSTATE,SENT) ; 115 ;Input: 116 ; SENT - flag = 1 if transmission of ack succeeded, 0 otherwise 117 ; 118 N NODE,I 119 S $P(NODE,"^")=HLMSTATE("MSA","DT/TM OF MESSAGE") 120 S $P(NODE,"^",2)=HLMSTATE("MSA","MESSAGE CONTROL ID") 121 S $P(NODE,"^",3)="MSA" 122 F I=1:1:3 S NODE=NODE_"|"_$G(HLMSTATE("MSA",I)) 123 S ^HLB(HLMSTATE("IEN"),4)=NODE 124 S:SENT $P(^HLB(HLMSTATE("IEN"),0),"^",$S($E(HLMSTATE("MSA",1))="A":18,1:17))=1 125 Q 126 ; 127 UPDATE(HLMSTATE,HLCSTATE) ; 128 ;Updates status and purge date when appropriate 129 ;Also, sets the "B" xrefs, files 777,778, and places message on the incoming queue 130 ; 131 N PARMS,PURGE,WAIT 132 S PARMS("PASS")=0 133 I HLMSTATE("STATUS","ACTION")]"",HLMSTATE("STATUS")'="SE" D 134 .N IEN 135 .S IEN=HLMSTATE("IEN") 136 .S PARMS("PASS")=1,$P(^HLB(IEN,0),"^",6)=HLMSTATE("STATUS","QUEUE"),$P(^HLB(IEN,0),"^",10)=$P(HLMSTATE("STATUS","ACTION"),"^"),$P(^HLB(IEN,0),"^",11)=$P(HLMSTATE("STATUS","ACTION"),"^",2) 137 D:'PARMS("PASS") ;if not passing to the app, set the purge date 138 .I HLMSTATE("STATUS")="" S HLMSTATE("STATUS")="SU" 139 .S:HLMSTATE("BATCH") WAIT=HLCSTATE("SYSTEM","ERROR PURGE") 140 .S:'HLMSTATE("BATCH") WAIT=$S(($G(HLMSTATE("ACK TO","STATUS"))="ER"):24*HLCSTATE("SYSTEM","ERROR PURGE"),HLMSTATE("STATUS")="ER":24*HLCSTATE("SYSTEM","ERROR PURGE"),1:HLCSTATE("SYSTEM","NORMAL PURGE")) 141 .S PURGE=$$FMADD^XLFDT($$NOW^XLFDT,,WAIT) 142 .S $P(^HLB(HLMSTATE("IEN"),0),"^",9)=PURGE 143 .S ^HLB("AD","IN",PURGE,HLMSTATE("IEN"))="" 144 .;if this is an app ack, purge the original message at the same time 145 .I $G(HLMSTATE("ACK TO","IEN")),'HLMSTATE("BATCH") D 146 ..S $P(^HLB(+HLMSTATE("ACK TO","IEN"),0),"^",9)=PURGE 147 ..S ^HLB("AD","IN",PURGE,+HLMSTATE("ACK TO","IEN"))="" 148 ; 149 ;if not waiting for an application ack, set the status now even if passing to the app - but don't set the purge until the infiler passes the message 150 I HLMSTATE("STATUS")="",($G(HLMSTATE("ACK TO","IEN"))!HLMSTATE("HDR","APP ACK TYPE")'="AL") S HLMSTATE("STATUS")="SU" 151 I HLMSTATE("STATUS")'="" S $P(^HLB(HLMSTATE("IEN"),0),"^",20)=HLMSTATE("STATUS") S:$G(HLMSTATE("MSA",3))]"" $P(^HLB(HLMSTATE("IEN"),0),"^",21)=HLMSTATE("MSA",3) D:HLMSTATE("STATUS")="SE" 152 .N APP 153 .S APP=HLMSTATE("HDR","RECEIVING APPLICATION") S:APP="" APP="UNKNOWN" S ^HLB("ERRORS",APP,HLMSTATE("DT/TM"),HLMSTATE("IEN"))="" 154 .D COUNT^HLOESTAT("IN",$G(HLMSTATE("HDR","RECEIVING APPLICATION")),$G(HLMSTATE("HDR","SENDING APPLICATION")),$S(HLMSTATE("BATCH"):"BATCH",1:$G(HLMSTATE("HDR","MESSAGE TYPE"))),$G(HLMSTATE("HDR","EVENT"))) 155 ; 156 ;set the necessary parms for passing the msg to the app via the infiler 157 D:PARMS("PASS") 158 .N I,FROM 159 .S FROM=HLMSTATE("HDR","SENDING FACILITY",1) 160 .I HLMSTATE("HDR","SENDING FACILITY",2)]"" S FROM=FROM_"~"_HLMSTATE("HDR","SENDING FACILITY",2)_"~"_HLMSTATE("HDR","SENDING FACILITY",3) 161 .I FROM="" S FROM="UNKNOWN SENDING FACILITY" 162 .S PARMS("FROM")=FROM,PARMS("QUEUE")=HLMSTATE("STATUS","QUEUE"),PARMS("ACTION")=HLMSTATE("STATUS","ACTION") 163 .I HLMSTATE("STATUS")'="" S PARMS("PURGE")=$S(HLMSTATE("STATUS")="ER":2,$G(HLMSTATE("ACK TO","STATUS"))="ER":2,1:1) 164 .S:$G(HLMSTATE("ACK TO","IEN")) PARMS("ACKTOIEN")=HLMSTATE("ACK TO","IEN") ;to insure that the infiler will know to set the purge date at the same time as the initial message 165 ; 166 S PARMS("BODY")=HLMSTATE("BODY") 167 S PARMS("DT/TM")=HLMSTATE("DT/TM") 168 S PARMS("MSGID")=HLMSTATE("ID") 169 D INQUE(HLMSTATE("IEN"),.PARMS) 170 Q 171 ; 172 WRITEACK(HLCSTATE,HLMSTATE) ; 173 ;Sends an accept ack 174 ; 175 ;Input: 176 ; HLCSTATE (pass by reference) defines the communication channel 177 ; HLMSTATE (pass by reference) the message being acked 178 ; ("MSA",1) - value for MSA-1 179 ; ("MSA",2) - value for MSA-2 180 ; ("MSA",3) - value for MSA-3 181 ; ("HDR") - parsed values for the message being ack'd 182 ;Output: 183 ; Function returns 1 if successful, 0 otherwise 184 ; HLMSTATE("MSA","MESSAGE CONTROL ID") - the msg id of the ack 185 ; HLMSTATE(,"MSA","DT/TM OF MESSAGE") - from the ack header 186 ; 187 N HDR,SUB,FS,CS,MSA,ACKID,TIME 188 ;Hard-code the delimiters, the standard requires that the receiving system accept the delimiters listed in the header 189 S FS="|" 190 S CS="^" 191 S TIME=$$NOW^XLFDT 192 S HLMSTATE("MSA","DT/TM OF MESSAGE")=TIME 193 S ACKID=HLCSTATE("SYSTEM","STATION")_" "_$$NEWIEN^HLOF778A("OUT") 194 S HLMSTATE("MSA","MESSAGE CONTROL ID")=ACKID 195 ; 196 S HDR(1)="MSH"_FS_"^~\&"_FS_HLMSTATE("HDR","RECEIVING APPLICATION")_FS_HLCSTATE("SYSTEM","STATION")_CS_HLCSTATE("SYSTEM","DOMAIN")_CS_"DNS"_FS 197 S HDR(1)=HDR(1)_HLMSTATE("HDR","SENDING APPLICATION")_FS_HLMSTATE("HDR","SENDING FACILITY",1)_CS_HLMSTATE("HDR","SENDING FACILITY",2)_CS_HLMSTATE("HDR","SENDING FACILITY",3) 198 ; 199 S HDR(2)=FS_$$HLDATE^HLFNC(TIME,"TS")_FS_FS_"ACK"_FS_ACKID_FS_HLMSTATE("HDR","PROCESSING ID")_FS_"2.4"_FS_FS_FS_"NE"_FS_"NE" 200 ; 201 S MSA(1)="MSA"_FS 202 F SUB=1:1:3 S MSA(1)=MSA(1)_HLMSTATE("MSA",SUB)_FS 203 I $$WRITEHDR^HLOT(.HLCSTATE,.HDR),$$WRITESEG^HLOT(.HLCSTATE,.MSA),$$ENDMSG^HLOT(.HLCSTATE) S HLCSTATE("COUNTS","ACKS")=$G(HLCSTATE("COUNTS","ACKS"))+1 Q 1 204 S HLMSTATE("MSA","DT/TM OF MESSAGE")="" 205 Q 0 1 HLOSRVR ;ALB/CJM- Server for receiving messages - 10/4/94 1pm ;03/22/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,130,131,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 GETWORK(WORK) ; 6 ;GET WORK function for a single server or a Taskman multi-server 7 N LINK 8 I '$$CHKSTOP^HLOPROC,$G(WORK("LINK"))]"",$$GETLINK^HLOTLNK(WORK("LINK"),.LINK),+LINK("SERVER") S WORK("PORT")=LINK("PORT") Q 1 9 Q 0 10 ; 11 DOWORKS(WORK) ; 12 ;DO WORK rtn for a single server (non-concurrent) 13 D SERVER(WORK("LINK")) 14 Q 15 DOWORKM(WORK) ; 16 ;DO WORK rtn for a Taskman multi-server (Cache systems only) 17 D LISTEN^%ZISTCPS(WORK("PORT"),"SERVER^HLOSRVR("""_WORK("LINK")_""")") 18 Q 19 ; 20 VMS2(LINKNAME) ;called from a VMS TCP Service once a connection request has been received. This entry point should be used only if an additional VMS TCPIP Services are being created for HLO. 21 ;Input: 22 ; LINKNAME - only pass it in if an additional service is being created on a different port 23 Q:'$L(LINKNAME) 24 D VMS 25 Q 26 ; 27 VMS ;Called from VMS TCP Service once a connection request has been received. This entry point should be used only by the standard HLO service that runs on the standard HLO port. 28 Q:$$CHKSTOP^HLOPROC 29 D 30 .Q:$L($G(LINKNAME)) 31 .; 32 .N PROC,NODE 33 .S PROC=$O(^HLD(779.3,"B","VMS TCP LISTENER",0)) 34 .I PROC S LINKNAME=$P($G(^HLD(779.3,PROC,0)),"^",14) Q:$L(LINKNAME) 35 .S NODE=$G(^HLD(779.1,1,0)) I $P(NODE,"^",10) S LINKNAME=$P($G(^HLCS(870,$P(NODE,"^",10),0)),"^") Q:$L(LINKNAME) 36 .S LINKNAME="HLO DEFAULT LISTENER" 37 ; 38 D SERVER(LINKNAME,"SYS$NET") 39 Q 40 ; 41 SERVER(LINKNAME,LOGICAL) ; LINKNAME identifies the logical link, which describes the communication channel to be used 42 N $ETRAP,$ESTACK S $ETRAP="G ERROR^HLOSRVR1" 43 N HLCSTATE,INQUE 44 S INQUE=0 45 Q:'$$CONNECT(.HLCSTATE,LINKNAME,.LOGICAL) 46 K LINKNAME 47 F Q:'HLCSTATE("CONNECTED") D Q:$$CHKSTOP^HLOPROC 48 .N HLMSTATE,SENT 49 .; 50 .;read msg and parse the hdr 51 .;HLMSTATE("MSA",1) is set with type of ack to return 52 .I $$READMSG^HLOSRVR1(.HLCSTATE,.HLMSTATE) D 53 ..; 54 ..;send an ack if required and save the MSA segment 55 ..I (HLMSTATE("MSA",1)]"") S SENT=$$WRITEACK(.HLCSTATE,.HLMSTATE) D:HLMSTATE("IEN") SAVEACK(.HLMSTATE,SENT) 56 ..D:HLMSTATE("IEN") UPDATE(.HLMSTATE,.HLCSTATE) 57 ..D:HLCSTATE("COUNTS")>4 SAVECNTS^HLOSTAT(.HLCSTATE) 58 .E D INQUE() H:HLCSTATE("CONNECTED") 1 59 ; 60 END D CLOSE^HLOT(.HLCSTATE) 61 D INQUE() 62 D SAVECNTS^HLOSTAT(.HLCSTATE) 63 Q 64 ; 65 CONNECT(HLCSTATE,LINKNAME,LOGICAL) ; 66 ;sets up HLCSTATE() and opens a server connection 67 ; 68 N LINK,NODE 69 S HLCSTATE("CONNECTED")=0 70 Q:'$$GETLINK^HLOTLNK(LINKNAME,.LINK) 0 71 Q:+LINK("SERVER")'=1 0 72 S HLCSTATE("SERVER")=LINK("SERVER") 73 M HLCSTATE("LINK")=LINK 74 S HLCSTATE("READ TIMEOUT")=20 75 S HLCSTATE("OPEN TIMEOUT")=30 76 S HLCSTATE("READ")="" ;buffer for reads 77 ; 78 ;HLCSTATE("BUFFER",<seg>,<line>) write buffer 79 S HLCSTATE("BUFFER","BYTE COUNT")=0 ;count of bytes in buffer 80 S HLCSTATE("BUFFER","SEGMENT COUNT")=0 ;count of segments in buffer 81 ; 82 S HLCSTATE("COUNTS")=0 83 S HLCSTATE("MESSAGE ENDED")=0 ;end of message flag 84 S NODE=^%ZOSF("OS") 85 S HLCSTATE("SYSTEM","OS")=$S(NODE["DSM":"DSM",NODE["OpenM":"CACHE",NODE["G.TM":"G.TM",1:"") 86 Q:HLCSTATE("SYSTEM","OS")="" 0 87 D ;get necessary system parameters 88 .N SYS,SUB 89 .D SYSPARMS^HLOSITE(.SYS) 90 .F SUB="MAXSTRING","DOMAIN","STATION","PROCESSING ID","NORMAL PURGE","ERROR PURGE" S HLCSTATE("SYSTEM",SUB)=SYS(SUB) 91 .S HLCSTATE("SYSTEM","BUFFER")=SYS("HL7 BUFFER") 92 I HLCSTATE("LINK","LLP")="TCP" D 93 .D OPEN^HLOTCP(.HLCSTATE,.LOGICAL) 94 E ;no other LLP implemented 95 ; 96 Q HLCSTATE("CONNECTED") 97 ; 98 INQUE(MSGIEN,PARMS) ; 99 ;puts received messages on the incoming queue and sets the B x-refs 100 I $G(MSGIEN) S INQUE=INQUE+1 M INQUE(MSGIEN)=PARMS 101 I ('$G(MSGIEN))!(INQUE>20) S MSGIEN=0 D 102 .F S MSGIEN=$O(INQUE(MSGIEN)) Q:'MSGIEN D 103 ..S ^HLB("B",INQUE(MSGIEN,"MSGID"),MSGIEN)="" 104 ..S ^HLA("B",INQUE(MSGIEN,"DT/TM"),INQUE(MSGIEN,"BODY"))="" 105 ..D:INQUE(MSGIEN,"PASS") 106 ...N PURGE 107 ...S PURGE=+$G(INQUE(MSGIEN,"PURGE")) 108 ...S PURGE("ACKTOIEN")=$G(INQUE(MSGIEN,"ACKTOIEN")) 109 ...D INQUE^HLOQUE(INQUE(MSGIEN,"FROM"),INQUE(MSGIEN,"QUEUE"),MSGIEN,INQUE(MSGIEN,"ACTION"),.PURGE) 110 .K INQUE S INQUE=0 111 Q 112 ; 113 SAVEACK(HLMSTATE,SENT) ; 114 ;Input: 115 ; SENT - flag = 1 if transmission of ack succeeded, 0 otherwise 116 ; 117 N NODE,I 118 S $P(NODE,"^")=HLMSTATE("MSA","DT/TM OF MESSAGE") 119 S $P(NODE,"^",2)=HLMSTATE("MSA","MESSAGE CONTROL ID") 120 S $P(NODE,"^",3)="MSA" 121 F I=1:1:3 S NODE=NODE_"|"_$G(HLMSTATE("MSA",I)) 122 S ^HLB(HLMSTATE("IEN"),4)=NODE 123 S:SENT $P(^HLB(HLMSTATE("IEN"),0),"^",$S($E(HLMSTATE("MSA",1))="A":18,1:17))=1 124 Q 125 ; 126 UPDATE(HLMSTATE,HLCSTATE) ; 127 ;Updates status and purge date when appropriate 128 ;Also, sets the "B" xrefs, files 777,778, and places message on the incoming queue 129 ; 130 N PARMS,PURGE,WAIT 131 S PARMS("PASS")=0 132 I HLMSTATE("STATUS","ACTION")]"",HLMSTATE("STATUS")'="SE" D 133 .N IEN 134 .S IEN=HLMSTATE("IEN") 135 .S PARMS("PASS")=1,$P(^HLB(IEN,0),"^",6)=HLMSTATE("STATUS","QUEUE"),$P(^HLB(IEN,0),"^",10)=$P(HLMSTATE("STATUS","ACTION"),"^"),$P(^HLB(IEN,0),"^",11)=$P(HLMSTATE("STATUS","ACTION"),"^",2) 136 D:'PARMS("PASS") ;if not passing to the app, set the purge date 137 .I HLMSTATE("STATUS")="" S HLMSTATE("STATUS")="SU" 138 .S:HLMSTATE("BATCH") WAIT=HLCSTATE("SYSTEM","ERROR PURGE") 139 .S:'HLMSTATE("BATCH") WAIT=$S(($G(HLMSTATE("ACK TO","STATUS"))="AE"):24*HLCSTATE("SYSTEM","ERROR PURGE"),HLMSTATE("STATUS")="SE":24*HLCSTATE("SYSTEM","ERROR PURGE"),1:HLCSTATE("SYSTEM","NORMAL PURGE")) 140 .S PURGE=$$FMADD^XLFDT($$NOW^XLFDT,,WAIT) 141 .S $P(^HLB(HLMSTATE("IEN"),0),"^",9)=PURGE 142 .S ^HLB("AD","IN",PURGE,HLMSTATE("IEN"))="" 143 .;if this is an app ack, purge the original message at the same time 144 .I $G(HLMSTATE("ACK TO","IEN")),'HLMSTATE("BATCH") D 145 ..S $P(^HLB(+HLMSTATE("ACK TO","IEN"),0),"^",9)=PURGE 146 ..S ^HLB("AD","IN",PURGE,+HLMSTATE("ACK TO","IEN"))="" 147 ; 148 ;if not waiting for an application ack, set the status now even if passing to the app - but don't set the purge until the infiler passes the message 149 I HLMSTATE("STATUS")="",($G(HLMSTATE("ACK TO","IEN"))!HLMSTATE("HDR","APP ACK TYPE")'="AL") S HLMSTATE("STATUS")="SU" 150 I HLMSTATE("STATUS")'="" S $P(^HLB(HLMSTATE("IEN"),0),"^",20)=HLMSTATE("STATUS") S:$G(HLMSTATE("MSA",3))]"" $P(^HLB(HLMSTATE("IEN"),0),"^",21)=HLMSTATE("MSA",3) D:HLMSTATE("STATUS")="SE" 151 .N APP 152 .S APP=HLMSTATE("HDR","RECEIVING APPLICATION") S:APP="" APP="UNKNOWN" S ^HLB("ERRORS","SE",APP,HLMSTATE("DT/TM"),HLMSTATE("IEN"))="" 153 .D COUNT^HLOESTAT("IN",$G(HLMSTATE("HDR","RECEIVING APPLICATION")),$G(HLMSTATE("HDR","SENDING APPLICATION")),$S(HLMSTATE("BATCH"):"BATCH",1:$G(HLMSTATE("HDR","MESSAGE TYPE"))),$G(HLMSTATE("HDR","EVENT"))) 154 ; 155 ;set the necessary parms for passing the msg to the app via the infiler 156 D:PARMS("PASS") 157 .N I,FROM 158 .S FROM=HLMSTATE("HDR","SENDING FACILITY",1) 159 .I HLMSTATE("HDR","SENDING FACILITY",2)]"" S FROM=FROM_"~"_HLMSTATE("HDR","SENDING FACILITY",2)_"~"_HLMSTATE("HDR","SENDING FACILITY",3) 160 .I FROM="" S FROM="UNKNOWN SENDING FACILITY" 161 .S PARMS("FROM")=FROM,PARMS("QUEUE")=HLMSTATE("STATUS","QUEUE"),PARMS("ACTION")=HLMSTATE("STATUS","ACTION") 162 .I HLMSTATE("STATUS")'="" S PARMS("PURGE")=$S(HLMSTATE("STATUS")'="SU":2,$G(HLMSTATE("ACK TO","STATUS"))="AE":2,1:1) 163 .S:$G(HLMSTATE("ACK TO","IEN")) PARMS("ACKTOIEN")=HLMSTATE("ACK TO","IEN") ;to insure that the infiler will know to set the purge date at the same time as the initial message 164 ; 165 S PARMS("BODY")=HLMSTATE("BODY") 166 S PARMS("DT/TM")=HLMSTATE("DT/TM") 167 S PARMS("MSGID")=HLMSTATE("ID") 168 D INQUE(HLMSTATE("IEN"),.PARMS) 169 Q 170 ; 171 WRITEACK(HLCSTATE,HLMSTATE) ; 172 ;Sends an accept ack 173 ; 174 ;Input: 175 ; HLCSTATE (pass by reference) defines the communication channel 176 ; HLMSTATE (pass by reference) the message being acked 177 ; ("MSA",1) - value for MSA-1 178 ; ("MSA",2) - value for MSA-2 179 ; ("MSA",3) - value for MSA-3 180 ; ("HDR") - parsed values for the message being ack'd 181 ;Output: 182 ; Function returns 1 if successful, 0 otherwise 183 ; HLMSTATE("MSA","MESSAGE CONTROL ID") - the msg id of the ack 184 ; HLMSTATE(,"MSA","DT/TM OF MESSAGE") - from the ack header 185 ; 186 N HDR,SUB,FS,CS,MSA,ACKID,TIME 187 ;Hard-code the delimiters, the standard requires that the receiving system accept the delimiters listed in the header 188 S FS="|" 189 S CS="^" 190 S TIME=$$NOW^XLFDT 191 S HLMSTATE("MSA","DT/TM OF MESSAGE")=TIME 192 S ACKID=HLCSTATE("SYSTEM","STATION")_" "_$$NEWIEN^HLOF778A("OUT") 193 S HLMSTATE("MSA","MESSAGE CONTROL ID")=ACKID 194 ; 195 S HDR(1)="MSH"_FS_"^~\&"_FS_HLMSTATE("HDR","RECEIVING APPLICATION")_FS_HLCSTATE("SYSTEM","STATION")_CS_HLCSTATE("SYSTEM","DOMAIN")_CS_"DNS"_FS 196 S HDR(1)=HDR(1)_HLMSTATE("HDR","SENDING APPLICATION")_FS_HLMSTATE("HDR","SENDING FACILITY",1)_CS_HLMSTATE("HDR","SENDING FACILITY",2)_CS_HLMSTATE("HDR","SENDING FACILITY",3) 197 ; 198 S HDR(2)=FS_$$HLDATE^HLFNC(TIME,"TS")_FS_FS_"ACK"_FS_ACKID_FS_HLMSTATE("HDR","PROCESSING ID")_FS_"2.4"_FS_FS_FS_"NE"_FS_"NE" 199 ; 200 S MSA(1)="MSA"_FS 201 F SUB=1:1:3 S MSA(1)=MSA(1)_HLMSTATE("MSA",SUB)_FS 202 I $$WRITEHDR^HLOT(.HLCSTATE,.HDR),$$WRITESEG^HLOT(.HLCSTATE,.MSA),$$ENDMSG^HLOT(.HLCSTATE) S HLCSTATE("COUNTS","ACKS")=$G(HLCSTATE("COUNTS","ACKS"))+1 Q 1 203 S HLMSTATE("MSA","DT/TM OF MESSAGE")="" 204 Q 0 -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOSRVR1.m
r613 r623 1 HLOSRVR1 ;IRMFO-ALB/CJM - Reading messages, sending acks;03/24/2004 14:43 ;07/17/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,130,131,133,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 READMSG(HLCSTATE,HLMSTATE) ; 6 ;Reads a message. The header is parsed. Does these checks: 7 ; 1) Duplicate? 8 ; 2) Wrong Receiving Facility? 9 ; 3) Can the Receiving App accept this message, based message type & event? 10 ; 4) Processing ID must match the receiving system 11 ; 5) Must have an ID 12 ; 6) Header must be BHS or MSH 13 ; 14 ;Output: 15 ; Function returns 1 if the message was read fully, 0 otherwise 16 ; HLMSTATE (pass by reference) the message. It will include the fields for the return ack in HLMSTATE("MSA") 17 ; 18 N ACK,SEG,STORE,I 19 ; 20 S STORE=1 21 Q:'$$READHDR^HLOT(.HLCSTATE,.SEG) 0 22 D SPLITHDR(.SEG) 23 ; 24 ;parse the header, stop if unsuccessful because the server cannot know what to do next 25 I '$$PARSEHDR^HLOPRS(.SEG) D Q 0 26 .S HLCSTATE("MESSAGE ENDED")=0 27 .D CLOSE^HLOT(.HLCSTATE) 28 D NEWMSG^HLOSRVR2(.HLCSTATE,.HLMSTATE,.SEG) 29 I HLMSTATE("ID")="" D 30 .S STORE=0 31 .I HLMSTATE("HDR","ACCEPT ACK TYPE")="AL" S HLMSTATE("MSA",1)="CE",HLMSTATE("MSA",3)="CONTROL ID MISSING" 32 I STORE,$$DUP(.HLMSTATE) S STORE=0 33 ; 34 ;if the message is not to be stored, just read it and discard the segments 35 I 'STORE D 36 .F Q:'$$READSEG^HLOT(.HLCSTATE,.SEG) 37 ; 38 E D 39 .N FS 40 .S FS=HLMSTATE("HDR","FIELD SEPARATOR") 41 .F Q:'$$READSEG^HLOT(.HLCSTATE,.SEG) D 42 ..N MSA,SEGTYPE,OLDMSGID,CODE,IEN,NEWMSGID,TEXT 43 ..S SEGTYPE=$E($E(SEG(1),1,3)_$E($G(SEG(2)),1,2),1,3) 44 ..I SEGTYPE="MSA" D 45 ...S MSA=SEG(1)_$G(SEG(2))_$G(SEG(3)) 46 ...S OLDMSGID=$P(MSA,FS,3),CODE=$P(MSA,FS,2),TEXT=$E($P(MSA,FS,4),1,30) 47 ...I $E(CODE,1)'="A" S SEGTYPE="" Q 48 ...S:$P(OLDMSGID,"-")]"" IEN=$O(^HLB("B",$P(OLDMSGID,"-"),0)) 49 ...S:$G(IEN) IEN=IEN_"^"_$P(OLDMSGID,"-",2) 50 ..I 'HLMSTATE("BATCH") D 51 ...D:SEGTYPE="MSA" 52 ....S HLMSTATE("ACK TO")=OLDMSGID 53 ....S HLMSTATE("ACK TO","ACK BY")=HLMSTATE("ID") 54 ....S HLMSTATE("ACK TO","STATUS")=$S(CODE="AA":"SU",1:"ER") 55 ....I $G(IEN) D 56 .....S HLMSTATE("ACK TO","IEN")=IEN 57 .....S HLMSTATE("ACK TO","SEQUENCE QUEUE")=$P($G(^HLB(+IEN,5)),"^") 58 ....S HLMSTATE("ACK TO","ERROR TEXT")=TEXT 59 ...D ADDSEG^HLOMSG(.HLMSTATE,.SEG) 60 ..E D ;batch 61 ...I SEGTYPE="MSH" D 62 ....D SPLITHDR(.SEG) 63 ....S NEWMSGID=$P(SEG(2),FS,5) 64 ....D ADDMSG2^HLOMSG(.HLMSTATE,.SEG) 65 ...E D ;not MSH 66 ....D:SEGTYPE="MSA" 67 .....N SUBIEN S SUBIEN=HLMSTATE("BATCH","CURRENT MESSAGE") 68 .....S HLMSTATE("BATCH","ACK TO",SUBIEN)=OLDMSGID 69 .....S HLMSTATE("BATCH","ACK TO",SUBIEN,"ACK BY")=NEWMSGID 70 .....S HLMSTATE("BATCH","ACK TO",SUBIEN,"STATUS")=$S(CODE="AA":"SU",1:"ER") 71 .....S:$D(IEN) HLMSTATE("BATCH","ACK TO",SUBIEN,"IEN")=IEN 72 ....D ADDSEG^HLOMSG(.HLMSTATE,.SEG) 73 .I HLMSTATE("UNSTORED LINES"),HLCSTATE("MESSAGE ENDED"),$$SAVEMSG^HLOF778(.HLMSTATE) 74 ; 75 I STORE,'HLCSTATE("MESSAGE ENDED") D 76 .;reading failed, don't store 77 .D:HLMSTATE("IEN") DEL778(HLMSTATE("IEN")) D:HLMSTATE("BODY") DEL777(HLMSTATE("BODY")) 78 .S HLMSTATE("IEN")="",HLMSTATE("BODY")="" 79 E D:STORE 80 .D CHECKMSG(.HLMSTATE) 81 .D ADDAC(.HLMSTATE) ;so future duplicates are detected 82 .D COUNT^HLOSTAT(.HLCSTATE,HLMSTATE("HDR","RECEIVING APPLICATION"),HLMSTATE("HDR","SENDING APPLICATION"),$S(HLMSTATE("BATCH"):"BATCH",1:HLMSTATE("HDR","MESSAGE TYPE")_"~"_HLMSTATE("HDR","EVENT"))) 83 ; 84 D:'HLCSTATE("MESSAGE ENDED") CLOSE^HLOT(.HLCSTATE) 85 Q HLCSTATE("MESSAGE ENDED") 86 ; 87 ADDAC(HLMSTATE) ;adds the AC xref for duplicates detection 88 ; 89 N FROM 90 S FROM=$S(HLMSTATE("HDR","SENDING FACILITY",2)]"":HLMSTATE("HDR","SENDING FACILITY",2),1:HLMSTATE("HDR","SENDING FACILITY",1)) 91 S ^HLB("AC",FROM_HLMSTATE("HDR","SENDING APPLICATION")_HLMSTATE("ID"),HLMSTATE("IEN"))="" 92 Q 93 ; 94 DUP(HLMSTATE) ; 95 ;Returns 1 if the message is a duplicate and its ack (if requested) is found, 0 otherwise 96 ;Input: 97 ; HLMSTATE (pass by reference) the message being read 98 ;Output: 99 ; Function returns 1 if the message is a duplicate, 0 otherwise 100 ; HLMSTATE (pass by reference) IF the message is a duplicate: 101 ; returns the prior MSA segment in HLMSTATE("MSA") 102 ; 103 N IEN,FROM,DUP 104 S (IEN,DUP)=0 105 ; 106 ;no way to determine! Bad header will be rejected 107 Q:(HLMSTATE("ID")="") 0 108 ; 109 S FROM=$S(HLMSTATE("HDR","SENDING FACILITY",2)]"":HLMSTATE("HDR","SENDING FACILITY",2),1:HLMSTATE("HDR","SENDING FACILITY",1)) 110 F S IEN=$O(^HLB("AC",FROM_HLMSTATE("HDR","SENDING APPLICATION")_HLMSTATE("ID"),IEN)) Q:'IEN D Q:DUP 111 .I HLMSTATE("HDR","ACCEPT ACK TYPE")="NE" S DUP=1 Q 112 .;need the MSA to return 113 .D Q 114 ..N NODE 115 ..S NODE=$P($G(^HLB(IEN,4)),"^",3,10) 116 ..S HLMSTATE("MSA",1)=$P(NODE,"|",2) 117 ..Q:$L(HLMSTATE("MSA",1))'=2 118 ..S HLMSTATE("MSA",2)=$P(NODE,"|",3) 119 ..S HLMSTATE("MSA",3)=$P(NODE,"|",4,10) 120 ..S DUP=1 121 ; 122 Q DUP 123 ; 124 CHECKMSG(HLMSTATE) ; 125 ;Checks the header & MSA segment, sets HLMSTATE("STATUS","ACTION") if the message needs to be passed, determines if completion status should be set 126 ;Input: 127 ; HLMSTATE("HDR") - the parsed header segment 128 ;Output: 129 ; HLMSTATE("STATUS")="ER" if an error is detected 130 ; HLMSTATE("STATUS","QUEUE") queue to put the message on 131 ; HLMSTATE("STATUS","ACTION") <tag^rtn> that is the processing routine for the receiving application 132 ; HLMSTATE("MSA") - MSA(1)=accept code to be returned, MSA(3)= error txt 133 ; 134 N WANTACK,PASS,ACTION,QUEUE,ERROR 135 M HDR=HLMSTATE("HDR") 136 S ERROR=0 137 I HDR("ACCEPT ACK TYPE")="NE",'HLMSTATE("ORIGINAL MODE") D 138 .S WANTACK=0 139 E D 140 .S WANTACK=1 141 I HLMSTATE("ORIGINAL MODE") S HLMSTATE("MSA",1)="AE",HLMSTATE("MSA",3)="THIS INTERFACE DOES NOT IMPLEMENT ORIGINAL MODE APPLICATION ACKOWLEDGMENTS",HLMSTATE("STATUS")="ER" Q 142 I $G(HLMSTATE("ACK TO"))="" D Q:ERROR 143 .I '$$ACTION^HLOAPP(.HDR,.ACTION,.QUEUE) S ERROR=1 S:WANTACK HLMSTATE("MSA",1)="CR" S HLMSTATE("MSA",3)="RECEIVING APPLICATION NOT DEFINED",HLMSTATE("STATUS")="ER" Q 144 .S HLMSTATE("STATUS","ACTION")=$G(ACTION),HLMSTATE("STATUS","QUEUE")=$G(QUEUE) 145 E D Q:ERROR ;this is an app ack 146 .;does the original message exist? 147 .N NODE 148 .S:+$G(HLMSTATE("ACK TO","IEN")) NODE=$G(^HLB(+HLMSTATE("ACK TO","IEN"),0)) 149 .I $G(NODE)="" S ERROR=1,HLMSTATE("STATUS")="ER",HLMSTATE("ACK TO","IEN")="" S:WANTACK HLMSTATE("MSA",1)="CE" S HLMSTATE("MSA",3)="INITIAL MESSAGE TO APPLICATION ACKNOWLEDGMENT NOT FOUND" Q 150 .I $P(NODE,"^",7)'="",$P(NODE,"^",7)'=HLMSTATE("ID") S ERROR=1,HLMSTATE("STATUS")="ER",HLMSTATE("ACK TO","IEN")="" S:WANTACK HLMSTATE("MSA",1)="CE" S HLMSTATE("MSA",3)="INITIAL MESSAGE WAS ALREADY ACKED" Q 151 .I ($P(NODE,"^",11)]"") S HLMSTATE("STATUS","ACTION")=$P(NODE,"^",10,11),HLMSTATE("STATUS","QUEUE")=$S($P(NODE,"^",6)]"":$P(NODE,"^",6),1:"DEFAULT") Q 152 .;processing routine for the app ack wasn't found with the original message, look in the HLO Application Registry 153 .I HLMSTATE("HDR","MESSAGE TYPE")="ACK",HLMSTATE("HDR","EVENT")="" S HDR("EVENT")=$$GETEVENT^HLOCLNT2(+HLMSTATE("ACK TO","IEN")) 154 .I $$ACTION^HLOAPP(.HDR,.ACTION,.QUEUE) S HLMSTATE("STATUS","ACTION")=$G(ACTION),HLMSTATE("STATUS","QUEUE")=$G(QUEUE) 155 ; 156 I HDR("PROCESSING ID")'=HLCSTATE("SYSTEM","PROCESSING ID") S:WANTACK HLMSTATE("MSA",1)="CR" S HLMSTATE("STATUS")="ER",HLMSTATE("MSA",3)="SYSTEM PROCESSING ID="_HLCSTATE("SYSTEM","PROCESSING ID") Q 157 ; 158 ;wrong receiving facility? This is hard to check if the sender is not VistA, because the HL7 standard permits different coding systems to be used. This check is only for DNS or station number. 159 S PASS=0 160 D 161 .;if its an ack to an existing message, don't check the receiving facility 162 .I $G(HLMSTATE("ACK TO"))]"" S PASS=1 Q 163 .I HDR("RECEIVING FACILITY",1)=HLCSTATE("SYSTEM","STATION") S PASS=1 Q 164 .I HDR("RECEIVING FACILITY",3)'="DNS" S PASS=1 Q 165 .I HDR("RECEIVING FACILITY",2)="" S PASS=1 Q 166 .I $P(HDR("RECEIVING FACILITY",2),":")[HLCSTATE("SYSTEM","DOMAIN") S PASS=1 Q 167 .I HLCSTATE("SYSTEM","DOMAIN")[$P(HDR("RECEIVING FACILITY",2),":") S PASS=1 Q 168 I 'PASS S HLMSTATE("STATUS")="ER",HLMSTATE("MSA",3)="RECEIVING FACILITY IS "_HLCSTATE("SYSTEM","DOMAIN") S:WANTACK HLMSTATE("MSA",1)="CE" 169 I PASS,WANTACK S HLMSTATE("MSA",1)="CA" 170 Q 171 ; 172 DEL777(IEN777) ;delete a record from file 777 where the read did not complete 173 ; 174 K ^HLA(IEN777,0) 175 Q 176 DEL778(IEN778) ;delete a record from file 778 where the read did not complete 177 ; 178 K ^HLB(IEN778,0) 179 Q 180 ; 181 SPLITHDR(HDR) ; 182 ;splits hdr segment into two lines, first being just components 1-6 183 ; 184 N TEMP,FS 185 D SQUISH(.HDR) 186 S FS=$E($G(HDR(1)),4) 187 S TEMP(1)=$P($G(HDR(1)),FS,1,6) 188 S TEMP(2)="" 189 I $L(TEMP(1))<$L($G(HDR(1))) S TEMP(2)=FS_$P($G(HDR(1)),FS,7,20) 190 S HDR(2)=TEMP(2)_$G(HDR(2)) 191 S HDR(1)=TEMP(1) 192 Q 193 ; 194 SQUISH(SEG) ; 195 ;reformat the segment array into full lines 196 ; 197 ;nothing to do if less than 2 lines 198 Q:'$O(SEG(1)) 199 ; 200 N A,I,J,K,MAX,COUNT,LEN 201 S MAX=$S($G(HLCSTATE("SYSTEM","MAXSTRING"))>256:HLCSTATE("SYSTEM","MAXSTRING"),1:256) 202 S (COUNT,I)=0,J=1 203 F S I=$O(SEG(I)) Q:'I D 204 .S LEN=$L(SEG(I)) 205 .F K=1:1:LEN D 206 ..S A(J)=$G(A(J))_$E(SEG(I),K) 207 ..S COUNT=COUNT+1 208 ..I (COUNT>(MAX-1)) S COUNT=0,J=J+1 209 K SEG 210 M SEG=A 211 Q 212 ; 213 ERROR ;error trap 214 S $ETRAP="Q:$QUIT """" Q" 215 D END^HLOSRVR 216 ; 217 ;multi-listener should stop execution, only a single server may continue 218 I $P($G(HLCSTATE("LINK","SERVER")),"^",2)'="S" D Q:$QUIT "" Q 219 .;don't log these errors 220 .I ($ECODE["READ")!($ECODE["NOTOPEN")!($ECODE["DEVNOTOPN")!($ECODE["WRITE")!($ECODE["OPENERR") D 221 ..; 222 .E D 223 ..D ^%ZTER 224 ; 225 ;debugging? 226 I $G(^HLTMP("LOG ALL ERRORS"))!($ECODE["EDITED") Q:$QUIT "" Q 227 ; 228 ;possibly an endless loop? 229 N HOUR 230 S HOUR=$E($$NOW^XLFDT,1,10) 231 I ($G(^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2)))>30) Q:$QUIT "" Q 232 ; 233 ;resume execution for the single listener 234 S ^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2))=$G(^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2)))+1 235 D UNWIND^%ZTER 236 Q 1 HLOSRVR1 ;IRMFO-ALB/CJM - Reading messages, sending acks;03/24/2004 14:43 ;03/26/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,130,131,133,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 READMSG(HLCSTATE,HLMSTATE) ; 6 ;Reads a message. The header is parsed. Does these checks: 7 ; 1) Duplicate? 8 ; 2) Wrong Receiving Facility? 9 ; 3) Can the Receiving App accept this message, based message type & event? 10 ; 4) Processing ID must match the receiving system 11 ; 5) Must have an ID 12 ; 6) Header must be BHS or MSH 13 ; 14 ;Output: 15 ; Function returns 1 if the message was read fully, 0 otherwise 16 ; HLMSTATE (pass by reference) the message. It will include the fields for the return ack in HLMSTATE("MSA") 17 ; 18 N ACK,SEG,STORE,I 19 ; 20 S STORE=1 21 Q:'$$READHDR^HLOT(.HLCSTATE,.SEG) 0 22 D SPLITHDR(.SEG) 23 ; 24 ;parse the header, stop if unsuccessful because the server cannot know what to do next 25 I '$$PARSEHDR^HLOPRS(.SEG) D Q 0 26 .S HLCSTATE("MESSAGE ENDED")=0 27 .D CLOSE^HLOT(.HLCSTATE) 28 D NEWMSG^HLOSRVR2(.HLCSTATE,.HLMSTATE,.SEG) 29 I HLMSTATE("ID")="" D 30 .S STORE=0 31 .I HLMSTATE("HDR","ACCEPT ACK TYPE")="AL" S HLMSTATE("MSA",1)="CE",HLMSTATE("MSA",3)="CONTROL ID MISSING" 32 I STORE,$$DUP(.HLMSTATE) S STORE=0 33 ; 34 ;if the message is not to be stored, just read it and discard the segments 35 I 'STORE D 36 .F Q:'$$READSEG^HLOT(.HLCSTATE,.SEG) 37 ; 38 E D 39 .N FS 40 .S FS=HLMSTATE("HDR","FIELD SEPARATOR") 41 .F Q:'$$READSEG^HLOT(.HLCSTATE,.SEG) D 42 ..N MSA,SEGTYPE,OLDMSGID,CODE,IEN,NEWMSGID,TEXT 43 ..S SEGTYPE=$E($E(SEG(1),1,3)_$E($G(SEG(2)),1,2),1,3) 44 ..I SEGTYPE="MSA" D 45 ...S MSA=SEG(1)_$G(SEG(2))_$G(SEG(3)) 46 ...S OLDMSGID=$P(MSA,FS,3),CODE=$P(MSA,FS,2),TEXT=$E($P(MSA,FS,4),1,30) 47 ...I $E(CODE,1)'="A" S SEGTYPE="" Q 48 ...S:$P(OLDMSGID,"-")]"" IEN=$O(^HLB("B",$P(OLDMSGID,"-"),0)) 49 ...S:$G(IEN) IEN=IEN_"^"_$P(OLDMSGID,"-",2) 50 ..I 'HLMSTATE("BATCH") D 51 ...D:SEGTYPE="MSA" 52 ....S HLMSTATE("ACK TO")=OLDMSGID 53 ....S HLMSTATE("ACK TO","ACK BY")=HLMSTATE("ID") 54 ....S HLMSTATE("ACK TO","STATUS")=$S(CODE="AA":"SU",1:"AE") 55 ....S:$D(IEN) HLMSTATE("ACK TO","IEN")=IEN 56 ....S HLMSTATE("ACK TO","ERROR TEXT")=TEXT 57 ...D ADDSEG^HLOMSG(.HLMSTATE,.SEG) 58 ..E D ;batch 59 ...I SEGTYPE="MSH" D 60 ....D SPLITHDR(.SEG) 61 ....S NEWMSGID=$P(SEG(2),FS,5) 62 ....D ADDMSG2^HLOMSG(.HLMSTATE,.SEG) 63 ...E D ;not MSH 64 ....D:SEGTYPE="MSA" 65 .....N SUBIEN S SUBIEN=HLMSTATE("BATCH","CURRENT MESSAGE") 66 .....S HLMSTATE("BATCH","ACK TO",SUBIEN)=OLDMSGID 67 .....S HLMSTATE("BATCH","ACK TO",SUBIEN,"ACK BY")=NEWMSGID 68 .....S HLMSTATE("BATCH","ACK TO",SUBIEN,"STATUS")=$S(CODE="AA":"SU",1:"AE") 69 .....S:$D(IEN) HLMSTATE("BATCH","ACK TO",SUBIEN,"IEN")=IEN 70 ....D ADDSEG^HLOMSG(.HLMSTATE,.SEG) 71 .I HLMSTATE("UNSTORED LINES"),HLCSTATE("MESSAGE ENDED"),$$SAVEMSG^HLOF778(.HLMSTATE) 72 ; 73 I STORE,'HLCSTATE("MESSAGE ENDED") D 74 .;reading failed, don't store 75 .D:HLMSTATE("IEN") DEL778(HLMSTATE("IEN")) D:HLMSTATE("BODY") DEL777(HLMSTATE("BODY")) 76 .S HLMSTATE("IEN")="",HLMSTATE("BODY")="" 77 E D:STORE 78 .D CHECKMSG(.HLMSTATE) 79 .D ADDAC(.HLMSTATE) ;so future duplicates are detected 80 .D COUNT^HLOSTAT(.HLCSTATE,HLMSTATE("HDR","RECEIVING APPLICATION"),HLMSTATE("HDR","SENDING APPLICATION"),$S(HLMSTATE("BATCH"):"BATCH",1:HLMSTATE("HDR","MESSAGE TYPE")_"~"_HLMSTATE("HDR","EVENT"))) 81 ; 82 D:'HLCSTATE("MESSAGE ENDED") CLOSE^HLOT(.HLCSTATE) 83 Q HLCSTATE("MESSAGE ENDED") 84 ; 85 ADDAC(HLMSTATE) ;adds the AC xref for duplicates detection 86 ; 87 N FROM 88 S FROM=$S(HLMSTATE("HDR","SENDING FACILITY",2)]"":HLMSTATE("HDR","SENDING FACILITY",2),1:HLMSTATE("HDR","SENDING FACILITY",1)) 89 S ^HLB("AC",FROM_HLMSTATE("HDR","SENDING APPLICATION")_HLMSTATE("ID"),HLMSTATE("IEN"))="" 90 Q 91 ; 92 DUP(HLMSTATE) ; 93 ;Returns 1 if the message is a duplicate and its ack (if requested) is found, 0 otherwise 94 ;Input: 95 ; HLMSTATE (pass by reference) the message being read 96 ;Output: 97 ; Function returns 1 if the message is a duplicate, 0 otherwise 98 ; HLMSTATE (pass by reference) IF the message is a duplicate: 99 ; returns the prior MSA segment in HLMSTATE("MSA") 100 ; 101 N IEN,FROM,DUP 102 S (IEN,DUP)=0 103 ; 104 ;no way to determine! Bad header will be rejected 105 Q:(HLMSTATE("ID")="") 0 106 ; 107 S FROM=$S(HLMSTATE("HDR","SENDING FACILITY",2)]"":HLMSTATE("HDR","SENDING FACILITY",2),1:HLMSTATE("HDR","SENDING FACILITY",1)) 108 F S IEN=$O(^HLB("AC",FROM_HLMSTATE("HDR","SENDING APPLICATION")_HLMSTATE("ID"),IEN)) Q:'IEN D Q:DUP 109 .I HLMSTATE("HDR","ACCEPT ACK TYPE")="NE" S DUP=1 Q 110 .;need the MSA to return 111 .D Q 112 ..N NODE 113 ..S NODE=$P($G(^HLB(IEN,4)),"^",3,10) 114 ..S HLMSTATE("MSA",1)=$P(NODE,"|",2) 115 ..Q:$L(HLMSTATE("MSA",1))'=2 116 ..S HLMSTATE("MSA",2)=$P(NODE,"|",3) 117 ..S HLMSTATE("MSA",3)=$P(NODE,"|",4,10) 118 ..S DUP=1 119 ; 120 Q DUP 121 ; 122 CHECKMSG(HLMSTATE) ; 123 ;Checks the header & MSA segment, sets HLMSTATE("STATUS","ACTION") if the message needs to be passed, determines if completion status should be set 124 ;Input: 125 ; HLMSTATE("HDR") - the parsed header segment 126 ;Output: 127 ; HLMSTATE("STATUS")="SE" if an error is detected 128 ; HLMSTATE("STATUS","QUEUE") queue to put the message on 129 ; HLMSTATE("STATUS","ACTION") <tag^rtn> that is the processing routine for the receiving application 130 ; HLMSTATE("MSA") - MSA(1)=accept code to be returned, MSA(3)= error txt 131 ; 132 N WANTACK,PASS,ACTION,QUEUE,ERROR 133 M HDR=HLMSTATE("HDR") 134 S ERROR=0 135 I HDR("ACCEPT ACK TYPE")="NE",'HLMSTATE("ORIGINAL MODE") D 136 .S WANTACK=0 137 E D 138 .S WANTACK=1 139 I HLMSTATE("ORIGINAL MODE") S HLMSTATE("MSA",1)="AE",HLMSTATE("MSA",3)="THIS INTERFACE DOES NOT IMPLEMENT ORIGINAL MODE APPLICATION ACKOWLEDGMENTS",HLMSTATE("STATUS")="SE" Q 140 I $G(HLMSTATE("ACK TO"))="" D Q:ERROR 141 .I '$$ACTION^HLOAPP(.HDR,.ACTION,.QUEUE) S ERROR=1 S:WANTACK HLMSTATE("MSA",1)="CR" S HLMSTATE("MSA",3)="RECEIVING APPLICATION NOT DEFINED",HLMSTATE("STATUS")="SE" Q 142 .S HLMSTATE("STATUS","ACTION")=$G(ACTION),HLMSTATE("STATUS","QUEUE")=$G(QUEUE) 143 E D Q:ERROR ;this is an app ack 144 .;does the original message exist? 145 .N NODE 146 .S:+$G(HLMSTATE("ACK TO","IEN")) NODE=$G(^HLB(+HLMSTATE("ACK TO","IEN"),0)) 147 .I $G(NODE)="" S ERROR=1,HLMSTATE("STATUS")="SE",HLMSTATE("ACK TO","IEN")="" S:WANTACK HLMSTATE("MSA",1)="CE" S HLMSTATE("MSA",3)="INITIAL MESSAGE TO APPLICATION ACKNOWLEDGMENT NOT FOUND" Q 148 .I $P(NODE,"^",7)'="",$P(NODE,"^",7)'=HLMSTATE("ID") S ERROR=1,HLMSTATE("STATUS")="SE",HLMSTATE("ACK TO","IEN")="" S:WANTACK HLMSTATE("MSA",1)="CE" S HLMSTATE("MSA",3)="INITIAL MESSAGE WAS ALREADY ACKED" Q 149 .I ($P(NODE,"^",11)]"") S HLMSTATE("STATUS","ACTION")=$P(NODE,"^",10,11),HLMSTATE("STATUS","QUEUE")=$S($P(NODE,"^",6)]"":$P(NODE,"^",6),1:"DEFAULT") Q 150 .;processing routine for the app ack wasn't found with the original message, look in the HLO Application Registry 151 .I HLMSTATE("HDR","MESSAGE TYPE")="ACK",HLMSTATE("HDR","EVENT")="" S HDR("EVENT")=$$GETEVENT^HLOCLNT2(+HLMSTATE("ACK TO","IEN")) 152 .I $$ACTION^HLOAPP(.HDR,.ACTION,.QUEUE) S HLMSTATE("STATUS","ACTION")=$G(ACTION),HLMSTATE("STATUS","QUEUE")=$G(QUEUE) 153 ; 154 I HDR("PROCESSING ID")'=HLCSTATE("SYSTEM","PROCESSING ID") S:WANTACK HLMSTATE("MSA",1)="CR" S HLMSTATE("STATUS")="SE",HLMSTATE("MSA",3)="SYSTEM PROCESSING ID="_HLCSTATE("SYSTEM","PROCESSING ID") Q 155 ; 156 ;wrong receiving facility? This is hard to check if the sender is not VistA, because the HL7 standard permits different coding systems to be used. This check is only for DNS or station number. 157 S PASS=0 158 D 159 .;if its an ack to an existing message, don't check the receiving facility 160 .I $G(HLMSTATE("ACK TO"))]"" S PASS=1 Q 161 .I HDR("RECEIVING FACILITY",1)=HLCSTATE("SYSTEM","STATION") S PASS=1 Q 162 .I HDR("RECEIVING FACILITY",3)'="DNS" S PASS=1 Q 163 .I HDR("RECEIVING FACILITY",2)="" S PASS=1 Q 164 .I $P(HDR("RECEIVING FACILITY",2),":")[HLCSTATE("SYSTEM","DOMAIN") S PASS=1 Q 165 .I HLCSTATE("SYSTEM","DOMAIN")[$P(HDR("RECEIVING FACILITY",2),":") S PASS=1 Q 166 I 'PASS S HLMSTATE("STATUS")="SE",HLMSTATE("MSA",3)="RECEIVING FACILITY IS "_HLCSTATE("SYSTEM","DOMAIN") S:WANTACK HLMSTATE("MSA",1)="CE" 167 I PASS,WANTACK S HLMSTATE("MSA",1)="CA" 168 Q 169 ; 170 DEL777(IEN777) ;delete a record from file 777 where the read did not complete 171 ; 172 K ^HLA(IEN777,0) 173 Q 174 DEL778(IEN778) ;delete a record from file 778 where the read did not complete 175 ; 176 K ^HLB(IEN778,0) 177 Q 178 ; 179 SPLITHDR(HDR) ; 180 ;splits hdr segment into two lines, first being just components 1-6 181 ; 182 N TEMP,FS 183 D SQUISH(.HDR) 184 S FS=$E($G(HDR(1)),4) 185 S TEMP(1)=$P($G(HDR(1)),FS,1,6) 186 S TEMP(2)="" 187 I $L(TEMP(1))<$L($G(HDR(1))) S TEMP(2)=FS_$P($G(HDR(1)),FS,7,20) 188 S HDR(2)=TEMP(2)_$G(HDR(2)) 189 S HDR(1)=TEMP(1) 190 Q 191 ; 192 SQUISH(SEG) ; 193 ;reformat the segment array into full lines 194 ; 195 ;nothing to do if less than 2 lines 196 Q:'$O(SEG(1)) 197 ; 198 N A,I,J,K,MAX,COUNT,LEN 199 S MAX=$S($G(HLCSTATE("SYSTEM","MAXSTRING"))>256:HLCSTATE("SYSTEM","MAXSTRING"),1:256) 200 S (COUNT,I)=0,J=1 201 F S I=$O(SEG(I)) Q:'I D 202 .S LEN=$L(SEG(I)) 203 .F K=1:1:LEN D 204 ..S A(J)=$G(A(J))_$E(SEG(I),K) 205 ..S COUNT=COUNT+1 206 ..I (COUNT>(MAX-1)) S COUNT=0,J=J+1 207 K SEG 208 M SEG=A 209 Q 210 ; 211 ERROR ;error trap 212 S $ETRAP="Q:$QUIT """" Q" 213 D END^HLOSRVR 214 ; 215 ;concurrent server connections (multi-listener) should stop execution, only a single server may continue 216 I $P($G(HLCSTATE("LINK","SERVER")),"^",2)'="S" D Q:$QUIT "" Q 217 .;don't log these common errors 218 .I ($ECODE["READ")!($ECODE["NOTOPEN")!($ECODE["DEVNOTOPN")!($ECODE["WRITE")!($ECODE["OPENERR") D 219 ..; 220 .E D 221 ..D ^%ZTER 222 ; 223 ;while debugging quit on all errors 224 I $G(^HLTMP("LOG ALL ERRORS"))!($ECODE["EDITED") Q:$QUIT "" Q 225 ; 226 ;a lot of errors of the same time may indicate an endless loop, so keep a count and quit if large count 227 N HOUR 228 S HOUR=$E($$NOW^XLFDT,1,10) 229 ; 230 I ($G(^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2)))>30) Q:$QUIT "" Q 231 ; 232 ;resume execution for the single listener 233 S ^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2))=$G(^TMP("HL7 ERRORS",$J,HOUR,$P($ECODE,",",2)))+1 234 D UNWIND^%ZTER 235 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOSRVR2.m
r613 r623 1 HLOSRVR2 ;ALB/CJM-HL7 - HLO Server ;07/20/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**131,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 NEWMSG(HLCSTATE,HLMSTATE,HDR) ; 6 ;initialize the HLMSTATE array after reading the header 7 ;Inputs: 8 ; HLCSTATE (pass by reference) 9 ; HDR (pass by reference) parsed header 10 ;Output: 11 ; HLMSTATE (pass by reference) 12 ; 13 K HLMSTATE 14 S HLMSTATE("IEN")="" 15 S HLMSTATE("BODY")="" 16 S HLMSTATE("DIRECTION")="IN" 17 S HLMSTATE("CURRENT SEGMENT")=0 ;no segments in cache 18 S HLMSTATE("UNSTORED LINES")=1 ;just the header in cache so far 19 S HLMSTATE("LINE COUNT")=0 ;no lines within message stored to disk 20 I HDR("SEGMENT TYPE")="BHS" D 21 .S HLMSTATE("BATCH")=1 22 .S HLMSTATE("ID")=HDR("BATCH CONTROL ID") 23 .S HLMSTATE("BATCH","CURRENT MESSAGE")=0 ;no messages in batch 24 .S HLMSTATE("UNSTORED MSH")=0 25 E D 26 .S HLMSTATE("BATCH")=0 27 .S HLMSTATE("ID")=HDR("MESSAGE CONTROL ID") 28 M HLMSTATE("HDR")=HDR 29 M HLMSTATE("SYSTEM")=HLCSTATE("SYSTEM") 30 S HLMSTATE("STATUS")="" 31 S HLMSTATE("STATUS","QUEUE")="" 32 S HLMSTATE("STATUS","ACTION")="" 33 S HLMSTATE("STATUS","LINK NAME")=HLCSTATE("LINK","NAME") 34 S HLMSTATE("STATUS","PORT")=$P(HDR("SENDING FACILITY",2),":",2) 35 ; 36 ;if this is a batch, and it references another batch, assume it is a b. 37 I HLMSTATE("BATCH"),HLMSTATE("ID")]"" D 38 .N IEN 39 .S HLMSTATE("ACK TO")=HLMSTATE("ID") 40 .S HLMSTATE("ACK TO","STATUS")="SU" 41 .S IEN=$O(^HLB("B",HLMSTATE("ID"),0)) 42 .I IEN S HLMSTATE("ACK TO","IEN")=IEN_"^" 43 E S HLMSTATE("ACK TO")="" 44 I 'HLMSTATE("BATCH"),HDR("ACCEPT ACK TYPE")="",HDR("APP ACK TYPE")="" D 45 .S HLMSTATE("ORIGINAL MODE")=1 46 E D 47 .S HLMSTATE("ORIGINAL MODE")=0 48 N I F I=1,3 S HLMSTATE("MSA",I)="" 49 S HLMSTATE("MSA",2)=HLMSTATE("ID") 50 Q 1 HLOSRVR2 ;ALB/CJM-HL7 - Sends an application ack over an open connection, for original mode ;02/04/2004 2 ;;1.6;HEALTH LEVEL SEVEN;**131**;Oct 13, 1995;Build 10 3 ; 4 NEWMSG(HLCSTATE,HLMSTATE,HDR) ; 5 ;initialize the HLMSTATE array after reading the header 6 ;Inputs: 7 ; HLCSTATE (pass by reference) 8 ; HDR (pass by reference) parsed header 9 ;Output: 10 ; HLMSTATE (pass by reference) 11 ; 12 K HLMSTATE 13 S HLMSTATE("IEN")="" 14 S HLMSTATE("BODY")="" 15 S HLMSTATE("DIRECTION")="IN" 16 S HLMSTATE("CURRENT SEGMENT")=0 ;no segments in cache 17 S HLMSTATE("UNSTORED LINES")=1 ;just the header in cache so far 18 S HLMSTATE("LINE COUNT")=0 ;no lines within message stored to disk 19 I HDR("SEGMENT TYPE")="BHS" D 20 .S HLMSTATE("BATCH")=1 21 .S HLMSTATE("ID")=HDR("BATCH CONTROL ID") 22 .S HLMSTATE("BATCH","CURRENT MESSAGE")=0 ;no messages in batch 23 .S HLMSTATE("UNSTORED MSH")=0 24 E D 25 .S HLMSTATE("BATCH")=0 26 .S HLMSTATE("ID")=HDR("MESSAGE CONTROL ID") 27 M HLMSTATE("HDR")=HDR 28 M HLMSTATE("SYSTEM")=HLCSTATE("SYSTEM") 29 S HLMSTATE("STATUS")="" 30 S HLMSTATE("STATUS","QUEUE")="" 31 S HLMSTATE("STATUS","ACTION")="" 32 S HLMSTATE("STATUS","LINK NAME")=HLCSTATE("LINK","NAME") 33 S HLMSTATE("STATUS","PORT")=$P(HDR("SENDING FACILITY",2),":",2) 34 ; 35 ;if this is a batch, and it references another batch, assume it is a b. 36 I HLMSTATE("BATCH"),HLMSTATE("ID")]"" D 37 .N IEN 38 .S HLMSTATE("ACK TO")=HLMSTATE("ID") 39 .S HLMSTATE("ACK TO","STATUS")="SU" 40 .S IEN=$O(^HLB("B",HLMSTATE("ID"),0)) 41 .I IEN S HLMSTATE("ACK TO","IEN")=IEN_"^" 42 E S HLMSTATE("ACK TO")="" 43 I 'HLMSTATE("BATCH"),HDR("ACCEPT ACK TYPE")="",HDR("APP ACK TYPE")="" D 44 .S HLMSTATE("ORIGINAL MODE")=1 45 E D 46 .S HLMSTATE("ORIGINAL MODE")=0 47 N I F I=1,3 S HLMSTATE("MSA",I)="" 48 S HLMSTATE("MSA",2)=HLMSTATE("ID") 49 Q 50 ; 51 ACKNOW(MSG,ERROR) ; 52 ;Sends the messge immediately if there is an open connection, otherwise 53 ;will return an error. 54 ; 55 N $ETRAP,$ESTACK S $ETRAP="G ERROR^HLOSRVR2" 56 N SENT 57 S SENT=0,ERROR="" 58 I '$G(HLCSTATE("CONNECTED")) D 59 .S ERROR="NOT CONNECTED" 60 .S MSG("STATUS")="TF" 61 E S MSG("STATUS")="SU" 62 S:'$G(MSG("DT/TM CREATED")) MSG("DT/TM CREATED")=$$NOW^XLFDT 63 S MSG("STATUS","PURGE")=$$FMADD^XLFDT(MSG("DT/TM CREATED"),$S($G(HLCSTATE("ERROR PURGE")):HLCSTATE("ERROR PURGE"),1:7)) 64 D 65 .I $G(MSG("UNSTORED LINES")),'$$SAVEMSG^HLOF777(.MSG) S ERROR="$$SAVE^HLOF777 FAILED!" Q 66 .I '$$SAVEMSG^HLOF778(.MSG) S ERROR="$$SAVE^HLOF778 FAILED!" Q 67 .Q:MSG("STATUS")'="SU" 68 .I '$$WRITEMSG^HLOCLNT1(.HLCSTATE,.MSG) S ERROR="TRANSMISSION FAILURE" Q 69 .S SENT=1 70 .D COUNT^HLOSTAT(.HLCSTATE,ACK("HDR","RECEIVING APPLICATION"),ACK("HDR","SENDING APPLICATION"),ACK("HDR","MESSAGE TYPE")_"~"_ACK("HDR","EVENT")) 71 ; 72 END ; 73 I 'SENT,MSG("STATUS")="SU",$G(MSG("IEN")) D 74 .Q:'$D(^HLB(MSG("IEN"),0)) 75 .S MSG("STATUS")="TF" 76 .S MSG("STATUS","ERROR TEXT")=ERROR 77 .S $P(^HLB(MSG("IEN"),0),"^",20)=MSG("STATUS") 78 .S $P(^HLB(MSG("IEN"),0),"^",21)=MSG("STATUS","ERROR TEXT") 79 .S ^HLB("ERRORS","TF",$S($L($G(MSG("HDR","RECEIVING APPLICATION"))):MSG("HDR","RECEIVING APPLICATION"),1:"UNKNOWN"),MSG("DT/TM CREATED"),IEN)="" 80 ; 81 Q SENT 82 ; 83 ERROR ;error trap for ACKNOW 84 S SENT=0,ERROR="TRANSMISSION FAILURE:"_$P($ECODE,",",1,2) 85 S $ETRAP="D UNWIND^%ZTER" 86 ; 87 ;don't log some common errors 88 I ($ECODE["READ")!($ECODE["NOTOPEN")!($ECODE["DEVNOTOPN")!($ECODE["WRITE")!($ECODE["OPENERR") D 89 .;nothing! 90 E D 91 .D ^%ZTER 92 G END^HLOSRVR2 93 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOTCP.m
r613 r623 1 HLOTCP ;ALB/CJM- TCP/IP I/O - 10/4/94 1pm ;07/10/20072 ;;1.6;HEALTH LEVEL SEVEN;**126,131,134,137**;Oct 13, 1995;Build 21 3 4 5 OPEN(HLCSTATE,LOGICAL) 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 RETRY 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 DNS(DOMAIN) 92 93 94 WRITEHDR(HLCSTATE,HDR) 95 96 97 98 99 100 101 102 103 104 105 106 107 108 WRITESEG(HLCSTATE,SEG) 109 110 111 112 113 114 115 116 117 118 FLUSH 119 120 121 122 123 124 125 126 127 128 129 130 131 ...W $E(LINE,1,MAX-J),@HLCSTATE("FLUSH") S HLCSTATE("FLUSHED")=1 132 133 134 ..I (LINE]"") W LINE S HLCSTATE("FLUSHED")=0 135 136 137 138 139 140 141 READSEG(HLCSTATE,SEG) 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 READHDR(HLCSTATE,HDR) 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 CLOSE(HLCSTATE) 196 197 198 199 ENDMSG(HLCSTATE) 200 201 202 203 204 205 .I ('$G(HLCSTATE("FLUSHED")))!$X W @HLCSTATE("FLUSH") S HLCSTATE("FLUSHED")=1 206 1 HLOTCP ;ALB/CJM- TCP/IP I/O - 10/4/94 1pm ;03/22/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,131,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 OPEN(HLCSTATE,LOGICAL) ; 6 ;This may be called either in the context of a client or a server. 7 ;For the server, there are 3 situations: 8 ; 1) The server is not concurrent. In this case the TCP device should be opened. 9 ; 2) The server is concurrent, but this process was spawned by the OS 10 ; (via a VMS TCP Service) In this case, the device should be opened 11 ; via the LOGICAL that was passed in. 12 ; 3) The server is concurrent, but this process was spawned by the 13 ; TaskMan multi-listener. In this case TaskMan already opened the 14 ; device. This case can be determined by the absence of the LOGICAL 15 ; input parameter. 16 ; 17 N IP,PORT,DNSFLAG 18 ; 19 S DNSFLAG=0 ;DNS has not been contacted for IP 20 ; 21 S:'$G(HLCSTATE("SERVER")) IP=HLCSTATE("LINK","IP") 22 S PORT=HLCSTATE("LINK","PORT") 23 S HLCSTATE("CONNECTED")=0 24 S HLCSTATE("READ HEADER")="READHDR^HLOTCP" 25 S HLCSTATE("WRITE HEADER")="WRITEHDR^HLOTCP" 26 S HLCSTATE("READ SEGMENT")="READSEG^HLOTCP" 27 S HLCSTATE("WRITE SEGMENT")="WRITESEG^HLOTCP" 28 S HLCSTATE("END MESSAGE")="ENDMSG^HLOTCP" 29 S HLCSTATE("CLOSE")="CLOSE^HLOTCP" 30 ; 31 ;spawned by TaskMan multi-listener? If so, the device has already been opened 32 I $G(HLCSTATE("SERVER")),$G(HLCSTATE("LINK","SERVER"))="1^M",$G(LOGICAL)="" D Q 33 .S HLCSTATE("DEVICE")=IO(0),HLCSTATE("FLUSH")="!",HLCSTATE("TCP BUFFER SIZE")=510 34 .S HLCSTATE("CONNECTED")=1 35 ; 36 ;if no IP, not a server, give DNS a shot 37 I '$G(HLCSTATE("SERVER")),IP="" S DNSFLAG=1,IP=$$DNS(HLCSTATE("LINK","DOMAIN")),HLCSTATE("LINK","IP")=IP Q:IP="" 38 ; 39 RETRY I HLCSTATE("SYSTEM","OS")="DSM" D 40 .S HLCSTATE("TCP BUFFER SIZE")=512 41 .I $G(LOGICAL)]"" S HLCSTATE("DEVICE")=LOGICAL 42 .E S HLCSTATE("DEVICE")=PORT 43 .S HLCSTATE("FLUSH")="!" 44 .I $G(HLCSTATE("SERVER")) D 45 ..O:$G(LOGICAL)]"" HLCSTATE("DEVICE"):(TCPDEV,BLOCKSIZE=512):HLCSTATE("OPEN TIMEOUT") 46 ..O:$G(LOGICAL)="" HLCSTATE("DEVICE"):(TCPCHAN,BLOCKSIZE=512):HLCSTATE("OPEN TIMEOUT") 47 ..I $T D 48 ...S HLCSTATE("CONNECTED")=1 49 ...U HLCSTATE("DEVICE"):NOECHO 50 .E D ;client 51 ..O HLCSTATE("DEVICE"):(TCPCHAN,ADDRESS=IP,BLOCKSIZE=512):HLCSTATE("OPEN TIMEOUT") 52 ..I $T D 53 ...S HLCSTATE("CONNECTED")=1 54 ...U HLCSTATE("DEVICE"):NOECHO 55 E I HLCSTATE("SYSTEM","OS")="CACHE" D 56 .S HLCSTATE("FLUSH")="!" 57 .I $G(LOGICAL)]"" S HLCSTATE("DEVICE")=LOGICAL 58 .E S HLCSTATE("DEVICE")="|TCP|"_PORT 59 .S HLCSTATE("TCP BUFFER SIZE")=510 60 .I $G(HLCSTATE("SERVER")) D 61 ..I HLCSTATE("SERVER")="1^S" D Q 62 ...;single server (no concurrent connections) 63 ...O HLCSTATE("DEVICE"):(:PORT:"+A-S":::):HLCSTATE("OPEN TIMEOUT") 64 ...I $T D 65 ....N A 66 ....S HLCSTATE("CONNECTED")=1 67 ....U HLCSTATE("DEVICE") 68 ....F R *A:HLCSTATE("READ TIMEOUT") Q:$T I $$CHKSTOP^HLOPROC S HLCSTATE("CONNECTED")=0 D CLOSE(.HLCSTATE) Q 69 ..; 70 ..;multi-server spawned by OS - VMS TCP Services 71 ..O HLCSTATE("DEVICE")::HLCSTATE("OPEN TIMEOUT") I '$T S HLCSTATE("CONNECTED")=0 Q 72 ..S HLCSTATE("CONNECTED")=1 73 ..U HLCSTATE("DEVICE"):(::"-S") 74 ..; 75 .E D ;client 76 ..S HLCSTATE("TCP BUFFER SIZE")=510 77 ..O HLCSTATE("DEVICE"):(IP:PORT:"-S":::):HLCSTATE("OPEN TIMEOUT") 78 ..I $T D 79 ...S HLCSTATE("CONNECTED")=1 80 E D ;any other system but Cache or DSM 81 .S HLCSTATE("TCP BUFFER SIZE")=256 82 .D CALL^%ZISTCP(IP,PORT,HLCSTATE("OPEN TIMEOUT")) 83 .S HLCSTATE("CONNECTED")='POP 84 .I HLCSTATE("CONNECTED") S HLCSTATE("DEVICE")=IO 85 ; 86 ;if not connected, not the server, give DNS a shot if not tried already 87 I '$G(HLCSTATE("SERVER")),'HLCSTATE("CONNECTED"),'DNSFLAG S DNSFLAG=1,IP=$$DNS(HLCSTATE("LINK","DOMAIN")) I IP]"",IP'=HLCSTATE("LINK","IP") S HLCSTATE("LINK","IP")=IP G RETRY 88 I HLCSTATE("CONNECTED"),DNSFLAG S $P(^HLCS(870,HLCSTATE("LINK","IEN"),400),"^")=IP 89 Q 90 ; 91 DNS(DOMAIN) ; 92 Q $P($$ADDRESS^XLFNSLK(DOMAIN),",") 93 ; 94 WRITEHDR(HLCSTATE,HDR) ; 95 ; 96 ;insure that package buffer is empty 97 K HLCSTATE("BUFFER") 98 S HLCSTATE("BUFFER","BYTE COUNT")=0 99 S HLCSTATE("BUFFER","SEGMENT COUNT")=0 100 S HLCSTATE("FIRST WRITE")=1 ;so that FLUSH knows $X should be 0 101 ; 102 ;Start the message with <SB>, then write the header 103 N SEG 104 S SEG(1)=$C(11)_HDR(1) 105 S SEG(2)=HDR(2) 106 Q $$WRITESEG(.HLCSTATE,.SEG) 107 ; 108 WRITESEG(HLCSTATE,SEG) ; 109 N I,LAST 110 S HLCSTATE("BUFFER","SEGMENT COUNT")=HLCSTATE("BUFFER","SEGMENT COUNT")+1 111 S I=0,LAST=$O(SEG(99999),-1) 112 F S I=$O(SEG(I)) Q:'I D 113 .I HLCSTATE("BUFFER","BYTE COUNT")>HLCSTATE("SYSTEM","BUFFER") D FLUSH 114 .I I=LAST S SEG(I)=SEG(I)_$C(13) 115 .S HLCSTATE("BUFFER",HLCSTATE("BUFFER","SEGMENT COUNT"),I)=SEG(I),HLCSTATE("BUFFER","BYTE COUNT")=HLCSTATE("BUFFER","BYTE COUNT")+$L(SEG(I))+20 116 Q HLCSTATE("CONNECTED") 117 ; 118 FLUSH ;flushes the HL7 package buffer, and the system TCP buffer when full 119 N SEGMENT,MAX 120 S SEGMENT=0 121 S MAX=HLCSTATE("TCP BUFFER SIZE") 122 U HLCSTATE("DEVICE") I (HLCSTATE("SYSTEM","OS")="CACHE") S HLCSTATE("CONNECTED")=($ZA\8192#2) I 'HLCSTATE("CONNECTED") D CLOSE(.HLCSTATE) 123 F S SEGMENT=$O(HLCSTATE("BUFFER",SEGMENT)) Q:'SEGMENT D 124 .N I S I=0 125 .F S I=$O(HLCSTATE("BUFFER",SEGMENT,I)) Q:'I D 126 ..N LINE,J 127 ..S J=$S(HLCSTATE("FIRST WRITE"):0,1:$X) 128 ..S HLCSTATE("FIRST WRITE")=0 129 ..S LINE=HLCSTATE("BUFFER",SEGMENT,I) 130 ..F Q:'(J+$L(LINE)>MAX) D 131 ...W $E(LINE,1,MAX-J),@HLCSTATE("FLUSH") 132 ...S LINE=$E(LINE,(MAX-J)+1,99999) 133 ...S J=0 134 ..W:(LINE]"") LINE 135 K HLCSTATE("BUFFER") 136 S HLCSTATE("BUFFER","SEGMENT COUNT")=1 137 S HLCSTATE("BUFFER","BYTE COUNT")=0 138 S HLCSTATE("FIRST WRITE")=0 139 Q 140 ; 141 READSEG(HLCSTATE,SEG) ; 142 ; 143 ;Output: 144 ; SEG - returns the segment (pass by reference) 145 ; Function returns 1 on success, 0 on failure 146 ; 147 N SUCCESS,COUNT,BUF 148 S (COUNT,SUCCESS)=0 149 K SEG 150 ; 151 ;anything left from last read? 152 S BUF=HLCSTATE("READ") 153 S HLCSTATE("READ")="" 154 I BUF]"" D ;something was left! 155 .S COUNT=1 156 .I BUF[$C(13) D Q 157 ..S SEG(1)=$P(BUF,$C(13)),BUF=$P(BUF,$C(13),2,9999) 158 ..S SUCCESS=1 159 .S SEG(1)=BUF,BUF="" 160 I 'SUCCESS U HLCSTATE("DEVICE") F R BUF:HLCSTATE("READ TIMEOUT") Q:'$T D Q:SUCCESS 161 .I BUF[$C(13) S SUCCESS=1,COUNT=COUNT+1,SEG(COUNT)=$P(BUF,$C(13)),BUF=$P(BUF,$C(13),2,9999) Q 162 .S COUNT=COUNT+1,SEG(COUNT)=BUF 163 ; 164 I SUCCESS D 165 .S HLCSTATE("READ")=BUF ;save the leftover 166 .I COUNT>1,SEG(COUNT)="" K SEG(COUNT) S COUNT=COUNT-1 167 ;Cache can return the connection status 168 E I (HLCSTATE("SYSTEM","OS")="CACHE") S HLCSTATE("CONNECTED")=($ZA\8192#2) I 'HLCSTATE("CONNECTED") D CLOSE(.HLCSTATE) 169 ; 170 ;if the <EB> character was encountered, then there are no more segments in the message, set the end of message flag 171 I SUCCESS,SEG(COUNT)[$C(28) D 172 .K SEG 173 .S SUCCESS=0 174 .S HLCSTATE("MESSAGE ENDED")=1 175 Q SUCCESS 176 ; 177 READHDR(HLCSTATE,HDR) ; 178 ;reads the next header segment in the message stream, discarding everything that comes before it 179 ; 180 N SEG,SUCCESS,J,I 181 S SUCCESS=0 182 K HDR 183 F Q:'$$READSEG(.HLCSTATE,.SEG) D Q:SUCCESS 184 .S I=0 185 .;look for the <SB> 186 .;perhaps the <SB> isn't in the first line 187 .F S I=$O(SEG(I)) Q:'I D Q:SUCCESS 188 ..I (SEG(I)'[$C(11)) K SEG(I) Q 189 ..S SEG(I)=$P(SEG(I),$C(11),2) 190 ..S SUCCESS=1 191 ..K:SEG(I)="" SEG(I) 192 I SUCCESS S (I,J)=0 F S J=$O(SEG(J)) Q:'J S I=I+1,HDR(I)=SEG(J) 193 Q SUCCESS 194 ; 195 CLOSE(HLCSTATE) ; 196 CLOSE HLCSTATE("DEVICE") 197 Q 198 ; 199 ENDMSG(HLCSTATE) ; 200 N SEG 201 S SEG(1)=$C(28) 202 I $$WRITESEG(.HLCSTATE,.SEG) D Q 1 203 .D FLUSH 204 .U HLCSTATE("DEVICE") 205 .W:$X @HLCSTATE("FLUSH") 206 Q 0 -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOUSR.m
r613 r623 1 HLOUSR ;ALB/CJM -ListManager Screen for viewing system status;12 JUN 1997 10:00 am ;07/30/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,130,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 EN ; 6 ; 7 N HLSCREEN,TESTOPEN,HLRFRSH,HLPARMS 8 D WAIT^DICD 9 D EN^VALM("HLO SYSTEM MONITOR") 10 Q 11 ; 12 BRIEF ; 13 N COUNT,LINK,QUE,FROM,TIME,STATUS,TEMP,DIR,TODAY,LIST 14 S HLRFRSH="BRIEF^HLOUSR" 15 S (HLSCREEN,VALMSG)="Brief System Status" 16 S VALMCNT=16 17 ;K @VALMAR 18 D CLEAN^VALM10 19 S VALMBG=1 20 S VALMBCK="R" 21 S VALMDDF("COL 1")="COL1^1^80^" 22 K VALMDDF("COL 2"),VALMDDF("COL 3"),VALMDDF("COL 4"),VALMDDF("COL 5") 23 D CHGCAP^VALM("COL 1"," Brief Operational Overview") 24 S @VALMAR@(1,0)="SYSTEM STATUS: "_$S($$CHKSTOP^HLOPROC:"STOPPED",1:"RUNNING") 25 S @VALMAR@(2,0)="PROCESS MANAGER: "_$S($$RUNNING:"RUNNING",1:"STOPPED") 26 ; 27 S TIME=$P($G(TESTOPEN("LISTENER")),"^",2) 28 I TIME,$$FMDIFF^XLFDT($$NOW^XLFDT,TIME,2)<300 D 29 .S STATUS=+TESTOPEN("LISTENER") 30 E D 31 .S STATUS=0 32 .S LINK=$P($G(^HLD(779.1,1,0)),"^",10) 33 .I LINK S LINK=$P($G(^HLCS(870,LINK,0)),"^") Q:'$L(LINK) S STATUS=$$IFOPEN^HLOUSR1(LINK) 34 .S TESTOPEN("LISTENER")=STATUS_"^"_$$NOW^XLFDT 35 ; 36 S @VALMAR@(3,0)="STANDARD LISTENER: "_$S(STATUS:"OPERATIONAL",1:"NOT OPERATIONAL") 37 ; 38 S @VALMAR@(4,0)="TASKMAN: "_$S($$TM^%ZTLOAD:"RUNNING",1:"NOT RUNNING") 39 ; 40 S (LIST,LINK)="" 41 F S LINK=$O(^HLTMP("FAILING LINKS",LINK)) Q:LINK="" D I $L(LIST)>60 S LIST=LIST_",..." Q 42 .N TIME,QUE,LINKARY 43 .I $$GETLINK^HLOTLNK($P(LINK,":"),.LINKARY) 44 .S TIME=$G(^HLTMP("FAILING LINKS",LINK)) Q:TIME="" 45 .I '$G(LINKARY("SHUTDOWN")),TIME="" Q 46 .I '$G(LINKARY("SHUTDOWN")),($$HDIFF^XLFDT($H,TIME,2)<300) Q 47 .S LIST=LIST_$S($L(LIST):", ",1:"")_$P(LINK,":") 48 S @VALMAR@(5,0)="DOWN LINKS: "_LIST 49 S @VALMAR@(6,0)="CLIENT LINK PROCESSES: "_+$G(^HLC("HL7 PROCESS COUNTS","RUNNING","OUTGOING CLIENT LINK")) 50 S @VALMAR@(7,0)="IN-FILER PROCESSES: "_+$G(^HLC("HL7 PROCESS COUNTS","RUNNING","INCOMING QUEUES")) 51 S COUNT=0,LINK="" 52 F S LINK=$O(^HLC("QUEUECOUNT","OUT",LINK)) Q:LINK="" D 53 .S QUE="" 54 .F S QUE=$O(^HLC("QUEUECOUNT","OUT",LINK,QUE)) Q:QUE="" D 55 ..S TEMP=$G(^HLC("QUEUECOUNT","OUT",LINK,QUE)) 56 ..S:TEMP>0 COUNT=COUNT+TEMP 57 S @VALMAR@(8,0)="MESSAGES PENDING ON OUT QUEUES: "_$$RJ(+COUNT,7)_" ON SEQUENCE QUEUES: "_$$RJ(+$G(^HLC("QUEUECOUNT","SEQUENCE")),7) 58 S TEMP="STOPPED OUTGOING QUEUES: " 59 S COUNT=0,QUE="" 60 F S QUE=$O(^HLTMP("STOPPED QUEUES","OUT",QUE)) Q:QUE="" S COUNT=COUNT+1 Q:COUNT>4 S:COUNT=1 TEMP=TEMP_QUE S:"23"[COUNT TEMP=TEMP_"; "_QUE S:COUNT=4 TEMP=TEMP_" ..." 61 S @VALMAR@(9,0)=TEMP 62 S COUNT=0,QUE="" 63 F S QUE=$O(^HLC("QUEUECOUNT","IN",QUE)) Q:QUE="" D 64 .S FROM="" 65 .F S FROM=$O(^HLC("QUEUECOUNT","IN",QUE,FROM)) Q:FROM="" D 66 ..S TEMP=$G(^HLC("QUEUECOUNT","IN",QUE,FROM)) 67 ..S:TEMP>0 COUNT=COUNT+TEMP 68 S @VALMAR@(10,0)="MESSAGES PENDING ON APPLICATIONS: "_$$RJ(+COUNT,7) 69 S TEMP="STOPPED INCOMING QUEUES: " 70 S COUNT=0,QUE="" 71 F S QUE=$O(^HLTMP("STOPPED QUEUES","IN",QUE)) Q:QUE="" S COUNT=COUNT+1 Q:COUNT>4 S:COUNT=1 TEMP=TEMP_QUE S:"23"[COUNT TEMP=TEMP_"; "_QUE S:COUNT=4 TEMP=TEMP_" ..." 72 S @VALMAR@(11,0)=TEMP 73 S @VALMAR@(12,0)="FILE 777 RECORD COUNT: "_$$RJ($P($G(^HLTMP("FILE 777 RECORD COUNT")),"^"),10)_" --> as of "_$$FMTE^XLFDT($P($G(^HLTMP("FILE 777 RECORD COUNT")),"^",2)) 74 S @VALMAR@(13,0)="FILE 778 RECORD COUNT: "_$$RJ($P($G(^HLTMP("FILE 778 RECORD COUNT")),"^"),10)_" --> as of "_$$FMTE^XLFDT($P($G(^HLTMP("FILE 778 RECORD COUNT")),"^",2)) 75 S TODAY=$$DT^XLFDT 76 S @VALMAR@(14,0)="MESSAGES SENT TODAY: "_$$RJ($$ADD("OUT"),10) 77 S @VALMAR@(15,0)="MESSAGES RECEIVED TODAY: "_$$RJ($$ADD("IN"),10) 78 S @VALMAR@(16,0)="MESSAGE ERRORS TODAY: "_$$RJ($$ADD("EOUT")+$$ADD("EIN"),10) 79 Q 80 ADD(DIR) ; 81 N RAP,SAP,TIME,TOTAL 82 S TOTAL=0 83 S TIME=TODAY-.0001 84 F S TIME=$O(^HLSTATS(DIR,"HOURLY",TIME)) Q:'TIME Q:((TIME\1)>TODAY) D 85 .S SAP="" 86 .F S SAP=$O(^HLSTATS(DIR,"HOURLY",TIME,SAP)) Q:SAP="" D 87 ..Q:SAP="ACCEPT ACK" 88 ..S RAP="" 89 ..F S RAP=$O(^HLSTATS(DIR,"HOURLY",TIME,SAP,RAP)) Q:RAP="" D 90 ...S TYPE="" 91 ...F S TYPE=$O(^HLSTATS(DIR,"HOURLY",TIME,SAP,RAP,TYPE)) Q:TYPE="" D 92 ....S TOTAL=TOTAL+$G(^HLSTATS(DIR,"HOURLY",TIME,SAP,RAP,TYPE)) 93 Q TOTAL 94 ; 95 HELP ; 96 S X="?" D DISP^XQORM1 W !! 97 Q 98 ; 99 EXIT ; 100 D CLEAN^VALM10 101 D CLEAR^VALM1 102 Q 103 ; 104 EXPND ; 105 Q 106 ; 107 PROCS ; 108 S HLRFRSH="PROCS^HLOUSR" 109 ;K @VALMAR 110 D CLEAN^VALM10 111 S VALMCNT=0 112 S VALMBCK="R" 113 S VALMDDF("COL 1")="COL1^1^34^" 114 S VALMDDF("COL 2")="COL 2^35^10^MIN^H" 115 S VALMDDF("COL 3")="COL 3^47^10^MAX^H" 116 S VALMDDF("COL 4")="COL 4^59^10^#RUNNING^H" 117 S VALMDDF("COL 5")="COL 5^71^10^#QUEUED^IOBON" 118 D CHGCAP^VALM("COL 1","Process Type") 119 N IEN 120 S IEN=0 121 F S IEN=$O(^HLD(779.3,"C",1,IEN)) Q:'IEN D 122 .N PROC 123 .Q:'$$GETPROC^HLOPROC1(IEN,.PROC) 124 .Q:PROC("NAME")="VMS TCP LISTENER" 125 .S VALMCNT=VALMCNT+1 126 .S @VALMAR@(VALMCNT,0)=$$LJ(PROC("NAME"),30)_$$RJ(PROC("MINIMUM"),6)_$$RJ(PROC("MAXIMUM"),12)_$$RJ(+$G(^HLC("HL7 PROCESS COUNTS","RUNNING",PROC("NAME"))),14)_$$RJ(+$G(^HLC("HL7 PROCESS COUNTS","QUEUED",PROC("NAME"))),12) 127 S VALMCNT=VALMCNT+1,@VALMAR@(VALMCNT,0)="" 128 S IEN="" 129 F S IEN=$O(^HLTMP("HL7 RUNNING PROCESSES",IEN)) Q:IEN="" D 130 .N NODE 131 .S NODE=$G(^HLTMP("HL7 RUNNING PROCESSES",IEN)) 132 .Q:NODE="" 133 .S VALMCNT=VALMCNT+1 134 .S @VALMAR@(VALMCNT,0)="$J: "_$$LJ(IEN,9)_" ->"_$$CJ($P(NODE,"^",3),28)_"<- started at "_$$HTE^XLFDT($P(NODE,"^")) 135 Q 136 ; 137 OUTQUEUE ; 138 N LINK 139 D CLEAN^VALM10 140 ;K @VALMAR 141 S HLRFRSH="OUTQUEUE^HLOUSR" 142 S (HLSCREEN,VALMSG)="Outgoing Queues *down links !stopped queues" 143 S VALMCNT=0 144 S VALMBCK="R" 145 S VALMDDF("COL 1")="COL 1^2^20^ Link^H" 146 S VALMDDF("COL 2")="COL 2^28^20^Queue^H" 147 S VALMDDF("COL 3")="COL 3^50^20^Count^H" 148 K VALMDDF("COL 4"),VALMDDF("COL 5") 149 D CHGCAP^VALM("COL 1"," Link") 150 S LINK="" 151 F S LINK=$O(^HLC("QUEUECOUNT","OUT",LINK)) Q:LINK="" D 152 .N COUNT,QUE,SHOW 153 .S SHOW=LINK 154 .I $D(^HLTMP("FAILING LINKS",SHOW)) S SHOW="*"_SHOW 155 .S QUE="" 156 .F S QUE=$O(^HLC("QUEUECOUNT","OUT",LINK,QUE)) Q:QUE="" D 157 ..S COUNT=$G(^HLC("QUEUECOUNT","OUT",LINK,QUE)) 158 ..Q:COUNT<1 159 ..S VALMCNT=VALMCNT+1 160 ..I $E(SHOW)="*" D 161 ...S @VALMAR@(VALMCNT,0)=$$LJ(SHOW,20)_$$CJ($S($$STOPPED^HLOQUE("OUT",QUE):"!",1:"")_QUE,21)_" "_$$RJ(COUNT,10),SHOW="" 162 ...D CNTRL^VALM10(VALMCNT,1,1,IOBON,IOBOFF) 163 ..E S @VALMAR@(VALMCNT,0)=$$LJ(SHOW,20)_$$CJ($S($$STOPPED^HLOQUE("OUT",QUE):"!",1:"")_QUE,21)_" "_$$RJ(COUNT,10),SHOW="" 164 Q 165 ; 166 INQUEUE ; 167 N FROM 168 D CLEAN^VALM10 169 ;K @VALMAR 170 S HLRFRSH="INQUEUE^HLOUSR" 171 S (HLSCREEN,VALMSG)="Incoming Queues ('!' = stopped queues)" 172 S VALMCNT=0 173 S VALMBCK="R" 174 S VALMDDF("COL 1")="COL 1^1^40^ From^H" 175 S VALMDDF("COL 2")="COL 2^45^20^Queue^H" 176 S VALMDDF("COL 3")="COL 3^70^10^Count^H" 177 K VALMDDF("COL 4"),VALMDDF("COL 5") 178 D CHGCAP^VALM("COL 1"," From") 179 S FROM="" 180 F S FROM=$O(^HLC("QUEUECOUNT","IN",FROM)) Q:FROM="" D 181 .N COUNT,QUE,SHOW 182 .S SHOW=$$LJ(FROM,40)_" " 183 .S QUE="" 184 .F S QUE=$O(^HLC("QUEUECOUNT","IN",FROM,QUE)) Q:QUE="" D 185 ..S COUNT=$G(^HLC("QUEUECOUNT","IN",FROM,QUE)) 186 ..Q:COUNT<0 187 ..S VALMCNT=VALMCNT+1 188 ..S @VALMAR@(VALMCNT,0)=SHOW_$$LJ($S($$STOPPED^HLOQUE("IN",QUE):"!",1:"")_QUE,21)_" "_$$RJ(COUNT,10) 189 ..S SHOW=$$LJ("",40)_" " 190 Q 191 VIEWLINK ; 192 N C,QUIT,LINK,LINKARY,TEMP 193 S (QUIT,C,LINK)="" 194 S VALMBCK="R" 195 ; 196 ;currently HL7 (Optimized) only does TCP 197 S LINK=$$ASKLINK 198 Q:LINK="" 199 Q:'$$GETLINK^HLOTLNK(LINK,.LINKARY) 200 S LINK=LINK_":"_LINKARY("PORT") 201 W !,"Hit any key to stop...",! 202 F D Q:QUIT 203 .N COUNT,QUE 204 .S (COUNT,QUE)="" 205 .F S QUE=$O(^HLC("QUEUECOUNT","OUT",LINK,QUE)) Q:QUE="" S TEMP=$G(^HLC("QUEUECOUNT","OUT",LINK,QUE)) S:TEMP>0 COUNT=COUNT+TEMP 206 .W $C(13)," ",$C(13),"MESSAGES PENDING TRANSMISSION: ",IOBON,$$RJ(+COUNT,10),IOBOFF 207 .R *C:1 I $T S QUIT=1 208 Q 209 ; 210 CJ(STRING,LEN) ; 211 Q $$CJ^XLFSTR($E(STRING,1,LEN),LEN) 212 LJ(STRING,LEN) ; 213 Q $$LJ^XLFSTR($E(STRING,1,LEN),LEN) 214 RJ(STRING,LEN) ; 215 Q $$RJ^XLFSTR($E(STRING,1,LEN),LEN) 216 ; 217 RUNNING() ;Process Manager running? 218 N RUNNING 219 L +^HLTMP("PROCESS MANAGER"):0 220 S RUNNING='$T 221 I 'RUNNING L -^HLTMP("PROCESS MANAGER") 222 Q RUNNING 223 ; 224 TESTLINK ; 225 N LINK,LINKNAME,OK 226 S VALMBCK="R" 227 S LINKNAME=$$ASKLINK 228 Q:LINKNAME="" 229 S OK=$$IFOPEN^HLOUSR1(LINKNAME) 230 I OK W !,LINKNAME_" IS operational..." 231 E W !,LINKNAME_" is NOT operational..." 232 W !,"Hit any key to continue..." 233 R *C:DTIME 234 Q 235 ; 236 ASKLINK() ; 237 N DIC,TCP,X,Y,DTOUT,DUOUT 238 S DIC=870 239 S DIC(0)="AENQ" 240 S TCP=$O(^HLCS(869.1,"B","TCP",0)) 241 S DIC("A")="Select a TCP link:" 242 S DIC("S")="I $P(^(0),U,3)=TCP" 243 D FULL^VALM1 244 D ^DIC 245 I +Y'=-1,'$D(DTOUT),'$D(DUOUT) Q $P(Y,"^",2) 246 Q "" 247 ; 248 STOP ; 249 I '$$ASKYESNO^HLOUSR2("Are you SURE that you want to stop sending and receiving messages","NO") S VALMBCK="" Q 250 ; 251 D STOPHL7^HLOPROC1 252 S VALMBCK="R",VALMSG="HL7 (Optimized) has been stopped...." 253 H 5 254 D @HLRFRSH 255 ;D:HLSCREEN="Brief System Status" BRIEF^HLOUSR 256 ;D:HLSCREEN="Running Processes" PROCS^HLOUSR 257 Q 258 ; 259 UPDMODE ;realtime 260 Q:'$L(HLRFRSH) 261 N TOP,BOTTOM,DX,DY,IOTM,IOBM,LINE,OLD,OLDCNT 262 S OLDCNT=VALMCNT 263 W !!!!!,IOINHI,"Hit any key to escape realtime display mode...",IOINORM 264 S IOTM=20,IOBM=23 W @IOSTBM 265 S TOP=VALMBG 266 S BOTTOM=TOP+20 267 F LINE=TOP:1:BOTTOM D 268 .I LINE>VALMCNT S @VALMAR@(LINE,0)=$$LJ(" ",80) Q 269 .S @VALMAR@(LINE,0)=$$LJ(@VALMAR@(LINE,0),80) 270 F LINE=TOP:1:BOTTOM D 271 .S OLD(LINE)=@VALMAR@(LINE,0) 272 F LINE=17:1:BOTTOM D 273 .S DX=50,DY=22 X IOXY W ! 274 .D WRITE^VALM10(LINE) 275 D F R *C:4 Q:$T D 276 .D @HLRFRSH 277 .F LINE=TOP:1:BOTTOM D 278 ..I LINE>VALMCNT S @VALMAR@(LINE,0)=$$LJ(" ",80) Q 279 ..S @VALMAR@(LINE,0)=$$LJ(@VALMAR@(LINE,0),80) 280 .S VALMCNT=BOTTOM 281 .F LINE=TOP:1:BOTTOM IF OLD(LINE)'=@VALMAR@(LINE,0) D 282 ..S OLD(LINE)=@VALMAR@(LINE,0) 283 ..S DX=50,DY=22 X IOXY W ! 284 ..D WRITE^VALM10(LINE) 285 S VALMCNT=OLDCNT 286 S VALMBCK="R" 287 Q 1 HLOUSR ;ALB/CJM -ListManager Screen for viewing system status;12 JUN 1997 10:00 am ;02/07/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,130,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 EN ; 6 ; 7 N HLSCREEN,TESTOPEN,HLRFRSH 8 D WAIT^DICD 9 D EN^VALM("HLO SYSTEM MONITOR") 10 Q 11 ; 12 BRIEF ;Init variables and list array 13 N COUNT,LINK,QUE,FROM,TIME,STATUS,TEMP,DIR,TODAY,LIST 14 S HLRFRSH="BRIEF^HLOUSR" 15 S (HLSCREEN,VALMSG)="Brief System Status" 16 S VALMCNT=8 17 ;K @VALMAR 18 D CLEAN^VALM10 19 S VALMBG=1 20 S VALMBCK="R" 21 K VALMDDF("COL 2"),VALMDDF("COL 3"),VALMDDF("COL 4"),VALMDDF("COL 5") 22 D CHGCAP^VALM("COL 1","Brief Operational Overview") 23 S @VALMAR@(1,0)="SYSTEM STATUS: "_$S($$CHKSTOP^HLOPROC:"STOPPED",1:"RUNNING") 24 S @VALMAR@(2,0)="PROCESS MANAGER: "_$S($$RUNNING:"RUNNING",1:"STOPPED") 25 ; 26 S TIME=$P($G(TESTOPEN("LISTENER")),"^",2) 27 I TIME,$$FMDIFF^XLFDT($$NOW^XLFDT,TIME,2)<300 D 28 .S STATUS=+TESTOPEN("LISTENER") 29 E D 30 .S STATUS=0 31 .S LINK=$P($G(^HLD(779.1,1,0)),"^",10) 32 .I LINK S LINK=$P($G(^HLCS(870,LINK,0)),"^") Q:'$L(LINK) S STATUS=$$IFOPEN^HLOUSR1(LINK) 33 .S TESTOPEN("LISTENER")=STATUS_"^"_$$NOW^XLFDT 34 ; 35 S @VALMAR@(3,0)="STANDARD LISTENER: "_$S(STATUS:"OPERATIONAL",1:"NOT OPERATIONAL") 36 ; 37 S @VALMAR@(4,0)="TASKMAN: "_$S($$TM^%ZTLOAD:"RUNNING",1:"NOT RUNNING") 38 ; 39 S (LIST,LINK)="" 40 F S LINK=$O(^HLTMP("FAILING LINKS",LINK)) Q:LINK="" D I $L(LIST)>60 S LIST=LIST_",..." Q 41 .N TIME,QUE,LINKARY 42 .I $$GETLINK^HLOTLNK($P(LINK,":"),.LINKARY) 43 .S TIME=$G(^HLTMP("FAILING LINKS",LINK)) Q:TIME="" 44 .I '$G(LINKARY("SHUTDOWN")),TIME="" Q 45 .I '$G(LINKARY("SHUTDOWN")),($$HDIFF^XLFDT($H,TIME,2)<300) Q 46 .S LIST=LIST_$S($L(LIST):", ",1:"")_$P(LINK,":") 47 S @VALMAR@(5,0)="DOWN LINKS: "_LIST 48 S @VALMAR@(6,0)="CLIENT LINK PROCESSES: "_+$G(^HLC("HL7 PROCESS COUNTS","RUNNING","OUTGOING CLIENT LINK")) 49 S @VALMAR@(7,0)="IN-FILER PROCESSES: "_+$G(^HLC("HL7 PROCESS COUNTS","RUNNING","INCOMING QUEUES")) 50 S COUNT=0,LINK="" 51 F S LINK=$O(^HLC("QUEUECOUNT","OUT",LINK)) Q:LINK="" D 52 .S QUE="" 53 .F S QUE=$O(^HLC("QUEUECOUNT","OUT",LINK,QUE)) Q:QUE="" D 54 ..S TEMP=$G(^HLC("QUEUECOUNT","OUT",LINK,QUE)) 55 ..S:TEMP>0 COUNT=COUNT+TEMP 56 S @VALMAR@(8,0)="MESSAGES PENDING TRANSMISSION: "_+COUNT 57 S TEMP="STOPPED OUTGOING QUEUES: " 58 S COUNT=0,QUE="" 59 F S QUE=$O(^HLTMP("STOPPED QUEUES","OUT",QUE)) Q:QUE="" S COUNT=COUNT+1 Q:COUNT>4 S:COUNT=1 TEMP=TEMP_QUE S:"23"[COUNT TEMP=TEMP_"; "_QUE S:COUNT=4 TEMP=TEMP_" ..." 60 S @VALMAR@(9,0)=TEMP 61 S COUNT=0,QUE="" 62 F S QUE=$O(^HLC("QUEUECOUNT","IN",QUE)) Q:QUE="" D 63 .S FROM="" 64 .F S FROM=$O(^HLC("QUEUECOUNT","IN",QUE,FROM)) Q:FROM="" D 65 ..S TEMP=$G(^HLC("QUEUECOUNT","IN",QUE,FROM)) 66 ..S:TEMP>0 COUNT=COUNT+TEMP 67 S @VALMAR@(10,0)="MESSAGES PENDING ON APPLICATIONS: "_+COUNT 68 S TEMP="STOPPED INCOMING QUEUES: " 69 S COUNT=0,QUE="" 70 F S QUE=$O(^HLTMP("STOPPED QUEUES","IN",QUE)) Q:QUE="" S COUNT=COUNT+1 Q:COUNT>4 S:COUNT=1 TEMP=TEMP_QUE S:"23"[COUNT TEMP=TEMP_"; "_QUE S:COUNT=4 TEMP=TEMP_" ..." 71 S @VALMAR@(11,0)=TEMP 72 S @VALMAR@(12,0)="FILE 777 RECORD COUNT: "_$$RJ($P($G(^HLTMP("FILE 777 RECORD COUNT")),"^"),10)_" --> as of "_$$FMTE^XLFDT($P($G(^HLTMP("FILE 777 RECORD COUNT")),"^",2)) 73 S @VALMAR@(13,0)="FILE 778 RECORD COUNT: "_$$RJ($P($G(^HLTMP("FILE 778 RECORD COUNT")),"^"),10)_" --> as of "_$$FMTE^XLFDT($P($G(^HLTMP("FILE 778 RECORD COUNT")),"^",2)) 74 S TODAY=$$DT^XLFDT 75 S @VALMAR@(14,0)="MESSAGES SENT TODAY: "_$$RJ($$ADD("OUT"),10) 76 S @VALMAR@(15,0)="MESSAGES RECEIVED TODAY: "_$$RJ($$ADD("IN"),10) 77 S @VALMAR@(16,0)="MESSAGE ERRORS TODAY: "_$$RJ($$ADD("EOUT")+$$ADD("EIN"),10) 78 Q 79 ADD(DIR) ; 80 N RAP,SAP,TIME,TOTAL 81 S TOTAL=0 82 S TIME=TODAY-.0001 83 F S TIME=$O(^HLSTATS(DIR,"HOURLY",TIME)) Q:'TIME Q:((TIME\1)>TODAY) D 84 .S SAP="" 85 .F S SAP=$O(^HLSTATS(DIR,"HOURLY",TIME,SAP)) Q:SAP="" D 86 ..Q:SAP="ACCEPT ACK" 87 ..S RAP="" 88 ..F S RAP=$O(^HLSTATS(DIR,"HOURLY",TIME,SAP,RAP)) Q:RAP="" D 89 ...S TYPE="" 90 ...F S TYPE=$O(^HLSTATS(DIR,"HOURLY",TIME,SAP,RAP,TYPE)) Q:TYPE="" D 91 ....S TOTAL=TOTAL+$G(^HLSTATS(DIR,"HOURLY",TIME,SAP,RAP,TYPE)) 92 Q TOTAL 93 ; 94 HELP ;Help code 95 S X="?" D DISP^XQORM1 W !! 96 Q 97 ; 98 EXIT ;Exit code 99 D CLEAN^VALM10 100 D CLEAR^VALM1 101 ; 102 Q 103 ; 104 EXPND ;Expand code 105 Q 106 ; 107 PROCS ; 108 S HLRFRSH="PROCS^HLOUSR" 109 ;K @VALMAR 110 D CLEAN^VALM10 111 S VALMCNT=0 112 S VALMBCK="R" 113 S VALMDDF("COL 2")="COL 2^35^10^MIN^H" 114 S VALMDDF("COL 3")="COL 3^47^10^MAX^H" 115 S VALMDDF("COL 4")="COL 4^59^10^#RUNNING^H" 116 S VALMDDF("COL 5")="COL 5^71^10^#QUEUED^IOBON" 117 D CHGCAP^VALM("COL 1","Process Type") 118 N IEN 119 S IEN=0 120 F S IEN=$O(^HLD(779.3,"C",1,IEN)) Q:'IEN D 121 .N PROC 122 .Q:'$$GETPROC^HLOPROC1(IEN,.PROC) 123 .Q:PROC("NAME")="VMS TCP LISTENER" 124 .S VALMCNT=VALMCNT+1 125 .S @VALMAR@(VALMCNT,0)=$$LJ(PROC("NAME"),30)_$$RJ(PROC("MINIMUM"),6)_$$RJ(PROC("MAXIMUM"),12)_$$RJ(+$G(^HLC("HL7 PROCESS COUNTS","RUNNING",PROC("NAME"))),14)_$$RJ(+$G(^HLC("HL7 PROCESS COUNTS","QUEUED",PROC("NAME"))),12) 126 S VALMCNT=VALMCNT+1,@VALMAR@(VALMCNT,0)="" 127 S IEN="" 128 F S IEN=$O(^HLTMP("HL7 RUNNING PROCESSES",IEN)) Q:IEN="" D 129 .N NODE 130 .S NODE=$G(^HLTMP("HL7 RUNNING PROCESSES",IEN)) 131 .Q:NODE="" 132 .S VALMCNT=VALMCNT+1 133 .S @VALMAR@(VALMCNT,0)="$J: "_$$LJ(IEN,9)_" ->"_$$CJ($P(NODE,"^",3),28)_"<- started at "_$$HTE^XLFDT($P(NODE,"^")) 134 Q 135 ; 136 OUTQUEUE ; 137 N LINK 138 D CLEAN^VALM10 139 ;K @VALMAR 140 S HLRFRSH="OUTQUEUE^HLOUSR" 141 S (HLSCREEN,VALMSG)="Outgoing Queues *down links !stopped queues" 142 S VALMCNT=0 143 S VALMBCK="R" 144 S VALMDDF("COL 1")="COL 1^2^20^ Link^H" 145 S VALMDDF("COL 2")="COL 2^28^20^Queue^H" 146 S VALMDDF("COL 3")="COL 3^50^20^Count^H" 147 K VALMDDF("COL 4"),VALMDDF("COL 5") 148 D CHGCAP^VALM("COL 1"," Link") 149 S LINK="" 150 F S LINK=$O(^HLC("QUEUECOUNT","OUT",LINK)) Q:LINK="" D 151 .N COUNT,QUE,SHOW 152 .S SHOW=LINK 153 .I $D(^HLTMP("FAILING LINKS",SHOW)) S SHOW="*"_SHOW 154 .S QUE="" 155 .F S QUE=$O(^HLC("QUEUECOUNT","OUT",LINK,QUE)) Q:QUE="" D 156 ..S COUNT=$G(^HLC("QUEUECOUNT","OUT",LINK,QUE)) 157 ..Q:COUNT<1 158 ..S VALMCNT=VALMCNT+1 159 ..I $E(SHOW)="*" D 160 ...S @VALMAR@(VALMCNT,0)=$$LJ(SHOW,20)_$$CJ($S($$STOPPED^HLOQUE("OUT",QUE):"!",1:"")_QUE,21)_" "_$$RJ(COUNT,10),SHOW="" 161 ...D CNTRL^VALM10(VALMCNT,1,1,IOBON,IOBOFF) 162 ..E S @VALMAR@(VALMCNT,0)=$$LJ(SHOW,20)_$$CJ($S($$STOPPED^HLOQUE("OUT",QUE):"!",1:"")_QUE,21)_" "_$$RJ(COUNT,10),SHOW="" 163 Q 164 ; 165 INQUEUE ; 166 N FROM 167 D CLEAN^VALM10 168 ;K @VALMAR 169 S HLRFRSH="INQUEUE^HLOUSR" 170 S (HLSCREEN,VALMSG)="Incoming Queues ('!' = stopped queues)" 171 S VALMCNT=0 172 S VALMBCK="R" 173 S VALMDDF("COL 1")="COL 1^1^40^ From^H" 174 S VALMDDF("COL 2")="COL 2^45^20^Queue^H" 175 S VALMDDF("COL 3")="COL 3^70^10^Count^H" 176 K VALMDDF("COL 4"),VALMDDF("COL 5") 177 D CHGCAP^VALM("COL 1"," From") 178 S FROM="" 179 F S FROM=$O(^HLC("QUEUECOUNT","IN",FROM)) Q:FROM="" D 180 .N COUNT,QUE,SHOW 181 .S SHOW=$$LJ(FROM,40)_" " 182 .S QUE="" 183 .F S QUE=$O(^HLC("QUEUECOUNT","IN",FROM,QUE)) Q:QUE="" D 184 ..S COUNT=$G(^HLC("QUEUECOUNT","IN",FROM,QUE)) 185 ..Q:COUNT<0 186 ..S VALMCNT=VALMCNT+1 187 ..S @VALMAR@(VALMCNT,0)=SHOW_$$LJ($S($$STOPPED^HLOQUE("IN",QUE):"!",1:"")_QUE,21)_" "_$$RJ(COUNT,10) 188 ..S SHOW=$$LJ("",40)_" " 189 Q 190 VIEWLINK ; 191 N C,QUIT,LINK,LINKARY,TEMP 192 S (QUIT,C,LINK)="" 193 S VALMBCK="R" 194 ; 195 ;currently HL7 (Optimized) only does TCP, when serial added a change is needed here 196 S LINK=$$ASKLINK 197 Q:LINK="" 198 Q:'$$GETLINK^HLOTLNK(LINK,.LINKARY) 199 S LINK=LINK_":"_LINKARY("PORT") 200 W !,"Hit any key to stop...",! 201 F D Q:QUIT 202 .N COUNT,QUE 203 .S (COUNT,QUE)="" 204 .F S QUE=$O(^HLC("QUEUECOUNT","OUT",LINK,QUE)) Q:QUE="" S TEMP=$G(^HLC("QUEUECOUNT","OUT",LINK,QUE)) S:TEMP>0 COUNT=COUNT+TEMP 205 .W $C(13)," ",$C(13),"MESSAGES PENDING TRANSMISSION: ",IOBON,$$RJ(+COUNT,10),IOBOFF 206 .R *C:1 I $T S QUIT=1 207 Q 208 ; 209 CJ(STRING,LEN) ; 210 Q $$CJ^XLFSTR($E(STRING,1,LEN),LEN) 211 LJ(STRING,LEN) ; 212 Q $$LJ^XLFSTR($E(STRING,1,LEN),LEN) 213 RJ(STRING,LEN) ; 214 Q $$RJ^XLFSTR($E(STRING,1,LEN),LEN) 215 ; 216 RUNNING() ;Is the Process Manager running? 217 N RUNNING 218 L +^HLTMP("PROCESS MANAGER"):0 219 S RUNNING='$T 220 I 'RUNNING L -^HLTMP("PROCESS MANAGER") 221 Q RUNNING 222 ; 223 TESTLINK ; 224 N LINK,LINKNAME,OK 225 S VALMBCK="R" 226 S LINKNAME=$$ASKLINK 227 Q:LINKNAME="" 228 S OK=$$IFOPEN^HLOUSR1(LINKNAME) 229 I OK W !,LINKNAME_" IS operational..." 230 E W !,LINKNAME_" is NOT operational..." 231 W !,"Hit any key to continue..." 232 R *C:DTIME 233 Q 234 ; 235 ASKLINK() ; 236 N DIC,TCP,X,Y,DTOUT,DUOUT 237 S DIC=870 238 S DIC(0)="AENQ" 239 S TCP=$O(^HLCS(869.1,"B","TCP",0)) 240 S DIC("A")="Select a TCP link:" 241 S DIC("S")="I $P(^(0),U,3)=TCP" 242 D FULL^VALM1 243 D ^DIC 244 I +Y'=-1,'$D(DTOUT),'$D(DUOUT) Q $P(Y,"^",2) 245 Q "" 246 ; 247 STOP ; 248 I '$$ASKYESNO^HLOUSR2("Are you SURE that you want to stop sending and receiving messages","NO") S VALMBCK="" Q 249 ; 250 D STOPHL7^HLOPROC1 251 S VALMBCK="R",VALMSG="HL7 (Optimized) has been stopped...." 252 H 5 253 D @HLRFRSH 254 ;D:HLSCREEN="Brief System Status" BRIEF^HLOUSR 255 ;D:HLSCREEN="Running Processes" PROCS^HLOUSR 256 Q 257 ; 258 UPDMODE ;update mode 259 Q:'$L(HLRFRSH) 260 N QUIT,NEW,TOP,BOTTOM,DX,DY,IOTM,IOBM,I 261 W !!,IOINHI,"Hit any key to escape realtime display mode...",IOINORM 262 S IOTM=3,IOBM=23 263 W @IOSTBM 264 S DX=1,DY=$S(VALMCNT<17:VALMCNT+1,1:17) X IOXY 265 I VALMCNT>16 F I=17:1:$S(VALMCNT<22:VALMCNT,1:21) W !,@VALMAR@(I,0) 266 S QUIT=0 267 S TOP=VALMBG 268 S BOTTOM=TOP+23 269 S OLD=VALMAR 270 S VALMAR="NEW" 271 S VALMCNT=0 272 F D Q:QUIT 273 .N LINE 274 .R *C:3 I $T S QUIT=1 275 .S (VALMCNT,I)=0 276 .D @HLRFRSH 277 .F LINE=TOP:1:BOTTOM IF $G(@OLD@(LINE,0))'=$G(@VALMAR@(LINE,0)) D 278 ..S:'$D(@VALMAR@(LINE,0)) @VALMAR@(LINE,0)=" " 279 ..D WRITE^VALM10(LINE) 280 K @OLD M @OLD=@VALMAR S VALMAR=OLD 281 S VALMBCK="R" 282 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOUSR1.m
r613 r623 1 HLOUSR1 ;ALB/CJM -ListManager Screen for viewing messages;12 JUN 1997 10:00 am ;07/25/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 EN ; 6 N MSGIEN 7 S MSGIEN=$$PICKMSG 8 I 'MSGIEN S VALMBCK="R" Q 9 D EN^VALM("HLO SINGLE MESSAGE DISPLAY") 10 Q 11 ; 12 HDR ; 13 Q 14 ; 15 BLANK ; 16 S VALMCNT=0 17 D EXIT 18 Q 19 DISPLAY ; 20 K @VALMAR 21 S VALMBCK="R" 22 N MSG 23 S VALMBG=1 24 Q:'MSGIEN 25 D SHOWMSG($P(MSGIEN,"^"),$P(MSGIEN,"^",2)) 26 Q 27 ; 28 PICKMSG() ; 29 ;ask the user to select a message & return its ien 30 N MSGIEN,DIR,COUNT,LIST 31 D FULL^VALM1 32 S DIR(0)="F3:30" 33 S DIR("A")="Message ID" 34 S DIR("?")="Enter the full Message Control ID or Batch Control ID of the message, or '^' to exit." 35 PICK D ^DIR 36 I $D(DIRUT)!(Y="") Q 0 37 I $G(@VALMAR@("INDEX",Y)) Q $G(@VALMAR@("INDEX",Y)) 38 S COUNT=$$FINDMSG^HLOMSG1(Y,.LIST) 39 I COUNT="0" W !!,"That message can not be found! Try Again",! G PICK 40 I COUNT=1 Q LIST(1) 41 I COUNT>1 D 42 .N ITEM 43 .W !,"There is more than one message with that ID! You must choose one to display.",1 44 .S ITEM=0 45 .F S ITEM=$O(LIST(ITEM)) Q:'ITEM D 46 ..N MSG 47 ..Q:'$$GETMSG^HLOMSG(+LIST(ITEM),.MSG) 48 ..W !,"[",ITEM,"]"," DT/TM: ",$$FMTE^XLFDT(MSG("DT/TM CREATED"),2)," STATUS: ",MSG("STATUS") 49 .S DIR(0)="NO^1:"_COUNT,DIR("A")="Choose",DIR("?")="Choose one message from the list" 50 .D ^DIR 51 .I Y S Y=LIST(Y) 52 Q Y 53 ; 54 HELP ;Help code 55 S X="?" D DISP^XQORM1 W !! 56 Q 57 ; 58 EXIT ;Exit code 59 D CLEAN^VALM10 60 D CLEAR^VALM1 61 S VALMBCK="R" 62 ; 63 Q 64 ; 65 EXPND ;Expand code 66 Q 67 ; 68 CJ(STRING,LEN) ; 69 Q $$CJ^XLFSTR(STRING,LEN) 70 LJ(STRING,LEN) ; 71 Q $$LJ^XLFSTR(STRING,LEN) 72 SP(LEN,CHAR) ; 73 ;return padding - " " is the default pad character 74 N STR 75 S:$G(CHAR)="" CHAR=" " 76 S $P(STR,CHAR,LEN)=CHAR 77 Q STR 78 ; 79 SHOWMSG(MSGIEN,SUBIEN) ; 80 ;Description: 81 ; 82 ;Input: 83 ;Output: 84 ; 85 N MSG,I,TEMP,LINE 86 S VALMCNT=0 87 S SUBIEN=+$G(SUBIEN) 88 I '$$GETMSG^HLOMSG(MSGIEN,.MSG) W !,"UNABLE TO DISPLAY THE MESSAGE",!! Q 89 I SUBIEN D GETMSGB^HLOMSG1(.MSG,SUBIEN,.MSG) 90 ; 91 S I=0 92 ;** administrative information ** 93 S @VALMAR@($$I,0)=$$CJ("Administrative Information",80) 94 D CNTRL^VALM10(VALMCNT,26,30,IORVON,IORVOFF) 95 S LINE="MsgID: "_$$LJ(MSG("ID"),18) 96 S LINE=LINE_"Status: "_$$LJ(MSG("STATUS"),5) 97 S:MSG("ACK TO")]"" LINE=LINE_$$LJ(" Ack To:",14)_MSG("ACK TO") 98 S:MSG("ACK BY")]"" LINE=LINE_$$LJ(" Ack'd By:",14)_MSG("ACK BY") 99 S @VALMAR@($$I,0)=LINE 100 I MSG("STATUS","ERROR TEXT")]"" S @VALMAR@($$I,0)="Error: "_"** "_MSG("STATUS","ERROR TEXT")_" **" 101 S @VALMAR@($$I,0)="Dir: "_$$LJ($S(MSG("DIRECTION")="IN":"INCOMING",1:"OUTGOING"),10)_$$LJ(" Trans Dt/Tm: ",12)_$$FMTE^XLFDT(MSG("DT/TM"),2)_$$LJ(" Purge DT/TM: ",8)_$$FMTE^XLFDT(MSG("STATUS","PURGE"),2) 102 S @VALMAR@($$I,0)="Link: "_$$LJ(MSG("STATUS","LINK NAME"),29)_" "_$$LJ("Queue: ",13)_MSG("STATUS","QUEUE") 103 I $L($G(MSG("STATUS","SEQUENCE QUEUE"))) D 104 .S @VALMAR@($$I,0)="Sequence Queue: "_MSG("STATUS","SEQUENCE QUEUE")_" Moved: "_$S(MSG("STATUS","MOVED TO OUT QUEUE"):"YES",1:"NO") 105 I MSG("STATUS","ACCEPT ACK'D") D 106 .S @VALMAR@($$I,0)="Accept Ack: "_$$LJ(MSG("STATUS","ACCEPT ACK ID"),26)_$$LJ(" DT/TM Ack'd: ",14)_$$FMTE^XLFDT(MSG("STATUS","ACCEPT ACK DT/TM"),2) 107 .S @VALMAR@($$I,0)=" "_MSG("STATUS","ACCEPT ACK MSA") 108 I MSG("DIRECTION")="IN" D 109 .S LINE="App Response Rtn: " 110 .I $L($G(MSG("STATUS","APP ACK RESPONSE"))) S LINE=$$LJ(LINE_MSG("STATUS","APP ACK RESPONSE"),38)_" Executed: "_$S(MSG("STATUS","APP HANDOFF"):" YES",1:" NO") 111 .S @VALMAR@($$I,0)=LINE 112 I MSG("DIRECTION")="OUT",(MSG("STATUS","APP ACK'D")!MSG("STATUS","ACCEPT ACK'D")) D 113 .S LINE="" 114 .I MSG("STATUS","ACCEPT ACK'D") D 115 ..I MSG("STATUS","ACCEPT ACK RESPONSE")="" S MSG("STATUS","ACCEPT ACK RESPONSE")="n/a" 116 ..S LINE="Accept Ack Rtn: "_MSG("STATUS","ACCEPT ACK RESPONSE") 117 .S LINE=$$LJ(LINE,39) 118 .I MSG("STATUS","APP ACK'D") D 119 ..I MSG("STATUS","APP ACK RESPONSE")="" S MSG("STATUS","APP ACK RESPONSE")="n/a" 120 ..S LINE=LINE_"App Ack Rtn: "_MSG("STATUS","APP ACK RESPONSE") 121 .S @VALMAR@($$I,0)=LINE 122 ; 123 ;** the message text ** 124 S @VALMAR@($$I,0)="" 125 I '$G(SUBIEN) D 126 .S @VALMAR@($$I,0)=$$CJ("Message Text",80) 127 .D CNTRL^VALM10(VALMCNT,33,16,IORVON,IORVOFF) 128 E D 129 .S @VALMAR@($$I,0)=$$CJ("Individual Message Text (Batched)",80) 130 .D CNTRL^VALM10(VALMCNT,23,35,IORVON,IORVOFF) 131 D SHOWBODY(.MSG,$G(SUBIEN)) 132 ; 133 ;** display its application acknowledgment ** 134 I MSG("ACK BY")]"",$$FINDMSG^HLOMSG1(MSG("ACK BY"),.TEMP)=1 S MSGIEN=TEMP(1) D 135 .N MSG 136 .Q:'$$GETMSG^HLOMSG(+MSGIEN,.MSG) 137 .I $P(MSGIEN,"^",2) D GETMSGB^HLOMSG1(.MSG,$P(MSGIEN,"^",2),.MSG) 138 .S @VALMAR@($$I,0)="" 139 .S @VALMAR@($$I,0)=$$CJ("Application Acknowledgment",80) 140 .D CNTRL^VALM10(VALMCNT,26,30,IORVON,IORVOFF) 141 .D SHOWBODY(.MSG,$P(MSGIEN,"^",2)) 142 ; 143 ;** display the original message ** 144 I MSG("ACK TO")]"",$$FINDMSG^HLOMSG1(MSG("ACK TO"),.TEMP)=1 S MSGIEN=TEMP(1) D 145 .N MSG 146 .Q:'$$GETMSG^HLOMSG(+MSGIEN,.MSG) 147 .I $P(MSGIEN,"^",2) D GETMSGB^HLOMSG1(.MSG,$P(MSGIEN,"^",2),.MSG) 148 .S @VALMAR@($$I,0)="" 149 .S @VALMAR@($$I,0)=$$CJ("Original Message",80) 150 .D CNTRL^VALM10(VALMCNT,26,30,IORVON,IORVOFF) 151 .D SHOWBODY(.MSG,$P(MSGIEN,"^",2)) 152 Q 153 ; 154 SHOWBODY(MSG,SUBIEN) ; 155 N NODE,I,SEG,QUIT 156 S QUIT=0 157 M SEG=MSG("HDR") 158 D ADD(.SEG) 159 S MSG("BATCH","CURRENT MESSAGE")=0 160 I MSG("BATCH") D 161 .I $G(SUBIEN) D Q 162 ..S MSG("BATCH","CURRENT MESSAGE")=SUBIEN 163 ..F Q:'$$HLNEXT^HLOMSG(.MSG,.SEG) D ADD(.SEG) 164 .S MSG("BATCH","CURRENT MESSAGE")=0 165 .N LAST S LAST=0 166 .F Q:'$$NEXTMSG^HLOMSG(.MSG,.SEG) D Q:QUIT 167 ..D ADD(.SEG) 168 ..S LAST=MSG("BATCH","CURRENT MESSAGE") 169 ..F Q:'$$HLNEXT^HLOMSG(.MSG,.SEG) D ADD(.SEG) 170 .I MSG("DIRECTION")="OUT" K SEG S SEG(1)="BTS"_$E($G(NODE(1)),4)_LAST D ADD(.SEG) 171 E D 172 .F Q:'$$HLNEXT^HLOMSG(.MSG,.SEG) D Q:QUIT 173 ..D ADD(.SEG) 174 Q 175 I() ; 176 S VALMCNT=VALMCNT+1 177 Q VALMCNT 178 ADD(SEG) ; 179 N QUIT,I,J,LINE 180 S QUIT=0 181 S (I,J)=1 182 S LINE(1)=$E(SEG(1),1,80),SEG(1)=$E(SEG(1),81,9999) 183 I SEG(1)="" K SEG(1) 184 D SHIFT(.I,.J) 185 S @VALMAR@($$I,0)=LINE(1) 186 S I=1 187 F S I=$O(LINE(I)) Q:'I D 188 .S @VALMAR@($$I,0)=LINE(I) 189 .D CNTRL^VALM10(VALMCNT,1,1,IORVON,IORVOFF) 190 Q 191 ; 192 SHIFT(I,J) ; 193 I '$D(SEG(I)) S I=$O(SEG(0)) Q:'I 194 I $L(LINE(J))<80 D 195 .N LEN 196 .S LEN=$L(LINE(J)) 197 .S LINE(J)=LINE(J)_$E(SEG(I),1,80-LEN) 198 .S SEG(I)=$E(SEG(I),81-LEN,9999) 199 .I SEG(I)="" K SEG(I) 200 E D 201 .S J=J+1 202 .S LINE(J)="-" 203 D SHIFT(.I,.J) 204 Q 205 ; 206 SCRLMODE ;scroll mode 207 Q:'$L(HLRFRSH) 208 N QUIT,IOTM,IOBM,DX,DY,LINE,IOTM,IOBM 209 W !!,IOINHI,"Hit any key to escape scroll mode...",IOINORM 210 S IOTM=3,IOBM=23 211 S QUIT=0 212 S LINE=$S(VALMCNT<17:1,1:17) 213 W @IOSTBM 214 S DX=1,DY=$S(VALMCNT<17:VALMCNT+1,1:17) X IOXY 215 F I=1:1 D Q:QUIT 216 .;every 10 seconds refresh the data 217 .I I>42 D @HLRFRSH S I=0 218 .I LINE+1>VALMCNT D 219 ..S TEMP=$G(@VALMAR@(LINE,0)) 220 ..W !,IOUON,TEMP_$$SP(80-$L(TEMP)),IOUOFF 221 .E W !,$G(@VALMAR@(LINE,0)) 222 .S LINE=LINE+1 223 .I LINE>VALMCNT S LINE=1 224 .I (I=22)!(I=43) R *C:5 I $T S QUIT=1 Q 225 S VALMBG=LINE-23 I VALMBG<0 S VALMBG=1 226 S VALMBCK="R" 227 Q 228 HLP ; 229 Q 230 ; 231 IFOPEN(LINK) ; 232 ;returns 1 if the link can be opened, otherwise 0 233 ; 234 ;Inputs: 235 ; LINK - name of the link (required), optionally post-fixed with ":"_<port #>, will default to that defined for link 236 ; 237 N LINKNAME,LINKARY,POP,IO,IOF,IOST,OPEN,PORT 238 S OPEN=0 239 S LINKNAME=$P(LINK,":") 240 S PORT=$P(LINK,":",2) 241 Q:LINKNAME="" 0 242 Q:'$$GETLINK^HLOTLNK(LINKNAME,.LINKARY) 0 243 S:PORT LINKARY("PORT")=PORT 244 Q:'$G(LINKARY("PORT")) 0 245 I LINKARY("IP")="",LINKARY("DOMAIN")="",LINKARY("LLP")="TCP",LINKARY("SERVER") D 246 .N DATA 247 .S LINKARY("DOMAIN")=$P($G(^HLD(779.1,1,0)),"^") 248 .Q:LINKARY("DOMAIN")="" 249 .S DATA(.08)=LINKARY("DOMAIN") 250 .Q:$$UPD^HLOASUB1(870,LINKARY("IEN"),.DATA) 251 D:$G(LINKARY("IP"))'="" 252 .D CALL^%ZISTCP(LINKARY("IP"),LINKARY("PORT"),15) 253 .S OPEN='POP 254 I 'OPEN,LINKARY("DOMAIN")'="",$G(^HLTMP("DNS LAST",LINKARY("IEN")))<$$DT^XLFDT D 255 .N IP 256 .S ^HLTMP("DNS LAST",LINKARY("IEN"))=$$DT^XLFDT 257 .S IP=$$DNS^HLOTCP(LINKARY("DOMAIN")) 258 .I IP'="",IP'=LINKARY("IP") D 259 ..N DATA 260 ..S DATA(400.01)=IP,LINKARY("IP")=IP 261 ..Q:$$UPD^HLOASUB1(870,LINKARY("IEN"),.DATA) 262 ..D CALL^%ZISTCP(LINKARY("IP"),LINKARY("PORT"),15) 263 ..S OPEN='POP 264 C:OPEN IO 265 ;D CLOSE^%ZISTCP 266 Q OPEN 1 HLOUSR1 ;ALB/CJM -ListManager Screen for viewing messages;12 JUN 1997 10:00 am ;03/19/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 EN ; 6 N MSGIEN 7 S MSGIEN=$$PICKMSG 8 I 'MSGIEN S VALMBCK="R" Q 9 D EN^VALM("HLO SINGLE MESSAGE DISPLAY") 10 Q 11 ; 12 HDR ; 13 Q 14 ; 15 BLANK ; 16 S VALMCNT=0 17 D EXIT 18 Q 19 DISPLAY ; 20 K @VALMAR 21 S VALMBCK="R" 22 N MSG 23 S VALMBG=1 24 Q:'MSGIEN 25 D SHOWMSG($P(MSGIEN,"^"),$P(MSGIEN,"^",2)) 26 Q 27 ; 28 PICKMSG() ; 29 ;ask the user to select a message & return its ien 30 N MSGIEN,DIR,COUNT,LIST 31 D FULL^VALM1 32 S DIR(0)="F3:30" 33 S DIR("A")="Message ID" 34 S DIR("?")="Enter the full Message Control ID or Batch Control ID of the message, or '^' to exit." 35 PICK D ^DIR 36 I $D(DIRUT)!(Y="") Q 0 37 I $G(@VALMAR@("INDEX",Y)) Q $G(@VALMAR@("INDEX",Y)) 38 S COUNT=$$FINDMSG^HLOMSG1(Y,.LIST) 39 I COUNT="0" W !!,"That message can not be found! Try Again",! G PICK 40 I COUNT=1 Q LIST(1) 41 I COUNT>1 D 42 .N ITEM 43 .W !,"There is more than one message with that ID! You must choose one to display.",1 44 .S ITEM=0 45 .F S ITEM=$O(LIST(ITEM)) Q:'ITEM D 46 ..N MSG 47 ..Q:'$$GETMSG^HLOMSG(+LIST(ITEM),.MSG) 48 ..W !,"[",ITEM,"]"," DT/TM: ",$$FMTE^XLFDT(MSG("DT/TM CREATED"),2)," STATUS: ",MSG("STATUS") 49 .S DIR(0)="NO^1:"_COUNT,DIR("A")="Choose",DIR("?")="Choose one message from the list" 50 .D ^DIR 51 .I Y S Y=LIST(Y) 52 Q Y 53 ; 54 HELP ;Help code 55 S X="?" D DISP^XQORM1 W !! 56 Q 57 ; 58 EXIT ;Exit code 59 D CLEAN^VALM10 60 D CLEAR^VALM1 61 S VALMBCK="R" 62 ; 63 Q 64 ; 65 EXPND ;Expand code 66 Q 67 ; 68 CJ(STRING,LEN) ; 69 Q $$CJ^XLFSTR(STRING,LEN) 70 LJ(STRING,LEN) ; 71 Q $$LJ^XLFSTR(STRING,LEN) 72 SP(LEN,CHAR) ; 73 ;return padding - " " is the default pad character 74 N STR 75 S:$G(CHAR)="" CHAR=" " 76 S $P(STR,CHAR,LEN)=CHAR 77 Q STR 78 ; 79 SHOWMSG(MSGIEN,SUBIEN) ; 80 ;Description: 81 ; 82 ;Input: 83 ;Output: 84 ; 85 N MSG,I,TEMP,LINE 86 S VALMCNT=0 87 S SUBIEN=+$G(SUBIEN) 88 I '$$GETMSG^HLOMSG(MSGIEN,.MSG) W !,"UNABLE TO DISPLAY THE MESSAGE",!! Q 89 I SUBIEN D GETMSGB^HLOMSG1(.MSG,SUBIEN,.MSG) 90 ; 91 S I=0 92 ;** administrative information ** 93 S @VALMAR@($$I,0)=$$CJ("Administrative Information",80) 94 D CNTRL^VALM10(VALMCNT,26,30,IORVON,IORVOFF) 95 S LINE="MsgID: "_$$LJ(MSG("ID"),18) 96 S LINE=LINE_"Status: "_$$LJ(MSG("STATUS"),5) 97 S:MSG("ACK TO")]"" LINE=LINE_$$LJ(" Ack To:",14)_MSG("ACK TO") 98 S:MSG("ACK BY")]"" LINE=LINE_$$LJ(" Ack'd By:",14)_MSG("ACK BY") 99 S @VALMAR@($$I,0)=LINE 100 I MSG("STATUS","ERROR TEXT")]"" S @VALMAR@($$I,0)="Error: "_"** "_MSG("STATUS","ERROR TEXT")_" **" 101 S @VALMAR@($$I,0)="Dir: "_$$LJ($S(MSG("DIRECTION")="IN":"INCOMING",1:"OUTGOING"),10)_$$LJ(" Trans Dt/Tm: ",12)_$$FMTE^XLFDT(MSG("DT/TM"),2)_$$LJ(" Purge DT/TM: ",8)_$$FMTE^XLFDT(MSG("STATUS","PURGE"),2) 102 S @VALMAR@($$I,0)="Link: "_$$LJ(MSG("STATUS","LINK NAME"),29)_" "_$$LJ("Queue: ",13)_MSG("STATUS","QUEUE") 103 I MSG("STATUS","ACCEPT ACK'D") D 104 .S @VALMAR@($$I,0)="Accept Ack: "_$$LJ(MSG("STATUS","ACCEPT ACK ID"),26)_$$LJ(" At: ",14)_$$FMTE^XLFDT(MSG("STATUS","ACCEPT ACK DT/TM"),2) 105 .S @VALMAR@($$I,0)=" "_MSG("STATUS","ACCEPT ACK MSA") 106 I MSG("DIRECTION")="IN" D 107 .S LINE="App Response Rtn: " 108 .I $L($G(MSG("STATUS","APP ACK RESPONSE"))) S LINE=$$LJ(LINE_MSG("STATUS","APP ACK RESPONSE"),38)_" Executed: "_$S(MSG("STATUS","APP HANDOFF"):" YES",1:" NO") 109 .S @VALMAR@($$I,0)=LINE 110 I MSG("DIRECTION")="OUT",(MSG("STATUS","APP ACK'D")!MSG("STATUS","ACCEPT ACK'D")) D 111 .S LINE="" 112 .I MSG("STATUS","ACCEPT ACK'D") D 113 ..I MSG("STATUS","ACCEPT ACK RESPONSE")="" S MSG("STATUS","ACCEPT ACK RESPONSE")="n/a" 114 ..S LINE="Accept Ack Rtn: "_MSG("STATUS","ACCEPT ACK RESPONSE") 115 .S LINE=$$LJ(LINE,39) 116 .I MSG("STATUS","APP ACK'D") D 117 ..I MSG("STATUS","APP ACK RESPONSE")="" S MSG("STATUS","APP ACK RESPONSE")="n/a" 118 ..S LINE=LINE_"App Ack Rtn: "_MSG("STATUS","APP ACK RESPONSE") 119 .S @VALMAR@($$I,0)=LINE 120 ; 121 ;** the message text ** 122 S @VALMAR@($$I,0)="" 123 I '$G(SUBIEN) D 124 .S @VALMAR@($$I,0)=$$CJ("Message Text",80) 125 .D CNTRL^VALM10(VALMCNT,33,16,IORVON,IORVOFF) 126 E D 127 .S @VALMAR@($$I,0)=$$CJ("Individual Message Text (Batched)",80) 128 .D CNTRL^VALM10(VALMCNT,23,35,IORVON,IORVOFF) 129 D SHOWBODY(.MSG,$G(SUBIEN)) 130 ; 131 ;** display its application acknowledgment ** 132 I MSG("ACK BY")]"",$$FINDMSG^HLOMSG1(MSG("ACK BY"),.TEMP)=1 S MSGIEN=TEMP(1) D 133 .N MSG 134 .Q:'$$GETMSG^HLOMSG(+MSGIEN,.MSG) 135 .I $P(MSGIEN,"^",2) D GETMSGB^HLOMSG1(.MSG,$P(MSGIEN,"^",2),.MSG) 136 .S @VALMAR@($$I,0)="" 137 .S @VALMAR@($$I,0)=$$CJ("Application Acknowledgment",80) 138 .D CNTRL^VALM10(VALMCNT,26,30,IORVON,IORVOFF) 139 .D SHOWBODY(.MSG,$P(MSGIEN,"^",2)) 140 ; 141 ;** display the original message ** 142 I MSG("ACK TO")]"",$$FINDMSG^HLOMSG1(MSG("ACK TO"),.TEMP)=1 S MSGIEN=TEMP(1) D 143 .N MSG 144 .Q:'$$GETMSG^HLOMSG(+MSGIEN,.MSG) 145 .I $P(MSGIEN,"^",2) D GETMSGB^HLOMSG1(.MSG,$P(MSGIEN,"^",2),.MSG) 146 .S @VALMAR@($$I,0)="" 147 .S @VALMAR@($$I,0)=$$CJ("Original Message",80) 148 .D CNTRL^VALM10(VALMCNT,26,30,IORVON,IORVOFF) 149 .D SHOWBODY(.MSG,$P(MSGIEN,"^",2)) 150 Q 151 ; 152 SHOWBODY(MSG,SUBIEN) ; 153 N NODE,I,SEG,QUIT 154 S QUIT=0 155 M SEG=MSG("HDR") 156 D ADD(.SEG) 157 S MSG("BATCH","CURRENT MESSAGE")=0 158 I MSG("BATCH") D 159 .I $G(SUBIEN) D Q 160 ..S MSG("BATCH","CURRENT MESSAGE")=SUBIEN 161 ..F Q:'$$HLNEXT^HLOMSG(.MSG,.SEG) D ADD(.SEG) 162 .S MSG("BATCH","CURRENT MESSAGE")=0 163 .N LAST S LAST=0 164 .F Q:'$$NEXTMSG^HLOMSG(.MSG,.SEG) D Q:QUIT 165 ..D ADD(.SEG) 166 ..S LAST=MSG("BATCH","CURRENT MESSAGE") 167 ..F Q:'$$HLNEXT^HLOMSG(.MSG,.SEG) D ADD(.SEG) 168 .I MSG("DIRECTION")="OUT" K SEG S SEG(1)="BTS"_$E($G(NODE(1)),4)_LAST D ADD(.SEG) 169 E D 170 .F Q:'$$HLNEXT^HLOMSG(.MSG,.SEG) D Q:QUIT 171 ..D ADD(.SEG) 172 Q 173 I() ; 174 S VALMCNT=VALMCNT+1 175 Q VALMCNT 176 ADD(SEG) ; 177 N QUIT,I,J,LINE 178 S QUIT=0 179 S (I,J)=1 180 S LINE(1)=$E(SEG(1),1,80),SEG(1)=$E(SEG(1),81,9999) 181 I SEG(1)="" K SEG(1) 182 D SHIFT(.I,.J) 183 S @VALMAR@($$I,0)=LINE(1) 184 S I=1 185 F S I=$O(LINE(I)) Q:'I D 186 .S @VALMAR@($$I,0)=LINE(I) 187 .D CNTRL^VALM10(VALMCNT,1,1,IORVON,IORVOFF) 188 Q 189 ; 190 SHIFT(I,J) ; 191 I '$D(SEG(I)) S I=$O(SEG(0)) Q:'I 192 I $L(LINE(J))<80 D 193 .N LEN 194 .S LEN=$L(LINE(J)) 195 .S LINE(J)=LINE(J)_$E(SEG(I),1,80-LEN) 196 .S SEG(I)=$E(SEG(I),81-LEN,9999) 197 .I SEG(I)="" K SEG(I) 198 E D 199 .S J=J+1 200 .S LINE(J)="-" 201 D SHIFT(.I,.J) 202 Q 203 ; 204 SCRLMODE ;scroll mode 205 Q:'$L(HLRFRSH) 206 N QUIT,IOTM,IOBM,DX,DY,LINE,IOTM,IOBM 207 W !!,IOINHI,"Hit any key to escape scroll mode...",IOINORM 208 S IOTM=3,IOBM=23 209 S QUIT=0 210 S LINE=$S(VALMCNT<17:1,1:17) 211 W @IOSTBM 212 S DX=1,DY=$S(VALMCNT<17:VALMCNT+1,1:17) X IOXY 213 F I=1:1 D Q:QUIT 214 .;every 10 seconds refresh the data 215 .I I>42 D @HLRFRSH S I=0 216 .I LINE+1>VALMCNT D 217 ..S TEMP=$G(@VALMAR@(LINE,0)) 218 ..W !,IOUON,TEMP_$$SP(80-$L(TEMP)),IOUOFF 219 .E W !,$G(@VALMAR@(LINE,0)) 220 .S LINE=LINE+1 221 .I LINE>VALMCNT S LINE=1 222 .I (I=22)!(I=43) R *C:5 I $T S QUIT=1 Q 223 S VALMBG=LINE-23 I VALMBG<0 S VALMBG=1 224 S VALMBCK="R" 225 Q 226 HLP ; 227 Q 228 ; 229 IFOPEN(LINK) ; 230 ;returns 1 if the link can be opened, otherwise 0 231 ; 232 ;Inputs: 233 ; LINK - name of the link (required), optionally post-fixed with ":"_<port #>, will default to that defined for link 234 ; 235 N LINKNAME,LINKARY,POP,IO,IOF,IOST,OPEN,PORT 236 S OPEN=0 237 S LINKNAME=$P(LINK,":") 238 S PORT=$P(LINK,":",2) 239 Q:LINKNAME="" 0 240 Q:'$$GETLINK^HLOTLNK(LINKNAME,.LINKARY) 0 241 S:PORT LINKARY("PORT")=PORT 242 Q:'$G(LINKARY("PORT")) 0 243 I LINKARY("IP")="",LINKARY("DOMAIN")="",LINKARY("LLP")="TCP",LINKARY("SERVER") D 244 .N DATA 245 .S LINKARY("DOMAIN")=$P($G(^HLD(779.1,1,0)),"^") 246 .Q:LINKARY("DOMAIN")="" 247 .S DATA(.08)=LINKARY("DOMAIN") 248 .Q:$$UPD^HLOASUB1(870,LINKARY("IEN"),.DATA) 249 D:$G(LINKARY("IP"))'="" 250 .D CALL^%ZISTCP(LINKARY("IP"),LINKARY("PORT"),15) 251 .S OPEN='POP 252 I 'OPEN,LINKARY("DOMAIN")'="",$G(^HLTMP("DNS LAST",LINKARY("IEN")))<$$DT^XLFDT D 253 .N IP 254 .S ^HLTMP("DNS LAST",LINKARY("IEN"))=$$DT^XLFDT 255 .S IP=$$DNS^HLOTCP(LINKARY("DOMAIN")) 256 .I IP'="",IP'=LINKARY("IP") D 257 ..N DATA 258 ..S DATA(400.01)=IP,LINKARY("IP")=IP 259 ..Q:$$UPD^HLOASUB1(870,LINKARY("IEN"),.DATA) 260 ..D CALL^%ZISTCP(LINKARY("IP"),LINKARY("PORT"),15) 261 ..S OPEN='POP 262 C:OPEN IO 263 ;D CLOSE^%ZISTCP 264 Q OPEN -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLOUSR2.m
r613 r623 1 HLOUSR2 ;ALB/CJM -ListManager Screen for viewing messages(continued);12 JUN 1997 10:00 am ;07/17/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134,137**;Oct 13, 1995;Build 21 3 ;Per VHA Directive 2004-038, this routine should not be modified 4 ; 5 EN ; 6 D WAIT^DICD 7 D EN^VALM("HLO MESSAGE VIEWER") 8 Q 9 ; 10 SHOWLIST ; 11 N PARMS,I,ERRCOUNT 12 S (VALMBG,VALMCNT,I,ERRCOUNT)=0 13 D CLEAN^VALM10 14 S VALMBG=1 15 I '$$ASKPARMS(.PARMS) S VALMBCK="" Q 16 I PARMS("ALL") D 17 .N APP 18 .S APP="" 19 .F S APP=$O(^HLB("ERRORS",APP)) Q:APP="" D Q:ERRCOUNT>PARMS("MAX") 20 ..N TIME,IEN 21 ..S TIME=PARMS("START") 22 ..Q:($O(^HLB("ERRORS",APP,TIME))="") 23 ..S @VALMAR@($$I,0)="Application: "_APP 24 ..D CNTRL^VALM10(VALMCNT,14,$L(APP),IOINHI,IOINORM) 25 ..F S TIME=$O(^HLB("ERRORS",APP,TIME)) Q:'TIME Q:ERRCOUNT>PARMS("MAX") S IEN="" F S IEN=$O(^HLB("ERRORS",APP,TIME,IEN)) Q:IEN="" D ADDTO(IEN,TIME,.ERRCOUNT) Q:ERRCOUNT>PARMS("MAX") 26 E D 27 .N APP 28 .S APP=PARMS("APP") 29 .N TIME,IEN 30 .S TIME=PARMS("START") 31 .Q:$O(^HLB("ERRORS",APP,TIME))="" 32 .S @VALMAR@($$I,0)="Application: "_APP 33 .D CNTRL^VALM10(VALMCNT,14,$L(APP),IOINHI,IOINORM) 34 .F S TIME=$O(^HLB("ERRORS",APP,TIME)) Q:'TIME Q:ERRCOUNT>PARMS("MAX") S IEN="" F S IEN=$O(^HLB("ERRORS",APP,TIME,IEN)) Q:IEN="" D ADDTO(IEN,TIME,.ERRCOUNT) Q:ERRCOUNT>PARMS("MAX") 35 ; 36 SHOW S VALMBCK="R" 37 ; 38 Q 39 ADDTO(IEN,TIME,ERRCOUNT) ; 40 N NODE,MSG 41 Q:'$$GETMSG^HLOMSG(+IEN,.MSG) 42 S ERRCOUNT=ERRCOUNT+1 43 ;application errors could be an error to a msg within a batch 44 ;also, need to go to the ack msg to get the error text from the MSA segment 45 ; 46 N SUBIEN,MSA,ERRTEXT 47 S (ERRTEXT,MSA)="" 48 S SUBIEN=$P(IEN,"^",2) 49 ;within batch? 50 D:SUBIEN GETMSGB^HLOMSG1(.MSG,SUBIEN,.MSG) 51 S ERRTEXT=MSG("STATUS","ERROR TEXT") 52 I ERRTEXT="",MSG("ACK BY")]"",($$FINDMSG^HLOMSG1(MSG("ACK BY"),.LIST)=1) D 53 .N MSG,SEG,FS,AIEN 54 .S AIEN=+LIST(1),SUBIEN=$P(LIST(1),"^",2) 55 .Q:'$$GETMSG^HLOMSG(AIEN,.MSG) 56 .I SUBIEN S MSG("BATCH","CURRENT MESSAGE")=SUBIEN,MSG("LINE COUNT")=0 57 .F Q:'$$HLNEXT^HLOMSG(.MSG,.SEG) I $E(SEG(1),1,3)="MSA" S MSA=SEG(1),FS=$E(MSA,4),ERRTEXT=$P(MSA,FS,4) Q 58 I ERRTEXT="",MSG("ACK BY")="" D 59 .N FS 60 .S FS=$E(MSG("HDR",1),4) 61 .I $L(FS) S ERRTEXT=$P($G(MSG("STATUS","ACCEPT ACK MSA")),FS,4) 62 S @VALMAR@($$I,0)=" "_$$LJ(MSG("ID"),15)_$$LJ(MSG("MESSAGE TYPE")_"~"_MSG("EVENT"),8)_$$LJ($$FMTE^XLFDT(MSG("DT/TM CREATED"),2),20)_$E(ERRTEXT,1,35) 63 D CNTRL^VALM10(VALMCNT,3,15,IOINHI,IOINORM) 64 I $L(ERRTEXT)>35 D 65 .S @VALMAR@($$I,0)=$$RJ(" ",45)_$E(ERRTEXT,36,115) 66 S:MSG("ID")]"" @VALMAR@("INDEX",MSG("ID"))=IEN 67 Q 68 ; 69 ASKPARMS(PARMS) ; 70 K PARMS 71 S PARMS("START")=$$ASKBEGIN("T-1") 72 I 'PARMS("START") Q 0 73 S PARMS("MAX")=$$ASKMAX() 74 Q:'(PARMS("MAX")>-1) 0 75 S PARMS("ALL")=$$ASKYESNO("Include ALL applications","YES") 76 I PARMS("ALL") Q 1 77 I PARMS("ALL")="" Q 0 78 S PARMS("APP")=$$ASKAPP 79 I PARMS("APP")="" Q 0 80 Q 1 81 ; 82 ASKMAX() ; 83 N DIR 84 S DIR(0)="N^1:30000:0" 85 S DIR("A")="Maximum List Size" 86 S DIR("B")=1000 87 S DIR("?",1)="In case a large number of errors meet your search criteria, what are the" 88 S DIR("?")="maximum number of errors to display? (30,000 maximum)" 89 D ^DIR 90 Q:$D(DTOUT)!$D(DUOUT) -1 91 Q X-1 92 ASKAPP() ; 93 D FULL^VALM1 94 S VALMBCK="R" 95 N DIR 96 S DIR(0)="F^3:60" 97 S DIR("A")="Receiving Application" 98 S DIR("?")="Enter the full name of the application, or '^' to exit." 99 D ^DIR 100 I $D(DIRUT)!(Y="") Q "" 101 Q Y 102 ; 103 ASKYESNO(PROMPT,DEFAULT) ; 104 ;Description: Displays PROMPT, appending '?'. Expects a YES NO response 105 ;Input: 106 ; PROMPT - text to display as prompt. Appends '?' 107 ; DEFAULT - (optional) YES or NO. If not passed, defaults to YES 108 ;Output: 109 ; Function value: 1 if yes, 0 if no, "" if '^' entered or timeout 110 ; 111 N DIR,Y 112 S DIR(0)="Y" 113 S DIR("A")=PROMPT 114 S DIR("B")=$S($G(DEFAULT)="NO":"NO",1:"YES") 115 D ^DIR 116 Q:$D(DIRUT) "" 117 Q Y 118 ; 119 STRTSTPQ ; 120 ;action to start or stop a queue, either incoming or outgoing 121 ; 122 N STOP,INOROUT,QUE 123 S VALMBCK="R" 124 D FULL^VALM1 125 ;ask if stop or start 126 D Q:STOP="" 127 .N DIR 128 .S DIR(0)="S^1:START;2:STOP" 129 .S DIR("A")="Do you want to START or STOP a queue" 130 .S DIR("B")="1" 131 .D ^DIR 132 .S STOP=$S(Y=1:0,Y=2:1,1:"") 133 ;ask if in or out 134 D Q:INOROUT="" 135 .N DIR 136 .S DIR(0)="S^I:INCOMING;O:OUTGOING" 137 .S DIR("A")="Do you want to "_$S(STOP:"stop",1:"start")_" an incoming queue or an outgoing queue" 138 .S DIR("B")="I" 139 .D ^DIR 140 .S INOROUT=$S(Y="I":"IN",Y="O":"OUT",1:"") 141 S QUE=$$ASKQUE(INOROUT) 142 Q:QUE="" 143 I STOP=$$STOPPED^HLOQUE(INOROUT,QUE) D 144 .N C 145 .I STOP D 146 ..W !,"That queue is already stopped!" 147 .E W !,"That queue is not stopped!" 148 .W !,IOINHI,"Hit any key to continue...",IOINORM 149 .R *C:DTIME 150 E D 151 .N C 152 .D:STOP STOPQUE^HLOQUE(INOROUT,QUE) 153 .D:'STOP STARTQUE^HLOQUE(INOROUT,QUE) 154 .W !,"DONE!" 155 .W !,IOINHI,"Hit any key to continue...",IOINORM 156 .R *C:DTIME 157 .D @HLRFRSH 158 Q 159 ; 160 ASKQUE(DIR) ; 161 N QUEUE 162 AGAIN W !,"Enter the full, exact name of queue:" 163 S QUEUE="" 164 R QUEUE:60 I '$T Q "" 165 I $E(QUEUE)="?" W !,"Each message is placed on a queue that has an arbitrary name up to 20",!,"characters long." I $$ASKYESNO("Would you like to see a list of the queues that currently exist","NO") D G AGAIN 166 .N SUB,QUE,QUIT,COUNT 167 .K ^TMP($J,"HLO QUEUES") 168 .S SUB="" 169 .F S SUB=$O(^HLB("QUEUE",DIR,SUB)) Q:SUB="" D 170 ..S QUE="" 171 ..F S QUE=$O(^HLB("QUEUE",DIR,SUB,QUE)) Q:QUE="" S ^TMP($J,"HLO QUEUES",QUE)="" 172 .S QUE="" 173 .S IOSL=$G(IOSL,20) 174 .S (COUNT,QUIT)=0 175 .W ! 176 .F S QUE=$O(^TMP($J,"HLO QUEUES",QUE)) Q:QUE="" Q:QUIT D 177 ..W !,QUE 178 ..S COUNT=COUNT+1 179 ..I COUNT>(IOSL-3) D 180 ...N Y 181 ...D PAUSE^VALM1 182 ...I 'Y S QUIT=1 183 ...S COUNT=0 184 .W ! 185 .K ^TMP($J,"HLO QUEUES") 186 Q:$E(QUEUE)="?" "" 187 Q:$E(QUEUE)="^" "" 188 Q QUEUE 189 ; 190 ASKBEGIN(DEFAULT) ; 191 ;Description: Asks the user to enter a beginning date. 192 ;Input: DEFAULT - the suggested default dt/time (optional) 193 ;Output: Returns the date as the function value, or 0 if the user does not select a date 194 ; 195 ; 196 N %DT 197 S %DT="AEST" 198 S %DT("A")="Enter the beginning date/time: " 199 S %DT("B")=$$FMTE^XLFDT($S($L($G(DEFAULT)):DEFAULT,1:$$FMADD^XLFDT(DT,-1))) 200 S %DT(0)="-NOW" 201 Q:$D(DTOUT) 0 202 D ^%DT 203 I Y=-1 Q 0 204 Q Y 205 ; 206 ASKEND(BEGIN) ; 207 ;Description: Asks the user to enter an ending date/time 208 ;Input: BEGIN - the earliest date/time allowed 209 ;Output: Returns the date as the function value, or 0 if the user does not select a date/time 210 ; 211 N %DT 212 S %DT="AEST" 213 S %DT("A")="Enter the ending date/time: " 214 S %DT("B")="NOW" 215 S %DT(0)=BEGIN 216 Q:$D(DTOUT) 0 217 D ^%DT 218 I Y=-1 Q 0 219 Q Y 220 ; 221 LJ(STRING,LEN) ; 222 Q $$LJ^XLFSTR(STRING,LEN) 223 RJ(STRING,LEN) ; 224 Q $$RJ^XLFSTR(STRING,LEN) 225 ; 226 I() ; 227 S VALMCNT=VALMCNT+1 228 Q VALMCNT 229 ; 230 HEADER ; 231 Q 1 HLOUSR2 ;ALB/CJM -ListManager Screen for viewing messages(continued);12 JUN 1997 10:00 am ;03/19/2007 2 ;;1.6;HEALTH LEVEL SEVEN;**126,134**;Oct 13, 1995;Build 30 3 ;Per VHA Directive 2004-038, this routine should not be modified 4 ; 5 EN ; 6 D WAIT^DICD 7 D EN^VALM("HLO MESSAGE VIEWER") 8 Q 9 ; 10 SHOWLIST(TYPE) ; 11 ;TYPE= "SE", "AE", "TF" 12 N PARMS,I,ERRCOUNT 13 S (VALMBG,VALMCNT,I,ERRCOUNT)=0 14 D CLEAN^VALM10 15 S VALMBG=1 16 I '$$ASKPARMS(.PARMS) S VALMBCK="" Q 17 I PARMS("ALL") D 18 .N APP 19 .S APP="" 20 .F S APP=$O(^HLB("ERRORS",TYPE,APP)) Q:APP="" D Q:ERRCOUNT>PARMS("MAX") 21 ..N TIME,IEN 22 ..S TIME=PARMS("START") 23 ..Q:($O(^HLB("ERRORS",TYPE,APP,TIME))="") 24 ..S @VALMAR@($$I,0)="Application: "_APP 25 ..D CNTRL^VALM10(VALMCNT,14,$L(APP),IOINHI,IOINORM) 26 ..F S TIME=$O(^HLB("ERRORS",TYPE,APP,TIME)) Q:'TIME Q:ERRCOUNT>PARMS("MAX") S IEN="" F S IEN=$O(^HLB("ERRORS",TYPE,APP,TIME,IEN)) Q:IEN="" D ADDTO(TYPE,IEN,TIME,.ERRCOUNT) Q:ERRCOUNT>PARMS("MAX") 27 E D 28 .N APP 29 .S APP=PARMS("APP") 30 .N TIME,IEN 31 .S TIME=PARMS("START") 32 .Q:$O(^HLB("ERRORS",TYPE,APP,TIME))="" 33 .S @VALMAR@($$I,0)="Application: "_APP 34 .D CNTRL^VALM10(VALMCNT,14,$L(APP),IOINHI,IOINORM) 35 .F S TIME=$O(^HLB("ERRORS",TYPE,APP,TIME)) Q:'TIME Q:ERRCOUNT>PARMS("MAX") S IEN="" F S IEN=$O(^HLB("ERRORS",TYPE,APP,TIME,IEN)) Q:IEN="" D ADDTO(TYPE,IEN,TIME,.ERRCOUNT) Q:ERRCOUNT>PARMS("MAX") 36 ; 37 SHOW S VALMBCK="R" 38 ; 39 Q 40 ADDTO(LTYPE,IEN,TIME,ERRCOUNT) ; 41 N NODE,MSG 42 Q:'$$GETMSG^HLOMSG(+IEN,.MSG) 43 S ERRCOUNT=ERRCOUNT+1 44 I LTYPE'="AE" D 45 .N TYPE 46 .S TYPE=$S(MSG("BATCH"):"BATCH",1:MSG("MESSAGE TYPE")_"~"_MSG("EVENT")) 47 .S @VALMAR@($$I,0)=" "_$$LJ(MSG("ID"),15)_$$LJ(TYPE,8)_$$LJ($$FMTE^XLFDT(TIME,2),20)_MSG("STATUS","ERROR TEXT") 48 .D CNTRL^VALM10(VALMCNT,3,15,IOINHI,IOINORM) 49 .S:MSG("ID")]"" @VALMAR@("INDEX",MSG("ID"))=IEN 50 E D 51 .;application errors - could be an error to a msg within a batch 52 .;also, need to go to the ack msg to get the error text from the MSA segment 53 .; 54 .N SUBIEN,MSA,ERRTEXT 55 .S (ERRTEXT,MSA)="" 56 .S SUBIEN=$P(IEN,"^",2) 57 .;within batch? 58 .D:SUBIEN GETMSGB^HLOMSG1(.MSG,SUBIEN,.MSG) 59 .S ERRTEXT=MSG("STATUS","ERROR TEXT") 60 .I ERRTEXT="",MSG("ACK BY")]"",($$FINDMSG^HLOMSG1(MSG("ACK BY"),.LIST)=1) D 61 ..N MSG,SEG,FS,AIEN 62 ..S AIEN=+LIST(1),SUBIEN=$P(LIST(1),"^",2) 63 ..Q:'$$GETMSG^HLOMSG(AIEN,.MSG) 64 ..I SUBIEN S MSG("BATCH","CURRENT MESSAGE")=SUBIEN,MSG("LINE COUNT")=0 65 ..F Q:'$$HLNEXT^HLOMSG(.MSG,.SEG) I $E(SEG(1),1,3)="MSA" S MSA=SEG(1),FS=$E(MSA,4),ERRTEXT=$P(MSA,FS,4) Q 66 .S @VALMAR@($$I,0)=" "_$$LJ(MSG("ID"),15)_$$LJ(MSG("MESSAGE TYPE")_"~"_MSG("EVENT"),8)_$$LJ($$FMTE^XLFDT(MSG("DT/TM CREATED"),2),20)_$E(ERRTEXT,1,37) 67 .D CNTRL^VALM10(VALMCNT,3,15,IOINHI,IOINORM) 68 .I $L(ERRTEXT)>37 D 69 ..S @VALMAR@($$I,0)="~"_$E(ERRTEXT,38,112) 70 ..D CNTRL^VALM10(VALMCNT,1,1,IORVON,IORVOFF) 71 .S:MSG("ID")]"" @VALMAR@("INDEX",MSG("ID"))=IEN 72 Q 73 ; 74 ASKPARMS(PARMS) ; 75 K PARMS 76 S PARMS("START")=$$ASKBEGIN("T-1") 77 I 'PARMS("START") Q 0 78 S PARMS("MAX")=$$ASKMAX() 79 Q:'(PARMS("MAX")>-1) 0 80 S PARMS("ALL")=$$ASKYESNO("Include ALL applications","YES") 81 I PARMS("ALL") Q 1 82 I PARMS("ALL")="" Q 0 83 S PARMS("APP")=$$ASKAPP 84 I PARMS("APP")="" Q 0 85 Q 1 86 ; 87 ASKMAX() ; 88 N DIR 89 S DIR(0)="N^1:30000:0" 90 S DIR("A")="Maximum List Size" 91 S DIR("B")=1000 92 S DIR("?",1)="In case a large number of errors meet your search criteria, what are the" 93 S DIR("?")="maximum number of errors to display? (30,000 maximum)" 94 D ^DIR 95 Q:$D(DTOUT)!$D(DUOUT) -1 96 Q X-1 97 ASKAPP() ; 98 D FULL^VALM1 99 S VALMBCK="R" 100 N DIR 101 S DIR(0)="F^3:60" 102 S DIR("A")="Application" 103 S DIR("?")="Enter the full name of the application, or '^' to exit." 104 S DIR("?",1)="For transmission failures, enter the sending application. " 105 S DIR("?",2)="For other errors, enter the name of the receiving application. " 106 D ^DIR 107 I $D(DIRUT)!(Y="") Q "" 108 Q Y 109 ; 110 ASKYESNO(PROMPT,DEFAULT) ; 111 ;Description: Displays PROMPT, appending '?'. Expects a YES NO response 112 ;Input: 113 ; PROMPT - text to display as prompt. Appends '?' 114 ; DEFAULT - (optional) YES or NO. If not passed, defaults to YES 115 ;Output: 116 ; Function value: 1 if yes, 0 if no, "" if '^' entered or timeout 117 ; 118 N DIR,Y 119 S DIR(0)="Y" 120 S DIR("A")=PROMPT 121 S DIR("B")=$S($G(DEFAULT)="NO":"NO",1:"YES") 122 D ^DIR 123 Q:$D(DIRUT) "" 124 Q Y 125 ; 126 STRTSTPQ ; 127 ;action to start or stop a queue, either incoming or outgoing 128 ; 129 N STOP,INOROUT,QUE 130 S VALMBCK="R" 131 D FULL^VALM1 132 ;ask if stop or start 133 D Q:STOP="" 134 .N DIR 135 .S DIR(0)="S^1:START;2:STOP" 136 .S DIR("A")="Do you want to START or STOP a queue" 137 .S DIR("B")="1" 138 .D ^DIR 139 .S STOP=$S(Y=1:0,Y=2:1,1:"") 140 ;ask if in or out 141 D Q:INOROUT="" 142 .N DIR 143 .S DIR(0)="S^I:INCOMING;O:OUTGOING" 144 .S DIR("A")="Do you want to "_$S(STOP:"stop",1:"start")_" an incoming queue or an outgoing queue" 145 .S DIR("B")="I" 146 .D ^DIR 147 .S INOROUT=$S(Y="I":"IN",Y="O":"OUT",1:"") 148 S QUE=$$ASKQUE(INOROUT) 149 Q:QUE="" 150 I STOP=$$STOPPED^HLOQUE(INOROUT,QUE) D 151 .N C 152 .I STOP D 153 ..W !,"That queue is already stopped!" 154 .E W !,"That queue is not stopped!" 155 .W !,IOINHI,"Hit any key to continue...",IOINORM 156 .R *C:DTIME 157 E D 158 .N C 159 .D:STOP STOPQUE^HLOQUE(INOROUT,QUE) 160 .D:'STOP STARTQUE^HLOQUE(INOROUT,QUE) 161 .W !,"DONE!" 162 .W !,IOINHI,"Hit any key to continue...",IOINORM 163 .R *C:DTIME 164 .D @HLRFRSH 165 Q 166 ; 167 ASKQUE(DIR) ; 168 N QUEUE 169 AGAIN W !,"Enter the full, exact name of queue:" 170 S QUEUE="" 171 R QUEUE:60 I '$T Q "" 172 I $E(QUEUE)="?" W !,"Each message is placed on a queue that has an arbitrary name up to 20",!,"characters long." I $$ASKYESNO("Would you like to see a list of the queues that currently exist","NO") D G AGAIN 173 .N SUB,QUE,QUIT,COUNT 174 .K ^TMP($J,"HLO QUEUES") 175 .S SUB="" 176 .F S SUB=$O(^HLB("QUEUE",DIR,SUB)) Q:SUB="" D 177 ..S QUE="" 178 ..F S QUE=$O(^HLB("QUEUE",DIR,SUB,QUE)) Q:QUE="" S ^TMP($J,"HLO QUEUES",QUE)="" 179 .S QUE="" 180 .S IOSL=$G(IOSL,20) 181 .S (COUNT,QUIT)=0 182 .W ! 183 .F S QUE=$O(^TMP($J,"HLO QUEUES",QUE)) Q:QUE="" Q:QUIT D 184 ..W !,QUE 185 ..S COUNT=COUNT+1 186 ..I COUNT>(IOSL-3) D 187 ...N Y 188 ...D PAUSE^VALM1 189 ...I 'Y S QUIT=1 190 ...S COUNT=0 191 .W ! 192 .K ^TMP($J,"HLO QUEUES") 193 Q:$E(QUEUE)="?" "" 194 Q:$E(QUEUE)="^" "" 195 Q QUEUE 196 ; 197 ASKBEGIN(DEFAULT) ; 198 ;Description: Asks the user to enter a beginning date. 199 ;Input: DEFAULT - the suggested default dt/time (optional) 200 ;Output: Returns the date as the function value, or 0 if the user does not select a date 201 ; 202 ; 203 N %DT 204 S %DT="AEST" 205 S %DT("A")="Enter the beginning date/time: " 206 S %DT("B")=$$FMTE^XLFDT($S($L($G(DEFAULT)):DEFAULT,1:$$FMADD^XLFDT(DT,-1))) 207 S %DT(0)="-NOW" 208 Q:$D(DTOUT) 0 209 D ^%DT 210 I Y=-1 Q 0 211 Q Y 212 ; 213 ASKEND(BEGIN) ; 214 ;Description: Asks the user to enter an ending date/time 215 ;Input: BEGIN - the earliest date/time allowed 216 ;Output: Returns the date as the function value, or 0 if the user does not select a date/time 217 ; 218 N %DT 219 S %DT="AEST" 220 S %DT("A")="Enter the ending date/time: " 221 S %DT("B")="NOW" 222 S %DT(0)=BEGIN 223 Q:$D(DTOUT) 0 224 D ^%DT 225 I Y=-1 Q 0 226 Q Y 227 ; 228 LJ(STRING,LEN) ; 229 Q $$LJ^XLFSTR(STRING,LEN) 230 ; 231 I() ; 232 S VALMCNT=VALMCNT+1 233 Q VALMCNT 234 ; 235 HEADER ; 236 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLTF.m
r613 r623 1 HLTF ;AISC/SAW,JRP-Create/Process Message Text File Entries ;10/17/2007 09:41 2 ;;1.6;HEALTH LEVEL SEVEN;**1,19,43,55,109,120,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 Q 6 ; 7 FILE ;Create Entries in files 772 and 773 for Version 1.5 Interface Only 8 D CREATE(,.HLDA,.HLDT,.HLDT1) 9 Q 10 CREATE(HLMID,MTIEN,HLDT,HLDT1) ;Create entries in Message Text (#772) 11 ; 12 ;Input : HLMID = Variable in which value of message ID will be 13 ; returned (pass by reference) 14 ; MTIEN = Variable in which IEN of Message Text file entry 15 ; will be returned (pass by reference) 16 ; HLDT = Variable in which current date/time in FM internal 17 ; format will be returned (pass by reference) 18 ; HLDT1 = Variable in which current date/time in HL7 format 19 ; will be returned (pass by reference) 20 ; 21 ;Output : See above 22 ; 23 ;Notes : If HLDT has a value [upon entry], the created entries will 24 ; be given that value for their date/time (value of .01) 25 ; : Current date/time used if HLDT is not passed or invalid 26 ; 27 ;Make entry in Message Administration file 28 N Y 29 S HLDT=$G(HLDT) 30 D MT(.HLDT) 31 S Y=$$CHNGMID(MTIEN,.HLMID),HLDT1=$$HLDATE^HLFNC(HLDT) 32 Q 33 TCP(HLMID,MTIEN,HLDT) ;create new message in 772 & 773 entries 34 ;used for incoming messages and outgoing responses 35 ;Input : HLMID = Variable in which value of message ID will be 36 ; returned (pass by reference) 37 ; MTIEN = Variable in which IEN of file 773 entry 38 ; will be returned (pass by reference) 39 ; HLDT = Variable in which current date/time in FM internal 40 ; format will be returned (pass by reference) 41 ; 42 S HLDT=$G(HLDT),HLMID=$G(HLMID) 43 D MT(.HLDT) 44 S MTIEN=$$MA(MTIEN,.HLMID) 45 Q 46 ; 47 MT(HLX) ;Create entry in Message Text file (#772) 48 ; 49 ;Input : HLX = Date/time entry in file should be given (value of .01) 50 ; Defaults to current date/time 51 ; 52 ;Output : HLDT = Date/time of created entry (value of .01) 53 ; : HLDT1 = HLDT in HL7 format 54 ; 55 ;Notes : HLX must be in FileMan format (default value used if not) 56 ; : HLDT will be in FileMan format 57 ; : MTIEN is ien in file 772 58 ; 59 ;Check for input 60 S HLX=$G(HLX) 61 ;Declare variables 62 N DIC,DD,DO,HLCNT,HLJ,X,Y 63 F HLCNT=0:1 D Q:Y>0 H HLCNT 64 . I (HLX'?7N.1".".6N) S HLX=$$NOW^XLFDT 65 . S DIC="^HL(772,",DIC(0)="L",(HLDT,X)=HLX 66 . S Y=$$STUB772(X) ; This call substituted for D FILE^DICN by HL*1.6*109 67 . ;Entry not created - try again 68 . I Y<0 S HLX="" Q 69 . S MTIEN=+Y 70 ;***If we didn't get a record in 772, need to do something 71 I Y<0 Q 72 S HLDT1=$$HLDATE^HLFNC(HLDT) 73 Q 74 ;add to Message Admin file #773 75 MA(X,HLMID) ;X=ien in file 772, HLMID=msg. id (passed by ref.) 76 ;return ien in file 773 77 ; 78 ; patch HL*1.6*122: MPI-client/server start 79 F L +^HL(772,+$G(X)):10 Q:$T H 1 80 Q:'$G(^HL(772,X,0)) 0 81 L -^HL(772,+$G(X)) 82 ; patch HL*1.6*122: MPI-client/server end 83 ; 84 N DA,DD,DO,DIC,DIE,DR,HLDA,HLCNT,HLJ,Y 85 S DIC="^HLMA(",DIC(0)="L" 86 F HLCNT=0:1 D Q:Y>0 H HLCNT 87 . S Y=$$STUB773(X) ; This call substituted for D FILE^DICN by HL*1.6*109 88 ;***If we didn't get a record in 773, need to do something 89 I Y<0 Q 0 90 S HLDA=+Y,HLMID=$$MAID(HLDA,$G(HLMID)) 91 Q HLDA 92 ; 93 MAID(Y,HLMID) ;Determine message ID (if needed) & store message ID 94 ;Y=ien in 773, HLMID=id, Output message id 95 N HLJ 96 ;need to have id contain institution number to make unique 97 S:$G(HLMID)="" HLMID=+$P($$PARAM^HLCS2,U,6)_Y 98 S HLJ(773,Y_",",2)=HLMID 99 D FILE^HLDIE("","HLJ","","MAID","HLTF") ;HL*1.6*109 100 Q HLMID 101 ; 102 CHNGMID(PTRMT,NEWID) ;Change message ID for entry in Message Text file 103 ;Input : PTRMT - Pointer to entry in Message Text file (#772) 104 ; NEWID - New message ID 105 ;Output : 0 = Success 106 ; -1^ErrorText = Error/Bad input 107 ; 108 ;Check input 109 S PTRMT=+$G(PTRMT) 110 S NEWID=$G(NEWID) 111 Q:('$D(^HL(772,PTRMT,0))) "-1^Did not pass valid pointer to Message Text file (#772)" 112 N HLJ 113 I $G(NEWID)="" S NEWID=+$P($$PARAM^HLCS2,U,6)_PTRMT 114 S HLJ(772,PTRMT_",",6)=NEWID 115 D FILE^HLDIE("","HLJ","","CHNGMID","HLTF") ; HL*1.6*109 116 Q 0 117 ; 118 OUT(HLDA,HLMID,HLMTN) ;File Data in Message Text File for Outgoing Message 119 ;Version 1.5 Interface Only 120 ; 121 ; patch HL*1.6*122: HLTF routine splitted, moves sub-routines, 122 ; OUT, IN, and ACK to HLTF2 routine. 123 ; 124 D OUT^HLTF2($G(HLDA),$G(HLMID),$G(HLMTN)) 125 Q 126 ; 127 IN(HLMTN,HLMID,HLTIME) ;File Data in Message Text File for Incoming Message 128 ;Version 1.5 Interface Only 129 ; 130 ; patch HL*1.6*122: HLTF routine splitted, moves sub-routines, 131 ; OUT, IN, and ACK to HLTF2 routine. 132 ; 133 D IN^HLTF2($G(HLMTN),$G(HLMID),$G(HLTIME)) 134 Q 135 ; 136 ACK(HLMSA,HLIO,HLDA) ;Process 'ACK' Message Type - Version 1.5 Interface Only 137 ; 138 ; patch HL*1.6*122: HLTF routine splitted, moves sub-routines, 139 ; OUT, IN, and ACK to HLTF2 routine. 140 ; 141 D ACK^HLTF2($G(HLMSA),$G(HLIO),$G(HLDA)) 142 Q 143 ; 144 STUB772(FLD01,OS) ; 145 ;This function creates a new stub record in file 772. The Stub record may consist of only the 0 node with a value of "^". If a value is passed in for the .01 field it will be included in the 0 node and its "B" x-ref set. 146 ;Inputs: 147 ; OS (optional), the value of ^%ZOSF("OS") 148 ; FLD01 (optional), the value for the .01 field 149 ;Output - the function returns the ien of the newly created record 150 ; 151 N IEN 152 I '$L($G(OS)) N OS S OS=$G(^%ZOSF("OS")) 153 ; 154 I OS'["DSM",OS'["OpenM" D 155 .F L +^HLCS(869.3,1,772):10 S IEN=+$G(^HLCS(869.3,1,772))+1,^HLCS(869.3,1,772)=IEN S:$D(^HL(772,IEN)) IEN=0,^HLCS(869.3,1,772)=($O(^HL(772,":"),-1)\1) L -^HLCS(869.3,1,772) Q:IEN 156 E D 157 .F S IEN=$I(^HLCS(869.3,1,772),1) S:$D(^HL(772,IEN)) IEN=0,^HLCS(869.3,1,772)=($O(^HL(772,":"),-1)\1) Q:IEN 158 ; 159 ; patch HL*1.6*122: MPI-client/server start 160 F L +^HL(772,IEN):10 Q:$T H 1 161 S ^HL(772,IEN,0)=$G(FLD01)_"^" 162 I $L($G(FLD01)) S ^HL(772,"B",FLD01,IEN)="" 163 L -^HL(772,IEN) 164 ; patch HL*1.6*122: MPI-client/server end 165 ; 166 Q IEN 167 ; 168 STUB773(FLD01,OS) ; 169 ;This function creates a new stub record in file 772. The Stub record may consist of only the 0 node with a value of "^". If a value is passed in for the .01 field it will be included in the 0 node and its "B" x-ref set. 170 ;Inputs: 171 ; OS (optional), the value of ^%ZOSF("OS") 172 ; FLD01 (optional), the value for the .01 field 173 ;Output - the function returns the ien of the newly created record 174 ; 175 N IEN 176 I '$L($G(OS)) N OS S OS=$G(^%ZOSF("OS")) 177 ; 178 I OS'["DSM",OS'["OpenM" D 179 .F L +^HLCS(869.3,1,773):10 S IEN=+$G(^HLCS(869.3,1,773))+1,^HLCS(869.3,1,773)=IEN S:$D(^HLMA(IEN)) IEN=0,^HLCS(869.3,1,773)=($O(^HLMA(":"),-1)\1) L -^HLCS(869.3,1,773) Q:IEN 180 E D 181 .F S IEN=$I(^HLCS(869.3,1,773),1) S:$D(^HLMA(IEN)) IEN=0,^HLCS(869.3,1,773)=($O(^HLMA(":"),-1)\1) Q:IEN 182 ; 183 ; patch HL*1.6*122: MPI-client/server 184 F L +^HLMA(IEN):10 Q:$T H 1 185 S ^HLMA(IEN,0)=$G(FLD01)_"^" 186 I $L($G(FLD01)) S ^HLMA("B",FLD01,IEN)="" 187 L -^HLMA(IEN) 188 ; 189 Q IEN 1 HLTF ;AISC/SAW,JRP-Create/Process Message Text File Entries ;01/23/06 12:56 2 ;;1.6;HEALTH LEVEL SEVEN;**1,19,43,55,109,120**;Oct 13, 1995;Build 12 3 FILE ;Create Entries in files 772 and 773 for Version 1.5 Interface Only 4 D CREATE(,.HLDA,.HLDT,.HLDT1) 5 Q 6 CREATE(HLMID,MTIEN,HLDT,HLDT1) ;Create entries in Message Text (#772) 7 ; 8 ;Input : HLMID = Variable in which value of message ID will be 9 ; returned (pass by reference) 10 ; MTIEN = Variable in which IEN of Message Text file entry 11 ; will be returned (pass by reference) 12 ; HLDT = Variable in which current date/time in FM internal 13 ; format will be returned (pass by reference) 14 ; HLDT1 = Variable in which current date/time in HL7 format 15 ; will be returned (pass by reference) 16 ; 17 ;Output : See above 18 ; 19 ;Notes : If HLDT has a value [upon entry], the created entries will 20 ; be given that value for their date/time (value of .01) 21 ; : Current date/time used if HLDT is not passed or invalid 22 ; 23 ;Make entry in Message Administration file 24 N Y 25 S HLDT=$G(HLDT) 26 D MT(.HLDT) 27 S Y=$$CHNGMID(MTIEN,.HLMID),HLDT1=$$HLDATE^HLFNC(HLDT) 28 Q 29 TCP(HLMID,MTIEN,HLDT) ;create new message in 772 & 773 entries 30 ;used for incoming messages and outgoing responses 31 ;Input : HLMID = Variable in which value of message ID will be 32 ; returned (pass by reference) 33 ; MTIEN = Variable in which IEN of file 773 entry 34 ; will be returned (pass by reference) 35 ; HLDT = Variable in which current date/time in FM internal 36 ; format will be returned (pass by reference) 37 ; 38 S HLDT=$G(HLDT),HLMID=$G(HLMID) 39 D MT(.HLDT) 40 S MTIEN=$$MA(MTIEN,.HLMID) 41 Q 42 ; 43 MT(HLX) ;Create entry in Message Text file (#772) 44 ; 45 ;Input : HLX = Date/time entry in file should be given (value of .01) 46 ; Defaults to current date/time 47 ; 48 ;Output : HLDT = Date/time of created entry (value of .01) 49 ; : HLDT1 = HLDT in HL7 format 50 ; 51 ;Notes : HLX must be in FileMan format (default value used if not) 52 ; : HLDT will be in FileMan format 53 ; : MTIEN is ien in file 772 54 ; 55 ;Check for input 56 S HLX=$G(HLX) 57 ;Declare variables 58 N DIC,DD,DO,HLCNT,HLJ,X,Y 59 F HLCNT=0:1 D Q:Y>0 H HLCNT 60 . I (HLX'?7N.1".".6N) S HLX=$$NOW^XLFDT 61 . S DIC="^HL(772,",DIC(0)="L",(HLDT,X)=HLX 62 . S Y=$$STUB772(X) ; This call substituted for D FILE^DICN by HL*1.6*109 63 . ;Entry not created - try again 64 . I Y<0 S HLX="" Q 65 . S MTIEN=+Y 66 ;***If we didn't get a record in 772, need to do something 67 I Y<0 Q 68 S HLDT1=$$HLDATE^HLFNC(HLDT) 69 Q 70 ;add to Message Admin file #773 71 MA(X,HLMID) ;X=ien in file 772, HLMID=msg. id (passed by ref.) 72 ;return ien in file 773 73 Q:'$G(^HL(772,X,0)) 0 74 N DA,DD,DO,DIC,DIE,DR,HLDA,HLCNT,HLJ,Y 75 S DIC="^HLMA(",DIC(0)="L" 76 F HLCNT=0:1 D Q:Y>0 H HLCNT 77 . S Y=$$STUB773(X) ; This call substituted for D FILE^DICN by HL*1.6*109 78 ;***If we didn't get a record in 773, need to do something 79 I Y<0 Q 0 80 S HLDA=+Y,HLMID=$$MAID(HLDA,$G(HLMID)) 81 Q HLDA 82 ; 83 MAID(Y,HLMID) ;Determine message ID (if needed) & store message ID 84 ;Y=ien in 773, HLMID=id, Output message id 85 N HLJ 86 ;need to have id contain institution number to make unique 87 S:$G(HLMID)="" HLMID=+$P($$PARAM^HLCS2,U,6)_Y 88 S HLJ(773,Y_",",2)=HLMID 89 D FILE^HLDIE("","HLJ","","MAID","HLTF") ;HL*1.6*109 90 Q HLMID 91 ; 92 CHNGMID(PTRMT,NEWID) ;Change message ID for entry in Message Text file 93 ;Input : PTRMT - Pointer to entry in Message Text file (#772) 94 ; NEWID - New message ID 95 ;Output : 0 = Success 96 ; -1^ErrorText = Error/Bad input 97 ; 98 ;Check input 99 S PTRMT=+$G(PTRMT) 100 S NEWID=$G(NEWID) 101 Q:('$D(^HL(772,PTRMT,0))) "-1^Did not pass valid pointer to Message Text file (#772)" 102 N HLJ 103 I $G(NEWID)="" S NEWID=+$P($$PARAM^HLCS2,U,6)_PTRMT 104 S HLJ(772,PTRMT_",",6)=NEWID 105 D FILE^HLDIE("","HLJ","","CHNGMID","HLTF") ; HL*1.6*109 106 Q 0 107 ; 108 OUT(HLDA,HLMID,HLMTN) ;File Data in Message Text File for Outgoing Message 109 ;Version 1.5 Interface Only 110 Q:'$D(HLFS) 111 ; 112 I HLMTN="ACK"!(HLMTN="MCF")!(HLMTN="ORR") Q:'$D(HLMSA) D ACK(HLMSA,"I") Q 113 ; 114 ;-- if message contained MSA find inbound message 115 I $D(HLMSA),$D(HLNDAP),$P(HLMSA,HLFS,3)]"" D 116 . N HLDAI 117 . S HLDAI=0 118 . F S HLDAI=$O(^HL(772,"AH",+$P($G(HLNDAP0),U,12),$P(HLMSA,HLFS,3),HLDAI)) Q:'HLDAI!($P($G(^HL(772,+HLDAI,0)),U,4)="I") 119 . I 'HLDAI K HLDAI 120 ; 121 D STUFF^HLTF0("O") 122 ; 123 N HLAC S HLAC=$S($D(HLERR):4,'$P(HLNDAP0,"^",10):1,1:2) D STATUS^HLTF0(HLDA,HLAC,$G(HLMSG)) 124 D:$D(HLCHAR) STATS^HLTF0(HLDA,HLCHAR,$G(HLEVN)) 125 ; 126 ;-- update status if MSA and found inbound message 127 I $D(HLMSA),$D(HLDAI) D 128 .N HLERR,HLMSG I $P(HLMSA,HLFS,4)]"" S HLERR=$P(HLMSA,HLFS,4) 129 .S HLAC=$P(HLMSA,HLFS,2) 130 .I HLAC'="AA" S HLMSG=$S(HLAC="AR":"Application Reject",HLAC="AE":"Application Error",1:"")_" - "_HLERR 131 .S HLAC=$S(HLAC'="AA":4,1:3) D STATUS^HLTF0(HLDAI,HLAC,$G(HLMSG)) 132 Q 133 ; 134 IN(HLMTN,HLMID,HLTIME) ;File Data in Message Text File for Incoming Message 135 ;Version 1.5 Interface Only 136 Q:'$D(HLFS) 137 I HLMTN="ACK"!(HLMTN="MCF")!(HLMTN="ORR") Q:'$D(HLMSA) D ACK(HLMSA,"O",$G(HLDA)) Q 138 ; 139 N HLDAI S HLDA=0 140 I $D(HLNDAP),HLMID]"" D 141 .F S HLDA=+$O(^HL(772,"AH",+$P($G(HLNDAP0),U,12),HLMID,HLDA)) Q:'HLDA!($P($G(^HL(772,+HLDA,0)),U,4)="I") 142 .I HLDA D 143 ..S HLDT=+$P($G(^HL(772,HLDA,0)),"^"),HLDT1=$$HLDATE^HLFNC(HLDT) 144 ..K ^HL(772,HLDA,"IN") 145 .I $D(HLMSA),$P(HLMSA,HLFS,3)]"" D 146 ..S HLDAI=0 147 ..F S HLDAI=$O(^HL(772,"AH",+$P($G(HLNDAP0),U,12),$P(HLMSA,HLFS,3),HLDAI)) Q:'HLDAI!($P($G(^HL(772,+HLDAI,0)),U,4)="O") 148 ..I 'HLDAI K HLDAI 149 ; 150 I 'HLDA D CREATE(.HLMID,.HLDA,.HLDT,.HLDT1) K HLZ 151 ; 152 D STUFF^HLTF0("I") 153 N HLAC S HLAC=$S($D(HLERR):4,1:1) D STATUS^HLTF0(HLDA,HLAC,$G(HLMSG)) 154 ; 155 D MERGE15^HLTF1("G",HLDA,"HLR",HLTIME) 156 ; 157 I '$D(HLERR),$D(HLMSA),$D(HLDAI) D 158 .N HLAC,HLERR,HLMSG I $P(HLMSA,HLFS,4)]"" S HLERR=$P(HLMSA,HLFS,4) 159 .S HLAC=$P(HLMSA,HLFS,2) I HLAC'="AA" S HLMSG=$S(HLAC="AR":"Application Reject",1:"Application Error")_" - "_HLERR 160 .S HLAC=$S(HLAC'="AA":4,1:3) D STATUS^HLTF0(HLDAI,HLAC,$G(HLMSG)) 161 Q 162 ; 163 ACK(HLMSA,HLIO,HLDA) ;Process 'ACK' Message Type - Version 1.5 Interface Only 164 ; To determine the correct message to link the ACK, HLIO is used. 165 ; For an ack from DHCP (original message from remote system) then 166 ; HLIO should be "I" so that the correct inbound message is ack-ed. For 167 ; an inbound ack (original message outbound from DHCP) HLIO should be 168 ; "O". This distinction must be made due to the possible duplicate 169 ; message ids from a bi-direction interface. 170 ; 171 ; Input : MSA - MSA from ACK message. 172 ; HLIO - Either "I" or "O" : See note above. 173 ;Output : None 174 ; 175 N HLAC,HLMIDI 176 ;-- set up required vars 177 S HLAC=$P(HLMSA,HLFS,2),HLMIDI=$P(HLMSA,HLFS,3) 178 ;-- quit 179 Q:HLMIDI']""!(HLAC']"")!('$D(HLNDAP)) 180 ;-- find message to ack 181 I '$G(HLDA) S HLDA=0 D 182 . F S HLDA=+$O(^HL(772,"AH",+$P($G(HLNDAP0),U,12),HLMIDI,HLDA)) Q:'HLDA!($P($G(^HL(772,+HLDA,0)),U,4)=HLIO) 183 ;-- quit if no message 184 Q:'$D(^HL(772,+HLDA,0)) 185 ;-- check for error 186 I $P(HLMSA,HLFS,4)]"" N HLERR S HLERR=$P(HLMSA,HLFS,4) 187 I $D(HLERR),'$D(HLMSG) N HLMSG S HLMSG="Error During Receipt of Acknowledgement Message"_$S(HLAC="AR":" - Application Reject",HLAC="AE":" - Application Error",1:"")_" - "_HLERR 188 ;-- update status 189 S HLAC=$S(HLMTN="MCF":2,HLAC'="AA":4,1:3) 190 D STATUS^HLTF0(HLDA,HLAC,$G(HLMSG)) 191 Q 192 ; 193 STUB772(FLD01,OS) ; 194 ;This function creates a new stub record in file 772. The Stub record may consist of only the 0 node with a value of "^". If a value is passed in for the .01 field it will be included in the 0 node and its "B" x-ref set. 195 ;Inputs: 196 ; OS (optional), the value of ^%ZOSF("OS") 197 ; FLD01 (optional), the value for the .01 field 198 ;Output - the function returns the ien of the newly created record 199 ; 200 N IEN 201 I '$L($G(OS)) N OS S OS=$G(^%ZOSF("OS")) 202 ; 203 ; patch HL*1.6*120, protect Else command 204 ; I OS'["DSM",OS'["OpenM" D 205 I OS'["DSM",OS'["OpenM" D I 1 206 .F L +^HLCS(869.3,1,772):10 S IEN=+$G(^HLCS(869.3,1,772))+1,^HLCS(869.3,1,772)=IEN S:$D(^HL(772,IEN)) IEN=0,^HLCS(869.3,1,772)=($O(^HL(772,":"),-1)\1) L -^HLCS(869.3,1,772) Q:IEN 207 E D 208 .F S IEN=$I(^HLCS(869.3,1,772),1) S:$D(^HL(772,IEN)) IEN=0,^HLCS(869.3,1,772)=($O(^HL(772,":"),-1)\1) Q:IEN 209 S ^HL(772,IEN,0)=$G(FLD01)_"^" 210 I $L($G(FLD01)) S ^HL(772,"B",FLD01,IEN)="" 211 Q IEN 212 ; 213 STUB773(FLD01,OS) ; 214 ;This function creates a new stub record in file 772. The Stub record may consist of only the 0 node with a value of "^". If a value is passed in for the .01 field it will be included in the 0 node and its "B" x-ref set. 215 ;Inputs: 216 ; OS (optional), the value of ^%ZOSF("OS") 217 ; FLD01 (optional), the value for the .01 field 218 ;Output - the function returns the ien of the newly created record 219 ; 220 N IEN 221 I '$L($G(OS)) N OS S OS=$G(^%ZOSF("OS")) 222 ; 223 ; patch HL*1.6*120, protect Else command 224 ; I OS'["DSM",OS'["OpenM" D 225 I OS'["DSM",OS'["OpenM" D I 1 226 .F L +^HLCS(869.3,1,773):10 S IEN=+$G(^HLCS(869.3,1,773))+1,^HLCS(869.3,1,773)=IEN S:$D(^HLMA(IEN)) IEN=0,^HLCS(869.3,1,773)=($O(^HLMA(":"),-1)\1) L -^HLCS(869.3,1,773) Q:IEN 227 E D 228 .F S IEN=$I(^HLCS(869.3,1,773),1) S:$D(^HLMA(IEN)) IEN=0,^HLCS(869.3,1,773)=($O(^HLMA(":"),-1)\1) Q:IEN 229 S ^HLMA(IEN,0)=$G(FLD01)_"^" 230 I $L($G(FLD01)) S ^HLMA("B",FLD01,IEN)="" 231 Q IEN -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLTF1.m
r613 r623 1 HLTF1 ;AISC/SAW/MTC-Process Message Text File Entries (Cont'd) ;10/17/2007 09:43 2 ;;1.6;HEALTH LEVEL SEVEN;**5,8,22,25,19,78,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 MERGE15(ARAYTYPE,MTIEN,SUB1,SUB2) ;Merge Local/Global Array From Application into 6 ;Message Text File 7 ; 8 ;This is a routine call with parameter passing. There are no output 9 ;parameters returned by this call. 10 ; 11 ;** Merges incoming data for v1.5 applications only ** 12 ; 13 ;Required input parameters 14 ; MTIEN = The IEN from the Message Text file of the entry to be 15 ; updated 16 ; ARAYTYPE = Array type, G for global or L for local 17 ; SUB1 = The first level subscript of the array. Must be 18 ; either HLS or HLA 19 ;Optional input parameter 20 ; SUB2 = A second subscript associated with the array 21 ; 22 ;Check for required parameters 23 I "GL"'[$G(ARAYTYPE)!($G(SUB1)']"")!('$G(MTIEN)) G MRGE15X 24 ; 25 N HLCHAR,HLEVN,HLFS,I,X,X1,X2,X3 S (HLCHAR,HLEVN,X)=0 26 ; 27 ;Merge data from a global array with two subscript 28 I ARAYTYPE="G",$G(SUB2)'="" D 29 . S X="",I=0 30 . F S X=$O(^TMP(SUB1,$J,SUB2,X)) Q:'X S I=I+1,X1=^TMP(SUB1,$J,SUB2,X),HLCHAR=HLCHAR+$L(X1) S:$E(X1,1,3)="MSH" HLFS=$E(X1,4),$P(X1,HLFS,8)="",HLEVN=HLEVN+1 S ^HL(772,MTIEN,"IN",I,0)=X1 31 ; 32 ;Merge data from a global array with one subscripts 33 I ARAYTYPE="G",$G(SUB2)="" D 34 . S X="",I=0 35 . F S X=$O(^TMP(SUB1,$J,X)) Q:'X S I=I+1,X1=^TMP(SUB1,$J,X),HLCHAR=HLCHAR+$L(X1) S:$E(X1,1,3)="MSH" HLFS=$E(X1,4),$P(X1,HLFS,8)="",HLEVN=HLEVN+1 S ^HL(772,MTIEN,"IN",I,0)=X1 36 ; 37 ;Merge data from a local array with one subscript 38 I ARAYTYPE="L" D 39 . S X="",I=0 40 . F S X=$O(HLA(SUB1,X)) Q:'X S I=I+1,X1=HLA(SUB1,X),HLCHAR=HLCHAR+$L(X1) S:$E(X1,1,3)="MSH" HLFS=$E(X1,4),$P(X1,HLFS,8)="",HLEVN=HLEVN+1 S ^HL(772,MTIEN,"IN",I,0)=X1 41 ; 42 ;-- update 0 node for message text 43 S ^HL(772,MTIEN,"IN",0)="^^"_I_"^"_I_"^"_$$DT^XLFDT_"^" 44 ; 45 ;File message statistics 46 D STATS^HLTF0(MTIEN,HLCHAR,HLEVN) 47 ; 48 MRGE15X ;-- exit merge 49 Q 50 ; 51 MERGE(ARAYTYPE,MTIEN,SUB1,SUB2) ;Merge Local/Global Array From Application into 52 ;Message Text File 53 ; 54 ;This is a routine call with parameter passing. There are no output 55 ;parameters returned by this call. 56 ; 57 ;Required input parameters 58 ; MTIEN = The IEN from the Message Text file of the entry to be 59 ; updated 60 ; ARAYTYPE = Array type, G for global or L for local 61 ; SUB1 = The first level subscript of the array. Must be 62 ; either HLS or HLA 63 ;Optional input parameter 64 ; SUB2 = A second subscript associated with the array 65 ; 66 ;Check for required parameters 67 I "GL"'[$G(ARAYTYPE)!($G(SUB1)']"")!('$G(MTIEN)) G MERGEX 68 ; 69 N HLCHAR,HLEVN,HLFS,I,X,X1,X2,X3 S (HLCHAR,HLEVN,X)=0 70 ; 71 ; patch HL*1.6*122: MPI-client/server 72 F L +^HL(772,+$G(MTIEN)):10 Q:$T H 1 73 ; 74 ;Merge data from a global array with two subscript 75 I ARAYTYPE="G",$G(SUB2)'="" D 76 . S X="",I=0 77 . F S X=$O(^TMP(SUB1,$J,SUB2,X)) Q:'X S I=I+1,X1=^TMP(SUB1,$J,SUB2,X),HLCHAR=HLCHAR+$L(X1) S:$E(X1,1,3)="MSH" HLFS=$E(X1,4),$P(X1,HLFS,8)="",HLEVN=HLEVN+1 S ^HL(772,MTIEN,"IN",I,0)=X1,X2=$D(^TMP(SUB1,$J,SUB2,X)) D 78 .. I X2=11 S X3="" F S X3=$O(^TMP(SUB1,$J,SUB2,X,X3)) Q:'X3 D 79 ... S I=I+1,X1=$G(^TMP(SUB1,$J,SUB2,X,X3)),HLCHAR=HLCHAR+$L(X1),^HL(772,MTIEN,"IN",I,0)=X1 80 .. S I=I+1,^HL(772,MTIEN,"IN",I,0)="" Q 81 ; 82 ;Merge data from a global array with one subscripts 83 I ARAYTYPE="G",$G(SUB2)="" D 84 . S X="",I=0 85 . F S X=$O(^TMP(SUB1,$J,X)) Q:'X S I=I+1,X1=^TMP(SUB1,$J,X),HLCHAR=HLCHAR+$L(X1) S:$E(X1,1,3)="MSH" HLFS=$E(X1,4),$P(X1,HLFS,8)="",HLEVN=HLEVN+1 S ^HL(772,MTIEN,"IN",I,0)=X1,X2=$D(^TMP(SUB1,$J,X)) D 86 .. I X2=11 S X3="" F S X3=$O(^TMP(SUB1,$J,X,X3)) Q:'X3 D 87 ... S I=I+1,X1=$G(^TMP(SUB1,$J,X,X3)),HLCHAR=HLCHAR+$L(X1),^HL(772,MTIEN,"IN",I,0)=X1 88 .. S I=I+1,^HL(772,MTIEN,"IN",I,0)="" Q 89 ; 90 ;Merge data from a local array with one subscript 91 I ARAYTYPE="L" D 92 . S X="",I=0 93 . F S X=$O(HLA(SUB1,X)) Q:'X S I=I+1,X1=HLA(SUB1,X),HLCHAR=HLCHAR+$L(X1) S:$E(X1,1,3)="MSH" HLFS=$E(X1,4),$P(X1,HLFS,8)="",HLEVN=HLEVN+1 S ^HL(772,MTIEN,"IN",I,0)=X1,X2=$D(HLA(SUB1,X)) D 94 .. I X2=11 S X3="" F S X3=$O(HLA(SUB1,X,X3)) Q:'X3 D 95 ... S I=I+1,X1=$G(HLA(SUB1,X,X3)),HLCHAR=HLCHAR+$L(X1),^HL(772,MTIEN,"IN",I,0)=X1 96 .. S I=I+1,^HL(772,MTIEN,"IN",I,0)="" Q 97 ; 98 S:HLEVN=0 HLEVN=1 99 ;X=ien in file 773 for TCP messages 100 S X=+$O(^HLMA("B",MTIEN,0)) 101 ;batch message type 102 I X,$P($G(^HLMA(X,0)),U,5)="B" D BTS 103 I 'X,$P(^HL(772,MTIEN,0),U,8),$P(^HL(772,$P(^(0),U,8),0),U,14)="B" D BTS 104 ; 105 ;-- update 0 node for message text 106 S ^HL(772,MTIEN,"IN",0)="^^"_I_"^"_I_"^"_$$DT^XLFDT_"^" 107 ; 108 ; patch HL*1.6*122: MPI-client/server 109 L -^HL(772,+$G(MTIEN)) 110 ; 111 ;File message statistics 112 D STATS^HLTF0(MTIEN,HLCHAR,HLEVN) 113 ; 114 MERGEX ;-- exit merge 115 Q 116 ; 117 BTS ; create batch trailer seg (BTS) 118 ;HL*1.6*78 to obtain and insert FIELD SEPARATOR, HLFS 119 N HLFS,HLSAN 120 S HLFS=$G(HL("FS")) ; obtain from HL array 121 ; or obtain from sending application; default to "^" 122 I HLFS="" D S:HLFS="" HLFS="^" 123 . S HLSAN=$P($G(^HL(772,MTIEN,0)),U,2) 124 . S:HLSAN HLFS=$G(^HL(771,HLSAN,"FS")) 125 S I=I+1,^HL(772,MTIEN,"IN",I,0)="BTS"_HLFS_HLEVN,I=I+1,^HL(772,MTIEN,"IN",I,0)="" 126 Q 127 ; 128 MRGINT(MTOUT,MTIN,HDR) ;Merge Internal to Internal Message from the 129 ; Outbound message in 772 (MTOUT) to an Inbound entry (MTIN). The process 130 ; will involve Moving the Header and Text into 772. 131 ; 132 ;Required input parameters 133 ; MTOUT= Internal entry number of the Outbound message 134 ; MTIN = Internal entry number of the Inbound message 135 ; HDR = Name of the array that contains HL7 Header segment 136 ; format: HLHDR - Used with indirection to build message in out 137 ; queue 138 ; This routine will first take the header information in the array 139 ; specified by HDR and merge into the Message Text field of file 870. 140 ; Then it will move the message contained in 772 (MTIEN) into 870. 141 ; 142 ;Check for required parameters 143 I '$G(MTOUT)!('$G(MTIN))!(HDR="") Q 144 ; 145 ;-- initilize 146 N I,X 147 S I=0 148 ; 149 ;-- move header into 772 from HDR array 150 S X="" F S X=$O(@HDR@(X)) Q:'X D 151 . S I=I+1,^HL(772,MTIN,"IN",I,0)=@HDR@(X) 152 S I=I+1,^HL(772,MTIN,"IN",I,0)="" 153 ; 154 ;Move data from Message Text (MTOUT) file TO Message Text 772 (MTIN) 155 S X=0 F S X=$O(^HL(772,MTOUT,"IN",X)) Q:X="" S I=I+1 D 156 . S ^HL(772,MTIN,"IN",I,0)=$G(^HL(772,MTOUT,"IN",X,0)) 157 ; 158 ;-- update 0 node of message and format arrays 159 S ^HL(772,MTIN,"IN",0)="^^"_I_"^"_I_"^"_$$DT^XLFDT_"^" 160 ; 161 Q 1 HLTF1 ;AISC/SAW/MTC-Process Message Text File Entries (Cont'd) ;09/10/98 11:21 2 ;;1.6;HEALTH LEVEL SEVEN;**5,8,22,25,19,78**;Oct 13, 1995 3 MERGE15(ARAYTYPE,MTIEN,SUB1,SUB2) ;Merge Local/Global Array From Application into 4 ;Message Text File 5 ; 6 ;This is a routine call with parameter passing. There are no output 7 ;parameters returned by this call. 8 ; 9 ;** Merges incoming data for v1.5 applications only ** 10 ; 11 ;Required input parameters 12 ; MTIEN = The IEN from the Message Text file of the entry to be 13 ; updated 14 ; ARAYTYPE = Array type, G for global or L for local 15 ; SUB1 = The first level subscript of the array. Must be 16 ; either HLS or HLA 17 ;Optional input parameter 18 ; SUB2 = A second subscript associated with the array 19 ; 20 ;Check for required parameters 21 I "GL"'[$G(ARAYTYPE)!($G(SUB1)']"")!('$G(MTIEN)) G MRGE15X 22 ; 23 N HLCHAR,HLEVN,HLFS,I,X,X1,X2,X3 S (HLCHAR,HLEVN,X)=0 24 ; 25 ;Merge data from a global array with two subscript 26 I ARAYTYPE="G",$G(SUB2)'="" D 27 . S X="",I=0 28 . F S X=$O(^TMP(SUB1,$J,SUB2,X)) Q:'X S I=I+1,X1=^TMP(SUB1,$J,SUB2,X),HLCHAR=HLCHAR+$L(X1) S:$E(X1,1,3)="MSH" HLFS=$E(X1,4),$P(X1,HLFS,8)="",HLEVN=HLEVN+1 S ^HL(772,MTIEN,"IN",I,0)=X1 29 ; 30 ;Merge data from a global array with one subscripts 31 I ARAYTYPE="G",$G(SUB2)="" D 32 . S X="",I=0 33 . F S X=$O(^TMP(SUB1,$J,X)) Q:'X S I=I+1,X1=^TMP(SUB1,$J,X),HLCHAR=HLCHAR+$L(X1) S:$E(X1,1,3)="MSH" HLFS=$E(X1,4),$P(X1,HLFS,8)="",HLEVN=HLEVN+1 S ^HL(772,MTIEN,"IN",I,0)=X1 34 ; 35 ;Merge data from a local array with one subscript 36 I ARAYTYPE="L" D 37 . S X="",I=0 38 . F S X=$O(HLA(SUB1,X)) Q:'X S I=I+1,X1=HLA(SUB1,X),HLCHAR=HLCHAR+$L(X1) S:$E(X1,1,3)="MSH" HLFS=$E(X1,4),$P(X1,HLFS,8)="",HLEVN=HLEVN+1 S ^HL(772,MTIEN,"IN",I,0)=X1 39 ; 40 ;-- update 0 node for message text 41 S ^HL(772,MTIEN,"IN",0)="^^"_I_"^"_I_"^"_$$DT^XLFDT_"^" 42 ; 43 ;File message statistics 44 D STATS^HLTF0(MTIEN,HLCHAR,HLEVN) 45 ; 46 MRGE15X ;-- exit merge 47 Q 48 ; 49 MERGE(ARAYTYPE,MTIEN,SUB1,SUB2) ;Merge Local/Global Array From Application into 50 ;Message Text File 51 ; 52 ;This is a routine call with parameter passing. There are no output 53 ;parameters returned by this call. 54 ; 55 ;Required input parameters 56 ; MTIEN = The IEN from the Message Text file of the entry to be 57 ; updated 58 ; ARAYTYPE = Array type, G for global or L for local 59 ; SUB1 = The first level subscript of the array. Must be 60 ; either HLS or HLA 61 ;Optional input parameter 62 ; SUB2 = A second subscript associated with the array 63 ; 64 ;Check for required parameters 65 I "GL"'[$G(ARAYTYPE)!($G(SUB1)']"")!('$G(MTIEN)) G MERGEX 66 ; 67 N HLCHAR,HLEVN,HLFS,I,X,X1,X2,X3 S (HLCHAR,HLEVN,X)=0 68 ; 69 ;Merge data from a global array with two subscript 70 I ARAYTYPE="G",$G(SUB2)'="" D 71 . S X="",I=0 72 . F S X=$O(^TMP(SUB1,$J,SUB2,X)) Q:'X S I=I+1,X1=^TMP(SUB1,$J,SUB2,X),HLCHAR=HLCHAR+$L(X1) S:$E(X1,1,3)="MSH" HLFS=$E(X1,4),$P(X1,HLFS,8)="",HLEVN=HLEVN+1 S ^HL(772,MTIEN,"IN",I,0)=X1,X2=$D(^TMP(SUB1,$J,SUB2,X)) D 73 .. I X2=11 S X3="" F S X3=$O(^TMP(SUB1,$J,SUB2,X,X3)) Q:'X3 D 74 ... S I=I+1,X1=$G(^TMP(SUB1,$J,SUB2,X,X3)),HLCHAR=HLCHAR+$L(X1),^HL(772,MTIEN,"IN",I,0)=X1 75 .. S I=I+1,^HL(772,MTIEN,"IN",I,0)="" Q 76 ; 77 ;Merge data from a global array with one subscripts 78 I ARAYTYPE="G",$G(SUB2)="" D 79 . S X="",I=0 80 . F S X=$O(^TMP(SUB1,$J,X)) Q:'X S I=I+1,X1=^TMP(SUB1,$J,X),HLCHAR=HLCHAR+$L(X1) S:$E(X1,1,3)="MSH" HLFS=$E(X1,4),$P(X1,HLFS,8)="",HLEVN=HLEVN+1 S ^HL(772,MTIEN,"IN",I,0)=X1,X2=$D(^TMP(SUB1,$J,X)) D 81 .. I X2=11 S X3="" F S X3=$O(^TMP(SUB1,$J,X,X3)) Q:'X3 D 82 ... S I=I+1,X1=$G(^TMP(SUB1,$J,X,X3)),HLCHAR=HLCHAR+$L(X1),^HL(772,MTIEN,"IN",I,0)=X1 83 .. S I=I+1,^HL(772,MTIEN,"IN",I,0)="" Q 84 ; 85 ;Merge data from a local array with one subscript 86 I ARAYTYPE="L" D 87 . S X="",I=0 88 . F S X=$O(HLA(SUB1,X)) Q:'X S I=I+1,X1=HLA(SUB1,X),HLCHAR=HLCHAR+$L(X1) S:$E(X1,1,3)="MSH" HLFS=$E(X1,4),$P(X1,HLFS,8)="",HLEVN=HLEVN+1 S ^HL(772,MTIEN,"IN",I,0)=X1,X2=$D(HLA(SUB1,X)) D 89 .. I X2=11 S X3="" F S X3=$O(HLA(SUB1,X,X3)) Q:'X3 D 90 ... S I=I+1,X1=$G(HLA(SUB1,X,X3)),HLCHAR=HLCHAR+$L(X1),^HL(772,MTIEN,"IN",I,0)=X1 91 .. S I=I+1,^HL(772,MTIEN,"IN",I,0)="" Q 92 ; 93 S:HLEVN=0 HLEVN=1 94 ;X=ien in file 773 for TCP messages 95 S X=+$O(^HLMA("B",MTIEN,0)) 96 ;batch message type 97 I X,$P($G(^HLMA(X,0)),U,5)="B" D BTS 98 I 'X,$P(^HL(772,MTIEN,0),U,8),$P(^HL(772,$P(^(0),U,8),0),U,14)="B" D BTS 99 ; 100 ;-- update 0 node for message text 101 S ^HL(772,MTIEN,"IN",0)="^^"_I_"^"_I_"^"_$$DT^XLFDT_"^" 102 ; 103 ;File message statistics 104 D STATS^HLTF0(MTIEN,HLCHAR,HLEVN) 105 ; 106 MERGEX ;-- exit merge 107 Q 108 ; 109 BTS ; create batch trailer seg (BTS) 110 ;HL*1.6*78 to obtain and insert FIELD SEPARATOR, HLFS 111 N HLFS,HLSAN 112 S HLFS=$G(HL("FS")) ; obtain from HL array 113 ; or obtain from sending application; default to "^" 114 I HLFS="" D S:HLFS="" HLFS="^" 115 . S HLSAN=$P($G(^HL(772,MTIEN,0)),U,2) 116 . S:HLSAN HLFS=$G(^HL(771,HLSAN,"FS")) 117 S I=I+1,^HL(772,MTIEN,"IN",I,0)="BTS"_HLFS_HLEVN,I=I+1,^HL(772,MTIEN,"IN",I,0)="" 118 Q 119 ; 120 MRGINT(MTOUT,MTIN,HDR) ;Merge Internal to Internal Message from the 121 ; Outbound message in 772 (MTOUT) to an Inbound entry (MTIN). The process 122 ; will involve Moving the Header and Text into 772. 123 ; 124 ;Required input parameters 125 ; MTOUT= Internal entry number of the Outbound message 126 ; MTIN = Internal entry number of the Inbound message 127 ; HDR = Name of the array that contains HL7 Header segment 128 ; format: HLHDR - Used with indirection to build message in out 129 ; queue 130 ; This routine will first take the header information in the array 131 ; specified by HDR and merge into the Message Text field of file 870. 132 ; Then it will move the message contained in 772 (MTIEN) into 870. 133 ; 134 ;Check for required parameters 135 I '$G(MTOUT)!('$G(MTIN))!(HDR="") Q 136 ; 137 ;-- initilize 138 N I,X 139 S I=0 140 ; 141 ;-- move header into 772 from HDR array 142 S X="" F S X=$O(@HDR@(X)) Q:'X D 143 . S I=I+1,^HL(772,MTIN,"IN",I,0)=@HDR@(X) 144 S I=I+1,^HL(772,MTIN,"IN",I,0)="" 145 ; 146 ;Move data from Message Text (MTOUT) file TO Message Text 772 (MTIN) 147 S X=0 F S X=$O(^HL(772,MTOUT,"IN",X)) Q:X="" S I=I+1 D 148 . S ^HL(772,MTIN,"IN",I,0)=$G(^HL(772,MTOUT,"IN",X,0)) 149 ; 150 ;-- update 0 node of message and format arrays 151 S ^HL(772,MTIN,"IN",0)="^^"_I_"^"_I_"^"_$$DT^XLFDT_"^" 152 ; 153 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLTF2.m
r613 r623 1 HLTF2 ;AISC/SAW/MTC-Process Message Text File Entries (Cont'd) ;10/17/2007 09:44 2 ;;1.6;HEALTH LEVEL SEVEN;**25,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 MERGEIN(LLD0,LLD1,MTIEN,HDR,MSA) ;Merge Data From Communication Server 6 ;Module Logical Link File into Message Text File 7 ; 8 ;This is a subroutine call with parameter passing. The output 9 ;parameters HDR (and optionally) MSA are returned by this call. 10 ; 11 ;Required input parameters 12 ; LLD0 = Internal entry number where message is stored in Logical Link 13 ; file or XM if message is stored in MailMan 14 ; LLD1 = Internal entry number of IN QUEUE multiple entry in Logical 15 ; Link file (Only required for messages stored in Logical 16 ; Link file) 17 ; MTIEN = Internal entry number where message is to be copied to in 18 ; Message Text file 19 ; HDR = The variable in which the message header segment will 20 ; be returned 21 ; MSA = The variable in which the message acknowledgement segment 22 ; will be returned, if one exists for this message 23 ; 24 ;Check for required parameters 25 I $G(LLD0)']""!('$G(MTIEN)) Q 26 I LLD0'="XM",'$G(LLD1) Q 27 N FLG,HLCHAR,HLEVN,HLFS,I,X,X1,HLDONE 28 S (FLG,HLCHAR,HLEVN,X)=0 29 ; 30 ; patch HL*1.6*122: MPI-client/server 31 F L +^HL(772,+$G(MTIEN)):10 Q:$T H 1 32 ; 33 ;Move data from Logical Link file to Message Text file 34 I LLD0'="XM" D 35 .S I=0 F S X=$O(^HLCS(870,LLD0,1,LLD1,1,X)) Q:X'>0 S X1=$G(^(X,0)) S:"FHS,BHS,MSH"[$E(X1,1,3) FLG=1 I FLG S HLCHAR=HLCHAR+$L(X1) D 36 ..;If header segment, process it and set HDR equal to it 37 ..I X1'="","FHS,BHS,MSH"[$E(X1,1,3) D 38 ...I '$D(HDR) S HDR=X1,HLFS=$E(X1,4) I $E(HDR,1,3)="BHS" S MSA="MSA"_HLFS_$P($P(HDR,HLFS,10),$E(HDR,5),1)_HLFS_$P(HDR,HLFS,12)_HLFS_$P($P(HDR,HLFS,10),$E(HDR,5),2) 39 ...S $P(X1,HLFS,8)="" 40 ...S:$E(X1,1,3)="MSH" HLEVN=HLEVN+1 41 ..;If acknowledgement segment, set MSA equal to it 42 ..I $E(X1,1,3)="MSA",'$D(MSA),$E($G(HDR),1,3)="MSH" S MSA=X1 43 ..S I=I+1,^HL(772,MTIEN,"IN",I,0)=X1 44 ; 45 ;Move data from MailMan Message file to Message Text file 46 I LLD0="XM" D 47 .S I=0 F X XMREC Q:XMER<0 S:"FHS,BHS,MSH"[$E(XMRG,1,3) FLG=1 I FLG S HLCHAR=HLCHAR+$L(XMRG) D Q:XMER<0 48 ..;If header segment, process it and set HDR equal to it 49 ..I XMRG'="","FHS,BHS,MSH"[$E(XMRG,1,3) D 50 ...I '$D(HDR) S HDR=XMRG,HLFS=$E(XMRG,4) I $E(HDR,1,3)="BHS" S MSA="MSA"_HLFS_$P($P(HDR,HLFS,10),$E(HDR,5),1)_HLFS_$P(HDR,HLFS,12)_HLFS_$P($P(HDR,HLFS,10),$E(HDR,5),2) 51 ...S $P(XMRG,HLFS,8)="" 52 ...S:$E(XMRG,1,3)="MSH" HLEVN=HLEVN+1 53 ..;If acknowledgement segment, set MSA equal to it 54 ..I $E(XMRG,1,3)="MSA",'$D(MSA),$E($G(HDR),1,3)="MSH" S MSA=XMRG 55 ..S I=I+1,^HL(772,MTIEN,"IN",I,0)=XMRG 56 S ^HL(772,MTIEN,"IN",0)="^^"_I_"^"_I_"^"_$$DT^XLFDT_"^" 57 ;Update statistics in Message Text file for this entry 58 ; 59 ; patch HL*1.6*122: MPI-client/server 60 L -^HL(772,+$G(MTIEN)) 61 ; 62 D STATS^HLTF0(MTIEN,HLCHAR,HLEVN) 63 Q 64 MERGEOUT(MTIEN,LLD0,LLD1,HDR) ;Merge Text in Message Text File into 65 ;Communication Server Module Logical Link File 66 ; 67 ;This is a routine call with parameter passing. There are no output 68 ;parameters returned by this call. 69 ; 70 ;Required input parameters 71 ; MTIEN = Internal entry number where message is stored in Message 72 ; Text file 73 ; LLD0 = Internal entry number where message is to be copied to in 74 ; Logical Link file 75 ; LLD1 = Internal entry number of IN QUEUE multiple entry in Logical 76 ; Link file 77 ; HDR = Name of the array that contains HL7 Header segment 78 ; format: HLHDR - Used with indirection to build message in out 79 ; queue 80 ; This routine will first take the header information in the array 81 ; specified by HDR and merge into the Message Text field of file 870. 82 ; Then it will move the message contained in 772 (MTIEN) into 870. 83 ; 84 ;Check for required parameters 85 I '$G(MTIEN)!('$G(LLD0))!('$G(LLD1))!(HDR="") Q 86 ; 87 ;-- initilize 88 N I,X 89 S I=0 90 ; 91 ; patch HL*1.6*122: MPI-client/server 92 F L +^HLCS(870,+$G(LLD0),2,+$G(LLD1)):10 Q:$T H 1 93 ; 94 ;-- move header into 870 from HDR array 95 S X="" F S X=$O(@HDR@(X)) Q:'X D 96 . S I=I+1,^HLCS(870,LLD0,2,LLD1,1,I,0)=@HDR@(X) 97 S I=I+1,^HLCS(870,LLD0,2,LLD1,1,I,0)="" 98 ; 99 ;Move data from Message Text file to Logical Link file 100 S X=0 F S X=$O(^HL(772,MTIEN,"IN",X)) Q:X="" D 101 . S I=I+1,^HLCS(870,LLD0,2,LLD1,1,I,0)=$G(^HL(772,MTIEN,"IN",X,0)) 102 ; 103 ;-- update 0 node of message and format arrays 104 S ^HLCS(870,LLD0,2,LLD1,1,0)="^^"_I_"^"_I_"^"_$$DT^XLFDT_"^" 105 ; 106 ; patch HL*1.6*122: MPI-client/server 107 L -^HLCS(870,+$G(LLD0),2,+$G(LLD1)) 108 ; 109 Q 110 OUT(HLDA,HLMID,HLMTN) ;File Data in Message Text File for Outgoing Message 111 ;Version 1.5 Interface Only 112 ; 113 ; patch HL*1.6*122: HLTF routine splitted, moves sub-routines, 114 ; OUT, IN, and ACK to HLTF2 routine. 115 ; 116 Q:'$D(HLFS) 117 ; 118 I HLMTN="ACK"!(HLMTN="MCF")!(HLMTN="ORR") Q:'$D(HLMSA) D ACK(HLMSA,"I") Q 119 ; 120 ;-- if message contained MSA find inbound message 121 I $D(HLMSA),$D(HLNDAP),$P(HLMSA,HLFS,3)]"" D 122 . N HLDAI 123 . S HLDAI=0 124 . F S HLDAI=$O(^HL(772,"AH",+$P($G(HLNDAP0),U,12),$P(HLMSA,HLFS,3),HLDAI)) Q:'HLDAI!($P($G(^HL(772,+HLDAI,0)),U,4)="I") 125 . I 'HLDAI K HLDAI 126 ; 127 D STUFF^HLTF0("O") 128 ; 129 N HLAC S HLAC=$S($D(HLERR):4,'$P(HLNDAP0,"^",10):1,1:2) D STATUS^HLTF0(HLDA,HLAC,$G(HLMSG)) 130 D:$D(HLCHAR) STATS^HLTF0(HLDA,HLCHAR,$G(HLEVN)) 131 ; 132 ;-- update status if MSA and found inbound message 133 I $D(HLMSA),$D(HLDAI) D 134 .N HLERR,HLMSG I $P(HLMSA,HLFS,4)]"" S HLERR=$P(HLMSA,HLFS,4) 135 .S HLAC=$P(HLMSA,HLFS,2) 136 .I HLAC'="AA" S HLMSG=$S(HLAC="AR":"Application Reject",HLAC="AE":"Application Error",1:"")_" - "_HLERR 137 .S HLAC=$S(HLAC'="AA":4,1:3) D STATUS^HLTF0(HLDAI,HLAC,$G(HLMSG)) 138 Q 139 ; 140 IN(HLMTN,HLMID,HLTIME) ;File Data in Message Text File for Incoming Message 141 ;Version 1.5 Interface Only 142 ; 143 ; patch HL*1.6*122: HLTF routine splitted, moves sub-routines, 144 ; OUT, IN, and ACK to HLTF2 routine. 145 ; 146 Q:'$D(HLFS) 147 I HLMTN="ACK"!(HLMTN="MCF")!(HLMTN="ORR") Q:'$D(HLMSA) D ACK(HLMSA,"O",$G(HLDA)) Q 148 ; 149 N HLDAI S HLDA=0 150 I $D(HLNDAP),HLMID]"" D 151 .F S HLDA=+$O(^HL(772,"AH",+$P($G(HLNDAP0),U,12),HLMID,HLDA)) Q:'HLDA!($P($G(^HL(772,+HLDA,0)),U,4)="I") 152 .I HLDA D 153 ..S HLDT=+$P($G(^HL(772,HLDA,0)),"^"),HLDT1=$$HLDATE^HLFNC(HLDT) 154 ..K ^HL(772,HLDA,"IN") 155 .I $D(HLMSA),$P(HLMSA,HLFS,3)]"" D 156 ..S HLDAI=0 157 ..F S HLDAI=$O(^HL(772,"AH",+$P($G(HLNDAP0),U,12),$P(HLMSA,HLFS,3),HLDAI)) Q:'HLDAI!($P($G(^HL(772,+HLDAI,0)),U,4)="O") 158 ..I 'HLDAI K HLDAI 159 ; 160 ; patch HL*1.6*122: MPI-client/server 161 ; I 'HLDA D CREATE(.HLMID,.HLDA,.HLDT,.HLDT1) K HLZ 162 I 'HLDA D CREATE^HLTF(.HLMID,.HLDA,.HLDT,.HLDT1) K HLZ 163 ; 164 D STUFF^HLTF0("I") 165 N HLAC S HLAC=$S($D(HLERR):4,1:1) D STATUS^HLTF0(HLDA,HLAC,$G(HLMSG)) 166 ; 167 D MERGE15^HLTF1("G",HLDA,"HLR",HLTIME) 168 ; 169 I '$D(HLERR),$D(HLMSA),$D(HLDAI) D 170 .N HLAC,HLERR,HLMSG I $P(HLMSA,HLFS,4)]"" S HLERR=$P(HLMSA,HLFS,4) 171 .S HLAC=$P(HLMSA,HLFS,2) I HLAC'="AA" S HLMSG=$S(HLAC="AR":"Application Reject",1:"Application Error")_" - "_HLERR 172 .S HLAC=$S(HLAC'="AA":4,1:3) D STATUS^HLTF0(HLDAI,HLAC,$G(HLMSG)) 173 Q 174 ; 175 ACK(HLMSA,HLIO,HLDA) ;Process 'ACK' Message Type - Version 1.5 Interface Only 176 ; 177 ; patch HL*1.6*122: HLTF routine splitted, moves sub-routines, 178 ; OUT, IN, and ACK to HLTF2 routine. 179 ; 180 ; To determine the correct message to link the ACK, HLIO is used. 181 ; For an ack from DHCP (original message from remote system) then 182 ; HLIO should be "I" so that the correct inbound message is ack-ed. For 183 ; an inbound ack (original message outbound from DHCP) HLIO should be 184 ; "O". This distinction must be made due to the possible duplicate 185 ; message ids from a bi-direction interface. 186 ; 187 ; Input : MSA - MSA from ACK message. 188 ; HLIO - Either "I" or "O" : See note above. 189 ;Output : None 190 ; 191 N HLAC,HLMIDI 192 ;-- set up required vars 193 S HLAC=$P(HLMSA,HLFS,2),HLMIDI=$P(HLMSA,HLFS,3) 194 ;-- quit 195 Q:HLMIDI']""!(HLAC']"")!('$D(HLNDAP)) 196 ;-- find message to ack 197 I '$G(HLDA) S HLDA=0 D 198 . F S HLDA=+$O(^HL(772,"AH",+$P($G(HLNDAP0),U,12),HLMIDI,HLDA)) Q:'HLDA!($P($G(^HL(772,+HLDA,0)),U,4)=HLIO) 199 ;-- quit if no message 200 Q:'$D(^HL(772,+HLDA,0)) 201 ;-- check for error 202 I $P(HLMSA,HLFS,4)]"" N HLERR S HLERR=$P(HLMSA,HLFS,4) 203 I $D(HLERR),'$D(HLMSG) N HLMSG S HLMSG="Error During Receipt of Acknowledgement Message"_$S(HLAC="AR":" - Application Reject",HLAC="AE":" - Application Error",1:"")_" - "_HLERR 204 ;-- update status 205 S HLAC=$S(HLMTN="MCF":2,HLAC'="AA":4,1:3) 206 D STATUS^HLTF0(HLDA,HLAC,$G(HLMSG)) 207 Q 208 ; 1 HLTF2 ;AISC/SAW/MTC-Process Message Text File Entries (Cont'd) ;02/24/97 13:56 2 ;;1.6;HEALTH LEVEL SEVEN;**25**;Oct 13, 1995 3 MERGEIN(LLD0,LLD1,MTIEN,HDR,MSA) ;Merge Data From Communication Server 4 ;Module Logical Link File into Message Text File 5 ; 6 ;This is a subroutine call with parameter passing. The output 7 ;parameters HDR (and optionally) MSA are returned by this call. 8 ; 9 ;Required input parameters 10 ; LLD0 = Internal entry number where message is stored in Logical Link 11 ; file or XM if message is stored in MailMan 12 ; LLD1 = Internal entry number of IN QUEUE multiple entry in Logical 13 ; Link file (Only required for messages stored in Logical 14 ; Link file) 15 ; MTIEN = Internal entry number where message is to be copied to in 16 ; Message Text file 17 ; HDR = The variable in which the message header segment will 18 ; be returned 19 ; MSA = The variable in which the message acknowledgement segment 20 ; will be returned, if one exists for this message 21 ; 22 ;Check for required parameters 23 I $G(LLD0)']""!('$G(MTIEN)) Q 24 I LLD0'="XM",'$G(LLD1) Q 25 N FLG,HLCHAR,HLEVN,HLFS,I,X,X1,HLDONE 26 S (FLG,HLCHAR,HLEVN,X)=0 27 ; 28 ;Move data from Logical Link file to Message Text file 29 I LLD0'="XM" D 30 .S I=0 F S X=$O(^HLCS(870,LLD0,1,LLD1,1,X)) Q:X'>0 S X1=$G(^(X,0)) S:"FHS,BHS,MSH"[$E(X1,1,3) FLG=1 I FLG S HLCHAR=HLCHAR+$L(X1) D 31 ..;If header segment, process it and set HDR equal to it 32 ..I X1'="","FHS,BHS,MSH"[$E(X1,1,3) D 33 ...I '$D(HDR) S HDR=X1,HLFS=$E(X1,4) I $E(HDR,1,3)="BHS" S MSA="MSA"_HLFS_$P($P(HDR,HLFS,10),$E(HDR,5),1)_HLFS_$P(HDR,HLFS,12)_HLFS_$P($P(HDR,HLFS,10),$E(HDR,5),2) 34 ...S $P(X1,HLFS,8)="" 35 ...S:$E(X1,1,3)="MSH" HLEVN=HLEVN+1 36 ..;If acknowledgement segment, set MSA equal to it 37 ..I $E(X1,1,3)="MSA",'$D(MSA),$E($G(HDR),1,3)="MSH" S MSA=X1 38 ..S I=I+1,^HL(772,MTIEN,"IN",I,0)=X1 39 ; 40 ;Move data from MailMan Message file to Message Text file 41 I LLD0="XM" D 42 .S I=0 F X XMREC Q:XMER<0 S:"FHS,BHS,MSH"[$E(XMRG,1,3) FLG=1 I FLG S HLCHAR=HLCHAR+$L(XMRG) D Q:XMER<0 43 ..;If header segment, process it and set HDR equal to it 44 ..I XMRG'="","FHS,BHS,MSH"[$E(XMRG,1,3) D 45 ...I '$D(HDR) S HDR=XMRG,HLFS=$E(XMRG,4) I $E(HDR,1,3)="BHS" S MSA="MSA"_HLFS_$P($P(HDR,HLFS,10),$E(HDR,5),1)_HLFS_$P(HDR,HLFS,12)_HLFS_$P($P(HDR,HLFS,10),$E(HDR,5),2) 46 ...S $P(XMRG,HLFS,8)="" 47 ...S:$E(XMRG,1,3)="MSH" HLEVN=HLEVN+1 48 ..;If acknowledgement segment, set MSA equal to it 49 ..I $E(XMRG,1,3)="MSA",'$D(MSA),$E($G(HDR),1,3)="MSH" S MSA=XMRG 50 ..S I=I+1,^HL(772,MTIEN,"IN",I,0)=XMRG 51 S ^HL(772,MTIEN,"IN",0)="^^"_I_"^"_I_"^"_$$DT^XLFDT_"^" 52 ;Update statistics in Message Text file for this entry 53 D STATS^HLTF0(MTIEN,HLCHAR,HLEVN) 54 Q 55 MERGEOUT(MTIEN,LLD0,LLD1,HDR) ;Merge Text in Message Text File into 56 ;Communication Server Module Logical Link File 57 ; 58 ;This is a routine call with parameter passing. There are no output 59 ;parameters returned by this call. 60 ; 61 ;Required input parameters 62 ; MTIEN = Internal entry number where message is stored in Message 63 ; Text file 64 ; LLD0 = Internal entry number where message is to be copied to in 65 ; Logical Link file 66 ; LLD1 = Internal entry number of IN QUEUE multiple entry in Logical 67 ; Link file 68 ; HDR = Name of the array that contains HL7 Header segment 69 ; format: HLHDR - Used with indirection to build message in out 70 ; queue 71 ; This routine will first take the header information in the array 72 ; specified by HDR and merge into the Message Text field of file 870. 73 ; Then it will move the message contained in 772 (MTIEN) into 870. 74 ; 75 ;Check for required parameters 76 I '$G(MTIEN)!('$G(LLD0))!('$G(LLD1))!(HDR="") Q 77 ; 78 ;-- initilize 79 N I,X 80 S I=0 81 ; 82 ;-- move header into 870 from HDR array 83 S X="" F S X=$O(@HDR@(X)) Q:'X D 84 . S I=I+1,^HLCS(870,LLD0,2,LLD1,1,I,0)=@HDR@(X) 85 S I=I+1,^HLCS(870,LLD0,2,LLD1,1,I,0)="" 86 ; 87 ;Move data from Message Text file to Logical Link file 88 S X=0 F S X=$O(^HL(772,MTIEN,"IN",X)) Q:X="" D 89 . S I=I+1,^HLCS(870,LLD0,2,LLD1,1,I,0)=$G(^HL(772,MTIEN,"IN",X,0)) 90 ; 91 ;-- update 0 node of message and format arrays 92 S ^HLCS(870,LLD0,2,LLD1,1,0)="^^"_I_"^"_I_"^"_$$DT^XLFDT_"^" 93 ; 94 Q -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLTP3.m
r613 r623 1 HLTP3 ;SFIRMFO/RSD - Transaction Processor for TCP ;03/17/2008 11:26 2 ;;1.6;HEALTH LEVEL SEVEN;**19,43,57,58,59,66,69,109,115,108,116,117,125,120,133,122,140**;Oct 13, 1995;Build 5 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 Q 6 NEW(X) ;process new msg. ien in 773^ien in 772 7 ;HLMTIENS=ien in #773; HLMTIEN=ien in #772 8 ;HLHDRO=original header; HLHDR=response header 9 ;set error trap 10 N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLTP3" 11 N HL,HLEID,HLEIDS,HLERR,HLHDR,HLHDRO,HLMTIEN,HLMTIENS,HLJ,HLMSA,HLQUIT,HLNODE,HLNEXT,HLRESLTA,HLDONE1,HLASTRSP,HLRESLT 12 S HLRESLT="" 13 D INIT^HLTP3A 14 ;error with header, return commit/app reject 15 I $G(HLRESLT) D Q 16 . ;set status & unlock record 17 . D STATUS^HLTF0(HLMTIENS,4,,,1),EXIT 18 . ;quit if no commit or app ack 19 . I $G(HL("ACAT"))="NE",$G(HL("APAT"))="NE" Q 20 . S X=$S($G(HL("ACAT"))="AL":"CR",1:"AR") 21 . ;HLTCP=ien of acknowledgment msg. from ACK^HLTP4 22 . D ACK^HLTP4(X,$P(HLRESLT,U,2)) Q:'$G(HLTCP) 23 . ;write ack back 24 . S X=$$WRITE^HLCSTCP2(HLTCP) 25 . ;update counter to sent 26 . D LLCNT^HLCSTCP(HLDP,4) 27 . ;update status of ack 28 . D STATUS^HLTF0(HLTCP,3,,,1) 29 ; 30 ;check for duplicate msg., use rec. app and msg. id x-ref 31 ; patch HL*1.6*120 32 I $G(HL("MID"))]"",$G(HL("RAP")) S X=$O(^HLMA("AH",HL("RAP"),HL("MID"),0)) D Q:'$D(HLMTIENS) 33 . ;HLASTMSG=last ien received during this connection 34 . ;if no duplicate, save msg. ien and quit 35 . I X=HLMTIENS!'X S HLASTMSG=HLMTIENS Q 36 . N MSH,OIENS 37 . S (OIENS,Y)=X D S Y=HLMTIENS D 38 .. ;combine MSH into single string 39 .. S MSH(Y)="",I=0 F S I=$O(^HLMA(Y,"MSH",I)) Q:'I S MSH(Y)=MSH(Y)_$G(^(I,0)) 40 .; patch 117 & 125, check if identical 41 .I MSH(HLMTIENS)'=MSH(OIENS) S HLASTMSG=HLMTIENS Q 42 .; 43 . ;msg is duplicate, set status 44 . D STATUS^HLTF0(HLMTIENS,4,109,"Duplicate with ien "_OIENS,1),EXIT 45 . ;msg was resent, ignore it. 46 . I HLASTMSG=HLMTIENS K HLMTIENS Q 47 . ;find original response and send back 48 . S HLASTRSP=$O(^HLMA("AF",OIENS,OIENS)) 49 ; 50 ;Quit if this is ack to ack 51 I $G(HL("ACK")) D Q 52 . ;Update status of original ack message 53 . D STATUS^HLTF0(HL("MTIENS"),3,,,1),STATUS^HLTF0(HLMTIENS,3,,,1) 54 . ;unlock record 55 . D EXIT 56 ; 57 ;enhance ack., send commit, quit if not an ack, msg will be processed by filer 58 I $G(HL("ACAT"))="AL" D Q:'$G(HL("MTIENS")) 59 . ;msg is a resend, HLASTRSP=ien of original response 60 .I $G(HLASTRSP) D 61 ..S HLTCP=HLASTRSP 62 ..D LLCNT^HLCSTCP(HLDP,3) 63 . E D Q:'$G(HLTCP) 64 ..D ACK^HLTP4("CA") ;**109** LLCNT^HLCSTCP(HLDP,3) called in ACK^HLTP4 65 . S X=$$WRITE^HLCSTCP2(HLTCP) 66 . D LLCNT^HLCSTCP(HLDP,4),STATUS^HLTF0(HLTCP,3,,,1):'$G(HLASTRSP) 67 . S HLTCP="" 68 . ;if not an ack, set status to awaiting processing **109** and put on in queue 69 . I '$G(HL("MTIENS")),'$G(HLASTRSP) D STATUS^HLTF0(HLMTIENS,9),EXIT,SETINQUE^HLTP31 70 ; 71 ;enhance ack., no commit & no app ack 72 I $G(HL("ACAT"))="NE",$G(HL("APAT"))="NE" D Q 73 . ;set status to awaiting processing, **109** and put on in queue 74 . I '$G(HLASTRSP) D STATUS^HLTF0(HLMTIENS,9),EXIT,SETINQUE^HLTP31 75 ; 76 ; patch HL*1.6*120 start 77 ;resending old response, msg is a resend 78 ; do not re-send duplicate when $G(HL("ACAT"))="AL" 79 I $G(HLASTRSP),$G(HL("ACAT"))'="AL" S HLTCP=HLASTRSP G ACK 80 ; quit if duplicate 81 Q:$G(HLASTRSP) 82 ; patch HL*1.6*120 end 83 ; 84 CONT ;continue processing an enhance ack msg. called from DEFACK 85 ;Set special HL variables for processing rtn 86 S HLQUIT=0,HLNODE="",HLNEXT="D HLNEXT^HLCSUTL" 87 ; 88 ; message is an acknowledgement, HLMSA=ack code^id^text 89 I ($G(HLMSA)]"") D Q 90 . ;X=1 if ack ok, 0=reject of error 91 . S X=$E(HLMSA,2)="A" 92 . ;Update status of original message and remove it from the queue 93 . D STATUS^HLTF0(HL("MTIENS"),$S(X:3,1:4),"",$S(X:"",1:$P(HLMSA,HL("FS"),3)),1) 94 . D DEQUE^HLCSREP($P($G(^HLMA(HL("MTIENS"),0)),"^",7),"O",HL("MTIENS")) 95 . D 96 .. N HLTCP ;variable to update status in file #772. 97 ..; 98 ..;**108** 99 .. N TEMP 100 .. S TEMP=HLMTIENS 101 .. N HLMTIENS 102 .. S HLMTIENS=TEMP 103 ..;**END 108** 104 ..; 105 .. D PROCACK^HLTP2(HLMTIEN,HL("EID"),.HLRESLT,.HL) 106 . ;update status of incoming & unlock 107 . 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 108 ; 109 ;get entry action, exit action and processing routine 110 K HLHDR,HLLD0,HLLD1,HLMSA 111 I HL("EIDS")="",$G(HLEIDS)]"" S HL("EIDS")=HLEIDS ;**CIRN** 112 D EVENT^HLUTIL1(HL("EIDS"),"15,20,771",.HLN) 113 S HLENROU=$G(HLN(20)),HLEXROU=$G(HLN(15)),HLPROU=$G(HLN(771)) 114 ;quit if no processing routine,update status and quit 115 I HLPROU']"" S HLRESLT="10^"_$G(^HL(771.7,10,0)) D STATUS^HLTF0(HLMTIENS,3,,,1),EXIT Q 116 ;HLORNOD=subscriber protocol for Fileman auditing, ien;global ref 117 N HLORNODD S HLORNOD=HL("EIDS")_";ORD(101," 118 ;Execute entry action of client protocol 119 X:HLENROU]"" HLENROU K HLENROU,HLDONE1 120 ; 121 ;Execute processing routine 122 X HLPROU S HLRESLT=0 S:($D(HLERR)) HLRESLT="9^"_HLERR 123 ;update status of incoming to complete & unlock 124 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 125 ;HLTCPO=link open, HLTCP=ien of ack msg. from GENACK 126 ACK I $G(HLTCPO),$G(HLTCP) D Q 127 . D LLCNT^HLCSTCP(HLDP,3) 128 . ;write ack back over open tcp link 129 . S X=$$WRITE^HLCSTCP2(HLTCP) 130 . ;update status of ack to complete 131 . D:'$G(HLASTRSP) STATUS^HLTF0(HLTCP,3,,,1) 132 . D LLCNT^HLCSTCP(HLDP,4) 133 Q 134 ; 135 DEFACK(HLDP,X) ;process the deferred application ack, called from HLCSIN 136 ;HLDP=logical link, X=ien in file 773 137 ; 138 ; patch HL*1.6*120 start 139 ; clean non-Kernel variables 140 D 141 . ; protect variables defined in STARTIN^HLCSIN 142 . N HLFLG,HLEXIT,HLPTRFLR 143 . ; protect variables defined in DEFACK^HLCSIN 144 . N HLXX,HLD0,HLPCT 145 . ; protect input parameters of this sub-routine 146 . N HLDP,X 147 . D KILL^XUSCLEAN 148 ; patch HL*1.6*120 end 149 ; 150 ;set error trap 151 N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLTP3" 152 N HLERR ;patch HL*1.6*109 153 Q:'$G(HLDP)!'$G(X) Q:'$G(^HLMA(X,0)) 154 Q:'$D(^HLMA("AC","I",HLDP,X)) 155 ; 156 N HL,HLA,HLD0,HLEID,HLEIDS,HLHDR,HLHDRO,HLMTIEN,HLMTIENS,HLJ,HLMSA,HLN,HLQUIT,HLNODE,HLNEXT,HLRESLT,HLRESLTA,HLTCP,HLXX,Z,HLDONE1 157 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")="""""" 158 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) 159 S:$P(X,U,15) HL("MTP_ETP")=$P(X,U,15) 160 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) 161 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) 162 S:$G(HL("MTP_ETP")) HL("MTN_ETN")=$P($G(^HL(779.005,HL("MTP_ETP"),0)),U) 163 S HL("EID")=$P($G(^HL(772,HLMTIEN,0)),U,10) 164 M HLHDRO=^HLMA(HLMTIENS,"MSH") 165 ; if no header quit 166 Q:'$O(HLHDRO(0)) 167 ; 168 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) 169 ; 170 ; quit if ien of #772 is not defined 171 Q:'HLMTIEN 172 ; quit if field separator is not defined 173 Q:HL("FS")="" 174 ; 175 S X=$$P^HLTPCK2(.HLHDRO,1) 176 ; 177 ; patch HL*1.6*120 start 178 I X="MSH" D 179 . 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) 180 . ; 181 . ; 2nd component is Processing mode 182 . S HL("PMOD")=$P(HL("PID"),$E(HL("ECH"),1),2) 183 . ; first component is Processing id 184 . S HL("PID")=$P(HL("PID"),$E(HL("ECH"),1)) 185 ; 186 I X'="MSH" D 187 . S X=$$P^HLTPCK2(.HLHDRO,9),Z=$E(HL("ECH")),HL("PID")=$P(X,Z,2),HL("VER")=$P(X,Z,4) 188 . ; 189 . ; original code incorrectly treats repetition separator as 190 . ; subcomponent separator 191 . I $E(HL("ECH"),2)]"",X[$E(HL("ECH"),2) D 192 .. S HL("SUB-COMPONENT")=$E(HL("ECH"),2) 193 . ; if subcomponent separator is correctly applied 194 . I $E(HL("ECH"),4)]"",X[$E(HL("ECH"),4) D 195 .. S HL("SUB-COMPONENT")=$E(HL("ECH"),4) 196 . ; 197 . I $D(HL("SUB-COMPONENT")),HL("PID")[HL("SUB-COMPONENT") D 198 .. ; 2nd sub-component is Processing mode 199 .. S HL("PMOD")=$P(HL("PID"),HL("SUB-COMPONENT"),2) 200 .. ; first sub-component is Processing id 201 .. S HL("PID")=$P(HL("PID"),HL("SUB-COMPONENT")) 202 . ; patch HL*1.6*120 end 203 . ; 204 . Q:$$P^HLTPCK2(.HLHDRO,10)="" 205 . ;HLMSA=ack code^id^text 206 . 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) 207 ; 208 ; quit if this is a commit ack 209 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 210 ; 211 ;** HL*1.6*117 ** 212 K HLL("SET FOR APP ACK"),HLL("LINKS") 213 ; 214 D CONT 215 Q 216 ; 217 MSA(Y) ;Y=ien in 772, returns MSA segment 218 ;ack code^msg being ack id^text 219 ; patch HL*1.6*122 220 ; for HL7 v2.5 and beyond with MSA as 3rd segment 221 N X,SUBIEN,DATA,DONE 222 S X=$G(^HL(772,Y,"IN",1,0)),X=$S($E(X,1,3)="MSA":$E(X,5,999),1:"") 223 Q:X]"" X 224 ; 225 S DONE=0 226 S SUBIEN=1 227 F S SUBIEN=$O(^HL(772,Y,"IN",SUBIEN)) Q:'SUBIEN D Q:DONE 228 . S DATA=$G(^HL(772,Y,"IN",SUBIEN,0)) I DATA="" D 229 .. S DONE=1 230 .. S SUBIEN=$O(^HL(772,Y,"IN",SUBIEN)) Q:'SUBIEN 231 .. S X=$G(^HL(772,Y,"IN",SUBIEN,0)),X=$S($E(X,1,3)="MSA":$E(X,5,999),1:"") 232 ; patch HL*1.6*122 end 233 ; 234 Q X 235 ; 236 ERROR ;error trap 237 D ^%ZTER 238 I $G(HLMTIENS),$D(^HLMA(HLMTIENS,0)) D STATUS^HLTF0(HLMTIENS,4,,,1),EXIT 239 ; release locks created by inbound filer 240 ; patch HL*1.6*140 241 ; L -^HLMA("AC","I",+$G(HLXX)) 242 L -^HLMA("IN-FILER","AC","I",+$G(HLXX)) 243 G UNWIND^%ZTER 244 ; 245 ; 246 EXIT ;unlock 247 I $G(HLMTIENS) L -^HLMA(HLMTIENS) 248 Q 249 ; 250 ONAC(IEN773) ; 251 ;Returns 1 if the message is on the "AC","I" xref 252 ;Returns 0 otherwise 253 ; 254 N LINK 255 S LINK=$P($G(^HLMA(IEN773,0)),"^",17) 256 Q:'LINK 0 257 Q $D(^HLMA("AC","I",LINK,IEN773)) 1 HLTP3 ;SFIRMFO/RSD - Transaction Processor for TCP ;09/13/2006 2 ;;1.6;HEALTH LEVEL SEVEN;**19,43,57,58,59,66,69,109,115,108,116,117,125,120,133**;Oct 13, 1995;Build 13 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 Q 6 NEW(X) ;process new msg. ien in 773^msg. ien in 772 7 ;HLMTIENS=ien in #773, msg header; HLMTIEN=ien in #772, msg text 8 ;HLHDRO=original header; HLHDR=response header 9 ;set error trap 10 N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLTP3" 11 N HL,HLEID,HLEIDS,HLERR,HLHDR,HLHDRO,HLMTIEN,HLMTIENS,HLJ,HLMSA,HLQUIT,HLNODE,HLNEXT,HLRESLTA,HLDONE1,HLASTRSP,HLRESLT 12 S HLRESLT="" 13 D INIT^HLTP3A 14 ;error with header, return commit/app reject 15 I $G(HLRESLT) D Q 16 . ;set status & unlock record 17 . D STATUS^HLTF0(HLMTIENS,4,,,1),EXIT 18 . ;quit if no commit or app ack 19 . I $G(HL("ACAT"))="NE",$G(HL("APAT"))="NE" Q 20 . S X=$S($G(HL("ACAT"))="AL":"CR",1:"AR") 21 . ;HLTCP=ien of acknowledgment msg. from ACK^HLTP4 22 . D ACK^HLTP4(X,$P(HLRESLT,U,2)) Q:'$G(HLTCP) 23 . ;write ack back over connection 24 . S X=$$WRITE^HLCSTCP2(HLTCP) 25 . ;update counter to sent 26 . D LLCNT^HLCSTCP(HLDP,4) 27 . ;update status of ack to complete 28 . D STATUS^HLTF0(HLTCP,3,,,1) 29 ; 30 ;check for duplicate msg., use rec. app and msg. id x-ref 31 ; patch HL*1.6*120 32 ; I $L($G(HL("MID"))),$G(HL("RAP")) S X=$O(^HLMA("AH",HL("RAP"),HL("MID"),0)) D Q:'$D(HLMTIENS) 33 I $G(HL("MID"))]"",$G(HL("RAP")) S X=$O(^HLMA("AH",HL("RAP"),HL("MID"),0)) D Q:'$D(HLMTIENS) 34 . ;HLASTMSG=last ien received during this connection 35 . ;if no duplicate, save msg. ien and quit 36 . I X=HLMTIENS!'X S HLASTMSG=HLMTIENS Q 37 . N MSH,OIENS 38 . S (OIENS,Y)=X D S Y=HLMTIENS D 39 .. ;combine MSH into single string 40 .. S MSH(Y)="",I=0 F S I=$O(^HLMA(Y,"MSH",I)) Q:'I S MSH(Y)=MSH(Y)_$G(^(I,0)) 41 .; patch 117 & 125, check if identical 42 .I MSH(HLMTIENS)'=MSH(OIENS) S HLASTMSG=HLMTIENS Q 43 .; 44 . ;msg is duplicate, set status as duplicate 45 . D STATUS^HLTF0(HLMTIENS,4,109,"Duplicate with ien "_OIENS,1),EXIT 46 . ;msg was resent during this connection, ignore it. 47 . I HLASTMSG=HLMTIENS K HLMTIENS Q 48 . ;find original response and send back 49 . S HLASTRSP=$O(^HLMA("AF",OIENS,OIENS)) 50 ; 51 ;Quit if this is acknowledgment to acknowledgement message 52 I $G(HL("ACK")) D Q 53 . ;Update status of original acknowledgment message to successfully 54 . D STATUS^HLTF0(HL("MTIENS"),3,,,1),STATUS^HLTF0(HLMTIENS,3,,,1) 55 . ;unlock record 56 . D EXIT 57 ; 58 ;enhance ack., send commit, quit if not an ack, msg will be processed by filer 59 I $G(HL("ACAT"))="AL" D Q:'$G(HL("MTIENS")) 60 . ;msg is a resend, HLASTRSP=ien of original response 61 .I $G(HLASTRSP) D 62 ..S HLTCP=HLASTRSP 63 ..D LLCNT^HLCSTCP(HLDP,3) 64 . E D Q:'$G(HLTCP) 65 ..D ACK^HLTP4("CA") ;**109** LLCNT^HLCSTCP(HLDP,3) called in ACK^HLTP4 66 . S X=$$WRITE^HLCSTCP2(HLTCP) 67 . D LLCNT^HLCSTCP(HLDP,4),STATUS^HLTF0(HLTCP,3,,,1):'$G(HLASTRSP) 68 . S HLTCP="" 69 . ;if not an ack, set status to awaiting processing **109** and put on in queue 70 . I '$G(HL("MTIENS")),'$G(HLASTRSP) D STATUS^HLTF0(HLMTIENS,9),EXIT,SETINQUE^HLTP31 71 ; 72 ;enhance ack., no commit & no app ack 73 I $G(HL("ACAT"))="NE",$G(HL("APAT"))="NE" D Q 74 . ;set status to awaiting processing, **109** and put on in queue 75 . I '$G(HLASTRSP) D STATUS^HLTF0(HLMTIENS,9),EXIT,SETINQUE^HLTP31 76 ; 77 ; patch HL*1.6*120 start 78 ;resending old response, msg is a resend 79 ; I $G(HLASTRSP) S HLTCP=HLASTRSP G ACK 80 ; do not re-send duplicate message when $G(HL("ACAT"))="AL" 81 I $G(HLASTRSP),$G(HL("ACAT"))'="AL" S HLTCP=HLASTRSP G ACK 82 ; quit if duplicate 83 Q:$G(HLASTRSP) 84 ; patch HL*1.6*120 end 85 ; 86 CONT ;continue processing an enhance ack msg. called from DEFACK 87 ;Set special HL variables for processing rtn 88 S HLQUIT=0,HLNODE="",HLNEXT="D HLNEXT^HLCSUTL" 89 ; 90 ; message is an acknowledgement, HLMSA=ack code^id^text 91 I ($G(HLMSA)]"") D Q 92 . ;X=1 if ack ok, 0=reject of error 93 . S X=$E(HLMSA,2)="A" 94 . ;Update status of original subscriber message and remove it from the out-going queue 95 . D STATUS^HLTF0(HL("MTIENS"),$S(X:3,1:4),"",$S(X:"",1:$P(HLMSA,HL("FS"),3)),1) 96 . D DEQUE^HLCSREP($P($G(^HLMA(HL("MTIENS"),0)),"^",7),"O",HL("MTIENS")) 97 . D 98 .. N HLTCP ;New variable to update status in file #772. 99 ..; 100 ..;**108** 101 .. N TEMP 102 .. S TEMP=HLMTIENS 103 .. N HLMTIENS 104 .. S HLMTIENS=TEMP 105 ..;**END 108** 106 ..; 107 .. D PROCACK^HLTP2(HLMTIEN,HL("EID"),.HLRESLT,.HL) 108 . ;update status of incoming to complete & unlock 109 . 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 110 ; 111 ;get entry action, exit action and processing routine 112 K HLHDR,HLLD0,HLLD1,HLMSA 113 I HL("EIDS")="",$G(HLEIDS)]"" S HL("EIDS")=HLEIDS ;**CIRN** 114 D EVENT^HLUTIL1(HL("EIDS"),"15,20,771",.HLN) 115 S HLENROU=$G(HLN(20)),HLEXROU=$G(HLN(15)),HLPROU=$G(HLN(771)) 116 ;quit if no processing routine,update status and quit 117 I HLPROU']"" S HLRESLT="10^"_$G(^HL(771.7,10,0)) D STATUS^HLTF0(HLMTIENS,3,,,1),EXIT Q 118 ;HLORNOD=subscriber protocol for Fileman auditing, ien;global ref 119 N HLORNODD S HLORNOD=HL("EIDS")_";ORD(101," 120 ;Execute entry action of client protocol 121 X:HLENROU]"" HLENROU K HLENROU,HLDONE1 122 ; 123 ;Execute processing routine 124 X HLPROU S HLRESLT=0 S:($D(HLERR)) HLRESLT="9^"_HLERR 125 ;update status of incoming to complete & unlock 126 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 127 ;HLTCPO=link open, HLTCP=ien of acknowledgment msg. from GENACK 128 ACK I $G(HLTCPO),$G(HLTCP) D Q 129 . D LLCNT^HLCSTCP(HLDP,3) 130 . ;write ack back over open tcp link 131 . S X=$$WRITE^HLCSTCP2(HLTCP) 132 . ;update status of ack to complete 133 . D:'$G(HLASTRSP) STATUS^HLTF0(HLTCP,3,,,1) 134 . D LLCNT^HLCSTCP(HLDP,4) 135 Q 136 ; 137 DEFACK(HLDP,X) ;process the deferred application ack, called from HLCSIN 138 ;HLDP=logical link, X=ien in file 773 139 ; 140 ; patch HL*1.6*120 start 141 ; clean variables except Kernel related variables 142 D 143 . ; protect variables defined in STARTIN^HLCSIN 144 . N HLFLG,HLEXIT,HLPTRFLR 145 . ; protect variables defined in DEFACK^HLCSIN 146 . N HLXX,HLD0,HLPCT 147 . ; protect input parameters of this sub-routine 148 . N HLDP,X 149 . D KILL^XUSCLEAN 150 ; patch HL*1.6*120 end 151 ; 152 ;set error trap 153 N $ETRAP,$ESTACK S $ETRAP="D ERROR^HLTP3" 154 N HLERR ;patch HL*1.6*109 155 Q:'$G(HLDP)!'$G(X) Q:'$G(^HLMA(X,0)) 156 ;**109 START** 157 Q:'$D(^HLMA("AC","I",HLDP,X)) 158 ;**109 END** 159 ; 160 N HL,HLA,HLD0,HLEID,HLEIDS,HLHDR,HLHDRO,HLMTIEN,HLMTIENS,HLJ,HLMSA,HLN,HLQUIT,HLNODE,HLNEXT,HLRESLT,HLRESLTA,HLTCP,HLXX,Z,HLDONE1 161 ;setup variables 162 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")="""""" 163 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) 164 S:$P(X,U,15) HL("MTP_ETP")=$P(X,U,15) 165 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) 166 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) 167 S:$G(HL("MTP_ETP")) HL("MTN_ETN")=$P($G(^HL(779.005,HL("MTP_ETP"),0)),U) 168 S HL("EID")=$P($G(^HL(772,HLMTIEN,0)),U,10) 169 M HLHDRO=^HLMA(HLMTIENS,"MSH") 170 ; if no header quit 171 ;**109** 172 ;I '$O(HLHDRO(0)) L -^HLMA(HLMTIENS) Q 173 Q:'$O(HLHDRO(0)) 174 ; 175 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) 176 ; 177 ; patch HL*1.6*109 start 178 ; quit if ien of #772 is not defined 179 Q:'HLMTIEN 180 ; quit if field separator is not defined 181 Q:HL("FS")="" 182 ; patch HL*1.6*109 end 183 ; 184 S X=$$P^HLTPCK2(.HLHDRO,1) 185 ; 186 ; patch HL*1.6*120 start 187 I X="MSH" D 188 . 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) 189 . ; 190 . ; 2nd component is Processing mode 191 . S HL("PMOD")=$P(HL("PID"),$E(HL("ECH"),1),2) 192 . ; first component is Processing id 193 . S HL("PID")=$P(HL("PID"),$E(HL("ECH"),1)) 194 ; 195 I X'="MSH" D 196 . S X=$$P^HLTPCK2(.HLHDRO,9),Z=$E(HL("ECH")),HL("PID")=$P(X,Z,2),HL("VER")=$P(X,Z,4) 197 . ; 198 . ; original implementation incorrectly treats repetition separator as 199 . ; subcomponent separator 200 . I $E(HL("ECH"),2)]"",X[$E(HL("ECH"),2) D 201 .. S HL("SUB-COMPONENT")=$E(HL("ECH"),2) 202 . ; if subcomponent separator is correctly applied 203 . I $E(HL("ECH"),4)]"",X[$E(HL("ECH"),4) D 204 .. S HL("SUB-COMPONENT")=$E(HL("ECH"),4) 205 . ; 206 . I $D(HL("SUB-COMPONENT")),HL("PID")[HL("SUB-COMPONENT") D 207 .. ; 2nd sub-component is Processing mode 208 .. S HL("PMOD")=$P(HL("PID"),HL("SUB-COMPONENT"),2) 209 .. ; first sub-component is Processing id 210 .. S HL("PID")=$P(HL("PID"),HL("SUB-COMPONENT")) 211 . ; patch HL*1.6*120 end 212 . ; 213 . Q:$$P^HLTPCK2(.HLHDRO,10)="" 214 . ;HLMSA=ack code^id^text 215 . 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) 216 ; 217 ; HL*1.6*108 218 ; quit if this is a commit ack 219 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 220 ; ** 221 ; 222 ;** HL*1.6*117 ** 223 K HLL("SET FOR APP ACK"),HLL("LINKS") 224 ;** END HL*1.6*117 ** 225 ; 226 D CONT 227 Q 228 ; 229 MSA(Y) ;Y=ien in 772, returns MSA segment 230 ;ack code^msg being ack id^text 231 N X 232 S X=$G(^HL(772,Y,"IN",1,0)),X=$S($E(X,1,3)="MSA":$E(X,5,999),1:"") 233 Q X 234 ; 235 ERROR ;error trap 236 D ^%ZTER 237 I $G(HLMTIENS),$D(^HLMA(HLMTIENS,0)) D STATUS^HLTF0(HLMTIENS,4,,,1),EXIT 238 ;*109* release all locks created by inbound filer 239 L -^HLMA("AC","I",+$G(HLXX)) 240 G UNWIND^%ZTER 241 ; 242 ; 243 EXIT ;unlock 244 I $G(HLMTIENS) L -^HLMA(HLMTIENS) 245 Q 246 ; 247 ONAC(IEN773) ; 248 ;Returns 1 if the message is on the "AC","I" xref 249 ;Returns 0 otherwise 250 ; 251 N LINK 252 S LINK=$P($G(^HLMA(IEN773,0)),"^",17) 253 Q:'LINK 0 254 Q $D(^HLMA("AC","I",LINK,IEN773)) -
WorldVistAEHR/trunk/r/HEALTH_LEVEL_SEVEN-HL/HLTPCK2B.m
r613 r623 1 HLTPCK2B ;OIFO-O/RJH - Message Header Validation (Con't) ;10/04/2007 16:00 2 ;;1.6;HEALTH LEVEL SEVEN;**120,133,122**;Oct 13, 1995;Build 14 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ; splitted from HLTPCK2A 6 ; to be called from HLTPCK2A 7 ; 8 MS ;Check for Message Structure Code 9 I $G(ARY("MTN_ETN"))'="" D 10 . S ARY("MTP_ETP")=0 11 . S ARY("MTP_ETP")=+$O(^HL(779.005,"B",ARY("MTN_ETN"),0)) 12 . I ('ARY("MTP_ETP")) S:(ERR="") ERR="Invalid Message Structure Code" Q 13 ; 14 ;Get server and client Protocols 15 MSA ;if ack, then get information and quit, we don't need to respond 16 I $G(MSA)]"" D Q 17 . ;Message is an acknowledgement, find original message 18 . S ARY("MSAID")=$P(MSA,FS,2),ARY("MTIENS")=0 19 . I ARY("MSAID")="" S:(ERR="") ERR="Invalid Message Control ID in MSA Segment - No Message ID" Q 20 . F S ARY("MTIENS")=+$O(^HLMA("AH",ARY("SAP"),ARY("MSAID"),ARY("MTIENS"))) Q:'ARY("MTIENS")!($P($G(^HLMA(ARY("MTIENS"),0)),U,3)="O") 21 . I 'ARY("MTIENS") S:(ERR="") ERR="Invalid Message Control ID in MSA Segment - No message IEN in ""AH"" x-ref" Q 22 . ;get subscriber protocol and ack. to (show if this is an ack to an ack) 23 . S X=$G(^HLMA(ARY("MTIENS"),0)),ARY("EIDS")=$P(X,U,8),ARY("ACK")=$P(X,U,10) 24 . ;if no subscriber protocol then response msg. is invalid 25 . ; 26 . ; patch HL*1.6*122 start 27 . ; comment out the following code: for patch 109- dynamic addressing 28 . ; I ('ARY("EIDS")) S:(ERR="") ERR="Invalid Message Control ID in MSA Segment - No Subscr. IEN in 773" Q 29 . ;get message text ien in file 772 and server protocol, 'EID' 30 . S ARY("MTIEN")=+X,X=$G(^HL(772,+X,0)),ARY("EID")=$P(X,U,10) 31 . I ('ARY("EID")) S:(ERR="") ERR="Event Protocol not found" Q 32 . ; D EVENT^HLUTIL1(ARY("EIDS"),"770,773",.HLN) 33 . I ARY("EIDS") D EVENT^HLUTIL1(ARY("EIDS"),"770,773",.HLN) 34 . ; patch HL*1.6*122 end 35 ; 36 ;Find Server Protocol - based on sending application, message type, 37 ;event type and version ID 38 I ARY("ETP") S ARY("EID")=+$O(^ORD(101,"AHL1",ARY("SAP"),ARY("MTP"),ARY("ETP"),ARY("VEP"),0)) 39 ; 40 ;Find Server Protocol - based on sending application, message type, 41 ;and version ID 42 I 'ARY("ETP") S ARY("EID")=+$O(^ORD(101,"AHL21",ARY("SAP"),ARY("MTP"),ARY("VEP"),0)) 43 ; 44 I ('ARY("EID")) S:(ERR="") ERR="Event Protocol not found" Q 45 ;Find Client Protocol - in ITEM multiple of Server Protocol 46 S ARY("EIDS")=0 47 F S ARY("EIDS")=+$O(^ORD(101,ARY("EID"),775,"B",ARY("EIDS"))) Q:'ARY("EIDS")!($P($G(^ORD(101,ARY("EIDS"),770)),U,2)=ARY("RAP")) 48 I 'ARY("EIDS") S ERR="Invalid Receiving Application for this Event" Q 49 D EVENT^HLUTIL1(ARY("EIDS"),"770,773",.HLN) 50 ; 51 LLP ;Get logical link pointer 52 S ARY("LL")=$P($G(HLN(770)),"^",7) 53 ; 54 FAC ;Get sending/rec facility, validate if necessary 55 ; 56 S HLCS=$E(ECH,1) ;Get component separator 57 S ARY("RAF")=$$P^HLTPCK2(.HDR,6) ;Receiving Facility 58 S ARY("SAF")=$$P^HLTPCK2(.HDR,4) ;Sending Facility 59 ;Get sending/receiving facility from Application Parameter file(771) 60 S HL771SF=$P($G(^HL(771,ARY("SAP"),0)),U,3) 61 S HL771RF=$P($G(^HL(771,ARY("RAP"),0)),U,3) 62 ;Sending/Receiving facility required? 63 S X=$G(^ORD(101,ARY("EIDS"),773)) 64 S HLSFREQ=+X,HLRFREQ=+$P(X,U,2) 65 RF ;Validate Receiving Facility 66 I HLRFREQ D 67 .I ARY("RAF")="" S:ERR="" ERR="Missing required receiving facility" 68 .I HL771RF]"" D Q 69 ..;Facility data in 771 overrides data in site paramter file 70 ..Q 71 .;Check against local default value (site parameters) 72 .Q:ARY("RAF")=(HLINSTN_HLCS_HLDOM_HLCS_"DNS") 73 .; 74 .; patch HL*1.6*120 start 75 .; I $P(ARY("RAF"),HLCS)=HLINSTN,$P(ARY("RAF"),HLCS,3)="DNS" D Q 76 . I $P(ARY("RAF"),HLCS,3)="DNS" D Q 77 .. N ERROR,HLDOMP1,HLDOMP2 78 .. ; S HLDOMP1=$P(ARY("RAF"),HLCS,2),HLDOMP1=$$FIND1^DIC(4.2,"","BMX",HLDOMP1,"B^C","","ERROR") 79 .. S HLDOMP1=$P(ARY("RAF"),HLCS,2) 80 .. ; 81 .. ; assume the format is <domain>:<port #> 82 .. I HLDOMP1[":" S ARY("RAF-PORT")=$P(HLDOMP1,":",2) 83 .. S HLDOMP1=$P(HLDOMP1,":") 84 .. S ARY("RAF-DOMAIN")=HLDOMP1 85 .. ; 86 .. ; if first piece of domain is "HL7." or "MPI.", remove it 87 .. I ($E(HLDOMP1,1,4)="HL7.")!($E(HLDOMP1,1,4)="MPI.") D 88 ... S HLDOMP1=$P(HLDOMP1,".",2,99) 89 .. S HLDOMP1=$$FIND1^DIC(4.2,"","BMX",HLDOMP1,"B^C","","ERROR") 90 .. S HLDOMP2=HLDOM,HLDOMP2=$$FIND1^DIC(4.2,"","BMX",HLDOMP2,"B^C","","ERROR") 91 .. I HLDOMP1&HLDOMP2&(HLDOMP1=HLDOMP2) Q 92 .. ; 93 .. ; check DNS domain and ip address 94 .. ;initialize variable, HLDOMP("FLAG") 95 .. S HLDOMP("FLAG")=0 96 .. I ARY("RAF-DOMAIN")]"" D 97 ... ; 98 ... ; match DNS domain 99 ... I $D(^HLCS(870,"DNS",ARY("RAF-DOMAIN"))) D Q 100 .... S HLDOMP("FLAG")=1 101 .... S ARY("RAF-LL")=+$O(^HLCS(870,"DNS",ARY("RAF-DOMAIN"),0)) 102 ... I $D(^HLCS(870,"DNS",$$UP^XLFSTR(ARY("RAF-DOMAIN")))) D Q 103 .... S HLDOMP("FLAG")=1 104 .... S ARY("RAF-LL")=+$O(^HLCS(870,"DNS",$$UP^XLFSTR(ARY("RAF-DOMAIN")),0)) 105 ... I $D(^HLCS(870,"DNS",$$LOW^XLFSTR(ARY("RAF-DOMAIN")))) D Q 106 .... S HLDOMP("FLAG")=1 107 .... S ARY("RAF-LL")=+$O(^HLCS(870,"DNS",$$LOW^XLFSTR(ARY("RAF-DOMAIN")),0)) 108 ... ; 109 ... ; match ip address 110 ... I $D(^HLCS(870,"IP",ARY("RAF-DOMAIN"))) D Q 111 .... S HLDOMP("FLAG")=1 112 .... S ARY("RAF-LL")=+$O(^HLCS(870,"IP",ARY("RAF-DOMAIN"),0)) 113 .. Q:HLDOMP("FLAG")=1 114 .. I $P(ARY("RAF"),HLCS)=HLINSTN Q 115 .. ; 116 .. S:ERR="" ERR="Receiving Facility mismatch." 117 . I $P(ARY("RAF"),HLCS)=HLINSTN Q 118 . S:ERR="" ERR="Receiving Facility mismatch." 119 ; patch HL*1.6*120 end 120 ; 121 SF ;Validate Sending Facility 122 I HLSFREQ D 123 .I ARY("SAF")="" S:ERR="" ERR="Missing required sending facility" 124 .I HL771SF]"" D Q 125 ..;Check for facility data in 771 126 ..Q 127 .;If default value was sent, validate that DOMAIN RESOLVES TO LOGICAL LINK 128 .;If so, use this instead of Protocol definition for return path 129 .; 130 .; patch HL*1.6*120 start 131 . N HLDOMP 132 . ; S HLDOMP=$P(ARY("SAF"),HLCS,2),HLDOMP=$$FIND1^DIC(4.2,"","BMX",HLDOMP,"B^C","","ERROR") 133 . S HLDOMP=$P(ARY("SAF"),HLCS,2) 134 . ; 135 . ; assume the format is <domain>:<port #> 136 . I HLDOMP[":" S ARY("SAF-PORT")=$P(HLDOMP,":",2) 137 . S HLDOMP=$P(HLDOMP,":") 138 . S ARY("SAF-DOMAIN")=HLDOMP 139 . ; 140 . ; if first piece of domain is "HL7." or "MPI.", remove it 141 . I ($E(HLDOMP,1,4)="HL7.")!($E(HLDOMP,1,4)="MPI.") D 142 .. S HLDOMP=$P(HLDOMP,".",2,99) 143 . S HLDOMP=$$FIND1^DIC(4.2,"","BMX",HLDOMP,"B^C","","ERROR") 144 .;Note: This expects a unique domain in domain file. Multiple entries will fail 145 . ; I 'HLDOMP S:ERR="" ERR="Unrecognized/ambiguous domain in sending facility" 146 . ; 147 . ; check DNS domain and ip address 148 . I 'HLDOMP D 149 .. ; 150 .. ;initialize variable, HLDOMP("FLAG") 151 .. S HLDOMP("FLAG")=0 152 .. I ARY("SAF-DOMAIN")]"" D 153 ... ; 154 ... ; match DNS domain 155 ... I $D(^HLCS(870,"DNS",ARY("SAF-DOMAIN"))) D Q 156 .... S HLDOMP("FLAG")=1 157 .... S ARY("SAF-LL")=+$O(^HLCS(870,"DNS",ARY("SAF-DOMAIN"),0)) 158 ... I $D(^HLCS(870,"DNS",$$UP^XLFSTR(ARY("SAF-DOMAIN")))) D Q 159 .... S HLDOMP("FLAG")=1 160 .... S ARY("SAF-LL")=+$O(^HLCS(870,"DNS",$$UP^XLFSTR(ARY("SAF-DOMAIN")),0)) 161 ... I $D(^HLCS(870,"DNS",$$LOW^XLFSTR(ARY("SAF-DOMAIN")))) D Q 162 .... S HLDOMP("FLAG")=1 163 .... S ARY("SAF-LL")=+$O(^HLCS(870,"DNS",$$LOW^XLFSTR(ARY("SAF-DOMAIN")),0)) 164 ... ; 165 ... ; match ip address 166 ... I $D(^HLCS(870,"IP",ARY("SAF-DOMAIN"))) D Q 167 .... S HLDOMP("FLAG")=1 168 .... S ARY("SAF-LL")=+$O(^HLCS(870,"IP",ARY("SAF-DOMAIN"),0)) 169 .. Q:HLDOMP("FLAG")=1 170 .. ; quit if 1st component defined 171 .. S ARY("SAF-COMPONENT1")=$P(ARY("SAF"),HLCS,1) 172 .. Q:ARY("SAF-COMPONENT1")]"" 173 .. S:ERR="" ERR="Receiving Facility mismatch." 174 . ; patch HL*1.6*120 end 175 . ; 176 .Q:HLDOMP=$P(HLPARAM,U) ;This is local app to app 177 .I HLDOMP N HLNK S HLNK=+$O(^HLCS(870,"D",HLDOMP,0)) 178 .I $G(HLNK) S ARY("LL")=HLNK 179 ; 180 PID ;Validate processing ID 181 I ("DTP"'[ARY("PID")) S:(ERR="") ERR="Invalid HL7 Processing ID" 182 S HLPID=$P(HLPARAM,U,3) ;site param 183 S X=$G(^ORD(101,ARY("EID"),770)),X=$P(X,U,6) ;event driver 184 ;If message is 'debug' then event driver must be 'debug.' 185 ;If message is 'test' or 'production', then site param must match 186 I ARY("PID")="D"&(X'="D") S:ERR="" ERR="Processing ID Mismatch with Event Driver" 187 I ARY("PID")'="D"&(HLPID'=ARY("PID")) S:ERR="" ERR="Processing ID Mismatch with Site Parameters" 188 ; 189 SEC ;Validate security field - access code and electronic signature 190 I ($P($G(HLN(773)),"^",3)) D 191 .S X=$P($$P^HLTPCK2(.HDR,8),$E(ECH)) 192 .S X=$$UPPER^HLFNC(X) 193 .D ^XUSHSH 194 .I X="",(MSA="") S:(ERR="") ERR="Invalid access code" Q 195 .S ARY("DUZ")=0 196 .S:(X'="") ARY("DUZ")=+$O(^VA(200,"A",X,0)) 197 .I ('ARY("DUZ")) S:(ERR="") ERR="Invalid access code" Q 198 .I (($P($G(^VA(200,ARY("DUZ"),.1)),"^")="")&('$D(MSA))) S ARY("DUZ")=0 S:(ERR="") ERR="Invalid access code" Q 199 .S X=$P($$P^HLTPCK2(.HDR,8),$E(ECH),3) I (X'="") D 200 ..S X1=$G(^VA(200,ARY("DUZ"),20)) 201 ..I (X1="") S:(ERR="") ERR="No Signature Code on File" Q 202 ..S X=$$UPPER^HLFNC(X) 203 ..D HASH^XUSHSHP 204 ..I ((X'=$P(X1,"^",4))!($P(X1,"^",2)="")) S:(ERR="") ERR="Invalid Electronic Signature Code" Q 205 ..S ARY("ESIG")=$P(X1,"^",2) 206 I $D(ARY) M HLREC=ARY 207 Q 1 HLTPCK2B ;OIFO-O/RJH - Message Header Validation (Con't) ;09/13/2006 2 ;;1.6;HEALTH LEVEL SEVEN;**120,133**;Oct 13, 1995;Build 13 3 ;Per VHA Directive 2004-038, this routine should not be modified. 4 ; 5 ; splitted from HLTPCK2A 6 ; to be called from HLTPCK2A 7 ; 8 MS ;Check for Message Structure Code 9 I $G(ARY("MTN_ETN"))'="" D 10 . S ARY("MTP_ETP")=0 11 . S ARY("MTP_ETP")=+$O(^HL(779.005,"B",ARY("MTN_ETN"),0)) 12 . I ('ARY("MTP_ETP")) S:(ERR="") ERR="Invalid Message Structure Code" Q 13 ; 14 ;Get server and client Protocols 15 MSA ;if ack, then get information and quit, we don't need to respond 16 I $G(MSA)]"" D Q 17 . ;Message is an acknowledgement, find original message 18 . S ARY("MSAID")=$P(MSA,FS,2),ARY("MTIENS")=0 19 . I ARY("MSAID")="" S:(ERR="") ERR="Invalid Message Control ID in MSA Segment - No Message ID" Q 20 . F S ARY("MTIENS")=+$O(^HLMA("AH",ARY("SAP"),ARY("MSAID"),ARY("MTIENS"))) Q:'ARY("MTIENS")!($P($G(^HLMA(ARY("MTIENS"),0)),U,3)="O") 21 . I 'ARY("MTIENS") S:(ERR="") ERR="Invalid Message Control ID in MSA Segment - No message IEN in ""AH"" x-ref" Q 22 . ;get subscriber protocol and ack. to (show if this is an ack to an ack) 23 . S X=$G(^HLMA(ARY("MTIENS"),0)),ARY("EIDS")=$P(X,U,8),ARY("ACK")=$P(X,U,10) 24 . ;if no subscriber protocol then response msg. is invalid 25 . I ('ARY("EIDS")) S:(ERR="") ERR="Invalid Message Control ID in MSA Segment - No Subscr. IEN in 773" Q 26 . ;get message text ien in file 772 and server protocol, 'EID' 27 . S ARY("MTIEN")=+X,X=$G(^HL(772,+X,0)),ARY("EID")=$P(X,U,10) 28 . I ('ARY("EID")) S:(ERR="") ERR="Event Protocol not found" Q 29 . D EVENT^HLUTIL1(ARY("EIDS"),"770,773",.HLN) 30 ; 31 ;Find Server Protocol - based on sending application, message type, 32 ;event type and version ID 33 I ARY("ETP") S ARY("EID")=+$O(^ORD(101,"AHL1",ARY("SAP"),ARY("MTP"),ARY("ETP"),ARY("VEP"),0)) 34 ; 35 ;Find Server Protocol - based on sending application, message type, 36 ;and version ID 37 I 'ARY("ETP") S ARY("EID")=+$O(^ORD(101,"AHL21",ARY("SAP"),ARY("MTP"),ARY("VEP"),0)) 38 ; 39 I ('ARY("EID")) S:(ERR="") ERR="Event Protocol not found" Q 40 ;Find Client Protocol - in ITEM multiple of Server Protocol 41 S ARY("EIDS")=0 42 F S ARY("EIDS")=+$O(^ORD(101,ARY("EID"),775,"B",ARY("EIDS"))) Q:'ARY("EIDS")!($P($G(^ORD(101,ARY("EIDS"),770)),U,2)=ARY("RAP")) 43 I 'ARY("EIDS") S ERR="Invalid Receiving Application for this Event" Q 44 D EVENT^HLUTIL1(ARY("EIDS"),"770,773",.HLN) 45 ; 46 LLP ;Get logical link pointer 47 S ARY("LL")=$P($G(HLN(770)),"^",7) 48 ; 49 FAC ;Get sending/rec facility, validate if necessary 50 ; 51 S HLCS=$E(ECH,1) ;Get component separator 52 S ARY("RAF")=$$P^HLTPCK2(.HDR,6) ;Receiving Facility 53 S ARY("SAF")=$$P^HLTPCK2(.HDR,4) ;Sending Facility 54 ;Get sending/receiving facility from Application Parameter file(771) 55 S HL771SF=$P($G(^HL(771,ARY("SAP"),0)),U,3) 56 S HL771RF=$P($G(^HL(771,ARY("RAP"),0)),U,3) 57 ;Sending/Receiving facility required? 58 S X=$G(^ORD(101,ARY("EIDS"),773)) 59 S HLSFREQ=+X,HLRFREQ=+$P(X,U,2) 60 RF ;Validate Receiving Facility 61 I HLRFREQ D 62 .I ARY("RAF")="" S:ERR="" ERR="Missing required receiving facility" 63 .I HL771RF]"" D Q 64 ..;Facility data in 771 overrides data in site paramter file 65 ..Q 66 .;Check against local default value (site parameters) 67 .Q:ARY("RAF")=(HLINSTN_HLCS_HLDOM_HLCS_"DNS") 68 .; 69 .; patch HL*1.6*120 start 70 .; I $P(ARY("RAF"),HLCS)=HLINSTN,$P(ARY("RAF"),HLCS,3)="DNS" D Q 71 . I $P(ARY("RAF"),HLCS,3)="DNS" D Q 72 .. N ERROR,HLDOMP1,HLDOMP2 73 .. ; S HLDOMP1=$P(ARY("RAF"),HLCS,2),HLDOMP1=$$FIND1^DIC(4.2,"","BMX",HLDOMP1,"B^C","","ERROR") 74 .. S HLDOMP1=$P(ARY("RAF"),HLCS,2) 75 .. ; 76 .. ; assume the format is <domain>:<port #> 77 .. I HLDOMP1[":" S ARY("RAF-PORT")=$P(HLDOMP1,":",2) 78 .. S HLDOMP1=$P(HLDOMP1,":") 79 .. S ARY("RAF-DOMAIN")=HLDOMP1 80 .. ; 81 .. ; if first piece of domain is "HL7." or "MPI.", remove it 82 .. I ($E(HLDOMP1,1,4)="HL7.")!($E(HLDOMP1,1,4)="MPI.") D 83 ... S HLDOMP1=$P(HLDOMP1,".",2,99) 84 .. S HLDOMP1=$$FIND1^DIC(4.2,"","BMX",HLDOMP1,"B^C","","ERROR") 85 .. S HLDOMP2=HLDOM,HLDOMP2=$$FIND1^DIC(4.2,"","BMX",HLDOMP2,"B^C","","ERROR") 86 .. I HLDOMP1&HLDOMP2&(HLDOMP1=HLDOMP2) Q 87 .. ; 88 .. ; check DNS domain and ip address 89 .. ;initialize variable, HLDOMP("FLAG") 90 .. S HLDOMP("FLAG")=0 91 .. I ARY("RAF-DOMAIN")]"" D 92 ... ; 93 ... ; match DNS domain 94 ... I $D(^HLCS(870,"DNS",ARY("RAF-DOMAIN"))) D Q 95 .... S HLDOMP("FLAG")=1 96 .... S ARY("RAF-LL")=+$O(^HLCS(870,"DNS",ARY("RAF-DOMAIN"),0)) 97 ... I $D(^HLCS(870,"DNS",$$UP^XLFSTR(ARY("RAF-DOMAIN")))) D Q 98 .... S HLDOMP("FLAG")=1 99 .... S ARY("RAF-LL")=+$O(^HLCS(870,"DNS",$$UP^XLFSTR(ARY("RAF-DOMAIN")),0)) 100 ... I $D(^HLCS(870,"DNS",$$LOW^XLFSTR(ARY("RAF-DOMAIN")))) D Q 101 .... S HLDOMP("FLAG")=1 102 .... S ARY("RAF-LL")=+$O(^HLCS(870,"DNS",$$LOW^XLFSTR(ARY("RAF-DOMAIN")),0)) 103 ... ; 104 ... ; match ip address 105 ... I $D(^HLCS(870,"IP",ARY("RAF-DOMAIN"))) D Q 106 .... S HLDOMP("FLAG")=1 107 .... S ARY("RAF-LL")=+$O(^HLCS(870,"IP",ARY("RAF-DOMAIN"),0)) 108 .. Q:HLDOMP("FLAG")=1 109 .. I $P(ARY("RAF"),HLCS)=HLINSTN Q 110 .. ; 111 .. S:ERR="" ERR="Receiving Facility mismatch." 112 . I $P(ARY("RAF"),HLCS)=HLINSTN Q 113 . S:ERR="" ERR="Receiving Facility mismatch." 114 ; patch HL*1.6*120 end 115 ; 116 SF ;Validate Sending Facility 117 I HLSFREQ D 118 .I ARY("SAF")="" S:ERR="" ERR="Missing required sending facility" 119 .I HL771SF]"" D Q 120 ..;Check for facility data in 771 121 ..Q 122 .;If default value was sent, validate that DOMAIN RESOLVES TO LOGICAL LINK 123 .;If so, use this instead of Protocol definition for return path 124 .; 125 .; patch HL*1.6*120 start 126 . N HLDOMP 127 . ; S HLDOMP=$P(ARY("SAF"),HLCS,2),HLDOMP=$$FIND1^DIC(4.2,"","BMX",HLDOMP,"B^C","","ERROR") 128 . S HLDOMP=$P(ARY("SAF"),HLCS,2) 129 . ; 130 . ; assume the format is <domain>:<port #> 131 . I HLDOMP[":" S ARY("SAF-PORT")=$P(HLDOMP,":",2) 132 . S HLDOMP=$P(HLDOMP,":") 133 . S ARY("SAF-DOMAIN")=HLDOMP 134 . ; 135 . ; if first piece of domain is "HL7." or "MPI.", remove it 136 . I ($E(HLDOMP,1,4)="HL7.")!($E(HLDOMP,1,4)="MPI.") D 137 .. S HLDOMP=$P(HLDOMP,".",2,99) 138 . S HLDOMP=$$FIND1^DIC(4.2,"","BMX",HLDOMP,"B^C","","ERROR") 139 .;Note: This expects a unique domain in domain file. Multiple entries will fail 140 . ; I 'HLDOMP S:ERR="" ERR="Unrecognized/ambiguous domain in sending facility" 141 . ; 142 . ; check DNS domain and ip address 143 . I 'HLDOMP D 144 .. ; 145 .. ;initialize variable, HLDOMP("FLAG") 146 .. S HLDOMP("FLAG")=0 147 .. I ARY("SAF-DOMAIN")]"" D 148 ... ; 149 ... ; match DNS domain 150 ... I $D(^HLCS(870,"DNS",ARY("SAF-DOMAIN"))) D Q 151 .... S HLDOMP("FLAG")=1 152 .... S ARY("SAF-LL")=+$O(^HLCS(870,"DNS",ARY("SAF-DOMAIN"),0)) 153 ... I $D(^HLCS(870,"DNS",$$UP^XLFSTR(ARY("SAF-DOMAIN")))) D Q 154 .... S HLDOMP("FLAG")=1 155 .... S ARY("SAF-LL")=+$O(^HLCS(870,"DNS",$$UP^XLFSTR(ARY("SAF-DOMAIN")),0)) 156 ... I $D(^HLCS(870,"DNS",$$LOW^XLFSTR(ARY("SAF-DOMAIN")))) D Q 157 .... S HLDOMP("FLAG")=1 158 .... S ARY("SAF-LL")=+$O(^HLCS(870,"DNS",$$LOW^XLFSTR(ARY("SAF-DOMAIN")),0)) 159 ... ; 160 ... ; match ip address 161 ... I $D(^HLCS(870,"IP",ARY("SAF-DOMAIN"))) D Q 162 .... S HLDOMP("FLAG")=1 163 .... S ARY("SAF-LL")=+$O(^HLCS(870,"IP",ARY("SAF-DOMAIN"),0)) 164 .. Q:HLDOMP("FLAG")=1 165 .. ; quit if 1st component defined 166 .. S ARY("SAF-COMPONENT1")=$P(ARY("SAF"),HLCS,1) 167 .. Q:ARY("SAF-COMPONENT1")]"" 168 .. S:ERR="" ERR="Receiving Facility mismatch." 169 . ; patch HL*1.6*120 end 170 . ; 171 .Q:HLDOMP=$P(HLPARAM,U) ;This is local app to app 172 .I HLDOMP N HLNK S HLNK=+$O(^HLCS(870,"D",HLDOMP,0)) 173 .I $G(HLNK) S ARY("LL")=HLNK 174 ; 175 PID ;Validate processing ID 176 I ("DTP"'[ARY("PID")) S:(ERR="") ERR="Invalid HL7 Processing ID" 177 S HLPID=$P(HLPARAM,U,3) ;site param 178 S X=$G(^ORD(101,ARY("EID"),770)),X=$P(X,U,6) ;event driver 179 ;If message is 'debug' then event driver must be 'debug.' 180 ;If message is 'test' or 'production', then site param must match 181 I ARY("PID")="D"&(X'="D") S:ERR="" ERR="Processing ID Mismatch with Event Driver" 182 I ARY("PID")'="D"&(HLPID'=ARY("PID")) S:ERR="" ERR="Processing ID Mismatch with Site Parameters" 183 ; 184 SEC ;Validate security field - access code and electronic signature 185 I ($P($G(HLN(773)),"^",3)) D 186 .S X=$P($$P^HLTPCK2(.HDR,8),$E(ECH)) 187 .S X=$$UPPER^HLFNC(X) 188 .D ^XUSHSH 189 .I X="",(MSA="") S:(ERR="") ERR="Invalid access code" Q 190 .S ARY("DUZ")=0 191 .S:(X'="") ARY("DUZ")=+$O(^VA(200,"A",X,0)) 192 .I ('ARY("DUZ")) S:(ERR="") ERR="Invalid access code" Q 193 .I (($P($G(^VA(200,ARY("DUZ"),.1)),"^")="")&('$D(MSA))) S ARY("DUZ")=0 S:(ERR="") ERR="Invalid access code" Q 194 .S X=$P($$P^HLTPCK2(.HDR,8),$E(ECH),3) I (X'="") D 195 ..S X1=$G(^VA(200,ARY("DUZ"),20)) 196 ..I (X1="") S:(ERR="") ERR="No Signature Code on File" Q 197 ..S X=$$UPPER^HLFNC(X) 198 ..D HASH^XUSHSHP 199 ..I ((X'=$P(X1,"^",4))!($P(X1,"^",2)="")) S:(ERR="") ERR="Invalid Electronic Signature Code" Q 200 ..S ARY("ESIG")=$P(X1,"^",2) 201 I $D(ARY) M HLREC=ARY 202 Q
Note:
See TracChangeset
for help on using the changeset viewer.