-- 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.