1 EXTEND 2 ! RD1TRC == Trace RDS1.1 Directory Structure Overhead & ! & ! This program displays the disk accesses required to find a file & ! in a directory or to get to the end of the directory. If the file & ! exists, the directory accesses required to sequentially read the & ! file and the map of starting pack clusters for each file cluster are & ! also displayed. Minimizing the number of directory accesses & ! to open and access files will improve overall system performance. & ! & ! Author: & ! Unknown. Based on a program written circa 1978 to support the RDS & ! level 0 directory structure. Modified by Mike Mayfield to support & ! RDS level 1.0, 1.1 and 1.2 and allow generic directory searching. & ! & ! Edit History: & ! 00 xx-XXX-78 ??? Original version & ! 01 10-Jan-85 MEM Modified to support RDS1. Removed requirement & ! to specify device, filename, and filetype. & ! Conformed to programming standard. & ! 02 15-May-86 MEM Update for V9.x and publication. & ! 03 01-Oct-87 MEM Confirm before overwriting output file. & ! & ! RSTS Version: & ! V8.0-V9.4 & ! & ! Variable Usage: & ! BLKBUF$ Current block in cluster & ! BLOCK.NUM% Block number within UFD & ! CLUST.NUM% Cluster number within UFD & ! CUR.BLK% Block number of current block & ! CUR.ENT% Entry number of current entry & ! DEVNAM$ Disk name & ! ENT.NUM% Entry number within UFD sector & ! ENT.TYPE$ Current entry type & ! ENTRY%(0..16) Working values for UFD entry & ! FILNAM.1% File name. First 3 characters (RAD50) & ! FILNAM.2% File name. Second 3 characters (RAD50) & ! FILTYP% File type. (RAD50) & ! FLG.MASK% Mask for all but bits <0:4> (flag bits) & ! OUT.CHN% Channel number for report output I/O & ! PROG% Programmer number for file spec & ! PROJ% Project number for file spec & ! RE.CNT% Running total number of Retrieval Entry seeks & ! RE.PIC$ PRINT USING template for RE seek notification & ! SECT.NUM% Sector number within UFD cluster & ! SEEK.CNT% Running total number of directory seeks & ! SEEK.PIC$ PRINT USING template for seek notification & ! SYS.DAT$ Filename string scan values for file spec & ! UFD.CHN% Channel number for UFD I/O & ! UFD.ENTRY%() Current directory entry & ! UFD.MAP%() MFD map of current account & 100 DIM UFD.MAP%(7%), UFD.ENTRY%(7%), ENTRY%(16%) & \ UFD.CHN%=1% & \ OUT.CHN%=2% & \ FLG.MASK%=32767%+32753% & \ SEEK.PIC$="\ \ seek to Cluster ###### Sector ## Entry ##" & \ RE.PIC$="###### " & \ PRINT & \ PRINT "RD1TRC V1.1 == File Directory Trace Utility (RDS1.x)" & \ ON ERROR GOTO 32000 & ! Define I/O channels. FLG.MASK% is a constant of 177760(8) used to & ! mask off flag bits from link words. Define PRINT USING pictures. & ! Announce ourselves and trap ^Z on keyboard. & 110 PRINT "Output to "; & \ INPUT LINE Z$ & \ Z$=CVT$$(Z$,39%) & \ Z$="KB:RD1TRC.TXT" IF Z$="" & \ GOTO 115 IF LEFT(Z$,2%)="KB" & \ OPEN Z$ FOR INPUT AS FILE OUT.CHN% & \ PRINT "%File exists. Delete it "; & \ INPUT Z1$ & \ Z1$=CVT$$(Z1$,-1%) & \ GOTO 110 IF Z1$<>"YES" & ! Open our output file. If the file already exists, confirm that it & ! can be replaced. & 115 OPEN Z$ FOR OUTPUT AS FILE OUT.CHN% & ! Create the output file. & 120 PRINT & \ PRINT "File to trace "; & \ INPUT LINE Z$ & \ Z$=CVT$$(Z$,39%) & \ Z$="SY0:"+Z$ IF INSTR(1%,Z$,":")=0% & \ SYS.DAT$=SYS(CHR$(6%)+CHR$(-23%)+Z$) & \ FILNAM.1%=SWAP%(CVT$%(RIGHT(SYS.DAT$,7%))) & \ FILNAM.2%=SWAP%(CVT$%(RIGHT(SYS.DAT$,9%))) & \ FILTYP%=SWAP%(CVT$%(RIGHT(SYS.DAT$,11%))) & \ FILNAM.1%,FILNAM.2%=0% IF FILNAM.1%=-17947% & \ FILTYP%=0% IF FILTYP%=-17947% & \ Z%=SWAP%(CVT$%(RIGHT(SYS.DAT$,5%))) & \ PROJ%=SWAP%(Z%) AND 255% & \ PROG%=Z% AND 255% & \ IF (PROJ% OR PROG%)=0% THEN & PRINT "?You must enter an account number." & \ GOTO 120 130 IF FILNAM.1%=0% AND FILTYP%<>0% THEN & PRINT "?Invalid file specification: Missing filename." & \ GOTO 120 140 IF FILNAM.1%<>0% AND FILTYP%=0% THEN & PRINT "?Invalid file specification: Missing filetype." & \ GOTO 120 150 OPEN MID(SYS.DAT$,23%,2%)+CHR$(ASCII(RIGHT(SYS.DAT$,25%))+48%)+":["+ & NUM1$(PROJ%)+","+NUM1$(PROG%)+"]" AS FILE UFD.CHN% & \ FIELD #UFD.CHN%, 496% AS Z$, 16% AS Z$ & \ GET #UFD.CHN%, RECORD 1% & \ CHANGE Z$ TO ENTRY% & \ UFD.MAP%(Z%/2%)=ENTRY%(Z%+1%) OR SWAP%(ENTRY%(Z%+2%)) & FOR Z%=0% TO 15% STEP 2% & \ CUR.BLK%, CUR.ENT%=-1% & \ SEEK.CNT%, RE.CNT%=0% & ! Get the trace file specification. Convert logicals in filename. & ! Wildcard filenames default to same as not specifying a filename. & ! Check for required specification arguments. Build RAD50 filename, & ! filetype, and PPN. Open the specified directory. Get the first & ! block of the directory and map the cluster map. Ensure that we & ! do physical I/O on next access. & 200 ENT.TYPE$="UFD" & \ PRINT #OUT.CHN% & \ Z%=FNC.GET.ENTRY%(0%) & ! Set our access type as "UFD". Get the label entry. & 210 Z%=FNC.GET.ENTRY%(UFD.ENTRY%(0%)) & \ IF UFD.ENTRY%(1%)<>FILNAM.1% OR & UFD.ENTRY%(2%)<>FILNAM.2% OR & UFD.ENTRY%(3%)<>FILTYP% THEN & IF (UFD.ENTRY%(0%) AND FLG.MASK%) THEN & GOTO 210 & ELSE & Z$="?File not found" & \ Z$="End of directory reached" IF FILNAM.1%=0% & \ PRINT #OUT.CHN% & \ PRINT #OUT.CHN%, Z$; " after"; SEEK.CNT%; "seek"; & \ PRINT #OUT.CHN%, "s"; IF SEEK.CNT%<>1% & \ PRINT #OUT.CHN%, "." & \ CLOSE #UFD.CHN% & \ GOTO 120 & ! Follow the link to the next entry. If this is not the file we're & ! looking for, try the next entry if there are more, else we failed & ! or reached the end of the directory. & 300 RE.LINK%=UFD.ENTRY%(7%) & \ Z%=FNC.GET.ENTRY%(UFD.ENTRY%(6%)) & \ Z%=FNC.GET.ENTRY%(UFD.ENTRY%(0%)) WHILE UFD.ENTRY%(0%) AND FLG.MASK% & \ UFD.ENTRY%(0%)=RE.LINK% & \ PRINT #OUT.CHN%, NUM1$(SEEK.CNT%); " seek"; & \ PRINT #OUT.CHN%, "s"; IF SEEK.CNT%<>1% & \ PRINT #OUT.CHN%, " to find file, accounting entry, and attributes." & \ PRINT #OUT.CHN% & \ PRINT #OUT.CHN%, "Retrieval entry listing:" & \ ENT.TYPE$="RE" & ! Save the link to the first retrieval entry (RE). Map the accounting & ! entry (AE). Get the clustersize from the AE. Prepare to map the & ! first retrieval entry. Print our banner. & 310 IF (UFD.ENTRY%(0%) AND FLG.MASK%) THEN & Z%=FNC.GET.ENTRY%(UFD.ENTRY%(0%)) & \ RE.CNT%=RE.CNT%+1% & \ PRINT #OUT.CHN%, USING "##: ", ENT.NUM%/16%; & \ PRINT #OUT.CHN%, USING RE.PIC$, FNC.UINT(UFD.ENTRY%(I%)); & IF UFD.ENTRY%(I%) FOR I%=1% TO 7% & \ PRINT #OUT.CHN% & \ GOTO 310 320 !ELSE & PRINT #OUT.CHN%, NUM1$(SEEK.CNT%); " total seek"; & \ PRINT #OUT.CHN%, "s"; IF SEEK.CNT%<>1% & \ PRINT #OUT.CHN%, " with"; RE.CNT%; "retrieval entr"; & \ IF RE.CNT%=1% THEN & PRINT #OUT.CHN%, "y." & ELSE & PRINT #OUT.CHN%, "ies." 330 CLOSE UFD.CHN% & \ GOTO 120 & ! Follow link to next retrieval entry. Print entry number and all & ! values in that entry. Repeat for all retrieval entries then quit. & 10000 ! FNC.GET.ENTRY% == Get Entry From a UFD Given a Link & ! & ! Loads the entry information for a directory UFD entry given a & ! directory link word. & ! & ! Input: & ! LINK% Link word to follow & ! UFD.MAP%(0..7) UFD cluster map for this UFD & ! SEEK.CNT% Count of seeks performed & ! CUR.BLK% Current block number in UFD.CHN% buffer & ! UFD.CHN% Channel number for UFD I/O & ! & ! Output: & ! UFD.ENTRY%(0..7) Contents of UFD pointed to by link word & ! CLUST.NUM% Current cluster number within UFD & ! SECT.NUM% Current sector number within cluster & ! ENT.NUM% Current entry number within sector & ! BLOCK.NUM% Current block within UFD & ! CUR.ENT% Current entry number & ! CUR.BLK% Current block number in UFD.CHN% buffer & ! & ! Variables Modified: & ! ENTRY%() Working array for UFD entry & & DEF* FNC.GET.ENTRY%(LINK%) & \ SECT.NUM%=(SWAP%(LINK%) AND 240%)/16% & \ ENT.NUM%=LINK% AND 496% & \ CLUST.NUM%=(SWAP%(LINK%) AND 14%)/2% & \ BLOCK.NUM%=CLUST.NUM%*UFD.MAP%(0%)+SECT.NUM%+1% & \ IF BLOCK.NUM%<>CUR.BLK% THEN & GET #UFD.CHN%, RECORD BLOCK.NUM% & \ CUR.BLK%=BLOCK.NUM% & \ CUR.ENT%=-1% & \ SEEK.CNT%=SEEK.CNT%+1% & \ PRINT #OUT.CHN%, USING SEEK.PIC$, ENT.TYPE$, & FNC.UINT(UFD.MAP%(CLUST.NUM%+1%)), SECT.NUM%, ENT.NUM%/16% 10010 IF ENT.NUM%<>CUR.ENT% THEN & FIELD #UFD.CHN%, ENT.NUM% AS Z$, 16% AS Z$ & \ CHANGE Z$ TO ENTRY% & \ UFD.ENTRY%(Z%/2%)=ENTRY%(Z%+1%) OR SWAP%(ENTRY%(Z%+2%)) & FOR Z%=0% TO 15% STEP 2% & \ CUR.ENT%=ENT.NUM% 10020 FNEND & ! Mask off sector, entry, and cluster numbers. Calculate block & ! number within UFD for specified block. If the block number changed & ! get the new block, ensure that we remap the entry and print our log & ! message. If the entry number changed, map the new entry. & 10100 ! FNC.UINT == Convert unsigned integer to floating point & ! & ! Converts an unsigned 16-bit integer to its equivalent positive & ! floating point value. & ! & ! Input: & ! INT.VAL% 16-bit value to convert & ! & ! Output: & ! FNC.UINT Floating point value equivalent to INT.VAL% & & DEF* FNC.UINT(INT.VAL%)=32768.+(INT.VAL% EQV 32767%) & 32000 IF ERR=11% AND (ERL=110% OR ERL=120) THEN & RESUME 32767 & ! ^Z on keyboard input. Exit gracefully. & 32010 IF ERR=2% AND ERL=150% THEN & PRINT "?Can't find account: "; Z$ & \ RESUME 120 & ! Nonexistant account entered. & 32020 IF ERR=5% AND ERL=110% THEN & RESUME 115 & ! Output file does not already exist. & 32099 ON ERROR GOTO 0 & ! All other errors are fatal. & 32767 END