.TITLE FRG DISK FRAGMENTATION .ident -030100- .nlist me,cnd,bex .list ttm .enabl lc .sbttl Author's credits ;+ ; ; DATE: 7/12/77 ; REVISED 2/7/78 D. M. ; BY: D. MICHAUD ; BORG INSTRUMENTS ; DELAVAN WISCONSIN ; ; THIS MCR TASK WILL PRODUCE FRAGMENTATION STATISTICS FOR THE SPECIFIED ; FILES-11 DEVICE. THE OUTPUT IS A FREQUENCY COUNT OF CONTIGUOUS FREE ; BLOCKS (HOLES) FALLING WITHIN EACH OF SEVERAL RANGES, THE TOTAL NUMBER ; OF BLOCKS FOR EACH RANGE, AND THE TOTAL NUMBER OF FREE BLOCKS FOR THE ; DEVICE. ; ; OUTPUT IS DIRECTED TO LUN 2, WHICH MAY BE ASSIGNED TO ANY TERMINAL. ; ERROR MESSAGES ARE DIRECTED TO LUN 5. ; ; MODIFIED: 19-OCT-78, D2.0, BRUCE C. WRIGHT ; CORRECTED NUMEROUS BUGS, ALLOWED NON-MCR COMMAND LINE ; EXECUTION, BETTER ERROR MESSAGES, USE 32-BIT ARITHMETIC. ; ; Modified: 06-Feb-80, -3.0.0-, Henry R. Tumblin ; Cleaned up output, Use $EDMSG to format messages ; ; Modified: 01-Nov-1981, -3.1.0-, Bruce C. Wright ; Corrected $EDMSG strings to avoid blanks being ; printed out rather than the numeric field if the ; numeric field was > 100000; also, fixed to default ; the line width to 80. if the device we're running ; on doesn't return its line length (like the batch ; handler, for example). ; ; Verified: 01-Nov-1981, -3.1.0-, Bruce C. Wright ;- .sbttl Mcalls and local definitions .MCALL GTIM$S,QIOW$,EXIT$S,DIR$,ALUN$,WSIG$S .MCALL GCMLB$,GCML$,FCSMC$,GLUN$S,QIOW$S FCSMC$ .MACRO ERROR STR,?ADDR .NCHR $$$, .PSECT ERMSG .EVEN ADDR: .WORD $$$ .ASCII "STR" .PSECT MOV #ADDR,-(SP) JMP $ERROR .ENDM .MACRO DIR$$ ARG MOV ARG,-(SP) JSR PC,.DIRDL .ENDM ; ; LOGICAL UNIT NUMBERS ; DSKLUN = 1 ;DISK I/O TTYLUN = 2 ; Message output lun CMLLUN = 3 ;COMMAND LINE I/O ERRLUN = 4 ;ERROR MESSAGE I/O .sbttl FDB's, DPB's FSRSZ$ 1,512.+S.BFHD ; ONE FCS BUFFER FOR GET FDB: FDBDF$ FDRC$A FD.RWM FDBK$A INBUF,512.,,,IOST FDOP$A DSKLUN,DSET DSET: .WORD 0,0 .WORD UICSIZ,UIC .WORD NAMSIZ,NAME UIC: .ASCII /[0,0]/ UICSIZ=.-UIC .EVEN NAME: .ASCII /BITMAP.SYS/ NAMSIZ=.-NAME .EVEN INBUF: .BLKB 10000 ;BUFFER FOR BITMAP. ENDBUF: ALUN: ALUN$ 1,DK,0 ; DUMMY ASSIGN LUN CMLBLK: GCMLB$ 0,FRG,USRBUF,CMLLUN USRBUF: .BLKB 82. ;BUFFER FOR COMMAND LINES. READ: QIOW$ IO.RVB,DSKLUN,32.,,IOST,, DPB: QIOW$ IO.WVB,TTYLUN,1,,,, TBUF: .BYTE TC.WID,0 ;BUFFER FOR CHARACTERISTICS BUFLEN = .-TBUF .sbttl Local Data SPSAVE: .WORD ;SAVE THE STACK POINTER FATAL: .WORD 0 ;FATAL ERROR INDICATOR. IOST: .BLKW 2 ;I/O STATUS BUFEND: .WORD 0 ; END OF BUFFER POINTER. BINS: .WORD 0,25.,0,50.,0,75.,0,100.,0,150.,0,200.,0,250. .WORD 0,300.,0,500.,0,750.,0,1000. BSIZ=11. ; NUMBER OF BINS - THE BIGGEST (< 1000. ) BIN: .BLKW *2. ;HOLDS FREQUENCY COUNT FOR EACH BIN BINSUM: .BLKW *2. ; HOLDS #BLOCKS FOR EACH BIN TOTAL: .WORD 0,0 ;TOTAL BLOCKS FOUND. WIDTH: .BLKW 1 ; Terminal width FRGNAM: .ASCII /FRG/ FRGLEN = .-FRGNAM .sbttl Message strings .EVEN STR1: .ASCIZ "%N%VSDisk Fragmentation Statistics for %2A%O:, %Y %3Z%2N" STR1S=.-STR1+6. STR1A: .ASCIZ "%VSContiguous free blocks(holes)%2N" STR1AS=.-STR1A-6 STR1B: .ASCIZ "%VSHole Range%10SFrequency%5SNumber of blocks%N" STR1BS=.-STR1B+6 STR2: .ASCIZ /%VS 0 - 25%11S%7<%T%7>%7J%10S%7<%T%7>%7J%N/ STR3: .ASCIZ /%VS 26 - 50%11S%7<%T%7>%7J%10S%7<%T%7>%7J%N/ STR4: .ASCIZ /%VS 51 - 75%11S%7<%T%7>%7J%10S%7<%T%7>%7J%N/ STR5: .ASCIZ /%VS 76 - 100%11S%7<%T%7>%7J%10S%7<%T%7>%7J%N/ STR6: .ASCIZ /%VS101 - 150%11S%7<%T%7>%7J%10S%7<%T%7>%7J%N/ STR7: .ASCIZ /%VS151 - 200%11S%7<%T%7>%7J%10S%7<%T%7>%7J%N/ STR8: .ASCIZ /%VS201 - 250%11S%7<%T%7>%7J%10S%7<%T%7>%7J%N/ STR9: .ASCIZ /%VS251 - 300%11S%7<%T%7>%7J%10S%7<%T%7>%7J%N/ STRA: .ASCIZ /%VS301 - 500%11S%7<%T%7>%7J%10S%7<%T%7>%7J%N/ STRB: .ASCIZ /%VS501 - 750%11S%7<%T%7>%7J%10S%7<%T%7>%7J%N/ STRC: .ASCIZ /%VS751 - 1000%11S%7<%T%7>%7J%10S%7<%T%7>%7J%N/ STRD: .ASCIZ /%VS > 1000%11S%7<%T%7>%7J%10S%7<%T%7>%7J%N/ STRE: .ASCIZ /%N%VSTotal Free Blocks -- %T. 512. byte blocks%N/ STRES=.-STRE .EVEN STRTAB: .WORD STR2,STR3,STR4,STR5,STR6,STR7,STR8,STR9 .WORD STRA,STRB,STRC,STRD,0 .SBTTL CODE AREA .ENABL LSB ;+ ; ** FRG - DISPLAY FRAGMENTATION DATA FOR FILES-11 DEVICES ; ; SYNTAX: ; FRG DDN: ; ; WHERE: ; DD - A LEGAL FILES-11 DEVICE NAME ; N - A LEGAL UNIT NUMBER < 8 ;- FRG: MOV SP,SPSAVE ; SAVE SP. 10$: QIOW$S #SF.GMC,#TTYLUN,#4,,#IOST,,<#TBUF,#BUFLEN> ;GET THE CHAR. CMP #-1,@#$DSW ;NO POOL NODES? BNE 12$ ;NO WSIG$S ;WAIT FOR THEM BR 10$ ;AND TRY AGAIN 12$: MOV #80.,WIDTH ; Default width to 80. TSTB IOST ; Success? BMI RESTRT ; J if not - take 80. default. CLR WIDTH ; INSURE IT'S 0 DECB TBUF+1 ; ONE LESS MOVB TBUF+1,WIDTH ; TERMINAL WIDTH RESTRT: MOV SPSAVE,SP ;RESTORE SP. GCML$ #CMLBLK ; GET A COMMAND LINE. BCC GETOK ; SKIP IF OK. CMPB CMLBLK+G.ERR,#GE.IOR ;I/O ERROR? BNE 1$ INC FATAL ;THIS ERROR IS FATAL. ERROR 1$: CMPB CMLBLK+G.ERR,#GE.OPR ;OPEN FAILURE? BNE 2$ ERROR 2$: CMPB CMLBLK+G.ERR,#GE.BIF ;SYNTAX ERROR? BNE 3$ ERROR 3$: CMPB CMLBLK+G.ERR,#GE.MDE ;MAX @ FILE DEPTH? BNE 4$ ERROR CMPB CMLBLK+G.ERR,#GE.EOF ;E-O-F? BEQ 4$ INC FATAL ;THIS ERROR IS FATAL. ERROR 4$: EXIT$S ;YES -- EXIT. FRGSYN: ERROR .DSABL LSB GETOK:: MOV CMLBLK+G.CMLD,R1 ;GET OUR COMMAND LINE LENGTH. BEQ RESTRT ; LOOP IF 0. MOV CMLBLK+G.CMLD+2,R0 ;GET ADDR OF LINE. ; 20$: CMPB (R0)+,#' ; GET TO FIRST NON-BLANK. BNE 25$ ; FOUND IT. SOB R1,20$ ; LOOP UNTIL FIRST NON-BLANK. BR FRGSYN ; LOOP EXHAUSTED -- ERROR. 25$: MOVB -1(R0),ALUN+A.LUNA DEC R1 ; IS THE LINE EXHAUSTED? BLE FRGSYN ; YES -- ERROR MOVB (R0)+,ALUN+A.LUNA+1 CLR ALUN+A.LUNU ; UNIT NUMBER. DEC R1 BLE 40$ ; SKIP IF END OF LINE. MOVB (R0)+,R2 ; GET THE DEVICE NUMBER. CMPB #' ,R2 ; IS IT A BLANK? BEQ 27$ ; YES -- END LINE. CMPB R2,#': ; LEGAL DEVICE? BEQ 27$ ; YES -- END LINE. CMPB R2,#'0 ; LEGAL DEVICE? BLO FRGSYN ; NO CMPB R2,#'7 ; LEGEL DEVICE? BHI FRGSYN ; NO SUB #'0,R2 ; CONVERT TO BINARY MOV R2,ALUN+A.LUNU ; SET UNIT NUMBER. DEC R1 ; DONE? BLE 40$ ; YES CMPB #' ,(R0) ; A BLANK? BEQ 30$ ; YES -- TERMINATE LINE. CMPB (R0)+,#': ; IS IT TRAILED WITH A :? BNE FRGSYN ; NO 27$: DEC R1 ; DONE YET? BLE 40$ ; YES 30$: CMPB #' ,(R0)+ ; IS IT BLANK AFTER THE :? BNE FRGSYN ; NO SOB R1,30$ ; LOOP OVER REST OF LINE. 40$: MOV #FDB,R0 ;POINT TO FDB JUST IN CASE. CLR F.ERR(R0) ; CLEAR ERROR. DIR$ #ALUN ; ASSIGN INPUT DEVICE BCC 50$ ; CS= ILLEGAL DEVICE MOV @#$DSW,F.ERR(R0) ;RETURN ERROR CODE JMP FRGIO ; AND DO I/O ; 50$: OPEN$R R0 BCS FRGIO ;ILLEGAL DEVICE. CLR R4 ;CLEAR R4,R5 FOR COMPUTATION CLR R5 ; R4,R5 WILL HAVE BLOCK COUNT. MOV #2,READ+Q.IOPL+10 ;POINT TO BEG OF FILE. CLR R3 ;CLEAR INDEX THRU TABLES. MOV #BSIZ+1,R4 ;GET SIZE OF TABLES. 60$: CLR BIN(R3) ;CLEAR CLR BIN+2(R3) ; VARIABLES CLR BINSUM(R3) ; FOR CLR BINSUM+2(R3) ; RE-USE. ADD #4,R3 ;GO TO NEXT ADDR SOB R4,60$ ;LOOP OVER ALL DATA STRUCTURES. CLR TOTAL ;CLEAR TOTAL COUNT CLR TOTAL+2 ; AND LOW ORDER. .SBTTL PROCESS THE BITMAP RECORD: MOV #FDB,R0 ; POINT TO FDB IN CASE OF ERROR. DIR$$ #READ ; DO I/O BCC 10$ ; SKIP IF OK MOV @#$DSW,F.ERR(R0) ;SET UP ERROR BYTE. BR FRGIO ; AND PRINT I/O ERROR. 10$: MOVB IOST,F.ERR(R0) ;ERROR? BPL 20$ ; NO ERROR -- NO NEED TO CHECK FOR E-O-F. CMPB IOST,#IE.EOF ; END-OF-FILE? BNE FRGIO ; J IF NOT -- FILE I/O ERROR. TST IOST+2 ; ANY DATA TRANSFERRED? BEQ FINISH ; J IF NOT -- REAL END-OF-FILE. 20$: MOV IOST+2,R0 ; GET LENGTH OF TRANSFER. MOV #INBUF,BUFEND ; POINT TO BUFFER END. ADD R0,BUFEND ; POINT TO NEXT FREE SLOT IN BUFFER. ASH #-9.,R0 ; SHIFT APPROPRIATELY. ADD R0,READ+Q.IOPL+10 ; INCREMENT BLOCK NUMBER. MOV #INBUF,R0 ; POINT TO RECORD. BLOCKS: MOV (R0)+,R1 ; GET 1ST 16 BLOCKS BEQ FULL ; EQ= ALL USED CMP R1,#-1 ; ALL FREE? BNE COUNT ; NE=NOT ALL FREE ADD #16.,R5 ; COUNT 16 FREE BLOCKS ADC R4 ; INC HI ORDER. BR END ; SEE IF DONE ; COUNT: MOV #16.,R2 ; BIT SHIFT COUNTER SHIFT: ASR R1 ; CHECK A BLOCK ; NOTE: ASR RATHER THAN ROR IS CORRECT ; SO THAT THE RESULT WILL BE NON-0 ; WHEN THE SIGN BIT IS SET (THIS ; IS V E R Y IMPORTENT!) BCC FULL ; CC= A USED BLOCK ADD #1,R5 ; COUNT A BLOCK FREE ADC R4 ; INC HI ORDER. BR ENDLP ; SEE IF DONE ; FULL: TST R5 ; ANY FREE BLOCKS? BNE FULL1 ; NE=YES TST R4 ; TEST HI ORDER. BEQ ENDLP ; EQ=NOPE FULL1: MOV #BSIZ,-(SP) ; NUMBER OF BINS CLR R3 ; CLEAR BIN POINTER 5$: CMP R4,BINS(R3) ; MORE THAN THIS BIN? BLT 10$ ; LE=NO BNE 7$ ; GT=YES CMP R5,BINS+2(R3) ; MORE THAN THIS BIN? BLOS 10$ ; LOS=NOPE 7$: ADD #4,R3 ; POINT TO NEXT BIN DEC (SP) ; DEC COUNT. BGT 5$ ; AND CHECK NEXT BIN. ; 10$: ADD #2,SP ; POP STACK. ADD R4,TOTAL ; ACCUMULATE TOTAL ADD R5,TOTAL+2 ; ACCUM LOW ORDER ADC TOTAL ; GET CARRY IF ANY. ADD R4,BINSUM(R3) ; ACC TOTAL FOR EACH BIN ADD R5,BINSUM+2(R3) ; ACC LOW ORDER ADC BINSUM(R3) ; AND CARRY. ADD #1,BIN+2(R3) ; INCREMENT BIN # ADC BIN(R3) ; DITTO CLR R4 ; CLEAR COUNTERS CLR R5 ; DITTO ENDLP: TST R1 ; ANY FREE BLOCKS STILL? BNE 1$ ;; NE=YES-END THE LOOP TST R5 ;;NO-BUT ARE OLD FREE BLOCKS COUNTED? BNE FULL1 ;; NE=NO, BETTER GO COUNT THEM TST R4 ;; OLD BLOCKS TO BE COUNTED? BNE FULL1 ;; YES. BR END ;; NONE LEFT IN THIS SET-GET OUT 1$: SOB R2,SHIFT ; CHECK ANOTHER BLOCK ; END: CMP R0,BUFEND ; READ ANOTHER DISK BLOCK? BHIS RECORD ; HIS=YES BR BLOCKS ; NO,LOOK AT ANOTHER 16 BITS ; FRGIO: MOV #FRGNAM,R1 MOV #FRGLEN,R2 CALL .PRFCS ;PRINT I/O ERROR CLOSE$ R0 ;CLOSE THE FILE. JMP RESTRT ;AND RESTART THE PROGRAM. ; .sbttl Output header FINISH: CLOSE$ #FDB ; CLOSE THE FILE ; Output the header message SUB #8.*2,SP ; Get work space MOV SP,R5 ; Get pointer GTIM$S R5 ; Get time and date MOV ALUN+A.LUNU,-(SP) ; Push device name MOV #ALUN,-(SP) ; Set up pointer to name ADD #A.LUNA,(SP) ; Point to it MOV WIDTH,R4 ; Get width of TI SUB #STR1S,R4 ; Subtract line length BPL 3$ ; PL - then continue MOV #2,R4 ; Default to 1 3$: ASR R4 ; Center line up MOV R4,-(SP) ; Place onto argument list MOV SP,R2 ; Set pointer SUB #132.,SP ; Get more buffer space MOV SP,R0 ; Point to it MOV #STR1,R1 ; Point to format string CALL $EDMSG ; Do it MOV SP,DPB+Q.IOPL ; Point to buffer MOV R1,DPB+Q.IOPL+2 ; Set length CLR DPB+Q.IOPL+4 ; No format control DIR$$ #DPB ; Output the header MOV SPSAVE,SP ; Restore stack ; Output second line of header MOV WIDTH,-(SP) ; Get terminal width SUB #STR1AS,(SP) ; Minus the string length ASR (SP) ; Divide by two MOV SP,R2 ; Save pointer SUB #132.,SP ; Get buffer space MOV SP,R0 ; Point to it MOV #STR1A,R1 ; Point to format string CALL $EDMSG ; Format the message MOV SP,DPB+Q.IOPL ; Point to buffer MOV R1,DPB+Q.IOPL+2 ; Set length CLR DPB+Q.IOPL+4 ; No format control DIR$$ #DPB ; Output the header ; Output the third line of the header MOV WIDTH,R4 ; Get width SUB #STR1BS,R4 ; Minus string length ASR R4 ; And center it up MOV SP,R0 ; Get pointer MOV #STR1B,R1 ; Point to format string MOV R4,-(SP) ; Set up argument list MOV SP,R2 ; And point to it CALL $EDMSG ; Format the message SUB R1,R0 ; Point to start of string MOV R0,DPB+Q.IOPL ; Point to buffer MOV R1,DPB+Q.IOPL+2 ; Set length CLR DPB+Q.IOPL+4 ; No format control DIR$$ #DPB ; Output the header MOV SPSAVE,SP ; Restore stack .sbttl Output statistics SUB #132.,SP ; Get workspace MOV SP,R0 ; Save pointer to it MOV R0,DPB+Q.IOPL ; Point to start of string CLR DPB+Q.IOPL+4 ; Set no carriage control CLR R3 ; Clear counter SUB #6,SP ; Create argument list MOV R4,(SP) ; Set up centering 10$: CMP R3,#BSIZ+1 ; At the end yet ? BEQ 40$ ; EQ - yes, output summary ASL R3 ; Convert to byte offset MOV STRTAB(R3),R1 ; Get pointer to format string ASL R3 ; (DOUBLE WORD) MOV #BIN,2(SP) ; Set up argument list ADD R3,2(SP) ; ... MOV #BINSUM,4(SP) ; ... ADD R3,4(SP) ; ... MOV SP,R2 ; Point to argument list CALL $EDMSG ; Format the message SUB R1,R0 ; Point to start of string MOV R1,DPB+Q.IOPL+2 ; Set string length DIR$$ #DPB ; Output the string ASR R3 ; Back to word ASR R3 INC R3 ; Bump up count BR 10$ ; And loop 40$: MOV WIDTH,R4 ; Get the width SUB #STRES,R4 ; Minus its length ASR R4 ; Center it up MOV R4,(SP) ; Set up argument list MOV #TOTAL,2(SP) ; ... MOV #STRE,R1 ; Point to format string MOV SP,R2 ; Point to argument list CALL $EDMSG ; Format the message MOV R1,DPB+Q.IOPL+2 ; Set string length DIR$$ #DPB ; Output the string JMP RESTRT ; AND RESTART PGM. .sbttl $ERROR - Error message output $ERROR: MOV (SP),R0 ; GET POINTER MOV (R0)+,DPB+Q.IOPL+2 ; SET UP READ DPB MOV R0,DPB+Q.IOPL ;AND THE ADDRESS OF WRITE. MOV #40,DPB+Q.IOPL+4 ; force carriage return DIR$$ #DPB ;DO THE I/O CLOSE$ #FDB ;CLOSE FILE. TST FATAL ;IS THE ERROR FATAL? BNE 10$ ;YES JMP RESTRT ;NO -- TRY AGAIN. 10$: EXIT$S ; AND LEAVE. .END FRG