[tor-commits] [ooni-probe/master] Work on the Director

isis at torproject.org isis at torproject.org
Sun Mar 10 01:57:01 UTC 2013


commit 8ca9928040168b71dbf41ed092c30def4a129e48
Author: Arturo Filastò <art at fuffa.org>
Date:   Sun Jan 13 14:00:00 2013 +0100

    Work on the Director
    
    Provide glue between Director, Tasks and Managers
    Director will keep track of the failure rate of measurements
---
 ooni/director.py |   89 +++++++++++++++++++++++++++++++++++++++++++-----------
 ooni/managers.py |   29 ++++++++++--------
 ooni/reporter.py |   36 ++++++++++++++++++++++
 ooni/tasks.py    |    7 ++++
 4 files changed, 130 insertions(+), 31 deletions(-)

diff --git a/ooni/director.py b/ooni/director.py
index 0707664..beb9c3a 100644
--- a/ooni/director.py
+++ b/ooni/director.py
@@ -1,4 +1,6 @@
-from ooni.managers import ReportingEntryManager, MeasurementManager
+from ooni.managers import ReportEntryManager, MeasurementManager
+from ooni.reporter import Report
+
 from ooni.nettest import NetTest
 
 class Director(object):
@@ -45,29 +47,51 @@ class Director(object):
     """
     _scheduledTests = 0
 
-    def __init__(self):
+    def __init__(self, reporters):
         self.reporters = reporters
 
         self.netTests = []
 
-        self.measurementManager = MeasurementManager(manager=self,
-                netTests=self.netTests)
+        self.measurementManager = MeasurementManager()
         self.measurementManager.director = self
 
-        self.reportEntryManager = ReportingEntryManager()
+        self.reportEntryManager = ReportEntryManager()
         self.reportEntryManager.director = self
 
-    def startTest(self, net_test_file, inputs, options):
-        """
-        Create the Report for the NetTest and start the report NetTest.
+        self.successfulMeasurements = 0
+        self.failedMeasurements = 0
+
+        self.totalMeasurements = 0
+
+        # The cumulative runtime of all the measurements
+        self.totalMeasurementRuntime = 0
+
+        self.failures = []
+
+    @property
+    def measurementSuccessRatio(self):
+        return self.successfulMeasurements / self.totalMeasurements
+
+    @property
+    def measurementFailureRatio(self):
+        return self.failedMeasurements / self.totalMeasurements
+
+    @property
+    def measurementSuccessRate(self):
         """
-        report = Report()
-        report.reportEntryManager = self.reportEntryManager
+        The speed at which tests are succeeding globally.
 
-        net_test = NetTest(net_test_file, inputs, options, report)
-        net_test.director = self
+        This means that fast tests that perform a lot of measurements will
+        impact this value quite heavily.
+        """
+        return self.successfulMeasurements / self.totalMeasurementRuntime
 
-        self.measurementManager.schedule(net_test.generateMeasurements())
+    @property
+    def measurementFailureRate(self):
+        """
+        The speed at which tests are failing globally.
+        """
+        return self.failedMeasurements / self.totalMeasurementRuntime
 
     def measurementTimedOut(self, measurement):
         """
@@ -76,12 +100,41 @@ class Director(object):
         """
         pass
 
+    def measurementStarted(self, measurement):
+        self.totalMeasurements += 1
+
+    def measurementSucceeded(self, measurement):
+        self.totalMeasurementRuntime += measurement.runtime
+
+        self.successfulMeasurements += 1
+
     def measurementFailed(self, failure, measurement):
-        pass
+        self.totalMeasurementRuntime += measurement.runtime
 
-    def writeFailure(self, measurement, failure):
-        pass
+        self.failedMeasurements += 1
+        self.failures.append((failure, measurement))
+
+    def startTest(self, net_test_file, options):
+        """
+        Create the Report for the NetTest and start the report NetTest.
+
+        Args:
+            net_test_file:
+                is either a file path or a file like object that will be used to
+                generate the test_cases.
+
+            options:
+                is a dict containing the options to be passed to the chosen net
+                test.
+        """
+        report = Report(self.reporters)
+        report.reportEntryManager = self.reportEntryManager
+
+        net_test = NetTest(net_test_file, options, report)
+        net_test.measurmentManager = self.measurementManager
 
-    def writeReport(self, report_write_task):
-        self.reportingManager.write(report_write_task)
+        try:
+            net_test.start()
+        except Exception, e:
+            pass
 
diff --git a/ooni/managers.py b/ooni/managers.py
index cee6086..dd748ae 100644
--- a/ooni/managers.py
+++ b/ooni/managers.py
@@ -99,15 +99,22 @@ class TaskManager(object):
         self._fillSlots()
 
     def start(self):
+        """
+        This is called to start the task manager.
+        """
         self.failures = []
 
-        self.tasksDone = defer.Deferred()
         self._fillSlots()
 
+    def started(self, task):
+        """
+        This hook will get called every time a task has been started.
+        """
+        pass
+
     def failed(self, failure, task):
         """
-        This method should be overriden by the subclass and should contains
-        logic for dealing with a failure that is subclass specific.
+        This hoook is called every time a task has failed.
 
         The default failure handling logic is to reschedule the task up until
         we reach the maximum number of retries.
@@ -115,6 +122,9 @@ class TaskManager(object):
         raise NotImplemented
 
     def succeeded(self, result, task):
+        """
+        This hook is called every time a task has been successfully executed.
+        """
         raise NotImplemented
 
 class MeasurementManager(TaskManager):
@@ -136,6 +146,9 @@ class MeasurementManager(TaskManager):
 
     director = None
 
+    def started(self, measurement):
+        self.director.measurementStarted(measurement)
+
     def succeeded(self, result, measurement):
         self.director.measurementSucceeded(measurement)
 
@@ -183,16 +196,6 @@ class ReportEntryManager(object):
 
     director = None
 
-    def __init__(self, manager, netTests=None):
-        self.netTests = netTests if netTests else []
-        self.manager = manager
-
-    def addNetTest(self, netTest):
-        self.netTests.append(netTest)
-
-    def initializeTaskList(self):
-        pass
-
     def succeeded(self, result, measurement):
         pass
 
diff --git a/ooni/reporter.py b/ooni/reporter.py
index 728c3f5..637131c 100644
--- a/ooni/reporter.py
+++ b/ooni/reporter.py
@@ -373,3 +373,39 @@ class OONIBReporter(OReporter):
         self.backend_version = parsed_response['backend_version']
         log.debug("Created report with id %s" % parsed_response['report_id'])
 
+class Report(object):
+    reportEntryManager = None
+
+    def __init__(self, reporters):
+        """
+        This will instantiate all the reporters and add them to the list of
+        available reporters.
+
+        net_test:
+            is a reference to the net_test to which the report object belongs to.
+        """
+        self.reporters = []
+        for r in reporters:
+            reporter = r()
+            self.reporters.append(reporter)
+
+        self.createReports()
+
+    def createReports(self):
+        """
+        This will create all the reports that need to be created.
+        """
+        for reporter in self.reporters:
+            reporter.createReport()
+
+    def write(self, measurement):
+        """
+        This will write to all the reporters, by waiting on the created
+        callback to fire.
+        """
+        for reporter in self.reporters:
+            @reporter.created.addCallback
+            def cb(result):
+                report_write_task = ReportWrite(reporter, measurement)
+                self.reportEntryManager.schedule(report_write_task)
+
diff --git a/ooni/tasks.py b/ooni/tasks.py
index 3230732..981f5e1 100644
--- a/ooni/tasks.py
+++ b/ooni/tasks.py
@@ -1,3 +1,5 @@
+import time
+
 from twisted.internet import defer, reactor
 
 class BaseTask(object):
@@ -6,6 +8,10 @@ class BaseTask(object):
     def __init__(self):
         self.running = False
         self.failures = 0
+
+        self.startTime = time.time()
+        self.runtime = 0
+
         # This is a deferred that gets called when a test has reached it's
         # final status, this means: all retries have been attempted or the test
         # has successfully executed.
@@ -17,6 +23,7 @@ class BaseTask(object):
         return failure
 
     def _succeeded(self, result):
+        self.runtime = time.time() - self.startTime
         self.succeeded(result)
         return result
 





More information about the tor-commits mailing list