- HLOCLNT1 ;IRMFO-ALB/CJM - Writing messages, reading acks;03/24/2004 14:43
- ;;1.6;HEALTH LEVEL SEVEN;**126,130,131**;Oct 13, 1995;Build 10
- ;
- ;
- WRITEMSG(HLCSTATE,HLMSTATE) ;
- ;Description: This function uses the services offered by the transport layer to send a message over an open communication channel.
- ;
- ;Input:
- ; HLCSTATE (pass by reference, required) Defines the LLP & its state
- ; HLMSTATE (pass by reference, required) The message
- ;Output:
- ; Function returns 1 on success, 0 on failure
- ;
- N SEG,QUIT,HDR
- S QUIT=0
- Q:'$G(HLMSTATE("IEN")) 0
- S HDR(1)=HLMSTATE("HDR",1),HDR(2)=HLMSTATE("HDR",2)
- Q:'$$WRITEHDR^HLOT(.HLCSTATE,.HDR) 0
- I HLMSTATE("BATCH") D
- .N LAST S LAST=0
- .S HLMSTATE("BATCH","CURRENT MESSAGE")=0
- .F Q:'$$NEXTMSG^HLOMSG(.HLMSTATE,.SEG) D Q:QUIT
- ..S LAST=HLMSTATE("BATCH","CURRENT MESSAGE")
- ..I '$$WRITESEG^HLOT(.HLCSTATE,.SEG) S QUIT=1 Q
- ..F Q:'$$HLNEXT^HLOMSG(.HLMSTATE,.SEG) D Q:QUIT
- ...I '$$WRITESEG^HLOT(.HLCSTATE,.SEG) S QUIT=1 Q
- .K SEG S SEG(1)="BTS"_HLMSTATE("HDR","FIELD SEPARATOR")_LAST
- .S:'$$WRITESEG^HLOT(.HLCSTATE,.SEG) QUIT=1
- E D
- .F Q:'$$HLNEXT^HLOMSG(.HLMSTATE,.SEG) D Q:QUIT
- ..S:'$$WRITESEG^HLOT(.HLCSTATE,.SEG) QUIT=1
- S:'$$ENDMSG^HLOT(.HLCSTATE) QUIT=1
- Q 'QUIT
- ;
- READACK(HLCSTATE,HDR,MSA) ;
- ;Description: This function uses the services offered by the transport layer to read an accept ack.
- ;
- ;Input:
- ; HLCSTATE (pass by reference, required) Defines the communication channel and its state.
- ;Output:
- ; Function returns 1 on success, 0 on failure
- ; HDR (pass by reference) the message header:
- ; HDR(1) is components 1-6
- ; HDR(2) is components 7-end
- ; MSA (pass by reference) the MSA segment as an unsubscripted variable
- ;
- N SEG
- K HDR,MSA,MAX,I
- 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
- Q:'$$READHDR^HLOT(.HLCSTATE,.HDR) 0
- F Q:'$$READSEG^HLOT(.HLCSTATE,.SEG) D
- .I $E($E(SEG(1),1,3)_$E($G(SEG(2)),1,3),1,3)="MSA" D
- ..S MSA=""
- ..F I=1:1 Q:'$D(SEG(I)) S MSA=MSA_$S((MAX-$L(MSA))<1:"",1:$E(SEG(I),1,MAX))
- I $D(MSA),HLCSTATE("MESSAGE ENDED") D Q 1
- .D SPLITHDR^HLOSRVR1(.HDR)
- .S HLCSTATE("COUNTS","ACKS")=$G(HLCSTATE("COUNTS","ACKS"))+1
- Q 0
- ;
- CONNECT(LINK,PORT,TIMEOUT,HLCSTATE) ;
- ;sets up HLCSTATE() and opens a client connection
- ;Input:
- ; LINK - name of the link to connect to
- ; PORT (optional) port # to connect to, defaults to that specified by the link
- ; TIMEOUT (optional) specifies the open timeout in seconds, defaults to 30
- ;Output:
- ; HLCSTATE - array to hold the connection state
- ;
- I $G(HLCSTATE("CONNECTED")) D Q:HLCSTATE("CONNECTED")
- .I $G(HLCSTATE("LINK","NAME"))]"",($G(HLCSTATE("LINK","NAME"))'=LINK) D CLOSE^HLOT(.HLCSTATE) Q
- .I $G(HLCSTATE("LINK","NAME"))]"",$G(PORT),($G(HLCSTATE("LINK","PORT"))'=PORT) D CLOSE^HLOT(.HLCSTATE) Q
- .I (HLCSTATE("SYSTEM","OS")="CACHE") D Q
- ..U HLCSTATE("DEVICE") S HLCSTATE("CONNECTED")=($ZA\8192#2)
- ..I 'HLCSTATE("CONNECTED") D CLOSE^HLOT(.HLCSTATE)
- .;D CLOSE^HLOT(.HLCSTATE)
- K HLCSTATE
- N ARY,NODE
- I '$$GETLINK^HLOTLNK(LINK,.ARY) S HLCSTATE("LINK","NAME")=LINK,HLCSTATE("LINK","PORT")=$G(PORT) D LINKDOWN^HLOCLNT(.HLCSTATE) Q 0
- M HLCSTATE("LINK")=ARY
- I HLCSTATE("LINK","SHUTDOWN") S HLCSTATE("CONNECTED")=0 D LINKDOWN^HLOCLNT(.HLCSTATE) Q 0
- ;overlay the port if supplied from the queue
- S:$G(PORT) HLCSTATE("LINK","PORT")=PORT
- S HLCSTATE("READ TIMEOUT")=20
- S HLCSTATE("OPEN TIMEOUT")=$S($G(TIMEOUT):TIMEOUT,1:30)
- S HLCSTATE("COUNTS")=0
- S HLCSTATE("READ")="" ;where the reads are stored
- ;
- ;HLCSTATE("BUFFER",<seg>,<line>) serves as a write buffer so that a lot can be written all at once
- S HLCSTATE("BUFFER","BYTE COUNT")=0 ;count of BYTES in buffer
- S HLCSTATE("BUFFER","SEGMENT COUNT")=0 ;count of segments in buffer
- ;
- S HLCSTATE("MESSAGE ENDED")=0 ;end of message flag
- S NODE=^%ZOSF("OS")
- S HLCSTATE("SERVER")=0
- S HLCSTATE("SYSTEM","OS")=$S(NODE["DSM":"DSM",NODE["OpenM":"CACHE",NODE["G.TM":"G.TM",1:"")
- I HLCSTATE("SYSTEM","OS")="" D LINKDOWN^HLOCLNT(.HLCSTATE) Q 0
- D
- .N SYS
- .D SYSPARMS^HLOSITE(.SYS)
- .S HLCSTATE("SYSTEM","BUFFER")=SYS("HL7 BUFFER")
- .S HLCSTATE("SYSTEM","MAXSTRING")=SYS("MAXSTRING")
- .S HLCSTATE("SYSTEM","NORMAL PURGE")=SYS("NORMAL PURGE")
- .S HLCSTATE("SYSTEM","ERROR PURGE")=SYS("ERROR PURGE")
- I HLCSTATE("LINK","LLP")="TCP" D
- .S HLCSTATE("OPEN")="OPEN^HLOTCP"
- E ;no other LLP implemented
- D OPEN^HLOT(.HLCSTATE)
- ;
- ;mark the failure time for the link so other processes know not to try for a while
- I 'HLCSTATE("CONNECTED") D LINKDOWN^HLOCLNT(.HLCSTATE)
- Q HLCSTATE("CONNECTED")
- ;
- BADMSGS(WORK) ;
- ;finds messages that won't transmit and takes them off the outgoing queue
- N LINK
- S LINK=""
- F S LINK=$O(^HLTMP("FAILING LINKS",LINK)) Q:LINK="" D
- .N TIME,QUE,COUNT
- .S TIME=$G(^HLTMP("FAILING LINKS",LINK)) Q:TIME=""
- .Q:$$HDIFF^XLFDT($H,TIME,2)<7200
- .Q:'$$IFOPEN^HLOUSR1(LINK)
- .L +^HLB("QUEUE","OUT",LINK):0
- .S QUE=""
- .F S QUE=$O(^HLB("QUEUE","OUT",LINK,QUE)) Q:QUE="" D
- ..N MSG S MSG=0
- ..S MSG=$O(^HLB("QUEUE","OUT",LINK,QUE,MSG))
- ..Q:'MSG
- ..S COUNT=$G(^HLB(MSG,"TRIES"))
- ..I COUNT>20 D
- ...N NODE,TIME,APP,FS,ACTION
- ...S NODE=$G(^HLB(MSG,0))
- ...Q:'$P(NODE,"^",2)
- ...S TIME=+$G(^HLA($P(NODE,"^",2),0))
- ...S NODE=$G(^HLB(MSG,1))
- ...S FS=$E(NODE,4)
- ...Q:FS=""
- ...S APP=$P(NODE,FS,3)
- ...Q:APP=""
- ...S $P(^HLB(MSG,0),"^",21)=COUNT_" FAILED TRANSMISSIONS"
- ...S $P(^HLB(MSG,0),"^",20)="TF"
- ...S ^HLB("ERRORS","TF",APP,TIME,MSG)=""
- ...S ACTION=$P(NODE,"^",14,15)
- ...I ACTION'="^",ACTION]"" D INQUE^HLOQUE(LINK,QUE,MSG,ACTION,1)
- ...D DEQUE^HLOQUE(LINK,QUE,"OUT",MSG)
- .L -^HLB("QUEUE","OUT",LINK)
- Q
- HLOCLNT1 ;IRMFO-ALB/CJM - Writing messages, reading acks;03/24/2004 14:43
- +1 ;;1.6;HEALTH LEVEL SEVEN;**126,130,131**;Oct 13, 1995;Build 10
- +2 ;
- +3 ;
- WRITEMSG(HLCSTATE,HLMSTATE) ;
- +1 ;Description: This function uses the services offered by the transport layer to send a message over an open communication channel.
- +2 ;
- +3 ;Input:
- +4 ; HLCSTATE (pass by reference, required) Defines the LLP & its state
- +5 ; HLMSTATE (pass by reference, required) The message
- +6 ;Output:
- +7 ; Function returns 1 on success, 0 on failure
- +8 ;
- +9 NEW SEG,QUIT,HDR
- +10 SET QUIT=0
- +11 IF '$GET(HLMSTATE("IEN"))
- QUIT 0
- +12 SET HDR(1)=HLMSTATE("HDR",1)
- SET HDR(2)=HLMSTATE("HDR",2)
- +13 IF '$$WRITEHDR^HLOT(.HLCSTATE,.HDR)
- QUIT 0
- +14 IF HLMSTATE("BATCH")
- Begin DoDot:1
- +15 NEW LAST
- SET LAST=0
- +16 SET HLMSTATE("BATCH","CURRENT MESSAGE")=0
- +17 FOR
- IF '$$NEXTMSG^HLOMSG(.HLMSTATE,.SEG)
- QUIT
- Begin DoDot:2
- +18 SET LAST=HLMSTATE("BATCH","CURRENT MESSAGE")
- +19 IF '$$WRITESEG^HLOT(.HLCSTATE,.SEG)
- SET QUIT=1
- QUIT
- +20 FOR
- IF '$$HLNEXT^HLOMSG(.HLMSTATE,.SEG)
- QUIT
- Begin DoDot:3
- +21 IF '$$WRITESEG^HLOT(.HLCSTATE,.SEG)
- SET QUIT=1
- QUIT
- End DoDot:3
- IF QUIT
- QUIT
- End DoDot:2
- IF QUIT
- QUIT
- +22 KILL SEG
- SET SEG(1)="BTS"_HLMSTATE("HDR","FIELD SEPARATOR")_LAST
- +23 IF '$$WRITESEG^HLOT(.HLCSTATE,.SEG)
- SET QUIT=1
- End DoDot:1
- +24 IF '$TEST
- Begin DoDot:1
- +25 FOR
- IF '$$HLNEXT^HLOMSG(.HLMSTATE,.SEG)
- QUIT
- Begin DoDot:2
- +26 IF '$$WRITESEG^HLOT(.HLCSTATE,.SEG)
- SET QUIT=1
- End DoDot:2
- IF QUIT
- QUIT
- End DoDot:1
- +27 IF '$$ENDMSG^HLOT(.HLCSTATE)
- SET QUIT=1
- +28 QUIT 'QUIT
- +29 ;
- READACK(HLCSTATE,HDR,MSA) ;
- +1 ;Description: This function uses the services offered by the transport layer to read an accept ack.
- +2 ;
- +3 ;Input:
- +4 ; HLCSTATE (pass by reference, required) Defines the communication channel and its state.
- +5 ;Output:
- +6 ; Function returns 1 on success, 0 on failure
- +7 ; HDR (pass by reference) the message header:
- +8 ; HDR(1) is components 1-6
- +9 ; HDR(2) is components 7-end
- +10 ; MSA (pass by reference) the MSA segment as an unsubscripted variable
- +11 ;
- +12 NEW SEG
- +13 KILL HDR,MSA,MAX,I
- +14 ;MAX is the maximum that can be safely stored on a node, leaving room for the other fields stored with MSA seg
- SET MAX=HLCSTATE("SYSTEM","MAXSTRING")-40
- +15 IF '$$READHDR^HLOT(.HLCSTATE,.HDR)
- QUIT 0
- +16 FOR
- IF '$$READSEG^HLOT(.HLCSTATE,.SEG)
- QUIT
- Begin DoDot:1
- +17 IF $EXTRACT($EXTRACT(SEG(1),1,3)_$EXTRACT($GET(SEG(2)),1,3),1,3)="MSA"
- Begin DoDot:2
- +18 SET MSA=""
- +19 FOR I=1:1
- IF '$DATA(SEG(I))
- QUIT
- SET MSA=MSA_$SELECT((MAX-$LENGTH(MSA))<1:"",1:$EXTRACT(SEG(I),1,MAX))
- End DoDot:2
- End DoDot:1
- +20 IF $DATA(MSA)
- IF HLCSTATE("MESSAGE ENDED")
- Begin DoDot:1
- +21 DO SPLITHDR^HLOSRVR1(.HDR)
- +22 SET HLCSTATE("COUNTS","ACKS")=$GET(HLCSTATE("COUNTS","ACKS"))+1
- End DoDot:1
- QUIT 1
- +23 QUIT 0
- +24 ;
- CONNECT(LINK,PORT,TIMEOUT,HLCSTATE) ;
- +1 ;sets up HLCSTATE() and opens a client connection
- +2 ;Input:
- +3 ; LINK - name of the link to connect to
- +4 ; PORT (optional) port # to connect to, defaults to that specified by the link
- +5 ; TIMEOUT (optional) specifies the open timeout in seconds, defaults to 30
- +6 ;Output:
- +7 ; HLCSTATE - array to hold the connection state
- +8 ;
- +9 IF $GET(HLCSTATE("CONNECTED"))
- Begin DoDot:1
- +10 IF $GET(HLCSTATE("LINK","NAME"))]""
- IF ($GET(HLCSTATE("LINK","NAME"))'=LINK)
- DO CLOSE^HLOT(.HLCSTATE)
- QUIT
- +11 IF $GET(HLCSTATE("LINK","NAME"))]""
- IF $GET(PORT)
- IF ($GET(HLCSTATE("LINK","PORT"))'=PORT)
- DO CLOSE^HLOT(.HLCSTATE)
- QUIT
- +12 IF (HLCSTATE("SYSTEM","OS")="CACHE")
- Begin DoDot:2
- +13 USE HLCSTATE("DEVICE")
- SET HLCSTATE("CONNECTED")=($ZA\8192#2)
- +14 IF 'HLCSTATE("CONNECTED")
- DO CLOSE^HLOT(.HLCSTATE)
- End DoDot:2
- QUIT
- +15 ;D CLOSE^HLOT(.HLCSTATE)
- End DoDot:1
- IF HLCSTATE("CONNECTED")
- QUIT
- +16 KILL HLCSTATE
- +17 NEW ARY,NODE
- +18 IF '$$GETLINK^HLOTLNK(LINK,.ARY)
- SET HLCSTATE("LINK","NAME")=LINK
- SET HLCSTATE("LINK","PORT")=$GET(PORT)
- DO LINKDOWN^HLOCLNT(.HLCSTATE)
- QUIT 0
- +19 MERGE HLCSTATE("LINK")=ARY
- +20 IF HLCSTATE("LINK","SHUTDOWN")
- SET HLCSTATE("CONNECTED")=0
- DO LINKDOWN^HLOCLNT(.HLCSTATE)
- QUIT 0
- +21 ;overlay the port if supplied from the queue
- +22 IF $GET(PORT)
- SET HLCSTATE("LINK","PORT")=PORT
- +23 SET HLCSTATE("READ TIMEOUT")=20
- +24 SET HLCSTATE("OPEN TIMEOUT")=$SELECT($GET(TIMEOUT):TIMEOUT,1:30)
- +25 SET HLCSTATE("COUNTS")=0
- +26 ;where the reads are stored
- SET HLCSTATE("READ")=""
- +27 ;
- +28 ;HLCSTATE("BUFFER",<seg>,<line>) serves as a write buffer so that a lot can be written all at once
- +29 ;count of BYTES in buffer
- SET HLCSTATE("BUFFER","BYTE COUNT")=0
- +30 ;count of segments in buffer
- SET HLCSTATE("BUFFER","SEGMENT COUNT")=0
- +31 ;
- +32 ;end of message flag
- SET HLCSTATE("MESSAGE ENDED")=0
- +33 SET NODE=^%ZOSF("OS")
- +34 SET HLCSTATE("SERVER")=0
- +35 SET HLCSTATE("SYSTEM","OS")=$SELECT(NODE["DSM":"DSM",NODE["OpenM":"CACHE",NODE["G.TM":"G.TM",1:"")
- +36 IF HLCSTATE("SYSTEM","OS")=""
- DO LINKDOWN^HLOCLNT(.HLCSTATE)
- QUIT 0
- +37 Begin DoDot:1
- +38 NEW SYS
- +39 DO SYSPARMS^HLOSITE(.SYS)
- +40 SET HLCSTATE("SYSTEM","BUFFER")=SYS("HL7 BUFFER")
- +41 SET HLCSTATE("SYSTEM","MAXSTRING")=SYS("MAXSTRING")
- +42 SET HLCSTATE("SYSTEM","NORMAL PURGE")=SYS("NORMAL PURGE")
- +43 SET HLCSTATE("SYSTEM","ERROR PURGE")=SYS("ERROR PURGE")
- End DoDot:1
- +44 IF HLCSTATE("LINK","LLP")="TCP"
- Begin DoDot:1
- +45 SET HLCSTATE("OPEN")="OPEN^HLOTCP"
- End DoDot:1
- +46 ;no other LLP implemented
- IF '$TEST
- +47 DO OPEN^HLOT(.HLCSTATE)
- +48 ;
- +49 ;mark the failure time for the link so other processes know not to try for a while
- +50 IF 'HLCSTATE("CONNECTED")
- DO LINKDOWN^HLOCLNT(.HLCSTATE)
- +51 QUIT HLCSTATE("CONNECTED")
- +52 ;
- BADMSGS(WORK) ;
- +1 ;finds messages that won't transmit and takes them off the outgoing queue
- +2 NEW LINK
- +3 SET LINK=""
- +4 FOR
- SET LINK=$ORDER(^HLTMP("FAILING LINKS",LINK))
- IF LINK=""
- QUIT
- Begin DoDot:1
- +5 NEW TIME,QUE,COUNT
- +6 SET TIME=$GET(^HLTMP("FAILING LINKS",LINK))
- IF TIME=""
- QUIT
- +7 IF $$HDIFF^XLFDT($HOROLOG,TIME,2)<7200
- QUIT
- +8 IF '$$IFOPEN^HLOUSR1(LINK)
- QUIT
- +9 LOCK +^HLB("QUEUE","OUT",LINK):0
- +10 SET QUE=""
- +11 FOR
- SET QUE=$ORDER(^HLB("QUEUE","OUT",LINK,QUE))
- IF QUE=""
- QUIT
- Begin DoDot:2
- +12 NEW MSG
- SET MSG=0
- +13 SET MSG=$ORDER(^HLB("QUEUE","OUT",LINK,QUE,MSG))
- +14 IF 'MSG
- QUIT
- +15 SET COUNT=$GET(^HLB(MSG,"TRIES"))
- +16 IF COUNT>20
- Begin DoDot:3
- +17 NEW NODE,TIME,APP,FS,ACTION
- +18 SET NODE=$GET(^HLB(MSG,0))
- +19 IF '$PIECE(NODE,"^",2)
- QUIT
- +20 SET TIME=+$GET(^HLA($PIECE(NODE,"^",2),0))
- +21 SET NODE=$GET(^HLB(MSG,1))
- +22 SET FS=$EXTRACT(NODE,4)
- +23 IF FS=""
- QUIT
- +24 SET APP=$PIECE(NODE,FS,3)
- +25 IF APP=""
- QUIT
- +26 SET $PIECE(^HLB(MSG,0),"^",21)=COUNT_" FAILED TRANSMISSIONS"
- +27 SET $PIECE(^HLB(MSG,0),"^",20)="TF"
- +28 SET ^HLB("ERRORS","TF",APP,TIME,MSG)=""
- +29 SET ACTION=$PIECE(NODE,"^",14,15)
- +30 IF ACTION'="^"
- IF ACTION]""
- DO INQUE^HLOQUE(LINK,QUE,MSG,ACTION,1)
- +31 DO DEQUE^HLOQUE(LINK,QUE,"OUT",MSG)
- End DoDot:3
- End DoDot:2
- +32 LOCK -^HLB("QUEUE","OUT",LINK)
- End DoDot:1
- +33 QUIT