.TITLE VDR -- Report virtual disks QIO counts .IDENT /V1.0/ .ENABLE LC .NLIST BEX ; ; AUTHOR: J.M. MILLER 6-18-82 ; ; ;****************************************************************************** ; ; This software is provided on an "as is" basis only. Caterpillar Tractor Co., ; disclaims all warranties on the program, including without limitation, all ; implied warranties of merchantablity and fitness. ; ; Full permission and consent is hereby given to DECUS and to the DECUS ; special interest groups to reproduce, distribute, and publish and permit ; others to reproduce in whole or in part, in any form and without restriction ; this program and any information relating thereto ; ;****************************************************************************** ; ; MODIFICATIONS: ; ; Description: ; ; This program takes the virtual disk QIO data from a log file ; and produces a report a on terminal or file. The report gives ; the total QIO's on each device, the total cumulative QIO's, ; and the times that the system was rebooted. A more detailed ; report can also be obtained which lists the QIO's accumulated ; on a device in each logging period. ; ; Command line: ; ; VDR [output file][/FU][=input file] ; ; where: ; ; output file - This is a standard file spec with the default being TI: ; ; input file - This is also a standard file spec but the default is ; LB:[200,1]VDQIO.OLD ; ; /FU - This switch gives a enables detail reporting. ; ; ; ; ; ; Needed macros ; .MCALL EXIT$S, QIOW$, DIR$, GMCR$, ALUN$S .MCALL FSRSZ$, FDBDF$, FDAT$A, FDRC$A, FDOP$A, FDBF$A, FINIT$ .MCALL NMBLK$, OPEN$R, OPEN$W, CLOSE$, PUT$, GET$ .MCALL CSI$, CSI$1, CSI$2, CSI$SW, CSI$ND FSRSZ$ 4 CSI$ ; ; Define FCS error macro. ; .MACRO FCSERR ERRMSG MOV #ERRMSG,R1 JMP ERR .ENDM FCSERR ; ; Define non FCS error macro. ; .MACRO ERROR ERRMSG MOV #ERRMSG,R1 JMP ERR1 .ENDM ERROR ; ; Define FDB for output file. ; FDB: FDBDF$ ;allocate file descriptor block FDAT$A R.VAR,FD.CR FDRC$A ,,132. FDOP$A 1,,DNB DNB: NMBLK$ ,,,TI,0 .EVEN ; ; Define FDB for file input file. ; FDB1: FDBDF$ ;allocate file descriptor block FDAT$A R.VAR FDRC$A ,,256. FDOP$A 2,DSB1 DSB1: .WORD 3 .WORD DEVNM1 .WORD 9. .WORD DIRNM1 .WORD 9. .WORD FILNM1 DEVNM1: .ASCII /LB:/ .EVEN DIRNM1: .ASCII /[200,001]/ .EVEN FILNM1: .ASCII /VDQIO.OLD/ .EVEN ; ; Switch bit masks ; FL.FUL=1 ;give full listing ; ; CSI data ; CSIBLK: .BLKB C.SIZE .EVEN SWTAB: CSI$SW FU,FL.FUL,,SET CSI$ND ; ; Work areas ; NEWBUF: .WORD BUF1 OLDBUF: .WORD BUF2 .WORD 0 DIFBUF: .BLKB 256. BUF1: .BLKB 256. BUF2: .BLKB 256. ARGBLK: .WORD 0,0 RLEN: .WORD 0 ITOTAL: .BLKW 80.*2 ;individual qio totals buffer TOTAL: .WORD 0,0 ;total qio buffer CRASH: .WORD 0 ;crash indicator FORMAT: .WORD 4 ;# virtual disks to output on a line ; ; Directives ; QOUT: QIOW$ IO.WVB,3,1,,,,<,,40> GETCMD: GMCR$ ; ; EDMSG strings. ; STR1: .ASCIZ /%10SVirtual disk QIO's for %Y%4N/ STR2: .ASCIZ /%3Z%2S/ STR3: .ASCIZ /%15%S%T.%9>/ STR4: .ASCIZ /%10S/ STR5: .ASCIZ /Total%5S/ STRT: .ASCIZ /%N%5STotal QIO's = %T./ CRSMSG: .ASCII <15><12>/System reboot at / ;system crash message CRTIM: .ASCII / /<15><12> CRSL=.-CRSMSG .EVEN ; ; Error messages. ; SERR1: .ASCIZ /VDR -- Error opening input file, FCS %O/ SERR2: .ASCIZ /VDR -- Error opening output file, FCS %O/ SERR3: .ASCIZ /VDR -- Error reading input file, FCS %O/ SERR4: .ASCIZ /VDR -- Error writing output file, FCS %O/ SERR7: .ASCIZ /VDR -- Command syntax error/ SERR8: .ASCIZ /VDR -- Invalid input filename/ SERR9: .ASCIZ /VDR -- Invalid output filename/ .EVEN .PAGE .SBTTL CMD - command line processing ; ; Get command line if there is one and parse it. ; START: ALUN$S #1,#"SY,#0 ;init luns to user's device ALUN$S #2,#"SY,#0 ; " " " " FINIT$ ;initialize FSR DIR$ #GETCMD ;get command line BCS 2$ ;branch if there isn't one MOV #GETCMD+G.MCRB,R1 ;get start of command line MOV $DSW,R2 ;get command line length 1$: CMPB #' ,(R1)+ ;get 1st blank char BEQ 5$ ;branch if found it SOB R2,1$ ;loop till end 2$: OPEN$R #FDB1 ;open input file BCC 3$ ;branch if good open FCSERR SERR1 ;output error message 3$: OPEN$W #FDB ;open output file BCC 4$ ;branch if error FCSERR SERR1 ;output error message 4$: JMP MAIN ;begin main processing 5$: DEC R2 ;adjust length CSI$1 #CSIBLK,R1,R2 ;verify command syntax BCC 10$ ;branch if successful ERROR SERR7 ;output error message ; ; Set up filename block for the input file if one was specified. ; 10$: BITB #CS.EQU,C.STAT(R0) ;is there an equal sign? BEQ 14$ ;branch if no 11$: CSI$2 #CSIBLK,INPUT ;get input file specification BCC 12$ ;branch if successful ERROR SERR8 ;output error message 12$: BITB #CS.NMF,C.STAT(R0) ;filename entered? BNE 13$ ;branch if entered ERROR SERR8 ;output error message 13$: MOV #CSIBLK+C.DSDS,FDB1+F.DSPT ;get dataset descriptor addr 14$: OPEN$R #FDB1 ;open input file BCC 20$ ;branch if successful FCSERR SERR1 ;output error message ; ; Setup output filename block if there was one. ; 20$: CSI$2 #CSIBLK,OUTPUT,#SWTAB ;get file specification & switches BCC 21$ ;branch if succesfull ERROR SERR9 ;output error message 21$: BITB #CS.NMF!CS.DIF!CS.DVF,C.STAT(R0) ;filespec entered? BEQ 24$ ;branch if no 22$: BITB #CS.NMF,C.STAT(R0) ;filename entered? BNE 23$ ;branch if yes ERROR SERR9 ;output error message 23$: MOV #7,FORMAT ;since file, put 7 disks on output line MOVB #63,STR1+1 ;center title line MOV #0,FDB+F.DFNB ;don't use default name block MOV #CSIBLK+C.DSDS,FDB+F.DSPT ;get dataset descriptor addr 24$: OPEN$W #FDB ;open output file BCC MAIN ;branch if good open FCSERR SERR2 ;output error message .PAGE .SBTTL MAIN - mainline processing ; ; Output report heading ; MAIN: GET$ #FDB1,NEWBUF ;get 1st record (date stamp) BCC 1$ ;branch if good read FCSERR SERR3 ;output error message 1$: MOV #DIFBUF,R0 ;create the report title MOV #STR1,R1 ; " " " " MOV NEWBUF,R2 ; " " " " CALL $EDMSG ; " " " " PUT$ #FDB,#DIFBUF,R1 ;output heading BCC PROC ;branch if good write FCSERR SERR4 ;output error message ; ; Now process the main records. ; PROC: GET$ #FDB1,NEWBUF ;get new detail record BCC 1$ ;branch if more records CMPB #IE.EOF,F.ERR(R0) ;end of file? BEQ TOTLZ ;branch if end-of-file FCSERR SERR3 ;output error message 1$: CLR CRASH ;clear crash indicator MOV #ITOTAL,R4 ;get individual qio total buf CALL DIF ;compute QIO's since last record TST CRASH ;did system crash BEQ 2$ ;branch if no MOV #CRTIM,R0 ;use edit message MOV #STR2,R1 ; to output MOV NEWBUF,R2 ; the time the CALL $EDMSG ; system was rebooted MOV #CRSL,R4 ;get length of message PUT$ #FDB,#CRSMSG,R4 ;output crash message 2$: BITB #FL.FUL,CSIBLK+C.MKW1 ;skip printing of detail line? BEQ 3$ ;branch if yes CALL TSTAMP ;make a time stamp CALL DLIN2 ;create data lines 3$: MOV NEWBUF,ARGBLK ;flip flop buffers so that the new MOV OLDBUF,NEWBUF ; input record does not write over MOV ARGBLK,OLDBUF ; previous record BR PROC ; ; Print out the total number of QIO's for each disk and also a ; cumulative total for all the disks. ; TOTLZ: MOV RLEN,R3 ;get length of last good record MOV NEWBUF,ARGBLK ;make NEWBUF have last good record MOV OLDBUF,NEWBUF ; " " " " " " MOV ARGBLK,OLDBUF ; " " " " " " ADD NEWBUF,R3 ;compute ending addr of last good record MOV NEWBUF,R0 ;get addr where 1st VD QIO count goes ADD #10,R0 ; " " " " " " " " MOV #ITOTAL,R1 ;get addr of individual disk QIO total 1$: ADD (R0),(R1) ;compute individual ADC (R1) ; disk QIO ADD 2(R0),2(R1) ; total MOV (R1),2(R0) ;put individual total count in NEWBUF MOV 2(R1),(R0) ; for printing-swap hi & lo for EDMSG ADD (R1),TOTAL ;compute grand total ADC TOTAL+2 ; for all the ADD 2(R1),TOTAL+2 ; virtual disk QIO's ADD #4,R1 ;increment ADD #6,R0 ; counters CMP R0,R3 ;done adding individual totals? BLT 1$ ;branch if no CLR R4 ;clear output byte counter MOV OLDBUF,R0 ;output "TOTAL" MOV #STR5,R1 ; " " MOV NEWBUF,R2 ; " " CALL $EDMSG ; " " ADD #6,R2 ;bypass time stamp ADD R1,R4 ;keep track of bytes in output buffer CALL DLIN2 ;create data lines MOV TOTAL,-(SP) ;swap lo and hi MOV TOTAL+2,TOTAL ; words for MOV (SP)+,TOTAL+2 ; EDMSG MOV #TOTAL,ARGBLK ;put total QIO addr in argument block MOV OLDBUF,R0 ;get output buffer addr MOV #STRT,R1 ;get input string addr MOV #ARGBLK,R2 ;get argument block addr CALL $EDMSG ; PUT$ #FDB,OLDBUF,R1 ;output total QIO's ; ; Close files and exit. ; DONE: CLOSE$ #FDB ;close output file CLOSE$ #FDB1 ;close input file EXIT$S .PAGE .SBTTL ERROR - output error messages ; ; Error processing. ; ERR: MOV R0,R2 ADD #F.ERR,R2 MOV OLDBUF,R0 ;get output buffer address CALL $EDMSG MOV OLDBUF,QOUT+Q.IOPL ;get output buffer address MOV R1,QOUT+Q.IOPL+2 ;get length of ouput message DIR$ #QOUT JMP DONE ERR1: MOV R1,QOUT+Q.IOPL MOV #-1,R0 1$: INC R0 TSTB (R1)+ BNE 1$ MOV R0,QOUT+Q.IOPL+2 DIR$ #QOUT JMP DONE .PAGE .SBTTL DIF - computes the differenc in QIO counts ; ; This subroutine copies the current input buffer (address ; stored in NEWBUF) to DIFBUF in order to compute the change ; in the QIO counts from the previous record (stored in buffer ; whose address is in OLDBUF). ; ; INPUTS: ; R0 FDB address of input file ; R3 input record length ; R4 address of individual disk QIO accumulator ; ; OUTPUTS: ; R0 destroyed ; R3 address of last record in work buffer (DIFBUF) ; R4 destroyed ; DIF: MOV F.NRBD(R0),R3 ;get length of record MOV R3,RLEN ;save record length MOV NEWBUF,R0 ;get addr of input buffer MOV #DIFBUF,R1 ;get addr of work buffer MOV R3,R2 ;get length of input record 1$: MOVB (R0)+,(R1)+ ;copy input record to work buffer SOB R2,1$ ;branch if more records MOV OLDBUF,R0 ;get addr of previous input record ADD #10,R0 ;skip over time & 1st unit number MOV #DIFBUF+10,R1 ;get addr of 1st QIO count in work buf ADD #DIFBUF,R3 ;compute addr of last byte+1 in work buf 2$: TST CRASH BNE 4$ CMP 2(R0),2(R1) ;old value greater than new value? BHI 4$ ;branch if yes BLO 3$ ;branch if less than CMP (R0),(R1) ;old value greater than new value? BHI 4$ ;branch if yes 3$: SUB (R0),(R1) ;compute the difference in the SBC (R1) ; current and the previous SUB 2(R0),2(R1) ; QIO counts MOV (R1),-(SP) ;swap low and high MOV 2(R1),(R1) ; values around MOV (SP)+,2(R1) ; for EDMSG BR 5$ ;go incr counters 4$: ADD (R0),(R4) ;add old value to total counter ADC (R4) ; " " " " " " ADD 2(R0),2(R4) ; " " " " " " MOV #-1,CRASH ;indicate there was a crash 5$: ADD #6,R0 ;advance pointers to next QIO count ADD #6,R1 ; " " " " " " ADD #4,R4 ;advance total qio buffer index CMP R1,R3 ;reached end of QIO counts? BLT 2$ ;branch if more counts to process RETURN .PAGE .SBTTL TIME STAMP - ; ; This routine puts the time stamp from the input record into ; ASCII and stores it in the output buffer. ; TSTAMP: CLR R4 ;init output byte counter MOV OLDBUF,R0 ;output the time stamp MOV #STR2,R1 ; " " " " MOV #DIFBUF,R2 ; " " " " CALL $EDMSG ; " " " " ADD R1,R4 ;keep track of bytes in output buffer RETURN .PAGE .SBTTL DLIN - Create data line for report ; ; This subroutine puts the actual data into a report format. ; It has two entry points. DLIN1 is where print lines are ; formatted that don't start with something in the time stamp ; position. DLIN2 is the starting point for print lines that ; do have something in the time stamp position. ; ; INPUT: ; R0 pointer to next byte to use in output buffer (OLDBUF) ; R2 pointer to next byte to use in work buffer (DIFBUF) ; R3 address of last byte of work record + 1 ; ; OUTPUT: ; R0-R5 not preserved ; DLIN1: CLR R4 ;init output byte counter MOV OLDBUF,R0 ;output blanks in the time stamp position MOV #STR4,R1 ; " " " " " " " " CALL $EDMSG ; " " " " " " " " ADD R1,R4 ;increment bytes to output DLIN2: MOV FORMAT,R5 ;number of virtual disks on a line 1$: MOV (R2)+,ARGBLK ;put unit # in argument block MOV R2,ARGBLK+2 ;put QIO count addr in argument block ADD #4,R2 ;advance work buffer pointer MOV R2,-(SP) ;save work buffer pointer MOV #ARGBLK,R2 ;put argument block addr in R2 MOV #STR3,R1 ;get descriptor string addr CALL $EDMSG ;do conversion ADD R1,R4 ;increment bytes to output counter MOV (SP)+,R2 ;restore work buffer record pointer CMP R2,R3 ;processed whole buffer? BLT 3$ ;branch if more PUT$ #FDB,OLDBUF,R4 ;output print line BCC 2$ ;branch if successful write FCSERR SERR4 ;output error message 2$: RETURN ; 3$: SOB R5,1$ ;see if print line full PUT$ #FDB,OLDBUF,R4 ;output print line BCC 4$ ;branch if successful write FCSERR SERR4 ;output error message 4$: CALL DLIN1 ;reinvoke self till record buffer empty RETURN .END START