// IfsLeafInit.bcpl - Leaf server initialization
// Copyright Xerox Corporation 1979, 1980, 1981

// Last modified November 18, 1981  6:14 PM by Taft

get "IfsRs.decl";
get wordsPerPage from "IfsLeaf.decl";
get FD, lookupStatus, lsNonexistent, lcVHighest, lcCreate, modeWrite,
 modeReadWrite from "IfsDirs.decl";
get ecCantCreateVPBIFile, ecVPBIFileFD, ecCantOpenVPBIFile from
 "IfsLeafErrors.decl";
get "IfsFiles.decl";
get "IfsSequin.decl";
get "IfsLeafVMem.decl";

external
[
// outgoing procedures
InitLeaf; EnableLeaf; LeafFinish; LeafStartup; 

// incoming procedures
Block; CreateCtx; CreateEvent; DestroyCtx;
SysAllocate; SysAllocateZero; SysFree; IFSError; Noop; Zero;
AllocateVMem; OpenLeafVMem; AllocateVPBIPage;
LeafDOPAGEIO; LeafEvent; LeafPageGroupAlign; LeafPurgeVFile;
LeafPageGroupSize; LeafPageGroupBase; LeafPageType;
CloseIFSStream; DestroyJob; LookupIFSFile; GetBufferForFD;
OpenIFSStream; DeclarePupSoc; OpenLevel1Socket; PositionPage;
SequinCtx; SequinFeedCtx; SetTimer; TransferLeaderPage;

// outgoing statics
leafEcb; leafPresent; leafEnabled; leafVMI; scb; socLeaf; vpbiLVMD;

// incoming statics
CtxRunning; system;
]

static
[
leafEcb; scb; socLeaf;
leafPresent = true; leafEnabled = true; leafVMI = 0; vpbiLVMD = 0;
]

//---------------------------------------------------------------------------
let InitLeaf() be
//---------------------------------------------------------------------------
[
// Open the Leaf level 1 socket
socLeaf = SysAllocate(lenPupSoc);
OpenLevel1Socket(socLeaf, table [ 0; 0; socketLeaf ]);
leafEcb = CreateEvent(LeafEvent);

// Allocate the sequin control block.
scb = SysAllocateZero(lenSCB);
]

//---------------------------------------------------------------------------
and EnableLeaf(value) = valof
//---------------------------------------------------------------------------
// Enables or disables the Leaf server according to value.
// Returns true if the action is possible and false otherwise.
[
if value & not leafPresent then resultis false
leafEnabled = value
resultis true
]

//---------------------------------------------------------------------------
and LeafStartup() be
//---------------------------------------------------------------------------
[
// called from the Leaf context.
DeclarePupSoc(socLeaf);

// Init the vpbi allocation blocks.
InitAllocInfo(lv scb>>SCB.inputAllocInfo);
InitAllocInfo(lv scb>>SCB.outputAllocInfo);
SetTimer(lv scb>>SCB.reaperTimer, reaperInterval);

if leafVMI eq 0 then
   [
   // Set up Leaf VMem Interface
   leafVMI = SysAllocateZero(lenLeafVMI);
   leafVMI>>VMI.DOPAGEIO = LeafDOPAGEIO
   leafVMI>>VMI.CleanupLocks = Noop
   leafVMI>>VMI.PageType = LeafPageType
   leafVMI>>VMI.PageGroupBase = LeafPageGroupBase
   leafVMI>>VMI.PageGroupAlign = LeafPageGroupAlign
   leafVMI>>VMI.PageGroupSize = LeafPageGroupSize
   leafVMI>>VMI.type = vmiTypeLeaf

   for probe = 0 to lenLeafHashTable - 1 do
    leafVMI>>LeafVMI.hashTable↑probe = firstFreePage;
   leafVMI>>LeafVMI.freePage = firstFreePage + 1;

   AllocateVMem(lv leafVMI>>LeafVMI.vmd, leafVMI,
    leafVMemPages lshift logVPagesPerLeafPage);

   // Lookup/create vpbi swapping file.
   let filename = "VirtualPBI.swap"; CtxRunning>>RSCtx.userInfo = system;
   let ec = 0; let fd = LookupIFSFile(filename, lcVHighest+lcCreate, lv ec);
   if fd eq 0 then IFSError(ecVPBIFileFD);
   if fd>>FD.lookupStatus eq lsNonexistent then CreateVPBIFile(fd);
   vpbiLVMD = OpenLeafVMem(fd, modeReadWrite, lv ec);
   unless ec eq 0 do IFSError(ecCantOpenVPBIFile);
   ]

// Start up the other contexts.
scb>>SCB.sequinFeedCtx = CreateCtx(sequinFeedSS, SequinFeedCtx);
scb>>SCB.sequinCtx = CreateCtx(sequinSS, SequinCtx);
scb>>SCB.ctxCount = 3;
]

//----------------------------------------------------------------------------
and LeafFinish() be
//----------------------------------------------------------------------------
[
scb>>SCB.haltFlag = true; scb>>SCB.ctxCount = scb>>SCB.ctxCount - 1;
unless CtxRunning eq scb>>SCB.leafCtx do DestroyCtx();

until scb>>SCB.ctxCount eq 0 do Block();
DeclarePupSoc(0);

// All vpbis should be flushed by now.
LeafPurgeVFile(vpbiLVMD);
Zero(scb, offset SCB.staticParams/16);
DestroyJob();
]

//----------------------------------------------------------------------------
and CreateVPBIFile(fd, lvEc) be
//----------------------------------------------------------------------------
[
let str = OpenIFSStream(fd, lvEc, modeWrite);
if str eq 0 then IFSError(ecCantCreateVPBIFile);

let ild = GetBufferForFD(fd);
TransferLeaderPage(fd, ild);
let prot = lv ild>>ILD.fileProt;
Zero(prot, lenFileProt);
prot>>FileProt.readProt.owner = true;
prot>>FileProt.writeProt.owner = true;
ild>>ILD.noBackup = true;
TransferLeaderPage(fd, ild, true);
SysFree(ild);
PositionPage(str, lastVPBIPage, true);
CloseIFSStream(str);
]

//----------------------------------------------------------------------------
and InitAllocInfo(alloc) be
//----------------------------------------------------------------------------
[
let firstPage = AllocateVPBIPage();
alloc>>AllocInfo.vPageQ.head = firstPage;
alloc>>AllocInfo.vPageQ.tail = firstPage;
alloc>>AllocInfo.nextVPage = AllocateVPBIPage();
]