[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r22556: {arm} added: observed bandwidth fetched from self descriptor fix: (in arm/trunk: interface/graphing util)



Author: atagar
Date: 2010-06-26 22:03:30 +0000 (Sat, 26 Jun 2010)
New Revision: 22556

Modified:
   arm/trunk/interface/graphing/bandwidthStats.py
   arm/trunk/interface/graphing/graphPanel.py
   arm/trunk/util/torTools.py
Log:
added: observed bandwidth fetched from self descriptor
fix: crashing issue when graph collapsed too much



Modified: arm/trunk/interface/graphing/bandwidthStats.py
===================================================================
--- arm/trunk/interface/graphing/bandwidthStats.py	2010-06-26 16:10:01 UTC (rev 22555)
+++ arm/trunk/interface/graphing/bandwidthStats.py	2010-06-26 22:03:30 UTC (rev 22556)
@@ -4,6 +4,7 @@
 """
 
 import time
+from TorCtl import TorCtl
 
 import graphPanel
 from util import torTools, uiTools
@@ -19,6 +20,59 @@
 
 DEFAULT_CONFIG = {"features.graph.bw.showAccounting": True, "features.graph.bw.isAccountingTimeLong": False}
 
+class ObservedBandwidthTracker(TorCtl.PostEventListener):
+  """
+  This keeps track of the relay's current observed bandwidth (the throughput
+  noted by the directory authorities and used by clients for relay selection).
+  This is a parameter of the descriptors and hence is likely to get stale.
+  """
+  
+  def __init__(self):
+    TorCtl.PostEventListener.__init__(self)
+    self.observedBandwidth = None
+    
+    conn = torTools.getConn()
+    conn.addEventListener(self) # listenes for NEWDESC events
+    conn.addStatusListener(self.resetListener) # listens for new controllers
+    
+    self._parseDescriptors()
+  
+  def getObservedBandwidth(self):
+    """
+    Reports the observed bandwidth noted in the cached descriptors. This
+    provides None if descriptors are unavailable or otherwise unable to be
+    parsed.
+    """
+    
+    return self.observedBandwidth
+  
+  def new_desc_event(self, event):
+    self._parseDescriptors()
+  
+  def _parseDescriptors(self):
+    conn = torTools.getConn()
+    myFingerprint = conn.getInfo("fingerprint")
+    myDescLines = []
+    
+    if myFingerprint:
+      myDesc = conn.getInfo("desc/id/%s" % myFingerprint)
+      if myDesc: myDescLines = myDesc.split("\n")
+    
+    for line in myDescLines:
+      if line.startswith("bandwidth"):
+        # line should look something like:
+        # bandwidth 40960 102400 47284
+        comp = line.split()
+        
+        if len(comp) == 4 and comp[-1].isdigit():
+          self.observedBandwidth = uiTools.getSizeLabel(int(comp[-1]), 1)
+          return
+    
+    self.observedBandwidth = None # no bandwidth desc entry found
+  
+  def resetListener(self, conn, eventType):
+    if eventType == torTools.TOR_INIT: self._parseDescriptors()
+
 class BandwidthStats(graphPanel.GraphStats):
   """
   Uses tor BW events to generate bandwidth usage graph.
@@ -30,6 +84,8 @@
     self._config = dict(DEFAULT_CONFIG)
     if config: config.update(self._config)
     
+    self.observedBwTracker = ObservedBandwidthTracker()
+    
     # accounting data (set by _updateAccountingInfo method)
     self.accountingInfo = dict([(arg, "") for arg in ACCOUNTING_ARGS])
     
@@ -121,24 +177,18 @@
         panel.addfstr(10, 0, "<b>Accounting:</b> Connection Closed...")
   
   def getTitle(self, width):
-    # provides label, dropping stats if there's not enough room
-    capLabel = "cap: %s" % self.bwRate if self.bwRate else ""
-    burstLabel = "burst: %s" % self.bwBurst if self.bwBurst else ""
+    stats, observedBw = [], self.observedBwTracker.getObservedBandwidth()
+    if self.bwRate: stats.append("limit: %s" % self.bwRate)
+    if self.bwBurst: stats.append("burst: %s" % self.bwBurst)
+    if observedBw: stats.append("observed: %s" % observedBw)
     
-    if capLabel and burstLabel:
-      bwLabel = " (%s, %s)" % (capLabel, burstLabel)
-    elif capLabel or burstLabel:
-      # only one is set - use whatever's avaialble
-      bwLabel = " (%s%s)" % (capLabel, burstLabel)
-    else:
-      bwLabel = ""
-    
-    labelContents = "Bandwidth%s:" % bwLabel
-    if width < len(labelContents):
-      labelContents = "%s):" % labelContents[:labelContents.find(",")]  # removes burst measure
-      if width < len(labelContents): labelContents = "Bandwidth:"       # removes both
-    
-    return labelContents
+    while True:
+      if not stats: return "Bandwidth:"
+      else:
+        label = "Bandwidth (%s):" % ", ".join(stats)
+        
+        if len(label) > width: del stats[-1]
+        else: return label
   
   def getHeaderLabel(self, width, isPrimary):
     graphType = "Downloaded" if isPrimary else "Uploaded"

Modified: arm/trunk/interface/graphing/graphPanel.py
===================================================================
--- arm/trunk/interface/graphing/graphPanel.py	2010-06-26 16:10:01 UTC (rev 22555)
+++ arm/trunk/interface/graphing/graphPanel.py	2010-06-26 22:03:30 UTC (rev 22556)
@@ -266,8 +266,12 @@
         secondaryMaxBound = param.maxSecondary[self.updateInterval]
       else:
         # both BOUNDS_LOCAL_MAX and BOUNDS_TIGHT use local maxima
-        primaryMaxBound = max(param.primaryCounts[self.updateInterval][1:graphCol + 1])
-        secondaryMaxBound = max(param.secondaryCounts[self.updateInterval][1:graphCol + 1])
+        if graphCol < 2:
+          # nothing being displayed
+          primaryMaxBound, secondaryMaxBound = 0, 0
+        else:
+          primaryMaxBound = max(param.primaryCounts[self.updateInterval][1:graphCol + 1])
+          secondaryMaxBound = max(param.secondaryCounts[self.updateInterval][1:graphCol + 1])
       
       primaryMinBound = secondaryMinBound = 0
       if self.bounds == BOUNDS_TIGHT:

Modified: arm/trunk/util/torTools.py
===================================================================
--- arm/trunk/util/torTools.py	2010-06-26 16:10:01 UTC (rev 22555)
+++ arm/trunk/util/torTools.py	2010-06-26 22:03:30 UTC (rev 22556)
@@ -256,7 +256,8 @@
     TorCtl.PostEventListener.__init__(self)
     self.conn = None                    # None if uninitialized or controller's been closed
     self.connLock = threading.RLock()
-    self.listeners = []                 # callback functions for tor's state changes
+    self.eventListeners = []            # instances listening for tor controller events
+    self.statusListeners = []           # callback functions for tor's state changes
     self.controllerEvents = {}          # mapping of successfully set controller events to their failure level/msg
     self._isReset = False               # internal flag for tracking resets
     self._status = TOR_CLOSED           # current status of the attached control port
@@ -445,6 +446,21 @@
     
     return (self._status, self._statusTime)
   
+  def addEventListener(self, listener):
+    """
+    Directs further tor controller events to callback functions of the
+    listener. If a new control connection is initialized then this listener is
+    reattached.
+    
+    Arguments:
+      listener - TorCtl.PostEventListener instance listening for events
+    """
+    
+    self.connLock.acquire()
+    self.eventListeners.append(listener)
+    if self.isAlive(): self.conn.add_event_listener(listener)
+    self.connLock.release()
+  
   def addStatusListener(self, callback):
     """
     Directs further events related to tor's controller status to the callback
@@ -455,7 +471,7 @@
                  myFunction(controller, eventType)
     """
     
-    self.listeners.append(callback)
+    self.statusListeners.append(callback)
   
   def removeStatusListener(self, callback):
     """
@@ -466,8 +482,8 @@
       callback - functor to be removed
     """
     
-    if callback in self.listeners:
-      self.listeners.remove(callback)
+    if callback in self.statusListeners:
+      self.statusListeners.remove(callback)
       return True
     else: return False
   
@@ -647,6 +663,6 @@
       eventType - enum representing tor's new status
     """
     
-    for callback in self.listeners:
+    for callback in self.statusListeners:
       callback(self, eventType)