commit 6417ffe9681138ac1fb9dbccd897df61ef358ae1 Author: Isis Lovecruft isis@torproject.org Date: Sun May 10 23:59:42 2015 +0000
Move Main.updateBridgeHistory() → Stability.updateBridgeHistory().
Conflicts: lib/bridgedb/Main.py --- lib/bridgedb/Main.py | 42 ++-------------------------------------- lib/bridgedb/Stability.py | 40 ++++++++++++++++++++++++++++++++++++++ lib/bridgedb/test/test_Main.py | 28 ++++++++++++++------------- 3 files changed, 57 insertions(+), 53 deletions(-)
diff --git a/lib/bridgedb/Main.py b/lib/bridgedb/Main.py index 88b386b..4a00799 100644 --- a/lib/bridgedb/Main.py +++ b/lib/bridgedb/Main.py @@ -40,51 +40,13 @@ from bridgedb.configure import Conf from bridgedb.parse import descriptors from bridgedb.parse import options from bridgedb.parse.addr import isIPAddress -from bridgedb.schedule import toUnixSeconds
import bridgedb.Storage
from bridgedb import Bridges from bridgedb import Dist -from bridgedb.Stability import addOrUpdateBridgeHistory - - -def updateBridgeHistory(bridges, timestamps): - """Process all the timestamps and update the bridge stability statistics in - the database. - - .. warning: This function is extremely expensive, and will keep getting - more and more expensive, on a linearithmic scale, every time it is - called. Blame the :mod:`bridgedb.Stability` module. - - :param dict bridges: All bridges from the descriptors, parsed into - :class:`bridgedb.bridges.Bridge`s. - :param dict timestamps: A dictionary whose keys are bridge fingerprints, - and whose values are lists of integers, each integer being a timestamp - (in seconds since Unix Epoch) for when a descriptor for that bridge - was published. - :rtype: dict - :returns: The original **timestamps**, but which each list of integers - (re)sorted. - """ - logging.debug("Beginning bridge stability calculations") - sortedTimestamps = {} - - for fingerprint, stamps in timestamps.items()[:]: - stamps.sort() - bridge = bridges[fingerprint] - for timestamp in stamps: - logging.debug( - ("Adding/updating timestamps in BridgeHistory for %s in " - "database: %s") % (fingerprint, timestamp)) - timestamp = toUnixSeconds(timestamp.timetuple()) - addOrUpdateBridgeHistory(bridge, timestamp) - # Replace the timestamps so the next sort is (hopefully) less - # expensive: - sortedTimestamps[fingerprint] = stamps - - logging.debug("Stability calculations complete") - return sortedTimestamps +from bridgedb.Stability import updateBridgeHistory +
def load(state, splitter, clear=False): """Read and parse all descriptors, and load into a bridge splitter. diff --git a/lib/bridgedb/Stability.py b/lib/bridgedb/Stability.py index ad6fd0c..fbc8e88 100644 --- a/lib/bridgedb/Stability.py +++ b/lib/bridgedb/Stability.py @@ -28,6 +28,9 @@ Bridge stability metrics are calculated using the model introduced in import logging import bridgedb.Storage
+from bridgedb.schedule import toUnixSeconds + + # tunables weighting_factor = float(19)/float(20) discountIntervalMillis = long(60*60*12*1000) @@ -253,3 +256,40 @@ def updateWeightedTime(statusPublicationMillis):
for bh in bhToUpdate: db.updateIntoBridgeHistory(bh) + +def updateBridgeHistory(bridges, timestamps): + """Process all the timestamps and update the bridge stability statistics in + the database. + + .. warning: This function is extremely expensive, and will keep getting + more and more expensive, on a linearithmic scale, every time it is + called. Blame the :mod:`bridgedb.Stability` module. + + :param dict bridges: All bridges from the descriptors, parsed into + :class:`bridgedb.bridges.Bridge`s. + :param dict timestamps: A dictionary whose keys are bridge fingerprints, + and whose values are lists of integers, each integer being a timestamp + (in seconds since Unix Epoch) for when a descriptor for that bridge + was published. + :rtype: dict + :returns: The original **timestamps**, but which each list of integers + (re)sorted. + """ + logging.debug("Beginning bridge stability calculations") + sortedTimestamps = {} + + for fingerprint, stamps in timestamps.items()[:]: + stamps.sort() + bridge = bridges[fingerprint] + for timestamp in stamps: + logging.debug( + ("Adding/updating timestamps in BridgeHistory for %s in " + "database: %s") % (fingerprint, timestamp)) + timestamp = toUnixSeconds(timestamp.timetuple()) + addOrUpdateBridgeHistory(bridge, timestamp) + # Replace the timestamps so the next sort is (hopefully) less + # expensive: + sortedTimestamps[fingerprint] = stamps + + logging.debug("Stability calculations complete") + return sortedTimestamps diff --git a/lib/bridgedb/test/test_Main.py b/lib/bridgedb/test/test_Main.py index 0b14319..5ae4025 100644 --- a/lib/bridgedb/test/test_Main.py +++ b/lib/bridgedb/test/test_Main.py @@ -48,13 +48,15 @@ w Bandwidth=2094050 p reject 1-65535 '''
-def mockAddOrUpdateBridgeHistory(bridge, timestamp): - """A mocked version of :func:`bridgedb.Stability.addOrUpdateBridgeHistory` +def mockUpdateBridgeHistory(bridges, timestamps): + """A mocked version of :func:`bridgedb.Stability.updateBridgeHistory` which doesn't access the database (so that we can test functions which - call it, like :func:`bridgedb.Main.updateBridgeHistory`). + call it, like :func:`bridgedb.Main.load`). """ - print("Pretending to update Bridge %s with timestamp %s..." % - (bridge.fingerprint, timestamp)) + for fingerprint, stamps in timestamps.items()[:]: + for timestamp in stamps: + print("Pretending to update Bridge %s with timestamp %s..." % + (fingerprint, timestamp))
class MockBridgeHolder(BridgeHolder): @@ -170,23 +172,23 @@ class MainTests(unittest.TestCase):
# Functions which some tests mock, which we'll need to re-replace # later in tearDown(): - self._orig_addOrUpdateBridgeHistory = Main.addOrUpdateBridgeHistory + self._orig_updateBridgeHistory = Main.updateBridgeHistory self._orig_sys_argv = sys.argv
def tearDown(self): - """Replace the mocked mockAddOrUpdateBridgeHistory() function with the - real function, Stability.addOrUpdateBridgeHistory(). + """Replace the mocked mockUpdateBridgeHistory() function with the + real function, Stability.updateBridgeHistory(). """ - Main.addOrUpdateBridgeHistory = self._orig_addOrUpdateBridgeHistory + Main.updateBridgeHistory = self._orig_updateBridgeHistory sys.argv = self._orig_sys_argv
def test_Main_updateBridgeHistory(self): """Main.updateBridgeHistory should update some timestamps for some bridges. """ - # Mock the addOrUpdateBridgeHistory() function so that we don't try to + # Mock the updateBridgeHistory() function so that we don't try to # access the database: - Main.addOrUpdateBridgeHistory = mockAddOrUpdateBridgeHistory + Main.updateBridgeHistory = mockUpdateBridgeHistory
# Get the bridges into the mocked splitter d = deferToThread(Main.load, self.state, self.splitter) @@ -222,12 +224,12 @@ class MainTests(unittest.TestCase): """ # Mock the addOrUpdateBridgeHistory() function so that we don't try to # access the database: - Main.addOrUpdateBridgeHistory = mockAddOrUpdateBridgeHistory + Main.updateBridgeHistory = mockUpdateBridgeHistory state = self.state state.COLLECT_TIMESTAMPS = True
# The reactor is deferring this to a thread, so the test execution - # here isn't actually covering the Main.updateBridgeHistory() + # here isn't actually covering the Storage.updateBridgeHistory() # function: Main.load(state, self.splitter)