-- 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.