%ZTMS1 ;SEA/RDS-TaskMan: Submanager, (Loop & Get Task) ;10/07/08 15:46
;;8.0;KERNEL;**36,49,104,118,127,136,275,446**;JUL 10, 1995;Build 35
;Per VHA Directive 2004-038, this routine should not be modified.
;Use ZTLKTM for Lock timeout. p446
SUBMGR ;START--outer submanager loop
D GETTASK G:ZTSK'>0 QUIT^%ZTMS ;task locked
S STATUS="Run Task "_ZTSK
D PROCESS^%ZTMS2 G:$D(ZTQUIT) QUIT^%ZTMS
S STATUS="Idle"
G SUBMGR
;
GETTASK ;SUBMGR--retain the partition; check Waiting Lists every 1 seconds
D SUB(1) S ZTSK=0
;
F ZRT=0:0 D Q:$$EXIT S %=$S($O(^%ZTSCH("JOB",0))>0:1,1:$$FIRST()),ZRT=ZRT+% H % ;Space out the SM loop
. I $D(^%ZTSCH("WAIT","SUB")) S STATUS="Wait Node" H 5 Q ;Wait
. S %ZTIME=$$H3($H),ZTSK=0 I $D(^%ZTSCH("STOP","SUB",ZTPAIR)) Q
. D C Q:ZTSK!(ZTYPE="C") ;Do directed work before check for balance
. ;If more than xx tasks in JOB Queue don't balance wait. p446
. I $$BALANCE S ZRT=ZRT-.9,STATUS="Balance Wait" I $$JCNT(ZTPFLG("BalLimit")) Q ;Wait for balance, Slow ZRT rise.
. D JOB,IOQ:'ZTSK ;Look for work
. Q
D SUB(-1) ;Adjust counter
Q
;
EXIT() ;GETTASK--decide whether to exit retention loop
I ZTSK,$D(^%ZTSCH("NO-OPTION")),$P(^%ZTSK(ZTSK,0),"^",1,2)="ZTSK^XQ1" D
. D SCHTM^%ZTMS2(ZTDTH+60) S ZTSK=0
. Q
I ZTSK G YES
I $D(^%ZTSCH("STOP","SUB",ZTPAIR)) G YES
I ZTPFLG("RT")>ZRT G NO ;Retention time check
I $$SUB(0)>ZTPFLG("MIN") G YES ;Let extras go
NO ;Don't exit, Update status node
L +^%ZTSCH("SUB",ZTPFLG("HOME"),$J):10 ;p446
S ^%ZTSCH("SUB",ZTPFLG("HOME"),$J)=$H_"^"_$G(STATUS)_"^"_$G(STATUS("Bal")) ;Keep our node current
I ZTPFLG("XUSCNT") D SETLOCK^XUSCNT($NA(^%ZTSCH("SUBLK",ZTPFLG("HOME"),$J)))
L -^%ZTSCH("SUB",ZTPFLG("HOME"),$J) ;p446
Q 0
;
YES ;EXIT--Yes ;p446
Q 1
;
C ;GETTASK--On C type volume sets, get tasks from Cross-Volume Job List
S STATUS="C List",ZTSK=0
I $O(^%ZTSCH("C",ZTPAIR,0))="" Q
L +^%ZTSCH("C",ZTPAIR):ZTLKTM I '$T S STATUS="No C Lock" Q
S ZTDTH="",^%ZTSCH("C",ZTPAIR)=0
F S ZTDTH=$O(^%ZTSCH("C",ZTPAIR,ZTDTH)),ZTSK=0 Q:ZTDTH="" D Q:ZTSK
. F S ZTSK=$O(^%ZTSCH("C",ZTPAIR,ZTDTH,ZTSK)),ZX=0 Q:ZTSK="" D Q:ZX
.. I $D(^%ZTSK(ZTSK,0))[0!'ZTSK D Q
... I ZTSK'=0,$D(^%ZTSK(ZTSK)) D TSKSTAT("I")
... K ^%ZTSCH("C",ZTPAIR,ZTDTH,ZTSK) S ZTSK=0
... Q
.. L +^%ZTSK(ZTSK):0 Q:'$T
.. S %ZTIO=^%ZTSCH("C",ZTPAIR,ZTDTH,ZTSK),ZTQUEUED=.5
.. I %ZTIO]"" S ZTDEVN=1
.. K ^%ZTSCH("C",ZTPAIR,ZTDTH,ZTSK)
.. S ZX=1
.. Q
. Q
L -^%ZTSCH("C",ZTPAIR) ;If ZTSK>0 then ^%ZTSK(ztsk) is locked.
Q
;
BALANCE() ;GETTASK--check load balance, and wait while Manager waits
Q:ZTPAIR="" 0
S STATUS("Bal")=0
;Try and Lock so we are synced. If can't get Lock run. ;p446
L +^%ZTSCH("LOADA"):0
I $T S STATUS("Bal")=+$G(^%ZTSCH("LOADA",ZTPAIR)) L -^%ZTSCH("LOADA")
I STATUS("Bal") H 1 ;Added set var & Hang. p446
Q STATUS("Bal")
;
JOB ;GETTASK--search Partition Waiting List
S ZTSK=0,ZTDTH=0,ZTQUEUED=0,STATUS="JOB Q"
L +^%ZTSCH("JOBQ"):ZTLKTM I '$T S STATUS="No JOBQ Lock" Q
J2 S ZTDTH=$O(^%ZTSCH("JOB",ZTDTH)),ZTSK=0 I ZTDTH="" L -^%ZTSCH("JOBQ") Q
J3 S ZTSK=$O(^%ZTSCH("JOB",ZTDTH,ZTSK)),ZTQUEUED=0 I ZTSK'>0 G J2
L +^%ZTSK(ZTSK):0 I '$T S STATUS="No ZTSK Lock" G J3 ;p446 Back to 0
I $D(^%ZTSCH("JOB",ZTDTH,ZTSK))[0 L -^%ZTSK(ZTSK) S STATUS="JOB cleared" G J3
I $D(^%ZTSK(ZTSK,0))[0 D BADTASK L -^%ZTSK(ZTSK) G J3
S %ZTIO=^%ZTSCH("JOB",ZTDTH,ZTSK),ZTQUEUED=.5,STATUS="Work Task "_ZTSK
K ^%ZTSCH("JOB",ZTDTH,ZTSK)
L -^%ZTSCH("JOBQ") ;Now can release JOBQ
;try and only pick up work for this node.
S ZTREC=$G(^%ZTSK(ZTSK,0)),%=$P(ZTREC,U,14) I %[":",%'[ZTNODE D ;p446
. L +^%ZTSCH("C",%):99 ;p446
. S ^%ZTSCH("C",%,ZTDTH,ZTSK)=%ZTIO
. L -^%ZTSCH("C",%),-^%ZTSK(ZTSK) ;p446
. S ZTSK=0,%ZTIO="" ;p446
. Q
I %ZTIO'="" S ZTDEVN=1
;On exit we have ^%ZTSK(ZTSK) Locked if ZTSK>0.
Q
;
BADTASK ;JOB--unschedule tasks with bad numbers or incomplete records
S %ZTIO=^%ZTSCH("JOB",ZTDTH,ZTSK) I %ZTIO]"" S ZTDEVN=1
I ZTSK'=0,$D(^%ZTSK(ZTSK)) D TSKSTAT("I",3)
K ^%ZTSCH("JOB",ZTDTH,ZTSK)
S ZTQUEUED=0
I %ZTIO]"" D DEVLK(-1,%ZTIO)
Q
;
IOQ ;GETTASK--search Device Waiting List, Lock IO then DEV.
S ZTSK=0 I '$D(^%ZTSCH("IO")) Q
;Lock to just to get last scan
L +^%ZTSCH("IO"):ZTLKTM I '$T S STATUS="No IO Lock" Q
S ZTI=$G(^%ZTSCH("IO")),ZTH=%ZTIME,%ZTIO=$P(ZTI,"^",2)
I $$I1() S ^%ZTSCH("IO")=ZTH_"^"_%ZTIO ;See if need to update
L -^%ZTSCH("IO") ;Update p446
Q
;
I1() ;Keep 2 sec apart
N ZTDEVOK,X1
I $$PDIFF(%ZTIME,+ZTI,1)'>1 Q 0 ;
I2 S %ZTIO=$O(^%ZTSCH("IO",%ZTIO)),ZTDTH="" I %ZTIO="" G IOX
I $D(^%ZTSCH("IO",%ZTIO))<9 G I2
S IOT=^%ZTSCH("IO",%ZTIO)
I IOT'["RES" G I2:'$$DEVLK(1,%ZTIO) ;lock device if not Resource.
I '$D(^%ZTSCH("DEVTRY",%ZTIO)) S ^%ZTSCH("DEVTRY",%ZTIO)=%ZTIME ;Set problem device check
S X=%ZTIO,X1=IOT,ZTDEVOK=X D DEVOK^%ZOSV I Y D DEVLK(-1,%ZTIO) G I2
I3 S ZTDTH=$O(^%ZTSCH("IO",%ZTIO,ZTDTH)),ZTSK=0 I ZTDTH="" D DEVLK(-1,%ZTIO) G I2
I5 S ZTSK=$O(^%ZTSCH("IO",%ZTIO,ZTDTH,ZTSK)) I ZTSK'>0 G I3
L +^%ZTSK(ZTSK):0 G I5:('$T)
S ZTQUEUED=.5 D DQ^%ZTM4 I $G(^%ZTSK(ZTSK,0))="" L -^%ZTSK(ZTSK) G I5
S ZTH=%ZTIME-20 ;Leave ^%ZTSCH("DEV",io) locked, Released in %ZTMS2
IOX ;
Q 1
;
DEVLK(X,ZIO,TO) ;1=Lock/-1=unlock the ^%ZTSCH("DEV",ZIO) node.
I X<0 L -^%ZTSCH("DEV",ZIO) Q
L +^%ZTSCH("DEV",ZIO):+$G(TO,ZTLKTM) I '$T Q 0
Q 1
;
SUB(X) ;Inc/Dec SUB or return SUB count
N % L +^%ZTSCH("SUB",ZTPFLG("HOME")):5
S %=+$G(^%ZTSCH("SUB",ZTPFLG("HOME"))) S:%<1 %=0
I X>0 D
. L +^%ZTSCH("SUBLK",ZTPFLG("HOME"),$J):5 ;p446
. S ^%ZTSCH("SUB",ZTPFLG("HOME"))=%+1,^%ZTSCH("SUB",ZTPFLG("HOME"),$J)=$H_"^"_$G(STATUS)
. Q
I X<0 D
. S ^%ZTSCH("SUB",ZTPFLG("HOME"))=$S(%>0:%-1,1:0) K ^%ZTSCH("SUB",ZTPFLG("HOME"),$J)
. L -^%ZTSCH("SUBLK",ZTPFLG("HOME"),$J) ;p446
. Q
L -^%ZTSCH("SUB",ZTPFLG("HOME"))
Q:X=0 % Q
;
JCNT(MAXWAIT) ;See if less that MaxWait tasks in JOB list p446
N Z2,Z3 S Z3=$NA(^%ZTSCH("JOB"))
F Z2=1:1:MAXWAIT+1 S Z3=$Q(@Z3) Q:Z3'["JOB"
Q (MAXWAIT>Z2)
;
PDIFF(N,O,T) ;Positive Diff
Q $TR($$DIFF(N,O,$G(T)),"-")
;
DIFF(N,O,T) ;Diff in sec.
Q:$G(T) N-O ;For new seconds times
Q N-O*86400-$P(O,",",2)+$P(N,",",2)
;
TSKSTAT(CODE,MSG) ;Update task's status
S $P(^%ZTSK(ZTSK,.1),U,1,4)=$G(CODE)_U_$H_U_$G(MSG)_U_$J
Q
;
H3(%) ;Convert $H to seconds.
Q 86400*%+$P(%,",",2)
H0(%) ;Covert from seconds to $H
Q (%\86400)_","_(%#86400)
;
FIRST() ;See if SM with lowest $J
I $O(^%ZTSCH("SUB",ZTPFLG("HOME"),0))=$J Q 1
Q 2
--- Routine Detail --- with STRUCTURED ROUTINE LISTING ---[H[J[2J[HZTMS1 6545 printed Dec 13, 2024@02:16:27 Page 2
%ZTMS1 ;SEA/RDS-TaskMan: Submanager, (Loop & Get Task) ;10/07/08 15:46
+1 ;;8.0;KERNEL;**36,49,104,118,127,136,275,446**;JUL 10, 1995;Build 35
+2 ;Per VHA Directive 2004-038, this routine should not be modified.
+3 ;Use ZTLKTM for Lock timeout. p446
SUBMGR ;START--outer submanager loop
+1 ;task locked
DO GETTASK
if ZTSK'>0
GOTO QUIT^%ZTMS
+2 SET STATUS="Run Task "_ZTSK
+3 DO PROCESS^%ZTMS2
if $DATA(ZTQUIT)
GOTO QUIT^%ZTMS
+4 SET STATUS="Idle"
+5 GOTO SUBMGR
+6 ;
GETTASK ;SUBMGR--retain the partition; check Waiting Lists every 1 seconds
+1 DO SUB(1)
SET ZTSK=0
+2 ;
+3 ;Space out the SM loop
FOR ZRT=0:0
Begin DoDot:1
+4 ;Wait
IF $DATA(^%ZTSCH("WAIT","SUB"))
SET STATUS="Wait Node"
HANG 5
QUIT
+5 SET %ZTIME=$$H3($HOROLOG)
SET ZTSK=0
IF $DATA(^%ZTSCH("STOP","SUB",ZTPAIR))
QUIT
+6 ;Do directed work before check for balance
DO C
if ZTSK!(ZTYPE="C")
QUIT
+7 ;If more than xx tasks in JOB Queue don't balance wait. p446
+8 ;Wait for balance, Slow ZRT rise.
IF $$BALANCE
SET ZRT=ZRT-.9
SET STATUS="Balance Wait"
IF $$JCNT(ZTPFLG("BalLimit"))
QUIT
+9 ;Look for work
DO JOB
if 'ZTSK
DO IOQ
+10 QUIT
End DoDot:1
if $$EXIT
QUIT
SET %=$SELECT($ORDER(^%ZTSCH("JOB",0))>0:1,1:$$FIRST())
SET ZRT=ZRT+%
HANG %
+11 ;Adjust counter
DO SUB(-1)
+12 QUIT
+13 ;
EXIT() ;GETTASK--decide whether to exit retention loop
+1 IF ZTSK
IF $DATA(^%ZTSCH("NO-OPTION"))
IF $PIECE(^%ZTSK(ZTSK,0),"^",1,2)="ZTSK^XQ1"
Begin DoDot:1
+2 DO SCHTM^%ZTMS2(ZTDTH+60)
SET ZTSK=0
+3 QUIT
End DoDot:1
+4 IF ZTSK
GOTO YES
+5 IF $DATA(^%ZTSCH("STOP","SUB",ZTPAIR))
GOTO YES
+6 ;Retention time check
IF ZTPFLG("RT")>ZRT
GOTO NO
+7 ;Let extras go
IF $$SUB(0)>ZTPFLG("MIN")
GOTO YES
NO ;Don't exit, Update status node
+1 ;p446
LOCK +^%ZTSCH("SUB",ZTPFLG("HOME"),$JOB):10
+2 ;Keep our node current
SET ^%ZTSCH("SUB",ZTPFLG("HOME"),$JOB)=$HOROLOG_"^"_$GET(STATUS)_"^"_$GET(STATUS("Bal"))
+3 IF ZTPFLG("XUSCNT")
DO SETLOCK^XUSCNT($NAME(^%ZTSCH("SUBLK",ZTPFLG("HOME"),$JOB)))
+4 ;p446
LOCK -^%ZTSCH("SUB",ZTPFLG("HOME"),$JOB)
+5 QUIT 0
+6 ;
YES ;EXIT--Yes ;p446
+1 QUIT 1
+2 ;
C ;GETTASK--On C type volume sets, get tasks from Cross-Volume Job List
+1 SET STATUS="C List"
SET ZTSK=0
+2 IF $ORDER(^%ZTSCH("C",ZTPAIR,0))=""
QUIT
+3 LOCK +^%ZTSCH("C",ZTPAIR):ZTLKTM
IF '$TEST
SET STATUS="No C Lock"
QUIT
+4 SET ZTDTH=""
SET ^%ZTSCH("C",ZTPAIR)=0
+5 FOR
SET ZTDTH=$ORDER(^%ZTSCH("C",ZTPAIR,ZTDTH))
SET ZTSK=0
if ZTDTH=""
QUIT
Begin DoDot:1
+6 FOR
SET ZTSK=$ORDER(^%ZTSCH("C",ZTPAIR,ZTDTH,ZTSK))
SET ZX=0
if ZTSK=""
QUIT
Begin DoDot:2
+7 IF $DATA(^%ZTSK(ZTSK,0))[0!'ZTSK
Begin DoDot:3
+8 IF ZTSK'=0
IF $DATA(^%ZTSK(ZTSK))
DO TSKSTAT("I")
+9 KILL ^%ZTSCH("C",ZTPAIR,ZTDTH,ZTSK)
SET ZTSK=0
+10 QUIT
End DoDot:3
QUIT
+11 LOCK +^%ZTSK(ZTSK):0
if '$TEST
QUIT
+12 SET %ZTIO=^%ZTSCH("C",ZTPAIR,ZTDTH,ZTSK)
SET ZTQUEUED=.5
+13 IF %ZTIO]""
SET ZTDEVN=1
+14 KILL ^%ZTSCH("C",ZTPAIR,ZTDTH,ZTSK)
+15 SET ZX=1
+16 QUIT
End DoDot:2
if ZX
QUIT
+17 QUIT
End DoDot:1
if ZTSK
QUIT
+18 ;If ZTSK>0 then ^%ZTSK(ztsk) is locked.
LOCK -^%ZTSCH("C",ZTPAIR)
+19 QUIT
+20 ;
BALANCE() ;GETTASK--check load balance, and wait while Manager waits
+1 if ZTPAIR=""
QUIT 0
+2 SET STATUS("Bal")=0
+3 ;Try and Lock so we are synced. If can't get Lock run. ;p446
+4 LOCK +^%ZTSCH("LOADA"):0
+5 IF $TEST
SET STATUS("Bal")=+$GET(^%ZTSCH("LOADA",ZTPAIR))
LOCK -^%ZTSCH("LOADA")
+6 ;Added set var & Hang. p446
IF STATUS("Bal")
HANG 1
+7 QUIT STATUS("Bal")
+8 ;
JOB ;GETTASK--search Partition Waiting List
+1 SET ZTSK=0
SET ZTDTH=0
SET ZTQUEUED=0
SET STATUS="JOB Q"
+2 LOCK +^%ZTSCH("JOBQ"):ZTLKTM
IF '$TEST
SET STATUS="No JOBQ Lock"
QUIT
J2 SET ZTDTH=$ORDER(^%ZTSCH("JOB",ZTDTH))
SET ZTSK=0
IF ZTDTH=""
LOCK -^%ZTSCH("JOBQ")
QUIT
J3 SET ZTSK=$ORDER(^%ZTSCH("JOB",ZTDTH,ZTSK))
SET ZTQUEUED=0
IF ZTSK'>0
GOTO J2
+1 ;p446 Back to 0
LOCK +^%ZTSK(ZTSK):0
IF '$TEST
SET STATUS="No ZTSK Lock"
GOTO J3
+2 IF $DATA(^%ZTSCH("JOB",ZTDTH,ZTSK))[0
LOCK -^%ZTSK(ZTSK)
SET STATUS="JOB cleared"
GOTO J3
+3 IF $DATA(^%ZTSK(ZTSK,0))[0
DO BADTASK
LOCK -^%ZTSK(ZTSK)
GOTO J3
+4 SET %ZTIO=^%ZTSCH("JOB",ZTDTH,ZTSK)
SET ZTQUEUED=.5
SET STATUS="Work Task "_ZTSK
+5 KILL ^%ZTSCH("JOB",ZTDTH,ZTSK)
+6 ;Now can release JOBQ
LOCK -^%ZTSCH("JOBQ")
+7 ;try and only pick up work for this node.
+8 ;p446
SET ZTREC=$GET(^%ZTSK(ZTSK,0))
SET %=$PIECE(ZTREC,U,14)
IF %[":"
IF %'[ZTNODE
Begin DoDot:1
+9 ;p446
LOCK +^%ZTSCH("C",%):99
+10 SET ^%ZTSCH("C",%,ZTDTH,ZTSK)=%ZTIO
+11 ;p446
LOCK -^%ZTSCH("C",%),-^%ZTSK(ZTSK)
+12 ;p446
SET ZTSK=0
SET %ZTIO=""
+13 QUIT
End DoDot:1
+14 IF %ZTIO'=""
SET ZTDEVN=1
+15 ;On exit we have ^%ZTSK(ZTSK) Locked if ZTSK>0.
+16 QUIT
+17 ;
BADTASK ;JOB--unschedule tasks with bad numbers or incomplete records
+1 SET %ZTIO=^%ZTSCH("JOB",ZTDTH,ZTSK)
IF %ZTIO]""
SET ZTDEVN=1
+2 IF ZTSK'=0
IF $DATA(^%ZTSK(ZTSK))
DO TSKSTAT("I",3)
+3 KILL ^%ZTSCH("JOB",ZTDTH,ZTSK)
+4 SET ZTQUEUED=0
+5 IF %ZTIO]""
DO DEVLK(-1,%ZTIO)
+6 QUIT
+7 ;
IOQ ;GETTASK--search Device Waiting List, Lock IO then DEV.
+1 SET ZTSK=0
IF '$DATA(^%ZTSCH("IO"))
QUIT
+2 ;Lock to just to get last scan
+3 LOCK +^%ZTSCH("IO"):ZTLKTM
IF '$TEST
SET STATUS="No IO Lock"
QUIT
+4 SET ZTI=$GET(^%ZTSCH("IO"))
SET ZTH=%ZTIME
SET %ZTIO=$PIECE(ZTI,"^",2)
+5 ;See if need to update
IF $$I1()
SET ^%ZTSCH("IO")=ZTH_"^"_%ZTIO
+6 ;Update p446
LOCK -^%ZTSCH("IO")
+7 QUIT
+8 ;
I1() ;Keep 2 sec apart
+1 NEW ZTDEVOK,X1
+2 ;
IF $$PDIFF(%ZTIME,+ZTI,1)'>1
QUIT 0
I2 SET %ZTIO=$ORDER(^%ZTSCH("IO",%ZTIO))
SET ZTDTH=""
IF %ZTIO=""
GOTO IOX
+1 IF $DATA(^%ZTSCH("IO",%ZTIO))<9
GOTO I2
+2 SET IOT=^%ZTSCH("IO",%ZTIO)
+3 ;lock device if not Resource.
IF IOT'["RES"
if '$$DEVLK(1,%ZTIO)
GOTO I2
+4 ;Set problem device check
IF '$DATA(^%ZTSCH("DEVTRY",%ZTIO))
SET ^%ZTSCH("DEVTRY",%ZTIO)=%ZTIME
+5 SET X=%ZTIO
SET X1=IOT
SET ZTDEVOK=X
DO DEVOK^%ZOSV
IF Y
DO DEVLK(-1,%ZTIO)
GOTO I2
I3 SET ZTDTH=$ORDER(^%ZTSCH("IO",%ZTIO,ZTDTH))
SET ZTSK=0
IF ZTDTH=""
DO DEVLK(-1,%ZTIO)
GOTO I2
I5 SET ZTSK=$ORDER(^%ZTSCH("IO",%ZTIO,ZTDTH,ZTSK))
IF ZTSK'>0
GOTO I3
+1 LOCK +^%ZTSK(ZTSK):0
if ('$TEST)
GOTO I5
+2 SET ZTQUEUED=.5
DO DQ^%ZTM4
IF $GET(^%ZTSK(ZTSK,0))=""
LOCK -^%ZTSK(ZTSK)
GOTO I5
+3 ;Leave ^%ZTSCH("DEV",io) locked, Released in %ZTMS2
SET ZTH=%ZTIME-20
IOX ;
+1 QUIT 1
+2 ;
DEVLK(X,ZIO,TO) ;1=Lock/-1=unlock the ^%ZTSCH("DEV",ZIO) node.
+1 IF X<0
LOCK -^%ZTSCH("DEV",ZIO)
QUIT
+2 LOCK +^%ZTSCH("DEV",ZIO):+$GET(TO,ZTLKTM)
IF '$TEST
QUIT 0
+3 QUIT 1
+4 ;
SUB(X) ;Inc/Dec SUB or return SUB count
+1 NEW %
LOCK +^%ZTSCH("SUB",ZTPFLG("HOME")):5
+2 SET %=+$GET(^%ZTSCH("SUB",ZTPFLG("HOME")))
if %<1
SET %=0
+3 IF X>0
Begin DoDot:1
+4 ;p446
LOCK +^%ZTSCH("SUBLK",ZTPFLG("HOME"),$JOB):5
+5 SET ^%ZTSCH("SUB",ZTPFLG("HOME"))=%+1
SET ^%ZTSCH("SUB",ZTPFLG("HOME"),$JOB)=$HOROLOG_"^"_$GET(STATUS)
+6 QUIT
End DoDot:1
+7 IF X<0
Begin DoDot:1
+8 SET ^%ZTSCH("SUB",ZTPFLG("HOME"))=$SELECT(%>0:%-1,1:0)
KILL ^%ZTSCH("SUB",ZTPFLG("HOME"),$JOB)
+9 ;p446
LOCK -^%ZTSCH("SUBLK",ZTPFLG("HOME"),$JOB)
+10 QUIT
End DoDot:1
+11 LOCK -^%ZTSCH("SUB",ZTPFLG("HOME"))
+12 if X=0
QUIT %
QUIT
+13 ;
JCNT(MAXWAIT) ;See if less that MaxWait tasks in JOB list p446
+1 NEW Z2,Z3
SET Z3=$NAME(^%ZTSCH("JOB"))
+2 FOR Z2=1:1:MAXWAIT+1
SET Z3=$QUERY(@Z3)
if Z3'["JOB"
QUIT
+3 QUIT (MAXWAIT>Z2)
+4 ;
PDIFF(N,O,T) ;Positive Diff
+1 QUIT $TRANSLATE($$DIFF(N,O,$GET(T)),"-")
+2 ;
DIFF(N,O,T) ;Diff in sec.
+1 ;For new seconds times
if $GET(T)
QUIT N-O
+2 QUIT N-O*86400-$PIECE(O,",",2)+$PIECE(N,",",2)
+3 ;
TSKSTAT(CODE,MSG) ;Update task's status
+1 SET $PIECE(^%ZTSK(ZTSK,.1),U,1,4)=$GET(CODE)_U_$HOROLOG_U_$GET(MSG)_U_$JOB
+2 QUIT
+3 ;
H3(%) ;Convert $H to seconds.
+1 QUIT 86400*%+$PIECE(%,",",2)
H0(%) ;Covert from seconds to $H
+1 QUIT (%\86400)_","_(%#86400)
+2 ;
FIRST() ;See if SM with lowest $J
+1 IF $ORDER(^%ZTSCH("SUB",ZTPFLG("HOME"),0))=$JOB
QUIT 1
+2 QUIT 2