~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/statcache.py

  • Committer: Martin Pool
  • Date: 2005-05-10 06:07:16 UTC
  • Revision ID: mbp@sourcefrog.net-20050510060716-0f939ce3ddea5d15
- New command update-stat-cache for testing
- work-cache always stored with unix newlines and in ascii

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
 
52
52
At the moment this is stored in a simple textfile; it might be nice
53
53
to use a tdb instead.
54
 
 
55
 
The cache is represented as a map from file_id to a tuple of (file_id,
56
 
sha1, path, size, mtime, ctime, ino, dev).
57
54
"""
58
55
 
59
56
 
60
 
FP_SIZE  = 0
61
 
FP_MTIME = 1
62
 
FP_CTIME = 2
63
 
FP_INO   = 3
64
 
FP_DEV   = 4
65
 
 
66
 
 
67
 
SC_FILE_ID = 0
68
 
SC_SHA1    = 1 
69
 
 
70
57
 
71
58
def fingerprint(path, abspath):
72
59
    try:
82
69
            fs.st_ctime, fs.st_ino, fs.st_dev)
83
70
 
84
71
 
85
 
def _write_cache(branch, entry_iter, dangerfiles):
 
72
def write_cache(branch, entry_iter):
86
73
    from atomicfile import AtomicFile
87
74
    
88
 
    outf = AtomicFile(branch.controlfilename('stat-cache'), 'wb', 'utf-8')
 
75
    outf = AtomicFile(branch.controlfilename('work-cache.tmp'), 'wb')
89
76
    try:
90
77
        for entry in entry_iter:
91
 
            if entry[0] in dangerfiles:
92
 
                continue
93
78
            outf.write(entry[0] + ' ' + entry[1] + ' ')
94
79
            outf.write(b2a_qp(entry[2], True))
95
80
            outf.write(' %d %d %d %d %d\n' % entry[3:])
104
89
    cache = {}
105
90
 
106
91
    try:
107
 
        cachefile = branch.controlfile('stat-cache', 'r')
 
92
        cachefile = branch.controlfile('work-cache', 'rb')
108
93
    except IOError:
109
94
        return cache
110
95
    
126
111
        yield ie.file_id, path
127
112
    
128
113
 
129
 
 
130
 
def update_cache(branch, inv=None, flush=False):
131
 
    """Update and return the cache for the branch.
132
 
 
133
 
    The returned cache may contain entries that have not been written
134
 
    to disk for files recently touched.
135
 
 
136
 
    flush -- discard any previous cache and recalculate from scratch.
137
 
    """
138
 
 
 
114
def build_cache(branch):
 
115
    inv = branch.read_working_inventory()
 
116
 
 
117
    cache = {}
 
118
    _update_cache_from_list(branch, cache, _files_from_inventory(inv))
139
119
    
 
120
 
 
121
 
 
122
def update_cache(branch, inv):
140
123
    # TODO: It's supposed to be faster to stat the files in order by inum.
141
124
    # We don't directly know the inum of the files of course but we do
142
125
    # know where they were last sighted, so we can sort by that.
143
126
 
144
 
    assert isinstance(flush, bool)
145
 
    if flush:
146
 
        cache = {}
147
 
    else:
148
 
        cache = load_cache(branch)
149
 
    if inv == None:
150
 
        inv = branch.read_working_inventory()
 
127
    cache = load_cache(branch)
151
128
    return _update_cache_from_list(branch, cache, _files_from_inventory(inv))
152
129
 
153
130
 
154
131
 
155
132
def _update_cache_from_list(branch, cache, to_update):
156
 
    """Update and return the cache for given files.
157
 
 
158
 
    cache -- Previously cached values to be validated.
159
 
 
160
 
    to_update -- Sequence of (file_id, path) pairs to check.
 
133
    """Update the cache to have info on the named files.
 
134
 
 
135
    to_update is a sequence of (file_id, path) pairs.
161
136
    """
162
 
 
163
 
    from sets import Set
164
 
 
165
137
    hardcheck = dirty = 0
166
 
 
167
 
    # files that have been recently touched and can't be
168
 
    # committed to a persistent cache yet.
169
 
    
170
 
    dangerfiles = Set()
171
 
    now = int(time.time())
172
 
    
173
138
    for file_id, path in to_update:
174
139
        fap = branch.abspath(path)
175
140
        fp = fingerprint(fap, path)
181
146
                dirty += 1
182
147
            continue
183
148
 
184
 
        if (fp[FP_MTIME] >= now) or (fp[FP_CTIME] >= now):
185
 
            dangerfiles.add(file_id)
186
 
 
187
149
        if cacheentry and (cacheentry[3:] == fp):
188
150
            continue                    # all stat fields unchanged
189
151
 
198
160
            cache[file_id] = cacheentry
199
161
            dirty += 1
200
162
 
201
 
    mutter('statcache: read %d files, %d changed, %d dangerous, '
202
 
           '%d in cache'
203
 
           % (hardcheck, dirty, len(dangerfiles), len(cache)))
 
163
    mutter('work cache: read %d files, %d changed' % (hardcheck, dirty))
204
164
        
205
165
    if dirty:
206
 
        mutter('updating on-disk statcache')
207
 
        _write_cache(branch, cache.itervalues(), dangerfiles)
 
166
        write_cache(branch, cache.itervalues())
208
167
 
209
168
    return cache