DIRECTORY AlpFile, AlpineEnvironment, AlpineFile, AlpineInterimDirectory, AlpInstance, AlpTransaction, Basics, BasicTime, Buttons, IO, List, Real, Rope, ViewerClasses, ViewerTools, YodelData; YodelAdministrator: CEDAR PROGRAM IMPORTS AlpFile, AlpInstance, AlpineInterimDirectory, AlpTransaction, Buttons, IO, List, Real, Rope, ViewerTools, YodelData EXPORTS YodelData = BEGIN OPEN YodelData; ROPE: TYPE = Rope.ROPE; OwnerPropertyValuePairList: TYPE = LIST OF AlpineEnvironment.OwnerPropertyValuePair; CompareProc: SAFE PROC [ref1, ref2: REF ANY] RETURNS [Basics.Comparison] = CHECKED { RETURN [Rope.Compare[NARROW[ref1], NARROW[ref2], FALSE]]; }; trimWedges: PROC [inRope: ROPE] RETURNS [outRope: ROPE _NIL] = { len: INT _ inRope.InlineLength[]; IF len < 2 OR inRope.Fetch[0] ~= '< OR inRope.Fetch[len-1] ~= '> THEN ERROR; RETURN [ inRope.Substr[start: 1, len: len-2]]; }; ChangeAssertWheel: PUBLIC Buttons.ButtonProc = { d: MyData = NARROW[clientData]; p: ViewerClasses.Viewer = NARROW[parent]; d.assertWheel _ NOT d.assertWheel ; IF d.assertWheel THEN Buttons.SetDisplayStyle[p, $WhiteOnBlack] ELSE Buttons.SetDisplayStyle[p, $BlackOnWhite]; }; ChangeBreakLocks: PUBLIC Buttons.ButtonProc = { d: MyData = NARROW[clientData]; p: ViewerClasses.Viewer = NARROW[parent]; d.breakLocks _ NOT d.breakLocks ; IF d.breakLocks THEN Buttons.SetDisplayStyle[p, $WhiteOnBlack] ELSE Buttons.SetDisplayStyle[p, $BlackOnWhite]; }; createOwner: PROC [trans: AlpTransaction.Handle, server: ROPE, directory: ROPE, user: ROPE _ NIL, password: ROPE _ NIL , properties: OwnerPropertyValuePairList, d: MyData] RETURNS [resultList: LIST OF REF ANY] = { spaceLeftOnVolumeGroup: INT; owner: ROPE _ trimWedges[directory]; IF trans = NIL THEN RETURN [CONS[NARROW["Bad Server Name", ROPE], NIL]]; trans.AssertAlpineWheel[TRUE]; [spaceLeftOnVolumeGroup: spaceLeftOnVolumeGroup] _ trans.CreateOwner[ volumeGroupID: trans.GetNextVolumeGroup[previousGroup: AlpineEnvironment.nullVolumeGroupID, lock: [none, wait]], owner: owner, properties: properties]; IF (trans.Finish[requestedOutcome: commit, continue: FALSE] # commit) THEN { resultList _ CONS[ first: NARROW["Alpine transaction aborted -- owner NOT created", ROPE], rest: NIL]; } ELSE resultList _ CONS[ first: IO.PutFR["Owner added; space left on volume group is %g", IO.int[spaceLeftOnVolumeGroup]], rest: NIL]; }; CreateOwnerProc: PUBLIC Buttons.ButtonProc = { resultList: LIST OF REF ANY _ NIL; d: MyData = NARROW[clientData]; server, user, password: ROPE; directory: ROPE; properties: OwnerPropertyValuePairList ; pageLimit: INT; newPageLimitRope: ROPE; scratchStream: IO.STREAM _ NIL; callCreate: YodelData.PerformProc = { RETURN[createOwner[trans, server, directory, user, password, properties, d]]; }; d.stopFlag _ FALSE; [user, password, server, directory] _ ParseSArgs[d]; newPageLimitRope _ ViewerTools.GetContents[viewer: d.oQuota]; IF newPageLimitRope.IsEmpty[] THEN { d.out.PutF["\nCreate Owner has no quota specified\n"]; } ELSE { IF directory.Size[] <= 2 OR hasPattern[directory] THEN { d.out.PutF["\nCreate Owner has an invalid owner name to create. Name is %g\n", IO.rope[directory]]; } ELSE { scratchStream _ IO.RIS[newPageLimitRope, scratchStream]; pageLimit _ IO.GetInt[scratchStream]; properties _ LIST[[quota[pageLimit]]]; d.out.PutF["\nCreate Owner of [%g]%g for %g pages\n", IO.rope[server], IO.rope[directory], IO.int[pageLimit]]; resultList _ PerformOp[performProc: callCreate, server: server, user: user, password: password]; DO nowRope: ROPE _ NARROW[List.Car[resultList]]; IF resultList = NIL THEN EXIT; resultList _ List.Cdr[resultList]; d.out.PutF[" %g\n", IO.rope[nowRope]]; ENDLOOP; }; }; }; destroyOwner: PROC [trans: AlpTransaction.Handle, server: ROPE, directory: ROPE, user: ROPE _ NIL, password: ROPE _ NIL , d: MyData] RETURNS [resultList: LIST OF REF ANY] = { destroyOwnerEnumProc: PROC [fileName: REF TEXT, universalFile: AlpineEnvironment.UniversalFile] RETURNS [quit: BOOL] = { thereIsAFile _ TRUE; }; owner: ROPE _ trimWedges[directory]; thereIsAFile: BOOL _ FALSE; properties: LIST OF AlpineEnvironment.OwnerPropertyValuePair; rootFile: AlpineEnvironment.UniversalFile _ AlpineEnvironment.nullUniversalFile ; IF trans = NIL THEN RETURN [CONS[NARROW["Bad Server Name", ROPE], NIL]]; trans.AssertAlpineWheel[TRUE]; AlpineInterimDirectory.EnumerateDirectoryUnderTrans[ transHandle: trans, directoryName: Rope.Concat["[",Rope.Concat[server,Rope.Concat["]",directory]]], enumProc: destroyOwnerEnumProc]; IF thereIsAFile THEN RETURN [ CONS[ NARROW["Delete all files in the directory before destroying the owner",ROPE] ,NIL]]; properties _ AlpTransaction.ReadOwnerProperties[ handle: trans, volumeGroupID: AlpTransaction.GetNextVolumeGroup[handle: trans, previousGroup: AlpineEnvironment.nullVolumeGroupID, lock: [none, fail]], owner: owner]; UNTIL properties = NIL DO -- because ReadOwnerProperties does not sort them yet ... WITH properties.first SELECT FROM q: AlpineEnvironment.OwnerPropertyValuePair.createAccessList => { }; s: AlpineEnvironment.OwnerPropertyValuePair.modifyAccessList => { }; r: AlpineEnvironment.OwnerPropertyValuePair.rootFile => { rootFile _ r.rootFile ; }; t: AlpineEnvironment.OwnerPropertyValuePair.quota => {}; u: AlpineEnvironment.OwnerPropertyValuePair.spaceInUse => {}; ENDCASE ; properties _ properties.rest; ENDLOOP; IF rootFile # AlpineEnvironment.nullUniversalFile THEN { fileHandle: AlpFile.Handle _ NIL; [fileHandle] _ AlpFile.Open[transHandle: trans, universalFile: rootFile, access: readWrite, lock: [write, fail] ! AlpInstance.Unknown => CONTINUE; ]; IF fileHandle # NIL THEN AlpFile.Delete[fileHandle ! AlpInstance.Unknown => CONTINUE;]; }; [] _ trans.DestroyOwner[ volumeGroupID: trans.GetNextVolumeGroup[ previousGroup: AlpineEnvironment.nullVolumeGroupID, lock: [none, wait]], owner: owner]; IF (trans.Finish[requestedOutcome: commit, continue: FALSE] # commit) THEN { resultList _ CONS[ first: NARROW["Alpine transaction aborted -- owner NOT destroyed", ROPE], rest: NIL]; } ELSE resultList _ CONS[ first: NARROW["Owner destroyed", ROPE], rest: NIL]; }; DestroyOwnerProc: PUBLIC Buttons.ButtonProc = { resultList: LIST OF REF ANY _ NIL; d: MyData = NARROW[clientData]; server, user, file, password: ROPE; directory: ROPE; callDestroy: YodelData.PerformProc = { RETURN[destroyOwner[trans, server, directory, user, password, d]]; }; d.stopFlag _ FALSE; [user, password, server, directory, file] _ ParseSArgs[d]; d.out.PutF["\nDestroy Owner of [%g]%g \n", IO.rope[server], IO.rope[directory]]; resultList _ PerformOp[performProc: callDestroy, server: server, user: user, password: password]; DO nowRope: ROPE _ NARROW[List.Car[resultList]]; IF resultList = NIL THEN EXIT; resultList _ List.Cdr[resultList]; d.out.PutF[" %g\n", IO.rope[nowRope]]; ENDLOOP; }; writeQuota: PROC [trans: AlpTransaction.Handle, server: ROPE, directory: ROPE, user: ROPE _ NIL, password: ROPE _ NIL , properties: OwnerPropertyValuePairList, d: MyData] RETURNS [resultList: LIST OF REF ANY] = { owner: ROPE _ trimWedges[directory]; IF trans = NIL THEN RETURN [CONS[NARROW["Bad Server Name", ROPE], NIL]]; trans.AssertAlpineWheel[TRUE]; [] _ trans.WriteOwnerProperties[ volumeGroupID: trans.GetNextVolumeGroup[previousGroup: AlpineEnvironment.nullVolumeGroupID, lock: [none, wait]], owner: owner, properties: properties]; IF (trans.Finish[requestedOutcome: commit, continue: FALSE] # commit) THEN { resultList _ CONS[ first: NARROW["Alpine transaction aborted -- quota NOT changed", ROPE], rest: NIL]; } ELSE resultList _ CONS[ first: NARROW["Quota changed", ROPE], rest: NIL]; }; WriteQuotaProc: PUBLIC Buttons.ButtonProc = { resultList: LIST OF REF ANY _ NIL; d: MyData = NARROW[clientData]; server, user, password: ROPE; directory: ROPE; properties: OwnerPropertyValuePairList ; pageLimit: INT; newPageLimitRope: ROPE; scratchStream: IO.STREAM _ NIL; callWriteQuota: YodelData.PerformProc = { RETURN[writeQuota[trans, server, directory, user, password, properties, d]]; }; { d.stopFlag _ FALSE; [user, password, server, directory] _ ParseSArgs[d]; newPageLimitRope _ ViewerTools.GetContents[viewer: d.oQuota]; scratchStream _ IO.RIS[newPageLimitRope, scratchStream]; pageLimit _ IO.GetInt[scratchStream ! IO.EndOfStream, IO.Error => GOTO badInt]; properties _ LIST[[quota[pageLimit]]]; d.out.PutF["\nWrite quota for Owner of [%g]%g to %g pages\n", IO.rope[server], IO.rope[directory], IO.int[pageLimit]]; resultList _ PerformOp[performProc: callWriteQuota, server: server, user: user, password: password]; DO nowRope: ROPE _ NARROW[List.Car[resultList]]; IF resultList = NIL THEN EXIT; resultList _ List.Cdr[resultList]; d.out.PutF[" %g\n", IO.rope[nowRope]]; ENDLOOP; EXITS badInt => { d.out.PutF["\nWrite quota: bad quota specified\n"]; }; }; }; listOwners: PROC [trans: AlpTransaction.Handle] RETURNS [resultList: LIST OF REF ANY] = { owner: ROPE _ NIL ; properties: LIST OF AlpineEnvironment.OwnerPropertyValuePair; result: ROPE; totalQuota: INT _ 0 ; totalSpaceInUse: INT _ 0 ; IF trans = NIL THEN RETURN [CONS[NARROW["Bad Server Name", ROPE], NIL]]; trans.AssertAlpineWheel[TRUE]; DO quota: INT _ 0; spaceInUse: INT _ 0; [owner, properties] _ trans.ReadNextOwner[ volumeGroupID: trans.GetNextVolumeGroup[previousGroup: AlpineEnvironment.nullVolumeGroupID, lock: [none, wait]], previousOwner: owner, desiredProperties: ALL [TRUE]]; IF owner = NIL THEN EXIT; result _ IO.PutFR["%g\t\t", IO.rope[owner]]; UNTIL properties = NIL DO property: AlpineEnvironment.OwnerPropertyValuePair _ properties.first ; properties _ properties.rest; SELECT property.property FROM quota => { quota _ NARROW[property, AlpineEnvironment.OwnerPropertyValuePair.quota].quota; totalQuota _ totalQuota + quota ; result _ Rope.Concat[result, IO.PutFR["quota %5g ", IO.int[quota]]]; }; spaceInUse => { spaceInUse _ NARROW[property, AlpineEnvironment.OwnerPropertyValuePair.spaceInUse].spaceInUse; totalSpaceInUse _ totalSpaceInUse + spaceInUse ; result _ Rope.Concat[result, IO.PutFR["spaceInUse %5g ", IO.int[spaceInUse]]]; }; ENDCASE; ENDLOOP; IF quota > 0 THEN { percent: INT _ Real.Fix[(spaceInUse * 100.0)/quota]; result _ Rope.Concat[result, IO.PutFR[" (%2g%%) ", IO.int[percent]]]; IF percent > 90 THEN result _ Rope.Concat[result, " <-----"]; }; resultList _ CONS[ first: result, rest: resultList]; ENDLOOP; resultList _ CONS[ first: IO.PutFR[" totals\t\tspaceInUse %5g\tquota %5g\n", IO.int[totalSpaceInUse], IO.int[totalQuota] ], rest: resultList]; }; ListOwnersProc: PUBLIC Buttons.ButtonProc = { callListOwners: YodelData.PerformProc = { RETURN[listOwners[trans]]; }; resultList: LIST OF REF ANY _ NIL; d: MyData = NARROW[clientData]; server, user, password: ROPE; d.stopFlag _ FALSE; [user, password, server] _ ParseSArgs[d]; d.out.PutF["\nList Owners for server %g\n", IO.rope[server]]; resultList _ PerformOp[performProc: callListOwners, server: server, user: user, password: password]; resultList _ List.Sort[resultList, CompareProc]; DO nowRope: ROPE _ NARROW[List.Car[resultList]]; IF resultList = NIL THEN EXIT; resultList _ List.Cdr[resultList]; d.out.PutF[" %g\n", IO.rope[nowRope]]; ENDLOOP; }; readDBProperties: PROC [trans: AlpTransaction.Handle] RETURNS [resultList: LIST OF REF ANY] = { nOwners, nEntriesUsed, nEntries: NAT; totalQuota, totalSpaceInUse, volumeGroupSize: AlpineEnvironment.PageCount; IF trans = NIL THEN RETURN [CONS[NARROW["Bad Server Name", ROPE], NIL]]; trans.AssertAlpineWheel[TRUE]; TRUSTED { [nOwners, nEntriesUsed, nEntries, totalQuota, totalSpaceInUse, volumeGroupSize] _ trans.inst.owner.ReadDBProperties[conversation: trans.inst.conversation, transID: trans.transID, volumeGroupID: trans.GetNextVolumeGroup[previousGroup: AlpineEnvironment.nullVolumeGroupID, lock: [none, wait]]]; }; resultList _ CONS[ first: IO.PutFR[" owners %g, entries used %g, entries %g", IO.int[nOwners], IO.int[nEntriesUsed], IO.int[nEntries]], rest: CONS[ IO.PutFR[" total quota %g, total space in use %g, volume group size %g", IO.int[totalQuota], IO.int[totalSpaceInUse], IO.int[volumeGroupSize]], NIL] ]; }; ReadDBPropertiesProc: PUBLIC Buttons.ButtonProc = { callReadDBPropertiesProc: YodelData.PerformProc = { RETURN[readDBProperties[trans]]; }; resultList: LIST OF REF ANY _ NIL; d: MyData = NARROW[clientData]; server, user, password: ROPE; d.stopFlag _ FALSE; [user, password, server] _ ParseSArgs[d]; d.out.PutF["\nRead Statistics for server %g\n", IO.rope[server]]; resultList _ PerformOp[performProc: callReadDBPropertiesProc, server: server, user: user, password: password]; resultList _ List.Sort[resultList, CompareProc]; DO nowRope: ROPE _ NARROW[List.Car[resultList]]; IF resultList = NIL THEN EXIT; resultList _ List.Cdr[resultList]; d.out.PutF[" %g\n", IO.rope[nowRope]]; ENDLOOP }; END. ÔYodelAdministrator.mesa Last Edited by: Hagmann, April 4, 1984 4:24:43 pm PST filler to use all the variants so the compiler won't blow up (this is the cedar version of the "don't delete this line" comment Ê4˜Jšœ™Jšœ5™5J˜šÏk ˜ Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜J˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ ˜ —J˜Jšœœ˜!J˜JšœHœ+˜|J˜Jšœ ˜J˜J˜Jšœ˜J˜Jšœœ ˜J˜Jšœœœ˜Jšœœœœ*˜TJ˜JšÏn œœœœœœœ œœœœ ˜¤š Ïb œœ œœ œœ˜@Jšœœ˜!Jš œ œœœœ˜LJšœ(˜.J˜—J˜J˜šŸœœ˜0Jšœ œ ˜Jšœœ ˜)Jšœœ˜#Jšœœ+œ+˜oJšœ˜—J˜šŸœœ˜/Jšœ œ ˜Jšœœ ˜)Jšœœ˜!Jšœœ+œ+˜nJšœ˜—J˜šŸ œœ(œ œœœ œœ6œœœœœ˜ÕJšœœ˜Jšœœ˜$Jšœ œœœœœœœ˜HJšœœ˜Jšœæ˜æšœ3œ œ˜LJš œ œ œ4œ œ˜fJš œœœ œ:œ%œ˜‰—J˜J˜—šŸœœ˜.Jš œ œœœœœ˜"Jšœ œ ˜Jšœœ˜Jšœ œ˜Jšœ(˜(Jšœ œ˜Jšœœ˜Jšœœœœ˜J˜šœ%˜%JšœG˜MJ˜—Jšœ œ˜Jšœ4˜4Jšœ=˜=šœœ˜$Jšœ6˜6J˜—šœœ˜šœœœ˜8JšœPœ˜dJ˜—šœœ˜Jšœœœ"˜8Jšœ œ˜%Jšœ œ˜&J˜Jšœ6œœœ˜nJšœ`˜`š˜Jšœ œœ˜-Jšœœœœ˜Jšœ"˜"Jšœœ˜'Jšœ˜—J˜—J˜—J˜—J˜šŸ œœ(œ œœœ œœœœœœœ˜®š Ÿœœ œœ7œœ˜}Jšœœ˜J˜—Jšœœ˜$Jšœœœ˜Jšœ œœ*˜=JšœQ˜QJšœ œœœœœœœ˜HJšœœ˜JšœÑ˜ÑJšœœœœœAœœ˜JšœÚ˜ÚšœœœÏc9˜Sšœœ˜!šœA˜AJšœ˜—šœA˜AJšœ˜—Jšœ<™œœœ˜vJšœd˜dš˜Jšœ œœ˜-Jšœœœœ˜Jšœ"˜"Jšœœ˜'Jšœ˜—š˜šœ ˜ Jšœ3˜3J˜——J˜—J˜—J˜šŸ œœ œœœœœ˜YJšœœœ˜Jšœ œœ*˜=Jšœœ˜ Jšœ œ˜Jšœœ˜Jšœ œœœœœœœ˜HJšœœ˜š˜Jšœœ˜Jšœ œ˜Jšœæœœ˜òJšœ œœœ˜Jšœ œœ˜,šœœ˜JšœG˜GJšœ˜šœ˜˜ Jšœœ ˜JšœH˜HJšœ!˜!Jšœ˜Jšœœœ˜9J˜—šœ˜Jšœ œ ˜JšœR˜RJšœ0˜0Jšœ˜Jšœœœ˜CJ˜—Jšœ˜—Jšœ˜—šœ œ˜Jšœ œ(˜4Jšœ˜Jšœœœ˜:Jšœœ)˜=J˜—Jšœ œ#˜4Jšœ˜—Jš œ œ œ1œœ&˜ŽJšœ˜—J˜šŸœœ˜-šœ)˜)Jšœ˜J˜—Jš œ œœœœœ˜"Jšœ œ ˜Jšœœ˜J˜Jšœ œ˜J˜Jšœ)˜)Jšœ,œ˜=Jšœd˜dJšœ0˜0š˜Jšœ œœ˜-Jšœœœœ˜Jšœ"˜"Jšœœ˜'Jšœ˜—J˜—J˜šŸœœ œœœœœ˜_Jšœ!œ˜%JšœJ˜JJšœ œœœœœœœ˜HJšœœ˜šœ˜ Jšœ­˜­J˜—Jšœ œ œ6œœœœœLœœœœ˜¸J˜—J˜šŸœœ˜3šœ3˜3Jšœ˜ J˜—Jš œ œœœœœ˜"Jšœ œ ˜Jšœœ˜J˜Jšœ œ˜J˜Jšœ)˜)Jšœ0œ˜AJšœn˜nJšœ0˜0š˜Jšœ œœ˜-Jšœœœœ˜Jšœ"˜"Jšœœ˜'Jš˜—J˜J˜—J˜Jšœ˜J˜J˜J˜J˜J˜—…—2ÆAÎ