[896] | 1 | TMGKERN2 ;TMG/kst/OS Specific functions ;11/21/09
|
---|
| 2 | ;;1.0;TMG-LIB;**1**;11/21/09
|
---|
| 3 | ;
|
---|
| 4 | ;"TMG KERNEL FUNCTIONS -- 2
|
---|
| 5 | ;"This module is primarly for functions to support a SOCKET
|
---|
| 6 | ;" connection between two different VistA instances. One running
|
---|
| 7 | ;" as a server, and the other as a client.
|
---|
| 8 | ;"I.e. functions that are OS specific.
|
---|
| 9 | ;"Kevin Toppenberg MD
|
---|
| 10 | ;"GNU General Public License (GPL) applies
|
---|
| 11 | ;"11/21/09
|
---|
| 12 | ;
|
---|
| 13 | ;"=======================================================================
|
---|
| 14 | ;" API -- Public Functions.
|
---|
| 15 | ;"=======================================================================
|
---|
| 16 | ;"RUNSERVER(PORT,TMGMSGFN,TMGVERBOSE) --open up a socket that will listen to requests from a client.
|
---|
| 17 | ;"SEND(MSG) -- funnel all writing back to the client through this, so checksums can be calc'd
|
---|
| 18 | ;"ASK(MSG) -- funnel all writing to server through this function, so that checksums can calc'd
|
---|
| 19 | ;"DEBUGMSG(NOTE) ;
|
---|
| 20 | ;"RUNCLIENT(HOST,PORT) --Establish a connection with specified server. Then maintain connection, sending queries to server, and returning results.
|
---|
| 21 | ;"MSGCLIENT(JNUM,TMGQUERY,REPLY,ERROR,TIMEOUT) -- send messages to background client.
|
---|
| 22 | ;"CLEARBUF(JNUM,ERROR) -- remove all messages from message buffer.
|
---|
| 23 | ;"RUNMONITOR --Show DEBUG messages as they are added.
|
---|
| 24 | ;"=======================================================================
|
---|
| 25 | ;"Dependancies
|
---|
| 26 | ;"=======================================================================
|
---|
| 27 | ;"TMGUSRIF
|
---|
| 28 | ;"=======================================================================
|
---|
| 29 | ;
|
---|
| 30 | RUNSERVER(PORT,TMGMSGFN,TMGVERBOSE) ;
|
---|
| 31 | ;"Purpose: To open up a socket that will listen to requests from a client.
|
---|
| 32 | ;"Input: Port -- the port to listen on
|
---|
| 33 | ;" TMGMSGFN -- the NAME of a function that will handle incoming
|
---|
| 34 | ;" messages. E.g. 'HANDLMSG^MOD1'
|
---|
| 35 | ;" This function will be called as follows:
|
---|
| 36 | ;" xecute "DO "_TMGMSGFN_"(TMGCLIENT)"
|
---|
| 37 | ;" So the function must accept at least 1 parameter.
|
---|
| 38 | ;" NOTE: Any output that the handler function wants to go back
|
---|
| 39 | ;" to the client should be sent to SEND^TMGKERN2(MSG), so
|
---|
| 40 | ;" that error checking and self-correction can urr.
|
---|
| 41 | ;" TMGVERBOSE -- If 1 then some output will be show to console.
|
---|
| 42 | ;"Results: 1 if successful, -1^Error Message if failed.
|
---|
| 43 | ;"NOTE: This will be messaging protocol.
|
---|
| 44 | ;" #HELLO# will be sent on startup (possibly preceeded by 2 blank lines)
|
---|
| 45 | ;" #BYE# will be sent when server is quitting
|
---|
| 46 | ;" Server will respond to query of #BYE# by quitting.
|
---|
| 47 | ;" Server will turn control over to the message-handler-fn, allowing it to write
|
---|
| 48 | ;" out as many lines as it wants.
|
---|
| 49 | ;" After message-handler-fn returns, the server will send #DONE# to signal done.
|
---|
| 50 | ;"
|
---|
| 51 | NEW RESULT,TMGDELIM,TMGTCPDEV,TMGTIMEOUT
|
---|
| 52 | NEW TMGCLIENT,TMGANSWR,TMGCODE
|
---|
| 53 | KILL ^TMG("TMP","LOG","TCP")
|
---|
| 54 | ;
|
---|
| 55 | SET RESULT=1 ;"Default of success
|
---|
| 56 | IF +$GET(PORT)'>0 DO GOTO RSVRDN
|
---|
| 57 | . SET RESULT="-1^Invalid port number passed. Received: "_$GET(PORT)
|
---|
| 58 | IF $GET(TMGMSGFN)="" DO GOTO RSVRDN
|
---|
| 59 | . SET RESULT="-1^No Message handling function passed."
|
---|
| 60 | IF $TEXT(@TMGMSGFN)="" DO GOTO RSVRDN
|
---|
| 61 | . SET RESULT="-1^Message handler ["_TMGMSGFN_"] appears invalid"
|
---|
| 62 | SET PORT=+$GET(PORT)
|
---|
| 63 | SET TMGDELIM=$CHAR(13)
|
---|
| 64 | SET TMGTCPDEV="server$"_$JOB
|
---|
| 65 | SET TMGTIMEOUT=60
|
---|
| 66 | SET TMGCODE="DO "_TMGMSGFN_"(TMGCLIENT)"
|
---|
| 67 | SET TMGVERBOSE=+$GET(TMGVERBOSE)
|
---|
| 68 | ;
|
---|
| 69 | IF TMGVERBOSE DO
|
---|
| 70 | . WRITE "Starting server. Trying to connect to client..."
|
---|
| 71 | OPEN TMGTCPDEV:(ZLISTEN=PORT_":TCP":attach="server":DELIMITER=TMGDELIM:NOWRAP):TMGTIMEOUT:"SOCKET"
|
---|
| 72 | IF $TEST=0 DO GOTO RSVRDN
|
---|
| 73 | . SET RESULT="-1^Attempts to open server failed (timedout)"
|
---|
| 74 | USE TMGTCPDEV
|
---|
| 75 | WRITE /listen(1)
|
---|
| 76 | WRITE /wait(TMGTIMEOUT)
|
---|
| 77 | DO SEND("#HELLO#")
|
---|
| 78 | ;
|
---|
| 79 | IF TMGVERBOSE DO
|
---|
| 80 | . USE $P
|
---|
| 81 | . WRITE " Connected!",!
|
---|
| 82 | . WRITE "Press [ESC] multiple times to abort (and wait up to 60 sec).",!
|
---|
| 83 | . WRITE "Press '?' to see server output.",!
|
---|
| 84 | . WRITE "RUNNING SERVER..."
|
---|
| 85 | . USE TMGTCPDEV
|
---|
| 86 | L1 ;"Main Listen-Reply loop
|
---|
| 87 | NEW TMGCLIENT,TMGI,TMGDONE,TMGLEN
|
---|
| 88 | SET TMGDONE=-1,TMGI=1
|
---|
| 89 | NEW TMGSHOWOUT SET TMGSHOWOUT=0
|
---|
| 90 | DO DEBUGMSG("Starting main listen-reply loop")
|
---|
| 91 | FOR DO QUIT:(TMGDONE>0)!(TMGCLIENT="#BYE#")
|
---|
| 92 | . USE $P
|
---|
| 93 | . NEW USERKEY
|
---|
| 94 | . READ *USERKEY:0
|
---|
| 95 | . SET TMGDONE=(USERKEY=27)
|
---|
| 96 | . IF TMGDONE DO QUIT
|
---|
| 97 | . . DO SEND("#BYE#")
|
---|
| 98 | . . USE TMGTCPDEV
|
---|
| 99 | . SET:(USERKEY=63) TMGSHOWOUT=1 ;"63='?' Turn on showing ouput on console.
|
---|
| 100 | . SET:(USERKEY=33) TMGSHOWOUT=0 ;"33='!' Turn off showing ouput on console.
|
---|
| 101 | . USE TMGTCPDEV
|
---|
| 102 | . READ TMGCLIENT:TMGTIMEOUT
|
---|
| 103 | . IF ($TEST=0)!(TMGCLIENT="") DO QUIT
|
---|
| 104 | . . DO DEBUGMSG("$TEST=0 or TMGCLIENT='', so quitting")
|
---|
| 105 | . . SET TMGDONE=TMGDONE+1
|
---|
| 106 | . . DO SEND("#BYE#")
|
---|
| 107 | . . SET TMGCLIENT="#BYE#"
|
---|
| 108 | . ;"Check for valud query from client.
|
---|
| 109 | . SET TMGLEN=+$PIECE(TMGCLIENT,$CHAR(255),2)
|
---|
| 110 | . SET TMGCLIENT=$PIECE(TMGCLIENT,$CHAR(255),1)
|
---|
| 111 | . IF TMGLEN'=$LENGTH(TMGCLIENT) DO QUIT
|
---|
| 112 | . . DO DEBUGMSG("Length doesn't match checksup, so asking for resend")
|
---|
| 113 | . . DO SEND("#RESEND#")
|
---|
| 114 | . DO DEBUGMSG("TMGCLIENT="_TMGCLIENT)
|
---|
| 115 | . IF TMGCLIENT="#ENQ#" DO SEND("#ACK#") QUIT
|
---|
| 116 | . IF TMGCLIENT="#BYE#" DO SEND("#BYE#") QUIT
|
---|
| 117 | . ELSE DO SEND("#GOTQUERY#")
|
---|
| 118 | . SET TMGI=TMGI+1
|
---|
| 119 | . DO
|
---|
| 120 | . . NEW $ETRAP
|
---|
| 121 | . . SET $ETRAP="W ""<Error in message handler>"",!,$ZSTATUS,!,""#BYE"",! set $etrap="""",$ecode="""""
|
---|
| 122 | . . SET TMGMSGSUM=0
|
---|
| 123 | . . ;"DO DEBUGMSG("About to execute handler code")
|
---|
| 124 | . . XECUTE TMGCODE
|
---|
| 125 | . . ;"DO DEBUGMSG("Back from handler code")
|
---|
| 126 | . USE TMGTCPDEV ;"Ensure handler didn't redirect $IO
|
---|
| 127 | . ;"Send message to indicate done sending reply (will allow multi line responses)
|
---|
| 128 | . ;"Also append a count of total number of characters that have been sent, for error checking.
|
---|
| 129 | . DO DEBUGMSG("Sending back a DONE and total for amount sent: "_TMGMSGSUM)
|
---|
| 130 | . DO SEND("#DONE#^"_TMGMSGSUM)
|
---|
| 131 | . IF (TMGDONE>0) DO DEBUGMSG("NOTE: TMGDONE is > 0")
|
---|
| 132 | . IF (TMGCLIENT="#BYE#") DO DEBUGMSG("NOTE: TMGCLIENT = '#BYE#'")
|
---|
| 133 | ;
|
---|
| 134 | DO DEBUGMSG("Closing socket")
|
---|
| 135 | CLOSE TMGTCPDEV
|
---|
| 136 | ;
|
---|
| 137 | RSVRDN USE $P
|
---|
| 138 | DO DEBUGMSG("Quitting RUNSERVER")
|
---|
| 139 | IF TMGVERBOSE DO
|
---|
| 140 | . WRITE "Quitting ",$SELECT((RESULT=1):"normally",1:"with errors"),!
|
---|
| 141 | QUIT RESULT
|
---|
| 142 | ;
|
---|
| 143 | ;
|
---|
| 144 | SEND(MSG) ;
|
---|
| 145 | ;"Purpose: To funnel all writing back to the client through this function, so that
|
---|
| 146 | ;" checksums can be calculated for error checking...
|
---|
| 147 | ;"Input: MSG -- The message to write out
|
---|
| 148 | ;"NOTE: Will use globally scoped variable (on server side) TMGMSGSUM
|
---|
| 149 | ;" It is expected that RUNSERVER will set this to 0 before passing control
|
---|
| 150 | ;" over to a message handler.
|
---|
| 151 | ;
|
---|
| 152 | IF 1=0 DO
|
---|
| 153 | . NEW NUM SET NUM=+$GET(^TMG("TMP","LOG","TCP",0))
|
---|
| 154 | . SET NUM=NUM+1
|
---|
| 155 | . SET ^TMG("TMP","LOG","TCP",NUM,"NB")=$H_" SENDING; "_MSG
|
---|
| 156 | . SET ^TMG("TMP","LOG","TCP",0)=NUM
|
---|
| 157 | ;
|
---|
| 158 | WRITE MSG,!
|
---|
| 159 | SET TMGMSGSUM=+$GET(TMGMSGSUM)+$LENGTH(MSG)
|
---|
| 160 | IF $GET(TMGSHOWOUT)=1 DO
|
---|
| 161 | . USE $P
|
---|
| 162 | . WRITE "('!' to hide) ",MSG,!
|
---|
| 163 | . NEW USERKEY
|
---|
| 164 | . READ *USERKEY:0
|
---|
| 165 | . SET TMGDONE=(USERKEY=27)
|
---|
| 166 | . SET:(USERKEY=33) TMGSHOWOUT=0 ;"33='!' Turn off showing ouput on console.
|
---|
| 167 | . USE TMGTCPDEV
|
---|
| 168 | QUIT
|
---|
| 169 | ;
|
---|
| 170 | ;
|
---|
| 171 | ASK(MSG) ;
|
---|
| 172 | ;"Purpose: To funnel all writing to server through this function, so that
|
---|
| 173 | ;" checksums can be maintained for error checking...
|
---|
| 174 | ;"Input: MSG -- The message to write out
|
---|
| 175 | IF 1=0 DO
|
---|
| 176 | . NEW NUM SET NUM=+$GET(^TMG("TMP","LOG","TCP",0))
|
---|
| 177 | . SET NUM=NUM+1
|
---|
| 178 | . SET ^TMG("TMP","LOG","TCP",NUM,"ASK")=$H_"; "_MSG
|
---|
| 179 | . SET ^TMG("TMP","LOG","TCP",0)=NUM
|
---|
| 180 | ;
|
---|
| 181 | WRITE MSG_$CHAR(255)_$LENGTH(MSG),!
|
---|
| 182 | QUIT
|
---|
| 183 | ;
|
---|
| 184 | ;
|
---|
| 185 | DEBUGMSG(NOTE) ;f
|
---|
| 186 | IF 1=0 DO
|
---|
| 187 | . NEW NUM SET NUM=+$GET(^TMG("TMP","LOG","TCP",0))
|
---|
| 188 | . SET NUM=NUM+1
|
---|
| 189 | . SET ^TMG("TMP","LOG","TCP",NUM,"NB")=$H_"; "_NOTE
|
---|
| 190 | . SET ^TMG("TMP","LOG","TCP",0)=NUM
|
---|
| 191 | quit
|
---|
| 192 | ;
|
---|
| 193 | ;
|
---|
| 194 | RUNCLIENT(HOST,PORT) ;"NOTE: meant to be run as a background process
|
---|
| 195 | ;"Purpose: Establish a connection with specified server. Then maintain connection,
|
---|
| 196 | ;" sending queries to server, and returning results. Will take as input
|
---|
| 197 | ;" a messaging global ^TMG("TMP","TCP",$J,"TS",<index>)=<query> TS=ToServer
|
---|
| 198 | ;" And replies will be stored in ^TMG("TMP","TCP",$J,"FS",<index>)=<query> FS=FromServer
|
---|
| 199 | ;"Input: HOST -- the IP address, (or name for DNS lookup) of the server.
|
---|
| 200 | ;" PORT -- the port that the server is listening on.
|
---|
| 201 | ;"Result: none
|
---|
| 202 | ;"Output: Results will be stored in ^TMG("TMP","TCP",$J,"RESULT")=<result>
|
---|
| 203 | ;" 1 -- if successful, -1^Error Message if failed.
|
---|
| 204 | ;"!!NOTICE!! -- This can't be used to transfer binary files, because $char(255) is used
|
---|
| 205 | ;" as a signalling character for error checking.
|
---|
| 206 | ;"
|
---|
| 207 | NEW RESULT,TMGDELIM,TMGTCPDEV,TMGTIMEOUT
|
---|
| 208 | ;"Setup vars
|
---|
| 209 | SET TMGTCPDEV="client$"_$JOB
|
---|
| 210 | SET TMGTIMEOUT=30
|
---|
| 211 | KILL ^TMG("TMP","TCP",$J,"RESULT")
|
---|
| 212 | KILL ^TMG("TMP","LOG","TCP")
|
---|
| 213 | SET RESULT=1
|
---|
| 214 | ;"Validate input
|
---|
| 215 | IF +$GET(PORT)'>0 DO GOTO RCLDN
|
---|
| 216 | . SET RESULT="-1^Valid port number passed. Received: "_$GET(PORT)
|
---|
| 217 | IF $GET(HOST)="" DO GOTO RCLDN
|
---|
| 218 | . SET RESULT="-1^No Host passed."
|
---|
| 219 | SET PORT=+$GET(PORT)
|
---|
| 220 | IF PORT'>0 DO GOTO RCLDN
|
---|
| 221 | . SET RESULT="-1^Invalid port: ["_PORT_"]"
|
---|
| 222 | ;"Open up the TCP/IP connection
|
---|
| 223 | DO DEBUGMSG("NOTE: Job number="_$JOB)
|
---|
| 224 | DO DEBUGMSG("Starting to open connection with server")
|
---|
| 225 | OPEN TMGTCPDEV:(CONNECT=HOST_":"_PORT_":TCP":ATTACH="client":DELIMITER=$CHAR(13):NOWRAP):TMGTIMEOUT:"SOCKET"
|
---|
| 226 | IF $TEST=0 DO GOTO RCLDN
|
---|
| 227 | . SET RESULT="-1^Error on OPEN of SOCKET"
|
---|
| 228 | DO DEBUGMSG("Open succeeded.")
|
---|
| 229 | USE TMGTCPDEV
|
---|
| 230 | ;"Make sure server is ready to send information.
|
---|
| 231 | NEW TMGI,SRVREPLY
|
---|
| 232 | DO DEBUGMSG("Starting read (up to 3 tries), waiting for #HELLO#")
|
---|
| 233 | FOR TMGI=1:1:3 DO QUIT:(SRVREPLY="#HELLO#")
|
---|
| 234 | . READ SRVREPLY:TMGTIMEOUT
|
---|
| 235 | IF SRVREPLY'="#HELLO#" DO GOTO RCLDN
|
---|
| 236 | . SET RESULT="-1^Failed to get a '#HELLO#' from server"
|
---|
| 237 | DO DEBUGMSG("We got a #HELLO# alright. Great!")
|
---|
| 238 | SET ^TMG("TMP","TCP",$J,"RESULT")=$GET(RESULT)
|
---|
| 239 | ;
|
---|
| 240 | ;"Now process messaging.
|
---|
| 241 | RC1 NEW TSREF SET TSREF=$NAME(^TMG("TMP","TCP",$J,"TS"))
|
---|
| 242 | NEW FSREF SET FSREF=$NAME(^TMG("TMP","TCP",$J,"FS"))
|
---|
| 243 | NEW NTIME,STIME SET STIME=$PIECE($H,",",2)
|
---|
| 244 | NEW TMGQUERY SET TMGQUERY=""
|
---|
| 245 | NEW TMGIDLE SET TMGIDLE=0
|
---|
| 246 | NEW TMGABORT SET TMGABORT=0
|
---|
| 247 | DO DEBUGMSG("About to start main loop for messaging")
|
---|
| 248 | FOR DO QUIT:(TMGQUERY="#BYE#")!(SRVREPLY="#BYE#")!(TMGABORT=1)
|
---|
| 249 | . IF SRVREPLY'="#RESEND#" DO
|
---|
| 250 | . . SET TMGI=$ORDER(@TSREF@(""))
|
---|
| 251 | . . IF TMGI="" DO ;"Start idle handling
|
---|
| 252 | . . . SET TMGQUERY=""
|
---|
| 253 | . . . SET NTIME=$PIECE($H,",",2)
|
---|
| 254 | . . . IF (NTIME-STIME)<15 DO QUIT
|
---|
| 255 | . . . . IF TMGIDLE HANG 0.5 ;"This loop was taking 90+% of CPU othewise.
|
---|
| 256 | . . . SET TMGQUERY="#ENQ#" ;"send an ENQ every 15 seconds of idleness.
|
---|
| 257 | . . . SET STIME=$PIECE($H,",",2) ;"Reset idle counter
|
---|
| 258 | . . . SET TMGIDLE=1 ;"If idle for 15 seconds, then turn on idle mode. Will take 0.5 sec to turn off
|
---|
| 259 | . . ELSE DO
|
---|
| 260 | . . . SET TMGIDLE=0
|
---|
| 261 | . . . SET TMGQUERY=$get(@TSREF@(TMGI)) ;"Get query from user
|
---|
| 262 | . . . KILL @TSREF@(TMGI)
|
---|
| 263 | . . . SET STIME=$PIECE($H,",",2) ;"Reset idle counter
|
---|
| 264 | . . . IF $DATA(@TSREF)'=0 DO
|
---|
| 265 | . . . . NEW I SET I=""
|
---|
| 266 | . . . . FOR SET I=$order(@TSREF@(I)) QUIT:(I="") DO
|
---|
| 267 | . . . . . DO DEBUGMSG("Left over messages found!: "_$get(@TSREF@(I)))
|
---|
| 268 | . IF TMGQUERY="" QUIT
|
---|
| 269 | . USE TMGTCPDEV
|
---|
| 270 | . DO ASK(TMGQUERY) ;"Send out query to server.
|
---|
| 271 | . ;"Check for acknowledgement from server of query.
|
---|
| 272 | . READ SRVREPLY:TMGTIMEOUT ;"read reply.
|
---|
| 273 | . ;"IF ($TEST=0)!(SRVREPLY="")!(SRVREPLY="#BYE#") DO QUIT
|
---|
| 274 | . IF ($TEST=0)!(SRVREPLY="#BYE#") DO QUIT
|
---|
| 275 | . . SET TMGABORT=1
|
---|
| 276 | . . DO DEBUGMSG("1: Got bad or #BYE# reply, so quitting (Setting TMGABORT=1)")
|
---|
| 277 | . IF SRVREPLY="#ACK#" DO QUIT
|
---|
| 278 | . ;"Now process server reply to query.
|
---|
| 279 | . IF SRVREPLY="#RESEND" QUIT ;"Server replied with RESEND, so will ask query again
|
---|
| 280 | . IF SRVREPLY="#GOTQUERY#" FOR DO QUIT:(SRVREPLY="#BYE#")!(SRVREPLY="#DONE#")!(TMGABORT=1)
|
---|
| 281 | . . READ SRVREPLY:TMGTIMEOUT ;"read reply.
|
---|
| 282 | . . ;"IF ($TEST=0)!(SRVREPLY="")!(SRVREPLY="#BYE#") DO QUIT
|
---|
| 283 | . . IF ($TEST=0)!(SRVREPLY="#BYE#") DO QUIT
|
---|
| 284 | . . . DO DEBUGMSG("2: Got bad or #BYE# reply, so quitting (Setting TMGABORT=1)")
|
---|
| 285 | . . . SET TMGABORT=1 ;"Got NULL or bad or #BYE# reply, so setting quitting "
|
---|
| 286 | . . IF SRVREPLY="" QUIT ;"Ignore null replies (i.e. server sent a blank line) ?? good idea ??
|
---|
| 287 | . . IF SRVREPLY["#DONE#" DO ;"Cut off checksum, but DO store #DONE#
|
---|
| 288 | . . . DO DEBUGMSG("Got an #DONE#. Later I should check on checksum")
|
---|
| 289 | . . . ;"Later check on checksum
|
---|
| 290 | . . . SET SRVREPLY="#DONE#"
|
---|
| 291 | . . SET TMGI=+$ORDER(@FSREF@(""),-1)
|
---|
| 292 | . . SET @FSREF@(TMGI+1)=SRVREPLY
|
---|
| 293 | DO DEBUGMSG("Done with loop, so sending #BYE#")
|
---|
| 294 | DO DEBUGMSG("TMGQUERY="_TMGQUERY)
|
---|
| 295 | DO DEBUGMSG("SRVREPLY="_SRVREPLY)
|
---|
| 296 | DO DEBUGMSG("TMGABORT="_TMGABORT)
|
---|
| 297 | DO ASK("#BYE#") ;"Done with loop and exiting, so sending #BYE#"
|
---|
| 298 | CLOSE TMGTCPDEV
|
---|
| 299 | ;
|
---|
| 300 | RCLDN USE $P
|
---|
| 301 | KILL ^TMG("TMP","TCP",$J)
|
---|
| 302 | HALT ;"(quit background process)
|
---|
| 303 | ;
|
---|
| 304 | ;
|
---|
| 305 | MSGCLIENT(JNUM,TMGQUERY,REPLY,ERROR,TIMEOUT) ;
|
---|
| 306 | ;"Purpose: To send messages to background client. So this will be one function
|
---|
| 307 | ;" that the programmer may interact with. The reason for having the client
|
---|
| 308 | ;" run as a separate job is so that the server and the client can talk back
|
---|
| 309 | ;" and forth with ENQ<-->ACK upon either timing out, to keep the connection
|
---|
| 310 | ;" alive.
|
---|
| 311 | ;"Input: JNUM -- The job number of the background client process
|
---|
| 312 | ;" TMGQUERY -- The message to send to the server.
|
---|
| 313 | ;" REPLY -- PASS BY REFERENCE, AN OUT PARAMETER. Prior data killed.
|
---|
| 314 | ;" REPLY(1)=<a reply line from server>
|
---|
| 315 | ;" REPLY(2)=<a reply line from server>
|
---|
| 316 | ;" REPLY(3)=<a reply line from server>
|
---|
| 317 | ;" ERROR -- PASS BY REFERENCE, AN OUT PARAMETER. Prior data killed.
|
---|
| 318 | ;" If error, filled with -1^Message.
|
---|
| 319 | ;" TIMEOUT -- OPTIONAL. Default=1 (in seconds)
|
---|
| 320 | ;"Result: none
|
---|
| 321 | ;"Will set globally-scoped variable TMGABORT=1 if timeout or other error
|
---|
| 322 | ;
|
---|
| 323 | KILL ERROR,REPLY
|
---|
| 324 | NEW RESULT SET RESULT=""
|
---|
| 325 | SET JNUM=+$GET(JNUM)
|
---|
| 326 | IF JNUM'>0 SET ERROR="-1^BAD JOB NUMBER" GOTO MSGDN
|
---|
| 327 | SET TMGQUERY=$GET(TMGQUERY)
|
---|
| 328 | IF TMGQUERY="" SET ERROR="-1^NO QUERY PROVIDED" GOTO MSGDN
|
---|
| 329 | SET TIMEOUT=+$GET(TIMEOUT,1)
|
---|
| 330 | NEW SHOWPROG SET SHOWPROG=0
|
---|
| 331 | NEW NTIME,STIME SET STIME=$PIECE($H,",",2)
|
---|
| 332 | KILL ^TMG("TMP","TCP",JNUM,"FS") ;"Clear message buffer before communication
|
---|
| 333 | NEW TMGI SET TMGI=+$ORDER(^TMG("TMP","TCP",JNUM,"TS",""),-1)
|
---|
| 334 | SET ^TMG("TMP","TCP",JNUM,"TS",TMGI+1)=TMGQUERY
|
---|
| 335 | IF TMGQUERY="#BYE#" GOTO MSGDN
|
---|
| 336 | NEW LINECT SET LINECT=1
|
---|
| 337 | NEW TMGCT SET TMGCT=0
|
---|
| 338 | NEW REPLYI SET REPLYI=1
|
---|
| 339 | NEW STIME SET STIME=$PIECE($H,",",2)
|
---|
| 340 | NEW USERKEY
|
---|
| 341 | NEW TMGSHOWOUT SET TMGSHOWOUT=0
|
---|
| 342 | NEW ONELINE SET ONELINE=""
|
---|
| 343 | FOR DO QUIT:(ONELINE="#DONE#")
|
---|
| 344 | . SET TMGI=$ORDER(^TMG("TMP","TCP",JNUM,"FS",""))
|
---|
| 345 | . READ *USERKEY:0
|
---|
| 346 | . ;"SET TMGDONE=(USERKEY=27) QUIT:TMGDONE
|
---|
| 347 | . SET:(USERKEY=63) TMGSHOWOUT=1 ;"63='?' Turn on showing ouput on console.
|
---|
| 348 | . SET:(USERKEY=33) TMGSHOWOUT=0 ;"33='!' Turn off showing ouput on console.
|
---|
| 349 | . IF TMGI="" DO QUIT
|
---|
| 350 | . . SET NTIME=$PIECE($H,",",2)
|
---|
| 351 | . . IF (NTIME-STIME)'<TIMEOUT DO
|
---|
| 352 | . . . SET ERROR="-1^TIMED OUT WAITING FOR CLIENT TO GET REPLY FROM SERVER"
|
---|
| 353 | . . . SET ONELINE="#DONE#"
|
---|
| 354 | . . . SET TMGABORT=1
|
---|
| 355 | . SET ONELINE=$GET(^TMG("TMP","TCP",JNUM,"FS",TMGI))
|
---|
| 356 | . SET TMGCT=TMGCT+1
|
---|
| 357 | . IF TMGSHOWOUT=1 WRITE "('!' to hide) ",ONELINE,!
|
---|
| 358 | . IF (ONELINE'["#ERROR TRAPPED#") DO
|
---|
| 359 | . . IF (ONELINE["#THINKING#") DO QUIT
|
---|
| 360 | . . . NEW MSG SET MSG=$PIECE(ONELINE,"|",2)
|
---|
| 361 | . . . IF MSG="" SET MSG="(Server is working...)"
|
---|
| 362 | . . . WRITE MSG,!
|
---|
| 363 | . . . SET STIME=$PIECE($H,",",2) ;"Ignore server message to avoid timeout.
|
---|
| 364 | . . IF (ONELINE'="#DONE#") DO
|
---|
| 365 | . . . SET REPLY(REPLYI)=ONELINE
|
---|
| 366 | . . . SET REPLYI=REPLYI+1
|
---|
| 367 | . . . SET LINECT=LINECT+1
|
---|
| 368 | . ELSE DO
|
---|
| 369 | . . SET ERROR="-1^Error trapped on server side"
|
---|
| 370 | . . SET ERROR=ERROR_": "_$PIECE(ONELINE,"#ERROR TRAPPED#",2)
|
---|
| 371 | . . SET ONELINE="#DONE#"
|
---|
| 372 | . . SET TMGABORT=1
|
---|
| 373 | . KILL ^TMG("TMP","TCP",JNUM,"FS",TMGI)
|
---|
| 374 | . IF (SHOWPROG=0),($$HDIFF^XLFDT($H,STIME,2)>15) DO ;"Turn on progress bar after 15 seconds.
|
---|
| 375 | . . SET SHOWPROG=1
|
---|
| 376 | . IF (SHOWPROG=1),(TMGCT>1000) DO
|
---|
| 377 | . . DO ProgressBar^TMGUSRIF(100,"Receiving Data ('?' to monitor): "_LINECT,-1,-1,70)
|
---|
| 378 | . . SET TMGCT=0
|
---|
| 379 | MSGDN ;
|
---|
| 380 | KILL ^TMG("TMP","TCP",JNUM,"FS") ;"Clear message buffer after communication
|
---|
| 381 | QUIT
|
---|
| 382 | ;
|
---|
| 383 | ;
|
---|
| 384 | CLEARBUF(JNUM,ERROR) ;
|
---|
| 385 | ;"Purpose: To remove all messages from message buffer.
|
---|
| 386 | ;"Input: JNUM -- The job number of the background client process
|
---|
| 387 | ;" ERROR -- PASS BY REFERENCE, AN OUT PARAMETER. Prior data killed.
|
---|
| 388 | ;" If error, filled with -1^Message.
|
---|
| 389 | ;"Result: None
|
---|
| 390 | ;
|
---|
| 391 | KILL ERROR
|
---|
| 392 | SET JNUM=+$GET(JNUM)
|
---|
| 393 | IF JNUM'>0 SET ERROR="-1^BAD JOB NUMBER" GOTO CLBFDN
|
---|
| 394 | NEW TMGI
|
---|
| 395 | FOR DO QUIT:(TMGI="")
|
---|
| 396 | . SET TMGI=$ORDER(^TMG("TMP","TCP",JNUM,"TS",""))
|
---|
| 397 | . IF TMGI="" QUIT
|
---|
| 398 | . KILL ^TMG("TMP","TCP",JNUM,"TS",TMGI)
|
---|
| 399 | FOR DO QUIT:(TMGI="")
|
---|
| 400 | . SET TMGI=$ORDER(^TMG("TMP","TCP",JNUM,"FS",""))
|
---|
| 401 | . IF TMGI="" QUIT
|
---|
| 402 | . KILL ^TMG("TMP","TCP",JNUM,"FS",TMGI)
|
---|
| 403 | ;
|
---|
| 404 | CLBFDN QUIT
|
---|
| 405 | ;
|
---|
| 406 | ;
|
---|
| 407 | RUNMONITOR ;
|
---|
| 408 | ;"Purpose: This is a debugging routine. If run in a separate process, it will
|
---|
| 409 | ;" show DEBUG messages as they are added.
|
---|
| 410 | NEW NUM,TMGDONE,MSG,MAX
|
---|
| 411 | SET TMGDONE=0
|
---|
| 412 | FOR NUM=1:1 DO QUIT:(TMGDONE>0)
|
---|
| 413 | . READ *TMGDONE:0
|
---|
| 414 | . SET MAX=+$GET(^TMG("TMP","LOG","TCP",0))
|
---|
| 415 | . IF NUM>MAX SET NUM=MAX QUIT
|
---|
| 416 | . NEW NODE SET NODE=$ORDER(^TMG("TMP","LOG","TCP",NUM,""))
|
---|
| 417 | . WRITE NODE,": ",$GET(^TMG("TMP","LOG","TCP",NUM,NODE)),!
|
---|
| 418 | QUIT
|
---|
| 419 | ;
|
---|