-- Transport Mechanism Filestore - private DEFS for heap object directory. --
-- [Idun]<WServices>MS>ObjectDirInternal.mesa
-- Randy Gobbel 30-Jul-82 14:48:08 --
-- Andrew Birrell 3-Jun-81 12:59:45 --
DIRECTORY
Bitmap USING [Map],
Environment USING [wordsPerPage],
NSString USING [nullString, String],
ObjectDir USING [Client, ObjectNumber, ObjectType, noObject],
ServerLog USING [Handle],
VMDefs USING [FileHandle, FullAddress, PageAddress, PageIndex,
PageNumber, pageSize];
ObjectDirInternal: DEFINITIONS =
BEGIN
ObjectNumber: TYPE = ObjectDir.ObjectNumber;
ObjectCount: TYPE = CARDINAL;
gapObjectNumber: ObjectNumber = ObjectDir.noObject;
-- an object number that 'NewObject' will never return --
NewObject: PROCEDURE
[VMDefs.FullAddress, ObjectDir.ObjectType, ObjectDir.Client]
RETURNS [ObjectNumber];
-- sets reference count to one --
ObjectBase: PROCEDURE [ObjectNumber, ObjectDir.Client]
RETURNS [VMDefs.FullAddress];
segmentSize: CARDINAL = 6; -- number of pages in a segment
headerSize: CARDINAL = SIZE[LONG INTEGER] + SIZE[SegmentIndex];
segmentsPerPage: CARDINAL =
Environment.wordsPerPage/SIZE[SegmentIndex] - headerSize;
SegmentIndex: TYPE = CARDINAL;
noSegment: SegmentIndex = LAST[SegmentIndex];
-- the 'written' chain is stored permanently on disk --
ChainBlock: TYPE = MACHINE DEPENDENT RECORD [
vp(0): SELECT OVERLAID * FROM
sh => [header(0): ARRAY [0..0) OF SerialAndHead],
chain =>
[next(0): ARRAY SegmentIndex [0..0) OF SegmentIndex],
ENDCASE];
SerialAndHead: TYPE = MACHINE DEPENDENT RECORD [
serialNumber(0): LONG INTEGER,
chainHead(2): SegmentIndex,
-- head of written chain, unused on all pages but first of chain file
fill(3): ARRAY [0..segmentsPerPage) OF UNSPECIFIED];
ObjDirPageNumber: TYPE = [0..PRED[endOfChain]];
DirData: TYPE = MACHINE DEPENDENT RECORD [
vp(0:0..63): SELECT freedom(0:0..0): * FROM
free => [
next(0:1..15): VMDefs.PageIndex,
dopc(1:0..31): ObjectDirInternal.DOPC],
used => [
type(0:1..4): ObjectDir.ObjectType,
word(0:5..15): VMDefs.PageIndex,
page(1): VMDefs.PageNumber,
count(3): ObjectCount],
ENDCASE];
DirPage: TYPE = RECORD [header: DirPageHeader, data: ARRAY DirIndex OF DirData];
endOfChain: CARDINAL = PRED[unchained]; -- "end of free chain"
unchained: CARDINAL = LAST[CARDINAL]; -- "not on free chain"
DirPageHeader: TYPE = RECORD [
nextFreePage: CARDINAL, nextFreeIndex: VMDefs.PageIndex];
entriesPerPage: CARDINAL =
(VMDefs.pageSize - SIZE[DirPageHeader])/SIZE[DirData];
DirIndex: TYPE = [0..entriesPerPage);
-- NOTE: DirIndex values must fit in the "index" field of an object number --
nullAddress: VMDefs.PageAddress = [NIL, 0];
Client: TYPE = LONG POINTER TO ClientObject;
ClientObject: TYPE = RECORD [
name: NSString.String ← NSString.nullString,
-- stuff from StableStorageImpl
chainHandle: VMDefs.FileHandle ← NIL,
chain: LONG POINTER TO ChainBlock ← NIL,
lastWritten: SegmentIndex ← 0, -- last segment allocated for a writer
lastChained: SegmentIndex ← 0, -- last segment chained onto chain.written
lastPage: VMDefs.PageAddress ← nullAddress, -- last page used in chain.written
freeCount: CARDINAL ← 0, -- number of free segments
freeMap: Bitmap.Map, -- free segment bitmap
segmentCeiling: CARDINAL ← 0, -- size of segment bitmap
handle: VMDefs.FileHandle ← NIL,
segmentCount: CARDINAL ← 0, -- number of segments
-- synchronisation for single-page writers - beware!
claimedPage: VMDefs.PageAddress ← nullAddress,
claimed: BOOLEAN ← FALSE,
unwrittenAllocation: BOOLEAN ← FALSE,
-- stuff from ObjectDirImpl
firstFreePage: CARDINAL ← endOfChain,
-- first page containing free numbers
dirHandle: VMDefs.FileHandle ← NIL,
nextVirginPage: CARDINAL ← 0, -- current size of file
dpNumber: ObjDirPageNumber ← 0,
dpPage: LONG POINTER TO DirPage ← NIL,
lastDofpc: ObjectDirInternal.DOPC ← 0,
log: ServerLog.Handle,
zone: UNCOUNTED ZONE];
-- Compactor interface --
DOPC: TYPE = LONG CARDINAL;
-- "DeletedObjectPageCount"; see comments in GetObjectState
ObjectState: TYPE = {inUse, unused, duplicate};
GetObjectState: PROCEDURE [
obj: ObjectNumber,
where: VMDefs.FullAddress,
dorpc: DOPC, -- "r" = read --
client: ObjectDir.Client]
RETURNS [ObjectState];
-- If object's reference count is non-zero, returns "inUse".
-- If reference count is zero, but base#where, returns "duplicate"
-- Otherwise returns "unused", and marks object as free with dopc=dorpc
-- Object numbers are re-used only if their dopc is <= compactor's
-- most recently reported dofpc.
ReportDofpc: PROCEDURE
[dofpc: DOPC -- "f" = flushed --, client: ObjectDir.Client];
-- Compactor has overwritten objects whose dopc is <= dofpc.
MoveObject: PROCEDURE
[ObjectNumber, VMDefs.FullAddress, ObjectDir.Client];
-- Compactor has moved start of object to given address --
END.