~mkanat/loggerhead/synchronize-lru_cache

« back to all changes in this revision

Viewing changes to loggerhead/history.py

  • Committer: Matt Nordhoff
  • Date: 2010-01-14 00:20:24 UTC
  • mfrom: (399.1.3 loggerhead)
  • Revision ID: mnordhoff@mattnordhoff.com-20100114002024-w9wojo0hu8tg1j2q
Don't build a branch's revision graph cache more than once at the same time. (Max Kanat-Alexander)

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
import logging
34
34
import re
35
35
import textwrap
 
36
import threading
36
37
 
37
38
import bzrlib.branch
38
39
import bzrlib.delta
188
189
        """
189
190
        self._cache[key] = (revid, data)
190
191
 
 
192
# Used to store locks that prevent multiple threads from building a 
 
193
# revision graph for the same branch at the same time, because that can
 
194
# cause severe performance issues that are so bad that the system seems
 
195
# to hang.
 
196
revision_graph_locks = {}
 
197
revision_graph_check_lock = threading.Lock()
191
198
 
192
199
class History(object):
193
200
    """Decorate a branch to provide information for rendering.
227
234
        def update_missed_caches():
228
235
            for cache in missed_caches:
229
236
                cache.set(cache_key, self.last_revid, self._rev_info)
230
 
        for cache in caches:
231
 
            data = cache.get(cache_key, self.last_revid)
232
 
            if data is not None:
233
 
                self._rev_info = data
 
237
 
 
238
        # Theoretically, it's possible for two threads to race in creating
 
239
        # the Lock() object for their branch, so we put a lock around
 
240
        # creating the per-branch Lock().
 
241
        revision_graph_check_lock.acquire()
 
242
        try:
 
243
            if cache_key not in revision_graph_locks:
 
244
                revision_graph_locks[cache_key] = threading.Lock()
 
245
        finally:
 
246
            revision_graph_check_lock.release()
 
247
 
 
248
        revision_graph_locks[cache_key].acquire()
 
249
        try:
 
250
            for cache in caches:
 
251
                data = cache.get(cache_key, self.last_revid)
 
252
                if data is not None:
 
253
                    self._rev_info = data
 
254
                    update_missed_caches()
 
255
                    break
 
256
                else:
 
257
                    missed_caches.append(cache)
 
258
            else:
 
259
                whole_history_data = compute_whole_history_data(self._branch)
 
260
                self._rev_info, self._rev_indices = whole_history_data
234
261
                update_missed_caches()
235
 
                break
236
 
            else:
237
 
                missed_caches.append(cache)
238
 
        else:
239
 
            whole_history_data = compute_whole_history_data(self._branch)
240
 
            self._rev_info, self._rev_indices = whole_history_data
241
 
            update_missed_caches()
 
262
        finally:
 
263
            revision_graph_locks[cache_key].release()
242
264
 
243
265
        if self._rev_indices is not None:
244
266
            self._revno_revid = {}