// ISFINIT -- initialize indexed sequential file
// last edited November 12, 1976 12:42 PM
// file reassignments in local copies begun January 20, 1978, by Swinehart
get "isf.d"
external // entry procedures
[ InitFmap // (fmap, len, fp[, check, xtnd, zone, disk]) -> ok
morepageio // for extending files -- used at init time only in Spruce
WriteFmap // used if at all only at init time in Spruce
]
external
[ // O.S.
CallSwat
MoveBlock
ActOnDiskPages
DefaultArgs
Allocate; Free
Dvec
sysDisk
sysZone
SetBlock
Usc
WriteDiskPages
Zero
// Isf (utilities)
NextFmap
LookupFmap
// Spruce utilities
Min
]
let InitFmap(fmap, len, fp, check, xtnd, zone, disk, lvPages; numargs n) = valof
[ DefaultArgs(lv n, -3, false, 10, -1, sysDisk, 0)
// DCS 9-14-78 returns false if len too small or check error accessing file
if len ls mapoffset+3 then resultis false
fmap>>FM.seal = version
MoveBlock(lv fmap>>FM.fp, fp, lFP)
let leaderVda = fp>>FP.leaderVirtualDa
fmap>>FM.DA0 = leaderVda
fmap>>FM.DA1, fmap>>FM.DA2 = fillInDA, fillInDA
fmap>>FM.last = mapoffset+2
let end = (len-2)&-2
fmap>>FM.onern, fmap>>FM.oneda = 0, fmap>>FM.DA0
let map = fmap+mapoffset
map!0, map!1, map!2 = 0, leaderVda, 1
fmap>>FM.rewrite = check
fmap>>FM.extend = (xtnd ls ppc? xtnd, ppc)
if zone eq 0 then zone = sysZone
let pagesize = 1 lshift disk>>DSK.lnPageSize
let scratch, nch = pagesize, (check? 1, 0) // nch used for last page input until after Act..
test zone eq -1 then Dvec(InitFmap, lv scratch) or scratch = Allocate(zone, scratch)
let res = ActOnDiskPages(disk, 0, lv fmap>>FM.DA0, fp,
0, nch, DCreadD, lv nch, DCreadD, scratch, 0,0, true) ge 0
if res then test check then
[
if nch eq 2*pagesize & (scratch>>FM.last ge mapoffset+2) & (scratch!mapoffset eq 0) &
valof [ for i = 1 to checksize-1 do if scratch!i ne fmap!i resultis false; resultis true ] then
[
let last = scratch>>FM.last // stored map seems all right -- use it
if last gr end then last = end
if last ge pagesize then last = pagesize-2
MoveBlock(fmap, scratch, last+1)
]
]
or if lvPages then
[
@lvPages = scratch>>LD.hintLastPageFa.pageNumber
if @lvPages > 0 & scratch>>LD.hintLastPageFa.charPos eq 0 then @lvPages = @lvPages-1
]
if zone ne -1 then Free(zone, scratch)
fmap>>FM.end = end
fmap>>FM.disk = disk
fmap>>FM.zone = zone
resultis res
]
and morepageio(fmap, firstrn, scratch, npg, wflag) be
[ let pagesize, firstda = 1 lshift fmap>>FM.disk>>DSK.lnPageSize, LookupFmap(fmap, firstrn)
let zone = fmap>>FM.zone
if wflag eq -1 then
test zone eq -1
ifso [ scratch = pagesize; Dvec(morepageio, lv scratch) ]
ifnot scratch = Allocate(zone, pagesize)
let lastrn, lastmaprn = firstrn+npg, NextFmap(fmap)
let rn = lastmaprn-1
let DAs = vec ppc+2 // ppc+3 words!
DAs!0 = (rn eq 0? eofDA, LookupFmap(fmap, rn-1))
let nch = nil
while rn ls lastrn do
[ DAs!1 = LookupFmap(fmap, rn)
let np = Min(ppc, lastrn-rn)
SetBlock(DAs+2, fillInDA, np+1)
let nrn = ActOnDiskPages(fmap>>FM.disk, 0, DAs+1-rn, lv fmap>>FM.fp, rn, rn+np-1, DCreadD, lv nch, DCreadD, scratch)
if nch eq 0 then // extend file
test nrn eq rn
ifnot // too hard to pick up
np = nrn-rn
ifso
[ let nxp = fmap>>FM.extend
unless (nxp gr 0) & (wflag ne 0) do CallSwat("Attempt to access non-existent page")
if np ls nxp then np = nxp
Zero(scratch, pagesize)
SetBlock(DAs+2, fillInDA, np+1)
DAs!(np+2) = eofDA
WriteDiskPages(fmap>>FM.disk, 0, DAs+1-rn, lv fmap>>FM.fp, rn, rn+np, DCwriteD, 0, 0, scratch)
]
for j = 1 to np do
[ let xrn, xda = rn+j, DAs!(j+1)
ExtendFmap(fmap, xrn, xda)
if xrn eq firstrn then firstda = xda
]
DAs!0 = DAs!np
rn = rn+np
]
ExtendFmap(fmap, firstrn, firstda) // just in case map is full
if NextFmap(fmap) gr lastmaprn then WriteFmap(fmap)
if (wflag eq -1) & (zone ne -1) then Free(zone, scratch)
]
and WriteFmap(fmap) be
[ if fmap>>FM.rewrite then
[ ActOnDiskPages(fmap>>FM.disk, 0, lv fmap>>FM.DA0, lv fmap>>FM.fp, 1, 1, DCwriteD, 0, DCwriteD, fmap)
]
]
and ExtendFmap(fmap, rn, da) = valof
[ fmap>>FM.onern, fmap>>FM.oneda = rn, da
let last = fmap>>FM.last
let lastp = lv (fmap!last)
if rn ne @lastp then resultis false
let curva = da
test curva eq (lastp!-1)+@lastp-(lastp!-2)
ifso // still in same chunk
@lastp = @lastp+1
ifnot // start new chunk
test last eq fmap>>FM.end
ifso // out of space
resultis false
ifnot
[ lastp!1, lastp!2 = curva, @lastp+1
fmap>>FM.last = last+2
]
resultis true
]
// DCS, January 20, 1978 10:41 PM, file reassignments
// September 14, 1978 10:26 AM, InitFmap checks existence of file, check or not,
// returns false on check error (file with that fp does not exist)
// September 18, 1978 8:26 AM, if not checking and not check error (InitFmap), and if
// lvPages (new) arg supplied, fill it with numPages value from length hint in leader page
//