PROC DS$$DOC; # TITLE DS$$DOC - DESIGN DOCUMENTATION FOR THE DESTAGE PROCESS. # BEGIN # DS$$DOC # # * D E S T A G I N G O V E R V I E W * * *SSMOVE* CREATES A FILE CALLED *MVOCOM* (UI = 377760B) WHICH HAS * AN ENTRY FOR EACH FILE TO BE DESTAGED OR DESTAGED AND RELEASED. * *SSMOVE* ISSUES A *UCP* CALL TO *SSEXEC* TO INDICATE THAT * DESTAGING IS TO BE DONE. THE *UCP* REQUEST PROCESSOR *TYP2RP* * CALLS *DSSETUP* TO PREPARE FOR FILE DESTAGING. * * *DSSETUP* COPIES THE DESTAGING ENTRIES (*TDAM* ENTRIES) FROM THE * FILE PREPARED BY *SSMOVE* TO EIGHT SCRATCH FILES, ONE PER * SUBFAMILY. WHILE DOING THIS COPY, IT CALCULATES THE NUMBER OF AU * REQUIRED TO HOLD THE FILES TO BE DESTAGED. THESE REQUIREMENTS * ARE USED BY THE ALLOCATOR (*DSALLO*) TO SELECT THE BEST STORAGE * MODULE AND CARTRIDGE FOR THE SET OF FILES IN ATTEMPTING TO * SATISFY THE DUAL OBJECTIVES OF AVOIDING CARTRIDGE OVERFLOW AND * REDUCING CARTRIDGE ACCESS TIME BY PLACING MANY FILES ON THE SAME * CARTRIDGE. * * WHEN THE EIGHT SCRATCH FILES ARE PREPARED, THE FILE FROM *SSMOVE* * IS REWOUND AND IS READY TO BE USED TO REPORT BACK TO *SSMOVE* THE * IDENTITY OF ALL FILES WHICH COULD NOT BE DESTAGED. THE REASON * FOR EACH SUCH FAILURE IS ALSO SUPPLIED. THE VARIABLE *DSC$INIT* * IS SET NON-ZERO TO SIGNAL THE MAIN LOOP THAT DESTAGING IS TO BE * INITIATED. *MAINLP* CALLS *NEWWORK* WHICH GETS AN *HLRQ* ENTRY * AND THEN CALLS *DSNTDAM* TO SELECT A SUBFAMILY AND FILE TO START * DESTAGING. * * IT SHOULD BE NOTED THAT THE STAGING PROCESS CAN PRE-EMPT THE * CARTRIDGE OR *HLRQ* ENTRY USED FOR DESTAGING BY SETTING THE * *DOSTG* FLAG IN THE *HLRQ* ENTRY. WHEN DESTAGER IS DONE WITH THE * CURRENT CARTRIDGE (EXCEPT IN A CARTRIDGE OVERFLOW CONDITION), IT * WILL CALL *STNTDAM* TO SELECT A FILE TO BE STAGED FROM THE * CURRENT CARTRIDGE USING THE CURRENT *HLRQ* ENTRY. WHEN THIS * OCCURS, THE *DSC$INIT* FLAG IS AGAIN SET NON-ZERO TO CAUSE THE * DESTAGING PROCESS TO BE RE-INITIATED. # CONTROL EJECT; # * M A J O R R O U T I N E S I N D E S T A G I N G * * 1) DSSETUP IS CALLED BY *TYP2RP* WHEN *SSMOVE* MAKES A *UCP* * REQUEST TO *SSEXEC*. IT COPIES THE *TDAM* ENTRIES FOR FILES TO * BE DESTAGED FROM THE *MVOCOM* FILE TO EIGHT SCRATCH FILES, ONE * PER SUBFAMILY. * * 2) DESTAGR IS CALLED BY THE *HLRQ* MONITOR TO DESTAGE A FILE. * IT CALLS PROCEDURES 3 AND 5-8 BELOW TO ASSIST IT IN THIS PROCESS. * WHEN A FILE HAS BEEN DESTAGED, IT CALLS *DSNTDAM* TO UPDATE THE * *HLRQ* ENTRY TO REFLECT THE NEXT FILE TO BE DESTAGED. * * 3) DSALLO IS CALLED BY *DESTAGR* TO SELECT A STORAGE MODULE * AND CARTRIDGE FOR A FILE AND ALSO ASSIGN SOME UNUSED SPACE TO THE * FILE BEING DESTAGED. * * 4) ANLZAST IS A HELPER ROUTINE TO *DSALLO* TO IDENTIFY THE * BEST CARTRIDGE FOR A SHORT FILE AND THE BEST CARTRIDGE OR * CARTRIDGE GROUP FOR A LONG FILE. * * 5) HLLOAD IS CALLED BY *DESTAGR* TO INTERFACE WITH THE DRIVER * TO CAUSE A CARTRIDGE TO BE MADE AVAILABLE FOR I/O. * * 6) HLCPYDC IS CALLED BY *DESTAGR* TO COPY SOME FILE DATA FROM * DISK TO THE CURRENTLY ASSIGNED M860 VOLUME. * * 7) HLUNLD IS CALLED BY *DESTAGR* TO INTERFACE WITH THE DRIVER * TO UNLOAD A CARTRIDGE WHICH IS NO LONGER NEEDED. * * 8) RLSVOL IS CALLED BY *DESTAGR* AND *HLCPYDC* (AND OTHER * PROCEDURES) TO RELEASE ANY UNUSED AU BY RETURNING THEM TO THE * CHAIN OF AVAILABLE AU ON THE CURRENT CARTRIDGE. * * 9) DSNTDAM IS CALLED BY *DESTAGR* AND *NEWWORK* WHEN AN *HLRQ* * ENTRY IS AVAILABLE FOR USE IN DESTAGING A FILE. *DSNTDAM* ISSUES * ANY APPROPRIATE MESSAGES ABOUT THE STATUS OF THE FILE JUST * DESTAGED AND SELECTS THE NEXT FILE TO BE DESTAGED, TRYING TO PICK * ONE WHICH WILL FIT ON THE CURRENTLY LOADED CARTRIDGE. * * 10) LLRQXXX REPRESENT SEVERAL LOW LEVEL REQUEST MODULES WHICH * ARE CALLED BY THE *HLXXXXX* ROUTINES AS NEEDED TO PERFORM * CARTRIDGE LOADS, UNLOADS, AND COPIES FROM DISK TO CARTRIDGE. # CONTROL EJECT; # * D E S T A G E O V E R V I E W ( D E T A I L E D ) * * INPUT TO THE TOTAL DESTAGE PROCESS IS PREPARED BY THE *SSMOVE* * UTILITY AND CONSISTS OF ONE FILE WHICH CONTAINS AN ENTRY FOR EACH * FILE WHICH IS TO BE DESTAGED. THESE ENTRIES HAVE BEEN ORDERED BY * *SSMOVE* TO ASSIST IN REDUCING THE NUMBER OF CARTRIDGE ACCESSES * NEEDED TO DESTAGE ALL THE FILES. THE FIRST SET OF ENTRIES IS FOR * SUBFAMILY 0, SUBFAMILY 1, ... THROUGH SUBFAMILY 7. WITHIN EACH * SUBFAMILY, ENTRIES ARE ORDERED SUCH THAT ALL SHORT FILES OCCUR * FIRST AND ALL LONG FILES OCCUR AFTERWARDS. WITHIN THE LIST OF * SHORT FILES AND LONG FILES, INDIVIDUAL FILES ARE ORDERED BY * DECREASING FILE LENGTH. THE *SSMOVE* UTILITY DECLARES A FILE TO * BE SHORT IF ITS LENGTH IS LESS THAN A SITE SPECIFIED VALUE. * * BY DEFINITION, SHORT FILES ONLY RESIDE ON ONE CARTRIDGE. IF A * SHORT FILE IS ENCOUNTERED WHICH DOES NOT FIT ON ONE CARTRIDGE, * THE ATTEMPT TO DESTAGE IT IS ABANDONED DUE TO LACK OF SPACE AND * DESTAGING CONTINUES WITH THE NEXT FILE. TO REDUCE STAGING DELAYS * DUE TO CARTRIDGE POSITIONING TIME, SHORT FILES ARE STORED AT THE * FRONT OF A CARTRIDGE. A CARTRIDGE DIVISION POINT PARAMETER TO * *SSLABEL* DETERMINES THE END OF THE SHORT FILE AREA. * * LONG FILES ARE ALLOWED TO OVERFLOW FROM ONE CARTRIDGE TO ANOTHER * WITHIN A GROUP OF UP TO 16 CARTRIDGES, ALTHOUGH THE DESTAGER * ATTEMPTS TO AVOID OR REDUCE CARTRIDGE OVERFLOW AS MUCH AS * POSSIBLE. IF A LONG FILE DOES NOT FIT ON ANY GROUP OF * CARTRIDGES, THE ATTEMPT TO DESTAGE IT IS ABANDONED DUE TO LACK OF * AVAILABLE SPACE. * * IF THE FIRST FILE OF THE SEQUENCE OF FILES FOR A SUBFAMILY IS A * SHORT FILE, THE ALLOCATOR SELECTS A CARTRIDGE WHICH WILL * DEFINITELY HOLD THE FIRST SHORT FILE AND HOPEFULLY WILL HOLD ALL * THE SHORT FILES. IF THIS IS POSSIBLE, THE ALLOCATOR WILL FURTHER * PICK THE CARTRIDGE WHICH IS ABLE TO HOLD THE MOST LONG FILES. * AFTER A CARTRIDGE HAS BEEN SELECTED AND THE FIRST SHORT FILE HAS * BEEN DESTAGED, AS MANY OTHER SHORT FILES AS WILL FIT ON THAT * CARTRIDGE ARE DESTAGED, AND THEN AS MANY LONG FILES AS WILL FIT * ON THAT CARTRIDGE ARE ALSO DESTAGED. ALL FILES WHICH DO NOT FIT * ON THE CURRENT CARTRIDGE ARE DEFERRED FOR SUBSEQUENT DESTAGING TO * A DIFFERENT CARTRIDGE. THIS IS DONE BY WRITING THE FILES'S * *TDAM* ENTRY TO A SCRATCH FILE. WHEN DESTAGING TO THIS FIRST * CARTRIDGE HAS BEEN COMPLETED, THE ABOVE PROCESS IS REPEATED USING * THE LIST OF DEFERRED FILES AS INPUT INSTEAD OF THE ORIGINAL LIST * OF FILES FROM *SSMOVE*. THIS PROCESS CONTINUES ONE CARTRIDGE AT * A TIME UNTIL ALL THE SHORT FILES AND AS MANY LONG FILES AS * POSSIBLE HAVE BEEN DESTAGED. * * WHEN ONLY LONG FILES REMAIN TO BE DESTAGED, THE PROCESS CONTINUES * AS DESCRIBED ABOVE. HOWEVER, IF AT ANY TIME, THE FIRST FILE ON * THE SEQUENCE OF REMAINING FILES WILL NOT FIT ON ONE CARTRIDGE, * THEN A GROUP OF CARTRIDGES IS SELECTED AND CARTRIDGES WITHIN THIS * GROUP ARE SELECTED ONE AT A TIME UNTIL THE FIRST FILE HAS BEEN * COMPLETELY DESTAGED. THE DESTAGE PROCESS THEN CONTINUES BY * DESTAGING AS MANY OF THE REMAINING LONG FILES AS POSSIBLE TO THE * FINAL CONTINUATION CARTRIDGE AS LONG AS NO FILE HAS TO OVERFLOW * TO ANOTHER CARTRIDGE. AGAIN, ANY FILES WHICH DO NOT FIT IN THEIR * ENTIRETY ARE DEFERRED FOR DESTAGING TO A SUBSEQUENT CARTRIDGE OR * CARTRIDGES BY WRITING THE DESTAGE *TDAM* ENTRY TO A SCRATCH FILE. # CONTROL EJECT; # * D E S T A G E D E T A I L E D F L O W * * ( N O R M A L C A S E ) * * THE FOLLOWING SEQUENCE OCCURS WHEN A FILE IS DESTAGED. * * CASE A) NO CARTRIDGE OVERFLOW. * * PROCEDURE *DSNTDAM* SELECTS THE SUBFAMILY FOR WHICH FILE * DESTAGING IS TO OCCUR. IT THEN SELECTS THE FIRST FILE ON THE * LIST OF FILES SUBMITTED BY *SSMOVE*. IF SHORT FILES ARE TO BE * DESTAGED, THIS FIRST FILE IS THE LONGEST OF THE SHORT FILES. IF * ONLY LONG FILES ARE TO BE DESTAGED, THIS FILE IS THE LONGEST OF * THE LONG FILES. * * PROCEDURE *DSALLO* IS CALLED BY *DESTAGR* TO ALLOCATE SOME * CARTRIDGE SPACE FOR THE FILE DATA. SINCE THIS IS THE INITIAL * ALLOCATION CALL, IT FIRST SELECTS A STORAGE MODULE THAT CAN BE * USED, READS IN THE *AST* FOR THIS STORAGE MODULE, PICKS A * CARTRIDGE (OR, IF OVERFLOW IS ANTICIPATED, A GROUP OF CARTRIDGES * AND THE INITIAL CARTRIDGE TO BE USED WITHIN THIS GROUP), READS IN * THE *FCT* ENTRY FOR THIS CARTRIDGE AND FINALLY ALLOCATES A * SEQUENCE OF ALLOCATION UNITS TO BE USED FOR THE FILE DATA. THIS * SEQUENCE IS CALLED A VOLUME. * * THE DESTAGER THEN CALLS *HLLOAD* TO LOAD THE CARTRIDGE SO IT CAN * BE ACCESSED AND MAKES A CALL TO *PFM* TO OBTAIN ACCESS TO THE * FILE DATA. IT THEN CALLS *HLCPYDC* TO COPY SOME FILE DATA FROM * DISK TO THE CARTRIDGE. IF THE ENTIRE FILE IS NOT YET COPIED TO * THE CARTRIDGE, CALLS TO ALLOCATE MORE SPACE AND COPY MORE DATA * ARE MADE UNTIL THE FILE IS COPIED TO THE CARTRIDGE. AS EACH * VOLUME IS COPIED TO THE CARTRIDGE, THE *FCT* ENTRY IS UPDATED IN * MEMORY TO REFLECT THE SEQUENCE OF ALLOCATION UNITS THAT ARE USED * TO STORE THE FILE DATA. UPON COMPLETION OF THIS ALLOCATE/COPY * SEQUENCE, *PFM* IS AGAIN CALLED TO UPDATE THE FILE'S *PFC* ENTRY * TO REFLECT THE LOCATION OF THE FILE DATA ON THE ALLOCATED * CARTRIDGE. IF DISK SPACE IS TO BE RELEASED, ANOTHER CALL TO * *PFM* IS MADE TO ACHIEVE THIS. * * CASE B) ADDITIONAL FILES ON THE SAME CARTRIDGE. * * UPON COMPLETION OF THE DESTAGE PROCESS FOR THE FIRST FILE, * PROCEDURE *DSNTDAM* IS AGAIN CALLED TO SELECT THE NEXT FILE TO BE * DESTAGED. IT SELECTS ONE WHICH WILL FIT ON THE CURRENT * CARTRIDGE. IF LONGER FILES EXIST, THEIR DESTAGE ENTRIES ARE * STORED ON A SCRATCH FILE TO BE PROCESSED LATER WHEN IT BECOMES * NECESSARY TO SWITCH TO A DIFFERENT CARTRIDGE. THE DESTAGER * ALLOCATES SPACE VIA *DSALLO*, OBTAINS ACCESS TO THE FILE DATA VIA * *PFM* AND COPIES THE FILE TO THE CARTRIDGE USING THE * ALLOCATE/COPY SEQUENCE DESCRIBED ABOVE. THE FILE'S *PFC* ENTRY * IS UPDATED AND THE DISK SPACE RELEASED AS DESCRIBED ABOVE. * * CASE C) CARTRIDGE OVERFLOW. * * THIS DESTAGE PROCESS IS SIMILAR TO CASE A), EXCEPT THAT WHEN THE * FIRST CARTRIDGE NO LONGER HAS AVAILABLE SPACE, THE ALLOCATOR * SELECTS A CONTINUATION CARTRIDGE. THIS SECOND CARTRIDGE MUST BE * IN THE SAME GROUP AS THE FIRST. THE LINKAGE INFORMATION FOR THE * FIRST CARTRIDGE IS UPDATED TO POINT TO ANOTHER CARTRIDGE WITHOUT * IDENTIFYING A SPECIFIC CARTRIDGE OR INITIAL ALLOCATION UNIT. THE * *FCT* ENTRY FOR THE FIRST CARTRIDGE IS THEN WRITTEN TO DISK, AND * THE *FCT* ENTRY FOR THE SECOND CARTRIDGE IS THEN READ TO MEMORY. * AFTER THE FIRST VOLUME ON THE SECOND CARTRIDGE HAS BEEN WRITTEN, * THE *FCT* ENTRY FOR THE SECOND CARTRIDGE IS UPDATED TO REFLECT * THE NEW VOLUME AND WRITTEN TO DISK. THE *FCT* ENTRY FOR THE * FIRST CARTRIDGE IS READ INTO MEMORY, UPDATED TO LINK TO THE * INITIAL ALLOCATION UNIT OF THE FIRST VOLUME ON THE SECOND * CARTRIDGE AND THEN WRITTEN BACK TO DISK. THE *FCT* ENTRY FOR THE * SECOND CARTRIDGE IS THEN READ BACK TO MEMORY. UPON COMPLETION OF * THE ALLOCATE/COPY SEQUENCE, THE FILE'S *PFC* ENTRY IS UPDATED AS * BEFORE, AND THE DISK SPACE RELEASED IF APPROPRIATE. # CONTROL EJECT; # * D E S T A G E * * E R R O R C O N D I T I O N S A N D P R O C E S S I N G * * THE RESULT OF ANY ERROR ENCOUNTERED IN DESTAGING A FILE IS THAT * THE ERROR CAN BE OVERCOME (SUCH AS A DELAY CONDITION), OR THE * ERROR WILL CAUSE THE DESTAGE TO BE RETRIED, OR THE ERROR WILL * CAUSE THE DESTAGE TO BE ABANDONED. FILE DESTAGES WHICH ARE * ABANDONED RESULT IN A DAYFILE AND ACCOUNT FILE MESSAGE WITH AN * ERROR CODE. IN ADDITION, *SSMOVE* WILL PRODUCE A NON-CODED * DESCRIPTION OF THE REASON FOR THE DESTAGE FAILING IF THE *NW* * PARAMETER WAS NOT SELECTED. IF A DESTAGE IS TO BE RETRIED, THE * DESTAGE REQUEST IS WRITTEN (BY *DSNTDAM*) TO A SCRATCH FILE. * AFTER THE CARTRIDGE CURRENTLY IN USE IS SCHEDULED TO BE UNLOADED, * THE ENTRIES ON THE SCRATCH FILE ARE RESCHEDULED FOR ANOTHER * DESTAGE ATTEMPT. * * CASE A) NO CARTRIDGE OVERFLOW. * * 1) *DSALLO* MAKES AN INITIAL ACCESS TO THE SUBFAMILY CATALOG TO * DETERMINE WHICH STORAGE MODULE TO USE. IF THE SUBFAMILY CATALOG * IS TEMPORARILY NOT AVAILABLE (BECAUSE *PFDUMP* IS DOING A CATALOG * BACKUP DUMP) THE DESTAGE ATTEMPT IS DELAYED BY PLACING THE *HLRQ* * ENTRY ON THE DELAY CHAIN FOR A FEW SECONDS. THE CATALOG ACCESS * REQUEST IS THEN REPEATED UNTIL THE CATALOG CAN BE ACCESSED. THIS * TYPE OF CATALOG ACCESS DELAY SHOULD NEVER OCCUR WITH ANY OTHER * CATALOG ACCESS REQUEST ISSUED BY THE REST OF THE DESTAGE PROCESS. * IF IT DOES, A FATAL ERROR WILL OCCUR. * * 2) *DSALLO* LOOKS AT THE SUBFAMILY CATALOG PREAMBLE AND THE UNIT * DEVICE TABLE (*UDT*) TO IDENTIFY A STORAGE MODULE WHICH IS USABLE * AND WHICH ALSO HAS ENOUGH SPACE FOR THE FILE TO BE DESTAGED. IF * NO SUCH STORAGE MODULE CAN BE FOUND, THE DESTAGE REQUEST IS * ABANDONED. * * 3) *DSALLO* THEN READS THE *AST* FOR THE SELECTED STORAGE MODULE * SO THE BEST CARTRIDGE OR CARTRIDGE GROUP CAN BE IDENTIFIED. IF A * READ ERROR OCCURS WHEN READING THE SUBFAMILY CATALOG, THE DESTAGE * IS ABANDONED. ANY OTHER CATALOG ACCESS ERROR CONDITION IS FATAL. * * 4) *DSALLO* THEN EXAMINES THE *AST*. IF THE FILE IS TOO LONG TO * FIT ON ANY CARTRIDGE OR GROUP OF CARTRIDGES, THE DESTAGE IS * ABANDONED. * * 5) *DSALLO* THEN READS IN THE *FCT* ENTRY FOR THE SELECTED * CARTRIDGE. A CATALOG ACCESS ERROR RESULTS IN THE DESTAGE BEING * ABANDONED. ALSO, IF THE *FCT* ENTRY SAYS THAT THE CARTRIDGE IS * NOT TO BE USED FOR ANY MORE FILES, THE *AST* AND PREAMBLE ARE * UPDATED, AND A NEW CARTRIDGE IS SELECTED. * * 6) *DSALLO* THEN ALLOCATES A VOLUME CONSISTING OF A SEQUENCE OF * AVAILABLE ALLOCATION UNITS. IF NONE EXIST AND THE CARTRIDGE OR * GROUP OF CARTRIDGES WAS CHOSEN FOR THIS FILE, THE DESTAGE IS * ABANDONED. IF THIS FILE IS BEING DESTAGED BECAUSE IT SHOULD HAVE * BEEN ABLE TO FIT ON A PREVIOUSLY SELECTED CARTRIDGE, THE DESTAGE * IS RETRIED. THIS ERROR TYPICALLY OCCURS IF A GREATER THAN * EXPECTED NUMBER OF STRIPES ARE DEMARKED WHILE PREVIOUS VOLUMES OF * THE FILE WERE BEING WRITTEN. * * 7) *DSTAGR* CALLS *HLLOAD* TO LOAD THE CARTRIDGE SO DATA CAN BE * WRITTEN TO IT. IF ANY PROBLEMS OCCUR, THE DESTAGE ATTEMPT IS * RETRIED. ALSO, IF THE CARTRIDGE IS LOST OR IS UNUSABLE DUE TO A * LABEL PROBLEM, THE APPROPRIATE FLAGS ARE SET IN THE *FCT* AND * EVENTUALLY IN THE *AST* AND PREAMBLE FOR THE SUBFAMILY CATALOG. * * 8) *DSTAGR* THEN CALLS *PFM* TO ACQUIRE ACCESS TO THE FILE DATA. * IF THE REQUEST CAN NOT BE PROCESSED IMMEDIATELY BECAUSE THE * CATALOG TRACK IS INTERLOCKED, *DESTAGR* PLACES THE *HLRQ* ENTRY * ON A DELAY CHAIN FOR A FEW SECONDS AND RETRIES THE CALL UNTIL IT * CAN BE PROCESSED. IF A USER OR SYSTEM ACTION SUCH AS A FILE * PURGE OR UPDATE HAS OCCURED SUCH THAT THE REASON FOR SELECTING * THE FILE TO BE DESTAGED HAS BEEN INVALIDATED, THE DESTAGE REQUEST * IS ABANDONED. * * 9) *DESTAGR* CALLS *HLCPYDC* TO COPY FILE DATA FROM DISK TO THE * CARTRIDGE. A DISK READ ERROR RESULTS IN THE DESTAGE BEING * ABANDONED. ANY OTHER ERROR CAUSES THE DESTAGE TO BE RETRIED. IF * THE ERROR WAS DUE TO AN UNRECOVERABLE WRITE ERROR (STRIPE DEMARK * FAILURE) OR DUE TO EXCESSIVE RECOVERED WRITE ERROS (SUCCESSFUL * STRIPE DEMARKS) THE AFFECTED AU(S) ARE MARKED AS FLAWED IN THE * *FCT* ENTRY AND WILL NO LONGER BE AVAILABLE FOR ALLOCATION. IF A * GENERAL HARDWARE PROBLEM OCCURED, THE CARTRIDGE IS ALSO FORCED TO * BE UNLOADED SO ANY FURTHER DESTAGES WILL BEGIN WITH THE SELECTION * OF A STORAGE MODULE AND THEN A CARTRIDGE. * * 10) UPON COMPLETION OF THE COPY SEQUENCE, *DESTAGR* MAKES A * CATALOG ACCESS REQUEST TO WRITE THE *FCT* ENTRY TO DISK TO * PRESERVE THE STATUS OF THE CARTRIDGE SPACE ALLOCATED TO THE FILE. * IT THEN CALLS *PFM* TO UPDATE THE FILE'S *PFC* ENTRY TO REFLECT * THE LOCATION OF THE DATA ON THE CARTRIDGE AND MAY CALL *PFM* TO * RELEASE THE FILE'S DISK SPACE. A CATALOG ACCESS ERROR RESULTS IN * THE DESTAGE BEING ABANDONED. A *PFM* ERROR RESPONSE CAN RESULT * IN A DELAY OR MAY RESULT IN THE DESTAGE BEING ABANDONED OR THE * DISK SPACE RELEASE NOT BEING DONE. * * * C A R T R I D G E O V E R F L O W E R R O R S * * 11) *DSALLO* CAN ENCOUNTER A CASE WHERE MORE SPACE IS NEEDED, BUT * NONE IS AVAILABLE ON THE CARTRIDGE IN USE. THE DESTAGE IS * ABANDONED IF THIS CARTRIDGE DOES NOT HAVE AN OFF CARTRIDGE LINK * AVAILABLE OR IF NO OTHER CARTRIDGE IN THE GROUP HAS ANY AVAILABLE * SPACE. * * A D D I T I O N A L N O T E S * * 1) THE ABILITY OF THE M860 CONTROLLER TO DO WRITE ERROR RECOVERY * BY DEMARKING A STRIPE MEANS THAT LESS DATA CAN BE STORED ON AN AU * THAN EXPECTED. THEREFORE, A FILE MAY REQUIRE ONE OR POSSIBLY * MORE AU THAN ANTICIPATED. BECAUSE OF THIS, *DSALLO* CALCULATES * AN AMOUNT OF CONTINGENCY SPACE WHICH IT TRIES TO ALLOCATE IN * ADDITION TO THE SPACE NEEDED FOR FILE DATA IF NO STRIPES ARE * DEMARKED. * * 2) IF A FILE DESTAGE IS ABANDONED OR RETRIED, THE DESTAGE * PROCESS WILL ATTEMPT TO RELEASE ANY AU ALLOCATED TO THE FILE. IF * CARTRIDGE OVERFLOW HAS OCCURED, THIS IS NOT DONE. * * 3) ANY ERRORS ENCOUNTERED BY THE DRIVER AS IT ATTEMPTS TO UNLOAD * A CARTRIDGE ARE IGNORED BY THE DESTAGE PROCESS. * # END # DS$$DOC # TERM PROC DESTAGR((HLRQADR)); # TITLE DESTAGR - DESTAGE FILE FROM DISK TO M860 CARTRIDGE. # BEGIN # DESTAGR # # * DESTAGR - DESTAGE FILE FROM DISK TO M860 CARTRIDGE. * * *DESTAGR* COPIES A PERMANENT FILE FROM DISK TO AN M860 * CARTRIDGE. IT SELECTS THE BEST CARTRIDGE(S) FOR THE FILE, * ALLOCATES AVAILABLE AU AS NEEDED TO HOLD THE FILE DATA, * ORGANIZES CONSECUTIVE AU INTO VOLUMES AND LINKS THESE * VOLUMES INTO A CHAIN THAT DEFINES THE LOCATION OF THE FILE * DATA ON THE CARTRIDGE. UPON COMPLETION OF THE COPY, THE * *FCT* ON DISK IS UPDATED TO REFLECT THE CHAIN OF AU/VOLUMES AND * THE *PFC* ENTRY FOR THE FILE IS UPDATED TO REFLECT THE * NEW *ASA* VALUE FOR THE M860 COPY OF THE FILE. DEPENDING UPON * AN INPUT PARAMETER FROM *SSMOVE*, THE DISK SPACE FOR THE FILE * IS RELEASED UPON SUCCESSFUL COMPLETION OF THE DESTAGE. * PERFORMANCE MESSAGES ARE WRITTEN TO THE ACCOUNT FILE IF * EXEC WAS CALLED WITH THE TRACE MODE (*TM*) RUN-TIME PARAMETER. * * PROC DESTAGR((HLRQADR)) * * ENTRY (HLRQADR) - ADDRESS OF THE *HLRQ* ENTRY CONTAINING * THE DESTAGE REQUEST. * THE PROCESS STATE FIELD (HLR$HPS) INDICATES THE TYPE * OF PROCESSING TO BE DONE ON THIS CALL TO *DESTAGR*. * POSSIBLE ACTIONS ARE AS FOLLOWS.. * - INITIATE THE DESTAGE PROCESS. * - RESUME PROCESSING AFTER INTERFACING WITH THE DRIVER, * (TO DO A CARTRIDGE LOAD OR UNLOAD, OR A COPY FROM * DISK TO CARTRIDGE.) * - RETRY A FUNCTION WHICH COULD NOT BE DONE PREVIOUSLY * BECAUSE OF AN INTERLOCK CONDITION. * - ACCESS A SUBFAMILY CATALOG * - INTERFACE TO *PFM* (ACQUIRE THE FILE TO BE * DESTAGED, ENTER A NEW *ASA* VALUE IN THE *PFC*, * SET AN ERROR FLAG IN THE *PFC*, OR DROP THE * FILES DISK SPACE). * EXIT THE PROCESS NAME AND STATE FIELDS ARE SET UP TO * IDENTIFY THE NEXT PROCESSING ACTION - WHETHER * BY *DESTAGR* OR BY ONE OF ITS HELPER * ROUTINES (*HLXXXX*). * * PROCESSING LOGIC FOR *DESTAGR* HAS BEEN * ORGANIZED INTO THE FOLLOWING STEPS. * * 1. INITIALIZATION. * * 2. ALLOCATE NEXT VOLUME. * * 3. UNLOAD CARTRIDGE (IF CARTRIDGE OVERFLOW). * * 4. LOAD CARTRIDGE (IF NECESSARY). * * 5. ACQUIRE ACCESS TO THE PERMANENT FILE (VIA *PFM*). * * 6. COPY DATA TO THE ALLOCATED VOLUME. * * 7. UPDATE THE *FCT* TO REFLECT A SUCCESSFUL COPY. * * 8. COMPLETE DESTAGING AND UPDATE THE *FCT* ON * DISK, AND THE *PFC* ENTRY FOR THE FILE. * * 9. RELEASE DISK SPACE (IF REQUESTED). * * 10. ERROR PROCESSING. * * 11. PREPARE TO DESTAGE NEXT FILE, OR TERMINATE. # ITEM HLRQADR U; # *HLRQ* ENTRY ADDRESS # # **** PROC DESTAGR - XREF LIST BEGIN. # XREF BEGIN PROC ADD$LNK; # ADD ENTRY TO CHAIN # PROC ACQ$FCT; # ACQUIRE *FCT* ENTRY # PROC CKPFETC; # CHECK *UGET* STATUS # PROC CFLUSH; # FLUSH SM CATALOG BUFFER # PROC CPUTFCT; # UPDATE *FCT* ENTRY # PROC CRELSLK; # RELEASE CATALOG INTERLOCKS # PROC DELAY; # TIMED DELAY # PROC DROPDS; # DROP DIRECT FILE DISK SPACE # PROC DROPIDS; # DROP INDIRECT FILE DISK SPACE # PROC DSALLO; # ALLOCATE SPACE ON SM # PROC DSERCAT; # DESTAGE ERROR PROCESSOR # PROC DSERPFM; # DESTAGE ERROR PROCESSOR # PROC DSNTDAM; # GET NEXT DESTAGE REQUEST # PROC HLCPYDC; # CHECK COPY RETURN CODES # PROC HLLOAD; # CHECK LOAD RETURN CODES # PROC HLLDSET; # SET *HLRQ* INTO *LLRQ* # PROC MSG; # ISSUE DAYFILE MESSAGE # PROC MSGAFDF; # ISSUE ACCOUNT-DAYFILE MESSAGE # PROC RECALL; # GIVE UP CPU FOR A MOMENT # PROC RETERN; # RETURN FILE # PROC RLSVOL; # RELEASE UNUSED VOLUME # PROC RLS$FCT; # RELEASE *FCT* ENTRY # PROC SETASA; # SET ALTERNATE STORAGE ADDRESS # PROC UASTPRM; # UPDATE *AST* AND PREAMBLE # PROC UATTACH; # UTILITY ATTACH OF FILE # PROC UGET; # UTILITY GET OF FILE # PROC UPUSAGE; # UPDATE USAGE INFO # PROC ZFILL; # ZERO FILL BUFFER # PROC ZSETFET; # INITIALIZE A FET # END # **** PROC DESTAGR - XREF LIST END. # DEF LISTCON #0#; # DO NOT LIST COMMON DECKS # *CALL,COMBFAS *CALL,COMBCHN *CALL,COMBCMD *CALL,COMBCMS *CALL COMBCPR *CALL COMBLRQ *CALL,COMBMCT *CALL,COMBTDM *CALL COMBUDT *CALL,COMXCTF *CALL,COMXEMC *CALL,COMXFCQ *CALL,COMXHLR *CALL COMXIPR *CALL,COMXMSC *CALL,COMSPFM ITEM ATEOI B; # END OF INFORMATION # ITEM CC U; # CHAIN CONTROL VALUE # ITEM CURFCT U; # *FCT* OF A PARALLEL *HLRQ* # ITEM DRDCOUNT I; # NUMBER OF DRD-S AVAILABLE # ITEM DSTGCOUNT I; # DRD AVAILABLE TO DESTAGER # ITEM FLAG B; # BOOLEAN STATUS # ITEM I I; # LOOP COUNTER # ITEM QADDR U; # *FCT* ENTRY ADDRESS # ITEM START I; # STARTING AU # ITEM STAT I; # STATUS # ITEM TEMP U; # TEMPORARY # ITEM TEMP1 U; # TEMPORARY # ITEM TFAM C(7); # TERMPORARY FAMILY # ITEM TFCT U; # ASAFCT # ITEM TTDAMSBF U; # SUBFAMILY NUMBER # ITEM T1 I; # TEMPORARY # ITEM T2 I; # TEMPORARY # ITEM USED I; # AU USED # ARRAY SCR$FET [0:0] P(SFETL); ; # SCRATCH FET # STATUS DSLABEL DS1A, # INITIALIZATION # DS2A, # RETRY *DSALLO* CALL # DS3A, # RE-ENTER AFTER "NORMAL" UNLOAD # DS3B, # RE-ENTER AFTER "FORCED" LOAD # DS3C, # RE-ENTER AFTER "UNLOAD" # DS4A, # RE-ENTER AFTER *HLLOAD* # DS5A, # RETRY *UATTACH*/*UGET* CALL # DS5B, # WAIT *UGET* COMPLETE # DS6A, # RE-ENTER AFTER *HLCPYDC* # DS8A, # RETRY *SETASA* CALL # DS9A, # RETRY *DROP(I)DS* CALL # DS11A, # RE-ENTER AFTER "NORMAL" UNLOAD # DS11B, # RE-ENTER AFTER "FORCED" LOAD # DS11C, # RE-ENTER AFTER "UNLOAD" # DSEND; # END OF LIST # SWITCH DSENTR:DSLABEL DS1A:DS1A, DS2A:DS2A, DS3A:DS3A, DS3B:DS3B, DS3C:DS3C, DS4A:DS4A, DS5A:DS5A, DS5B:DS5B, DS6A:DS6A, DS8A:DS8A, DS9A:DS9A, DS11A:DS11A, DS11B:DS11B, DS11C:DS11C; ARRAY MSGMB [0:0] S(5); BEGIN # MESSAGE BUFFER # ITEM MSG$LINE C(00,00,28) = [" CATALOG *FCT* PROBLEM. "]; ITEM MSG$ZERO U(03,48,12) = [0]; # ZERO-BYTE TERMINATOR # END BASED ARRAY CLEAR [0:0] S(1); BEGIN ITEM CLN U(00,36,24); # CLEAR *DRD* ASSIGNMENT # ITEM RESETDRD U(00,36,24); # NEW *HLRQ* ADDRESS # END CONTROL EJECT; # * STEP 1 - INITIALIZE. # P = HLRQADR; P = LOC(HLR$TDAM[0]); GOTO DSENTR[HLR$HPS[0]]; DS1A: # BEGIN DESTAGE # # * INITIALIZE *HLRQ* FIELDS. NOTE THAT *HLR$VOLAUP* IS * INITIALIZED IN STEP 5 SINCE IT HAS INPUT TO *DSALLO*. # HLR$RESP[0] = ERRST"NOERR"; HLR$PRU[0] = 0; HLR$1STVOL[0] = 0; HLR$NEWASA[0] = 0; IF TDAMFC[0] EQ TDAMFCODE"STAGE" THEN BEGIN # NO RESOURCES - END # GOTO ENDALL; END # * STEP 1 - END. # CONTROL EJECT; # * STEP 2 - ALLOCATE CARTRIDGE SPACE. * - THE ALLOCATED AU ARE USED IN STEP 6 TO STORE * FILE DATA. ANY UNUSED AU ARE MADE AVAILABLE * FOR RE-USE IN STEP 7 IF NO ERRORS OCCUR. * IF ERRORS OCCUR IN STEP 6, THE PROCEDURE * *HLCPYDC* WILL MAKE ANY UNFLAWED AU AVAILABLE * FOR RE-USE. IF ERRORS OCCUR ELSEWHERE, * STEP 10 WILL MAKE THESE AU AVAILABLE. # NEXTVOL: # CHOOSE CARTRIDGE AND AUS # DS2A: # RETRY *DSALLO* CALL # HLR$HPS[0] = DSLABEL"DS2A"; # IF WAIT FOR INITERLOCK # DSALLO(HLRQADR); HLR$AUUD [0] = HLR$VOLAU [0] ; # IN CASE OF ERROR # IF HLR$RESP[0] EQ ERRST"WAIT" THEN # *HLRQ* IS ON CATALOG WAIT # BEGIN HLR$RESP[0] = 0; RETURN; END IF HLR$RESP[0] EQ ERRST"SPECIAL" THEN BEGIN ADD$LNK(HLRQADR,LCHN"HL$DRDRESW",0); HLR$RESP[0] = ERRST"NOERR"; RETURN; END IF (HLR$RESP[0] EQ ERRST"NOERR" ) ## AND (HLR$VOLLN[0] EQ 0) THEN # NO SPACE # BEGIN IF HLR$FFILE[0] THEN # ABANDON FIRST FILE # BEGIN HLR$RESP[0] = ERRST"ABANDON"; HLR$ERRC[0] = ABANDON"NOSPACE"; END ELSE # RETRY OTHER FILES # BEGIN HLR$RESP[0] = ERRST"RETRY"; END END IF HLR$RESP[0] NQ ERRST"NOERR" THEN BEGIN HLR$HPS[0] = DSLABEL"DS2A"; # IF WAIT FOR INTERLOCK # GOTO DSERR; END # * STEP 2 - END. # CONTROL EJECT; # * STEP 3 - UNLOAD PREVIOUS CARTRIDGE, IF APPROPRIATE. * - CALL *HLUNLD* TO DO THE UNLOAD. THE CARTRIDGE * USAGE STATISTICS ARE RETURNED IN THE *HLRQ* * ENTRY AND USED TO UPDATE THE *FCT* IN STEP 7. * - ALL ERROR CONDITIONS ENCOUNTERED IN UNLOADING * A CARTRIDGE ARE HANDLED BY *HLUNLD*. * SINCE *DESTAGR* DOES NOT NEED THIS CARTRIDGE * TO COMPLETE DESTAGING IT DOES NOT CONCERN * ITSELF WITH WHETHER OR NOT UNLOAD ERRORS OCCURRED. # IF HLR$UNLD[0] THEN BEGIN # UNLOAD OLD CARTRIDGE # HLR$UNLD[0] = FALSE; IF HLR$HLRQW[0] NQ 0 THEN BEGIN # SWITCH CONTROL OF *DRD* TO WAITTING *HLRQ* # TEMP = HLR$DRDRA[0]; TEMP1 = HLR$LRQADR[0]; P = HLR$HLRQW[0]; HLR$DRDRA[0] = TEMP; HLR$LRQADR[0] = TEMP1; P = HLRQADR; ADD$LNK(HLR$HLRQW[0],LCHN"HL$READY",0); P = HLR$LRQADR[0]; LLR$UCPRA[0] = HLR$HLRQW[0]; # INSURE PPU POINTS TO NEW *HLRQ* # P = HLR$DRDRA[0]; RESETDRD = HLR$HLRQW[0]; HLR$HLRQW[0] = 0; HLR$DRDRA[0] = 0; HLR$LRQADR[0] = 0; END ELSE BEGIN # DO UNLOAD OF CARTRIDGE # P = HLR$LRQADR[0]; MSGAFDF("I","UL",0,HLRQADR); LLR$DR[0] = ERRST"NOERR"; LLR$PRCNME[0] = REQTYP4"UNLD$CART"; LLR$PRCST[0] = PROCST"INITIAL"; HLR$HPS[0] = DSLABEL"DS3A"; ADD$LNK(HLR$LRQADR[0],LCHN"LL$READY",0); RETURN; DS3A: # RETURN FROM UNLOAD OF CARTRIDGE # IF HLR$RESP[0] NQ RESPTYP4"OK4" THEN BEGIN # * PROCESS UNLOAD CARTRIDGE ERROR AS FOLLOWS: * -DRIVER PLACED ORIGINAL CARTRIDGE IN OUTPUT STATION. * -ASSUME A SECOND CARTRIDGE WAS IN DESTINATION CELL. * -ATTEMPT TO MOVE THIS 2ND CARTRIDGE TO THE OUTPUT * STATION BY LOADING IT. * -IF THE LOAD SUCCEEDS, DO A SECOND UNLOAD BACK TO * THE ORIGINAL DESTINATION. # HLLDSET((HLRQADR)); # SET UP SECOND LOAD # HLR$HPS[0] = DSLABEL"DS3B"; RETURN; DS3B: # RETURN FROM SECOND LOAD # IF HLR$RESP[0] EQ RESPTYP4"OK4" THEN # UNLOAD 2ND CARTRIDGE # BEGIN LLR$PRCNME[0] = REQTYP4"UNLD$CART"; LLR$PRCST[0] = PROCST"INITIAL"; HLR$HPS[0] = DSLABEL"DS3C"; ADD$LNK(HLR$LRQADR[0],LCHN"LL$READY",0); RETURN; DS3C: END # UNLOAD OF 2ND REQUEST # END # LOAD OF 2ND REQUEST # P = HLR$DRDRA[0]; CLN = 0; HLR$DRDRA[0] = 0; END # PHYSICAL CARTRIDGE UNLOAD # END # ORIGINAL UNLOAD REQUEST # # * STEP 3 END. # CONTROL EJECT; # * STEP 4 - LOAD CARTRIDGE, IF APPROPRIATE. * - CALL *HLLOAD* TO DO THE LOAD AND OBTAIN * THE LARGE BUFFER. *HLLOAD* WILL UPDATE * THE *FCT* IF THE CARTRIDGE IS LOST OR HAS * AN IMPROPER LABEL. * - IF ERRORS OCCUR, STEP 11 WILL EVENTUALLY CAUSE * THE CARTRIDGE TO BE UNLOADED AND THE * ASSOCIATED LARGE BUFFER TO BE RELEASED. # IF HLR$LOAD[0] THEN BEGIN # STEP 4 # SLOWFOR I=1 STEP 1 UNTIL MAXSMUNIT DO BEGIN # FIND *SM* # IF HLR$SM[0] EQ SM$ID[I] THEN BEGIN GOTO SMFOUND; END # *SM* FOUND # END # *SM* SEARCH COMPLETE # SMFOUND: DRDCOUNT = 0; IF D0$ON[I] THEN BEGIN DRDCOUNT = 1; END IF D1$ON[I] THEN BEGIN DRDCOUNT = DRDCOUNT + 1; END IF SM$DSNUM[I] EQ 0 THEN # DESTAGE DISABLED ON THIS SM # BEGIN HLR$RESP[0] = ERRST"SMDSTAGEOFF"; GOTO DSINERR; END DSTGCOUNT = SM$DSNUM[I]; TTDAMSBF = HLR$SBF[0]; TFCT = HLR$FCTX[0]; TFAM = HLR$FAM[0]; IF NOT SM$LLRQ1[I] THEN BEGIN IF SM$REQRES1[I] NQ 0 AND SM$REQRES1[I] NQ HLRQADR THEN BEGIN P = SM$REQRES1[I]; IF HLR$HPN[0] EQ HLRPN"DESTAGE" THEN BEGIN DSTGCOUNT = DSTGCOUNT - 1; IF DSTGCOUNT EQ 0 THEN # DO NOT LET A NEW DESTAGE START # BEGIN P = HLRQADR; # SET ERROR TO ORGINIAL HLRQ # HLR$RESP[0] = ERRST"RSFULL"; GOTO DSINERR; END END IF HLR$FCTX[0] NQ 0 THEN BEGIN CURFCT = HLR$FCTX[0]; END ELSE BEGIN CURFCT = HLR$ASAFCT[0]; END IF (TFCT EQ CURFCT) AND (TTDAMSBF EQ HLR$SBF[0]) AND (TFAM EQ HLR$FAM[0]) THEN # REQUESTING CARTRIDGE MOUNTED # BEGIN NEXTHLRQ: IF HLR$HLRQW[0] EQ 0 THEN BEGIN # END OF *HLRQ* WRITING CARTRIDGE # HLR$HLRQW[0] = HLRQADR; P = HLRQADR; STG$MSK = 0; HLR$HPS[0] = DSLABEL"DS5A"; HLR$LOAD[0] = FALSE; RETURN; END ELSE BEGIN # FIND END OF *HLRQ* WRITING # P = HLR$HLRQW[0]; GOTO NEXTHLRQ; END END END END # SM$LLRQ1 CHECK # IF NOT SM$LLRQ2[I] THEN BEGIN IF SM$REQRES2[I] NQ 0 AND SM$REQRES2[I] NQ HLRQADR THEN BEGIN P = SM$REQRES2[I]; IF HLR$HPN[0] EQ HLRPN"DESTAGE" THEN BEGIN DSTGCOUNT = DSTGCOUNT - 1; IF DSTGCOUNT EQ 0 THEN # DO NOT LET A NEW DESTAGE START # BEGIN P = HLRQADR; # SET ERROR TO ORGINIAL HLRQ # HLR$RESP[0] = ERRST"RSFULL"; GOTO DSINERR; END END IF HLR$FCTX[0] NQ 0 THEN BEGIN CURFCT = HLR$FCTX[0]; END ELSE BEGIN CURFCT = HLR$ASAFCT[0]; END IF (TFCT EQ CURFCT) AND (TTDAMSBF EQ HLR$SBF[0]) AND (TFAM EQ HLR$FAM[0]) THEN # REQUESTING CARTRIDGE MOUNTED # BEGIN NEXTHLRQ1: IF HLR$HLRQW[0] EQ 0 THEN BEGIN # END OF *HLRQ* WRITING CARTRIDGE # HLR$HLRQW[0] = HLRQADR; P = HLRQADR; STG$MSK = 0; HLR$HPS[0] = DSLABEL"DS5A"; HLR$LOAD[0] = FALSE; RETURN; END ELSE BEGIN # FIND END OF *HLRQ* WRITING # P = HLR$HLRQW[0]; GOTO NEXTHLRQ1; END END END END # SM$LLRQ2 CHECK # P = HLRQADR; IF (SM$REQRES1[I] NQ 0) ## AND (SM$REQRES2[I] NQ 0) THEN BEGIN HLR$RESP[0] = ERRST"RSFULL"; GOTO DSINERR; END IF DRDCOUNT EQ 1 THEN BEGIN IF(SM$REQRES1[I] NQ 0) ## OR (SM$REQRES2[I] NQ 0) THEN BEGIN HLR$RESP[0] = ERRST"RSFULL"; GOTO DSINERR; END END # END OF ONE *DRD* # IF SM$REQRES1[I] EQ 0 THEN # RESERVE *DRD* # BEGIN SM$REQRES1[I] = HLRQADR; SM$DSFLAG1[I] = TRUE; HLR$DRDRA[0] = LOC(SM$REQRES1[I]); END ELSE BEGIN SM$REQRES2[I] = HLRQADR; SM$DSFLAG2[I] = TRUE; HLR$DRDRA[0] = LOC(SM$REQRES2[I]); END HLR$HPS[0] = DSLABEL"DS4A"; HLLDSET((HLRQADR)); # MOVE *HLRQ* DATA TO *LLRQ* # MSGAFDF("I","LD",0,HLRQADR); RETURN; # WAIT LOAD OF CARTRIDGE # DS4A: HLLOAD((HLRQADR)); # CHECK RETURN CODES # DSINERR: # IF *DRD* NOT ASSIGNED # P = HLRQADR; HLR$LOAD[0] = FALSE; IF HLR$RESP[0] NQ ERRST"NOERR" THEN BEGIN HLR$ERRC[0] = ERRST"SPECIAL"; GOTO DSERR; END END # STEP 4 # CONTROL EJECT; # * STEP 5 - ACQUIRE FILE FROM *PFM*, IF APPROPRIATE. * - ISSUE A *UATTACH* IF DIRECT ACCESS, OTHERWISE, * ISSUE A *UGET*. * - CAUSE THE *PFC* ENTRY TO BE STORED AT *HLR$PFC*. * - RELOOP IF THE *UATTACH* OR *UGET* REQUEST * CAN NOT BE PROCESSED DUE TO SOME DELAY CONDITION. * - ABANDON DESTAGE IF THE FILE HAS BEEN DESTAGED. * - CLEAR THE *HLR$VOLAUP* FIELD. # DS5A: # RETRY *UATTACH*/*UGET* CALL # IF HLR$FVOL[0] THEN BEGIN # STEP 5 # NAMEC[0] = HLR$FLNM[0]; NAMEC[2] = TDAMPFN[0]; NAMEC[1] = TDAMFAM[0]; P = LOC(HLR$PFC[0]); IF NOT TDAMIA[0] THEN BEGIN # DIRECT ACCESS FILE # UATTACH(NAME[0],PFMSTAT,6,NAME[2],PTRD,TDAMUI[0],NAME[1], ## TDAMPFID[0],PFC[0],TDAMCDT[0],LOC(PFMRET)); HLR$PRU[0] = 0; # START WITH SYSTEM SECTOR # END # DIRECT ACCESS FILE # ELSE BEGIN # INDIRECT ACCESS FILE # UGET(NAME[0],PFMSTAT,6,NAME[2],TDAMUI[0],NAME[1], ## TDAMPFID[0],PFC[0],TDAMCDT[0],LOC(PFMRET)); HLR$PRU[0] = 1; # START WITH 1ST DATA SECTOR # PFMSTAT = -1; HLR$HPS[0] = DSLABEL"DS5B"; GLPFMFL = TRUE; ADD$LNK(HLRQADR,LCHN"HL$PFMWAIT",0); RETURN; END # INDIRECT ACCESS FILE # DS5B: P = LOC(HLR$PFC[0]); # * CHECK FOR ERROR ON UGET OR UATTACH. # IF PFMSTAT NQ 0 THEN BEGIN DSERPFM(HLRQADR,PFMSTAT); IF HLR$RESP[0] NQ ERRST"NOERR" THEN BEGIN HLR$HPS[0] = DSLABEL"DS5A"; GOTO DSERR; END END IF TDAMASA[0] NQ PFC$AA[0] THEN # IF FILE ALREADY DESTAGED # BEGIN HLR$RESP[0] = ERRST"ABANDON"; HLR$ERRC[0] = ABANDON"NEWASA";; GOTO DSERR; END HLR$VOLAUP[0] = 0; HLR$CSNDP[0] = ""; HLR$CCODP[0] = ""; HLR$VOLLNP[0] = 0; MSGAFDF("B", "BD",0,HLRQADR); END # STEP 5 # CONTROL EJECT; # * STEP 6 - COPY DATA TO THE NEXT VOLUME. * - CALL *HLCPYDC* TO EFFECT THE COPY. * - IF NO ERROR, *HLR$AUUD* IDENTIFIES THE * LAST AU WRITTEN. *HLR$EOI* IS SET IF * THE DESTAGE IS COMPLETE. # P = HLR$LRQADR[0]; HLR$HPS[0] = DSLABEL"DS6A"; LLR$PRCNME[0] = REQTYP4"CPY$DA"; LLR$PRCST[0] = PROCST"INITIAL"; LLR$DR[0] = 0; ADD$LNK(HLR$LRQADR[0],LCHN"LL$READY",0); RETURN; # START COPY # DS6A: # RE-ENTER AFTER COPY COMPLETE # HLCPYDC((HLRQADR)); # CHECK RETURN CODES # IF HLR$RESP[0] NQ ERRST"NOERR" THEN BEGIN GOTO DSERR; END # * STEP 6 - END. # CONTROL EJECT; # * STEP 7 - UPDATE *FCT* ENTRY TO REFLECT NEW VOLUME. # # * STEP 7.1 - RELEASE UNUSED AU. # USED = HLR$AUUD[0]+1-HLR$VOLAU[0]; RLSVOL(HLRQADR,HLR$FCTQ[0],HLR$AUUD[0]+1,HLR$VOLLN[0]-USED); P = LOC(HLR$PFC[0]); IF TDAMIA[0] THEN BEGIN ATEOI = (HLR$PRU[0] - 1) GQ HLR$PFC$LN[0]; END ELSE BEGIN # DIRECT FILE # ATEOI = HLR$PRU[0] GQ HLR$PFC$LN[0]; END # * STEP 7.2 - ORGANIZED USED AU INTO ONE VOLUME. * (CC=LAST, LINK=0, LENGTH=WHATEVER). * - THE LINK FIELD IS SET TO ZERO TO FACILITATE * ERROR CORRECTION WHEN A PARTIAL CHAIN EXISTS. * *SSVAL* WILL TREAT A CHAIN WHICH HAS NO *PFC* * ENTRY AND HAS CC=FIRST OR MIDDLE AND A * LINK=0 AS IF IT WERE A NORMAL ORPHAN. THIS * PERMITS THE NORMAL M860 SPACE MANAGEMENT * PROCESS TO MAKE THIS SPACE AVAILABLE WITHOUT * HUMAN INTERVENTION. # P = HLR$FCTQ[0] + FCTQHL; T1 = 0; T2 = 0; START = HLR$VOLAU[0]; FOR I = 0 STEP 1 UNTIL USED-1 DO BEGIN SETFCTX(START+I); # SET *FWD* AND *FPS* VALUES # FCT$CLFG(FWD,FPS) = 0; FCT$FBF(FWD,FPS) = 1; FCT$CAUF(FWD,FPS) = T1; FCT$CC(FWD,FPS) = CHAINCON"LAST"; FCT$LEN(FWD,FPS) = USED - 1 - I; FCT$LINK(FWD,FPS) = T2; T1 = 1; # ALL BUT THE FIRST AU ARE CONTINUATION AU # T2 = START; END # * SAVE THE ID OF THE FIRST ALLOCATED VOLUME ON THE * CARTRIDGE IN CASE THE DESTAGE IS ABANDONED. THEN THE * ALLOCATED SPACE CAN BE RELEASED AND REUSED. # IF HLR$1STVOL[0] EQ 0 THEN BEGIN HLR$1STVOL[0] = START; END HLR$VOLLN[0] = 0; # PREVENT RE-RELEASING IF FUTURE ERROR RECOVERY # CONTROL EJECT; # * STEP 7.3 - SAVE NEW *FCT* ENTRY, AND GET OLD *FCT* ENTRY. # IF HLR$JOF[0] THEN BEGIN # GET *FCT* ENTRY FOR PREVIOUS CARTRIDGE # RLS$FCT(HLR$FCTQ[0],0,STAT); HLR$FCTQ[0] = 0; # PREVENT A 2ND RELEASE # IF STAT EQ CMASTAT"NOERR" THEN BEGIN ACQ$FCT(TDAMFAM[0],TDAMSBF[0],HLR$SM[0], ## HLR$FCTXP[0],QADDR,0,STAT); END IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); GOTO DSERR; END P = QADDR + FCTQHL; # * UPDATE CARTRIDGE USAGE STATISTICS. * UPDATE *AST* AND THE PREAMBLE TO REFLECT THE SPACE NOW AVAILABLE. # UPUSAGE(HLRQADR,QADDR); UASTPRM(TDAMFAM[0],TDAMSBF[0],HLR$SM[0],QADDR,STAT); IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); RLS$FCT(QADDR,0,STAT); GOTO DSERR; END END # GET *FCT* ENTRY FOR PREVIOUS CARTRIDGE # CONTROL EJECT; # * STEP 7.4 - UPDATE LINK TO THIS VOLUME. # IF HLR$FVOL[0] THEN # SET LINKAGE IN *HLRQ* # BEGIN P = LOC(HLR$NEWASA[0]); ASASM[0] = HLR$SM[0]; ASAFCT[0] = HLR$FCTX[0]; ASAAU[0] = HLR$VOLAU[0]; END ELSE # SET LINKAGE IN PREVIOUS VOLUME # BEGIN SETFCTX(HLR$VOLAUP[0]); # SET *FWD* AND *FPS* VALUES # FCT$LINK(FWD,FPS) = HLR$VOLAU[0]; IF HLR$JOF[0] THEN BEGIN T1 = FCT$CLKOCL(FWD,FPS); FCT$OCLNK(T1) = HLR$FCTX[0]; END END CONTROL EJECT; # * STEP 7.5 - UPDATE BACKLINK INFORMATION. # HLR$VOLAUP[0] = HLR$VOLAU[0]; HLR$VOLLNP[0] = USED; # * STEP 7.6 - RESTORE NEW *FCT* ENTRY, IF APPROPRIATE. # IF HLR$JOF[0] THEN BEGIN RLS$FCT(QADDR,0,STAT); IF STAT EQ CMASTAT"NOERR" THEN BEGIN ACQ$FCT(TDAMFAM[0],TDAMSBF[0],HLR$SM[0], ## HLR$FCTX[0],QADDR,0,STAT); END IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); GOTO DSERR; END P = QADDR + FCTQHL; HLR$FCTQ[0] = QADDR; END CONTROL EJECT; # * STEP 7.7 - SET CORRECT VALUE IN *CC* FIELD. # IF HLR$FVOL[0] THEN BEGIN # FIRST OR ONLY VOLUME # IF ATEOI THEN BEGIN CC = CHAINCON"ONLY"; END ELSE BEGIN CC = CHAINCON"FIRST"; END END # FIRST OR ONLY VOLUME # ELSE BEGIN # MIDDLE OR LAST # IF ATEOI THEN BEGIN CC = CHAINCON"LAST"; END ELSE BEGIN CC = CHAINCON"MIDDLE"; END END # MIDDLE OR LAST # SETFCTX(HLR$VOLAU[0]); # SET *FWD* AND *FPS* VALUES # FCT$CC(FWD,FPS) = CC; # * STEP 7 - END. # CONTROL EJECT; # * STEP 8 - COMPLETE DESTAGING OF THIS FILE. # HLR$FVOL[0] = FALSE; IF NOT ATEOI THEN BEGIN GOTO NEXTVOL; END # * STEP 8.2 - WRITE *FCT* ENTRY TO DISK. # CPUTFCT(TDAMFAM[0],TDAMSBF[0],HLR$SM[0], ## HLR$FCTX[0],P,HLRQADR,STAT); IF STAT EQ 0 THEN BEGIN CFLUSH(TDAMFAM[0],TDAMSBF[0],HLRQADR,STAT); END IF STAT NQ 0 THEN BEGIN DSERCAT(HLRQADR,STAT); GOTO DSERR; END # * STEP 8.4 - ISSUE *SETASA* TO COMPLETE DESTAGE. # DS8A: # RETRY *SETASA* CALL # HLR$HPS[0] = DSLABEL"DS8A"; # IF WAIT CONDITION # NAMEC[0] = HLR$FLNM[0]; NAMEC[1] = TDAMFAM[0]; TDAMASA[0] = HLR$NEWASA[0]; TDAMAT[0] = ATAS; SETASA(NAME[0],STAT,6,TDAMUI[0],NAME[1],TDAMPFID[0], ## TDAMASI[0],TDAMCDT[0],LOC(PFMRET)); IF STAT NQ 0 THEN BEGIN DSERPFM(HLRQADR,STAT); IF HLR$RESP[0] NQ ERRST"NOERR" THEN BEGIN GOTO DSERR; END HLR$NEWASA[0] = 0; # CLEAR FOR NO FURTHER *FCT* RELEASE # END # * STEP 8 - END. # CONTROL EJECT; # * STEP 9 - RELEASE DISK SPACE, IF REQUESTED. # IF TDAMFC[0] EQ TDAMFCODE"DESTRLS" THEN BEGIN # DO RELEASE PROCESSING # DS9A: # RETRY *DROP(I)DS* CALL # HLR$HPS[0] = DSLABEL"DS9A"; # IF NEED TO RETRY *PFM* CALL # NAMEC[0] = HLR$FLNM[0]; NAMEC[1] = TDAMFAM[0]; IF TDAMIA[0] THEN # INDIRECT ACCESS FILE # BEGIN DROPIDS(NAME[0],STAT,6,TDAMUI[0],NAME[1], ## TDAMPFID[0],TDAMASI[0],TDAMCDT[0],LOC(PFMRET)); END ELSE # DIRECT ACCESS FILE # BEGIN DROPDS(NAME[0],STAT,6,TDAMUI[0],NAME[1], ## TDAMPFID[0],TDAMASI[0],TDAMCDT[0],LOC(PFMRET)); END IF STAT NQ 0 THEN BEGIN DSERPFM(HLRQADR,STAT); IF HLR$RESP[0] NQ ERRST"NOERR" THEN BEGIN # THE *ASA* IS SET, THE *FCT* SPACE MUST NOT BE RELEASED. # IF HLR$RESP[0] EQ ERRST"WAIT" THEN BEGIN HLR$RESP[0] = ERRST"NOERR"; DELAY(PFM$INTV,HLRQADR,HLRQIND); RETURN; END ELSE # REPORT ERROR, BUT DON-T RELEASE *FCT* SPACE. # BEGIN # SET *ASA* WORKED - LEAVE *FCT* IN TACK. # HLR$RESP[0] = ERRST"ABANDON"; GOTO STARTSTEP11; END END END END # DO RELEASE PROCESSING # HLR$TDAMFL[0] = HLR$PFC$LN[0]; # SET DAYFILE MESSAGE # # * STEP 9 - END. # CONTROL EJECT; # * STEP 10 - HANDLE ERRORS SPECIFIC TO THIS FILE. # DSERR: # ERROR CLEANUP # STAT = HLR$RESP[0]; IF STAT NQ ERRST"NOERR" THEN BEGIN # STEP 10 # IF STAT EQ ERRST"WAIT" THEN BEGIN HLR$RESP[0] = ERRST"NOERR"; DELAY(PFM$INTV,HLRQADR,HLRQIND); RETURN; END IF HLR$FCTQ[0] NQ 0 THEN # RELEASE ALLOCATED AU, IF ANY # BEGIN P = HLR$FCTQ[0] + FCTQHL; # RELEASE SPACE ON CURRENT CARTRIDGE. # START = HLR$1STVOL[0]; REPEAT WHILE START NQ 0 DO BEGIN SETFCTX(START); T1 = FCT$LINK(FWD,FPS); T2 = FCT$LEN(FWD,FPS) + 1; RLSVOL(HLRQADR,HLR$FCTQ,START,T2); P = HLR$FCTQ[0] + FCTQHL; START = T1; END P = HLR$FCTQ[0] + FCTQHL; RLSVOL(HLRQADR,HLR$FCTQ[0],HLR$VOLAU[0],HLR$VOLLN[0]); END # RELEASE PREVIOUS CARTRIDGE SPACE ON CURRENT FILE. # P = LOC(HLR$NEWASA[0]); # RECOVER FROM *ASA* IN *HLRQ*. # I = 0; # CLEAR FOR ERROR CHECK # IF ASAFCT[0] NQ HLR$FCTX[0] ## AND ASAFCT[0] NQ 0 THEN BEGIN # RELEASE THE FIRST SET OF CARTRIDGE SPACE # RLS$FCT(HLR$FCTQ[0],0,STAT); TEMP = ASAFCT[0]; START = ASAAU[0]; USED = ASAGP[0]; IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); GOTO DSERREND; END HLR$FCTQ[0] = 0; RLSTART: IF TEMP NQ HLR$FCTX[0] ## AND TEMP NQ 0 THEN BEGIN # START NEW FCT LOCATION # ACQ$FCT(TDAMFAM[0],TDAMSBF[0],HLR$SM[0],TEMP, ## QADDR,0,STAT); IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); I = 1; GOTO DSERREND; END P = QADDR + FCTQHL; UASTPRM(TDAMFAM[0],TDAMSBF[0],HLR$SM[0],QADDR,STAT); REPEAT WHILE START NQ 0 DO BEGIN TEMP1 = 0; SETFCTX(START); T1 = FCT$LINK(FWD,FPS); T2 = FCT$LEN(FWD,FPS) + 1; # CHECK FOR OFF-CARTRIDGE LINK # IF FCT$CLKOCL(FWD,FPS) NQ 0 THEN BEGIN # OFF-CARTRIDGE LINK # IF FCT$CLKOCL(FWD,FPS) EQ 1 THEN BEGIN B<0,1>FCT$OCLF[0] = 0; TEMP1 = USED * 16 + FCT$OCL[0]; END ELSE BEGIN IF FCT$CLKOCL(FWD,FPS) EQ 2 THEN BEGIN B<1,1>FCT$OCLF[0] = 0; TEMP1 = USED * 16 + FCT$OCL1[0]; END ELSE BEGIN B<2,1>FCT$OCLF[0] = 0; TEMP1 = USED * 16 + FCT$OCL2[0]; END END IF TEMP1 GR (PRM$ENTRC[HLR$SM[0]] + 15) ## OR TEMP1 LS 16 THEN BEGIN I = 1; GOTO DSERREND; END END RLSVOL(HLRQADR,QADDR,START,T2); P = QADDR + FCTQHL; START = T1; IF TEMP1 NQ 0 THEN BEGIN TEMP = TEMP1; P = QADDR + FCTQHL; UASTPRM(TDAMFAM[0],TDAMSBF[0],HLR$SM[0],QADDR,STAT); RLS$FCT(QADDR,0,STAT); IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); I = 1; GOTO DSERREND; END GOTO RLSTART; END END # END OF DO LOOP # P = QADDR + FCTQHL; UASTPRM(TDAMFAM[0],TDAMSBF[0],HLR$SM[0],QADDR,STAT); RLS$FCT(QADDR,0,STAT); IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); I = 1; GOTO DSERREND; END END # END OF NEW *FCT* LOACTION FIND # # RESET THE ORGINAL CURRENT CARTRIDGE FCT. # DSERREND: IF I NQ 0 # CHECK FOR AN ERROR IN ERROR CLEAN UP # THEN BEGIN MSG(MSGMB,UDFL1); IF HLR$FCTQ[0] EQ 0 # IF NO CARTRIDGE # THEN BEGIN GOTO CKSPECIAL; END END HLR$NEWASA[0] = 0; # CLEAR FOR FURTHER RECOVERY # IF HLR$FCTX[0] EQ 0 THEN BEGIN GOTO CKSPECIAL; END ACQ$FCT(TDAMFAM[0],TDAMSBF[0],HLR$SM[0],HLR$FCTX[0], ## QADDR,0,STAT); IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); HLR$AUSF[0] = 0; HLR$AULF[0] = 0; GOTO STARTSTEP11; END P = QADDR + FCTQHL; UASTPRM(TDAMFAM[0],TDAMSBF[0],HLR$SM[0],QADDR,STAT); HLR$FCTQ[0] = QADDR; END CKSPECIAL: IF HLR$ERRC[0] EQ ERRST"SPECIAL" THEN BEGIN # NO CARTRIDGE LOADED # HLR$AUSF[0] = 0; HLR$AULF[0] = 0; END # CARTRIDGE NO LOAD # END # STEP 10 # CONTROL EJECT; # * STEP 11 - COMPLETE THIS FILE AND PROCEED WITH NEXT ONE. * - RETURN FILE USED FOR DESTAGING. * - CALL *DSNTDAM* TO OBTAIN NEXT FILE TO DESTAGE. * - UPDATE *AST* TO REFLECT AVAILABLE AU, IF APPROPRIATE. * - SWITCH TO STAGING, IF APPROPRIATE. * - UNLOAD CARTRIDGE, IF NO MORE FILES FOR IT. * - UPDATE *FCT* TO REFLECT USAGE COUNTS. * - RELEASE INTERLOCKS ON SUBFAMILY CATALOGS. # STARTSTEP11: ZSETFET(LOC(SCR$FET[0]),HLR$FLNM[0],0,0,SFETL); # RETURN FILE # RETERN(SCR$FET[0],RCL); HLR$FFILE[0] = FALSE; DSNTDAM(HLRQADR); # * UPDATE THE *AST* IF DONE DESTAGING TO THIS CARTRIDGE. # FLAG = (HLR$UNLD[0]) OR (TDAMFC[0] EQ TDAMFCODE"NOREQ") OR (TDAMFC[0] EQ TDAMFCODE"STAGE"); IF (HLR$FCTQ[0] NQ 0) AND ## (FLAG OR (HLR$HPN[0] EQ HLRPN"STAGE" ) ) THEN # UPDATE THE *AST* # BEGIN P = HLR$FCTQ[0]; UASTPRM(FCTQFAMILY[0],FCTQSUBF[0],HLR$SM[0], ## HLR$FCTQ[0],STAT); IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); END END # * IF THIS *HLRQ* IS TO BE USED TO DO STAGING FROM THIS CARTRIDGE, * TRANSFER CONTROL TO *STAGER*. # IF HLR$HPN[0] EQ HLRPN"STAGE" THEN BEGIN IF DSC$LKMSK NQ 0 THEN BEGIN CRELSLK(DSC$FAM,DSC$LKMSK,0,STAT); DSC$LKMSK = 0; END RETURN; END # * EXIT IF NEXT FILE IS TO GO TO THIS CARTRIDGE. # IF NOT FLAG THEN # DESTAGE NEXT FILE TO SAME CARTRIDGE # BEGIN ADD$LNK(HLRQADR,LCHN"HL$READY",0); RETURN; END IF HLR$FCTQ[0] NQ 0 THEN # RELEASE *FCT* ENTRY # BEGIN P = HLR$FCTQ[0]; UPUSAGE(HLRQADR,HLR$FCTQ[0]); RLS$FCT(HLR$FCTQ[0],0,STAT); IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); END HLR$FCTQ[0] = 0; HLR$FCTX[0] = 0; END # * UNLOAD CARTRIDGE IF ONE WAS SUCCESSFULLY LOADED. # IF HLR$HLRQW[0] NQ 0 THEN BEGIN # SWITCH CONTROL OF *DRD* TO WAITTING *HLRQ* # TEMP = HLR$DRDRA[0]; TEMP1 = HLR$LRQADR[0]; P = HLR$HLRQW[0]; HLR$DRDRA[0] = TEMP; HLR$LRQADR[0] = TEMP1; IF HLR$LRQADR[0] EQ 0 THEN BEGIN # TELL NEXT HLRQ CARTRIDGE LOADED BAD # HLR$RESP[0] = ERRST"TEMP"; END P = HLRQADR; ADD$LNK(HLR$HLRQW[0],LCHN"HL$READY",0); P = HLR$LRQADR[0]; LLR$UCPRA[0] = HLR$HLRQW[0]; # INSURE PPU POINTS TO NEW *HLRQ* # P = HLR$DRDRA[0]; RESETDRD = HLR$HLRQW[0]; HLR$HLRQW[0] = 0; HLR$DRDRA[0] = 0; HLR$LRQADR[0] = 0; END IF HLR$LRQADR[0] NQ 0 THEN BEGIN # DO UNLOAD OF CARTRIDGE # P = HLR$LRQADR[0]; MSGAFDF("I","UL",0,HLRQADR); LLR$DR[0] = ERRST"NOERR"; LLR$PRCNME[0] = REQTYP4"UNLD$CART"; LLR$PRCST[0] = PROCST"INITIAL"; HLR$HPS[0] = DSLABEL"DS11A"; ADD$LNK(HLR$LRQADR[0],LCHN"LL$READY",0); RETURN; DS11A: # RETURN FROM UNLOAD OF CARTRIDGE # IF HLR$RESP[0] NQ RESPTYP4"OK4" THEN BEGIN # * PROCESS UNLOAD CARTRIDGE ERROR AS FOLLOWS: * -DRIVER PLACED ORIGINAL CARTRIDGE IN OUTPUT STATION. * -ASSUME A SECOND CARTRIDGE WAS IN DESTINATION CELL. * -ATTEMPT TO MOVE THIS 2ND CARTRIDGE TO THE OUTPUT * STATION BY LOADING IT. * -IF THE LOAD SUCCEEDS, DO A SECOND UNLOAD BACK TO * THE ORIGINAL DESTINATION. # HLLDSET((HLRQADR)); # SET UP SECOND LOAD # HLR$HPS[0] = DSLABEL"DS11B"; RETURN; DS11B: # RETURN FROM SECOND LOAD # IF HLR$RESP[0] EQ RESPTYP4"OK4" THEN # UNLOAD 2ND CARTRIDGE # BEGIN LLR$PRCNME[0] = REQTYP4"UNLD$CART"; LLR$PRCST[0] = PROCST"INITIAL"; HLR$HPS[0] = DSLABEL"DS11C"; ADD$LNK(HLR$LRQADR[0],LCHN"LL$READY",0); RETURN; DS11C: END # UNLOAD OF 2ND REQUEST # END # LOAD OF 2ND REQUEST # P = HLR$DRDRA[0]; CLN = 0; HLR$DRDRA[0] = 0; END # PHYSICAL CARTRIDGE UNLOAD # HLR$UNLD[0] = FALSE; IF DSC$LKMSK NQ 0 THEN # TIME TO RELEASE INTERLOCKS # BEGIN CRELSLK(DSC$FAM,DSC$LKMSK,0,STAT); DSC$LKMSK = 0; END ENDALL: IF TDAMFC[0] EQ TDAMFCODE"STAGE" THEN BEGIN # *DSNTDAM* PROC FOUND NO ROOM - DO NOT RECALL DESTAGE ROUTINE # DSC$INIT = 0; DSC$WRESRS = 1; HLR$HPS[0] = PROCST"COMPLETE"; RETURN; END IF TDAMFC[0] NQ TDAMFCODE"NOREQ" THEN BEGIN HLR$HPS[0] = PROCST"INITIAL"; ADD$LNK(HLRQADR,LCHN"HL$READY",0); END ELSE BEGIN HLR$HPS[0] = PROCST"COMPLETE"; DSC$INIT = 1; END # * END STEP 11. # RETURN; END # DESTAGR # TERM PROC DSALLO((HLRQADR)); # TITLE DSALLO - ALLOCATE A VOLUME ON A M860 CARTRIDGE. # BEGIN # DSALLO # # ** DSALLO - ALLOCATE A VOLUME ON A M860 CARTRIDGE. * * AN INITIAL CALL TO *DSALLO* SELECTS THE STORAGE MODULE * (*SM*), CARTRIDGE GROUP, SPECIFIC CARTRIDGE, AND FIRST * VOLUME TO USE ON THAT CARTRIDGE. * ON SUBSEQUENT CALLS, *DSALLO* WILL ASSIGN ADDITIONAL * VOLUMES ON THE SAME CARTRIDGE. IN A CARTRIDGE OVERFLOW * SITUATION, NEW CARTRIDGES IN THE SAME GROUP AS THE FIRST * CARTRIDGE WILL BE ASSIGNED IN ORDER TO ACQUIRE THE M860 * SPACE NECESSARY TO DESTAGE A LONG FILE. * * PROC DSALLO((HLRQADR)) * * ENTRY (HLRQADR) - ADDRESS OF THE *HLRQ* ENTRY FOR A * DESTAGE REQUEST. * (HLR$FFILE) - IF FIRST FILE OF A SEQUENCE OF FILES. * (HLR$FVOL) - IF FIRST VOLUME OF A FILE. * (HLR$PRU) - NUMBER OF PRU DESTAGED SO FAR. * (HLR$SH) - TRUE IF SHORT FILE. * (HLR$TDAM) - HAS FAMILY, SUBFAMILY, FILE LENGTH. * (HLR$XXX) - WHERE XXX REFERS TO THE FIELDS SET BY * THE INITIAL CALL TO *DSALLO* WHICH * SELECTED A CARTRIDGE. * (HLR$VOLAUP) - ID OF PREVIOUS VOLUME IF *FVOL* IS FALSE. * TOTAL AU NEEDED FOR SHORT FILES IF * *FFILE* AND *FVOL* ARE TRUE. * * EXIT (HLR$CCOD) - IDENTIFIES SELECTED CARTRIDGE. * (HLR$CSND) - IDENTIFIES SELECTED CARTRIDGE. * (HLR$SM) - IDENTIFIES *SM* CONTAINING CARTRIDGE. * (HLR$FCTQ) - *FCT* QUEUE ENTRY FOR CARTRIDGE. * (HLR$Y/Z) - CUBICLE LOCATION OF SELECTED CARTRIDGE. * (HLR$FCTX) - *FCT* INDEX OF CARTRIDGE. * (HLR$VOLAU) - FIRST *AU* OF ALLOCATED VOLUME. * (HLR$VOLLN) - NUMBER OF *AU* IN ALLOCATED VOLUME. * (HLR$LOAD) - SAYS TO LOAD A NEW CARTRIDGE. * (HLR$UNLD) - SAYS TO UNLOAD AN OLD CARTRIDGE. * (HLR$JOF) - SAYS A CARTRIDGE OVERFLOW JUST OCCURRED. * (HLR$RESP) - =0, REQUEST SATISFIED WITHOUT ERROR. * =N, N IDENTIFIES THE ERROR ACTION. * (HLR$ERRC) - REASON FOR ABANDONING A DESTAGE. # # ** NOTES ABOUT THE LOGIC USED IN *DSALLO*. * * THE SPECIFIC PROCESSING DONE BY *DSALLO* ON A GIVEN CALL * DEPENDS UPON WHICH OF FOUR (4) CASES EXISTS AT THE TIME OF * THE CALL TO *DSALLO*. * * CASE A) INITIAL CALL (FIRST VOLUME OF THE FIRST FILE OF * A SEQUENCE OF FILES) IN A CARTRIDGE OVERFLOW SITUATION * (FIRST FILE IS A LONG FILE). * * *DSALLO* SELECTS A *SM*, GROUP, INITIAL CARTRIDGE IN * THE GROUP, AND A VOLUME ON THE CARTRIDGE. * * * CASE B) INITIAL CALL IN A NON-OVERFLOW SITUATION (FIRST * FILE IS A SMALL FILE OR A LONG FILE WHICH IS EXPECTED * TO FIT ON ONE CARTRIDGE). * * *DSALLO* SELECTS A *SM*, SPECIFIC CARTRIDGE, AND A * VOLUME ON THAT CARTRIDGE. * * * CASE C) SUBSEQUENT CALL TO CASE A) - TO SELECT THE NEXT * CARTRIDGE IN THE GROUP AND ASSIGN A VOLUME ON THIS * NEW CARTRIDGE. * * * CASE D) SUBSEQUENT CALL TO CASES A), B) OR C) FOR THE FIRST * FILE OF A SEQUENCE, OR ANY CALL FOR OTHER THAN THE * FIRST FILE OF A SEQUENCE. IN THIS CASE, *DSALLO* * ASSIGNS A VOLUME FROM THE LAST SELECTED CARTRIDGE. * * * THE FOLLOWING LOGIC STEPS ARE CONDITIONALLY EXECUTED * DEPENDING UPON THE CASE WHICH EXISTS FOR THIS CALL. * * STEP IF CASE ACTION * * 1 (A,B) SELECT A STORAGE MODULE. * * 1 (C,D) DETERMINE WHETHER CASE C OR D EXISTS. * ITS CASE C) IF ITS THE FIRST FILE, A LONG FILE, * AND NO SPACE IS LEFT. ITS CASE D) OTHERWISE. * * 2 (A,B,C) READ IN THE *AST* FOR THE *SM* FROM STEP 1. * * 3 (A,B) PICK A CARTRIDGE IF ONE WILL HOLD THE FIRST * FILE (DETERMINES CASE B), OR PICK A CARTRIDGE * GROUP (DETEMINES CASE A). * * 4 (A,C) SELECT A CARTRIDGE IN THE GROUP. * * 5 (C) UPDATE OFF-CARTRIDGE LINK. * .1) UPDATE THE *FCT* FOR THE PREVIOUS CARTRIDGE * TO LINK TO THIS NEW CARTRIDGE. * .2) SET THE FLAG TO CAUSE AN UNLOAD OF OLD CARTRIDGE. * .3) WRITE THE *FCT* ENTRY FOR THE OLD CARTRIDGE TO * DISK. * * 6 (A,B,C) DO SETUP FOR NEW CARTRIDGE. * .1) GET *FCT* ENTRY FOR NEW CARTRIDGE. * .2) VERIFY THAT THE *FCT* AND *AST* ENTRIES FOR * THIS CARTRIDGE ARE IN SYNC. * .3) SET *HLR$FCTQ* FIELD TO POINT TO NEW *FCT* ENTRY. * .4) SET THE *HLRQ* FIELDS IDENTIFYING THE AMOUNT OF * SPACE LEFT ON THIS CARTRIDGE FOR * AND LONG FILES. * .5) SET FLAG TO LOAD THIS NEW CARTRIDGE. * * 7 (ALL) ALLOCATE A VOLUME OF AVAILABLE SPACE ON THIS CARTRIDGE. * # # * NOTES ABOUT THE ALLOCATION STRATEGY. * * 1. ONE ALLOCATION OBJECTIVE IS TO ALLOCATE ENOUGH EXTRA * AU TO PROVIDE SOME CONTINGENCY IN CASE SOME STRIPES * ARE DEMARKED. INSTALLATION PARAMETERS *CONTG$ADD* * AND *CONTG$PER* DEFINE THE NUMBER OF EXTRA STRIPES * TO HOPEFULLY BE PROVIDED BY THE ALLOCATION PROCESS. * IF THESE EXTRA STRIPES (AU) ARE NOT AVAILABLE, * ALLOCATION WILL PROCEED WITHOUT ANY EXTRA STRIPES. * * 2. IF A CARTRIDGE IS SELECTED BASED ON ITS *AST* ENTRY, BUT * ITS *FCT* ENTRY THEN INDICATES THE CARTRIDGE IS UNUSABLE, * THE *AST* AND PREAMBLE ARE UPDATED TO REFLECT THIS * NEW CARTRIDGE STATUS. THE ALLOCATION PROCESS THEN * REPEATS IN AN EFFORT TO FIND ANOTHER CARTRIDGE. # ITEM HLRQADR I; # *HLRQ* ADDRESS # # **** PROC DSALLO - XREF LIST BEGIN. # XREF BEGIN PROC ACQ$FCT; # ACQUIRE *FCT* ENTRY # PROC ANLZAST; # IDENTIFY BEST CARTRIDGE AND GROUP # PROC CRDAST; # READ AST TO MEMORY # PROC DSERCAT; # PROCESS CATALOG ERRORS # PROC OCTSRCH; # OPEN CATALOG SEARCH # PROC RLSVOL; # RELEASE UNUSED AU # PROC RLS$FCT; # RELEASE *FCT* ENTRY # PROC UASTPRM; # UPDATE *AST* AND PREAMBLE # END # **** PROC DSALLO - XREF LIST END. # DEF LISTCON #0#; # DO NOT LIST COMMON DECKS # *CALL,COMBFAS *CALL COMBCHN *CALL,COMBCMD *CALL,COMBCMS *CALL,COMBMCT *CALL,COMBSIT *CALL,COMBTDM *CALL,COMBUDT *CALL,COMXFCQ *CALL,COMXHLR *CALL,COMXMSC ITEM AU$FILE I; # AU NEEDED FOR REST OF CURRENT FILE # ITEM AU$MAX I; # AU NEEDED FOR ALL SHORT FILES # ITEM CASE$A B; # IDENTIFIES CASE A # ITEM CASE$B B; # IDENTIFIES CASE B # ITEM CASE$C B; # IDENTIFIES CASE C # ITEM CASE$D B; # IDENTIFIES CASE D # ITEM DELTAAU I; # LOOP INDEX # ITEM EXTRAAU U; # NUMBER OF CONTINGENCY AU # ITEM FCTQADDR U; # FCTQ ADDRESS # ITEM FCTX I; # *FCT* INDEX OF BEST CANDIDATE # ITEM GRX I; # GROUP INDEX OF BEST CANDIDATE # ITEM GRSZ I; # SIZE OF BEST GROUP # ITEM I I; # LOOP INDEX # ITEM MAXC I; # CAPACITY OF BEST CARTRIDGE # ITEM MAXGR I; # CAPACITY OF BEST GROUP # ITEM MAXVOLLN U = 128; # REM (SB 128) MAXIMUM VOLUME LENGTH # ITEM NOTDONE B; # LOOP TERMINATOR # ITEM QADDR I; # ADDRESS OF *FCT* ENTRY # ITEM STAT I; # STATUS # ITEM SM I; # INDEX OF BEST STORAGE MODULE # ITEM SMGR I; # INDEX OF *SM* WITH BEST GROUP # ITEM SMOFF B; # STATUS INDICATOR # ITEM TMP1 I; # TEMPORARY VARIABLE # CONTROL EJECT; # * INITIALIZE FIELDS. # P = HLRQADR; P = LOC(HLR$TDAM[0]); P = HLR$FCTQ[0] + FCTQHL; HLR$JOF[0] = FALSE; HLR$VOLAU[0] = 0; HLR$VOLLN[0] = 0; # * CALCULATE NECESSARY AU AND A CONTINGENCY AMOUNT. # TMP1 = 1 + (TDAMFLN[0] - HLR$PRU[0]-1)/INPRUS; AU$FILE = 1 + (TMP1-1)/INSPAU; # NECESSARY AU # TMP1 = TMP1 + CONTG$ADD + (TMP1*CONTG$PER -1)/100 + 1; EXTRAAU = 1 + (TMP1-1)/INSPAU - AU$FILE; TRYAGAIN: # USED IF SELECTED CARTRIDGE IS UNUSABLE # CASE$A = FALSE; CASE$B = FALSE; CASE$C = FALSE; CASE$D = FALSE; # * STEP 1 (CASE A OR B) - SELECT A STORAGE MODULE. * (CASE C OR D) - DETERMINE WHETHER CASE C OR D. # IF NOT (HLR$FFILE[0] AND HLR$FVOL[0]) THEN # CASE C OR D # BEGIN # STEP 1CD # CASE$C = HLR$JOF[0] OR ## ( NOT HLR$SH[0] ## AND (FCT$FAULF[0] EQ 0) ## AND HLR$FFILE[0] ## ); CASE$D = NOT CASE$C; FCTX = HLR$FCTX[0]; END # STEP 1CD # ELSE # CASE A OR B # CONTROL EJECT; BEGIN # STEP 1AB # CASE$A = TRUE; # DECIDE A OR B IN STEP 3 # HLR$AUSF[0] = 0; HLR$AULF[0] = 0; OCTSRCH(TDAMFAM[0],TDAMSBF[0],TMP1,HLRQADR,STAT); IF STAT NQ CMASTAT"NOERR" THEN BEGIN # *OCTSRCH* ERROR # IF STAT EQ CMASTAT"INTLK" THEN BEGIN HLR$RESP[0] = ERRST"WAIT"; RETURN; END ELSE BEGIN DSERCAT(HLRQADR,STAT); RETURN; END END # *OCTSRCH* ERROR # P = OCT$PRMA[TMP1]; # * STEP 1.2 - CALCULATE AU NEEDED AND PREPARE TO SEARCH * FOR THE BEST *SM*. # AU$MAX = HLR$VOLAUP[0]; # FROM *NXTDEST* # SM = 0; SMGR = 0; P = UDTSADR; CONTROL EJECT; # * STEP 1.3 - SEARCH PREAMBLE TO FIND STORAGE MODULE. # FOR DELTAAU = EXTRAAU STEP -1 WHILE SM EQ 0 DO BEGIN # *SM* CONTINGENCY LOOP # IF DELTAAU LS 0 THEN # NOT ENOUGH SPACE # BEGIN HLR$RESP[0] = ERRST"ABANDON"; HLR$ERRC[0] = ABANDON"NOSPACE"; RETURN; END MAXC = AU$FILE + DELTAAU -1; MAXGR = MAXC; SMOFF = TRUE; FOR I = 1 STEP 1 UNTIL MAXSMUNIT DO BEGIN # *SM* SEARCH # TMP1 = SM$ID[I]; IF PRM$SCW1[TMP1] EQ 0 THEN # *SM* NOT ASSIGNED TO SUBFAMILY # BEGIN TEST I; END IF (SM$HWOFF[I] OR NOT SM$ON[I]) ## OR (SM$DSNUM[I] EQ 0) ## OR (NOT D0$ON[I] AND NOT D1$ON[I]) THEN # *SM*/*DRD* NOT USABLE # BEGIN TEST I; END ELSE # *SM* ASSIGNED AND USABLE # BEGIN SMOFF = FALSE; END IF HLR$SH[0] AND (PRM$MXAUS[TMP1] GR MAXC) THEN # FOUND *SM* WITH BETTER CARTRIDGE FOR SHORT FILES # BEGIN SM = TMP1; MAXC = PRM$MXAUS[TMP1]; TEST I; END IF NOT HLR$SH[0] AND (PRM$MXAUGR[TMP1] GR MAXC) THEN BEGIN # CONSIDER CARTRIDGE OR GROUP SIZE # IF PRM$MXAUL[TMP1] GR MAXC THEN # CONSIDER INDIVIDUAL CARTRIDGE # BEGIN MAXC = PRM$MXAUL[TMP1]; SM = TMP1; END ELSE # CONSIDER GROUP SIZE # BEGIN IF PRM$MXAUGR[TMP1] GR MAXGR THEN BEGIN MAXGR = PRM$MXAUGR[TMP1]; SMGR = TMP1; END END END # CONSIDER CARTRIDGE OR GROUP SIZE # END # *SM* SEARCH # IF SMOFF THEN # NO *SM* AVAILABLE # BEGIN HLR$RESP[0] = ERRST"ABANDON"; HLR$ERRC[0] = ABANDON"NOSM"; RETURN; END # * MAKE FINAL *SM* DECISION. # IF SM EQ 0 THEN # TRY *SM* WITH BEST GROUP # BEGIN SM = SMGR; END END # *SM* CONTINGENCY LOOP # HLR$SM[0] = SM; END # STEP 1AB # CONTROL EJECT; # * STEP 2 ( CASE A, B OR C) - READ IN *AST*. # IF NOT CASE$D THEN # CASE A, B OR C # BEGIN # STEP 2 # CRDAST(TDAMFAM[0],TDAMSBF[0],HLR$SM[0],ASTBADR,HLRQADR,STAT); IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); RETURN; END P = ASTBADR; END # STEP 2 # CONTROL EJECT; # * STEP 3 (CASE A OR B) - PICK CARTRIDGE (CASE B) OR * PICK GROUP (CASE A). # IF CASE$A THEN BEGIN # STEP 3 # FCTX = 0; FOR DELTAAU = EXTRAAU STEP -1 WHILE FCTX EQ 0 DO BEGIN # *AST* CONTINGENCY LOOP # IF DELTAAU LS 0 THEN # NO SPACE # BEGIN HLR$RESP[0] = ERRST"ABANDON"; HLR$ERRC[0] = ABANDON"NOCARGP"; RETURN; END IF HLR$SH[0] THEN # FIND CARTRIDGE FOR SHORT FILES # BEGIN GRX = 0; ANLZAST(HLR$SM[0],AU$MAX,0,FCTX,DUMMY,DUMMY,DUMMY); IF FCTX NQ 0 ## AND (AST$AUSF[FCTX] LS AU$FILE) THEN # FILE DOES NOT FIT # BEGIN FCTX = 0; END END ELSE # FIND CARTRIDGE OR GROUP FOR LONG FILES # BEGIN ANLZAST(HLR$SM[0],0,AU$FILE+DELTAAU,DUMMY,FCTX,GRX,GRSZ); END IF FCTX NQ 0 THEN # CASE B # BEGIN CASE$B = TRUE; CASE$A = FALSE; END ELSE # CASE A OR NO SPACE # BEGIN IF GRX NQ 0 THEN # CASE A # BEGIN CASE$A = TRUE; FCTX = GRX*MAXGRT; END END END # *AST* CONTINGENCY LOOP # END # STEP 3 # CONTROL EJECT; # * STEP 4 (CASE A OR C) - PICK CARTRIDGE IN GROUP. # IF CASE$A OR CASE$C THEN BEGIN # STEP 4 # GRX = (FCTX/MAXGRT)*MAXGRT; FCTX = 0; MAXC = 0; FOR DELTAAU = EXTRAAU STEP -1 WHILE FCTX EQ 0 DO BEGIN # CARTRIDGE CONTINGENCY LOOP # IF DELTAAU LS 0 THEN # NO SPACE # BEGIN HLR$RESP[0] = ERRST"ABANDON"; HLR$ERRC[0] = ABANDON"GRFULL"; RETURN; END FOR I = 0 STEP 1 UNTIL MAXGRT-1 DO BEGIN # SEARCH GROUP FOR BEST CARTRIDGE # IF (GRX+I EQ HLR$FCTX[0]) THEN # DO NOT PICK THIS CARTRIDGE # BEGIN TEST I; END TMP1 = AST$AULF[GRX+I]; IF ((TMP1 LS AU$FILE+DELTAAU) ## AND AST$NOCLF[GRX+I]) ## OR NOT AST$AAF[GRX+I] THEN # CARTRIDGE NOT USABLE # BEGIN TEST I; END IF TMP1 GR MAXC THEN # PICK THIS CARTRIDGE # BEGIN FCTX = GRX+I; MAXC = TMP1; END END # SEARCH FOR BEST CARTRIDGE # END # CARTRIDGE CONTINGENCY LOOP # END # STEP 4 # CONTROL EJECT; # * STEP 5 (CASE C) - PREPARE FOR CARTRIDGE OVERFLOW. * .1 SET FLAG TO UNLOAD OLD CARTRIDGE. * .2 FORCE *FCT* FOR PREVIOUS CARTRIDGE TO DISK. * .3 SET JUST OVERFLOWED FLAG IN *HLRQ* ENTRY. # IF CASE$C AND (NOT HLR$JOF[0]) THEN BEGIN # STEP 5 # HLR$FCTXP[0] = HLR$FCTX[0]; HLR$CSNTPS[0] = HLR$CSNTCU[0]; # * SELECT AN AVAILABLE *OCL* FIELD IN THE *FCT* HEADER * AND UPDATE THE PREVIOUS VOLUME TO LINK TO THE NEW * CARTRIDGE VIA THIS *OCL* FIELD. # NOTDONE = TRUE; FOR I = 0 STEP 1 WHILE NOTDONE DO BEGIN # SET LINK TO NEW CARTRIDGE # IF I EQ 3 THEN # NO OFF-CARTRIDGE LINK AVAILABLE # BEGIN HLR$RESP[0] = ERRST"ABANDON"; HLR$ERRC[0] = ABANDON"NOOVERF"; RETURN; END IF BFCT$OCLF[0] EQ 1 THEN # THIS LINK FIELD IN USE # BEGIN TEST I; END # * HAVING FOUND AN AVAILABLE LINK, UPDATE THE * LINKAGE TO THE NEW CARTRIDGE. # BFCT$OCLF[0] = 1; SETFCTX(HLR$VOLAUP[0]); FCT$CLKOCL(FWD,FPS) = I+1; NOTDONE = FALSE; END # SET LINK TO NEW CARTRIDGE # # * COMPLETE REST OF STEP 5. # HLR$UNLD[0] = TRUE; HLR$JOF[0] = TRUE; HLR$1STVOL[0] = 0; # INDICATE O VOLUMES TO RELEASE # RLS$FCT(HLR$FCTQ[0],0,STAT); IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); RETURN; END END # STEP 5 # CONTROL EJECT; # * STEP 6 (CASE A, B OR C) - DO NEW CARTRIDGE SETUP. * * .1 GET *FCT* ENTRY. * .2 VERIFY *FCT* AND *AST* ENTRIES AGREE. * .3 COMPLETE SETUP. # IF NOT CASE$D THEN BEGIN # STEP 6 # FCTQADDR = CHN$BOC[LCHN"FCT$FRSPC"]; IF FCTQADDR EQ 0 THEN BEGIN HLR$RESP[0] = ERRST"SPECIAL"; RETURN; END ACQ$FCT(TDAMFAM[0],TDAMSBF[0],HLR$SM[0],FCTX,QADDR,0, STAT); IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); RETURN; END P = QADDR + FCTQHL; IF FCT$LCF[0] OR FCT$EEF[0] OR FCT$IAF[0] THEN # CLEAR ALLOCATION AUTHORIZED FLAG IN *AST* ENTRY # BEGIN AST$AAF[FCTX] = FALSE; UASTPRM(TDAMFAM[0],TDAMSBF[0],HLR$SM[0],0,STAT); RLS$FCT(QADDR,0,TMP1); IF STAT NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,STAT); RETURN; END IF TMP1 NQ CMASTAT"NOERR" THEN BEGIN DSERCAT(HLRQADR,TMP1); RETURN; END GOTO TRYAGAIN; # TRY FOR ANOTHER CARTRIDGE/GROUP/SM # END HLR$FCTQ[0] = QADDR; CONTROL EJECT; # * STEP 6.3 - COMPLETE SETUP. # HLR$FCTX[0] = FCTX; HLR$AUSF[0] = AST$AUSF[FCTX]; HLR$AULF[0] = AST$AULF[FCTX]; HLR$LOAD[0] = TRUE; HLR$CSND[0] = FCT$CSND[0]; HLR$CCOD[0] = FCT$CCOD[0]; HLR$Z[0] = FCT$Z[0]; HLR$Y[0] = FCT$Y[0]; END # STEP 6 # CONTROL EJECT; # * STEP 7 (ALL CASE$S) - ALLOCATE A VOLUME. # IF HLR$SH[0] THEN # USE *AU* FOR SHORT FILES # BEGIN TMP1 = FCT$FAUSF[0]; END ELSE # USE *AU* FOR LONG FILES # BEGIN TMP1 = FCT$FAULF[0]; END IF TMP1 EQ 0 THEN # NO SPACE LEFT # BEGIN RETURN; END SETFCTX(TMP1); HLR$VOLAU[0] = TMP1; # * CALCULATE AU NEEDED IN THIS VOLUME (MAX OF MAXVOLLN). # AU$FILE = AU$FILE + EXTRAAU; IF AU$FILE GR MAXVOLLN THEN BEGIN AU$FILE = MAXVOLLN; END # * CONCATENATE ADJACENT FREE VOLUMES INTO ONE LARGER * VOLUME. IF THE TOTAL EXCEEDS MAXVOLLN AU, RELEASE THE * EXTRA AU SO THE FINAL VOLUME IS MAXVOLLN AU. # NOTDONE = TRUE; FOR I = 0 WHILE NOTDONE DO BEGIN HLR$VOLLN[0] = HLR$VOLLN[0] + FCT$LEN(FWD,FPS) + 1; TMP1 = FCT$LINK(FWD,FPS); IF (HLR$VOLLN[0] GQ AU$FILE ) ## OR ( HLR$VOLAU[0] + HLR$VOLLN[0] NQ TMP1 ) THEN # NO MORE CONCATENATION POSSIBLE/NEEDED # BEGIN NOTDONE = FALSE; TEST I; END # * ADD NEXT FREE VOLUME INTO THE ONE TO BE USED. # SETFCTX(TMP1); TEST I; END # * UPDATE POINTER TO FREE SPACE TO REFLECT SELECTION * OF THE ABOVE SELECTED *AU*. # EXTRAAU = 0; IF HLR$VOLLN[0] GR MAXVOLLN THEN BEGIN EXTRAAU = HLR$VOLLN[0] - MAXVOLLN; HLR$VOLLN[0] = MAXVOLLN; END IF HLR$SH[0] THEN BEGIN FCT$FAUSF[0] = TMP1; HLR$AUSF[0] = HLR$AUSF[0] - HLR$VOLLN[0] - EXTRAAU; END ELSE BEGIN FCT$FAULF[0] = TMP1; HLR$AULF[0] = HLR$AULF[0] - HLR$VOLLN[0] - EXTRAAU; END # * AFTER DONE WITH CONCATENATION, RELEASE EXTRA AU. # RLSVOL(HLRQADR,HLR$FCTQ[0],HLR$VOLAU[0]+MAXVOLLN,EXTRAAU); # * STEP 7 END. # RETURN; END # DSALLO # TERM PROC DSERCAT((HLRQADR),(ERRSTAT)); # TITLE DSERCAT - PROCESS DESTAGE CATALOG ACCESS ERRORS. # BEGIN # DSERCAT # # ** DSERCAT - PROCESS DESTAGE CATALOG ACCESS ERRORS. * * *DSERCAT* VERIFIES THAT THE ERROR RESPONSES FROM CATALOG * ACCESS ROUTINES ARE EXPECTED ONES. IF SO, AN APPROPRIATE * ERROR CODE IS RETURNED TO THE *HLRQ*. IF NOT, AN ABORT IS DONE. * * PROC DSERCAT((HLRQADR)) * * ENTRY (HLRQADR) - ADDRESS OF *HLRQ* ENTRY FOR DESTAGE * REQUEST. * (ERRSTAT) - ERROR STATUS RETURNED BY A CATALOG * ACCESS REQUEST. * * EXIT (HLR$RESP) - ERROR STATE. * (VALUES DEFINED IN *COMXMSC*) * = ERRST"ABANDON". * * MESSAGES * EXEC ABNORMAL, DSERCAT.* # ITEM HLRQADR U; # *HLRQ* ENTRY ADDRESS # ITEM ERRSTAT I; # CATALOG ACCESS ERROR CODE # # **** PROC DSERCAT - XREF LIST BEGIN. # XREF BEGIN PROC ABORT; # ABORT # PROC MESSAGE; # ISSUE MESSAGE # END # **** PROC DSERCAT - XREF LIST END. # DEF LISTCON #0#; # DO NOT LIST COMMON DECKS # *CALL,COMBFAS *CALL,COMBCMS *CALL,COMBTDM *CALL,COMXHLR *CALL,COMXMSC P = HLRQADR; IF ERRSTAT EQ CMASTAT"CIOERR" THEN # IF READ/WRITE ERROR # BEGIN HLR$RESP[0] = ERRST"ABANDON"; HLR$ERRC[0] = ABANDON"CATIOERR"; RETURN; END FE$RTN[0] = "DSERCAT."; # ABORT ON FATAL ERROR # MESSAGE(FEMSG,UDFL1); ABORT; END TERM PROC DSERPFM((HLRQADR),(ERRSTAT)); # TITLE DSERPFM - PROCESS DESTAGE *PFM* ERRORS. # BEGIN # DSERPFM # # ** DSERPFM - PROCESS DESTAGE *PFM* ERRORS. * * *DSERPFM* PROCESSES ERROR RESPONSES RETURNED TO *DESTAGR* FROM * *PFM* AND RETURNS A STATUS IN THE *HLRQ* ENTRY OF THE * DESTAGE REQUEST. * * PROC DSERPFM((HLRQADR),(ERRSTAT)) * * ENTRY (HLRQADR) - ADDRESS OF *HLRQ* ENTRY FOR DESTAGE * REQUEST. * (ERRSTAT) - *PFM* ERROR CODE. * * EXIT (HLR$RESP) - ERROR STATE. * (VALUES DEFINED IN *COMXMSC*) * = ERRST"NOERR". * = ERRST"WAIT". * = ERRST"ABANDON". * * IF THE ERROR STATE INDICATES A DELAY CONDITION * (*ERRST"WAIT"*) THEN THE DESTAGE REQUEST HAS BEEN * ADDED TO THE *HLRQ* DELAY CHAIN AND WILL BE PUT * BACK ON THE *HLRQ* READY CHAIN AFTER A DELAY TIME * HAS EXPIRED. * * MESSAGES * EXEC ABNORMAL, DSERPFM.* # ITEM HLRQADR U; # *HLRQ* ENTRY ADDRESS # ITEM ERRSTAT I; # *PFM* ERROR CODE # # **** PROC DSERPFM - XREF LIST BEGIN. # XREF BEGIN PROC ABORT; # ABORT # PROC DELAY; # TIMED DELAY # PROC MESSAGE; # ISSUE MESSAGE # PROC PFMEC; # CONVERT *PFM* ERROR RESPONSE # END # **** PROC DSERPFM - XREF LIST END. # DEF LISTCON #0#; # DO NOT LIST COMMON DECKS # *CALL,COMBFAS *CALL,COMBTDM *CALL,COMXHLR *CALL,COMXIPR *CALL,COMXMSC *CALL,COMSPFM ITEM ACTION I; # ERROR PROCESSING ACTION # SWITCH DPFMER:ERRST # DESTAGE ERROR STATES # DPNOERR:NOERR, # NO ERROR # DPDELAY:WAIT, # DELAY CONDITION # DPFATAL:FATAL, # FATAL ERROR # DPFATAL:RESTART, # RESPONSE INVALID FROM *PFMEC* # DPFATAL:PERM, # RESPONSE INVALID FROM *PFMEC* # DPABAN:ABANDON, # ABANDON DESTAGE # DPSPEC:SPECIAL; # SPECIAL CONDITION # CONTROL EJECT; P = HLRQADR; PFMEC(ERRSTAT,ACTION); HLR$RESP[0] = ACTION; GOTO DPFMER[ACTION]; DPABAN: # ABANDON DESTAGE REQUEST # IF ERRSTAT EQ FTL THEN # RESPONSE INVALID FOR DESTAGE # BEGIN GOTO DPFATAL; END HLR$ERRC[0] = ABANDON"PFMERR"; RETURN; DPDELAY: # DELAY DESTAGE REQUEST # HLR$RESP[0] = ERRST"WAIT"; RETURN; DPSPEC: # RESPONSE INVALID FOR DESTAGE # DPFATAL: # FATAL DESTAGE ERROR # FE$RTN[0] = "DSERPFM."; # ABORT ON FATAL ERROR # MESSAGE(FEMSG,UDFL1); ABORT; DPNOERR: # NO ERRORS # RETURN; END # DSERPFM # TERM PROC DSNTDAM((HLRQADR)); # TITLE DSNTDAM - SELECT NEXT FILE TO DESTAGE. # BEGIN # DSNTDAM # # ** DSNTDAM - SELECT NEXT FILE TO DESTAGE. * * *DSNTDAM* ANALYZES THE RESULTS OF THE PREVIOUS DESTAGE * AND ADVANCES TO THE NEXT FILE TO BE DESTAGED. *DSNTDAM* * ADVANCES TO THE NEXT SUBFAMILY IF A SUBFAMILY RUNS OUT * OF FILES. * * PROC DSNTDAM * * ENTRY HLRQADR - ADRRESS OF *HLRQ* ENTRY. * FET/BUFFER FOR SCRATC"I" SET UP FOR READ. * FET/BUFFER FOR SCRATCH SET UP FOR WRITE. * FET/BUFFER FOR *MVOCOM* SET UP FOR WRITE. * * EXIT (HLR$TDAM) HAS *TDAM* REQUEST FOR NEXT FILE. * THE FOLLOWING *HLRQ* FIELDS ARE INITIALIZED. * - SH/FFILE/FVOL(TRUE)/VOLAUP. # ITEM HLRQADR U; # ADDRESS OF *HLRQ* ENTRY # # ***** PROC DSNTDAM - XREF LIST BEGIN. # XREF BEGIN FUNC XCOD C(10); # BINARY TO OCTAL DISPLAY # PROC BLOWUP; PROC CRELSLK; # RELEASE CATALOG INTERLOCK # PROC MESSAGE; # ISSUE A DAYFILE MESSAGE # PROC MSGAFDF; # ISSUE ACCOUNT-DAYFILE MESSAGE # PROC READ; # READ A FILE # PROC READW; # READ FILE TO WORKING BUFFER # PROC RENAME; # RENAME A FILE # PROC RETERN; # RETURN A FILE # PROC REWIND; # REWIND A FILE # PROC STNTDAM; # GET FILE TO STAGE # PROC WRITER; # WRITE RECORD MARK # PROC WRITEW; # WRITE DATA FROM WORKING BUFFER # PROC ZSETFET; # SET UP A FET # END # **** PROC DSNTDAM - XREF LIST END. # DEF PRUPAU #(INSPAU*PRUBLK)#; DEF LISTCON #0#; # DO NOT LIST COMMON DECKS # *CALL,COMBFAS *CALL,COMBBZF *CALL,COMBCPR *CALL,COMBTDM *CALL COMBMAT *CALL,COMBUDT *CALL COMXCTF *CALL,COMXHLR *CALL,COMXMFD *CALL,COMXMSC ITEM ACTION U; # CONTROLS MAIN LOOP PROCESSING # ITEM AU U; # FILE SIZE # ITEM I U; # LOOP COUNTER # ITEM J U; # SCRATCH 1 INDEX # ITEM K U; # SCRATCH 2 INDEX # ITEM LOOP U; # LOOP INDEX # ITEM SF U; # SUBFAMILY INDEX # ITEM STAT U; # FET STATUS # ITEM STATS U; # WRITE FET STATUS # ITEM TAKEIT B; # IF 1ST FILE ABANDONED, DO 2ND # CONTROL EJECT; P = HLRQADR; P = LOC(HLR$TDAM[0]); P = LOC(MCF$PRM[0]); SF = TDAMSBF[0]; ACTION = HLR$RESP[0]; HLR$RESP[0] = ERRST"NOERR"; TAKEIT = FALSE; J = HLR$SCROS1[0]; # ** PROCESS *ABANDON* STATUS. * - WRITE *TDAM* ENTRY WITH REASON TO *MOVCOM* FILE. * - ISSUE DAYFILE MESSAGE WITH FILE ID AND REASON. # IF ACTION EQ ERRST"NOERR" ## OR ACTION EQ ERRST"ABANDON" THEN # ISSUE A MESSAGE # BEGIN IF ACTION EQ ERRST"ABANDON" THEN BEGIN STAT = HLR$ERRC[0]; ACTION = ERRST"NOERR"; TDAMABR[0] = HLR$ERRC[0]; # SAVE ABANDON REASON # WRITEW(MCF$FET[0],TDAM[0],TDAMLEN,STATS); END ELSE BEGIN STAT = ABANDON"OK"; DSTCNT = DSTCNT + 1; END MSGAFDF("E", "ED", STAT,HLRQADR); END FOR LOOP = LOOP STEP 1 DO BEGIN # MAIN LOOP # # ** PROCESS *TOTAL DESTAGE DISABLE* CASE. * * - CLOSE ALL SUB FAMILIES. * # IF (NOT GLBDSFL AND ACTION NQ ERRST"NXTSUBF") # # OR (ACTION EQ ERRST"SMDSTAGEOFF") THEN # CLOSE OUT SUB FAMILY # BEGIN STATS = 0; IF HLR$ERRC[0] NQ ERRST"SPECIAL" THEN # FILE REPORT ALREADY WROTE # BEGIN READW(SCR1$FET[J],TDAM[0],TDAMLEN,STATS); END IF STATS NQ 0 THEN BEGIN WRITER(SCR2$FET[J],RCL); RENAME(SCR2$FET[J],SCRNMU[SF]); HLR$ERRC[0] = 0; HLR$UNLD[0] = HLR$FCTQ[0] NQ 0; CLEARBUF[J] = 0; SCR$HLRQ[SF] = 0; SLOWFOR I = 0 STEP 1 UNTIL MAXSF DO BEGIN # CLEAR WAIT DRD FLAG ON ALL SUB FAMILYS # SCR$WTDRD[I] = FALSE; END ACTION = ERRST"NXTSUBF"; END ELSE BEGIN STAT = ABANDON"CLOSEDS"; TDAMABR[0] = ABANDON"CLOSEDS"; WRITEW(MCF$FET[0],TDAM[0],TDAMLEN,STATS); MSGAFDF("E", "ED", STAT,HLRQADR); ACTION = ERRST"SMDSTAGEOFF"; END HLR$ERRC[0] = 0; END # ** PROCESS *NOERR* CASE. * * - GET NEXT *TDAM* ENTRY. * - IF NEXT FILE OK TO DESTAGE, RETURN. * OTHERWISE, DEFER ITS DESTAGE BY SETTING * ITS STATUS TO "RETRY". * - IF NO MORE FILES, CLOSE THE SCRATCH FILE * CONTAINING FILES TO BE RETRIED AND * RENAME IT TO THE ORIGINAL NAME FOR THAT SF. * - IF *DOSTG* FLAG IS SET, ASSIGN *HLRQ* ENTRY TO STAGE * A FILE. OTHERWISE, GET THE NEXT FILE FROM THE * NEXT SUBFAMILY AND CONTINUE DESTAGING. # IF ACTION EQ ERRST"NOERR" THEN BEGIN # GET NEXT *TDAM* ENTRY # READW(SCR1$FET[J],TDAM[0],TDAMLEN,STAT); IF STAT EQ OK THEN BEGIN # DESTAGE OR RETRY THIS FILE # AU = 1 + (TDAMFLN[0]-1)/PRUPAU; HLR$SH[0] = TDAMFLN[0] LS MVPR$LB[0]; IF HLR$FFILE[0] OR TAKEIT # ACCEPT 1ST FILE OF SEQUENCE # OR (HLR$SH[0] # SHORT FILE WHICH SHOULD FIT # AND (AU LS HLR$AUSF[0]) ) ## OR (NOT HLR$SH[0] # LONG FILE WHICH SHOULD FIT # AND (AU LS HLR$AULF[0]) ) ## THEN # DESTAGE FILE # BEGIN HLR$HPS[0] = PROCST"INITIAL"; HLR$FVOL[0] = TRUE; RETURN; END ELSE # RETRY FILE # BEGIN ACTION = ERRST"RETRY"; TEST LOOP; END END # DESTAGE OR RETRY THIS FILE # ELSE # CLOSE FILE OF TDAM-S TO BE RETRIED # BEGIN WRITER(SCR2$FET[J],RCL); RENAME(SCR2$FET[J],SCRNMU[SF]); CLEARBUF[J] = 0; SCR$HLRQ[SF] = 0; IF HLR$DOSTG[0] AND (HLR$LRQADR[0] NQ 0) ## AND (HLR$ERRC[0] NQ ERRST"SPECIAL") THEN # GET FILE TO BE STAGED # BEGIN DSC$INIT = 1; STNTDAM(HLRQADR); RETURN; END HLR$ERRC[0] = 0; HLR$UNLD[0] = HLR$FCTQ[0] NQ 0; SLOWFOR I = 1 STEP 1 UNTIL MAXSMUNIT DO BEGIN # FIND MATCHING *SM* # IF HLR$SM[0] EQ SM$ID[I] THEN BEGIN # CLEAR FOR THE NEXT SUBFAMILY # SLOWFOR K = 0 STEP 1 UNTIL MAXSF DO BEGIN # CHECK FOR PENDING REQUEST # IF BSM$DSRFW0[I] NQ 0 THEN BEGIN # CLEAR REQUEST # BSM$DSRFW0[I] = 0; SCR$WTDRD[K] = FALSE; GOTO DRDOPEN; END END # CHECK FOR PENDING REQUEST # END # CLEAR OF SUBFAMILY # END # CLEAR OF DRD # IF DSC$WRESRS NQ 0 THEN # FORCE A DESTAGE RESTART # BEGIN DSC$INIT = 1; END # * CHECK FOR AN OTHER *SM* WAITING A RESTART. * # SLOWFOR I = 1 STEP 1 UNTIL MAXSMUNIT DO BEGIN # FIND *SM* # IF HLR$SM[0] NQ SM$ID[I] THEN BEGIN # DESTAGE WAITING *DRD* # SLOWFOR J = 0 STEP 1 UNTIL MAXSF DO BEGIN # CHECK FOR DESTAGE WAITING # IF BSM$DSRFW0[I] NQ 0 THEN BEGIN BSM$DSRFW0[I] = 0; SCR$WTDRD[J] = FALSE; DSC$INIT = 1; GOTO DRDOPEN; END END # COMPLETED CHECK OF WAITING # END # DESTAGE WAITNG *DRD* # END # FIND *SM* # DRDOPEN: ACTION = ERRST"NXTSUBF"; TEST LOOP; END END # GET NEXT *TDAM* ENTRY # # ** PROCESS *RETRY* STATUS. * * - SAVE *TDAM* ENTRY ON SCRATCH FILE. * - ADD FILE LENGTH TO REQUIREMENTS. # IF ACTION EQ ERRST"RETRY" THEN BEGIN # RETRY CASE # WRITEW(SCR2$FET[J],TDAM[0],TDAMLEN,STAT); AU = 1 + (TDAMFLN[0]-1)/PRUPAU; IF HLR$SH[0] THEN BEGIN SCR$AUS[SF] = SCR$AUS[SF] + AU; END ELSE BEGIN SCR$AUL[SF] = SCR$AUL[SF] + AU; END ACTION = ERRST"NOERR"; # GET NEXT FILE TO DESTAGE # TEST LOOP; END # RETRY CASE # # * * PROCESS A *RESOURES* BEING CASE. * - HOLD UP *DESTAGING* UNTIL RESOURSES * ARE AVAILABLE. * # IF ACTION EQ ERRST"RSFULL" THEN BEGIN NEXTENTR: WRITEW(SCR2$FET[J],TDAM[0],TDAMLEN,STAT); AU = 1 + (TDAMFLN[0]-1)/PRUPAU; IF HLR$SH[0] THEN BEGIN SCR$AUS[SF] = SCR$AUS[SF] + AU; END ELSE BEGIN SCR$AUL[SF] = SCR$AUL[SF] + AU; END READW(SCR1$FET[J],TDAM[0],TDAMLEN,STAT); IF STAT EQ 0 THEN BEGIN GOTO NEXTENTR; END ELSE BEGIN WRITER(SCR2$FET[J],RCL); RENAME(SCR2$FET[J],SCRNMU[SF]); CLEARBUF[J] = 0; SCR$HLRQ[SF] = 0; END SLOWFOR I=1 STEP 1 UNTIL MAXSMUNIT DO BEGIN # SET *SM* FOR DESTAGE RECALL # IF HLR$SM EQ SM$ID[I] THEN BEGIN B<(SF)>SM$DSRFW0[I] = 1; SCR$WTDRD[SF] = TRUE; # HOLD DESTAGE ON THIS SUBFAMILY # GOTO SMFOUND; END END # END OF SET *DESTAGE* RECALL # SMFOUND: ACTION = ERRST"NXTSUBF"; HLR$ERRC[0] = 0; HLR$UNLD[0] = HLR$FCTQ[0] NQ 0; TEST LOOP; END # ** PROCESS *NXTSUBF* CASE. * * - LOOK FOR NEXT SUBFAMILY WITH FILES TO BE DESTAGED. * IF ONE IS FOUND, PREPARE TO PROCESS ITS FILES. * IF NONE FOUND, TERMINATE DESTAGING. # IF ACTION EQ ERRST"NXTSUBF" THEN # FIND NEXT SUBFAMILY TO BE DESTAGED # BEGIN # NEXT SUBFAMILY CASE # SLOWFOR I = 0 STEP 1 UNTIL MAXSF DO BEGIN # LOOK FOR NEXT SUBFAMILY # IF NOT SCR$WTDRD[I] ## AND (SCR$AUS[I] NQ 0 OR SCR$AUL[I] NQ 0) AND (SCR$HLRQ[I] EQ 0) THEN BEGIN # PREPARE SCRATCH FILES # SF = I; SBI[SF] = "0" + I; SCI[SF] = "0" + I; SLOWFOR J = 0 STEP SCCBL WHILE J LS MAT$SPACE ## [MAT$ENTRY"SCR$BUF"] DO BEGIN # FIND FREE SET OF SCRATCH BUFFERS # IF CLEARBUF[J] EQ 0 THEN BEGIN # SCRATCH FILES FREE # HLR$SCROS1[0] = J; K = J + SFETL + MAT$FWA[MAT$ENTRY"SCR$BUF"]; ZSETFET(LOC(SCR1$FET[J]),SCRNM[SF],K,MCFBUFL,SFETL); ZSETFET(LOC(SCR2$FET[J]),SCRNMX[SF],K + MCFBUFL + SFETL, MCFBUFL,RFETL); REWIND(SCR1$FET[J],RCL); REWIND(SCR2$FET[J],RCL); READ(SCR1$FET[J],RCL); HLR$VOLAUP[0] = SCR$AUS[I]; SCR$HLRQ[SF] = HLRQADR; SCR$AUS[I] = 0; SCR$AUL[I] = 0; HLR$FFILE[0] = TRUE; IF NOT GLBDSFL THEN BEGIN # DESTAGING CLOSED # ACTION = ERRST"SMDSTAGEOFF"; # TO GIBDSFL CHECK # END ELSE BEGIN # CHECK FIRST FILE # ACTION = ERRST"NOERR"; # GET FIRST FILE # END TEST LOOP; END # SCRATCH BUFFER # END # FREE SCRATCH BUFFER # END END # LOOK FOR NEXT SUBFAMILY # # * CHECK IF ALL DESTAGES ARE COMPLETE. # SLOWFOR I = 0 STEP 1 UNTIL MAXSF DO BEGIN IF SCR$HLRQ[I] NQ 0 OR SCR$WTDRD[I] THEN BEGIN # DESTAGES NOT COMPLETE # TDAMFC[0] = TDAMFCODE"STAGE"; RETURN; END END # * IF NO SUBFAMILY WAS FOUND, TERMINATE DESTAGING. # TDAMFC[0] = TDAMFCODE"NOREQ"; WRITER(MCF$FET[0],RCL); REWIND(MCF$FET[0],RCL); RETERN(MCF$FET[0],RCL); RETURN; END # NEXT SUBFAMILY CASE # END # MAIN LOOP # END # DSNTDAM # TERM PROC DSSETUP(FAM,ERRSTAT); # TITLE DSSETUP - DESTAGING INITIALIZATION PROCESSOR. # BEGIN # DSSETUP # # ** DSSETUP - DESTAGING INITIALIZATION PROCESSOR. * * *DSSETUP* READS THE *MVOCOM* FILE CREATED BY *SSMOVE* AND WRITES * ( UP TO 8 ) SCRATCH FILES ( ONE FOR EACH SUBFAMILY WITH FILES * TO BE DESTAGED ). *DSSETUP* THEN CALLS *DSNTDAM* TO PREPARE * THE *HLRQ* ENTRY FOR THE FIRST FILE TO BE DESTAGED. * THE *MVOCOM* FILE IS ALSO INITIALIZED BY REWRITING * THE PREAMBLE BACK TO IT. * * PROC DSSETUP(FAM,ERRSTAT) * * ENTRY *MOVCOM* FILE HAS BEEN GENERATED BY *SSMOVE*. * (FAM) = FAMILY TO BE PROCESSED. * * EXIT SCRATCH FILES WRITTEN AND REWOUND FOR EACH AFFECTED * SUBFAMILY. *HLRQ* ENTRY ESTABLISHED FOR FIRST FILE. * (ERRSTAT) =0, IF NO PROBLEMS. * * MESSAGES * UNABLE TO READ MVOCOM, FM=FFFFFFF.*. * * UNABLE TO WRITE SCRATCH, FM=FFFFFFF.*. * # ITEM FAM C(7); # FAMILY NAME # ITEM ERRSTAT U; # REPLY STATUS # # **** PROC DSSETUP - XREF LIST BEGIN. # XREF BEGIN PROC ABORT; # ABNORMAL TERMINATION # PROC BLOWUP; PROC BZFILL; # BLANK OR ZERO FILL ITEM # PROC HLRQENQ; # *HLRQ* ENQUEUER # PROC MESSAGE; # ISSUE MESSAGE # PROC MSG; # ISSUE MESSAGE # PROC PFD; # PERMANENT FILE REQUEST DELAYS # PROC READ; # READ A FILE # PROC READW; # READ DATA TO WORKING BUFFER # PROC RETERN; # RETURN FILE # PROC REWIND; # REWIND A FILE # PROC RMVBLNK; # REMOVE EXCESS BLANKS # PROC SETPFP; # SWITCH TO GIVEN SUBFAMILY # PROC WRITER; # WRITE END OF RECORD # PROC WRITEW; # WRITE DATA FROM WORKING BUFFER # PROC ZSETFET; # INITIALIZES A FET # END # **** PROC DSSETUP - XREF LIST END. # DEF LISTCON #0#; # DO NOT LIST COMMON DECKS # *CALL,COMBFAS *CALL,COMBBZF *CALL,COMBFET *CALL COMBMAT *CALL,COMXCTF *CALL,COMBPFP *CALL,COMBPFS *CALL,COMBTDM *CALL,COMXMFD *CALL,COMXMSC ITEM AU U; # FILE SIZE IN AU # ITEM I I; # LOOP COUNTER # ITEM J I; # LOOP COUNTER # ITEM K I; # BUFFER POINTER # ITEM MCFCATM C(40) = " UNKNOWN FAMILY - XXXXXXX.;"; ITEM MCFUNPR C(40) = " UNABLE TO PROCESS MOVE REQUEST FILE.;" ; ITEM OPEN B; # CONTROL OPENING OF NEW SCRATCH FILE # ITEM PREVSF U; # PREVIOUS SUBFAMILY # ITEM PRUPAU U; # NUMBER OF PRU PER AU # ITEM STAT I; # STATUS # ITEM STATW I; # WRITE STATUS # CONTROL EJECT; # * INITIALIZE SUBFAMILY SCRATCH FILE ENTRIES. # PRUPAU = INSPAU*PRUBLK; SLOWFOR I = 0 STEP 1 UNTIL MAXSF DO BEGIN SCR$AUS[I] = 0; SCR$AUL[I] = 0; END # * VERIFY *FAM* IS A KNOWN FAMILY. # OPEN = FALSE; FOR I = 0 STEP 1 WHILE I LS FAMCNT AND NOT OPEN DO BEGIN OPEN = MRFTFAM[I] EQ FAM; END IF NOT OPEN THEN # UNKNOWN FAMILY # BEGIN ERRSTAT = 1; BZFILL(FAM,TYPFILL"BFILL",7); C<18,7>MCFCATM = FAM; MSG(MCFCATM,UDFL1); MSG(MCFUNPR,UDFL1); RETURN; END # * SWITCH TO SPECIFIED FAMILY. # PFP$WRD0[0] = 0; PFP$FAM[0] = FAM; PFP$UI[0] = DEF$UI; PFP$FG1[0] = TRUE; PFP$FG4[0] = TRUE; SETPFP(PFP); IF PFP$STAT[0] NQ 0 THEN BEGIN FE$RTN[0] = "DSSETUP"; MESSAGE(FEMSG,UDFL1); ABORT; END # * ATTACH *MVOCOM* FILE GENERATED BY *SSMOVE*. # PFD("ATTACH", MVOCOM,0,"M","W","RC",STAT,0); IF STAT NQ OK THEN BEGIN MOVMLINE[0] = MCFATTERR; BZFILL(FAM,TYPFILL"BFILL",7); MOVMFAM[0] = FAM; RMVBLNK(MOVMSG[0],38); MESSAGE(MOVMSG[0],UDFL1); ERRSTAT = 1; RETURN; END # * READ *MVOCOM* FILE PREAMBLE. # J = LOC(MCF$FET[0]); ZSETFET(J,MVOCOM,LOC(MCF$BUF[0]),MCFBUFL,SFETL); FET$EP[0] = TRUE; READ(MCF$FET[0],NRCL); READW(MCF$FET[0],MCF$PRM[0],MVPRML,STAT); IF STAT NQ OK THEN BEGIN MOVMLINE[0] = MCFRDERR; FAM = MRFTFAM[0]; BZFILL(FAM,TYPFILL"BFILL",7); MOVMFAM[0] = FAM; RMVBLNK(MOVMSG[0],38); MESSAGE(MOVMSG[0],UDFL1); RETERN(MCF$FET[0],RCL); ERRSTAT = 1; RETURN; END # * SET UP SCRATCH FILE NAMES. # SLOWFOR I = 0 STEP 1 UNTIL MAXSF DO BEGIN # SET SCRATCH FILE NAMES # NAMESCR[I] = "SCRATC"; SCRNMX[I] = "SCRBBB"; END # * COPY *MVOCOM* TO SCRATCH FILES. # P = LOC(MCF$FET[0]); P = LOC(MCF$REQ[0]); P = LOC(MCF$PRM[0]); K = MAT$FWA[MAT$ENTRY"SCR$BUF"]; P = K; P = K + SFETL + MCFBUFL + 1; PREVSF = 8; SLOWFOR I =0 STEP 1 WHILE STAT EQ 0 DO BEGIN # TRANSFER TDAM ENTRIES FROM *MVOCOM* TO SCRATCH # READW(MCF$FET[0],MCF$REQ[0],TDAMLEN,STAT); IF STAT EQ CIOERR THEN BEGIN # TERMINATE PROCESSING *MVOCOM* FILE # IF FET$AT[0] NQ OK THEN BEGIN # READ ERROR # MOVMLINE[0] = MCFRDERR; FAM = MRFTFAM[0]; BZFILL(FAM,TYPFILL"BFILL",7); MOVMFAM[0] = FAM; RMVBLNK(MOVMSG[0],38); MESSAGE(MOVMSG[0],UDFL1); END # READ ERROR # RETERN(MCF$FET[0],RCL); ERRSTAT = 1; RETURN; END # TERMINATE *MVOCOM* PROCESSING # J = TDAMSBF[0]; # * CLOSE OUT PREVIOUS SCRATCH FILE, IF APPROPRIATE. # IF (I NQ 0) # NOT 1ST PASS # AND (J NQ PREVSF OR STAT NQ 0) # FOUND A NEW SUBFAMILY # THEN # CLOSE OUT SCRATCH FILE FOR PREVIOUS SUBFAMILY # BEGIN OPEN = TRUE; WRITER(SCR1$FET[0],RCL); END IF STAT NQ 0 THEN BEGIN TEST I; END # * OPEN NEW SCRATCH FILE, IF APPROPRIATE. # IF (I EQ 0) OR (OPEN) THEN BEGIN SBI[0] = "0" + J; PREVSF = J; ZSETFET(K,SCRNM[0],K+SFETL, ## MCFBUFL,SFETL); ## REWIND(SCR1$FET[0],RCL); OPEN = FALSE; END AU = 1 + (TDAMFLN[0]-1)/PRUPAU; IF TDAMFLN[0] LS MVPR$LB[0] THEN BEGIN SCR$AUS[TDAMSBF[0]] = SCR$AUS[TDAMSBF[0]] + AU; END ELSE BEGIN SCR$AUL[TDAMSBF[0]] = SCR$AUL[TDAMSBF[0]] + AU; END WRITEW(SCR1$FET[0],MCF$REQ[0],TDAMLEN,STATW); END # TRANSFER TDAM ENTRIES FROM *MVOCOM* TO SCRATCH # # * COMPLETE SETTING UP FOR DESTAGING OF FILES. * - WRITE PREAMBLE BACK TO *MVOCOM* FILE. * - COMPLETE INITIALIZATION. # REWIND(MCF$FET[0],RCL); WRITEW(MCF$FET[0],MCF$PRM[0],MVPRML,STATW); DSC$INIT = 1; ERRSTAT = 0; CLEARBUF[0] = 0; DSC$FAM = FAM; DSC$LKMSK = 0; DSC$LKTYP = 0; RETURN; END # DSSETUP # TERM