! FILE 'SYS_FSYSTU581S' - MODIFIED TO RUN TU58 ONLY !!!!!!! !****************************** !* FILE SYSTEM HANDLER * !* FSYS1S/FSYS1Y * !* DATE: 28.JUN.79 * !****************************** !*W.S.C. 25TH AUGUST 1976 !*B.G. 27.MAR.78 !*THIS HANDLER IS THE FILE SYSTEM UTILITY TO REPLACE THE !*EXISTING ONE IN DEIMOS TO PERMIT A FILE SYSTEM TO BE !*CREATED ON THE AMPEX 9500 DISC AS WELL AS THE RK05'S. !*IT IS A CONCEPTUAL COPY OF THE RK05 FILE SYSTEM HANDLER !*EXCEPT THAT A BUFFER POOL IS USED FOR BLOCK DESCRIPTORS !*AND DIRECTORY BLOCKS. !*THE CODE IS SHARED BY 3 SYSTEM SLOTS,4 FOR THE RK05'S, !*AND 9,15 FOR THE AMPEX DISC.THE AMPEX DISC IS LOGICALLY !*DIVIDED INTO TWO,UNITS 2&3. !* A FURTHER DISC IS CATERED FOR IN SLOT 28 !*THE CLOCK IS USED TO WRITE BLOCKS BACK EVERY 10SECS !*(BLOCK DESCRIPTOR BLOCKS).DIRECTORY BLOCKS ARE ALWAYS !*WRITTEN BACK AS SOON AS POSSIBLE AFTER A CHANGE. !*TUNEABLE PARAMETERS !* NBUF=NUMBER OF BUFFERS IN POOL-1(MUST BE>0) !* SECS::LENGTH OF TIME BETWEEN INSPECTING BUFFER !* POOL FOR WRITING BACK TO DISC. !*THE FOLLOWING FACILITIES ARE OFFERED !* EXAMINE A FILE !* GET NEXT BLOCK OF A FILE !* DESTROY A FILE !* CREATE A FILE !* APPEND A BLOCK TO A FILE !* RENAME A FILE !* RENAME A TEMPORARY FILE !*STACK=300 STREAMS=0 !********************************************************** !********************************************************** CONTROL K'101010'; !SYSTEM+FAST ROUTINE ENTRY SYSTEMROUTINESPEC LINKIN(INTEGER SER) SYSTEMROUTINESPEC ALARM(INTEGER TICKS) SYSTEMINTEGERFNSPEC GETID PERMROUTINESPEC SVC(INTEGER EP, R0, R1) PERMINTEGERMAPSPEC INTEGER(INTEGER N) PERMBYTEINTEGERMAPSPEC BYTEINTEGER(INTEGER N) PERMINTEGERFNSPEC ADDR(BYTEINTEGERNAME N) PERMINTEGERFNSPEC ACC RECORDFORMAT DD(INTEGER X) PERMRECORD (DD) MAPSPEC RECORD(INTEGER X) CONSTRECORD (DD) NAME NULL = 0 BEGIN !********************************************************* !************* DATA AREAS &DECLARATIONS ********** !********************************************************* !*SYSTEM SLOTS/DISC CONSTINTEGER MAX DRIVES = 4 CONSTBYTEINTEGERARRAY SERV(0:MAX DRIVES) = 3, 3, 8, 14, 28 !*DIRECTORY BLOCK AREAS/DISC CONSTINTEGERARRAY DIRBLK(0:MAX DRIVES) = K'220', 0, K'100', K'100', K'220' !*BLOCK DESCRIPTOR BASE/DISC CONSTBYTEINTEGERARRAY BLKLST(0:MAX DRIVES) = K'100', 0, K'103', K'103', K'100' !*FREE BLOCK START/DISC CONSTINTEGERARRAY FBLOCK(0:MAX DRIVES) = K'400', 0, K'110', K'110', K'400' OWNINTEGERARRAY FIRST FREE(0:MAX DRIVES) = K'400', 0, K'110', K'110', K'400' ! INITIALLY IS IDENTICAL TO ! FBLOCK !*TOP OF DISC CONSTINTEGERARRAY LASTBL(0:MAX DRIVES) = 9199, 0, 511, 511, 9199 !*REQUEST TYPES CONSTINTEGER EXAMINE = 0 CONSTINTEGER GET NEXT = 1 CONSTINTEGER DESTROY = 2 CONSTINTEGER CREATE = 3 CONSTINTEGER APPEND = 4 CONSTINTEGER RENAME = 5 CONSTINTEGER RENAME TEMP = 6 CONSTINTEGER RENAME FSYS = 7 CONSTINTEGER DIR BLK NO = 8 !*SYSTEM CONSTANTS CONSTINTEGER DREAD = 0, DWRITE = 1 !MODES CONSTINTEGER CLOCK INT = 0 CONSTINTEGER MY SEG = 4, MSA = K'100000' !*SYSTEM SLOTS CONSTINTEGER RKSER = 4 CONSTINTEGER AMP1SER = 9 CONSTINTEGER AMP2SER = 15 CONSTINTEGER RKBSER = 29 SWITCH REQUEST(0:DIR BLK NO) INTEGER ID, SEG, I, BK, NO, NOSAVE, PR, EXIT, SEG2 OWNINTEGER DRIVE, FNO !*MESSAGE FORMATS RECORDFORMAT PF(BYTEINTEGER SERVICE, REPLY, INTEGER A1, A2, A3) RECORDFORMAT P2F(BYTEINTEGER SERVICE, REPLY, INTEGER A1, C INTEGERNAME A2, INTEGER A3) RECORD (PF)P, PX !*DISC BUFFER POOL CONSTINTEGER SECS = 60; !BUFFER WRITE BACK TIME CONSTINTEGER NBUF = 2; !NUMBER OF BUFFERS-1(MUST BE>0) RECORDFORMAT XF(INTEGER X) RECORDFORMAT BF(INTEGER DRIVE, BLOCK, WRM, RECORD (XF) C ARRAY BLK(0:255)) !*WRM IS A WRITE MARKER TO SAY THAT BLOCK HAS BEEN !*ALTERED AND MUST BE WRITTEN BACK TO DISC. OWNRECORD (BF) ARRAY B(0:NBUF) OWNINTEGER BLAST = 0; !LAST BUFFER USED IN POOL OWNRECORD (BF) NAME BX; !POINTS TO CURRENT BUFFER RECORD !*FORMATS FOR BLOCK DESCRIPTORS AND DIRECTORY BLOCKS RECORDFORMAT BLKF(INTEGER PR, NEXT) !BLOCK DESCRIPTOR RECORDFORMAT N1F(BYTEINTEGERARRAY NAME(0:5)) RECORDFORMAT N2F(INTEGER A, B, C) ! TWO FORMS OF THE FILE NAME RECORDFORMAT INFF(BYTEINTEGER UNIT, FSYS, RECORD (N1F)N) ! FILE DESCRIPTOR RECORDFORMAT INF2F(BYTEINTEGER UNIT, FSYS, RECORD (N2F)N) RECORDFORMAT FILEF(RECORD (N1F)N, INTEGER FIRST, PR) !DIRECTORY ENTRY RECORDFORMAT FILE2F(RECORD (N2F)N, INTEGER FIRST, PR) OWNRECORD (BLKF) ARRAYNAME BLKA RECORD (FILEF) ARRAYNAME FA OWNRECORD (FILEF) NAME F RECORD (BLKF) NAME BLK RECORD (BLKF)SAVE BLK RECORD (INFF) NAME INF, INF2 RECORD (INFF)G !*********************************************** !* E V E N T S !! %ON %EVENT 15 %START; ! DISC I/O FAIL !! %IF PX_SERVICE = 0 %THEN -> RESTART; ! IN TIMER SECTION !! -> REPLY !! %FINISH !********************************************** !**************************************************************** !****************************************************************** !*ROUTINE DA !*CALLS DISC HANDLER TO READ IN A BLOCK !* NB: THIS ROUTINE ASSUMES THAT BX POINTS TO THE BLOCK DESCRIPTOR ROUTINE DA(INTEGER MODE) RECORD (P2F)P INTEGER DRIVE DRIVE = BX_DRIVE P_A3 = BX_BLOCK; ! COMPILER ERROR FORCES THIS P_SERVICE = SERV(DRIVE) P_REPLY = ID IF DRIVE = 1 THEN P_A3 = P_A3!K'020000' P_A1 = MODE IF MODE # D READ THEN BX_WRM = 0 ! CLEAR THE WRITE MARKER P_A2 == BX_BLK(0) PONOFF(P) IF P_A1 # 0 THENSIGNAL 15, 15 END !******************************************************* !*RECORD MAP LOAD !*LOADS REQUESTED BLOCK INTO CORE IF IT IS NOT ALREADY THERE !*AND RETURNS A POINTER TO THE START OF THE RECORD BX !*WHICH IS SET UP TO CURRENT ENTRY IN THE BUFFER POOL !*DRIVE IS ASSUMED TO BE SET UP. ******** !* THE ROUTINE ALSO SETS UP GLOBAL BX AS A SIDE EFFECT RECORD (BF) MAP LOAD(INTEGER BLOCK) INTEGER I, TEMP !*CHECK IF BLOCK ALREADY IN POOL CYCLE I = NBUF, -1, 0 BX == B(I) IF BX_DRIVE = DRIVE AND BX_BLOCK = BLOCK START RESULT == BX FINISH REPEAT !*BLOCK NOT IN POOL BX == B(BLAST) BLAST = BLAST+1 IF BLAST > NBUF THEN BLAST = 0 IF BX_WRM # 0 START ; !WRITE BACK OLD BLOCK DA(DWRITE) FINISH BX_DRIVE = DRIVE BX_BLOCK = BLOCK DA(DREAD); !READ IN NEW BLOCK RESULT == BX END !************************************************************ !*RECORD MAP EXAM !*TO READ IN CORRECT DIRECTORY BLOCK !*AND FIND REQUIRED ENTRY RECORD (FILEF) MAP EXAM(RECORD (INFF) NAME INF) INTEGER N, J, K, HIT, T RECORD (N2F) NAME FILE RECORD (N2F) NAME INFO RECORD (FILE2F) NAME F !*SET UP DRIVE NUMBER,0,1 RK05 !2,3 AMPEX DRIVE = INF_UNIT INFO == INF_N; ! POINT TO NAME PART !*SET UP DIRECTORY BLOCK FOR SCAN T = DIRBLK(DRIVE) N = T+INF_FSYS; ! MAP TO USERS DIRECTORY UNTIL N > T+2 CYCLE ; ! SYSTEM OCCUPIES 3 BLOCKS FA == LOAD(N)_BLK !*LOOK FOR MATCH CYCLE J = 0, 1, 50 FNO = J; ! GLOBAL FOR CREATE F == FA(J); ! POINT TO TARGET ENTRY FILE == F_N; ! MOST CONVENIENT FORMATR IF FILE_A = INFO_A AND FILE_B = INFO_B AND FILE_C = C INFO_C THENRESULT == F REPEAT N = N+1 EXIT ; ! ONLY ON BLOCK ON TU58 REPEAT RESULT == NULL END !****************************************************************** !*RECORD MAP GET BLOCK !*RETURNS POINTER TO CORRECT BLOCK DESCRIPTOR !*AFTER CALLING LOAD TO READ IT INTO CORE RECORD (BLKF) MAP GET BLOCK(INTEGER BLOCK NO) INTEGER POS, PT POS = BLOCK NO >> 7+BLKLST(DRIVE) !BLOCK DESC BLOCK BLKA == LOAD(POS)_BLK RESULT == BLKA(BLOCK NO&K'177') ! OFFSET INTO BLOCK END !********************************************************** !*INTEGER FUNCTION APPENDB !*RETURNS NEXT FREE BLOCK NUMBER INTEGERFN APPENDB(INTEGER LAST) INTEGER WRAP WRAP = 0 CYCLE LAST = LAST+1 IF LAST = LASTBL(DRIVE) START IF WRAP = 0 THENRESULT = 0 WRAP = WRAP+1 LAST = FBLOCK(DRIVE) FINISH BLK == GET BLOCK(LAST) IF BLK_PR = 0 THENRESULT = LAST REPEAT END !***************************************************************** !************************************************************* !************************************************************* !*MAIN CONTROL LOOP !*LINK TO SYSTEM SLOTS LINKIN(AMP1SER) LINKIN(AMP2SER) ID = GETID ALARM(SECS*50); !SET CLOCK FOR SECS SECONDS RESTART: CYCLE P_SERVICE = 0 POFF(P) !*IF CLOCK TICK CHECK IF BUFFER POOL NEEDS WRITING IF P_REPLY = CLOCK INT START PX_SERVICE = 0; ! FOR EVENT 15 HANDLING CYCLE I = NBUF, -1, 0 IF B(I)_WRM # 0 START BX == B(I) DA(DWRITE) FINISH REPEAT ALARM(SECS*50) CONTINUE FINISH !*NOT A CLOCK TICK--REQUEST FOR SERVICE PX_SERVICE = P_REPLY PX_REPLY = P_SERVICE PX_A2 = P_A2 !*GET CALLERS BLOCK NO = 0 SEG = P_A2 >> 13 IF SEG = 0 THENSIGNAL 36, 36 MAP VIRT(P_REPLY, SEG, MY SEG) INF == RECORD(MSA+(P_A2&K'17777')); INF2 == INF -> REQUEST(P_A1) !* !** !***** EXAMINE FILE !** !* REQUEST(EXAMINE): !*P_A2 HAS ADDRESS OF DESCRIPTOR !*EXAMINE FINDS THE FILE ENTRY IN THE DIRECTORY BLOCK !*AND RETURNS THE FIRST BLOCK'S NUMBER IN THE FILE !*TO THE CALLER. NO = 0 F == EXAM(INF) UNLESS F == NULL THEN NO = F_FIRST IF DRIVE = 1 AND NO # 0 THEN NO = NO!K'020000' -> REPLY WRITE DIR: DA(DWRITE); !PUT DIRECTORY BLOCK BACK REPLY: MAP VIRT(0, -1, MYSEG); !RELEASE SEGMENT PX_A1 = NO PON(PX) CONTINUE !* !** !***** GET NEXT !** !* REQUEST(GET NEXT): !*P_A2=FILE DESCRIPTOR,P_A3=LAST BLOCK !*GET NEXT IS GIVEN A BLOCK OF A FILE AND RETURNS !*THE NEXT BLOCK IN THE FILE BY LOOKING AT THE LINK IN !*THE BLOCK DESCRIPTOR.IT ALSO READS THE BLOCK DECRIPTOR !*ENTRY FOR THE NEXT BLOCK TO CHECK THE PROTECT CODE. DRIVE = INF_UNIT BK = P_A3 IF DRIVE = 1 THEN BK = BK&K'17777' BLK == GET BLOCK(BK); !GET PREVIOUS BLOCK PR = BLK_PR; NO = BLK_NEXT IF NO # 0 START BLK == GET BLOCK(NO) IF BLK_PR # PR THEN NO =- 1 ELSESTART !! NO = -1 IS A PROTECT CODE ERROR IF DRIVE = 1 THEN NO = NO!K'020000' FINISH FINISH -> REPLY !* !** !***** DESTROY !** !* REQUEST(DESTROY): !*DESTROY REMOVES THE FILE'S NAME FROM THE DIRECTORY !*BLOCK AND GOES DOWN THE BLOCK DESCRIPTOR ENTRIES FOR !*THAT FILE SETTING ALL THE LINKS AND PROTECT CODES TO !*ZERO(CHECKING THE PROTECT CODES AS IT GOES.) EXIT = 0; !TAKE NORMAL EXIT DESTF: NO = 1; ! FILE DOES NOT EXIST F == EXAM(INF) UNLESS F == NULL START NO = 0 BK = F_FIRST; PR = F_PR F = 0; ! DELETE NAME ETC F_PR = PR; ! RESTORE "PR" DA(DWRITE); !WRITE BLOCK BACK IMMEDIATELY UNTIL BK = 0 CYCLE !DELETE ALL LINKS AND PR BLK == GET BLOCK(BK) IF BLK_PR # PR START NO =- 1; !CORRUPT FILE!!! EXIT FINISH IF FBLOCK(DRIVE) <= BK < FIRST FREE(DRIVE) THEN C FIRST FREE(DRIVE) = BK BK = BLK_NEXT BLK = 0; ! ZERO PR AND NEXT BX_WRM = BX_WRM+1 REPEAT FINISH -> REPLY IF EXIT = 0 -> REN TMP; !BACK TO RENAME TEMP !* !** !***** CREATE FILE !** !* REQUEST(CREATE): !*A FILE IS CREATED BY FINDING AN EMPTY SLOT IN THE DIRECTORY !*BLOCK AND COPYING THE NAME INTO IT.A FREE BLOCK IS THEN FOUND !*AND IS DEEMED TO BE THE FIRST BLOCK OF THE FILE.A LINK TO !*THIS BLOCK IS SET UP AND THE PROTECT CODE CALCULATED AND !*INSERTED INTO THE BLOCK DESCRIPTOR. DRIVE = INF_UNIT NOSAVE = 0 NOSAVE = APPENDB(FIRST FREE(DRIVE)) IF NOSAVE # 0 START G_FSYS = INF_FSYS G_UNIT = INF_UNIT F == EXAM(G); !FIND EMPTY SLOT UNLESS F == NULL START NO = NOSAVE F_N = INF_N; ! COPY NAME BX_WRM = BX_WRM+1 F_PR = ((F_PR+K'010000')&K'170000')!INF_FSYS << 6!FNO F_PR = K'010000' IF F_PR = 0 ! IN CASE OF ZERO PR F_FIRST = NO PR = F_PR DA(D WRITE); !PUT DIRECTORY BLOCK BACK BLK == GET BLOCK(NO); !GET BLOCK DESCRIPTOR BACK BLK_PR = PR BX_WRM = BX_WRM+1 FIRST FREE(DRIVE) = NO IF DRIVE = 1 THEN NO = NO!K'020000' FINISH FINISH -> REPLY !* !** !***** APPEND BLOCK !** !* REQUEST(APPEND): !*TO APPEND A BLOCK TO A FILE THE CURRENT LAST BLOCK !*DESCRIPTOR ENTRY IS INSPECTED FOR THE PROTECT CODE. !*THE NEXT FREE BLOCK'S DESCRIPTOR IS THEN !*UPDATED WITH THIS CODE AND A LINK TO THIS BLOCK !*IS INSERTED IN THE LAST DESCRIPTOR ENTRY. DRIVE = INF_UNIT BK = P_A3; !GET LAST BLOCK IF DRIVE = 1 THEN BK = BK&K'17777' BLK == GET BLOCK(BK); !GET LAST BLOCK PR = BLK_PR NO = APPENDB(BK); !GET NEW LAST BLOCK IF NO # 0 START BLK_NEXT = 0 BLK_PR = PR BX_WRM = BX_WRM+1 FIRST FREE(DRIVE) = NO BLK == GET BLOCK(BK); !GET PREVIUOS LAST BLOCK TO ! INSERT LINK BLK_NEXT = NO IF DRIVE = 1 THEN NO = NO!K'020000' BX_WRM = BX_WRM+1 FINISH -> REPLY !* !** !***** RENAME FILE !** !* REQUEST(RENAME): REQUEST(RENAME FSYS): ! FILES IN DIFFERENT FSYS !*P_A2HAS EXISTING,P_A3 HAS NEW FILE DESCRIPTOR !*IF THE NEW FILE DOES NOT ALREADY EXIST THEN THE OLD !*FILE NAME IN THE DIRECTORY BLOCK IS REPLACED BY !*THE NEW. NO =- 1 SEG2 = P_A3 >> 13 IF SEG2 = SEG START INF2 == RECORD(MSA+(P_A3&K'17777')) IF INF_UNIT = INF2_UNIT START IF P_A1 = RENAME FSYS START G_FSYS = INF2_FSYS G_UNIT = INF2_UNIT F == EXAM(G) UNLESS F == NULL START F == EXAM(INF); ! GET EXISTING FILE UNLESS F == NULL START ; ! DOESN'T EXIST BK = F_FIRST; PR = F_PR F = 0; ! ZERO NAME RECORD BX_WRM = BX_WRM+1 DA(D WRITE) F == EXAM(G); ! GET EMPTY SLOT AGAIN F_N = INF2_N; ! COPY NAME F_FIRST = BK; F_PR = PR !! BX_WRM = BX_WRM+1 (WRITE DIR WRITES BACK) NO = 0 FINISH FINISH ELSE F == EXAM(INF2); !CHECK NEW FILE DOES NOT EXIST IF F == NULL START F == EXAM(INF) IF F == NULL THEN NO = 1 ELSESTART F_N = INF2_N; ! COPY NAME !! BX_WRM = BX_WRM+1 (WRITE DIR WRITES BACK) NO = 0 FINISH FINISH FINISH FINISH FINISH -> WRITE DIR !* !** !***** RENAME TEMPORARY FILE !** !* REQUEST(RENAME TEMP): !*THIS RENAMES A TEMPORARY FILE IN THE SENSE THAT IT REMOVES !*THE TEMP FILE MARKER AND DESTROYS THE FILE. EXIT = 1; !SPECIAL EXIT FORM DIRECTORY INF_N_NAME(0) = INF_N_NAME(0)&X'FF7F' !REMOVE TEMP MARKER -> DESTF REN TMP: INF_N_NAME(0) = INF_N_NAME(0)!X'0080' !PUT BACK MARKER F == EXAM(INF) IF F == NULL THEN NO =- 1 ELSESTART F_N_NAME(0) = F_N_NAME(0)&X'FF7F' !NOT TEMP NOW !! BX_WRM = BX_WRM+1 (WRITE DIR WRITES BACK) NO = 0 FINISH -> WRITE DIR REQUEST(DIR BLK NO): ! GIVE BLOCK NO OF DIRECTORY NO = DIRBLK(INF_UNIT)+INF_FSYS -> REPLY REPEAT ENDOFPROGRAM