[tor-commits] [stem/master] Expanding attributes for read/write-history

atagar at torproject.org atagar at torproject.org
Sun Apr 15 02:50:21 UTC 2012


commit 62f34c67bcaaa7205b09cc7cf6201d78447c0a39
Author: Damian Johnson <atagar at torproject.org>
Date:   Sat Apr 14 15:51:16 2012 -0700

    Expanding attributes for read/write-history
    
    Parsing and validating read-history and write-history attributes. These are
    depricated fields, but still found on archived and extra-info descriptors. This
    includes a unit test to exercise the additions.
---
 stem/descriptor/server_descriptor.py      |   64 +++++++++++++++++++++++++---
 test/unit/descriptor/server_descriptor.py |   27 ++++++++++++
 2 files changed, 84 insertions(+), 7 deletions(-)

diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index 9b74e2b..6892381 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -202,10 +202,18 @@ class ServerDescriptorV3(stem.descriptor.Descriptor):
     average_bandwidth (int)  - rate of traffic relay is willing to relay in bytes/s (*)
     burst_bandwidth (int)    - rate of traffic relay is willing to burst to in bytes/s (*)
     observed_bandwidth (int) - estimated capacity of the relay based on usage in bytes/s (*)
-    read_history (str)       - (deprecated) always unset
-    write_history (str)      - (deprecated) always unset
     eventdns (bool)          - (deprecated) always unset (*)
     
+    read_history (str)       - (deprecated) read-history line, always unset
+    read_history_end (datetime.datetime) - (deprecated) end of the sampling interval
+    read_history_interval (int) - (deprecated) seconds per interval
+    read_history_values (list) - (deprecated) bytes read during each interval (*)
+    
+    write_history (str)      - (deprecated) write-history line, always unset
+    write_history_end (datetime.datetime) - (deprecated) end of the sampling interval
+    write_history_interval (int) - (deprecated) seconds per interval
+    write_history_values (list) - (deprecated) bytes written during each interval (*)
+    
     (*) required fields, others are left as None if undefined
   """
   
@@ -254,9 +262,18 @@ class ServerDescriptorV3(stem.descriptor.Descriptor):
     self.average_bandwidth = None
     self.burst_bandwidth = None
     self.observed_bandwidth = None
+    self.eventdns = True
+    
     self.read_history = None
+    self.read_history_end = None
+    self.read_history_interval = None
+    self.read_history_values = []
+    
     self.write_history = None
-    self.eventdns = True
+    self.write_history_end = None
+    self.write_history_interval = None
+    self.write_history_values = []
+    
     self._unrecognized_lines = []
     
     self._annotation_lines = annotations if annotations else []
@@ -474,12 +491,45 @@ class ServerDescriptorV3(stem.descriptor.Descriptor):
           raise ValueError("Protocols line did not match the expected pattern: %s" % line)
       elif keyword == "family":
         self.family = value.split(" ")
-      elif keyword == "read-history":
-        self.read_history = value
-      elif keyword == "write-history":
-        self.write_history = value
       elif keyword == "eventdns":
         self.eventdns = value == "1"
+      elif keyword in ("read-history", "write-history"):
+        is_read = keyword == "read-history"
+        
+        if is_read: self.read_history = value
+        else: self.write_history = value
+        
+        value_match = re.match("^(.*) \(([0-9]+) s\) (.*)$", value)
+        
+        if not value_match:
+          if not validate: continue
+          raise ValueError("Malformed %s line: %s" % (keyword, line))
+        
+        end_value, interval_value, history_values = value_match.groups()
+        
+        try:
+          end_datetime = datetime.datetime.strptime(end_value, "%Y-%m-%d %H:%M:%S")
+          
+          if is_read: self.read_history_end = end_datetime
+          else: self.write_history_end = end_datetime
+        except ValueError:
+          if validate:
+            raise ValueError("%s line's time wasn't parseable: %s" % (keyword, line))
+        
+        if interval_value.isdigit():
+          if is_read: self.read_history_interval = int(interval_value)
+          else: self.write_history_interval = int(interval_value)
+        elif validate:
+          raise ValueError("%s line's interval wasn't a number: %s" % (keyword, line))
+        
+        for sampling in history_values.split(","):
+          if sampling.isdigit():
+            if is_read: self.read_history_values.append(int(sampling))
+            else: self.write_history_values.append(int(sampling))
+          else:
+            if validate:
+              raise ValueError("%s line has non-numeric values: %s" % (keyword, line))
+            else: break
       else:
         self._unrecognized_lines.append(line)
   
diff --git a/test/unit/descriptor/server_descriptor.py b/test/unit/descriptor/server_descriptor.py
index 89a28c6..5c4cfce 100644
--- a/test/unit/descriptor/server_descriptor.py
+++ b/test/unit/descriptor/server_descriptor.py
@@ -222,6 +222,33 @@ class TestServerDescriptor(unittest.TestCase):
     desc_text = _make_descriptor({"published": "2012-01-01"})
     self._expect_invalid_attr(desc_text, "published")
   
+  def test_read_and_write_history(self):
+    """
+    Parses a read-history and write-history entry. This is now a depricated
+    field for relay server descriptors but is still found in archives and
+    extra-info descriptors.
+    """
+    
+    for field in ("read-history", "write-history"):
+      value = "2005-12-16 18:00:48 (900 s) 81,8848,8927,8927,83,8848"
+      desc_text = _make_descriptor({"opt %s" % field: value})
+      desc = RelayDescriptorV3(desc_text)
+      
+      if field == "read-history":
+        attr = (desc.read_history, desc.read_history_end,
+          desc.read_history_interval, desc.read_history_values)
+      else:
+        attr = (desc.write_history, desc.write_history_end,
+          desc.write_history_interval, desc.write_history_values)
+      
+      expected_end = datetime.datetime(2005, 12, 16, 18, 0, 48)
+      expected_values = [81, 8848, 8927, 8927, 83, 8848]
+      
+      self.assertEquals(value, attr[0])
+      self.assertEquals(expected_end, attr[1])
+      self.assertEquals(900, attr[2])
+      self.assertEquals(expected_values, attr[3])
+  
   def test_annotations(self):
     """
     Checks that content before a descriptor are parsed as annotations.





More information about the tor-commits mailing list