DIRECTORY
BasicTime USING[GMT],
Camelot USING[segmentIdT],
YggDIDPrivate USING[DIDRep],
YggInternal USING[Document, FileHandle],
YggEnvironment USING [DID, nullDID],
YggRep USING[nullTimeStamp, TimeStamp],
Documents
Document: TYPE = YggInternal.Document;
DocumentRep:
TYPE =
MONITORED
RECORD[
did: YggEnvironment.
DID,
-- id of this document
for links, the next three fields have non-trivial values
fromDID: YggEnvironment.DID ← YggEnvironment.nullDID,
toDID: YggEnvironment.DID ← YggEnvironment.nullDID,
linkType: Rope.ROPE ← NIL,
name: Rope.ROPE, -- human-legible name.
parsedDocList: LIST OF DocItem ← NIL,
modifiedDIDMap: BOOL ← FALSE,
timeStampForIndexMaint: YggRep.TimeStamp ← YggRep.nullTimeStamp,
componentFiles: LIST OF YggInternal.FileHandle,
interlock: BOOLEAN ← FALSE,
next: Document];
Disk resident B-tree entries
notCompressed: CARD = 0;
EntryPtr: TYPE = LONG BASE POINTER TO Entry;
DocPartPtr: TYPE = LONG BASE POINTER TO DocPart;
TextRP: TYPE = DocPartPtr RELATIVE POINTER TO TextRep;
TextRep: TYPE = MACHINE DEPENDENT RECORD [PACKED SEQUENCE length: CARDINAL OF CHAR];
PartType: TYPE = MACHINE DEPENDENT {root(0), contents(1), outlinks(2), attributes(3), index(4)};
Disk resident encoding of the variable fields for the DID map.
DocPart:
TYPE =
MACHINE
DEPENDENT
RECORD [
docPartSize(0): CARD, -- size in words of part
compression(1): CARD ← notCompressed,
keepingModifications(2:0..0): BOOL,
partType(2:1..4): PartType,
extraFlags(2:5..31): CARD [0..0FFFFFFh] ← 0,
slotNo(3): CARD ← 0,
indexName(4): TextRP ← NIL,
versionIdentifierString(5): TextRP ← NIL,
segments(6): CARD
];
SegmentRep:
TYPE =
MACHINE
DEPENDENT
RECORD [
firstPage(0): CARD,
numberOfBytes(1): CARD,
modificationDeltasOffset(2): CARD,
lastUsedTime(3): BasicTime.GMT,
backUpTime(4): BasicTime.GMT,
backUpID(5): CARD,
length(6): CARDINAL,
runs(7): SEQUENCE COMPUTED CARDINAL OF RunRep
];
RunRep:
TYPE =
MACHINE
DEPENDENT
RECORD [
segmentId: Camelot.segmentIdT,
segmentPage: CARD, -- offset in segment in pages
pages: INT -- for non-leader, number of pages (0 for leader)
];
Virtual memory resident versions the variable fields for the DID map.
DocItem:
TYPE =
RECORD [
partType: PartType,
indexName: ATOM ← NIL,
slotNo: CARD ← 0,
segments: LIST OF SegmentItem
];
SegmentItem:
TYPE =
RECORD [
firstPage: CARD,
numberOfBytes: CARD,
runs: LIST OF RunItem
];
RunItem:
TYPE =
RECORD [
segmentId: Camelot.segmentIdT,
segmentPage: CARD, -- offset in segment in pages
pages: INT -- for non-leader, number of pages (0 for leader)
];
OverheadPerEntry: CARD = 3;
The info for a DID is usually stored in one B-tree entry. However, the entry can grow too large. Hence, it can be split up into parts. The records are indexed by both did and extensionCount. The extensionCount is a flag for normal or extended records. If it is 0, this is a normal record and all the info is stored starting at the data field, and continuing to end-of-record. For extended records, the CARD at data is the total size of all of the info for the did. The rest of the words from the first record are concatenated with the words from the rest of the records.
The info is the link data and a list of DocPart's (see above.) The links are the from and to DIDs, followed by a string
Each DocPart starts with it's size (docPartSize). The last DocPart completely uses all of the space in the data part of the entry. The segments field in the DocPart is the start of the segment list for the DocPart. The segment list completely consumes all of the space indicated by the docPartSize field. Each segment has a list of runs, written as a SEQUENCE.
Entry:
TYPE =
MACHINE
DEPENDENT
RECORD [
size(0:0..15): CARD16, -- size in words of entire (physical) entry
link(0:16..16): BOOL , -- does a link follow?
extensionCount(0:17..31): [0..07fffh] , -- 0 for normal, 1 for normal with extentions, and 2 and up for extended entries
did(1): YggDIDPrivate.DIDRep, -- the bits for a DID
data(OverheadPerEntry): SEQUENCE COMPUTED CARD OF CARD -- see above
];