-- Grapevine: database measuring tool -- DBCount.mesa -- Andrew Birrell November 10, 1982 4:11 pm DIRECTORY BodyDefs, IO, LocateDefs USING[ FindRegServer, FoundServerInfo ], NameInfoDefs, Process USING[ Detach ], ProtocolDefs, PupDefs, String, UserExec USING[ CommandProc, RegisterCommand ], ViewerIO USING[ CreateViewerStreams ]; DBCount: MONITOR IMPORTS IO, LocateDefs, NameInfoDefs, Process, ProtocolDefs, String, UserExec, ViewerIO = BEGIN OPEN BodyDefs, 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 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; WriteType: PROC[out: IO.STREAM, type: RNameType] = BEGIN out.PutRope[SELECT type FROM group => "group", individual => "individual", notFound => "not found", dead => "dead", ENDCASE => ERROR]; END; WriteRC: PROC[out: IO.STREAM, rc: ReturnCode] = BEGIN out.PutRope[SELECT rc.code FROM done => "ok", noChange => "no change", outOfDate => "out of date", NotAllowed => "not allowed", BadOperation => "bad operation", BadProtocol => "bad protocol", BadRName => "bad R-Name: ", BadPassword => "bad password", WrongServer => "wrong server", AllDown => "all suitable R-Servers down", ENDCASE => ERROR]; IF rc.code = BadRName THEN WriteType[out, rc.type]; END; Complaint: PROC[out: IO.STREAM, name: RName, rc: ReturnCode] = BEGIN out.PutF["\n%g", [string[name]] ]; WriteRC[out, 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[out: IO.STREAM, n: LONG CARDINAL] = BEGIN out.PutF["%g words = %g pages\n", [cardinal[n]], [cardinal[(n+128)/256]] ]; END; WriteStats: PROC[out: IO.STREAM] = BEGIN out.PutF[" %g items\n", [cardinal[items]] ]; IF items = 0 THEN RETURN; out.PutRope[" total = "]; WriteWordCount[out, totalLength]; out.PutRope[" max size = "]; WriteWordCount[out, maxLength]; out.PutRope[" mean words = "]; WriteWordCount[out, totalLength/items]; totalLength _ maxLength _ items _ 0; END; Look: PROC[out: IO.STREAM, 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[out, 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[out: IO.STREAM, enumName: RName, work: PROC[IO.STREAM, RName]RETURNS[done: BOOLEAN] ] = -- argument is "groups.reg", "individuals.reg", or "dead.reg" -- BEGIN Enumeratee: PROC[name: RName]RETURNS[done: BOOLEAN] = { done _ work[out, name] }; memberInfo: MemberInfo; out.PutChar['\n]; out.Put[[string[enumName]]]; memberInfo _ GetMembers[enumName]; WITH memberInfo SELECT FROM group => BEGIN ENABLE UNWIND => Close[members]; out.PutChar['\n]; Enumerate[members, Enumeratee]; Close[members]; END; allDown => out.PutRope[": all R-Servers down!"]; notFound => out.PutRope[": not found!"]; 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[out: IO.STREAM, 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; out.PutF["\n\nRegistry %g\n", [string[regGroup]]]; String.AppendString[wanted, "Groups."L]; String.AppendString[wanted, regGroup]; LookEnum[out, wanted, Look]; dbGroups _ dbGroups + items; regTotal _ regTotal + totalLength; WriteStats[out]; wanted.length _ 0; String.AppendString[wanted, "Individuals."L]; String.AppendString[wanted, regGroup]; LookEnum[out, wanted, Look]; dbIndividuals _ dbIndividuals + items; regTotal _ regTotal + totalLength; WriteStats[out]; wanted.length _ 0; String.AppendString[wanted, "Dead."L]; String.AppendString[wanted, regGroup]; LookEnum[out, wanted, Look]; dbDead _ dbDead + items; regTotal _ regTotal + totalLength; WriteStats[out]; out.PutRope["\nTotal registry size = "]; WriteWordCount[out, regTotal]; dbRegistries _ dbRegistries + 1; dbSize _ dbSize + regTotal; done _ FALSE; END; LookAtAll: ENTRY PROC = BEGIN out: IO.STREAM = ViewerIO.CreateViewerStreams["GV database size measurement"].out; LookEnum[out, "Groups.gv", LookAtRegistry ! ProtocolDefs.Failed => { out.PutRope["ProtocolDefs.Failed"]; CONTINUE }]; out.PutF["\n\nEntire database contains:\n %g registries\n %g groups\n %g individuals\n %g dead entries\n Total size = ", [cardinal[dbRegistries]], [cardinal[dbGroups]], [cardinal[dbIndividuals]], [cardinal[dbDead]] ]; WriteWordCount[out, dbSize]; IF str # NIL THEN DestroyStream[str]; END; DoIt: UserExec.CommandProc = TRUSTED BEGIN ProtocolDefs.Init[]; Process.Detach[FORK LookAtAll[]]; END; UserExec.RegisterCommand["DBCount", DoIt, "Gather size statistics on GV database"]; END. Ę˜JšøĪc&œœ-œĪk œ žœ žœ;žœ4žœ+žœ#žœžœžœYžœžœQœ žœžœœžœœ.œĪnœžœžœažœ2žœ0žœYžœžœ žœ%žœžœŸ œžœ#žœ'žœ žœžœžœ žœ§žœ-žœ2žœ žœžœžœ´žœ žœžœžœCžœ žœžœžœEžœ žœžœžœžœžœžœ žœžœ žœžœŸœžœ žœ:žœŸœžœ žœžœžœžœ!žœžœŸœžœžœžœ žœ3žœžœžœžœžœžœžœžœ>žœ!žœ žœžœžœ žœ žœžœžœžœžœžœžœžœ'žœžœ%žœžœžœžœžœ žœžœžœžœžœQžœžœžœžœžœ'žœžœžœžœ žœžœ žœžœ#žœžœžœ žœžœ'œtžœ žœžœžœ(žœžœKžœ žœžœ žœžœŸ œžœžœžœžœžœžœyžœžœžœŸœžœžœžœžœžœ žœđžœžœžœžœžœŸ œžœžœžœ$žœ?žœŸœžœžœ žœžœ žœžœžœžœž œžœ(žœžœ žœžœ œZžœžœœžœžœžœžœ žœžœŸœžœžœžœžœžœžœSžœŸ œžœžœžœžœ5žœ žœžœųžœŸœžœžœžœžœžœžœžœžœ`žœžœ$žœžœžœžœžœžœžœžœžœžœžœžœ9žœžœlžœ!žœžœŸœžœžœžœ(žœžœžœžœžœ @œžœŸ œžœ žœžœžžœ žœžœžœžœžœržœižœžœžœžœžœžœžœžœžœžœžœžœžœŸœžœžœžœžœžœžœžœžœ.žœžœž œžœžœ,žœžœžœžœėžœžœŸ œžœžœžœžœžœ¸žœ›žœžœžœžœĪbœžœžœ)žœžœZžœ˜•J—…—%*: