DIRECTORY Rope USING [Equal, Find, InlineFetch, Length, ROPE], PBasics USING [ByteBlt], YggDID USING [DID, EqualDIDs, ValidateDID], YggDIDMap USING [AddRootDID, CreateNewDID, DestroyDID, GetRootDIDs, RemoveRootDID], YggDIDPrivate USING [DIDRep], YggEnvironment USING [nullDID, nullTransID, Outcome, TransID], YggFixedNames USING [], YggIndex USING [], YggIndexMaint USING [AddOrRemoveIndexPattern], YggNav USING [ErrorDesc, LinkList], YggRep USING [AccurateGMT, AccurateGMTRep, Attribute, AttributeValue, Bits, BitsRep, BytesFromBits, BytesToBits, date, did, DocType, float, int, lastReservedDocType, LatchVDoc, linkMod, metaAttributeMod, noValue, rope, shortRope, SetSizeOfBits, SizeOfBits, symbolicLink, TypedPrimitiveElement, UnlatchVDoc, uninterpretedBytes, VDoc, VolatizeFromDID], YggTransaction USING [Check, CreateTrans, Finish, GetDefaultContainer, NotePossibleDocumentUpdate, SetDefaultContainer]; YggNavImpl: CEDAR MONITOR IMPORTS PBasics, Rope, YggDID, YggDIDMap, YggIndexMaint, YggRep, YggTransaction EXPORTS YggDID, YggFixedNames, YggNav ~ BEGIN ROPE: TYPE = Rope.ROPE; Error: PUBLIC ERROR [error: YggNav.ErrorDesc] = CODE; DID: PUBLIC TYPE ~ REF DIDRep; DIDRep: PUBLIC TYPE ~ YggDIDPrivate.DIDRep; NoBytes: YggRep.Bits; Contents: PUBLIC Rope.ROPE _ "$contents"; Inlinks: PUBLIC Rope.ROPE _ "$inlinks"; Outlinks: PUBLIC Rope.ROPE _ "$outlinks"; Parents: PUBLIC Rope.ROPE _ "$parents"; Children: PUBLIC Rope.ROPE _ "$children"; ParentContainers: PUBLIC Rope.ROPE _ "$parent-containers"; ChildContainers: PUBLIC Rope.ROPE _ "$child-containers"; AutoIndices: PUBLIC Rope.ROPE _ "$auto-indices"; IndexPrefix: PUBLIC Rope.ROPE _ "$index-"; IndexPrefixSize: PUBLIC INT _ Rope.Length[IndexPrefix]; DirectoryContents: PUBLIC Rope.ROPE _ "$directoryContents"; NFSPropertyName: PUBLIC Rope.ROPE _ "$NFSProperites"; -- NFS (UNIX) properties StartTransaction: PUBLIC PROC [parentTrans: YggEnvironment.TransID] RETURNS [trans: YggEnvironment.TransID] ~ { trans _ YggTransaction.CreateTrans[parentTrans]; }; EndTransaction: PUBLIC PROC [trans: YggEnvironment.TransID, commit: BOOL] RETURNS [ok: BOOL _ TRUE] ~ { outcome: YggEnvironment.Outcome; [outcome: outcome] _ YggTransaction.Finish[transID: trans, requestedOutcome: IF commit THEN commit ELSE abort]; IF outcome = commit THEN RETURN [TRUE] ELSE RETURN [FALSE]; }; CheckTransaction: PUBLIC PROC [trans: YggEnvironment.TransID] RETURNS [found: BOOL _ FALSE, active: BOOL _ FALSE, committed: BOOL _ FALSE] ~ { outcome: YggEnvironment.Outcome; [outcome: outcome] _ YggTransaction.Check[transID: trans]; SELECT outcome FROM active => RETURN [TRUE, TRUE, FALSE]; abort => RETURN [TRUE, FALSE, FALSE]; commit => RETURN [TRUE, FALSE, TRUE]; unknown => RETURN [FALSE, FALSE, FALSE]; suspended => RETURN [TRUE, FALSE, FALSE]; ENDCASE => ERROR; }; GetRoots: PUBLIC PROC RETURNS [roots: LIST OF DID] ~ { roots _ YggDIDMap.GetRootDIDs[]; }; AddRoot: PUBLIC PROC [did: DID] RETURNS [ok: BOOL _ FALSE] ~ { IF ~YggDID.ValidateDID[did] THEN RETURN [FALSE]; ok _ YggDIDMap.AddRootDID[did]; }; RemoveRoot: PUBLIC PROC [did: DID] RETURNS [ok: BOOL _ TRUE] ~ { IF ~YggDID.ValidateDID[did] THEN RETURN [FALSE]; ok _ YggDIDMap.RemoveRootDID[did]; }; GetTypeOfContents: PUBLIC PROC [trans: YggEnvironment.TransID, did: YggDID.DID] RETURNS [YggRep.DocType] ~ { document: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did]; RETURN[document.contents.docType]; }; IsDocTypeUninterpretedOK: PROC [docType: YggRep.DocType] RETURNS [ok: BOOL] ~ { IF docType # YggRep.uninterpretedBytes AND docType # YggRep.symbolicLink AND docType <= YggRep.lastReservedDocType THEN RETURN [TRUE] ELSE RETURN [FALSE]; }; GetUninterpretedContents: PUBLIC UNSAFE PROC [trans: YggEnvironment.TransID, did: DID, firstByte: CARD, byteCount: CARD, to: LONG POINTER] RETURNS [bytesMoved: CARD] ~ { document: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did]; [] _ YggRep.LatchVDoc[document]; IF IsDocTypeUninterpretedOK[document.contents.docType] THEN { IF ~YggRep.UnlatchVDoc[document] THEN ERROR; ERROR Error[[$invalidReservedType, "Attempt to access a TypedPrimitiveElement with reserved type as uninterpreted"]]; }; YggRep.BytesFromBits[bits: document.contents.bits, startByte: firstByte, block: [base: LOOPHOLE[to], startIndex: 0, count: byteCount]]; bytesMoved _ byteCount; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; GetContents: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] RETURNS [contents: YggRep.TypedPrimitiveElement] ~ { document: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did]; [] _ YggRep.LatchVDoc[document]; contents _ document.contents; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; SetUninterpretedContents: PUBLIC UNSAFE PROC [trans: YggEnvironment.TransID, did: YggDID.DID, setDocType: BOOL, docType: YggRep.DocType, firstByte: CARD, byteCount: CARD, from: LONG POINTER] RETURNS [bytesMoved: CARD] ~ { document: YggRep.VDoc; newRef: BOOL; newBits: YggRep.Bits; oldContentsBits: YggRep.Bits; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did, readWrite, [write, wait]]; [] _ YggRep.LatchVDoc[document]; IF setDocType THEN { IF IsDocTypeUninterpretedOK[docType] THEN { IF ~YggRep.UnlatchVDoc[document] THEN ERROR; ERROR Error[[$invalidReservedType, "Attempt to set a TypedPrimitiveElement with reserved type as uninterpreted"]]; }; document.contents.docType _ docType; oldContentsBits _ NoBytes; } ELSE { IF IsDocTypeUninterpretedOK[document.contents.docType] THEN { IF ~YggRep.UnlatchVDoc[document] THEN ERROR; ERROR Error[[$invalidReservedType, "Attempt to set a TypedPrimitiveElement with reserved type as uninterpreted"]]; }; oldContentsBits _ document.contents.bits; }; [newRef: newRef, newBits: newBits] _ YggRep.BytesToBits[bits: oldContentsBits, startByte: firstByte, block: [base: LOOPHOLE[from], startIndex: 0, count: byteCount]]; IF newRef THEN document.contents.bits _ newBits; document.contentsChanged _ TRUE; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; RETURN[byteCount]; }; SetContents: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, contents: YggRep.TypedPrimitiveElement] ~ { document: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did, readWrite, [write, wait]]; [] _ YggRep.LatchVDoc[document]; document.contents _ contents; document.contentsChanged _ TRUE; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; GetSize: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] RETURNS [size: CARD] ~ { document: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did, readWrite, [write, wait]]; [] _ YggRep.LatchVDoc[document]; IF IsDocTypeUninterpretedOK[document.contents.docType] THEN { IF ~YggRep.UnlatchVDoc[document] THEN ERROR; ERROR Error[[$invalidReservedType, "Attempt to get the size of a TypedPrimitiveElement with reserved type as uninterpreted"]]; }; size _ YggRep.SizeOfBits[bits: document.contents.bits]; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; SetSize: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, size: CARD] ~ { document: YggRep.VDoc; newRef: BOOL; newBits: YggRep.Bits; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did, readWrite, [write, wait]]; [] _ YggRep.LatchVDoc[document]; IF IsDocTypeUninterpretedOK[document.contents.docType] THEN { IF ~YggRep.UnlatchVDoc[document] THEN ERROR; ERROR Error[[$invalidReservedType, "Attempt to set a TypedPrimitiveElement with reserved type as uninterpreted"]]; }; IF YggRep.SizeOfBits[bits: document.contents.bits] # size THEN { [newRef: newRef, newBits: newBits] _ YggRep.SetSizeOfBits[bits: document.contents.bits, size: size]; IF newRef THEN document.contents.bits _ newBits; document.contentsChanged _ TRUE; }; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; GetProperty: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, propertyName: ROPE] RETURNS [propertyExists: BOOL _ FALSE, property: LIST OF YggRep.Attribute _ NIL] ~ { document: YggRep.VDoc; metaAttributesOnly: BOOL _ FALSE; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; IF Rope.Length[propertyName] > 0 THEN { IF Rope.InlineFetch[propertyName, 0] = '$ THEN metaAttributesOnly _ TRUE; }; document _ YggRep.VolatizeFromDID[transID: trans, did: did, metaAttributesOnly: metaAttributesOnly]; [] _ YggRep.LatchVDoc[document]; FOR aL: LIST OF YggRep.Attribute _ document.attributes, aL.rest UNTIL aL = NIL DO IF Rope.Equal[aL.first.attributeName, propertyName] THEN { property _ CONS[aL.first, property]; propertyExists _ TRUE; }; ENDLOOP; FOR aL: LIST OF YggRep.Attribute _ document.metaAttributes, aL.rest UNTIL aL = NIL DO IF Rope.Equal[aL.first.attributeName, propertyName] THEN { property _ CONS[aL.first, property]; propertyExists _ TRUE; }; ENDLOOP; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; GetAllProperties: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] RETURNS [properties: LIST OF YggRep.Attribute] ~ { document: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did]; RETURN[document.attributes]; }; ListAllProperties: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] RETURNS [propertyNames: LIST OF ROPE _ NIL] ~ { document: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did]; [] _ YggRep.LatchVDoc[document]; FOR aL: LIST OF YggRep.Attribute _ document.attributes, aL.rest UNTIL aL = NIL DO FOR pN: LIST OF ROPE _ propertyNames, pN.rest UNTIL pN = NIL DO IF Rope.Equal[aL.first.attributeName, pN.first] THEN EXIT; REPEAT FINISHED => { propertyNames _ CONS[aL.first.attributeName, propertyNames]; }; ENDLOOP; ENDLOOP; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; SetProperty: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, propertyName: ROPE, property: YggRep.Attribute, appendProperty: BOOL] ~ { document: YggRep.VDoc; somethingChanged: BOOL _ FALSE; prev: LIST OF YggRep.Attribute _ NIL; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did, readWrite, [write, wait]]; [] _ YggRep.LatchVDoc[document]; SELECT TRUE FROM appendProperty AND property.value = NIL => NULL; -- nothing to do appendProperty AND property.value # NIL => { -- add prop to end of list somethingChanged _ TRUE; IF document.attributes = NIL THEN document.attributes _ LIST[property] ELSE { FOR aL: LIST OF YggRep.Attribute _ document.attributes, aL.rest UNTIL aL = NIL DO IF aL.rest = NIL THEN {aL.rest _ LIST[property]; EXIT}; ENDLOOP; }; }; ~appendProperty AND property.value = NIL => { -- delete all props of this name IF document.attributes = NIL THEN RETURN -- nothing to do ELSE { FOR aL: LIST OF YggRep.Attribute _ document.attributes, aL.rest UNTIL aL = NIL DO IF Rope.Equal[aL.first.attributeName, propertyName] THEN { somethingChanged _ TRUE; IF prev = NIL THEN document.attributes _ aL.rest ELSE prev.rest _ aL.rest; LOOP; }; prev _ aL; ENDLOOP; }; }; ~appendProperty AND property.value # NIL => { -- delete all props of this name and add this one somethingChanged _ TRUE; IF document.attributes = NIL THEN document.attributes _ LIST[property] ELSE { FOR aL: LIST OF YggRep.Attribute _ document.attributes, aL.rest UNTIL aL = NIL DO IF Rope.Equal[aL.first.attributeName, propertyName] THEN { somethingChanged _ TRUE; IF prev = NIL THEN document.attributes _ aL.rest ELSE prev.rest _ aL.rest; LOOP; }; prev _ aL; ENDLOOP; IF prev = NIL THEN document.attributes _ LIST[property] ELSE prev.rest _ LIST[property]; }; }; ENDCASE; IF somethingChanged THEN { FOR aC: LIST OF ROPE _ document.namesOfAttributesChanged, aC.rest UNTIL aC = NIL DO IF Rope.Equal[aC.first, propertyName] THEN EXIT; REPEAT FINISHED => { document.namesOfAttributesChanged _ CONS[propertyName, document.namesOfAttributesChanged]; }; ENDLOOP; }; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; ConstructIntTPE: PUBLIC PROC [int: INT32] RETURNS [property: YggRep.TypedPrimitiveElement] ~ { ri: REF INT32; ri _ NEW[INT32 _ int]; property _ [YggRep.int, ri]; }; ConstructFloatTPE: PUBLIC PROC [float: REAL32] RETURNS [property: YggRep.TypedPrimitiveElement] ~ { rReal: REF REAL32; rReal _ NEW[REAL32 _ float]; property _ [YggRep.float, rReal]; }; ConstructDateTPE: PUBLIC PROC [date: YggRep.AccurateGMTRep] RETURNS [property: YggRep.TypedPrimitiveElement] ~ { rAccurateGMT: YggRep.AccurateGMT; rAccurateGMT _ NEW[YggRep.AccurateGMTRep _ date]; property _ [YggRep.date, rAccurateGMT]; }; ConstructShortRopeTPE: PUBLIC PROC [rope: ROPE] RETURNS [property: YggRep.TypedPrimitiveElement] ~ { IF Rope.Find[rope, "\000"] = -1 THEN { property _ [YggRep.shortRope, rope]; } ELSE ERROR Error[[$shortRopeWithNulls, "Rope has nulls"]]; }; ConstructRopeTPE: PUBLIC PROC [rope: ROPE] RETURNS [property: YggRep.TypedPrimitiveElement] ~ { property _ [YggRep.rope, rope]; }; ConstructUninterpretedBytesTPE: PUBLIC PROC [docType: YggRep.DocType, bytes: LONG POINTER, size: CARD] RETURNS [property: YggRep.TypedPrimitiveElement] ~ { nBytes: CARD; rBits: REF YggRep.BitsRep; IF IsDocTypeUninterpretedOK[docType] THEN ERROR Error[[$invalidReservedType, "Attempt to create a TypedPrimitiveElement with reserved type"]]; rBits _ NEW[YggRep.BitsRep[size]]; rBits.validBytes _ size; TRUSTED {nBytes _ PBasics.ByteBlt[ from: [blockPointer: bytes, startIndex: 0, stopIndexPlusOne: size], to: [blockPointer: LOOPHOLE[rBits, LONG POINTER] + SIZE[YggRep.BitsRep[0]], startIndex: 0, stopIndexPlusOne: size]]; }; IF nBytes # size THEN ERROR; property _ [docType, rBits]; }; getTypedLinks: PROC [links: LIST OF YggRep.AttributeValue, linksChanged: LIST OF YggRep.linkMod, linkType: ROPE] RETURNS [dids: LIST OF DID _ NIL] ~ { lastDIDs: LIST OF DID _ NIL; FOR linkList: LIST OF YggRep.AttributeValue _ links, linkList.rest UNTIL linkList = NIL DO IF linkType = NIL OR Rope.Equal[linkType, linkList.first.fieldName, FALSE] THEN { FOR lotpe: LIST OF YggRep.TypedPrimitiveElement _ linkList.first.valueSet, lotpe.rest UNTIL lotpe = NIL DO linkDID: DID; IF lotpe.first.docType # YggRep.did THEN ERROR; linkDID _ NARROW[lotpe.first.bits]; IF dids = NIL THEN lastDIDs _ (dids _ LIST[linkDID]) ELSE lastDIDs.rest _ LIST[linkDID]; ENDLOOP; }; ENDLOOP; FOR lolm: LIST OF YggRep.linkMod _ linksChanged, lolm.rest UNTIL lolm = NIL DO IF linkType = NIL AND ~Rope.Equal[lolm.first.linkName, linkType, FALSE] THEN LOOP; IF lolm.first.add THEN { IF lastDIDs = NIL THEN lastDIDs _ (dids _ LIST[lolm.first.linkValue]) ELSE lastDIDs.rest _ LIST[lolm.first.linkValue]; } ELSE { prevLod: LIST OF DID _ NIL; FOR lod: LIST OF DID _ dids, lod.rest UNTIL lod = NIL DO IF YggDID.EqualDIDs[lod.first, lolm.first.linkValue] THEN { IF prevLod = NIL THEN dids _ dids.rest ELSE prevLod.rest _ lod.rest; IF lastDIDs = lod THEN lastDIDs _ prevLod; EXIT; }; prevLod _ lod; ENDLOOP; }; ENDLOOP; }; getLinks: PROC [links: LIST OF YggRep.AttributeValue, linksChanged: LIST OF YggRep.linkMod] RETURNS [currentLinks: LIST OF YggNav.LinkList _ NIL] ~ { lastCurrentLinks: LIST OF YggNav.LinkList _ NIL; FOR linkList: LIST OF YggRep.AttributeValue _ links, linkList.rest UNTIL linkList = NIL DO dids: LIST OF DID _ NIL; lastDIDs: LIST OF DID _ NIL; FOR lotpe: LIST OF YggRep.TypedPrimitiveElement _ linkList.first.valueSet, lotpe.rest UNTIL lotpe = NIL DO linkDID: DID; IF lotpe.first.docType # YggRep.did THEN ERROR; linkDID _ NARROW[lotpe.first.bits]; IF dids = NIL THEN lastDIDs _ (dids _ LIST[linkDID]) ELSE lastDIDs.rest _ LIST[linkDID]; ENDLOOP; IF currentLinks = NIL THEN currentLinks _ lastCurrentLinks _ LIST[[linkList.first.fieldName, dids]] ELSE lastCurrentLinks.rest _ LIST[[linkList.first.fieldName, dids]]; ENDLOOP; FOR lolm: LIST OF YggRep.linkMod _ linksChanged, lolm.rest UNTIL lolm = NIL DO FOR curLnk: LIST OF YggNav.LinkList _ currentLinks, curLnk.rest UNTIL curLnk = NIL DO IF ~Rope.Equal[curLnk.first.linkName, lolm.first.linkName, FALSE] THEN LOOP; IF lolm.first.add THEN { curLnk.first.dids _ CONS[lolm.first.linkValue, curLnk.first.dids]; } ELSE { prevLod: LIST OF DID _ NIL; FOR lod: LIST OF DID _ curLnk.first.dids, lod.rest UNTIL lod = NIL DO IF YggDID.EqualDIDs[lod.first, lolm.first.linkValue] THEN { IF prevLod = NIL THEN curLnk.first.dids _ curLnk.first.dids.rest ELSE prevLod.rest _ lod.rest; EXIT; }; prevLod _ lod; ENDLOOP; }; REPEAT FINISHED => IF lolm.first.add THEN { IF currentLinks = NIL THEN currentLinks _ lastCurrentLinks _ LIST[[lolm.first.linkName, LIST [lolm.first.linkValue]]] ELSE lastCurrentLinks.rest _ LIST[[lolm.first.linkName, LIST [lolm.first.linkValue]]]; }; ENDLOOP; ENDLOOP; }; GetTypedOutlinks: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, linkType: ROPE] RETURNS [outlinks: LIST OF DID _ NIL] ~ { document: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did, readOnly, [read, wait]]; [] _ YggRep.LatchVDoc[document]; outlinks _ getTypedLinks[document.outlinks, document.outlinksChanged, linkType]; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; GetAllOutlinks: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] RETURNS [outlinks: LIST OF YggNav.LinkList _ NIL] ~ { document: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did, readOnly, [read, wait]]; [] _ YggRep.LatchVDoc[document]; outlinks _ getLinks[document.outlinks, document.outlinksChanged]; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; GetTypedInlinks: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, linkType: ROPE] RETURNS [inlinks: LIST OF DID _ NIL] ~ { document: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did, readOnly, [read, wait]]; [] _ YggRep.LatchVDoc[document]; inlinks _ getTypedLinks[document.inlinks, document.inlinksChanged, linkType]; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; GetAllInlinks: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] RETURNS [inlinks: LIST OF YggNav.LinkList _ NIL] ~ { document: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did, readOnly, [read, wait]]; [] _ YggRep.LatchVDoc[document]; inlinks _ getLinks[document.inlinks, document.inlinksChanged]; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; SnapLink: PUBLIC PROC [trans: YggEnvironment.TransID, fromDID: DID, toDID: DID, linkType: ROPE] RETURNS [linkDID: DID _ NIL] ~ { lastLinkMod: LIST OF YggRep.linkMod _ NIL; newLinkMod: LIST OF YggRep.linkMod _ NIL; fromVDoc: YggRep.VDoc; toVDoc: YggRep.VDoc; linkVDoc: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; fromVDoc _ YggRep.VolatizeFromDID[trans, fromDID, readWrite, [write, wait]]; toVDoc _ YggRep.VolatizeFromDID[trans, toDID, readOnly, [read, wait]]; [] _ YggRep.LatchVDoc[fromVDoc]; FOR lolm: LIST OF YggRep.linkMod _ fromVDoc.outlinksChanged, lolm.rest UNTIL lolm = NIL DO lastLinkMod _ lolm; ENDLOOP; linkDID _ YggDIDMap.CreateNewDID[trans]; linkVDoc _ YggRep.VolatizeFromDID[trans, linkDID, readWrite, [write, wait]]; linkVDoc.fromDID _ fromDID; linkVDoc.toDID _ toDID; linkVDoc.linkType _ linkType; linkVDoc.contents.docType _ YggRep.noValue; linkVDoc.linkChanged _ TRUE; newLinkMod _ LIST[[TRUE, linkType, linkDID]]; IF lastLinkMod = NIL THEN fromVDoc.outlinksChanged _ newLinkMod ELSE lastLinkMod.rest _ newLinkMod; IF ~YggRep.UnlatchVDoc[fromVDoc] THEN ERROR; [] _ YggRep.LatchVDoc[toVDoc]; lastLinkMod _ NIL; FOR lolm: LIST OF YggRep.linkMod _ toVDoc.inlinksChanged, lolm.rest UNTIL lolm = NIL DO lastLinkMod _ lolm; ENDLOOP; newLinkMod _ LIST[[TRUE, linkType, linkDID]]; IF lastLinkMod = NIL THEN toVDoc.inlinksChanged _ newLinkMod ELSE lastLinkMod.rest _ newLinkMod; YggTransaction.NotePossibleDocumentUpdate[trans, toVDoc]; IF ~YggRep.UnlatchVDoc[toVDoc] THEN ERROR; }; RemoveLink: PUBLIC PROC [trans: YggEnvironment.TransID, linkDID: YggDID.DID] ~ { lastLinkMod: LIST OF YggRep.linkMod _ NIL; newLinkMod: LIST OF YggRep.linkMod _ NIL; fromVDoc: YggRep.VDoc; toVDoc: YggRep.VDoc; linkVDoc: YggRep.VDoc; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; linkVDoc _ YggRep.VolatizeFromDID[trans, linkDID, readWrite, [write, wait]]; [] _ YggRep.LatchVDoc[linkVDoc]; fromVDoc _ YggRep.VolatizeFromDID[trans, linkVDoc.fromDID, readWrite, [write, wait]]; toVDoc _ YggRep.VolatizeFromDID[trans, linkVDoc.toDID, readOnly, [read, wait], TRUE]; YggDIDMap.DestroyDID[trans, linkDID]; IF ~YggRep.UnlatchVDoc[linkVDoc] THEN ERROR; [] _ YggRep.LatchVDoc[fromVDoc]; FOR lolm: LIST OF YggRep.linkMod _ fromVDoc.outlinksChanged, lolm.rest UNTIL lolm = NIL DO lastLinkMod _ lolm; ENDLOOP; newLinkMod _ LIST[[FALSE, linkVDoc.linkType, linkDID]]; IF lastLinkMod = NIL THEN fromVDoc.outlinksChanged _ newLinkMod ELSE lastLinkMod.rest _ newLinkMod; IF ~YggRep.UnlatchVDoc[fromVDoc] THEN ERROR; [] _ YggRep.LatchVDoc[toVDoc]; lastLinkMod _ NIL; FOR lolm: LIST OF YggRep.linkMod _ toVDoc.inlinksChanged, lolm.rest UNTIL lolm = NIL DO lastLinkMod _ lolm; ENDLOOP; newLinkMod _ LIST[[FALSE, linkVDoc.linkType, linkDID]]; IF lastLinkMod = NIL THEN toVDoc.inlinksChanged _ newLinkMod ELSE lastLinkMod.rest _ newLinkMod; YggTransaction.NotePossibleDocumentUpdate[trans, toVDoc]; IF ~YggRep.UnlatchVDoc[toVDoc] THEN ERROR; }; GetDefaultContainer: PUBLIC PROC [trans: YggEnvironment.TransID] RETURNS [did: DID _ NIL] ~ { IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; did _ YggTransaction.GetDefaultContainer[trans]; }; SetDefaultContainer: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] ~ { IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; YggTransaction.SetDefaultContainer[trans, did]; }; AddToContainer: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, containerDID: DID] ~ { IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; addOrRemoveContainer[trans, did, containerDID, TRUE, Parents, Children]; }; RemoveFromContainer: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, containerDID: DID] RETURNS [ok: BOOL _ TRUE] ~ { IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; addOrRemoveContainer[trans, did, containerDID, FALSE, Parents, Children]; }; GetObjectsInContainer: PUBLIC PROC [trans: YggEnvironment.TransID, containerDID: DID, dontWait: BOOL] RETURNS [dids: LIST OF DID, success: BOOL] ~ { IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; [dids, success] _ listContainer [trans, containerDID, Children, dontWait]; }; GetParents: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID, dontWait: BOOL] RETURNS [dids: LIST OF DID _ NIL, success: BOOL] ~ { [dids, success] _ listContainer [trans, did, Parents, dontWait]; }; AddContainerToContainer: PUBLIC PROC [trans: YggEnvironment.TransID, subcontainerDID: DID, containerDID: DID] ~ { IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; addOrRemoveContainer[trans, subcontainerDID, containerDID, TRUE, ParentContainers, ChildContainers]; }; RemoveContainerFromContainer: PUBLIC PROC [trans: YggEnvironment.TransID, subcontainerDID: DID, containerDID: DID] RETURNS [ok: BOOL _ TRUE] ~ { IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; addOrRemoveContainer[trans, subcontainerDID, containerDID, FALSE, ParentContainers, ChildContainers]; }; GetContainersInContainer: PUBLIC PROC [trans: YggEnvironment.TransID, containerDID: DID, dontWait: BOOL] RETURNS [dids: LIST OF DID _ NIL, success: BOOL] ~ { IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; [dids, success] _ listContainer [trans, containerDID, ChildContainers, dontWait]; }; GetSuperContainers: PUBLIC PROC [trans: YggEnvironment.TransID, containerDID: DID, dontWait: BOOL] RETURNS [dids: LIST OF DID _ NIL, success: BOOL] ~ { IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; [dids, success] _ listContainer [trans, containerDID, ParentContainers, dontWait]; }; addOrRemoveContainer: PROC [trans: YggEnvironment.TransID, did: DID, containerDID: DID, add: BOOL, pAN: ROPE, cN: ROPE, dontLatchDoc: BOOL _ FALSE] ~ { document: YggRep.VDoc; containerDocument: YggRep.VDoc; newCVal: LIST OF YggRep.metaAttributeMod; document _ YggRep.VolatizeFromDID[trans, did, readWrite, [write, wait]]; IF ~dontLatchDoc THEN { [] _ YggRep.LatchVDoc[document]; }; newCVal _ LIST [[attributeName: pAN, add: add, didValue: containerDID, stringValue: NIL]]; IF document.metaAttributesChanged = NIL THEN document.metaAttributesChanged _ newCVal ELSE { prev: LIST OF YggRep.metaAttributeMod _ NIL; FOR macl: LIST OF YggRep.metaAttributeMod _ document.metaAttributesChanged, macl.rest UNTIL macl = NIL DO prev _ macl; ENDLOOP; prev.rest _ newCVal; }; IF ~dontLatchDoc THEN { IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; containerDocument _ YggRep.VolatizeFromDID[trans, containerDID, readWrite, [write, wait]]; [] _ YggRep.LatchVDoc[containerDocument]; newCVal _ LIST [[attributeName: cN, add: add, didValue: did, stringValue: NIL]]; IF containerDocument.metaAttributesChanged = NIL THEN containerDocument.metaAttributesChanged _ newCVal ELSE { prev: LIST OF YggRep.metaAttributeMod _ NIL; FOR macl: LIST OF YggRep.metaAttributeMod _ containerDocument.metaAttributesChanged, macl.rest UNTIL macl = NIL DO prev _ macl; ENDLOOP; prev.rest _ newCVal; }; [] _ YggRep.UnlatchVDoc[containerDocument]; }; listContainer: PROC [trans: YggEnvironment.TransID, did: DID, pAN: ROPE, dontWait: BOOL, dontLatch: BOOL _ FALSE] RETURNS[didList: LIST OF DID _ NIL, success: BOOL _ TRUE] ~ { document: YggRep.VDoc; lastDidList: LIST OF DID _ NIL; didCountItem: TYPE = RECORD [ count: INT _ 0, did: DID ]; modifiedDIDs: LIST OF didCountItem _ NIL; stdValues: LIST OF YggRep.TypedPrimitiveElement _ NIL; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; document _ YggRep.VolatizeFromDID[trans, did, readWrite, [write, IF dontWait THEN fail ELSE wait]]; IF ~dontLatch THEN { IF ~YggRep.LatchVDoc[document, ~dontWait] THEN RETURN[NIL, FALSE]; }; FOR loa: LIST OF YggRep.Attribute _ document.metaAttributes, loa.rest UNTIL loa = NIL DO IF Rope.Equal[loa.first.attributeName, pAN] THEN {stdValues _ loa.first.value.first.valueSet; EXIT}; ENDLOOP; FOR lotpe: LIST OF YggRep.TypedPrimitiveElement _ stdValues, lotpe.rest UNTIL lotpe = NIL DO tpe: YggRep.TypedPrimitiveElement _ lotpe.first; forgetIt: BOOL _ FALSE; didOnList: DID; didl2add: LIST OF DID _ NIL; IF tpe.docType # YggRep.did THEN ERROR; didOnList _ NARROW[tpe.bits]; FOR macl: LIST OF YggRep.metaAttributeMod _ document.metaAttributesChanged, macl.rest UNTIL macl = NIL DO IF ~Rope.Equal[pAN, macl.first.attributeName] THEN LOOP; IF ~YggDID.EqualDIDs[macl.first.didValue, didOnList] THEN LOOP; forgetIt _ TRUE; FOR mdlist: LIST OF didCountItem _ modifiedDIDs, mdlist.rest UNTIL mdlist = NIL DO IF YggDID.EqualDIDs[mdlist.first.did, didOnList] THEN { mdlist.first.count _ mdlist.first.count + 1; EXIT; }; REPEAT FINISHED => modifiedDIDs _ CONS[[1, didOnList], modifiedDIDs]; ENDLOOP; EXIT; ENDLOOP; IF forgetIt THEN LOOP; didl2add _ LIST[didOnList]; IF didList = NIL THEN lastDidList _ didList _ didl2add ELSE lastDidList _ (lastDidList.rest _ didl2add); ENDLOOP; FOR macl: LIST OF YggRep.metaAttributeMod _ document.metaAttributesChanged, macl.rest UNTIL macl = NIL DO IF ~Rope.Equal[pAN, macl.first.attributeName] THEN LOOP; FOR mdlist: LIST OF didCountItem _ modifiedDIDs, mdlist.rest UNTIL mdlist = NIL DO IF YggDID.EqualDIDs[mdlist.first.did, macl.first.didValue] THEN { IF macl.first.add THEN mdlist.first.count _ mdlist.first.count + 1 ELSE mdlist.first.count _ mdlist.first.count - 1; EXIT; }; REPEAT FINISHED => ERROR; ENDLOOP; ENDLOOP; FOR mdlist: LIST OF didCountItem _ modifiedDIDs, mdlist.rest UNTIL mdlist = NIL DO IF mdlist.first.count > 0 THEN { FOR i: INT IN [1..mdlist.first.count] DO didl2add: LIST OF DID _ NIL; didl2add _ LIST[mdlist.first.did]; IF didList = NIL THEN lastDidList _ didList _ didl2add ELSE lastDidList _ (lastDidList.rest _ didl2add); ENDLOOP; }; ENDLOOP; IF ~dontLatch THEN { IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; }; AddIndexPatternToContainer: PUBLIC PROC [containerDID: YggDID.DID, pattern: ROPE] RETURNS [patternOK: BOOL] ~ { patternOK _ YggIndexMaint.AddOrRemoveIndexPattern[containerDID: containerDID, pattern: pattern, add: TRUE] }; RemoveIndexPatternFromContainer: PUBLIC PROC [containerDID: YggDID.DID, pattern: ROPE] RETURNS [ok: BOOL] ~ { ok _ YggIndexMaint.AddOrRemoveIndexPattern[containerDID: containerDID, pattern: pattern, add: FALSE] }; GetPatternsInContainer: PUBLIC PROC [containerDID: YggDID.DID, dontWait: BOOL] RETURNS [patterns: LIST OF ROPE _ NIL, success: BOOL _ TRUE] ~ { document: YggRep.VDoc; lastPattern: LIST OF ROPE _ NIL; stdValues: LIST OF YggRep.AttributeValue _ NIL; document _ YggRep.VolatizeFromDID[YggEnvironment.nullTransID, containerDID, readOnly, [read, IF dontWait THEN fail ELSE wait], TRUE]; IF ~YggRep.LatchVDoc[document, ~dontWait] THEN RETURN[NIL, FALSE]; FOR loa: LIST OF YggRep.Attribute _ document.metaAttributes, loa.rest UNTIL loa = NIL DO IF Rope.Equal[loa.first.attributeName, AutoIndices] THEN {stdValues _ loa.first.value; EXIT}; ENDLOOP; FOR loav: LIST OF YggRep.AttributeValue _ stdValues, loav.rest UNTIL loav = NIL DO indexPattern: ROPE _ NIL; tpe: YggRep.TypedPrimitiveElement _ loav.first.valueSet.first; SELECT tpe.docType FROM YggRep.rope, YggRep.shortRope => { indexPattern _ NARROW[tpe.bits]; }; ENDCASE => ERROR; IF lastPattern = NIL THEN patterns _ LIST[indexPattern] ELSE lastPattern _ (lastPattern.rest _ LIST[indexPattern]); ENDLOOP; IF ~YggRep.UnlatchVDoc[document] THEN ERROR; }; CreateObject: PUBLIC PROC [trans: YggEnvironment.TransID, containerDID: DID, makeRoot: BOOL] RETURNS [did: DID _ NIL] ~ { foundTrans: BOOL _ FALSE; activeTrans: BOOL _ FALSE; ok: BOOL _ FALSE; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; IF containerDID = NIL OR YggDID.EqualDIDs[containerDID, YggEnvironment.nullDID] THEN containerDID _ GetDefaultContainer[trans]; IF (containerDID = NIL OR YggDID.EqualDIDs[containerDID, YggEnvironment.nullDID]) AND ~makeRoot THEN ERROR Error[error: [code: $invalidDID, explanation: "default container and the containerDID specified are both null; a object must have a container"]]; did _ YggDIDMap.CreateNewDID[trans]; IF containerDID # NIL THEN AddToContainer[trans, did, containerDID]; IF makeRoot THEN ok _ YggDIDMap.AddRootDID[did]; }; RemoveObject: PUBLIC PROC [trans: YggEnvironment.TransID, did: DID] ~ { vDoc: YggRep.VDoc; kidDIDs: LIST OF DID; superDIDs: LIST OF DID; subDIDs: LIST OF DID; parentDIDs: LIST OF DID; success: BOOL _ TRUE; IF YggTransaction.Check[transID: trans] # active THEN ERROR Error [ [$invalidTrans, "transaction not active"]]; vDoc _ YggRep.VolatizeFromDID[trans, did, readWrite, [write, wait]]; IF vDoc.outlinks # NIL OR vDoc.inlinks # NIL OR vDoc.outlinksChanged # NIL OR vDoc.inlinksChanged # NIL THEN ERROR; -- doesn't handle recursive delete yet [] _ YggRep.LatchVDoc[vDoc]; [didList: kidDIDs, success: success] _ listContainer[trans: trans, did: did, pAN: Children, dontWait: FALSE, dontLatch: TRUE]; IF kidDIDs # NIL THEN { IF ~YggRep.UnlatchVDoc[vDoc] THEN ERROR; ERROR Error[error: [code: $containerMustBeEmpty, explanation: "attempt to remove an object that is the root of a container that has objects in it"]]; }; [didList: subDIDs, success: success] _ listContainer[trans: trans, did: did, pAN: ChildContainers, dontWait: FALSE, dontLatch: TRUE]; IF subDIDs # NIL THEN { IF ~YggRep.UnlatchVDoc[vDoc] THEN ERROR; ERROR Error[error: [code: $containerMustBeEmpty, explanation: "attempt to remove an object that is the root of a container that has containers in it"]]; }; [didList: parentDIDs, success: success] _ listContainer[trans: trans, did: did, pAN: Parents, dontWait: FALSE, dontLatch: TRUE]; [didList: superDIDs, success: success] _ listContainer[trans: trans, did: did, pAN: ParentContainers, dontWait: FALSE, dontLatch: TRUE]; FOR lopd: LIST OF DID _ parentDIDs, lopd.rest UNTIL lopd = NIL DO addOrRemoveContainer[trans: trans, did: did, containerDID: lopd.first, add: FALSE, pAN: Parents, cN: Children, dontLatchDoc: TRUE]; ENDLOOP; FOR lopd: LIST OF DID _ superDIDs, lopd.rest UNTIL lopd = NIL DO addOrRemoveContainer[trans: trans, did: did, containerDID: lopd.first, add: FALSE, pAN: ParentContainers, cN: ChildContainers, dontLatchDoc: TRUE]; ENDLOOP; vDoc.destroyed _ TRUE; YggDIDMap.DestroyDID[trans, did]; IF ~YggRep.UnlatchVDoc[vDoc] THEN ERROR; }; NoBytes _ NEW[YggRep.BitsRep[0]]; END. êYggNavImpl.mesa Copyright Ó 1988, 1989 by Xerox Corporation. All rights reserved. Bob Hagmann March 10, 1989 1:04:08 pm PST Top level navigational ``interface'' for Yggdrasil. Types, variables, and constants Fixed names for properties Fixed names for index prefix Fixed names for directory Fixed names for NFS Transactions Start up a new transaction. Commit or abort a transaction. Check on a transaction. If it no found, then active and committed are not meaningful. If found, then if active then committed is not meaningful. If not active, then the commit state is returned in committed. Old transactions will not be found. Root objects Note: none of the root operations operate under transaction (or any other!) control Get all the root objects for the service. Add a root object. If the DID does not exist, FALSE will be returned. Remove a root object. If the DID is not a root object, FALSE will be returned. Object contents Get the contents of the object with the specified did. Errors: $invalidDID, $invalidTrans Get the contents of the object with the specified did. The contents must not be a well known interpreted type (e. g., int, date, float, ...) Errors: $invalidDID, $invalidTrans, $invalidReservedType Get the contents of the object with the specified did. Errors: $invalidDID, $invalidTrans Set the contents of the object with the specified did. The object is grown if needed. The contents type is changed if setDocType is TRUE to docType. Errors: $invalidDID, $invalidTrans Set the contents of the object with the specified did. The object is grown if needed. Errors: $invalidDID, $invalidTrans Get the size contents of the object with the specified did. Errors: $invalidDID, $invalidTrans, Set the size contents of the object with the specified did. The object is grown if needed. Errors: $invalidDID, $invalidTrans, Object property manipulation Get the named property of the object with the specified did. If the property does not exist, [FALSE, NIL] is returned. Errors: $invalidDID, $invalidTrans Get all the properties of the object with the specified did. If no properties exist, NIL is returned. Errors: $invalidDID, $invalidTrans Get all the property names of the object with the specified did. If no properties exist, NIL is returned. Errors: $invalidDID, $invalidTrans Set the named property of the object with the specified did. If appendProperty is TRUE, the property is appended. If FALSE, it first destroys all properties with this name. A NIL value for the property with appendProperty as TRUE is a noop, and with appendProperty as FALSE deletes the property. A non-NIL value for the property with appendProperty as FALSE makes the new property the one and only value for the property. Errors: $invalidDID, $invalidTrans Object property construction Note: all of these procedures copy data. Construct a YggRep.TypedPrimitiveElement for a 32 bit integer. Errors: $invalidDID, $invalidTrans Construct a YggRep.TypedPrimitiveElement for a 32 bit real. Construct a YggRep.TypedPrimitiveElement for a date. Construct a YggRep.TypedPrimitiveElement for a ROPE that is short (less than a few disk pages preferred) and contains no nulls. Errors: $shortRopeWithNulls Construct a YggRep.TypedPrimitiveElement for a ROPE that is long (more than a disk page preferred) and may contain no nulls. Construct a YggRep.TypedPrimitiveElement for an array of bytes. Errors: $$invalidReservedType Links Get the did's of all the outlinks for this object with "link type" propertyName. Errors: $invalidDID, $invalidTrans Get the did's of all the outlinks for this object. Errors: $invalidDID, $invalidTrans Get the did's of all the inlinks for this object with "link type" propertyName. Errors: $invalidDID, $invalidTrans Get the did's of all the inlinks for this object. Errors: $invalidDID, $invalidTrans Construct a link between the two dids. Errors: $invalidDID, $invalidTrans Remove a link. Errors: $invalidDID, $invalidTrans Containers Get the default container for this transaction. Errors: $invalidTrans Set the default container for this transaction. Errors: $invalidDID, $invalidTrans Add the object to the container. Errors: $invalidDID, $invalidTrans Remove the object from the container. Errors: $invalidDID, $invalidTrans Get the did's of all the objects in this container. containerDID of NIL means use the default container. Errors: $invalidDID, $invalidTrans Get the did's of all the parents. Errors: $invalidDID, $invalidTrans Add the subcontainer to the container. Errors: $invalidDID, $invalidTrans Remove the subcontainer from the container. Errors: $invalidDID, $invalidTrans Get the did's of all the containers in this container. containerDID of NIL means use the default container. Errors: $invalidDID, $invalidTrans Get the did's of all the containers containing this container. Errors: $invalidDID, $invalidTrans Add the object to the container. Errors: $invalidDID, $invalidTrans Add the object to the container. Errors: $invalidDID, $invalidTrans find the right list flip through looking for DID's that don't have any modifications flip through the mods and see which are visible spit out dids still visible Indexing in containers Add the pattern to index on for the container. Errors: $invalidDID Remove the pattern.. Errors: $invalidDID Get the patterns in this container. Errors: $invalidDID find the right list flip through looking for DID's that don't have any modifications Object creation and destruction Make up a new object in the specified container. The default container for the transaction is used if containerDID is NIL. Errors: $invalidDID, $invalidTrans Remove a object. Any links pointing to this object are also removed. This is a recursive process (if the links are really objects). Errors: $invalidDID, $invalidTrans Initialization Ê(2˜codešœ™KšœB™BKšœ)™)—K™K™K™3K™šÏk ˜ Kšœœ"œ˜4Kšœœ ˜Kšœœœ˜+Kšœ œD˜SKšœœ ˜Kšœœ*˜>Kšœœ˜Kšœ œ˜Kšœœ˜.Kšœœ˜#KšœœÒ˜ÞKšœœd˜x—K˜KšÑbln œœ˜KšœH˜OKšœ˜%šœ˜K˜—head™Icode0šœœœ˜M˜KšÏnœœœœ˜5K˜K˜Kšœœœœ˜Kšœœœ˜+K˜KšŸœ˜K˜™KšŸœœœ˜)KšŸœœœ˜'KšŸœœœ˜)KšŸœœœ˜'KšŸœœœ˜)KšŸœœœ˜:KšŸœœœ˜8KšŸ œœœ˜0K˜—™KšŸ œœœ ˜*KšŸœœœ˜7K˜—™KšŸœœœ˜;—™KšŸœœœÏc˜NK˜——™ šŸœœœ'œ$˜oK™Kšœ0˜0K˜K™—šŸœœœ)œœœœ˜gK™Kšœ ˜ KšœMœœœ˜oKšœœœœœœœ˜;Kšœ˜K™—šŸœœœ!œ œœ œœ œœ˜ŽKšœ÷™÷Kšœ ˜ Kšœ:˜:šœ ˜Kš œ œœœœ˜&Kš œ œœœœ˜&Kš œ œœœœ˜&Kš œ œœœœ˜)Kš œœœœœ˜*Kšœœ˜—K˜——™ K™SK™šŸœœœœ œœœ˜6K™)Kšœ ˜ K˜K™—š Ÿœœœœœ œ˜>Kšœœœ™FKšœœœœ˜0Kšœ˜K˜K™—š Ÿ œœœœœ œ˜@Kšœœœ™OKšœœœ˜0Kšœ"˜"K˜——™š Ÿœœœ-œœ˜lK™6K™"Kšœ˜Kšœ/œœ4˜oKšœ.˜.Kšœ˜"K˜K™—šŸœœœœ˜OKšœ%œœ'œœœœœœ˜šKšœ˜K˜—šŸœœœœ&œ œ œœœœœ˜©K™K™8Kšœ˜Kšœ/œœ4˜oKšœ.˜.Kšœ ˜ šœ5œ˜=Kšœœœ˜,Kšœp˜uK˜—JšœWœ(˜‡Kšœ˜Kšœ,˜,K˜K™—š Ÿ œœœ&œœ-˜wK™6K™"Kšœ˜Kšœ/œœ4˜oKšœ.˜.Kšœ ˜ Jšœ˜Kšœ,˜,K˜K™—šŸœœœœ-œœ&œ œœœœœ˜ÝKšœxÏo œœ¡œ™–K™"Kšœ˜Kšœœ˜ Kšœ˜Kšœ˜Kšœ/œœ4˜oKšœH˜HKšœ ˜ šœ ˜šœ#œ˜+Kšœ œ˜,Kšœm˜rK˜—Kšœ$˜$Kšœ˜Kšœ˜—šœ˜šœ5œ˜=Kšœœœ˜,Kšœm˜rK˜—Kšœ)˜)K˜—Jšœsœ*˜¥Kšœœ"˜0Kšœœ˜ Kšœœœ˜,Kšœ ˜K˜K™—šŸ œœœ&œ-˜nK™VK™"Kšœ˜Kšœ/œœ4˜oKšœH˜HKšœ ˜ Jšœ˜Kšœœ˜ Kšœ,˜,K˜K™—š Ÿœœœ&œœœ˜WK™;K™$Kšœ˜Kšœ/œœ4˜oKšœH˜HKšœ ˜ šœ5œ˜=Kšœœœ˜,Kšœy˜~K˜—Jšœ7˜7Kšœœœ˜,K˜K™—š Ÿœœœ&œœ˜NK™[K™$Kšœ˜Kšœœ˜ Kšœ˜Kšœ/œœ4˜oKšœH˜HKšœ ˜ šœ5œ˜=Kšœ,˜,Kšœm˜rK˜—šœ8œ˜@Jšœd˜dKšœœ"˜0Kšœœ˜ K˜—Kšœ,˜,K˜K™——™šŸ œœœ&œœœœœ œœœ˜«Kšœ_œœ™wK™"Kšœ˜Kšœœœ˜!Kšœ/œœ4˜ošœœ˜'Kšœ(œœ˜IK˜—Kšœd˜dKšœ ˜ š œœœ1œœ˜Qšœ2œ˜:Kšœ œ˜$Kšœœ˜K˜—Kšœ˜—š œœœ5œœ˜Ušœ2œ˜:Kšœ œ˜$Kšœœ˜K˜—Kšœ˜—Kšœœœ˜,K˜K™—šŸœœœ&œœœœ˜zKšœVœ ™fK™"Kšœ˜Kšœ/œœ4˜oKšœ.˜.Kšœ˜K˜K™—šŸœœœ&œœœœœœ˜xKšœZœ ™jK™"Kšœ˜Kšœ/œœ4˜oKšœ.˜.Kšœ ˜ š œœœ1œœ˜Qš œœœœœœ˜?Kšœ.œœ˜:šœœ˜Kšœœ(˜™>K™"Kšœœœ˜Kšœœœ˜Kšœ˜K˜K™—š Ÿœœœ œœ-˜cKšœ;™;Kšœœœ˜Kšœœœ ˜Kšœ!˜!K˜K™—šŸœœœœ-˜pKšœ4™4Kšœ!˜!Kšœœ˜1Kšœ'˜'K˜K™—š Ÿœœœœœ-˜dKšœ/œL™K™šœœ˜&Kšœ$˜$K˜—Kšœœœ0˜;K˜K™—š Ÿœœœœœ-˜_Kšœ/œI™|Kšœ˜K˜K™—šŸœœœ"œœœœ-˜›Kšœ?™?K™Kšœœ˜ Kšœœ˜Kšœ#œœ_˜ŽKšœœ˜"Kšœ˜šœ˜"KšœD˜DKšœœ œœ=˜tK˜—Kšœœœ˜Kšœ˜K˜——™šÏb œœ œœ&œœœœœœœœ˜–Kš œ œœœœ˜š œ œœ.œ œ˜Zš œ œœ0œœ˜Qš œœœDœ œ˜jKšœ œ˜ Kšœ"œœ˜/Kšœ œ˜#Kšœœœœ ˜4Kšœœœ ˜$Kšœ˜—K˜—Kšœ˜—š œœœ*œœ˜NKš œ œœ,œœœ˜Ršœœ˜Kšœ œœœ˜EKšœœœ˜1K˜—šœœ˜Kš œ œœœœ˜š œœœœœœ˜8šœ3œ˜;Kšœ œœ˜&Kšœœ˜Kšœœ˜*Kšœ˜K˜—Kšœ˜Kšœ˜—K˜—Kšœ˜—K˜K˜—š¢œœ œœ&œœœœœœ˜•Kšœœœœ˜0š œ œœ.œ œ˜ZKš œœœœœ˜Kš œ œœœœ˜š œœœDœ œ˜jKšœ œ˜ Kšœ"œœ˜/Kšœ œ˜#Kšœœœœ ˜4Kšœœœ ˜$Kšœ˜—Kšœœœ#œ"˜cKšœœœ#˜EKšœ˜—š œœœ*œœ˜Nš œ œœ-œ œ˜UKšœ9œœœ˜Lšœœ˜KšœB˜BK˜—šœœ˜Kš œ œœœœ˜š œœœœœœ˜Ešœ3œ˜;Kšœ œœ+˜@Kšœœ˜Kšœ˜K˜—Kšœ˜Kšœ˜—K˜—šœœ˜+Kš œœœ#œœ˜uKšœœœœ˜WKšœ˜—Kšœ˜—Kšœ˜—K˜K˜—šŸœœœ&œ œœ œœœœ˜KšœP™PK™"Kšœ˜Kšœ/œœ4˜oKšœF˜FKšœ ˜ KšœP˜PKšœœœ˜,K˜K™—šŸœœœ&œœ œœœ˜{Kšœ2™2K™"Kšœ˜Kšœ/œœ4˜oKšœF˜FKšœ ˜ KšœA˜AKšœœœ˜,K˜K™—šŸœœœ&œ œœ œœœœ˜KšœO™OK™"Kšœ˜Kšœ/œœ4˜oKšœF˜FKšœ ˜ KšœM˜MKšœœœ˜,K˜K™—šŸ œœœ&œœ œœœ˜yKšœ1™1K™"Kšœ˜Kšœ/œœ4˜oKšœF˜FKšœ ˜ Kšœ>˜>Kšœœœ˜,K˜K™—šŸœœœ*œ œ œœ œœ˜€K™&K™"Kšœ œœœ˜*Kšœ œœœ˜)Kšœ˜Kšœ˜Kšœ˜Kšœ/œœ4˜oKšœL˜LKšœF˜FKšœ ˜ š œœœ6œœ˜ZKšœ˜Kšœ˜—Kšœ(˜(KšœL˜LKšœ˜Kšœ˜Kšœ˜Kšœ+˜+Kšœœ˜Kšœ œœ˜-Kšœœœ&˜?Kšœœ˜$Kšœœœ˜,Kšœ˜Kšœœ˜š œœœ3œœ˜WKšœ˜Kšœ˜—Kšœ œœ˜-Kšœœœ#˜™>K™"Kšœ/œœ4˜oKšœR˜RK˜K˜—š¢œœ&œœœœœœœ˜—K™ K™"Kšœ˜Kšœ˜Kšœ œœ˜)KšœH˜Hšœ˜Kšœ ˜ Kšœ˜—Kšœ œFœ˜ZKšœ"œœ)˜Ušœœ˜Kšœœœœ˜,š œœœEœœ˜iKšœ ˜ Kšœ˜—Kšœ˜K˜—šœ˜Kšœœœ˜,Kšœ˜—KšœZ˜ZKšœ)˜)Kšœ œ<œ˜PKšœ+œœ2˜gšœœ˜Kšœœœœ˜,š œœœNœœ˜rKšœ ˜ Kšœ˜—Kšœ˜K˜—Kšœ+˜+K˜K˜—š¢ œœ&œœ œ œœœ œœœœ œœ˜°K™ K™"Kšœ˜Kš œœœœœ˜ šœ œ˜Kšœœ˜Kšœ˜K˜—Kšœœœœ˜)Kšœ œœ œ˜6Kšœ/œœ4˜oKšœAœ œœ˜cšœ œ˜Kš œ(œœœœ˜BK˜K™—š œœœ6œœ˜XKšœ*œ.œ˜dKšœ˜Kšœœ$™@—š œœœ6œ œ˜\Kšœ0˜0Kšœ œœ˜Kšœ œ˜Kš œ œœœœ˜Kšœœœ˜'Kšœ œ ˜š œœœEœœ˜iJšœ,œœ˜8Jšœ3œœ˜?Jšœ œ˜š œ œœ*œ œ˜Ršœ/œ˜7Jšœ,˜,Jšœ˜J˜—Jšœœœ˜EJšœ˜—Jšœ˜Kšœ˜—Kšœ œœ˜Kšœ œ ˜Kšœ œœ!˜6Kšœœ-˜2Kšœ˜K™/—š œœœEœœ˜iJšœ,œœ˜8š œ œœ*œ œ˜Ršœ9œ˜AJšœœ,˜BJšœ2˜2Jšœ˜J˜—Jšœœ ˜Jšœ˜—Kšœ˜K™—š œ œœ*œ œ˜Ršœ ˜ šœ(˜(Kš œ œœœœ˜Kšœ œ˜"Kšœ œœ!˜6Kšœœ-˜2Jšœ˜—J˜—J˜—šœ œ˜Kšœœœ˜,K˜—K˜K˜——™šŸœ œœ œ˜oK™.K™Kšœeœ˜jK˜K™—š Ÿœ œœ œœœ˜mK™K™Kšœ^œ˜dK˜K˜—šŸœœœœ œœ œœœœ œœ˜Kšœ#™#K™Kšœ˜Kš œœœœœ˜!Kšœ œœœ˜/Kš œ]œ œœœ˜…š œ(œœœœ˜BK™—š œœœ6œœ˜XKšœ2œœ˜]Kšœ˜Kšœœ$™@—š œœœ.œœ˜RK˜Kšœ>˜>šœ ˜šœ"˜"Kšœœ ˜ Kšœ˜—Kšœœ˜—Kšœ7˜7Kšœ<˜