[tor-commits] [ooni-probe/master] Handle errors when writing to the list of Reporters

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


commit 07d5d569bf4a5746da9495edfedc31b42459d01b
Author: Arturo Filastò <art at fuffa.org>
Date:   Wed Jan 16 23:15:18 2013 +0100

    Handle errors when writing to the list of Reporters
    
    We will try to write to a reporter the number of times the ReportManager is
    configured to do so.
    If no more reporters are available an exception will be raised and the test
    will stop running (XXX this needs to be tested properly)
---
 ooni/director.py |   14 +++++++++++---
 ooni/errors.py   |    6 ++++++
 ooni/managers.py |    2 --
 ooni/nettest.py  |   27 ++++++++++++++++++++++-----
 ooni/reporter.py |   15 +++++++++++++++
 5 files changed, 54 insertions(+), 10 deletions(-)

diff --git a/ooni/director.py b/ooni/director.py
index b3dfba3..9a20491 100644
--- a/ooni/director.py
+++ b/ooni/director.py
@@ -139,9 +139,17 @@ class Director(object):
         self.failures.append((failure, measurement))
         return failure
 
-    def reportEntryFailed(self, failure):
-        # XXX add failure handling logic
-        return
+    def reporterFailed(self, failure, net_test):
+        """
+        This gets called every time a reporter is failing and has been removed
+        from the reporters of a NetTest.
+        Once a report has failed to be created that net_test will never use the
+        reporter again.
+
+        XXX hook some logic here.
+        note: failure contains an extra attribute called failure.reporter
+        """
+        pass
 
     def netTestDone(self, result, net_test):
         self.activeNetTests.remove(net_test)
diff --git a/ooni/errors.py b/ooni/errors.py
index 9281c6c..2023dbf 100644
--- a/ooni/errors.py
+++ b/ooni/errors.py
@@ -118,5 +118,11 @@ class DirectorException(Exception):
     pass
 
 class UnableToStartTor(DirectorException):
+    pass
+
 class InvalidOONIBCollectorAddress(Exception):
     pass
+
+class AllReportersFailed(Exception):
+    pass
+
diff --git a/ooni/managers.py b/ooni/managers.py
index 533e6b5..011e3b0 100644
--- a/ooni/managers.py
+++ b/ooni/managers.py
@@ -28,8 +28,6 @@ class TaskManager(object):
         The has failed to complete, we append it to the end of the task chain
         to be re-run once all the currently scheduled tasks have run.
         """
-        print "This task has failed"
-        print failure
         self._active_tasks.remove(task)
         self.failures.append((failure, task))
 
diff --git a/ooni/nettest.py b/ooni/nettest.py
index e2c17f1..4aa013c 100644
--- a/ooni/nettest.py
+++ b/ooni/nettest.py
@@ -9,6 +9,8 @@ from ooni.utils import log, checkForRoot, NotRootError
 from ooni import config
 from ooni import otime
 
+from ooni.errors import AllReportersFailed
+
 from inspect import getmembers
 from StringIO import StringIO
 
@@ -248,16 +250,32 @@ class NetTest(object):
 
         self.state = NetTestState(self.done)
 
-    def doneReport(self, result):
+    def doneReport(self, report_results):
         """
         This will get called every time a measurement is done and therefore a
         measurement is done.
 
         The state for the NetTest is informed of the fact that another task has
         reached the done state.
+
+        Args:
+            report_results:
+                is the list of tuples returned by the self.report.write
+                :class:twisted.internet.defer.DeferredList
+
+        Returns:
+            the same deferred list results
         """
+        for report_status, report_result in report_results:
+            if report_status == False:
+                self.director.reporterFailed(report_result, self)
+
         self.state.taskDone()
-        return result
+
+        if len(self.report.reporters) == 0:
+            raise NoMoreReporters
+
+        return report_results
 
     def makeMeasurement(self, test_class, test_method, test_input=None):
         """
@@ -282,9 +300,8 @@ class NetTest(object):
         measurement.done.addCallback(self.director.measurementSucceeded)
         measurement.done.addErrback(self.director.measurementFailed, measurement)
 
-        measurement.done.addCallback(self.report.write)
-        measurement.done.addErrback(self.director.reportEntryFailed)
-
+        measurement.done.addBoth(self.report.write)
+        # here we are dealing with a deferred list
         measurement.done.addBoth(self.doneReport)
         return measurement
 
diff --git a/ooni/reporter.py b/ooni/reporter.py
index 237bae7..bfd2330 100644
--- a/ooni/reporter.py
+++ b/ooni/reporter.py
@@ -380,6 +380,19 @@ class Report(object):
         for reporter in self.reporters:
             d = defer.maybeDeferred(reporter.createReport)
             d.addCallback(reporter.created.callback)
+            d.addErrback(reporter.created.callback)
+
+    def failedOpeningReport(self, failure, reporter):
+        """
+        This errback get's called every time we fail to create a report.
+        By fail we mean that the number of retries has exceeded.
+        Once a report has failed to be created with a reporter we give up and
+        remove the reporter from the list of reporters to write to.
+        """
+        log.err("Failed to open %s reporter, giving up..." % reporter)
+        self.reporters.remove(reporter)
+        failure.reporter = reporter
+        return failure
 
     def write(self, measurement):
         """
@@ -406,6 +419,8 @@ class Report(object):
                 return report_write_task.done
 
             d = reporter.created.addBoth(writeReportEntry)
+            # Give up on writing to the reporter if the task fails X times
+            d.addErrback(self.failedOpeningReport, reporter)
             l.append(d)
 
         dl = defer.DeferredList(l)





More information about the tor-commits mailing list