[or-cvs] r20016: {arm} Resolved a few quick bugs: fix: added fingerprint lookup cac (arm/trunk/interface)

atagar at seul.org atagar at seul.org
Tue Jul 14 19:17:14 UTC 2009


Author: atagar
Date: 2009-07-14 15:17:14 -0400 (Tue, 14 Jul 2009)
New Revision: 20016

Modified:
   arm/trunk/interface/connPanel.py
   arm/trunk/interface/controller.py
   arm/trunk/interface/hostnameResolver.py
   arm/trunk/interface/util.py
Log:
Resolved a few quick bugs:
fix: added fingerprint lookup cache to resolve substantial performance issue
fix: hostname resolution progress accounts for newly added entries (no more negative progress)
fix: resolved bug that prevented arm from starting if too small
fix: ordering issue when sorting unresolved ip addresses



Modified: arm/trunk/interface/connPanel.py
===================================================================
--- arm/trunk/interface/connPanel.py	2009-07-14 19:11:46 UTC (rev 20015)
+++ arm/trunk/interface/connPanel.py	2009-07-14 19:17:14 UTC (rev 20016)
@@ -65,6 +65,7 @@
     self.sortOrdering = [ORD_TYPE, ORD_FOREIGN_LISTING, ORD_FOREIGN_PORT]
     self.isPaused = False
     self.resolver = hostnameResolver.HostnameResolver()
+    self.fingerprintLookupCache = {}                              # chache of (ip, port) -> fingerprint
     self.fingerprintMappings = _getFingerprintMappings(self.conn) # mappings of ip -> [(port, OR identity), ...]
     
     # gets process id to make sure we get the correct netstat data
@@ -92,9 +93,11 @@
   
   # when consensus changes update fingerprint mappings
   def new_consensus_event(self, n):
+    self.fingerprintLookupCache = {}
     self.fingerprintMappings = _getFingerprintMappings(self.conn)
   
   def new_desc_event(self, d):
+    self.fingerprintLookupCache = {}
     self.fingerprintMappings = _getFingerprintMappings(self.conn)
   
   def reset(self):
@@ -190,7 +193,7 @@
               dst = "%s:%s" % (hostname if hostname else entry[CONN_F_IP], entry[CONN_F_PORT])
               dst = "%-37s" % dst
             else:
-              src = "localhost "
+              src = "localhost  "
               if entry[CONN_TYPE] == "control": dst = "localhost"
               else: dst = self.getFingerprint(entry[CONN_F_IP], entry[CONN_F_PORT])
               dst = "%-41s" % dst
@@ -210,15 +213,21 @@
     returns "UNKNOWN".
     """
     
-    if ipAddr in self.fingerprintMappings.keys():
-      potentialMatches = self.fingerprintMappings[ipAddr]
+    if (ipAddr, port) in self.fingerprintLookupCache:
+      return self.fingerprintLookupCache[(ipAddr, port)]
+    else:
+      match = "UNKNOWN"
       
-      if len(potentialMatches) == 1: return potentialMatches[0][1]
-      else:
-        for (entryPort, entryFingerprint) in potentialMatches:
-          if entryPort == port: return entryFingerprint
-    
-    return "UNKNOWN"
+      if ipAddr in self.fingerprintMappings.keys():
+        potentialMatches = self.fingerprintMappings[ipAddr]
+        
+        if len(potentialMatches) == 1: match = potentialMatches[0][1]
+        else:
+          for (entryPort, entryFingerprint) in potentialMatches:
+            if entryPort == port: match = entryFingerprint
+      
+      self.fingerprintLookupCache[(ipAddr, port)] = match
+      return match
   
   def setPaused(self, isPause):
     """
@@ -272,10 +281,10 @@
       listingWrapper = lambda ip, port: _ipToInt(ip)
     elif self.listingType == LIST_HOSTNAME:
       # alphanumeric hostnames followed by unresolved IP addresses
-      listingWrapper = lambda ip, port: self.resolver.resolve(ip).upper() if self.resolver.resolve(ip) else "ZZZZZ" + ip
+      listingWrapper = lambda ip, port: self.resolver.resolve(ip).upper() if self.resolver.resolve(ip) else "ZZZZZ%099i" % _ipToInt(ip)
     elif self.listingType == LIST_FINGERPRINT:
       # alphanumeric fingerprints followed by UNKNOWN entries
-      listingWrapper = lambda ip, port: self.getFingerprint(ip, port) if self.getFingerprint(ip, port) != "UNKNOWN" else "ZZZZZ" + ip
+      listingWrapper = lambda ip, port: self.getFingerprint(ip, port) if self.getFingerprint(ip, port) != "UNKNOWN" else "ZZZZZ%099i" % _ipToInt(ip)
     
     for entry in self.sortOrdering:
       if entry == ORD_FOREIGN_LISTING:

Modified: arm/trunk/interface/controller.py
===================================================================
--- arm/trunk/interface/controller.py	2009-07-14 19:11:46 UTC (rev 20015)
+++ arm/trunk/interface/controller.py	2009-07-14 19:17:14 UTC (rev 20016)
@@ -44,7 +44,7 @@
     self.msgAttr = curses.A_NORMAL    # formatting attributes
     self.page = 1                     # page number currently being displayed
     self.resolver = resolver          # dns resolution thread
-    self.resolvingBatchSize = 0       # number of entries in batch being resolved
+    self.resolvingCounter = -1         # count of resolver when starting (-1 if we aren't working on a batch)
   
   def setMsg(self, msgText, msgAttr=curses.A_NORMAL):
     """
@@ -65,18 +65,19 @@
       if msgText == CTL_HELP:
         msgAttr = curses.A_NORMAL
         
-        if self.resolvingBatchSize > 0:
+        if self.resolvingCounter != -1:
           if self.resolver.unresolvedQueue.empty() or self.resolver.isPaused:
             # done resolving dns batch
-            self.resolvingBatchSize = 0
+            self.resolvingCounter = -1
             curses.halfdelay(REFRESH_RATE * 10) # revert to normal refresh rate
           else:
-            entryCount = self.resolvingBatchSize - self.resolver.unresolvedQueue.qsize()
-            progress = 100 * entryCount / self.resolvingBatchSize
+            batchSize = self.resolver.totalResolves - self.resolvingCounter
+            entryCount = batchSize - self.resolver.unresolvedQueue.qsize()
+            progress = 100 * entryCount / batchSize
             additive = "(or l) " if self.page == 2 else ""
-            msgText = "Resolving hostnames (%i / %i, %i%%) - press esc %sto cancel" % (entryCount, self.resolvingBatchSize, progress, additive)
+            msgText = "Resolving hostnames (%i / %i, %i%%) - press esc %sto cancel" % (entryCount, batchSize, progress, additive)
         
-        if self.resolvingBatchSize == 0:
+        if self.resolvingCounter == -1:
           msgText = "page %i / %i - q: quit, p: pause, h: page help" % (self.page, PAGE_COUNT)
       elif msgText == CTL_PAUSED:
         msgText = "Paused"
@@ -345,19 +346,19 @@
         for key in PAUSEABLE: panels[key].setPaused(isPaused or key not in PAGES[page])
       finally:
         cursesLock.release()
-    elif (page == 1 and (key == ord('l') or key == ord('L'))) or (key == 27 and panels["conn"].listingType == connPanel.LIST_HOSTNAME and panels["control"].resolvingBatchSize > 0):
+    elif (page == 1 and (key == ord('l') or key == ord('L'))) or (key == 27 and panels["conn"].listingType == connPanel.LIST_HOSTNAME and panels["control"].resolvingCounter != -1):
       # either pressed 'l' on connection listing or canceling hostname resolution (esc on any page)
       panels["conn"].listingType = (panels["conn"].listingType + 1) % 3
       
       if panels["conn"].listingType == connPanel.LIST_HOSTNAME:
         curses.halfdelay(10) # refreshes display every second until done resolving
-        panels["control"].resolvingBatchSize = len(panels["conn"].connections)
+        panels["control"].resolvingCounter = panels["conn"].resolver.totalResolves
         
         resolver = panels["conn"].resolver
         resolver.setPaused(not panels["conn"].allowDNS)
         for connEntry in panels["conn"].connections: resolver.resolve(connEntry[connPanel.CONN_F_IP])
       else:
-        panels["control"].resolvingBatchSize = 0
+        panels["control"].resolvingCounter = -1
         resolver.setPaused(True)
       
       panels["conn"].sortConnections()

Modified: arm/trunk/interface/hostnameResolver.py
===================================================================
--- arm/trunk/interface/hostnameResolver.py	2009-07-14 19:11:46 UTC (rev 20015)
+++ arm/trunk/interface/hostnameResolver.py	2009-07-14 19:17:14 UTC (rev 20016)
@@ -36,6 +36,7 @@
     self.recentQueries = []           # recent resolution requests to prevent duplicate requests
     self.counter = itertools.count()  # atomic counter to track age of entries (for trimming)
     self.threadPool = []              # worker threads that process requests
+    self.totalResolves = 0            # counter for the total number of addresses querried to be resolved
     self.isPaused = True
     
     for i in range(RESOLVER_THREAD_POOL_SIZE):
@@ -58,6 +59,7 @@
     if ipAddr in self.resolvedCache.keys():
       return self.resolvedCache[ipAddr][0]
     elif ipAddr not in self.recentQueries:
+      self.totalResolves += 1
       self.recentQueries.append(ipAddr)
       self.unresolvedQueue.put(ipAddr)
       

Modified: arm/trunk/interface/util.py
===================================================================
--- arm/trunk/interface/util.py	2009-07-14 19:11:46 UTC (rev 20015)
+++ arm/trunk/interface/util.py	2009-07-14 19:17:14 UTC (rev 20016)
@@ -111,7 +111,7 @@
     if self.win and startY > y:
       return False # trying to make panel out of bounds
     
-    newHeight = y - startY
+    newHeight = max(0, y - startY)
     if self.height != -1: newHeight = min(newHeight, self.height)
     
     if self.startY != startY or newHeight > self.maxY or self.isDisplaced or (self.maxX > maxX and maxX != -1):



More information about the tor-commits mailing list