-- AlpInstanceImpl.mesa -- Last edited by -- Kolling on October 18, 1983 3:51 pm -- MBrown on February 2, 1984 10:55:52 am PST DIRECTORY AlpineEnvironment USING[Conversation, FileStore, LockFailure, NeededAccess, OperationFailure, Principal, UnknownType], AlpineFile USING[AccessFailed, Close, Create, Delete, GetAccessRights, GetLockOption, GetRecoveryOption, GetReferencePattern, GetSize, GetTransID, GetUniversalFile, IncrementVersion, LockFailed, LockPages, Open, OperationFailed, PossiblyDamaged, ReadPages, ReadProperties, SetLockOption, SetReferencePattern, SetSize, StaticallyInvalid, UnlockPages, Unknown, UnlockVersion, WritePages, WriteProperties], AlpineFileRpcControl USING[ImportNewInterface, NewInterfaceRecord], AlpineOwner USING[AccessFailed, Create, Destroy, LockFailed, OperationFailed, ReadDBProperties, ReadNext, ReadProperties, ReorganizeDB, StaticallyInvalid, Unknown, WriteProperties], AlpineOwnerRpcControl USING[ImportNewInterface, NewInterfaceRecord], AlpineTransaction USING[AssertAlpineWheel, Create, CreateWorker, Finish, OperationFailed, Unknown], AlpineTransactionRpcControl USING[ImportNewInterface, NewInterfaceRecord], AlpineVolume USING[AccessFailed, GetEnclosingGroup, GetGroup, GetNextGroup, StaticallyInvalid, Unknown], AlpineVolumeRpcControl USING[ImportNewInterface, NewInterfaceRecord], AlpInstance USING[Failure, Handle, Object], AlpPrivate USING[InterfaceCreatorProc], Booting USING[RegisterProcs, RollbackProc], ClientMap USING[Register], PrincOpsUtils USING[IsBound], Rope USING[Equal, ROPE], RPC USING[AuthenticateFailed, EncryptionKey, GenerateConversation, GetCaller, ImportFailed, MakeKey, StartConversation, VersionRange], UserCredentials USING[Get]; AlpInstanceImpl: CEDAR MONITOR IMPORTS AF: AlpineFile, AlpineFileRpcControl, AO: AlpineOwner, AlpineOwnerRpcControl, AT: AlpineTransaction, AlpineTransactionRpcControl, AV: AlpineVolume, AlpineVolumeRpcControl, Booting, ClientMap, PrincOpsUtils, Rope, RPC, UserCredentials EXPORTS AlpInstance, AlpPrivate SHARES AlpineFileRpcControl, AlpineOwnerRpcControl, AlpineTransactionRpcControl, AlpineVolumeRpcControl = BEGIN OPEN AE: AlpineEnvironment, AlpI: AlpInstance; objectCache: LIST OF AlpI.Object _ NIL; localFileStore: AE.FileStore _ "Local.alpine"; FindObjectInCache: INTERNAL PROCEDURE[fileStore: AE.FileStore, caller: AE.Principal, key: RPC.EncryptionKey] RETURNS[handle: AlpI.Handle] = BEGIN conversation: AE.Conversation; FOR list: LIST OF AlpI.Object _ objectCache, list.rest UNTIL list = NIL DO IF Rope.Equal[list.first.fileStore, fileStore, FALSE] THEN BEGIN TRUSTED BEGIN conversation _ (IF (Rope.Equal[RPC.GetCaller[list.first.conversation], caller, FALSE] AND (key = list.first.key)) THEN list.first.conversation ELSE RPC.StartConversation[caller, key, fileStore, authOnly]); END; handle _ NEW[AlpI.Object _ [ trans: list.first.trans, file: list.first.file, owner: list.first.owner, volume: list.first.volume, otherInterfaces: list.first.otherInterfaces, conversation: conversation, key: key, fileStore: fileStore]]; RETURN; END; ENDLOOP; TRUSTED BEGIN conversation _ RPC.StartConversation[caller, key, fileStore, authOnly]; END; handle _ NEW[AlpI.Object _ [ trans: AlpineTransactionRpcControl.ImportNewInterface[[type: "AlpineTransaction.alpine", instance: fileStore, version: version], [NIL, NIL, NIL]], file: AlpineFileRpcControl.ImportNewInterface[[type: "AlpineFile.alpine", instance: fileStore, version: version], [NIL, NIL, NIL]], owner: AlpineOwnerRpcControl.ImportNewInterface[[type: "AlpineOwner.alpine", instance: fileStore, version: version], [NIL, NIL, NIL]], volume: AlpineVolumeRpcControl.ImportNewInterface[[type: "AlpineVolume.alpine", instance: fileStore, version: version], [NIL, NIL, NIL]], otherInterfaces: NIL, conversation: conversation, key: key, fileStore: fileStore]]; FOR list: LIST OF AlpPrivate.InterfaceCreatorProc _ interfaceCreators, list.rest UNTIL list = NIL DO handle.otherInterfaces _ CONS[list.first[fileStore, version], handle.otherInterfaces]; ENDLOOP; objectCache _ CONS[handle^, objectCache]; END; Create: PUBLIC ENTRY PROCEDURE[fileStore: AE.FileStore, caller: AE.Principal, key: RPC.EncryptionKey] RETURNS [handle: AlpI.Handle] = -- non system-fatal errors: -- Failed[alpineDownOrCommunications, alpineDown, authenticateFailed, badCallee, grapevineDownOrCommunications, mismatch]. -- caller = NIL means the logged-in user. BEGIN ENABLE UNWIND => NULL; BEGIN ENABLE BEGIN RPC.AuthenticateFailed => SELECT why FROM badCaller, badKey => GOTO authenticateFailed; badCallee => GOTO badCallee; communications => GOTO grapevineDownOrCommunications; ENDCASE => NULL; RPC.ImportFailed => SELECT why FROM communications => GOTO alpineDownOrCommunications; -- almost certainly alpine and not grapevine, since authenticate got through. wrongVersion, stubProtocol => GOTO mismatch; unbound => GOTO alpineDown; ENDCASE => NULL; END; startedAlready _ TRUE; IF caller = NIL THEN BEGIN psw: Rope.ROPE; [caller, psw] _ UserCredentials.Get[]; TRUSTED BEGIN key _ RPC.MakeKey[psw]; END; END; IF Rope.Equal[fileStore, localFileStore, FALSE] THEN BEGIN conversation: AE.Conversation; IF NOT PrincOpsUtils.IsBound[AT.Create] THEN GOTO alpineDownOrCommunications; TRUSTED BEGIN conversation _ RPC.GenerateConversation[]; ClientMap.Register[conversation, caller]; END; handle _ NEW[AlpI.Object _ [ trans: AlpineTransactionRpcControl.NewInterfaceRecord[], file: AlpineFileRpcControl.NewInterfaceRecord[], owner: AlpineOwnerRpcControl.NewInterfaceRecord[], volume: AlpineVolumeRpcControl.NewInterfaceRecord[], otherInterfaces: NIL, conversation: conversation, key: key, fileStore: fileStore]]; handle.trans^ _ [Create: AT.Create, CreateWorker: AT.CreateWorker, AssertAlpineWheel: AT.AssertAlpineWheel, Finish: AT.Finish, Unknown: AT.Unknown, OperationFailed: AT.OperationFailed, lupineDetails: ]; handle.file^ _ [Open: AF.Open, Create: AF.Create, Close: AF.Close, Delete: AF.Delete, GetUniversalFile: AF.GetUniversalFile, GetTransID: AF.GetTransID, GetAccessRights: AF.GetAccessRights, GetLockOption: AF.GetLockOption, SetLockOption: AF.SetLockOption, GetRecoveryOption: AF.GetRecoveryOption, GetReferencePattern: AF.GetReferencePattern, SetReferencePattern: AF.SetReferencePattern, ReadPages: AF.ReadPages, WritePages: AF.WritePages, LockPages: AF.LockPages, UnlockPages: AF.UnlockPages, ReadProperties: AF.ReadProperties, WriteProperties: AF.WriteProperties, UnlockVersion: AF.UnlockVersion, IncrementVersion: AF.IncrementVersion, GetSize: AF.GetSize, SetSize: AF.SetSize, AccessFailed: AF.AccessFailed, LockFailed: AF.LockFailed, OperationFailed: AF.OperationFailed, StaticallyInvalid: AF.StaticallyInvalid, Unknown: AF.Unknown, PossiblyDamaged: AF.PossiblyDamaged, lupineDetails: ]; handle.owner^ _ [ReadProperties: AO.ReadProperties, WriteProperties: AO.WriteProperties, Create: AO.Create, Destroy: AO.Destroy, ReadNext: AO.ReadNext, ReadDBProperties: AO.ReadDBProperties, ReorganizeDB: AO.ReorganizeDB, AccessFailed: AO.AccessFailed, LockFailed: AO.LockFailed, OperationFailed: AO.OperationFailed, StaticallyInvalid: AO.StaticallyInvalid, Unknown: AO.Unknown, lupineDetails: ]; handle.volume^ _ [GetNextGroup: AV.GetNextGroup, GetGroup: AV.GetGroup, GetEnclosingGroup: AV.GetEnclosingGroup, AccessFailed: AV.AccessFailed, Unknown: AV.Unknown, StaticallyInvalid: AV.StaticallyInvalid, lupineDetails: ]; FOR list: LIST OF AlpPrivate.InterfaceCreatorProc _ interfaceCreators, list.rest UNTIL list = NIL DO handle.otherInterfaces _ CONS[list.first[fileStore, version], handle.otherInterfaces]; ENDLOOP; END ELSE handle _ FindObjectInCache[fileStore, caller, key]; EXITS alpineDownOrCommunications => RETURN WITH ERROR Failed[alpineDownOrCommunications]; alpineDown => RETURN WITH ERROR Failed[alpineDown]; authenticateFailed => RETURN WITH ERROR Failed[authenticateFailed]; badCallee => RETURN WITH ERROR Failed[badCallee]; grapevineDownOrCommunications => RETURN WITH ERROR Failed[grapevineDownOrCommunications]; mismatch => RETURN WITH ERROR Failed[mismatch]; END; END; -- If a object in our cache has an InterfaceRecord matching an InterfaceRecord in this handle, throw out the object. I think one interface matching means all match..... NoticeUnboundInstance: PUBLIC ENTRY PROCEDURE[handle: AlpI.Handle] = -- non system-fatal errors: -- none. BEGIN prevEntry: LIST OF AlpI.Object _ NIL; list: LIST OF AlpI.Object _ objectCache; DO IF list = NIL THEN EXIT; IF list.first.trans = handle.trans THEN BEGIN IF prevEntry = NIL THEN objectCache _ list.rest ELSE prevEntry.rest _ list.rest; END ELSE prevEntry _ list; list _ list.rest; ENDLOOP; END; RegisterInterfaceCreator: PUBLIC ENTRY PROCEDURE[proc: AlpPrivate.InterfaceCreatorProc] = -- non system-fatal errors: -- none. BEGIN IF startedAlready THEN ERROR; interfaceCreators _ CONS[proc, interfaceCreators]; END; interfaceCreators: LIST OF AlpPrivate.InterfaceCreatorProc _ NIL; startedAlready: BOOLEAN _ FALSE; AlpRollbackProcedure: ENTRY Booting.RollbackProc = -- TYPE = PROC[clientData: REF ANY]; -- non system-fatal errors: -- none. BEGIN objectCache _ NIL; END; Failed: PUBLIC ERROR [why: AlpInstance.Failure] = CODE; AccessFailed: PUBLIC ERROR [missingAccess: AE.NeededAccess] _ AF.AccessFailed; LockFailed: PUBLIC ERROR [why: AE.LockFailure] _ AF.LockFailed; OperationFailed: PUBLIC ERROR [why: AE.OperationFailure] _ AF.OperationFailed; StaticallyInvalid: PUBLIC ERROR _ AF.StaticallyInvalid; Unknown: PUBLIC ERROR [what: AE.UnknownType] _ AF.Unknown; PossiblyDamaged: PUBLIC SIGNAL _ LOOPHOLE[AF.PossiblyDamaged]; version: RPC.VersionRange = [3, 3]; -- start up code. TRUSTED BEGIN Booting.RegisterProcs[c: , r: AlpRollbackProcedure]; END; END. Edit Log Initial: Kolling: February 15, 1983 2:58 pm. Changed: MBrown: February 1, 1984 8:27:49 pm PST. Rolled version stamp.