.TITLE DISK_FRAGMENTATION_STATISTICS .SUBTITLE DECLARE CONSTANTS AND MACROS .ENABLE DEBUG ; DISK FRAGMENTATION DISPLAY PROGRAM ; MICHAEL N. LEVINE ; CODE 3514 ; NAVAL WEAPONS CENTER ; CHINA LAKE ; CA ; (619)939-2318 AVN 437-2318 $DVIDEF $DCDEF $IODEF ; MACRO TO CONVERT A LONG WORD BINARY NUMBER TO AN UNSIGNED INTEGER STRING .MACRO GENSTR SIZE,LOC,VAR MOVL SIZE,DESCRIPTER MOVAL LOC,DESCRIPTER+4 $FAO_S CTRSTR,,DESCRIPTER,VAR .ENDM .MACRO GENPCT VAR,LOC,DIVISOR,MULT,?AAA,?BBB,?CCC CVTLD VAR,TEMP MULD2 TEN_K,TEMP .IF NB MULT CVTLD MULT,TEMP_2 MULD2 TEMP_2,TEMP .ENDC CVTLD DIVISOR,TEMP_2 DIVD2 TEMP_2,TEMP ADDD2 HALF,TEMP CVTDL TEMP,TEMP MOVL #5,DESCRIPTER MOVAL LOC,DESCRIPTER+4 $FAO_S CTRSTR_2,,DESCRIPTER,TEMP MOVC3 #2,LOC+3,LOC+4 MOVB #^A/./,LOC+3 CMPB #^A/ /,LOC+5 BNEQ AAA MOVB #^A/0/,LOC+5 AAA: CMPB #^A/ /,LOC+4 BNEQ BBB MOVB #^A/0/,LOC+4 BBB: CMPB #^A/ /,LOC+2 BNEQ CCC MOVB #^A/0/,LOC+2 CCC: .ENDM ; MACRO TO PRINT OUT A STRING .MACRO PUTSTR SIZE,LOC MOVL SIZE,DESCRIPTER MOVAL LOC,DESCRIPTER+4 CALLG OUTPUT_ARG,G^LIB$PUT_OUTPUT .ENDM .PAGE .SUBTITLE DATA STORAGE .PSECT PURE_DATA,RD,NOWRT,SHR,NOEXE,LONG,GBL,CON ; ARGUMENT LIST FOR ERROR MESSAGE THAT SELECTED DEVICE IS NOT A DISK NOT_DISK_ARG: .LONG 1 .ADDRESS NOT_DISK_STRING NOT_DISK_STRING: .ASCID /Specified device is not a disk/ ; ARGUMENT LIST FOR LIB$GET_FOREIGN GET_ARG: .LONG 4 .ADDRESS DEVICE_NAME .ADDRESS PROMPT .ADDRESS LENGTH .ADDRESS FORCE PROMPT: .ASCID /Device ? / ; ITEM LIST FOR THE $GETDVI CALL ITEM_LIST: .WORD 4,DVI$_CLUSTER .ADDRESS CLUSTER_SIZE .LONG 0 .WORD 4,DVI$_DEVCLASS .ADDRESS CLASS .LONG 0 .WORD 4,DVI$_MAXBLOCK .ADDRESS MAXBLOCK .LONG 0 .WORD 4,DVI$_FREEBLOCKS .ADDRESS FREE .LONG 0 .LONG 0 ; LIST OF BOUNDRY VALUES FOR BUCKETS. THE FIRST MUST BE "1" AND THE ; LAST "-1", TO CHANGE THE BUCKET BOUNDRY VALUES AND NUMBER OF BUCKETS, ; JUST CHANGE THE LIST BELOW. THE PROGRAM IS WRITTEN TO TAKE CARE ; OF THE DETAILS.-- THE LIST MUST BE MONOTONICALLY INCREASING. BUCKET_SIZE_LIST: .LONG 1,5,10,25,50,75,100,250,500,750,1000,2500,5000,7500 .LONG 10000,25000,50000,75000,100000,250000,500000,750000 .LONG 1000000,2500000,5000000,7500000,10000000 .LONG -1 NUMBER_OF_BUCKETS = <<<.-BUCKET_SIZE_LIST>/4>-1> ; MAP THE BITS IN EACH 32 BIT WORD BIT_MAP:.LONG ^X1,^X2,^X4,^X8,^X10,^X20,^X40,^X80,^X100,^X200,^X400,^X800 .LONG ^X1000,^X2000,^X4000,^X8000,^X10000,^X20000,^X40000,^X80000 .LONG ^X100000,^X200000,^X400000,^X800000 .LONG ^X1000000,^X2000000,^X4000000,^X8000000 .LONG ^X10000000,^X20000000,^X40000000,^X80000000 ; STATISTICS CONSTANTS TEN_K: .DOUBLE 10000.0 HALF: .DOUBLE 0.5 .PAGE .PSECT IMPURE_DATA,RD,WRT,NOSHR,NOEXE,LONG,GBL,CON ; ARGUMENT LIST FOR LIB$PUT_OUTPUT OUTPUT_ARG: .LONG 1,DESCRIPTER ; FORMAT LIST FOR $FAO_S CTRSTR: .ASCID /!10UL/ CTRSTR_2:.ASCID /!5UL/ ; GENERIC STRING DESCRIPTER DESCRIPTER: .LONG 0,0 ; ASSORTED TEXT LINES AWAITING INSERTION OF INTEGER STRINGS FOR OUTPUT LINE_1: .ASCII /Disk size in blocks / LINE_1_DATA: .ASCII / / LINE_2: .ASCII /Number of free blocks / LINE_2_DATA: .ASCII / / LINE_3: .ASCII /Cluster size in blocks / LINE_3_DATA: .ASCII / / LINE_4: .ASCII /Largest free space in clusters / LINE_4_DATA: .ASCII / / LINE_5: .ASCII / / LINE_6: .ASCII /Free area size in clusters Count of Total / .ASCII / % Disk % Free/ LINE_6_A:.ASCII / Fragments Clusters/ .ASCII / Space Space / LINE_7: .ASCII / -/ LINE_7_B:.ASCII / / LINE_7_A: .ASCII / (/ LINE_7_C:.ASCII ? /? LINE_7_D:.ASCII ? %/? LINE_7_E:.ASCII / %)/ LINE_8: .ASCII / Total / LINE_8_A:.ASCII / (/ LINE_8_B:.ASCII ? /? LINE_8_C:.ASCII ? %/? LINE_8_D:.ASCII / %)/ ; BUCKETS FOR COUNT OF NUMBER OF FRAGMENTS OF IN GIVEN SIZE RANGE BUCKET_BRIGADE: .BLKL NUMBER_OF_BUCKETS ; TOTAL NUMBER OF CLUSTERS IN A GIVEN BUCKET AND TOTAL FOUND (LAST SLOT) TOTALS: .BLKL NUMBER_OF_BUCKETS+1 ; TOTAL NUMBER OF FRAGMENTS FOUND TOTAL_FRAGS: .LONG 0 ; TEMPORARY STORAGE TEMP: .LONG 0,0 TEMP_2: .LONG 0,0 ; LAST BLOCK NUMBER IN SYS$DISK:[000000]BITMAP.SYS READ IN BLOCK_NUMBER: .LONG 0 ; BIT MAP BLOCK BLOCK: .BLKB 512 ; LONGEST FRAGMENT FOUND LONGEST:.LONG 0 ; WHAT DOES THE SYSTEM SAY THE NUMBER OF FREE BLOCKS IS FREE: .LONG 0 ; DISK SIZE IN BLOCKS MAXBLOCK: .LONG 0 ; WHAT TYPE OF DEVICE IS THIS (SHOULD BE A DISK) CLASS: .LONG 0 ; GET DISK CLUSTER SIZE CLUSTER_SIZE: .LONG 0 ; FORCE THE PROMPT IF NO DEVICE SPECIFIED ON COMMAND LINE FORCE: .LONG 0 ; LENGTH OF INPUT STRING LENGTH: .LONG 0 ; SPECIFIED DEVICE STRING STORED HERE DEVICE_NAME: .ASCID / / ; IO STATUS BLOCK IOSB: .LONG 0,0 ; THIS IS THE FILE WANTED FOR THE BIT MAP DEFAULT_NAME: .ASCII /SYS$DISK:[000000]BITMAP.SYS/ DFLT_NAM_SIZ=.-DEFAULT_NAME ; DEFINE THE FAB AND RAB FORTHE BIT MAP FILE .ALIGN LONG FAB: $FAB ALQ=0,- DEQ=0,- DNA=DEFAULT_NAME,DNS=DFLT_NAM_SIZ,- FAC=,- FNA=,FNS=0,- FOP=,SHR= .ALIGN LONG RAB: $RAB BKT=1,- FAB=FAB,- ROP=,- UBF=BLOCK,USZ=512 .PAGE .SUBTITLE CODE .SUBTITLE INITIALIZATION .PSECT CODE,RD,NOWRT,SHR,EXE,LONG,GBL,CON .ENTRY START,0 ; GET THE DEVICE NAME CALLG GET_ARG,G^LIB$GET_FOREIGN CMPW #SS$_NORMAL,R0 BEQL 1$ $EXIT_S R0 1$: MOVL LENGTH,DEVICE_NAME ; GET INFORMATION ON SPECIFIED DEVICE $GETDVI_S #1,,DEVICE_NAME,ITEM_LIST,IOSB CMPW #SS$_NORMAL,R0 BEQL 2$ $EXIT_S R0 2$: $WAITFR_S #1 CMPW #SS$_NORMAL,IOSB BEQL 3$ CVTWL IOSB,R0 $EXIT_S R0 ; MUST BE A DISK 3$: CMPL #DC$_DISK,CLASS BEQL 103$ CALLG NOT_DISK_ARG,G^LIB$PUT_OUTPUT $EXIT_S ; OPEN THE BITMAP FILE 103$: MOVB LENGTH,FAB+FAB$B_FNS $OPEN FAB=FAB BLBS R0,4$ $EXIT_S R0 4$: $CONNECT RAB=RAB BLBS R0,5$ $EXIT_S R0 ; INIT ALL INTERNAL VARIBALES AND ARRAYS 5$: CLRL LONGEST MOVC5 #0,LONGEST,#0,#,BUCKET_BRIGADE MOVC5 #0,LONGEST,#0,#<*4>,TOTALS CLRL TOTAL_FRAGS ; BIT MAP STARTS IN LBN 2 MOVL #2,BLOCK_NUMBER MOVL #2,RAB+RAB$L_BKT ; READ IN FIRST BLOCK OF BITMAP AN INIT ALL REGESTERS $READ RAB=RAB BLBS R0,6$ $EXIT_S R0 6$: CLRL R11 MOVL #32,R8 CLRL R6 MOVL BLOCK(R11),R9 ADDL2 #4,R11 CLRL R10 .PAGE .SUBTITLE ACCUMULATE DATA LOOP: BITL BIT_MAP[R6],R9 BEQL NOT_SET INCL R10 BRW END_LOOP NOT_SET: TSTL R10 BEQL END_LOOP CLRL R7 ;FIND BUCKET TO PUT IT IN BUCKET_LOOP: CMPL [R7],R10 BGTRU 1$ INCL R7 BRW BUCKET_LOOP 1$: INCL BUCKET_BRIGADE[R7] INCL TOTAL_FRAGS ADDL2 R10,TOTALS[R7] ADDL2 R10,TOTALS+ CMPL R10,LONGEST BLEQ 2$ MOVL R10,LONGEST 2$: CLRL R10 END_LOOP: INCL R6 SOBGTR R8,LOOP CMPL #512,R11 BGTR 1$ INCL BLOCK_NUMBER MOVL BLOCK_NUMBER,RAB+RAB$L_BKT $READ RAB=RAB BLBS R0,2$ CMPL #RMS$_EOF,R0 BEQL BIT_MAP_IN $EXIT_S R0 2$: CLRL R11 1$: MOVL BLOCK(R11),R9 ADDL2 #4,R11 CLRL R6 MOVL #32,R8 BRW LOOP .PAGE .SUBTITLE CLEAN UP AND GEN OUTPUT BIT_MAP_IN: TSTL R10 BEQL CLOSE_DOWN_FILE CLRL R7 ;FIND BUCKET TO PUT IT IN BUCKET_LOOP_2: CMPL [R7],R10 BGTRU 1$ INCL R7 BRW BUCKET_LOOP_2 1$: INCL BUCKET_BRIGADE[R7] INCL TOTAL_FRAGS ADDL2 R10,TOTALS[R7] ADDL2 R10,TOTALS+ CMPL R10,LONGEST BLEQ CLOSE_DOWN_FILE MOVL R10,LONGEST CLOSE_DOWN_FILE: $DISCONNECT RAB=RAB $CLOSE FAB=FAB ; FORMAT RESULTS FOR OUTPUT GENSTR #14,LINE_1_DATA,MAXBLOCK GENSTR #14,LINE_2_DATA,FREE GENSTR #14,LINE_3_DATA,CLUSTER_SIZE GENSTR #14,LINE_4_DATA,LONGEST PUTSTR #46,LINE_1 PUTSTR #46,LINE_2 PUTSTR #46,LINE_3 PUTSTR #46,LINE_4 PUTSTR #1,LINE_5 PUTSTR #77,LINE_6 PUTSTR #77,LINE_6_A MOVL #NUMBER_OF_BUCKETS,R11 CLRL R10 1$: TSTL BUCKET_BRIGADE[R10] BNEQ 4$ BRW 3$ 4$: GENSTR #14,LINE_7,BUCKET_SIZE_LIST[R10] SUBL3 #1,[R10],R0 GENSTR #14,LINE_7_B,R0 GENSTR #14,LINE_7_A,BUCKET_BRIGADE[R10] GENSTR #14,LINE_7_C,TOTALS[R10] GENPCT TOTALS[R10],LINE_7_D,MAXBLOCK,CLUSTER_SIZE GENPCT TOTALS[R10],LINE_7_E,> PUTSTR #78,LINE_7 3$: INCL R10 DECL R11 BLEQ 2$ BRW 1$ 2$: GENSTR #14,LINE_8_A,TOTAL_FRAGS GENSTR #14,LINE_8_B,TOTALS[R10] GENPCT TOTALS[R10],LINE_8_C,MAXBLOCK,CLUSTER_SIZE GENPCT TOTALS[R10],LINE_8_D,TOTALS[R10] PUTSTR #78,LINE_8 $EXIT_S .END START