diff options
| author | Steven Knight <knight@baldmt.com> | 2002-04-09 13:49:11 (GMT) |
|---|---|---|
| committer | Steven Knight <knight@baldmt.com> | 2002-04-09 13:49:11 (GMT) |
| commit | 72b58192cc6bea9962cff01f2d72e8de77591bda (patch) | |
| tree | 584a5efd3d6ca331f6b3cf93d17f49055ca890df /src/engine/SCons/Sig | |
| parent | 3ccdd2cb4b633d5d3603d1af53c2e578f1af8f1d (diff) | |
| download | SCons-72b58192cc6bea9962cff01f2d72e8de77591bda.zip SCons-72b58192cc6bea9962cff01f2d72e8de77591bda.tar.gz SCons-72b58192cc6bea9962cff01f2d72e8de77591bda.tar.bz2 | |
Implement content signature caching and --max-drift (Anthony Roach)
Diffstat (limited to 'src/engine/SCons/Sig')
| -rw-r--r-- | src/engine/SCons/Sig/SigTests.py | 42 | ||||
| -rw-r--r-- | src/engine/SCons/Sig/__init__.py | 62 |
2 files changed, 85 insertions, 19 deletions
diff --git a/src/engine/SCons/Sig/SigTests.py b/src/engine/SCons/Sig/SigTests.py index 90488e1..2a2560f 100644 --- a/src/engine/SCons/Sig/SigTests.py +++ b/src/engine/SCons/Sig/SigTests.py @@ -99,15 +99,21 @@ class DummyNode: def get_bsig(self): return self.bsig + def store_bsig(self): + pass + def set_csig(self, csig): self.csig = csig def get_csig(self): return self.csig + def store_csig(self): + pass + def get_prevsiginfo(self): return (self.oldtime, self.oldbsig, self.oldcsig) - + def builder_sig_adapter(self): class Adapter: def get_contents(self): @@ -160,7 +166,11 @@ def write(calc, nodes): node.oldtime = node.file.timestamp node.oldbsig = calc.bsig(node) node.oldcsig = calc.csig(node) - + +def clear(nodes): + for node in nodes: + node.csig = None + node.bsig = None class SigTestBase: @@ -173,6 +183,7 @@ class SigTestBase: self.test_initial() self.test_built() self.test_modify() + self.test_modify_same_time() self.test_delete() self.test_cache() @@ -217,6 +228,8 @@ class SigTestBase: self.files[6].modify('blah blah blah', 333) self.files[8].modify('blah blah blah', 333) + clear(nodes) + self.failUnless(not current(calc, nodes[0]), "modified directly") self.failUnless(not current(calc, nodes[1]), "direct source modified") self.failUnless(current(calc, nodes[2])) @@ -229,6 +242,27 @@ class SigTestBase: self.failUnless(not current(calc, nodes[9]), "direct source modified") self.failUnless(not current(calc, nodes[10]), "indirect source modified") + + def test_modify_same_time(self): + + nodes = create_nodes(self.files) + + calc = SCons.Sig.Calculator(self.module, 0) + + write(calc, nodes) + + #simulate a modification of some files without changing the timestamp: + self.files[0].modify('blah blah blah blah', 333) + self.files[3].modify('blah blah blah blah', 333) + self.files[6].modify('blah blah blah blah', 333) + self.files[8].modify('blah blah blah blah', 333) + + clear(nodes) + + for node in nodes: + self.failUnless(current(calc, node), + "all of the nodes should be current") + def test_delete(self): nodes = create_nodes(self.files) @@ -306,6 +340,10 @@ class CalcTestCase(unittest.TestCase): return 1 def get_bsig(self): return self.bsig + def set_bsig(self, bsig): + self.bsig = bsig + def store_sigs(self): + pass def get_csig(self): return self.csig def get_prevsiginfo(self): diff --git a/src/engine/SCons/Sig/__init__.py b/src/engine/SCons/Sig/__init__.py index cb03630..d077114 100644 --- a/src/engine/SCons/Sig/__init__.py +++ b/src/engine/SCons/Sig/__init__.py @@ -33,6 +33,7 @@ import os import os.path import string import SCons.Node +import time #XXX Get rid of the global array so this becomes re-entrant. sig_files = [] @@ -52,13 +53,13 @@ class SConsignFile: dir - the directory for the file module - the signature module being used """ - + self.dir = dir self.module = module self.sconsign = os.path.join(dir.path, '.sconsign') self.entries = {} self.dirty = None - + try: file = open(self.sconsign, 'rt') except: @@ -78,7 +79,7 @@ class SConsignFile: filename - the filename whose signature will be returned returns - (timestamp, bsig, csig) """ - + try: arr = map(string.strip, string.split(self.entries[filename], " ")) except KeyError: @@ -162,13 +163,17 @@ class Calculator: for the build engine. """ - def __init__(self, module): + def __init__(self, module, max_drift=2*24*60*60): """ Initialize the calculator. module - the signature module to use for signature calculations + max_drift - the maximum system clock drift used to determine when to + cache content signatures. A negative value means to never cache + content signatures. (defaults to 2 days) """ self.module = module + self.max_drift = max_drift def bsig(self, node): """ @@ -185,21 +190,23 @@ class Calculator: """ if not node.use_signature: return None - #XXX If configured, use the content signatures from the - #XXX .sconsign file if the timestamps match. bsig = node.get_bsig() if not bsig is None: return bsig - sigs = [] - for child in node.children(): - sigs.append(self.get_signature(child)) + sigs = map(self.get_signature, node.children()) if node.builder: sigs.append(self.module.signature(node.builder_sig_adapter())) + bsig = self.module.collect(filter(lambda x: not x is None, sigs)) + + node.set_bsig(bsig) + + # don't store the bsig here, because it isn't accurate until + # the node is actually built. + + return bsig - return self.module.collect(filter(lambda x: not x is None, sigs)) - def csig(self, node): """ Generate a node's content signature, the digested signature @@ -210,14 +217,35 @@ class Calculator: """ if not node.use_signature: return None - #XXX If configured, use the content signatures from the - #XXX .sconsign file if the timestamps match. + csig = node.get_csig() if not csig is None: return csig - - return self.module.signature(node) - + + if self.max_drift >= 0: + info = node.get_prevsiginfo() + else: + info = None + + mtime = node.get_timestamp() + + if (info and info[0] and info[2] and info[0] == mtime): + # use the signature stored in the .sconsign file + csig = info[2] + # Set the csig here so it doesn't get recalculated unnecessarily + # and so it's set when the .sconsign file gets written + node.set_csig(csig) + else: + csig = self.module.signature(node) + # Set the csig here so it doesn't get recalculated unnecessarily + # and so it's set when the .sconsign file gets written + node.set_csig(csig) + + if self.max_drift >= 0 and (time.time() - mtime) > self.max_drift: + node.store_csig() + + return csig + def get_signature(self, node): """ Get the appropriate signature for a node. @@ -264,5 +292,5 @@ class Calculator: if not node.builder and node.get_timestamp() == oldtime: return 1 - + return self.module.current(newsig, oldbsig) |
