~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/hashcache.py

  • Committer: Martin Pool
  • Date: 2005-07-08 06:54:58 UTC
  • Revision ID: mbp@sourcefrog.net-20050708065458-2af06c3659faf1d8
- use new path-based hashcache for WorkingTree- squash mtime/ctime to whole seconds- update and if necessary write out hashcache when WorkingTree object is   created.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
 
30
30
 
31
 
CACHE_HEADER = "### bzr statcache v5\n"
 
31
CACHE_HEADER = "### bzr hashcache v5\n"
32
32
 
33
33
 
34
34
def _fingerprint(abspath):
43
43
    if stat.S_ISDIR(fs.st_mode):
44
44
        return None
45
45
 
46
 
    return (fs.st_size, fs.st_mtime,
47
 
            fs.st_ctime, fs.st_ino, fs.st_dev)
 
46
    # we discard any high precision because it's not reliable; perhaps we
 
47
    # could do better on some systems?
 
48
    return (fs.st_size, long(fs.st_mtime),
 
49
            long(fs.st_ctime), fs.st_ino, fs.st_dev)
48
50
 
49
51
 
50
52
class HashCache(object):
81
83
    miss_count
82
84
        number of misses (times files have been completely re-read)
83
85
    """
 
86
    needs_write = False
 
87
 
84
88
    def __init__(self, basedir):
85
89
        self.basedir = basedir
86
90
        self.hit_count = 0
87
91
        self.miss_count = 0
88
92
        self.stat_count = 0
89
93
        self.danger_count = 0
90
 
 
91
94
        self._cache = {}
92
95
 
93
96
 
 
97
 
 
98
    def cache_file_name(self):
 
99
        import os.path
 
100
        return os.path.join(self.basedir, '.bzr', 'stat-cache')
 
101
 
 
102
 
 
103
 
 
104
 
94
105
    def clear(self):
95
106
        """Discard all cached information.
96
107
 
97
108
        This does not reset the counters."""
98
 
        self._cache_sha1 = {}
 
109
        if self._cache:
 
110
            self.needs_write = True
 
111
            self._cache = {}
99
112
 
100
113
 
101
114
    def get_sha1(self, path):
106
119
 
107
120
        import os, time
108
121
        from bzrlib.osutils import sha_file
 
122
        from bzrlib.trace import mutter
109
123
        
110
124
        abspath = os.path.join(self.basedir, path)
111
125
        fp = _fingerprint(abspath)
134
148
                # next time.
135
149
                self.danger_count += 1 
136
150
                if cache_fp:
 
151
                    mutter("remove outdated entry for %s" % path)
 
152
                    self.needs_write = True
137
153
                    del self._cache[path]
138
 
            else:
 
154
            elif (fp != cache_fp) or (digest != cache_sha1):
 
155
                mutter("update entry for %s" % path)
 
156
                mutter("  %r" % (fp,))
 
157
                mutter("  %r" % (cache_fp,))
 
158
                self.needs_write = True
139
159
                self._cache[path] = (digest, fp)
140
160
 
141
161
            return digest
142
162
 
143
163
 
144
164
 
145
 
    def write(self, cachefn):
 
165
    def write(self):
146
166
        """Write contents of cache to file."""
147
167
        from atomicfile import AtomicFile
148
168
 
149
 
        outf = AtomicFile(cachefn, 'wb')
 
169
        outf = AtomicFile(self.cache_file_name(), 'wb')
150
170
        try:
151
171
            print >>outf, CACHE_HEADER,
152
172
 
160
180
                print >>outf
161
181
 
162
182
            outf.commit()
 
183
            self.needs_write = False
163
184
        finally:
164
185
            if not outf.closed:
165
186
                outf.abort()
166
187
        
167
188
 
168
189
 
169
 
    def read(self, cachefn):
 
190
    def read(self):
170
191
        """Reinstate cache from file.
171
192
 
172
193
        Overwrites existing cache.
175
196
        the cache."""
176
197
        from bzrlib.trace import mutter, warning
177
198
 
178
 
        inf = file(cachefn, 'rb')
179
199
        self._cache = {}
180
200
 
 
201
        fn = self.cache_file_name()
 
202
        try:
 
203
            inf = file(fn, 'rb')
 
204
        except IOError, e:
 
205
            mutter("failed to open %s: %s" % (fn, e))
 
206
            return
 
207
 
 
208
 
181
209
        hdr = inf.readline()
182
210
        if hdr != CACHE_HEADER:
183
211
            mutter('cache header marker not found at top of %s; discarding cache'
206
234
 
207
235
            self._cache[path] = (sha1, fp)
208
236
 
 
237
        self.needs_write = False
 
238
           
 
239
 
209
240
 
210
241