-- Grapevine: database measuring tool -- DBCount.mesa -- Andrew Birrell 28-Jan-82 12:56:10 DIRECTORY BodyDefs, IODefs, LaurelExecDefs, LocateDefs USING[ FindRegServer, FoundServerInfo ], NameInfoDefs, ProtocolDefs, PupDefs, Runtime, StringDefs, TimeDefs; DBCount: PROGRAM IMPORTS IODefs, LaurelExecDefs, LocateDefs, NameInfoDefs, ProtocolDefs, Runtime, StringDefs, TimeDefs = BEGIN OPEN BodyDefs, IODefs, NameInfoDefs, ProtocolDefs, PupDefs; serverAddr: PupDefs.PupAddress; -- other server's address -- addrKnown: BOOLEAN _ FALSE; -- validity of serverAddr -- str: Handle _ NIL; -- stream to other server -- -- "Operate" procedure stolen from Maintain -- Operate: PUBLIC PROC[op: ProtocolDefs.RSOperation, name: BodyDefs.RName, value: BodyDefs.RName _ NIL, connect: BodyDefs.Connect _ NIL, remark: BodyDefs.Remark _ NIL, key: BodyDefs.Password _ [0,0,0,0], sendRList: PROC[ProtocolDefs.Handle] _ NIL ] RETURNS[ rc: ProtocolDefs.ReturnCode ] = BEGIN OPEN ProtocolDefs; TryUpdate: PROC[str: ProtocolDefs.Handle] = BEGIN SendRSOperation[str, op]; IF op # NoOp THEN SendRName[str, name]; SELECT op FROM IN [Expand..ReadEntry] => SendTimestamp[str, BodyDefs.oldestTime]; IdentifyCaller => SendPassword[str:str, pw: key, key: [0,0,0,0]]; IN [AddMember..DeleteFriend], NewName, IN [IsMemberDirect..IsFriendClosure] => { IF value = NIL THEN ERROR; SendRName[str, value] }; Authenticate, CreateIndividual, ChangePassword => SendPassword[str:str, pw: key, key: [0,0,0,0]]; ChangeConnect => { IF connect = NIL THEN ERROR; SendConnect[str, connect] }; ChangeRemark => { IF remark = NIL THEN ERROR; SendRemark[str, remark] }; AddListOfMembers => { IF sendRList = NIL THEN ERROR; sendRList[str] }; ENDCASE => NULL; SendNow[str]; IF op # NoOp THEN rc _ ReceiveRC[str]; END; oldBad: BOOLEAN _ FALSE; Create: PROC = BEGIN serverSite: STRING = [21] --377#377#177777|177777--; str _ ProtocolDefs.CreateStream[serverAddr]; END; Destroy: PROC = BEGIN IF str # NIL THEN DestroyStream[str]; str _ NIL; END; Accept: PROC[addr: PupDefs.PupAddress]RETURNS[BOOLEAN] = BEGIN addr.socket _ RegServerEnquirySocket; IF str # NIL AND serverAddr # addr THEN Destroy[]; IF str = NIL THEN BEGIN serverAddr _ addr; Create[ ! Failed => GOTO failed]; addrKnown _ TRUE; END; RETURN[TRUE]; EXITS failed => RETURN[FALSE] END; BEGIN IF str # NIL THEN BEGIN TryUpdate[ str ! Failed => GOTO streamGone ]; EXITS streamGone => Destroy[]; END; IF str = NIL THEN BEGIN IF addrKnown THEN Create[ ! Failed => GOTO notThere] ELSE BEGIN [] _ LocateDefs.FindRegServer["x.GV"L, Accept]; IF str = NIL THEN GOTO notThere; END; TryUpdate[str ! Failed => GOTO notThere]; END; IF rc.code = WrongServer THEN oldBad _ TRUE ELSE oldBad _ FALSE; EXITS notThere => { Destroy[]; oldBad _ TRUE }; END; IF oldBad THEN BEGIN -- need to find the correct R-Server -- foundInfo: LocateDefs.FoundServerInfo; foundInfo _ LocateDefs.FindRegServer[name, Accept]; WITH foundInfo SELECT FROM notFound => rc _ [BadRName, notFound]; allDown => rc _ [AllDown,notFound]; found => BEGIN TryUpdate[ str ! Failed => GOTO down ]; EXITS down => { Destroy[]; rc _ [AllDown,notFound] }; END; ENDCASE => ERROR; END; END; WriteLongDecimal: PROC[n: LONG CARDINAL] = BEGIN s: STRING = [10]; StringDefs.AppendLongNumber[s, n, 10]; WriteString[s]; END; WriteStamp: PROC[stamp: Timestamp] = BEGIN text: STRING = [30]; WriteOctal: PROC[n: CARDINAL] = BEGIN buffer: STRING = [6] --177777--; StringDefs.AppendNumber[buffer, n, 8]; WriteString[buffer]; END; WriteChar['[]; WriteOctal[stamp.net]; WriteChar['#]; WriteOctal[stamp.host]; WriteChar[',]; TimeDefs.AppendDayTime [text, TimeDefs.UnpackDT [stamp.time]]; WriteString[text]; WriteChar[']]; END; WriteType: PROC[type: RNameType] = BEGIN WriteString[SELECT type FROM group => "group"L, individual => "individual"L, notFound => "not found"L, dead => "dead"L, ENDCASE => ERROR]; END; WriteRC: PROC[rc: ReturnCode] = BEGIN WriteString[SELECT rc.code FROM done => "ok"L, noChange => "no change"L, outOfDate => "out of date"L, NotAllowed => "not allowed"L, BadOperation => "bad operation"L, BadProtocol => "bad protocol"L, BadRName => "bad R-Name: "L, BadPassword => "bad password"L, WrongServer => "wrong server"L, AllDown => "all suitable R-Servers down"L, ENDCASE => ERROR]; IF rc.code = BadRName THEN WriteType[rc.type]; END; Complaint: PROC[name: RName, rc: ReturnCode] = BEGIN WriteChar[CR]; WriteString[name]; WriteRC[rc]; END; AcceptComponent: PROC[thisStr: Handle] RETURNS[length: CARDINAL] = BEGIN bLength: CARDINAL = 64; buffer1: PACKED ARRAY [0..bLength) OF CHARACTER; length1: CARDINAL _ (length _ ReceiveCount[thisStr]); WHILE length1 > 0 DO wanted1: CARDINAL = 2*MIN[bLength/2, length1] --bytes--; ReceiveBytes[thisStr, @buffer1, wanted1]; length1 _ length1 - wanted1/2; ENDLOOP; END; -- stats increased by "Look" -- totalLength: LONG CARDINAL _ 0; maxLength: LONG CARDINAL _ 0; items: LONG CARDINAL _ 0; WriteWordCount: PROC[n: LONG CARDINAL] = BEGIN WriteLongDecimal[n]; WriteString[" words = "L]; WriteLongDecimal[(n+128)/256]; WriteString[" pages"L]; WriteChar[CR]; END; WriteStats: PROC = BEGIN WriteString[" "L]; WriteLongDecimal[items]; WriteString[" items"L]; WriteChar[CR]; IF items = 0 THEN RETURN; WriteString[" total = "L]; WriteWordCount[totalLength]; WriteString[" max size = "L]; WriteWordCount[maxLength]; WriteString[" mean words = "L]; WriteLongDecimal[totalLength/items]; WriteChar[CR]; totalLength _ maxLength _ items _ 0; END; Look: PROC[name: RName]RETURNS[done: BOOLEAN] = BEGIN thisLength: LONG CARDINAL _ 0; stamp2: Timestamp; rc2: ReturnCode; rc2 _ Operate[op: ReadEntry, name: name]; IF rc2.code = done THEN stamp2 _ ReceiveTimestamp[str]; IF rc2.code # done THEN Complaint[name, rc2] ELSE BEGIN count2: CARDINAL _ IF rc2.code # done THEN 0 ELSE ReceiveCount[str]; FOR c: CARDINAL IN [0..count2) DO thisLength _ thisLength + AcceptComponent[str]; ENDLOOP; maxLength _ MAX[maxLength, thisLength]; totalLength _ totalLength + thisLength; items _ items + 1; END; done _ rc2.code=WrongServer OR rc2.code=AllDown; END; LookEnum: PROC[enumName: RName, work: PROC[RName]RETURNS[done: BOOLEAN] ] = -- argument is "groups.reg", "individuals.reg", or "dead.reg" -- BEGIN memberInfo: MemberInfo; WriteChar[CR]; WriteString[enumName]; memberInfo _ GetMembers[enumName]; WITH memberInfo SELECT FROM group => BEGIN ENABLE UNWIND => Close[members]; WriteChar[CR]; Enumerate[members, work]; Close[members]; END; allDown => WriteString[": all R-Servers down!"L]; notFound => WriteString[": not found!"L]; ENDCASE => ERROR; END; dbRegistries: LONG CARDINAL _ 0; dbIndividuals: LONG CARDINAL _ 0; dbGroups: LONG CARDINAL _ 0; dbDead: LONG CARDINAL _ 0; dbSize: LONG CARDINAL _ 0; LookAtRegistry: PROC[regGroup: RName] RETURNS[done: BOOLEAN] = BEGIN regTotal: LONG CARDINAL _ 0; wanted: RName = [maxRNameLength]; FOR i: CARDINAL DECREASING IN [0..regGroup.length) DO regGroup.length _ regGroup.length-1; IF regGroup[i] = '. THEN EXIT; ENDLOOP; WriteChar[CR]; WriteChar[CR]; WriteString["Registry "L]; WriteLine[regGroup]; StringDefs.AppendString[wanted, "Groups."L]; StringDefs.AppendString[wanted, regGroup]; LookEnum[wanted, Look]; dbGroups _ dbGroups + items; regTotal _ regTotal + totalLength; WriteStats[]; wanted.length _ 0; StringDefs.AppendString[wanted, "Individuals."L]; StringDefs.AppendString[wanted, regGroup]; LookEnum[wanted, Look]; dbIndividuals _ dbIndividuals + items; regTotal _ regTotal + totalLength; WriteStats[]; wanted.length _ 0; StringDefs.AppendString[wanted, "Dead."L]; StringDefs.AppendString[wanted, regGroup]; LookEnum[wanted, Look]; dbDead _ dbDead + items; regTotal _ regTotal + totalLength; WriteStats[]; WriteChar[CR]; WriteString["Total registry size = "L]; WriteWordCount[regTotal]; dbRegistries _ dbRegistries + 1; dbSize _ dbSize + regTotal; done _ FALSE; END; LookAtAll: PROC = { LookEnum["Groups.gv"L, LookAtRegistry ! ProtocolDefs.Failed => { WriteString["ProtocolDefs.Failed"L]; CONTINUE }] }; IF Runtime.IsBound[LaurelExecDefs.MakeMenuCommandCallable] THEN BEGIN LaurelExecDefs.MakeMenuCommandCallable[user]; LaurelExecDefs.MakeMenuCommandCallable[newMail]; LaurelExecDefs.MakeMenuCommandCallable[mailFile]; LaurelExecDefs.MakeMenuCommandCallable[display]; LaurelExecDefs.MakeMenuCommandCallable[delete]; LaurelExecDefs.MakeMenuCommandCallable[undelete]; LaurelExecDefs.MakeMenuCommandCallable[moveTo]; LaurelExecDefs.MakeMenuCommandCallable[copy]; END; ProtocolDefs.Init[]; LookAtAll[]; WriteChar[CR]; WriteChar[CR]; WriteString["Entire database contains:"L]; WriteChar[CR]; WriteString[" "L]; WriteLongDecimal[dbRegistries]; WriteLine[" registries"L]; WriteString[" "L]; WriteLongDecimal[dbGroups]; WriteLine[" groups"L]; WriteString[" "L]; WriteLongDecimal[dbIndividuals]; WriteLine[" individuals"L]; WriteString[" "L]; WriteLongDecimal[dbDead]; WriteLine[" dead entries"L]; WriteString[" Total size = "L]; WriteWordCount[dbSize]; IF str # NIL THEN DestroyStream[str]; END.