[tor-commits] [arm/master] Revising header panel's method of fetching attributes

atagar at torproject.org atagar at torproject.org
Sun Mar 16 17:38:42 UTC 2014


commit 02ca417cf0d2fab7c8f49bbfdb9cc0d41e8eb1d4
Author: Damian Johnson <atagar at torproject.org>
Date:   Sat Mar 8 15:04:01 2014 -0800

    Revising header panel's method of fetching attributes
    
    Rearranging and minor tweaks to the header panel's method for polling
    information.
---
 arm/connections/circ_entry.py |    2 +-
 arm/header_panel.py           |  163 +++++++++++++++++------------------------
 2 files changed, 68 insertions(+), 97 deletions(-)

diff --git a/arm/connections/circ_entry.py b/arm/connections/circ_entry.py
index 4aa3fc8..7f9c47b 100644
--- a/arm/connections/circ_entry.py
+++ b/arm/connections/circ_entry.py
@@ -109,7 +109,7 @@ class CircHeaderLine(conn_entry.ConnectionLine):
     shown completely (not enough room) is dropped.
     """
 
-    etc_attr = ["Purpose: %s" % self.purpose, "Circuit ID: %i" % self.circuit_id]
+    etc_attr = ["Purpose: %s" % self.purpose, "Circuit ID: %s" % self.circuit_id]
 
     for i in range(len(etc_attr), -1, -1):
       etc_label = ", ".join(etc_attr[:i])
diff --git a/arm/header_panel.py b/arm/header_panel.py
index 2affaad..dcdbeda 100644
--- a/arm/header_panel.py
+++ b/arm/header_panel.py
@@ -22,7 +22,7 @@ import threading
 import arm.util.tracker
 
 from stem import Signal
-from stem.control import State
+from stem.control import Listener, State
 from stem.util import conf, log, proc, str_tools, system
 
 import arm.starter
@@ -98,7 +98,9 @@ class HeaderPanel(panel.Panel, threading.Thread):
 
     self.vals = {}
     self.vals_lock = threading.RLock()
-    self._update()
+
+    with self.vals_lock:
+      self.vals = self._get_attributes()
 
     # listens for tor reload (sighup) events
 
@@ -470,7 +472,8 @@ class HeaderPanel(panel.Panel, threading.Thread):
           is_changed = self._last_resource_fetch != resource_tracker.run_counter()
 
         if is_changed or current_time - self._last_update >= 20:
-          self._update()
+          with self.vals_lock:
+            self.vals = self._get_attributes()
 
         self.redraw(True)
         last_draw += 1
@@ -494,7 +497,9 @@ class HeaderPanel(panel.Panel, threading.Thread):
       initial_height = self.get_height()
       self._is_tor_connected = True
       self._halt_time = None
-      self._update()
+
+      with self.vals_lock:
+        self.vals = self._get_attributes()
 
       if self.get_height() != initial_height:
         # We're toggling between being a relay and client, causing the height
@@ -508,57 +513,24 @@ class HeaderPanel(panel.Panel, threading.Thread):
     elif event_type == State.CLOSED:
       self._is_tor_connected = False
       self._halt_time = time.time()
-      self._update()
-      self.redraw(True)
-
-  def _update(self):
-    """
-    Updates stats in the vals mapping. By default this just revises volatile
-    attributes.
-    """
 
-    self.vals_lock.acquire()
-    controller = tor_controller()
+      with self.vals_lock:
+        self.vals = self._get_attributes()
 
-    # version is truncated to first part, for instance:
-    # 0.2.2.13-alpha (git-feb8c1b5f67f2c6f) -> 0.2.2.13-alpha
-
-    self.vals['tor/version'] = str(controller.get_version('Unknown')).split()[0]
-    self.vals['tor/versionStatus'] = controller.get_info('status/version/current', 'Unknown')
-    self.vals['tor/nickname'] = controller.get_conf('Nickname', '')
-    self.vals['tor/or_port'] = controller.get_conf('ORPort', '0')
-    self.vals['tor/dir_port'] = controller.get_conf('DirPort', '0')
-    self.vals['tor/control_port'] = controller.get_conf('ControlPort', '0')
-    self.vals['tor/socketPath'] = controller.get_conf('ControlSocket', '')
-    self.vals['tor/isAuthPassword'] = controller.get_conf('HashedControlPassword', None) is not None
-    self.vals['tor/isAuthCookie'] = controller.get_conf('CookieAuthentication', None) == '1'
-
-    # orport is reported as zero if unset
-
-    if self.vals['tor/or_port'] == '0':
-      self.vals['tor/or_port'] = ''
-
-    # overwrite address if ORListenAddress is set (and possibly or_port too)
-
-    self.vals['tor/orListenAddr'] = ''
-    listen_addr = controller.get_conf('ORListenAddress', None)
-
-    if listen_addr:
-      if ':' in listen_addr:
-        # both ip and port overwritten
-        self.vals['tor/orListenAddr'] = listen_addr[:listen_addr.find(':')]
-        self.vals['tor/or_port'] = listen_addr[listen_addr.find(':') + 1:]
-      else:
-        self.vals['tor/orListenAddr'] = listen_addr
+      self.redraw(True)
 
-    # fetch exit policy (might span over multiple lines)
+  def _get_attributes(self):
+    controller = tor_controller()
 
-    policy_entries = []
+    or_listeners = controller.get_listeners(Listener.OR, [])
 
-    for exit_policy in controller.get_conf('ExitPolicy', [], True):
-      policy_entries += [policy.strip() for policy in exit_policy.split(',')]
+    if not or_listeners:
+      or_address, or_port = '', ''
+    else:
+      # TODO: Relays can bind to multiple ports to listen for OR connections.
+      # Not sure how we'd like to surface that...
 
-    self.vals['tor/exit_policy'] = ', '.join(policy_entries)
+      or_address, or_port = or_listeners[0]
 
     # file descriptor limit for the process, if this can't be determined
     # then the limit is None
@@ -566,66 +538,40 @@ class HeaderPanel(panel.Panel, threading.Thread):
     fd_limit = controller.get_info('process/descriptor-limit', '-1')
 
     if fd_limit != '-1' and fd_limit.isdigit():
-      self.vals['tor/fd_limit'] = int(fd_limit)
+      fd_limit = int(fd_limit)
     else:
-      self.vals['tor/fd_limit'] = None
-
-    # system information
+      fd_limit = None
 
     uname_vals = os.uname()
-    self.vals['sys/hostname'] = uname_vals[1]
-    self.vals['sys/os'] = uname_vals[0]
-    self.vals['sys/version'] = uname_vals[2]
-
-    self.vals['tor/pid'] = controller.get_pid('')
 
     try:
       start_time = system.get_start_time(controller.get_pid())
     except:
       start_time = None
 
-    self.vals['tor/start_time'] = start_time if start_time else ''
-
-    # reverts volatile parameters to defaults
-
-    self.vals['tor/fingerprint'] = 'Unknown'
-    self.vals['tor/flags'] = []
-    self.vals['tor/fd_used'] = 0
-    self.vals['stat/%torCpu'] = '0'
-    self.vals['stat/%armCpu'] = '0'
-    self.vals['stat/rss'] = '0'
-    self.vals['stat/%mem'] = '0'
-
-    # sets volatile parameters
-    # TODO: This can change, being reported by STATUS_SERVER -> EXTERNAL_ADDRESS
-    # events. Introduce caching via tor_tools?
-
-    self.vals['tor/address'] = controller.get_info('address', '')
-
-    self.vals['tor/fingerprint'] = controller.get_info('fingerprint', self.vals['tor/fingerprint'])
-
+    flags = []
     my_fingerprint = controller.get_info('fingerprint', None)
 
     if my_fingerprint:
       my_status_entry = controller.get_network_status(my_fingerprint)
 
       if my_status_entry:
-        self.vals['tor/flags'] = my_status_entry.flags
+        flags = my_status_entry.flags
 
     # Updates file descriptor usage and logs if the usage is high. If we don't
     # have a known limit or it's obviously faulty (being lower than our
     # current usage) then omit file descriptor functionality.
 
-    if self.vals['tor/fd_limit']:
+    fd_used = 0
+
+    if fd_limit:
       fd_used = get_file_descriptor_usage(controller.get_pid(None))
 
-      if fd_used and fd_used <= self.vals['tor/fd_limit']:
-        self.vals['tor/fd_used'] = fd_used
-      else:
-        self.vals['tor/fd_used'] = 0
+      if not fd_used or fd_used > fd_limit:
+        fd_used = 0
 
-    if self.vals['tor/fd_used'] and self.vals['tor/fd_limit']:
-      fd_percent = 100 * self.vals['tor/fd_used'] / self.vals['tor/fd_limit']
+    if fd_used and fd_limit:
+      fd_percent = 100 * fd_used / fd_limit
       msg = "Tor's file descriptor usage is at %i%%." % fd_percent
 
       if fd_percent >= 90 and not self._is_fd_ninety_percent_warned:
@@ -636,16 +582,14 @@ class HeaderPanel(panel.Panel, threading.Thread):
         self._is_fd_sixty_percent_warned = True
         log.notice(msg)
 
-    # ps or proc derived resource usage stats
+    resource_tracker = arm.util.tracker.get_resource_tracker()
 
-    if self.vals['tor/pid']:
-      resource_tracker = arm.util.tracker.get_resource_tracker()
+    resources = resource_tracker.get_resource_usage()
+    self._last_resource_fetch = resource_tracker.run_counter()
 
-      resources = resource_tracker.get_resource_usage()
-      self._last_resource_fetch = resource_tracker.run_counter()
-      self.vals['stat/%torCpu'] = '%0.1f' % (100 * resources.cpu_sample)
-      self.vals['stat/rss'] = str(resources.memory_bytes)
-      self.vals['stat/%mem'] = '%0.1f' % (100 * resources.memory_percent)
+    tor_cpu = '%0.1f' % (100 * resources.cpu_sample)
+    tor_rss = str(resources.memory_bytes)
+    tor_memory = '%0.1f' % (100 * resources.memory_percent)
 
     # determines the cpu time for the arm process (including user and system
     # time of both the primary and child processes)
@@ -655,11 +599,38 @@ class HeaderPanel(panel.Panel, threading.Thread):
     arm_time_delta = current_time - self._arm_cpu_sampling[1]
     python_cpu_time = arm_cpu_telta / arm_time_delta
     sys_call_cpu_time = 0.0  # TODO: add a wrapper around call() to get this
-    self.vals['stat/%armCpu'] = '%0.1f' % (100 * (python_cpu_time + sys_call_cpu_time))
+    arm_cpu = '%0.1f' % (100 * (python_cpu_time + sys_call_cpu_time))
     self._arm_cpu_sampling = (total_arm_cpu_time, current_time)
 
     self._last_update = current_time
-    self.vals_lock.release()
+
+    return {
+      'tor/address': controller.get_info('address', ''),
+      'tor/fingerprint': controller.get_info('fingerprint', 'Unknown'),
+      'tor/version': str(controller.get_version('Unknown')).split()[0],
+      'tor/versionStatus': controller.get_info('status/version/current', 'Unknown'),
+      'tor/nickname': controller.get_conf('Nickname', ''),
+      'tor/orListenAddr': or_address,
+      'tor/or_port': or_port,
+      'tor/exit_policy': str(controller.get_exit_policy),
+      'tor/flags': flags,
+      'tor/dir_port': controller.get_conf('DirPort', '0'),
+      'tor/control_port': controller.get_conf('ControlPort', '0'),
+      'tor/socketPath': controller.get_conf('ControlSocket', ''),
+      'tor/isAuthPassword': controller.get_conf('HashedControlPassword', None) is not None,
+      'tor/isAuthCookie': controller.get_conf('CookieAuthentication', None) == '1',
+      'tor/fd_limit': fd_limit,
+      'tor/fd_used': fd_used,
+      'tor/pid': controller.get_pid(''),
+      'tor/start_time': start_time if start_time else '',
+      'stat/%torCpu': tor_cpu,
+      'stat/%armCpu': arm_cpu,
+      'stat/rss': tor_rss,
+      'stat/%mem': tor_memory,
+      'sys/hostname': uname_vals[1],
+      'sys/os': uname_vals[0],
+      'sys/version': uname_vals[2],
+    }
 
 
 def get_file_descriptor_usage(pid):





More information about the tor-commits mailing list