" *********************************************************** " * * " * Copyright, (C) Honeywell Information Systems Inc., 1982 * " * * " *********************************************************** " RESTOR Command for BOS. " Modified 9/27/73 by N. I. Morris " Modified 2/80 by R.J.C. Kissel for 6250 bpi operation. name restor " ****************************************************** " * * " * * " * Copyright (c) 1972 by Massachusetts Institute of * " * Technology and Honeywell Information Systems, Inc. * " * * " * * " ****************************************************** include bosequ " include ntape_equ include sav_util " go: startape: tsx2 resetq reset done for header, set everything else tsx2 opentaper start tape zero qh zero tapen eax3 qh wait for header to read in tsx2 savwait .. arg erh tra eot lda bf|svhc+svh.allsw get ALL flag from tape sta bf|svh.allsw copy into header tsx2 rqm merge requests rpre: tsx2 copy_to_preamble copy info into preamble tsx2 ckmore anything to do? tra nxtvol if not, skip this code lda bf|svh.curvol get current volume index als 24 move to ID position sta qp+1 set ID for reading preamble lxl7 0,dl set queue entry to read tape sxl7 qp .. eax3 qp wait for preamble to read in tsx2 savwait .. arg erp tra eot tsx2 set_preamble_info copy pertinent info into preamble tsx2 pprint announce tape contents stc1 firstsw set first time switch stz lastsw clear last time switch tsx2 savloop enter volume loop arg dorestor stc1 lastsw set last time switch drain: tsx2 dorestor do last lap of queue cmpx3 ql,du until back at beginning tnz drain .. sznc fatalsw fatal errors on this volume? tnz force_salv if so, force a salvage later nxtvol: lda bf|svh.curvol have we processed last volume? cmpa bf|svh.nvol .. tpl done if so, stop now aos bf|svh.curvol step to next volume tra rpre .. " dorestor: stx2 dorsx2 save X2 more: szn firstsw first time through loop? tnz qsetl if so, get tape rolling stz base clear base of block stx3 qtemp save current queue pointer wait: tsx2 savwait wait for I/O and check arg rserr tra eot tsx2 comp_base compute base and top tsx2 nextq chain to next queue entry tze wait and loop until queue stopper tsx2 disk_io do disk output arg wdev .. szn lastsw last time? tnz dorsx2 if so, don't queue more tape I/O ldx3 qtemp restore queue pointer qsetl: eax7 0 clear all queue flags tsx2 setq go set ID and flags in queue entry tsx2 nextq chain to next queue entry tze qsetl until queue stopper tsx2 runtape now keep the tape moving cmpx3 ql,du fill whole 32K queue tnz more until queue lapped stz firstsw then, clear first time flag dorsx2: eax2 * restore X2 tra 0,2 return to caller " eot: lda 1,3 save current place ana -1,dl mask device address sta bf|svp.sva+sva.done and save tsx2 disk_io do last block of disk output arg wdev .. tsx2 copy_from_preamble copy preamble back into header tra startape now, start new tape " set_preamble_info: ldq bf|svh.curvol get current volume index sbq 1,dl minus 1 mpy sva_size,dl compute array element offset epp xs1,bf|svh.sva,ql get pointer to array element lda xs1|sva.done copy pertinent info into preamble sta bf|svp.sva+sva.done .. lda xs1|sva.last .. sta bf|svp.sva+sva.last .. lda xs1|sva.devt .. sta bf|svp.sva+sva.devt .. tra 0,2 return to caller " rserr: stx2 rserx2 save return lda 1,3 get ID ana -1,dl mask the device address sta rtemp and save for printing message tsx2 erpt acc 'unrecoverable error reading record ^d.' arg rtemp lda 2,3 get location of disk record contents ana =o077777,du mask it als 2 compute character offset ldq 1024*4,du record length in QU mlr (),(pr,rl,au),fill(0) clear the record in error desc9a *,0 desc9a tmp|0,qu stc2 fatalsw indicate fatal I/O error rserx2: eax2 * restore X2 tra 0,2 return to caller " force_salv: lda LABEL_ADDR,dl get disk address of label tsx2 mulbos convert to BOS address arg =itp(bf,svp.sva+sva.devt),* tra nxtvol sta rtemp save temporarily tsx2 rdev read the label arg =itp(bf,svp.sva+sva.devt),* arg bf|LABEL tra nxtvol stz bf|LABEL+label.time_map_updated This will cause salvager to run. stz bf|LABEL+label.time_map_updated+1 .. lda rtemp get label address again tsx2 wdev write it back out arg =itp(bf,svp.sva+sva.devt),* arg bf|LABEL tra nxtvol tra nxtvol continue to next volume " " RESTOR request merger " Nov. 18, 1975 by Bernard Greenberg " " " This routine operates upon the request lines (cards) given to RESTOR. " It checks their internal consistency, and their consistency with the " data saved on a SAVE tape/disk. It reorders the requests to be in the " same order as the tape/disk, by volume name. Card slots for which " there are no requests for a given volume on the tape/disk are marked " with a "skip" flag. " " It is essential to the functioning of this algorithm, which reorders " the requests in place, that it remove duplicate requests for any " volume, and those which do not correspond to a volume on the " tape/disk. This is not merely an error check. " " It is assumed that there are no duplicate volumes on the tape/disk, or " other instances than the first can never be RESTORed. " rqm: stx2 rqm_x2 save exit " Initialize limits for starting and ending scans. ldq bf|svhc+svh.nvol mpy sva_size,du stq rqm_limt tape limit ldq bf|svh.nvol mpy sva_size,du stq rqm_limc cards limit ldq bf|svh.curvol sbq 1,dl make org 0 mpy sva_size,du stq rqm_start " If more tape vols than reqs, fill out with skip cards. ldq rqm_limc cards rqm_fills:cmpq rqm_limt tape tpl rqm_filld tra if cards > tape stc2 bf|svh.sva+sva.skip,qu eaq sva_size,qu next req tra rqm_fills rqm_filld:stq rqm_limc see next comment " We have now insured that there are at least as many " cards as tape requests. This will be very important later on. " " Scan card requests for duplicates, and " volumes not on tape. When this has been done, " there will be fewer or same non-skip cards " than tape requests. ldx1 rqm_start begin outer loop on cards tra *+2 rqm_lp1: eax1 sva_size,1 cmpx1 rqm_limc are we done? tpl rqm_2 yes, begin next phase epp xs1,bf|svh.sva,1 address sva entry szn xs1|sva.skip is this entry already skipped? tnz rqm_lp1 yes, go on to next. stx1 rqm_curvol save for later compare. " Scan other cards to eliminate duplicates. " ldx3 rqm_start scan tra *+2 rqm_lp2: eax3 sva_size,3 move on scanning cards cmpx3 rqm_limc done with cards? tpl rqm_e1 done with check cmpx3 rqm_curvol is it the one we are checking against? tze rqm_lp2 yes, don't compare epp xs2,bf|svh.sva,3 address sva entry szn xs2|sva.skip skip this one too? tnz rqm_lp2 yes cmpc (pr),(pr) "compare the names. xs1desc: desc9a xs1|sva.pvname,32 xs2desc: desc9a xs2|sva.pvname,32 tnz rqm_lp2 not same, ok. tsx2 erpt type out complaint acc "ignoring duplicate request for vol ^A, ^d. to ^d." arg xs2desc arg xs2|sva.done arg xs2|sva.last stc2 xs2|sva.skip skip the duplicate tra rqm_lp2 " " All duplicates weeded out for xs1 -> sva. " Now make sure such a vol is present on tape. rqm_e1: ldx3 rqm_start tra *+2 rqm_l2: eax3 sva_size,3 scan on cmpx3 rqm_limt are we done? tpl rqm_novol yes, could not find it. Too bad. epp xs2,bf|svhc+svh.sva,3 cmpc (pr),(pr) "same name? desc9a xs1|sva.pvname,32 desc9a xs2|sva.pvname,32 tnz rqm_l2 not found, scan tape more tra rqm_lp1 found it, scan cards more. rqm_novol: tsx2 erpt acc "No records for vol ^A; igNoring request." arg xs1desc stc2 xs1|sva.skip skip it tra rqm_lp1 loop on cards " There are now no duplicate cards, or cards that do not correspond to " tape requests. " " Phase 2 of request merge. We reorder the cards to be in the same " positions as the tape requests. Where there is a tape request for " which there appears no card, we put a skip card. We do this by " scanning the tape requests in order, placing the card that corresponds " to that request, if any, in that slot, or a skip card if there is " none. In the case that a corresponding card is found, we swap the " found card with the current resident of the current slot (card slot " corresponding to tape slot). We have ensured that there is only, if " any, one card per tape request. Thus, when we have scanned any number " of tape requests, there are no cards for them in slots higher than the " processed tape requests. In the case where a card is found for a tape " request, we swap it into place. The card with which it is swapped, " i.e., the card currently at the current index, must either be a skip " card, or a card for an as yet unprocessed request, as we have just " shown that cards for processed requests cannot appear. Thus, we will " process the card later. The case where no card is found for the " current tape request is even more involved, and explained at rqm_lpe4. " rqm_2: ldx1 rqm_start tra *+2 rqm_lp3: eax1 sva_size,1 scan on tape cmpx1 rqm_limt tra when done tpl rqmlpe3 tra when done. epp xs1,bf|svhc+svh.sva,1 address sva entry stx1 rqm_curvol save for compare " " Find the card which has the same request name as the tape request " pointed to by xs1. We have ensured that there is not more than one. If " there is none, go to rqm_lpe4. Since, by induction, all card slots " below the current tape slot contain either skip cards or the right " cards, if there is a card for the current tape record at all, it is " either in place now or beyond this point. " ldx3 rqm_curvol start at current index tra *+2 rqm_lp4: eax3 sva_size,3 scan on cards cmpx3 rqm_limc check end of deck tpl rqm_lpe4 very interesting case where not found. epp xs2,bf|svh.sva,3 address card. szn xs2|sva.skip skip this entry? tnz rqm_lp4 yes cmpc (pr),(pr) "is this same name? desc9a xs1|sva.pvname,32 desc9a xs2|sva.pvname,32 tnz rqm_lp4 no, not interesting " " There is a single card corresponding to the tape request pointed to by " xs1. We found it, and xs2 points to it. If it is already in the right " slot (x1 = x3), we are done. If not, the card currently in the current " slot (bf|svh.sva,1) is either a skip card or a card corresponding to a " tape request as yet not scanned. Hence, we swap the card here now " with the card that wants to be here. " epp xs1,bf|svh.sva,1 from hereon in in this loop, "xs1 -> card entry for this tape slot. cmpx3 rqm_curvol same card? tze *+2 yes, no swap tsx7 rqm_swap exch sva's at xs1 and xs2 " Request is in place -- validate parameters. epp xs2,bf|svhc+svh.sva,1 address tape entry in xs2 " address card entry in xs1 lda xs1|sva.devt era xs2|sva.devt ana =o17,dl tnz diff_devt current restr: same type lda xs1|sva.done cmpa xs2|sva.done tnz differs lda xs1|sva.last cmpa xs2|sva.last tze rqm_lp3 take as is, next tape request. differs: tsx2 erpt announce bad news. acc "Save sequence contains ^A ^d. to ^d." arg xs2desc arg xs2|sva.done arg xs2|sva.last tsx2 erpt acc "Outstanding request is ^d. to ^d." arg xs1|sva.done arg xs1|sva.last tsx2 erpt acc "Is ^g ^o correct^g" arg subsysname arg tapen arg =h!!???? tsx2 ask find out tra x2 abort tsx2 erpt acc "Should request be changed to ^d. to ^d.^g" arg xs2|sva.done arg xs2|sva.last arg =h!!???? tsx2 ask tra rqm_lp3 leave as is if says no. lda xs2|sva.done sta xs1|sva.done move tape to cards lda xs2|sva.last sta xs1|sva.last tra rqm_lp3 process as this. diff_devt:tsx2 erpt cannot handle mismatched devices acc "Request for vol ^a differs in device type." arg xs1desc tra x2 " " At this point, we have determined that there is no card containing a " request described by the tape request of the current index (pointed to " by xs1 and x1). We must thus put a skip request in the card slot of " this index. However, the card in this slot now, if not a skip card " already, represents a tape request that we have not yet scanned. We " will exchange it with a skip card of higher index (ahead of us). The " following is a proof that, given that the current card is not a skip " card, a skip card must exist ahead of us. " " The current card, is, by hypothesis, not a skip card. Define that " there are n tape requests, including the current index, left " unprocessed. There are at least n unprocessed cards, possibly " including skip cards put there to fulfill this requirement by the " first loop in the merger program. Now of those n cards, either a skip " card exists among them or does not. Assume one does not. Now there " are n cards corresponding to n tape requests. The first phase of the " merger ensured that there are no duplications among cards, and that " each corresponds to a tape request. Since all cards corresponding to " processed tape requests have been swapped with thereto unprocessed " ones, the n cards from here above must all correspond to unprocessed " tape requests. By definition, the current tape request is considered " unprocessed. Since all cards are different, and they all correspond " to unprocessed tape requests, and there are as many as there are " unprocessed tape requests, there must be a card for each unprocessed " tape request, including the current one. But we arrived at this point " because there is no card for the current tape request. Hence, the " assumption that there does not exist a skip card must be false. " Therefore, there exists a skip card in the n cards. As the current " card is not a skip card, by hypothesis, one must therefore appear " later on. " " Q.E.D. " rqm_lpe4: tsx2 erpt acc "No requests for vol ^A." arg xs1desc announce the news. epp xs2,bf|svh.sva,1 look at card here szn xs2|sva.skip tnz rqm_lp3 will never need this skip, let it go. " " If we just branched, there was a skip record here, and there is no " problem. We proceed down the array of tape requests. If we fell " through, there is a card here corresponding to an as yet unprocessed " tape request. Find the skip card which was just proven to exist in " this case, and swap it with this request. " epp xs1,xs2|0 maintain pointer to this card slot epp xs2,xs2|sva_size try next card szn xs2|sva.skip skip record? tze *-2 loop. Loop _w_i_l_l terminate. tsx7 rqm_swap skip records. Swap xs1, xs2. tra rqm_lp3 move on to next tape record " " When the day's work is done, we arrive here. Patch nvol " in the card buffer as a testament to this. rqmlpe3: lda bf|svhc+svh.nvol cards := tape sta bf|svh.nvol rqm_x2: tra *-* " " " Routine to swap xs1 and xs2 sva entries. " rqm_swap: csl (pr),(pr),bool(6) XOR descb xs1|0,sva_size*36 descb xs2|0,sva_size*36 csl (pr),(pr),bool(6) descb xs2|0,sva_size*36 descb xs1|0,sva_size*36 csl (pr),(pr),bool(6) descb xs1|0,sva_size*36 descb xs2|0,sva_size*36 tra 0,7 " " Routine to answer questions. " ask: stx2 askx2 subr to read yes or else tsx2 readtty "get answer tra *-1 askx2: eax2 * ldq line cmpq =hyes " tnz 0,2 tra 1,2 " " " Variables. " All of them are in the UPPER. " rqm_start: arg 0 sva_size * adjusted index of first vol this call rqm_limc: arg 0 sva_size * (1+ adjusted index of last vol), for "the request lines (cards) typed in. rqm_limt: arg 0 same, but for the requests on tape. rqm_curvol: arg 0 temp used for comparison of current index pos. " " End of request merger " " firstsw: oct 0 lastsw: oct 0 erh: tsx2 erpt acc "Fatal error reading save header." tra x2 erp: tsx2 erpt acc "Fatal error reading save volume preamble." tra x2 " include bos_sdw include bos_tv include bos_common end " " " ----------------------------------------------------------- " " " " Historical Background " " This edition of the Multics software materials and documentation is provided and donated " to Massachusetts Institute of Technology by Group Bull including Bull HN Information Systems Inc. " as a contribution to computer science knowledge. " This donation is made also to give evidence of the common contributions of Massachusetts Institute of Technology, " Bell Laboratories, General Electric, Honeywell Information Systems Inc., Honeywell Bull Inc., Groupe Bull " and Bull HN Information Systems Inc. to the development of this operating system. " Multics development was initiated by Massachusetts Institute of Technology Project MAC (1963-1970), " renamed the MIT Laboratory for Computer Science and Artificial Intelligence in the mid 1970s, under the leadership " of Professor Fernando Jose Corbato. Users consider that Multics provided the best software architecture for " managing computer hardware properly and for executing programs. Many subsequent operating systems " incorporated Multics principles. " Multics was distributed in 1975 to 2000 by Group Bull in Europe , and in the U.S. by Bull HN Information Systems Inc., " as successor in interest by change in name only to Honeywell Bull Inc. and Honeywell Information Systems Inc. . " " ----------------------------------------------------------- " " Permission to use, copy, modify, and distribute these programs and their documentation for any purpose and without " fee is hereby granted,provided that the below copyright notice and historical background appear in all copies " and that both the copyright notice and historical background and this permission notice appear in supporting " documentation, and that the names of MIT, HIS, Bull or Bull HN not be used in advertising or publicity pertaining " to distribution of the programs without specific prior written permission. " Copyright 1972 by Massachusetts Institute of Technology and Honeywell Information Systems Inc. " Copyright 2006 by Bull HN Information Systems Inc. " Copyright 2006 by Bull SAS " All Rights Reserved " "