commit 8ca9928040168b71dbf41ed092c30def4a129e48 Author: Arturo Filastò art@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
tor-commits@lists.torproject.org