// IfsScav2-1.bcpl - Pass 2 Phase 1
// Copyright Xerox Corporation 1979, 1980, 1981
// Last modified July 14, 1981  3:55 PM by Boggs

get "AltoFileSys.d"

external
[
// outgoing procedures
Pass2Phase1

// incoming procedures
PutTemplate; Ws; InitializeZone; Sort
ReadLPTE; WriteLPTE; GetLptSorted; SetLptSorted
Gets; Resets; TruncateDiskStream; FlushLPT; CompareLPTEs
GetLpteIfsName; GetLpteLength; GetLpteType
PrintTime; ReadCalendar; Usc; SysErr; Unqueue

// incoming statics
dsp; keys; debugFlag; scratchDisk; numFiles; phase; lpt
chunkQ
]

structure String [ length byte; char↑1,1 byte ]

//---------------------------------------------------------------------------
let Pass2Phase1(buffPtr, numBuffs) = valof
//---------------------------------------------------------------------------
// This phase sorts the leader page table for use by phase 3.
// The more memory available to the sort package, the faster things go.
// Pass2 starts in resident code with no paging buffers in use and
//  allocates as much contiguous space as it can, leaving just enough
//  slop for the intermediate sort files and the sort overlays.
[
Ws("*N[2-1]"); if debugFlag then Gets(keys)
if GetLptSorted(lpt) then
   [ Ws("*N[2-1] LPT is already sorted"); resultis true ]
phase, numFiles = 1, 0
Resets(lpt)
let sortZone = InitializeZone(buffPtr, 256*numBuffs, SysErr, 0)
// InitializeZone calls IfsAddToZone, which queues a chunk descriptor
//  on chunkQ.  Since sortZone is not part of sysZone, this is bad.
Unqueue(chunkQ, chunkQ!1)
let startTime = vec 1; ReadCalendar(startTime)
Sort(GetLpte, PutLpte, CompareLPTEs, 25, 256, sortZone, scratchDisk)
PrintTime(startTime)
PutTemplate(dsp, "*N[2-1] Number of files = $UD", numFiles)
PutTemplate(dsp, "*N[2-1] SortZone size = $D words", 256*numBuffs)
TruncateDiskStream(lpt)  //we may have squeezed out some deleted entries
SetLptSorted(lpt, true)
FlushLPT(lpt) 
resultis true
]

//---------------------------------------------------------------------------
and GetLpte(lpte, nil) = valof
//---------------------------------------------------------------------------
// Gets the next lpte to be added to the sort
[
unless ReadLPTE(lpt, lpte) resultis 0
if GetLpteType(lpte) ne dvTypeFile loop
resultis GetLpteLength(lpte)
] repeat

//---------------------------------------------------------------------------
and PutLpte(lpte, length) be
//---------------------------------------------------------------------------
// Puts a sorted lpte into the output file
[
if numFiles eq 0 then
   [
   //first output record - overwrite input!
   Resets(lpt)
   ReadLPTE(lpt)  //don't overwrite home block
   ]
numFiles = numFiles +1
WriteLPTE(lpt, lpte)
]