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 | ;
|
---|