<> <> <> <> <> DIRECTORY AlpineEnvironment USING[ NeededAccess, OperationFailure, Principal, UnknownType], AlpDirectory USING[ Error ], AlpineDirectory USING[ ErrorType ], AlpineInterimDirectory USING[ DirectoryInconsistent, Error, ErrorType], AlpInstance USING[ AccessFailed, Create, Handle, LockFailed, Failed, OperationFailed, PossiblyDamaged, StaticallyInvalid, Unknown], AlpTransaction USING[ Create, Finish, Handle, OperationFailed, Outcome], AMTypes USING[ IndexToName, Type], FS USING[ Error], IO, PrincOpsUtils USING[ IsBound ], Rope, RPC USING[ CallFailed, CallFailure, EncryptionKey, MakeKey], UserCredentials USING[ Get ], YodelData; YodelSignalsImpl: CEDAR PROGRAM IMPORTS AlpDirectory, AlpineInterimDirectory, AlpInstance, AlpTransaction, AMTypes, FS, IO, PrincOpsUtils, Rope, RPC, UserCredentials EXPORTS YodelData = BEGIN OPEN YodelData; ROPE: TYPE = Rope.ROPE; <> <> PerformOp: PUBLIC PROC[ performProc: PerformProc, server: ROPE, user: ROPE _ NIL, password: ROPE _ NIL] RETURNS [LIST OF REF ANY] = { failureName: ROPE _ "" ; userName, userPassword, keyRope: ROPE; caller: AlpineEnvironment.Principal ; key: RPC.EncryptionKey; inst: AlpInstance.Handle _ NIL; trans: AlpTransaction.Handle _ NIL ; outcome: AlpTransaction.Outcome _ unknown; result: LIST OF REF ANY _ NIL ; { ENABLE BEGIN RPC.CallFailed => { type: AMTypes.Type _ CODE[RPC.CallFailure]; failure: RPC.CallFailure; count: CARDINAL _ 1 ; failureName _ "*unknown*"; FOR failure IN RPC.CallFailure DO IF why = failure THEN { failureName _ AMTypes.IndexToName[type: type, index: count]; }; count _ count + 1 ; ENDLOOP; GOTO RPCFailed; }; AlpInstance.StaticallyInvalid => GOTO statInvalid ; AlpInstance.Unknown =>{ type: AMTypes.Type _ CODE[AlpineEnvironment.UnknownType]; failure: AlpineEnvironment.UnknownType; count: CARDINAL _ 1 ; failureName _ "*unknown*"; IF what = AlpineEnvironment.UnknownType.owner THEN GOTO badOwner; IF what = AlpineEnvironment.UnknownType.transID THEN GOTO badTransID; FOR failure IN AlpineEnvironment.UnknownType DO IF what = failure THEN { failureName _ AMTypes.IndexToName[type: type, index: count]; }; count _ count + 1 ; ENDLOOP; GOTO alpUnknown; }; AlpInstance.AccessFailed =>{ type: AMTypes.Type _ CODE[AlpineEnvironment.NeededAccess]; failure: AlpineEnvironment.NeededAccess; count: CARDINAL _ 1 ; failureName _ "*unknown*"; FOR failure IN AlpineEnvironment.NeededAccess DO IF missingAccess = failure THEN { failureName _ AMTypes.IndexToName[type: type, index: count]; }; count _ count + 1 ; ENDLOOP; GOTO accFail; }; AlpInstance.OperationFailed => { type: AMTypes.Type _ CODE[AlpineEnvironment.OperationFailure]; failure: AlpineEnvironment.OperationFailure; count: CARDINAL _ 1 ; failureName _ "*unknown*"; FOR failure IN AlpineEnvironment.OperationFailure DO IF why = failure THEN { failureName _ AMTypes.IndexToName[type: type, index: count]; }; count _ count + 1 ; ENDLOOP; GOTO opFail; }; AlpineInterimDirectory.DirectoryInconsistent => GOTO dirInconsistent; AlpineInterimDirectory.Error => { type: AMTypes.Type _ CODE[AlpineInterimDirectory.ErrorType]; failure: AlpineInterimDirectory.ErrorType; count: CARDINAL _ 1 ; failureName _ "*unknown*"; FOR failure IN AlpineInterimDirectory.ErrorType DO IF why = failure THEN { failureName _ AMTypes.IndexToName[type: type, index: count]; }; count _ count + 1 ; ENDLOOP; GOTO interimDirError; }; AlpDirectory.Error => { typeCode: AMTypes.Type _ CODE[AlpineDirectory.ErrorType]; failure: AlpineDirectory.ErrorType; count: CARDINAL _ 1 ; failureName _ "*unknown*"; FOR failure IN AlpineDirectory.ErrorType DO IF type = failure THEN { failureName _ AMTypes.IndexToName[type: typeCode, index: count]; }; count _ count + 1 ; ENDLOOP; GOTO dirError; }; AlpInstance.LockFailed => GOTO lockFail; AlpInstance.PossiblyDamaged => GOTO possDamaged; AlpTransaction.OperationFailed => GOTO alpineBusy; AlpInstance.Failed => { SELECT why FROM alpineDownOrCommunications => { failureName _ " alpine or communications are down"; GOTO alpineError ; }; alpineDown => { failureName _ " alpine server is down"; GOTO alpineError ; }; authenticateFailed => { failureName _ " of authentication error- suspect bad user name or password"; GOTO alpineError ; }; badCallee => { failureName _ " of bad server name"; GOTO alpineError ; }; grapevineDownOrCommunications => { failureName _ " communications or server are down"; GOTO alpineError ; }; mismatch => { failureName _ " mismatch (for example, version incompatibility)"; GOTO alpineError ; }; ENDCASE ; }; FS.Error => { failureName _ error.explanation ; GOTO FSError ; }; IO.Error => { SELECT ec FROM SyntaxError => { failureName _ "Syntax Error"; GOTO syntaxError ;} ; ENDCASE ; }; END; TRUSTED BEGIN IF NOT PrincOpsUtils.IsBound[link: LOOPHOLE[AlpInstance.Create]] THEN GOTO notBound ; END; [userName, userPassword] _ UserCredentials.Get[]; IF (Rope.Equal[user,""] OR Rope.Equal[user,NIL]) THEN caller _ userName ELSE caller _ user ; IF (Rope.Equal[password,""] OR Rope.Equal[password,NIL]) THEN keyRope _ userPassword ELSE keyRope _ password ; TRUSTED BEGIN key _ RPC.MakeKey[keyRope]; END; IF Rope.Match[pattern: "*.alpine", object: server, case: FALSE] THEN { inst _ AlpInstance.Create[fileStore: server, caller: caller, key: key]; trans _ AlpTransaction.Create[inst]; }; result _ performProc[trans: trans, serverForTrans: server, caller: caller, key: key]; IF trans # NIL THEN { outcome _ AlpTransaction.Finish[trans, commit]; }; RETURN[result]; EXITS RPCFailed => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["RPC failure: %g", IO.rope[failureName]],NIL]]; }; alpineBusy => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["Alpine server is busy - please try again later", ROPE], NIL]]; }; dirInconsistent => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["Alpine Interim Directory: directory is inconsistent",ROPE], NIL]]; }; dirError => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Alpine Directory Error: %g", IO.rope[failureName]],NIL]]; }; interimDirError => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Alpine Interim Directory Error: %g", IO.rope[failureName]],NIL]]; }; accFail => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Alpine denied access because client is not in the %g access control list", IO.rope[failureName]],NIL ]]; }; lockFail => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["Alpine server has a conflict or timed out a lock - please try again later", ROPE], NIL]]; }; opFail => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Alpine Instance Operation Failed: %g", IO.rope[failureName]],NIL]]; }; possDamaged => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["Alpine server reports possible damage", ROPE], NIL]]; }; alpUnknown => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Alpine Instance Unknown Type: %g", IO.rope[failureName]],NIL]]; }; badOwner => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["Alpine Unknown Type: owner -- suspect bad directory, owner or access list name", ROPE], NIL]]; }; badTransID => { RETURN[CONS[ NARROW["Alpine Unknown Type: transID -- suspect transaction has aborted or that the server has crashed and restarted", ROPE], NIL]]; }; statInvalid => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["Alpine Statically Invalid error - suspect unreasonable property value or Yodel bug", ROPE], NIL]]; }; notBound => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[NARROW["unbound error- suspect AlpineUserImpls has not been run", ROPE], NIL]]; }; alpineError => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Alpine error because %g",IO.rope[failureName]],NIL]]; }; FSError => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["FS could not perform operation because %g", IO.rope[failureName]], NIL]]; }; syntaxError => { IF trans # NIL THEN outcome _ AlpTransaction.Finish[trans, abort ! RPC.CallFailed => CONTINUE;]; RETURN[CONS[IO.PutFR["Syntax error in input: %g", IO.rope[failureName]],NIL]]; }; }; }; END. <> <> <> <> <> <<>>