[or-cvs] r9497: Support python 2.3, add collection of running orconn bw stat (torflow/trunk)

mikeperry at seul.org mikeperry at seul.org
Tue Feb 6 05:47:43 UTC 2007


Author: mikeperry
Date: 2007-02-06 00:47:35 -0500 (Tue, 06 Feb 2007)
New Revision: 9497

Added:
   torflow/trunk/data/
Modified:
   torflow/trunk/TorCtl.py
   torflow/trunk/metatroller.py
   torflow/trunk/nodemon.py
Log:
Support python 2.3, add collection of running orconn bw stats to node monitor.



Modified: torflow/trunk/TorCtl.py
===================================================================
--- torflow/trunk/TorCtl.py	2007-02-06 04:58:56 UTC (rev 9496)
+++ torflow/trunk/TorCtl.py	2007-02-06 05:47:35 UTC (rev 9497)
@@ -416,7 +416,7 @@
             rj = re.search(r"^reject (\S+):([^-]+)(?:-(\d+))?", line)
             bw = re.search(r"^bandwidth \d+ \d+ (\d+)", line)
             if re.search(r"^opt hibernating 1", line):
-                dead = 1
+                dead = 1 # XXX: Technically this may be stale..
             if ac:
                 exitpolicy.append(ExitPolicyLine(1, *ac.groups()))
             elif rj:

Modified: torflow/trunk/metatroller.py
===================================================================
--- torflow/trunk/metatroller.py	2007-02-06 04:58:56 UTC (rev 9496)
+++ torflow/trunk/metatroller.py	2007-02-06 05:47:35 UTC (rev 9497)
@@ -41,8 +41,8 @@
 # Technically we could just add member vars as we need them, but this
 # is a bit more clear
 class MetaRouter(TorCtl.Router):
-    def __init__(self, router):
-        # XXX: Copy router stuff over
+    def __init__(self, router): # Promotion constructor :)
+        self.__dict__ = router.__dict__
         self.failed = 0
         self.suspected = 0
         self.circ_selections = 0
@@ -51,10 +51,11 @@
         self.reason_failed = {}
 
 class MetaCircuit(TorCtl.Circuit):
-    def __init__(self, circuit):
-        # XXX: Copy circuit stuff over
+    def __init__(self, circuit): # Promotion
+        self.__dict__ = circuit.__dict__
         self.detached_cnt = 0
         self.used_cnt = 0
+        self.created_at = 0
     
 class Stream:
     def __init__(self):
@@ -90,7 +91,7 @@
         try:
             key_to_name[ns.idhex] = ns.name
             name_to_key[ns.name] = ns.idhex
-            r = c.get_router(ns)
+            r = MetaRouter(c.get_router(ns))
             if ns.idhex in routers:
                 if routers[ns.idhex].name != r.name:
                     plog("NOTICE", "Router "+r.idhex+" changed names from "
@@ -107,7 +108,7 @@
         except:
             traceback.print_exception(*sys.exc_info())
             continue
-    sorted_r.sort(cmp, lambda sr: sr.bw)
+    sorted_r.sort(lambda x, y: cmp(y.bw, x.bw))
 
     global total_r_bw, total_g_bw # lame....
     for r in sorted_r:
@@ -146,11 +147,12 @@
                     attach_circ = circ
                     break
             else:
-                attach_circ = self.c.build_circuit(3, choose_entry_uniform,
+                attach_circ = MetaCircuit(
+                                self.c.build_circuit(3, choose_entry_uniform,
                                       choose_middle_uniform,
                                       lambda path:
                                           choose_exit_uniform(path,
-                                          target_host, target_port))
+                                          target_host, target_port)))
                 circuits[attach_circ.cid] = attach_circ
             # TODO: attach
         elif status == "DETACHED":

Modified: torflow/trunk/nodemon.py
===================================================================
--- torflow/trunk/nodemon.py	2007-02-06 04:58:56 UTC (rev 9496)
+++ torflow/trunk/nodemon.py	2007-02-06 05:47:35 UTC (rev 9497)
@@ -16,16 +16,21 @@
 from TorUtil import *
 import sched, time
 import thread
+import copy
 
 class Reason:
     def __init__(self, reason): self.reason = reason
     ncircs = 0
     count = 0
 
-class RouterReasons:
-    # reason strings to Reason
-    def __init__(self, target): 
-        self.name = target
+class RouterStats(TorCtl.Router):
+    # Behold, a "Promotion Constructor"!
+    # Also allows null superclasses! Python is awesome
+    def __init__(self, r=None): 
+        if r:
+            self.__dict__ = r.__dict__
+        else:
+            self.down = 0
         self.reasons = {} # For a fun time, move this outside __init__
     tot_ncircs = 0
     tot_count = 0
@@ -45,7 +50,31 @@
 control_port = 9051
 max_detach = 3
 
+def read_routers(c, nslist):
+    bad_key = 0
+    errors_lock.acquire()
+    for ns in nslist:
+        try:
+            key_to_name[ns.idhex] = ns.name
+            name_to_key[ns.name] = ns.idhex
+            r = RouterStats(c.get_router(ns))
+            if ns.name in errors:
+                if errors[ns.name].idhex != r.idhex:
+                    plog("NOTICE", "Router "+r.name+" has multiple keys: "
+                         +errors[ns.name].idhex+" and "+r.idhex)
+            errors[r.name] = r # XXX: We get names only from ORCONN :(
+        except TorCtl.ErrorReply:
+            bad_key += 1
+            if "Running" in ns.flags:
+                plog("INFO", "Running router "+ns.name+"="
+                     +ns.idhex+" has no descriptor")
+            pass
+        except:
+            traceback.print_exception(*sys.exc_info())
+            continue
+    errors_lock.release()
 
+ 
 # Make eventhandler
 class NodeHandler(TorCtl.EventHandler):
     def __init__(self, c):
@@ -59,13 +88,17 @@
             if target not in key_to_name:
                 target = "AllClients:HASH"
             else: target = key_to_name[target]
-        elif target not in name_to_key: 
+        elif target not in name_to_key:
+            plog("DEBUG", "IP? " + target)
             target = "AllClients:IP"
 
         if status == "READ" or status == "WRITE":
             #plog("DEBUG", "Read: " + str(read) + " wrote: " + str(wrote))
             errors_lock.acquire()
-            if target not in errors: errors[target] = RouterReasons(target)
+            if target not in errors:
+                plog("NOTICE", "Buh?? No "+target)
+                errors[target] = RouterStats()
+                errors[target].name = target
             errors[target].running_read += read
             errors[target].running_wrote += wrote
             errors_lock.release()
@@ -73,7 +106,12 @@
             
         if status == "CLOSED" or status == "FAILED":
             errors_lock.acquire()
-            if target not in errors: errors[target] = RouterReasons(target)
+            if target not in errors:
+                plog("NOTICE", "Buh?? No "+target)
+                errors[target] = RouterStats()
+                errors[target].name = target
+            if status == "FAILED" and not errors[target].down:
+                status = status + "(Running)"
             reason = status+":"+reason
             if reason not in errors[target].reasons:
                 errors[target].reasons[reason] = Reason(reason)
@@ -101,16 +139,11 @@
                            reason, ncircs)))
 
     def ns(self, eventtype, nslist):
-        for ns in nslist:
-            key_to_name[ns.idhex] = ns.name
-            name_to_key[ns.name] = ns.idhex
-    
+        read_routers(self.c, nslist)
+ 
     def new_desc(self, eventtype, identities):
-        for i in identities:
-            nslist = self.c.get_network_status("id/"+i)
-            for ns in nslist: # should be only 1, but eh
-                key_to_name[ns.idhex] = ns.name
-                name_to_key[ns.name] = ns.idhex
+        for i in identities: # Is this too slow?
+            read_routers(self.c, self.c.get_network_status("id/"+i))
 
 def bw_stats(key, f):
     routers = errors.values()
@@ -132,26 +165,30 @@
     #    3. Routers sorted by tot bytes
     bw_stats(lambda x: x.tot_read+x.tot_wrote, file("./data/r_by_tbytes", "w"))
     #    4. Routers sorted by downstream bw
-    bw_stats(lambda x: x.tot_read/(x.tot_age+0.005), 
+    bw_stats(lambda x: x.tot_read/(x.tot_age+0.005),
              file("./data/r_by_rbw", "w"))
     #    5. Routers sorted by upstream bw
     bw_stats(lambda x: x.tot_wrote/(x.tot_age+0.005), file("./data/r_by_wbw", "w"))
     #    6. Routers sorted by total bw
-    bw_stats(lambda x: (x.tot_read+x.tot_wrote)/(x.tot_age+0.005), 
+    bw_stats(lambda x: (x.tot_read+x.tot_wrote)/(x.tot_age+0.005),
              file("./data/r_by_tbw", "w"))
 
-    bw_stats(lambda x: x.running_read, 
+    bw_stats(lambda x: x.running_read,
             file("./data/r_by_rrunbytes", "w"))
-    bw_stats(lambda x: x.running_wrote, 
+    bw_stats(lambda x: x.running_wrote,
             file("./data/r_by_wrunbytes", "w"))
-    bw_stats(lambda x: x.running_read+x.running_wrote, 
+    bw_stats(lambda x: x.running_read+x.running_wrote,
             file("./data/r_by_trunbytes", "w"))
     
     
-    
     f = file("./data/reasons", "w")
     routers = errors.values()
-    routers.sort(lambda x, y: cmp(y.tot_ncircs, x.tot_ncircs))
+    def notlambda(x, y):
+        if y.tot_ncircs or x.tot_ncircs:
+            return cmp(y.tot_ncircs, x.tot_ncircs)
+        else:    
+            return cmp(y.tot_count, x.tot_count)
+    routers.sort(notlambda)
 
     for r in routers:
         f.write(r.name+" " +str(r.tot_ncircs)+"/"+str(r.tot_count)+"\n")
@@ -167,10 +204,8 @@
 def startmon(c):
     global key_to_name, name_to_key
     nslist = c.get_network_status()
-    for ns in nslist:
-        key_to_name[ns.idhex] = ns.name
-        name_to_key[ns.name] = ns.idhex
-
+    read_routers(c, nslist)
+    
     s=sched.scheduler(time.time, time.sleep)
 
     s.enter(60, 1, save_stats, (s,))



More information about the tor-commits mailing list