!
! Connect Count Monitoring Routines.
! ------- ----- ---------- --------
!
! These routines are intended to provide the ability to monitor
! the number of times a given file is connected during a given time
! period.
! Each file on the system has an associated file descriptor one
! of whose fields is the connect count (CCT) which is incremented
! every time the file is connected. The CCT field is a single
! byte therefore values may range from 0 - 255. When the byte reaches
! 255 then further connections leave its value unchanged - the
! field must be reset. In essence the monitoring routines read the
! current value of CCT for the files monitored then reset the field
! back to zero.
! The monitoring programs comprise 4 external routines - CCTMON,
! ALTERCCT,CCTOUT and LOOKCCT - and an associated but separately set up
! monitor file whose name is compiled as a constant in the code.
! Each of the routines is described below along with operating
! instructions and instructions on setting up a monitor file.
!
! 1. Overview.
! The monitor file is a series of records, one for each file
! monitored. These contain fields for the name of the file, its fsys
! the date monitoring started, the value of CCT the last time it
! was read, the accumulated CCT, and the number of 'busy days' i.e.
! the number of days the CCT was >=255.
! Files are added or removed from the monitor file by the routine
! ALTERCCT. The same routine can reset counters for individual files.
! The monitoring information is written in to the monitor file
! by the routine CCTMON which reads and resets the CCT field in
! the file descriptors of the files to be monitored. CCTMON detaches
! itself automatically to run again after midnight n days hence
! (n = 1 currently).
! Information in the monitor file is displayed by the routine
! CCTOUT which produces a summary of monitoring to date.
!
! 2. Operating Instructions.
! ALTERCCT and CCTMON will only run in the owner process
! and require sufficient privilege to read and reset CCT
! fields. LOOKCCT and CCTOUT will run in any process with
! read access to the monitor file. LOOKCCT, however, requires
! the user process to have sufficient privilege to read
! CCT fields.
!
! 2.1 Setting up a monitor file.
! The routines currently expect a monitor file of 1Epage which
! allows 127 monitor records. The filename must be
! compiled in as a constant into the code.
! This file can easily be set up using one of the system
! editors and inserting 4064 characters (which will exactly
! fill 1 Epage) then cherishing and permitting it to those users
! allowed to read the file. If desired some extra protection
! can be supplied by changing the file type to non-standard
! (by using #SNAP on the 4th word of the header).
! The file should be zeroed before use by using option 'ZAP'
! in routine ALTERCCT.
!
! 2.2 CCTMON.
! This routine requires no parameters. When run it prints
! the document number of the job it has detached. When
! running for the first time the routine should be called
! interactively which will reset the CCTs of the files to
! be monitored to zero and detach a job to run next day.
!
! 2.3 ALTERCCT.
! This routine issues prompts for all commands and is used to
! make alterations to the monitor file.
! The command options are :
! HELP,ADD,DEL,REP,RES,TERM,XRES,ZAP,? and .END
! HELP - explains the commands
! ADD - adds a new member to the monitor file - will further
! prompt for <user> and <file>. Also resets the
! file descriptor CCT to 0.
! DEL - deletes a member from the monitor file - will further
! prompt for <user> and <file>
! REP - replaces <user> and <file> for one member of
! the monitor file. No resetting of counters. Should
! be used when a new version of a file with a different
! name (e.g. version number) is introduced. Previous
! monitoring is thus retained. Prompts for <user> and
! <file> to be replaced then new values of <user> and
! <file>. See also TERM.
! RES - resets CCT counters to 0 and the monitor start field to
! today's day number. Resets file descriptor CCT to 0.
! Will further prompt for <user> and <file>.
! TERM - updates counters for a given member for values
! accumulated since the last run of CCTMON. Intended
! to be used in conjunction with REP (q.v.) so that
! CCT values on old versions of a file can be added
! to the monitoring statistics before replacement
! by a new version. Prompts for <user> and <file>.
! XRES - effect is RES for all monitor file members. No <user>,
! <file> prompts.
! ZAP - zeroes the entire monitor file (all information destroyed
! ? - prints list of current members of monitor file.
! .END - terminates requests for another option
!
! 2.3 CCTOUT.
! This routine prints out a summary of the information held
! in the monitor file in a six column table of the form:
! User.file/ date monitoring began/number of days since monitoring
! began/ last value of CCT read for this file/ cumulative CCT/
! number of days when CCT>=255.
! N.B. No privilege required.
!
! 2.4 LOOKCCT.
! This routine prints a table of the current values of CCT
! for each member of the monitor file by reading the file
! descriptors directly. No alterations are made to the
! monitor file. The table therefore represents today's
! values of CCT from the last run of CCTMON till the
! moment of running the routine.
! Requires enough privilege to read CCT fields.
!
! Colin McCallum June 1981.
!
!>
!
RECORDFORMAT PF(INTEGER DEST,SRCE,P1,P2,P3,P4,P5,P6)
RECORDFORMAT MONF(STRING (6) USER, STRING (11) FILE, C
BYTEINTEGER LASTCCT, INTEGER CUMCCT,BUSYDAYS,MONSTART)
RECORDFORMAT RF(INTEGER CONAD,FTYPE,DATASTART,DATAEND)
RECORDFORMAT DFINFOF(INTEGER NKB,RUP,EEP,APF,USE,ARCH, C
FSYS,CONSEG,CCT,CODES, C
BYTEINTEGER SP1,DAYNO,POOL,CODES2, C
INTEGER SSBYTE,STRING (6) TRAN)
EXTERNALROUTINESPEC UDERRS(INTEGER FLAG)
EXTERNALINTEGERFNSPEC DFSTATUS(STRING (6) USER,STRING (11) FILE,C
INTEGER FSYS,ACT,VALUE)
EXTERNALROUTINESPEC RSTRG(STRINGNAME S)
EXTERNALROUTINESPEC PROMPT(STRING (15) S)
EXTERNALINTEGERFNSPEC DSPOOL(RECORD (PF)NAME P, INTEGER LEN,ADR)
EXTERNALINTEGERFNSPEC DFINFO(STRING (6) USER, STRING (11) FILE, C
INTEGER FSYS,ADR)
SYSTEMROUTINESPEC OUTFILE(STRING (31) S, INTEGER SIZE,MAXBYTES, C
PROT, INTEGERNAME CONAD,FLAG)
SYSTEMROUTINESPEC MOVE(INTEGER LEN,FROM,TO)
SYSTEMROUTINESPEC PSYSMES(INTEGER I, FLAG)
SYSTEMROUTINESPEC CONNECT(STRING (31)S,INTEGER ACC,MAXB,PRO, C
RECORD (RF)NAME RR, INTEGERNAME FLAG)
EXTERNALSTRINGFNSPEC DATE
EXTERNALSTRINGFNSPEC TIME
SYSTEMINTEGERFNSPEC PACKDATEANDTIME(STRING (8) DATE,TIME)
SYSTEMSTRING (8)FNSPEC UNPACKDATE(INTEGER I)
SYSTEMSTRING (8)FNSPEC UNPACKTIME(INTEGER I)
EXTERNALROUTINESPEC DISCONNECT(STRING (255) S)
SYSTEMSTRINGFNSPEC ITOS(INTEGER I)
CONSTINTEGER MAXREC=127
CONSTSTRING (255) HELP= C
"
Options are:
ADD - Add a new member
DEL - Delete a member
REP - Replace member name
RES - Reset counters for a single member
"
CONSTSTRING (255) HELP2= C
"TERM - Update counters for one member
XRES - Reset counters for all members
ZAP - Zero the entire file (destroys all info)
? - Print out files currently being monitored
"
CONSTSTRING (15) MONFILE="MANAGR.CCTMFILE"
OWNRECORD (MONF)ARRAYFORMAT MONAF(0:MAXREC-1)
OWNRECORD (MONF)ARRAYNAME TAB
OWNRECORD (DFINFOF) FINF
OWNRECORD (RF) RR
ROUTINE KDATE(INTEGERNAME D,M,Y,INTEGER K)
!***********************************************************************
!* K IS DAYS SINCE 1ST JAN 1900 *
!* RETURNS D, M, Y 2 DIGIT Y ONLY *
!***********************************************************************
! %INTEGER W
! K=K+693902; ! DAYS SINCE CEASARS BDAY
! W=4*K-1
! Y=W//146097
! K=W-146097*Y
! D=K//4
! K=(4*D+3)//1461
! D=4*D+3-1461*K
! D=(D+4)//4
! M=(5*D-3)//153
! D=5*D-3-153*M
! D=(D+5)//5
! Y=K
*LSS_K; *IAD_693902
*IMY_4; *ISB_1; *IMDV_146097
*LSS_TOS ; *IDV_4; *IMY_4; *IAD_3
*IMDV_1461; *ST_(Y)
*LSS_TOS ; *IAD_4; *IDV_4
*IMY_5; *ISB_3; *IMDV_153
*ST_(M); *LSS_TOS
*IAD_5; *IDV_5; *ST_(D)
IF M<10 THEN M=M+3 ELSE START
M=M-9
IF Y=99 THEN Y = 0 ELSE Y=Y+1
FINISH
END ; ! OF KDATE
INTEGERFN DDAYNO
CONSTLONGINTEGER JMS=X'141DD76000'
INTEGER RES
*RRTC_0
*USH_-1
*SHS_1
*USH_1
*IDV_JMS
*STUH_B
! *AND_255
*ST_RES
! RES=1 %IF RES=0
RESULT =RES
END ; ! OF DDAYNO
STRINGFN MYDATE(INTEGER DAYNO)
INTEGER D,M,Y
STRING (3) DD,MM,YY
KDATE(D,M,Y,DAYNO)
DD=ITOS(D)
DD="0".DD IF LENGTH(DD)=1
MM=ITOS(M)
MM="0".MM IF LENGTH(MM)=1
YY=ITOS(Y)
YY="0".YY IF LENGTH(YY)=1
RESULT =DD."/".MM."/".YY
END ; ! OF MYDATE
INTEGERFN GETCCT(STRING (15) USER,FILE)
INTEGER FLAG
! GET CCT
FLAG=DFINFO(USER,FILE,-1,ADDR(FINF))
PRINTSTRING(USER.".".FILE." ") AND C
UDERRS(FLAG) UNLESS FLAG=0
RESULT =FLAG
END ; ! OF GETCCT
INTEGERFN RESET CCT(INTEGER I)
INTEGER FLAG
! RESET CCT TO 0
FLAG=DFSTATUS(TAB(I)_USER,TAB(I)_FILE,-1,9,0)
PRINTSTRING(TAB(I)_USER.".".TAB(I)_FILE." ") AND C
UDERRS(FLAG) UNLESS FLAG=0
RESULT =FLAG
END ; ! OF RESET CCT
ROUTINE AUTOJOB(STRING (255) COMMANDS, INTEGER INTERVAL,CPU)
INTEGER COMMAD,FLAG,DAYNO,CONAD,NEWSIZE
STRING (255) MESSAGE
RECORD (PF) P
COMMAD=ADDR(COMMANDS)
NEWSIZE=LENGTH(COMMANDS)+32
OUTFILE("S#AUTO",NEWSIZE,NEWSIZE,0,CONAD,FLAG)
IF FLAG#0 THEN PSYSMES(10,FLAG) AND RETURN
INTEGER(CONAD)=NEWSIZE
INTEGER(CONAD+4)=32
INTEGER(CONAD+12)=3
MOVE(NEWSIZE-32,COMMAD+1,CONAD+32)
DISCONNECT("S#AUTO")
DAYNO=DDAYNO+INTERVAL
MESSAGE="DOCUMENT SRCE=S#AUTO,DEST=BATCH,NAME=AUTO,AFTER=". C
MYDATE(DAYNO).",DELIV=R.D.Eager CUR022 CUR022,".C
"TIME=".ITOS(CPU).",START=32". C
",LENGTH=".ITOS(NEWSIZE)
NEWLINE
P=0
FLAG=DSPOOL(P,LENGTH(MESSAGE),ADDR(MESSAGE)+1)
UNLESS FLAG=0 THEN START
UDERRS(FLAG)
PRINTSTRING(MESSAGE)
PRINTSTRING("Error at or around char")
WRITE(P_P3,1)
NEWLINE
FINISH ELSE START
PRINTSTRING("CCTMON Batch queue ident :")
WRITE(P_P2&X'FFFFFF',1)
NEWLINE
FINISH
RETURN
END ; ! OF AUTOJOB
EXTERNALROUTINE CCTMON(STRING (255) S)
STRING (8) TODAY,NOW
INTEGER FLAG,TOP,I
CONNECT(MONFILE,3,0,0,RR,FLAG)
PSYSMES(8,FLAG) AND RETURN UNLESS FLAG=0
TAB==ARRAY(RR_CONAD+RR_DATASTART,MONAF)
TOP=INTEGER(RR_CONAD+28)-1
FOR I=0,1,TOP CYCLE
! GET CCT
FLAG=GETCCT(TAB(I)_USER,TAB(I)_FILE)
CONTINUE UNLESS FLAG=0
TAB(I)_LASTCCT=FINF_CCT
TAB(I)_CUMCCT=TAB(I)_CUMCCT+FINF_CCT
TAB(I)_BUSYDAYS=TAB(I)_BUSYDAYS+1 IF FINF_CCT=255
! RESET CCT TO 0
FLAG=RESET CCT(I)
REPEAT
TODAY=DATE
NOW=TIME
INTEGER(RR_CONAD+16)=PACKDATEANDTIME(TODAY,NOW)
AUTOJOB("CCTMON
CCTOUT
",1,20)
DISCONNECT(MONFILE)
RETURN
END ; ! OF CCTMON
EXTERNALROUTINE ALTERCCT(STRING (255) S)
STRING (31) REPLY,USER,FILE
INTEGER TOP,FLAG,FOUND,TODAYSDAYNO,I,NEXTFREE
INTEGERFN FIND(STRING (6) USER, STRING (11) FILE)
INTEGER I,J
J=-1
FOR I=0,1,TOP CYCLE
J=I AND EXIT IF TAB(I)_USER=USER AND TAB(I)_FILE=FILE
REPEAT
RESULT =J
END ; ! OF FIND
TODAYSDAYNO=DDAYNO
CONNECT(MONFILE,3,0,0,RR,FLAG)
PSYSMES(8,FLAG) AND RETURN UNLESS FLAG=0
TAB==ARRAY(RR_CONAD+RR_DATASTART,MONAF)
NEXTFREE=INTEGER(RR_CONAD+28)
TOP=NEXTFREE-1
CYCLE
PRINTSTRING("Valid options are:
'HELP','ADD','DEL','REP','RES','TERM','XRES','ZAP' or '?'.
Terminate with '.END'
")
PROMPT("Option? : ")
RSTRG(REPLY) UNTIL REPLY="ADD" OR REPLY="DEL" OR REPLY=".END" C
OR REPLY="ZAP" OR REPLY="?" OR REPLY="RES" OR REPLY="XRES" C
OR REPLY="HELP" OR REPLY="REP" OR REPLY="TERM"
EXIT IF REPLY=".END"
IF REPLY="HELP" THEN PRINTSTRING(HELP) AND C
PRINTSTRING(HELP2) AND CONTINUE
IF REPLY="ZAP" THEN START
TAB(I)=0 FOR I=0,1,MAXREC-1
INTEGER(RR_CONAD+28)=0
NEXTFREE=0
TOP=-1
CONTINUE
FINISH
IF REPLY="XRES" THEN START
IF TOP<0 THEN PRINTSTRING("*Table empty*
") AND CONTINUE
FOR I=0,1,TOP CYCLE
TAB(I)_MONSTART=TODAYSDAYNO
TAB(I)_LASTCCT=0
TAB(I)_CUMCCT=0
TAB(I)_BUSYDAYS=0
FLAG=RESET CCT(I)
PRINTSTRING(TAB(I)_USER.".".TAB(I)_FILE." reset
") IF FLAG=0
REPEAT
CONTINUE
FINISH
IF REPLY="?" THEN START
PRINTSTRING(TAB(I)_USER.".".TAB(I)_FILE."
") FOR I=0,1,TOP
CONTINUE
FINISH
IF REPLY="ADD" AND NEXTFREE=MAXREC THEN PRINTSTRING("*Table full*
") AND CONTINUE
IF (REPLY="DEL" OR REPLY="RES") AND TOP<0 THEN C
PRINTSTRING("*Table empty*
") AND CONTINUE
PROMPT("User: ")
RSTRG(USER) UNTIL LENGTH(USER)=6
PROMPT("File: ")
RSTRG(FILE)
FLAG=GETCCT(USER,FILE); ! DOES IT EXIST?
CONTINUE UNLESS FLAG=0 OR REPLY="REP"
FOUND=FIND(USER,FILE)
IF REPLY="ADD" THEN START
IF FOUND>=0 THEN PRINTSTRING(USER.".".FILE." already in table
") AND CONTINUE
TAB(NEXTFREE)=0
TAB(NEXTFREE)_USER=USER
TAB(NEXTFREE)_FILE=FILE
TAB(NEXTFREE)_MONSTART=TODAYSDAYNO
TOP=NEXTFREE
FLAG=RESET CCT(NEXTFREE)
CONTINUE UNLESS FLAG=0
NEXTFREE=NEXTFREE+1
INTEGER(RR_CONAD+28)=NEXTFREE
PRINTSTRING(USER.".".FILE." added to CCT monitor table
")
CONTINUE
FINISH
! MUST BE DELETING OR RESETTING 1 MEM
IF FOUND=-1 THEN PRINTSTRING(USER.".".FILE." not in table
") AND CONTINUE
IF REPLY="DEL" THEN START
! CLOSE UP TABLE
TAB(FOUND)=TAB(FOUND+1) AND FOUND=FOUND+1 WHILE FOUND<TOP
TAB(TOP)=0
NEXTFREE=TOP
TOP=TOP-1
INTEGER(RR_CONAD+28)=NEXTFREE
PRINTSTRING(USER.".".FILE." removed from CCT monitor list
")
CONTINUE
FINISH
IF REPLY="RES" THEN START
FLAG=RESET CCT(FOUND)
CONTINUE UNLESS FLAG=0
TAB(FOUND)_MONSTART=TODAYSDAYNO
TAB(FOUND)_LASTCCT=0
TAB(FOUND)_CUMCCT=0
TAB(FOUND)_BUSYDAYS=0
PRINTSTRING(USER.".".FILE." reset
")
CONTINUE
FINISH
IF REPLY="REP" THEN START
PRINTSTRING("To be replaced by:
")
PROMPT("User: ")
RSTRG(USER) UNTIL LENGTH(USER)=6
PROMPT("File: ")
RSTRG(FILE)
FLAG=GETCCT(USER,FILE); ! DOES IT EXIST?
CONTINUE UNLESS FLAG=0
TAB(FOUND)_USER=USER
TAB(FOUND)_FILE=FILE
PRINTSTRING("Replacement complete
")
FINISH
IF REPLY="TERM" THEN START
TAB(FOUND)_LASTCCT=FINF_CCT
TAB(FOUND)_CUMCCT=TAB(FOUND)_CUMCCT+FINF_CCT
TAB(FOUND)_BUSYDAYS=TAB(FOUND)_BUSYDAYS+1 IF FINF_CCT=255
! RESET CCT TO 0
FLAG=RESET CCT(FOUND)
PRINTSTRING("Terminated O.K.
")
FINISH
REPEAT
DISCONNECT(MONFILE)
RETURN
END ; ! OF ALTERCCT
EXTERNALROUTINE CCTOUT(STRING (255) S)
INTEGER TOP,FLAG,I,TODAYSDAYNO
TODAYSDAYNO=DDAYNO
CONNECT(MONFILE,1,0,0,RR,FLAG)
PSYSMES(8,FLAG) AND RETURN UNLESS FLAG=0
TAB==ARRAY(RR_CONAD+RR_DATASTART,MONAF)
TOP=INTEGER(RR_CONAD+28)-1
PRINTSTRING("CCT monitor file has no entries
") AND RETURN UNLESS TOP>=0
PRINTSTRING("Monitoring file last updated - ". C
UNPACKDATE(INTEGER(RR_CONAD+16))." at ". C
UNPACKTIME(INTEGER(RR_CONAD+16))."
")
PRINTSTRING( C
"Monitor file Monstart Days Last CCT Cum CCT >=255
")
FOR I=0,1,TOP CYCLE
PRINTSTRING(TAB(I)_USER.".".TAB(I)_FILE)
SPACES(14-LENGTH(TAB(I)_FILE))
PRINTSTRING(MYDATE(TAB(I)_MONSTART))
WRITE(TODAYSDAYNO-TAB(I)_MONSTART,7)
WRITE(TAB(I)_LASTCCT,8)
WRITE(TAB(I)_CUMCCT,11)
WRITE(TAB(I)_BUSYDAYS,7)
NEWLINE
REPEAT
DISCONNECT(MONFILE)
RETURN
END ; ! OF CCTOUT
EXTERNALROUTINE LOOKCCT(STRING (255) S)
EXTERNALSTRINGFNSPEC DATE
EXTERNALSTRINGFNSPEC TIME
INTEGER TOP,FLAG,I
PRINTSTRING("LOOKCCT at ".TIME." on ".DATE."
")
CONNECT(MONFILE,1,0,0,RR,FLAG)
PSYSMES(8,FLAG) AND RETURN UNLESS FLAG=0
TAB==ARRAY(RR_CONAD+RR_DATASTART,MONAF)
TOP=INTEGER(RR_CONAD+28)-1
PRINTSTRING("CCT monitor file has no entries
") AND RETURN UNLESS TOP>=0
PRINTSTRING( C
"Monitor file Current CCT
")
FOR I=0,1,TOP CYCLE
! GET CCT
FLAG=GETCCT(TAB(I)_USER,TAB(I)_FILE)
IF FLAG=0 THEN PRINTSTRING(TAB(I)_USER.".".TAB(I)_FILE." ") C
ELSE CONTINUE
SPACES(14-LENGTH(TAB(I)_FILE))
WRITE(FINF_CCT,8)
NEWLINE
REPEAT
DISCONNECT(MONFILE)
RETURN
END ; ! OF LOOKCCT
ENDOFFILE