INHVTMT ; DGH, CHEM, KAC ; 02 Nov 1999 17:52 ; Multi-threaded socket transceiver
;;3.01;BHL IHS Interfaces with GIS;;JUL 01, 2001
;COPYRIGHT 1991-2000 SAIC
Q
;
EN N INA,INDA,INDEST,INDSTR,INUSEQ,INSEND,INSND,INERR,INUIF,INLOOP,OUT,RCVE,OK,UIF,X,ER,INCHNL,INIP,INMEM,INQPRI,INQTIME,INNORSP,SYSTEM,RUN,MSG,CLISRV,INBPNM,INMSASTA,INSTOP
N H,INDISCNT,INDISCON,INDONE,INDT,INERRMT,INHBSENT,INHBTRY,INHBWAIT,INITROU,INIVLEN,INLIN,INLOGMSG,INMLTHRD,INMSG,INNORESP,INPEND,INRECV,INRECVD,INRUNMT,INSENT,INSEQNUM,INSTATE,INSTD,INSYNC,INTM,INTMDUE,INTMSENT,INXDST,RC
S INSTD="PDTS" ; set via FFCR in future - flags project-specific coding
S X="ERR^INHVTMT5",@^%ZOSF("TRAP")
S SYSTEM="SC",INBPNM=$P($G(^INTHPC(INBPN,0)),U),INSTATE="OPEN",INMLTHRD=1,INHBTRY=20,(INHBSENT,INDISCNT)=0,INIVLEN=12
D DEBUG^INHVCRA1() ; turn on debug
;Start GIS Background process audit if flag is set in Site Parms File
D AUDCHK^XUSAUD D:$D(XUAUDIT) ITIME^XUSAUD(INBPNM)
D:'$$RUN^INHOTM ; ck shutdown status
. D:$G(INDEBUG) LOG^INHVCRA1("Shutdown transceiver "_INBPNM,"E")
. D SHUTDWN^INHVTMT5(INBPN)
L +^INRHB("RUN",INBPN):5 E D Q
. D:$G(INDEBUG) LOG^INHVCRA1("Cannot get exclusive lock for: ^INRHB(""RUN"","_INBPN_")","E")
. D SHUTDWN^INHVTMT5(INBPN)
; Get INTERFACE DESTINATION IEN & Destination Determination Code
S INDSTR=+$P(^INTHPC(INBPN,0),U,7),INXDST=$G(^(8))
I 'INDSTR D Q
. D:$G(INDEBUG) LOG^INHVCRA1("No destination designated for background process "_INBPNM,"E")
. D SHUTDWN^INHVTMT5(INBPN)
I '$L($G(INXDST)) D Q
. D:$G(INDEBUG) LOG^INHVCRA1("Missing code to determine inbound message destination for background process "_INBPNM,"E")
. D SHUTDWN^INHVTMT5(INBPN)
; Initialize variables from background process file
D:$G(INDEBUG) LOG^INHVCRA1("Initializing variables for background process file "_INBPNM,9)
D INIT^INHUVUT(INBPN,.INIP) ; get parms from BPC file
I $L($G(INSTD)) D ; project-specific init
. F X=1:1:9 S INITROU="INIT"_INSTD_"^INHVTMT"_X D:$L($T(@INITROU)) @INITROU
; if Encryption is flagged on, start C process
I $G(INIP("CRYPT")),'$L(INIP("DESKEY")) D Q
. D:$G(INDEBUG) LOG^INHVCRA1("Encrypt is set but no DES Key specified "_INBPNM,5)
. D SHUTDWN^INHVTMT5(INBPN)
I $G(INIP("CRYPT")) S X=$$CRYPON^INCRYPT(INIP("DESKEY"))
;Determine if process will be client (default,0) or server (1)
S CLISRV=+$P(^INTHPC(INBPN,0),U,8)
; sync up INPEND with current state of pend que
S INSYNC=$$PENDSYNC^INHVTMT4(.INPEND)
;
; Main program loop
F D Q:'$G(INRUNMT)
.; Update background process audit
. D:$D(XUAUDIT) ITIME^XUSAUD(INBPNM)
.;
.; Select port & open TCP/IP connection
. I INSTATE="OPEN" D Q:'INRUNMT
.. D CLOSE^INHVTMT5
.. D:$G(INDEBUG) LOG^INHVCRA1("OPEN: Transceiver "_INBPNM,1)
.. S INRUNMT=$$OPEN^INHVTAPU(INBPN,CLISRV,.INIP,INDEBUG,.INCHNL,.INMEM)
.. S:INRUNMT INSTATE="HB",INHBWAIT=0
.;
.; Heartbeat/dummy msg sent to target system for known, pervasive
.; problems til target sends msg indicating that msgs can flow again
. I INSTATE="HB" D Q:'INRUNMT
.. Q:'$L($G(INIP("INIT"))) ; hb not used (e.g. receipt ack precludes)
.. D:$G(INDEBUG) LOG^INHVCRA1("HB: Transceiver "_INBPNM,1)
.. I (INHBTRY'>INHBSENT) S INSTATE="OPEN",INHBSENT=0 Q ; close/reopen
.. S INRUNMT=$$HB^INHVTMT5(.INHBSENT,INHBWAIT) ; send heartbeat msg
.. S:INRUNMT INHBWAIT=1
.;
. I INSTATE="SEND" D Q:'INRUNMT S:INSTATE="SEND" INSTATE="RECV"
.. D:$G(INDEBUG) LOG^INHVCRA1("SEND: Transceiver "_INBPNM,1)
.. S INSEND=INIP("SMAX")-INPEND ; # msgs to send
.. S INSENT=0 ; # msgs sent
..; Send up to max transactions
.. F Q:(INSEND'>INSENT) D Q:(INSTATE'="SEND")!'INRUNMT
...; Get next transaction from destination queue
... S INUIF=""
... F D Q:INUIF!(INSTATE'="SEND")!'INRUNMT
.... D:$G(INDEBUG) LOG^INHVCRA1("Socket ready to start send/receive.",7)
.... S INRUNMT=$$INRHB^INHUVUT1(INBPN,"Idle") Q:'INRUNMT
.... D:$G(INDEBUG) LOG^INHVCRA1("Getting next transaction on "_INDSTR_" destination queue.",7)
.... S INUIF=$$NEXT^INHUVUT3(INDSTR,.INQPRI,.INQTIME,.INPEND)
.... I 'INUIF D Q
..... S INSTATE="RECV" ; nothing to send
..... D:$G(INDEBUG) LOG^INHVCRA1("No transactions on destination queue.",5)
...;
... Q:(INSTATE'="SEND")!'INRUNMT
...;
...; Ck for presence of msg content
... D:$G(INDEBUG) LOG^INHVCRA1("Checking for presence of message",7)
... I '$O(^INTHU(INUIF,3,0)) D Q
.... D ENR^INHE(INBPN,"Missing message "_INUIF_" for destination "_$P($G(^INRHD(INDSTR,0)),U))
.... D PQKILL^INHVTMT4(INDSTR,INSEQNUM,INUIF,.INPEND)
...;
...; Selective Routing (send/no send)
... S UIF=$G(^INTHU(INUIF,0)),INA="^INTHU("_INUIF_",7)",INDA="^INTHU("_INUIF_",6)"
... I $$SUPPRESS^INHUT6("XMT",$P(UIF,U,11),$P(UIF,U,2),INBPN,.INA,.INDA,INUIF) D Q
.... D PQKILL^INHVTMT4(INDSTR,INSEQNUM,INUIF,.INPEND)
...;
...; Send msg
...; Start transaction audit
... D:$D(XUAUDIT) TTSTRT^XUSAUD(INUIF,"",INBPNM,"","TRANSMIT")
... D:$G(INDEBUG) LOG^INHVCRA1("Sending outgoing message on "_INBPNM,7)
... S INRUNMT=$$INRHB^INHUVUT1(INBPN,"Sending UIF= "_INUIF) Q:'INRUNMT
... F S INERRMT=$$SEND^INHVTMT1(INUIF,INCHNL,.INIP) Q:'INERRMT!'INRUNMT
...; Post-send activities
... D ULOG^INHU(INUIF,"S") ; log activity in UIF - sent
... S INSENT=INSENT+1
... S $P(^INLHDEST(INDSTR,"PEND",INBPN,INSEQNUM,INUIF),U)=$H_U_1
... D:$D(XUAUDIT) TTSTP^XUSAUD(0) ;stop transaction audit
.;
. I "^RECV^HB^"[(U_INSTATE_U) D Q:'INRUNMT S:INSTATE="RECV" INSTATE="TIMEOUT"
.. D:$G(INDEBUG) LOG^INHVCRA1("RECV: Transceiver "_INBPNM,1)
.. S (INRECV,INDONE,INDISCON,INNORESP)=0
..; Receive til disconnect, no response after retries, stop transceiver
..; or done reading (e.g. INPEND=0)
.. F D Q:INDONE!INDISCON!INNORESP!'INRUNMT
... S INMSG="Waiting for response"
... D:$G(INDEBUG) LOG^INHVCRA1(INMSG_" on "_INBPNM,7)
... S INRUNMT=$$INRHB^INHUVUT1(INBPN,INMSG) Q:'INRUNMT
... S INERRMT=$$RECEIVE^INHVTMT2(.INCHNL,.INIP,.INERR,.INMEM)
... Q:'INRUNMT
... S INDISCON=(INERRMT=3),INDONE=(INERRMT=0)
...;
... I INDISCON D Q ; disconnect
.... D REROUTE^INHVTMT4(INDSTR,.INPEND)
.... S INSTATE="OPEN"
.... D ENR^INHE(INBPN,INERR)
.... D:$G(INDEBUG) LOG^INHVCRA1(INERR,5) K INERR
.... D:'CLISRV
.....; clients pause before close/reopen; srvrs expect disconnects
..... S INLOGMSG="Waiting "_INIP("DHNG")_" seconds for open retry following disconnect on "_INBPNM_". Attempt "_INDISCNT
..... D:$G(INDEBUG) LOG^INHVCRA1(INLOGMSG,7)
..... D WAIT^INHUVUT2(INBPN,INIP("DHNG"),INLOGMSG,.INRUNMT)
..... S INRUNMT='INRUNMT ; wait rtns opposite
...;
... Q:INDONE ; finished reading available data
...;
...; No response (1) or error (2), try reading up to read-try max
... D:$G(INDEBUG) LOG^INHVCRA1(INERR,5) K INERR
... S INRECV=INRECV+1,INNORESP=$S(INIP("RTRY")'>INRECV:1,1:0)
...; If read retries exceeded
... I INNORESP D Q ; max read tries exceeded - no response (1) or error (2)
.... D:$G(INDEBUG) LOG^INHVCRA1("Maximum receive retries,"_INIP("RTRY")_" exceeded.",7)
...; Read retry - max retries NOT exceeded
... D:$G(INDEBUG) LOG^INHVCRA1("Waiting "_INIP("RHNG")_" seconds for read retry.",7)
... H INIP("RHNG")
.;
.; Ck all entries on "pending response" que for no-response timeout
. I "^TIMEOUT^HB^"[(U_INSTATE_U) D Q:'INRUNMT S:INSTATE="TIMEOUT" INSTATE="SEND"
.. D:$G(INDEBUG) LOG^INHVCRA1("TIMEOUT: Transceiver "_INBPNM,1)
.. S:INSYNC INSYNC=0 ; ensured FIFO on startup (TIMEOUT before SEND state)
..; Quit if no items in pending queue
.. I '$D(^INLHDEST(INDSTR,"PEND",INBPN)) S INPEND=0 Q
.. S INRUNMT=$$INRHB^INHUVUT1(INBPN,"Cking for no-response timeout") Q:'INRUNMT
.. S INSEQNUM=""
.. F S INSEQNUM=$O(^INLHDEST(INDSTR,"PEND",INBPN,INSEQNUM)) Q:(INSEQNUM="") D Q:'INRUNMT
... S INUIF=""
... F S INUIF=$O(^INLHDEST(INDSTR,"PEND",INBPN,INSEQNUM,INUIF)) Q:'INUIF D Q:'INRUNMT
.... S INTMSENT=$P(^INLHDEST(INDSTR,"PEND",INBPN,INSEQNUM,INUIF),U)
.... S X=$P(INTMSENT,",",2)+INIP("STO")
....; ck for crossing day boundary
.... S INTMDUE=$S(86400'>X:($P(INTMSENT,",")+1)_","_$TR($J(X-86400,5)," ",0),1:$P(INTMSENT,",")_","_X)
.... S H=$H,INDT=$P(H,","),INTM=$P(H,",",2)
....; If past due date or today's date, but past due time
.... I ($P(INTMDUE,",")<INDT)!(($P(INTMDUE,",")=INDT)&($P(INTMDUE,",",2)'>INTM)) D
.....; If no-response timeout
..... I INIP("STRY")'>$P(^INLHDEST(INDSTR,"PEND",INBPN,INSEQNUM,INUIF),U,2) D Q
......; send tries exceeded, reroute msg to another xceiver
...... S INERR="No-response timeout: Rerouting UIF="_INUIF_" for background process "_INBPNM_$S(INSTATE="TIMEOUT":". Close/reopen socket. Transceiver entering heartbeat state.",1:"")
...... D:$G(INDEBUG) LOG^INHVCRA1(INERR,9)
...... D ENR^INHE(INBPN,INERR) K INERR
...... S INERRMT=$$GETPEND^INHVTMT4(INDSTR,INSEQNUM,INUIF,.INPEND)
...... S INSTATE="OPEN"
.....; else, send retries NOT exceeded
..... D:$G(INDEBUG) LOG^INHVCRA1("No-response timeout: Resending UIF="_INUIF,9)
..... D RESEND^INHVTMT4(INDSTR,INUIF,INSEQNUM)
;
;
; Shutdown transceiver (close socket, cleanup)
D SHUTDWN^INHVTMT5(INBPN,$G(INCHNL))
Q
;
;
INHVTMT ; DGH, CHEM, KAC ; 02 Nov 1999 17:52 ; Multi-threaded socket transceiver
+1 ;;3.01;BHL IHS Interfaces with GIS;;JUL 01, 2001
+2 ;COPYRIGHT 1991-2000 SAIC
+3 QUIT
+4 ;
EN NEW INA,INDA,INDEST,INDSTR,INUSEQ,INSEND,INSND,INERR,INUIF,INLOOP,OUT,RCVE,OK,UIF,X,ER,INCHNL,INIP,INMEM,INQPRI,INQTIME,INNORSP,SYSTEM,RUN,MSG,CLISRV,INBPNM,INMSASTA,INSTOP
+1 NEW H,INDISCNT,INDISCON,INDONE,INDT,INERRMT,INHBSENT,INHBTRY,INHBWAIT,INITROU,INIVLEN,INLIN,INLOGMSG,INMLTHRD,INMSG,INNORESP,INPEND,INRECV,INRECVD,INRUNMT,INSENT,INSEQNUM,INSTATE,INSTD,INSYNC,INTM,INTMDUE,INTMSENT,INXDST,RC
+2 ; set via FFCR in future - flags project-specific coding
SET INSTD="PDTS"
+3 SET X="ERR^INHVTMT5"
SET @^%ZOSF("TRAP")
+4 SET SYSTEM="SC"
SET INBPNM=$PIECE($GET(^INTHPC(INBPN,0)),U)
SET INSTATE="OPEN"
SET INMLTHRD=1
SET INHBTRY=20
SET (INHBSENT,INDISCNT)=0
SET INIVLEN=12
+5 ; turn on debug
DO DEBUG^INHVCRA1()
+6 ;Start GIS Background process audit if flag is set in Site Parms File
+7 DO AUDCHK^XUSAUD
IF $DATA(XUAUDIT)
DO ITIME^XUSAUD(INBPNM)
+8 ; ck shutdown status
IF '$$RUN^INHOTM
Begin DoDot:1
+9 IF $GET(INDEBUG)
DO LOG^INHVCRA1("Shutdown transceiver "_INBPNM,"E")
+10 DO SHUTDWN^INHVTMT5(INBPN)
End DoDot:1
+11 LOCK +^INRHB("RUN",INBPN):5
IF '$TEST
Begin DoDot:1
+12 IF $GET(INDEBUG)
DO LOG^INHVCRA1("Cannot get exclusive lock for: ^INRHB(""RUN"","_INBPN_")","E")
+13 DO SHUTDWN^INHVTMT5(INBPN)
End DoDot:1
QUIT
+14 ; Get INTERFACE DESTINATION IEN & Destination Determination Code
+15 SET INDSTR=+$PIECE(^INTHPC(INBPN,0),U,7)
SET INXDST=$GET(^(8))
+16 IF 'INDSTR
Begin DoDot:1
+17 IF $GET(INDEBUG)
DO LOG^INHVCRA1("No destination designated for background process "_INBPNM,"E")
+18 DO SHUTDWN^INHVTMT5(INBPN)
End DoDot:1
QUIT
+19 IF '$LENGTH($GET(INXDST))
Begin DoDot:1
+20 IF $GET(INDEBUG)
DO LOG^INHVCRA1("Missing code to determine inbound message destination for background process "_INBPNM,"E")
+21 DO SHUTDWN^INHVTMT5(INBPN)
End DoDot:1
QUIT
+22 ; Initialize variables from background process file
+23 IF $GET(INDEBUG)
DO LOG^INHVCRA1("Initializing variables for background process file "_INBPNM,9)
+24 ; get parms from BPC file
DO INIT^INHUVUT(INBPN,.INIP)
+25 ; project-specific init
IF $LENGTH($GET(INSTD))
Begin DoDot:1
+26 FOR X=1:1:9
SET INITROU="INIT"_INSTD_"^INHVTMT"_X
IF $LENGTH($TEXT(@INITROU))
DO @INITROU
End DoDot:1
+27 ; if Encryption is flagged on, start C process
+28 IF $GET(INIP("CRYPT"))
IF '$LENGTH(INIP("DESKEY"))
Begin DoDot:1
+29 IF $GET(INDEBUG)
DO LOG^INHVCRA1("Encrypt is set but no DES Key specified "_INBPNM,5)
+30 DO SHUTDWN^INHVTMT5(INBPN)
End DoDot:1
QUIT
+31 IF $GET(INIP("CRYPT"))
SET X=$$CRYPON^INCRYPT(INIP("DESKEY"))
+32 ;Determine if process will be client (default,0) or server (1)
+33 SET CLISRV=+$PIECE(^INTHPC(INBPN,0),U,8)
+34 ; sync up INPEND with current state of pend que
+35 SET INSYNC=$$PENDSYNC^INHVTMT4(.INPEND)
+36 ;
+37 ; Main program loop
+38 FOR
Begin DoDot:1
+39 ; Update background process audit
+40 IF $DATA(XUAUDIT)
DO ITIME^XUSAUD(INBPNM)
+41 ;
+42 ; Select port & open TCP/IP connection
+43 IF INSTATE="OPEN"
Begin DoDot:2
+44 DO CLOSE^INHVTMT5
+45 IF $GET(INDEBUG)
DO LOG^INHVCRA1("OPEN: Transceiver "_INBPNM,1)
+46 SET INRUNMT=$$OPEN^INHVTAPU(INBPN,CLISRV,.INIP,INDEBUG,.INCHNL,.INMEM)
+47 IF INRUNMT
SET INSTATE="HB"
SET INHBWAIT=0
End DoDot:2
IF 'INRUNMT
QUIT
+48 ;
+49 ; Heartbeat/dummy msg sent to target system for known, pervasive
+50 ; problems til target sends msg indicating that msgs can flow again
+51 IF INSTATE="HB"
Begin DoDot:2
+52 ; hb not used (e.g. receipt ack precludes)
IF '$LENGTH($GET(INIP("INIT")))
QUIT
+53 IF $GET(INDEBUG)
DO LOG^INHVCRA1("HB: Transceiver "_INBPNM,1)
+54 ; close/reopen
IF (INHBTRY'>INHBSENT)
SET INSTATE="OPEN"
SET INHBSENT=0
QUIT
+55 ; send heartbeat msg
SET INRUNMT=$$HB^INHVTMT5(.INHBSENT,INHBWAIT)
+56 IF INRUNMT
SET INHBWAIT=1
End DoDot:2
IF 'INRUNMT
QUIT
+57 ;
+58 IF INSTATE="SEND"
Begin DoDot:2
+59 IF $GET(INDEBUG)
DO LOG^INHVCRA1("SEND: Transceiver "_INBPNM,1)
+60 ; # msgs to send
SET INSEND=INIP("SMAX")-INPEND
+61 ; # msgs sent
SET INSENT=0
+62 ; Send up to max transactions
+63 FOR
IF (INSEND'>INSENT)
QUIT
Begin DoDot:3
+64 ; Get next transaction from destination queue
+65 SET INUIF=""
+66 FOR
Begin DoDot:4
+67 IF $GET(INDEBUG)
DO LOG^INHVCRA1("Socket ready to start send/receive.",7)
+68 SET INRUNMT=$$INRHB^INHUVUT1(INBPN,"Idle")
IF 'INRUNMT
QUIT
+69 IF $GET(INDEBUG)
DO LOG^INHVCRA1("Getting next transaction on "_INDSTR_" destination queue.",7)
+70 SET INUIF=$$NEXT^INHUVUT3(INDSTR,.INQPRI,.INQTIME,.INPEND)
+71 IF 'INUIF
Begin DoDot:5
+72 ; nothing to send
SET INSTATE="RECV"
+73 IF $GET(INDEBUG)
DO LOG^INHVCRA1("No transactions on destination queue.",5)
End DoDot:5
QUIT
End DoDot:4
IF INUIF!(INSTATE'="SEND")!'INRUNMT
QUIT
+74 ;
+75 IF (INSTATE'="SEND")!'INRUNMT
QUIT
+76 ;
+77 ; Ck for presence of msg content
+78 IF $GET(INDEBUG)
DO LOG^INHVCRA1("Checking for presence of message",7)
+79 IF '$ORDER(^INTHU(INUIF,3,0))
Begin DoDot:4
+80 DO ENR^INHE(INBPN,"Missing message "_INUIF_" for destination "_$PIECE($GET(^INRHD(INDSTR,0)),U))
+81 DO PQKILL^INHVTMT4(INDSTR,INSEQNUM,INUIF,.INPEND)
End DoDot:4
QUIT
+82 ;
+83 ; Selective Routing (send/no send)
+84 SET UIF=$GET(^INTHU(INUIF,0))
SET INA="^INTHU("_INUIF_",7)"
SET INDA="^INTHU("_INUIF_",6)"
+85 IF $$SUPPRESS^INHUT6("XMT",$PIECE(UIF,U,11),$PIECE(UIF,U,2),INBPN,.INA,.INDA,INUIF)
Begin DoDot:4
+86 DO PQKILL^INHVTMT4(INDSTR,INSEQNUM,INUIF,.INPEND)
End DoDot:4
QUIT
+87 ;
+88 ; Send msg
+89 ; Start transaction audit
+90 IF $DATA(XUAUDIT)
DO TTSTRT^XUSAUD(INUIF,"",INBPNM,"","TRANSMIT")
+91 IF $GET(INDEBUG)
DO LOG^INHVCRA1("Sending outgoing message on "_INBPNM,7)
+92 SET INRUNMT=$$INRHB^INHUVUT1(INBPN,"Sending UIF= "_INUIF)
IF 'INRUNMT
QUIT
+93 FOR
SET INERRMT=$$SEND^INHVTMT1(INUIF,INCHNL,.INIP)
IF 'INERRMT!'INRUNMT
QUIT
+94 ; Post-send activities
+95 ; log activity in UIF - sent
DO ULOG^INHU(INUIF,"S")
+96 SET INSENT=INSENT+1
+97 SET $PIECE(^INLHDEST(INDSTR,"PEND",INBPN,INSEQNUM,INUIF),U)=$HOROLOG_U_1
+98 ;stop transaction audit
IF $DATA(XUAUDIT)
DO TTSTP^XUSAUD(0)
End DoDot:3
IF (INSTATE'="SEND")!'INRUNMT
QUIT
End DoDot:2
IF 'INRUNMT
QUIT
IF INSTATE="SEND"
SET INSTATE="RECV"
+99 ;
+100 IF "^RECV^HB^"[(U_INSTATE_U)
Begin DoDot:2
+101 IF $GET(INDEBUG)
DO LOG^INHVCRA1("RECV: Transceiver "_INBPNM,1)
+102 SET (INRECV,INDONE,INDISCON,INNORESP)=0
+103 ; Receive til disconnect, no response after retries, stop transceiver
+104 ; or done reading (e.g. INPEND=0)
+105 FOR
Begin DoDot:3
+106 SET INMSG="Waiting for response"
+107 IF $GET(INDEBUG)
DO LOG^INHVCRA1(INMSG_" on "_INBPNM,7)
+108 SET INRUNMT=$$INRHB^INHUVUT1(INBPN,INMSG)
IF 'INRUNMT
QUIT
+109 SET INERRMT=$$RECEIVE^INHVTMT2(.INCHNL,.INIP,.INERR,.INMEM)
+110 IF 'INRUNMT
QUIT
+111 SET INDISCON=(INERRMT=3)
SET INDONE=(INERRMT=0)
+112 ;
+113 ; disconnect
IF INDISCON
Begin DoDot:4
+114 DO REROUTE^INHVTMT4(INDSTR,.INPEND)
+115 SET INSTATE="OPEN"
+116 DO ENR^INHE(INBPN,INERR)
+117 IF $GET(INDEBUG)
DO LOG^INHVCRA1(INERR,5)
KILL INERR
+118 IF 'CLISRV
Begin DoDot:5
+119 ; clients pause before close/reopen; srvrs expect disconnects
+120 SET INLOGMSG="Waiting "_INIP("DHNG")_" seconds for open retry following disconnect on "_INBPNM_". Attempt "_INDISCNT
+121 IF $GET(INDEBUG)
DO LOG^INHVCRA1(INLOGMSG,7)
+122 DO WAIT^INHUVUT2(INBPN,INIP("DHNG"),INLOGMSG,.INRUNMT)
+123 ; wait rtns opposite
SET INRUNMT='INRUNMT
End DoDot:5
End DoDot:4
QUIT
+124 ;
+125 ; finished reading available data
IF INDONE
QUIT
+126 ;
+127 ; No response (1) or error (2), try reading up to read-try max
+128 IF $GET(INDEBUG)
DO LOG^INHVCRA1(INERR,5)
KILL INERR
+129 SET INRECV=INRECV+1
SET INNORESP=$SELECT(INIP("RTRY")'>INRECV:1,1:0)
+130 ; If read retries exceeded
+131 ; max read tries exceeded - no response (1) or error (2)
IF INNORESP
Begin DoDot:4
+132 IF $GET(INDEBUG)
DO LOG^INHVCRA1("Maximum receive retries,"_INIP("RTRY")_" exceeded.",7)
End DoDot:4
QUIT
+133 ; Read retry - max retries NOT exceeded
+134 IF $GET(INDEBUG)
DO LOG^INHVCRA1("Waiting "_INIP("RHNG")_" seconds for read retry.",7)
+135 HANG INIP("RHNG")
End DoDot:3
IF INDONE!INDISCON!INNORESP!'INRUNMT
QUIT
End DoDot:2
IF 'INRUNMT
QUIT
IF INSTATE="RECV"
SET INSTATE="TIMEOUT"
+136 ;
+137 ; Ck all entries on "pending response" que for no-response timeout
+138 IF "^TIMEOUT^HB^"[(U_INSTATE_U)
Begin DoDot:2
+139 IF $GET(INDEBUG)
DO LOG^INHVCRA1("TIMEOUT: Transceiver "_INBPNM,1)
+140 ; ensured FIFO on startup (TIMEOUT before SEND state)
IF INSYNC
SET INSYNC=0
+141 ; Quit if no items in pending queue
+142 IF '$DATA(^INLHDEST(INDSTR,"PEND",INBPN))
SET INPEND=0
QUIT
+143 SET INRUNMT=$$INRHB^INHUVUT1(INBPN,"Cking for no-response timeout")
IF 'INRUNMT
QUIT
+144 SET INSEQNUM=""
+145 FOR
SET INSEQNUM=$ORDER(^INLHDEST(INDSTR,"PEND",INBPN,INSEQNUM))
IF (INSEQNUM="")
QUIT
Begin DoDot:3
+146 SET INUIF=""
+147 FOR
SET INUIF=$ORDER(^INLHDEST(INDSTR,"PEND",INBPN,INSEQNUM,INUIF))
IF 'INUIF
QUIT
Begin DoDot:4
+148 SET INTMSENT=$PIECE(^INLHDEST(INDSTR,"PEND",INBPN,INSEQNUM,INUIF),U)
+149 SET X=$PIECE(INTMSENT,",",2)+INIP("STO")
+150 ; ck for crossing day boundary
+151 SET INTMDUE=$SELECT(86400'>X:($PIECE(INTMSENT,",")+1)_","_$TRANSLATE($JUSTIFY(X-86400,5)," ",0),1:$PIECE(INTMSENT,",")_","_X)
+152 SET H=$HOROLOG
SET INDT=$PIECE(H,",")
SET INTM=$PIECE(H,",",2)
+153 ; If past due date or today's date, but past due time
+154 IF ($PIECE(INTMDUE,",")<INDT)!(($PIECE(INTMDUE,",")=INDT)&($PIECE(INTMDUE,",",2)'>INTM))
Begin DoDot:5
+155 ; If no-response timeout
+156 IF INIP("STRY")'>$PIECE(^INLHDEST(INDSTR,"PEND",INBPN,INSEQNUM,INUIF),U,2)
Begin DoDot:6
+157 ; send tries exceeded, reroute msg to another xceiver
+158 SET INERR="No-response timeout: Rerouting UIF="_INUIF_" for background process "_INBPNM_$SELECT(INSTATE="TIMEOUT":". Close/reopen socket. Transceiver entering heartbeat state.",1:"")
+159 IF $GET(INDEBUG)
DO LOG^INHVCRA1(INERR,9)
+160 DO ENR^INHE(INBPN,INERR)
KILL INERR
+161 SET INERRMT=$$GETPEND^INHVTMT4(INDSTR,INSEQNUM,INUIF,.INPEND)
+162 SET INSTATE="OPEN"
End DoDot:6
QUIT
+163 ; else, send retries NOT exceeded
+164 IF $GET(INDEBUG)
DO LOG^INHVCRA1("No-response timeout: Resending UIF="_INUIF,9)
+165 DO RESEND^INHVTMT4(INDSTR,INUIF,INSEQNUM)
End DoDot:5
End DoDot:4
IF 'INRUNMT
QUIT
End DoDot:3
IF 'INRUNMT
QUIT
End DoDot:2
IF 'INRUNMT
QUIT
IF INSTATE="TIMEOUT"
SET INSTATE="SEND"
End DoDot:1
IF '$GET(INRUNMT)
QUIT
+166 ;
+167 ;
+168 ; Shutdown transceiver (close socket, cleanup)
+169 DO SHUTDWN^INHVTMT5(INBPN,$GET(INCHNL))
+170 QUIT
+171 ;
+172 ;