[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] [pytorctl/master] Alter ConsensusTracker to actually track the consensus.
Author: Mike Perry <mikeperry-git@xxxxxxxxxx>
Date: Mon, 27 Sep 2010 14:34:19 -0700
Subject: Alter ConsensusTracker to actually track the consensus.
Commit: 3972639c49844ff77cd3175671357b47669526ce
It was tracking the Tor client's notion of the consensus, in a poor way. It
now can do one or the other, depending on constructor option.
Also, add some APIs that are helpful for torperf.
---
TorCtl.py | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/TorCtl.py b/TorCtl.py
index e16b64e..4382ba9 100755
--- a/TorCtl.py
+++ b/TorCtl.py
@@ -811,6 +811,10 @@ class Connection:
self.set_event_handler(EventHandler())
self._handler.add_event_listener(listener)
+ def block_until_close(self):
+ """ Blocks until the connection to the Tor process is interrupted"""
+ return self._eventThread.join()
+
def _read_reply(self):
lines = []
while 1:
@@ -1012,6 +1016,11 @@ class Connection:
"""
self.sendAndRecv("RESETCONF %s\r\n"%(" ".join(keylist)))
+ def get_consensus(self):
+ """Get the pristine Tor Consensus. Returns a list of
+ TorCtl.NetworkStatus instances."""
+ return parse_ns_body(self.sendAndRecv("GETINFO dir/status-vote/current/consensus\r\n")[0][2])
+
def get_network_status(self, who="all"):
"""Get the entire network status list. Returns a list of
TorCtl.NetworkStatus instances."""
@@ -1556,8 +1565,15 @@ class ConsensusTracker(EventHandler):
"""
A ConsensusTracker is an EventHandler that tracks the current
consensus of Tor in self.ns_map, self.routers and self.sorted_r
+
+ Users must subscribe to "NEWCONSENSUS" and "NEWDESC" events.
+
+ If you also wish to track the Tor client's opinion on the Running flag
+ based on reachability tests, you must subscribe to "NS" events,
+ and you should set the constructor parameter "consensus_only" to
+ False.
"""
- def __init__(self, c, RouterClass=Router):
+ def __init__(self, c, RouterClass=Router, consensus_only=True):
EventHandler.__init__(self)
c.set_event_handler(self)
self.ns_map = {}
@@ -1566,6 +1582,7 @@ class ConsensusTracker(EventHandler):
self.name_to_key = {}
self.RouterClass = RouterClass
self.consensus_count = 0
+ self.consensus_only = consensus_only
self.update_consensus()
# XXX: If there were a potential memory leak through perpetually referenced
@@ -1646,7 +1663,10 @@ class ConsensusTracker(EventHandler):
self.name_to_key[n.nickname] = "$"+n.idhex
def update_consensus(self):
- self._update_consensus(self.c.get_network_status())
+ if self.consensus_only:
+ self._update_consensus(self.c.get_consensus())
+ else:
+ self._update_consensus(self.c.get_network_status())
self._read_routers(self.ns_map.values())
def new_consensus_event(self, n):
@@ -1660,7 +1680,11 @@ class ConsensusTracker(EventHandler):
for i in d.idlist:
r = None
try:
- ns = self.c.get_network_status("id/"+i)
+ if i in self.ns_map:
+ ns = (self.ns_map[i],)
+ else:
+ plog("WARN", "Need to getinfo ns/id for router desc: "+i)
+ ns = self.c.get_network_status("id/"+i)
r = self.c.read_routers(ns)
except ErrorReply, e:
plog("WARN", "Error reply for "+i+" after NEWDESC: "+str(e))
@@ -1698,6 +1722,31 @@ class ConsensusTracker(EventHandler):
self._sanity_check(self.sorted_r)
return update
+ def ns_event(self, ev):
+ update = False
+ for ns in ev.nslist:
+ # Check current consensus.. If present, check flags
+ if ns.idhex in self.ns_map and ns.idhex in self.routers and \
+ ns.orhash == self.ns_map[ns.idhex].orhash:
+ if "Running" in ns.flags and \
+ "Running" not in self.ns_map[ns.idhex].flags:
+ plog("INFO", "Router "+ns.nickname+"="+ns.idhex+" is now up.")
+ update = True
+ self.routers[ns.idhex].flags = ns.flags
+ self.routers[ns.idhex].down = False
+
+ if "Running" not in ns.flags and \
+ "Running" in self.ns_map[ns.idhex].flags:
+ plog("INFO", "Router "+ns.nickname+"="+ns.idhex+" is now down.")
+ update = True
+ self.routers[ns.idhex].flags = ns.flags
+ self.routers[ns.idhex].down = True
+ if update:
+ self.sorted_r = filter(lambda r: not r.down, self.routers.itervalues())
+ self.sorted_r.sort(lambda x, y: cmp(y.bw, x.bw))
+ for i in xrange(len(self.sorted_r)): self.sorted_r[i].list_rank = i
+ self._sanity_check(self.sorted_r)
+
def current_consensus(self):
return Consensus(self.ns_map, self.sorted_r, self.routers,
self.name_to_key, self.consensus_count)
--
1.7.1