~ubuntu-branches/debian/jessie/bzr-fastimport/jessie

« back to all changes in this revision

Viewing changes to cache_manager.py

  • Committer: Bazaar Package Importer
  • Author(s): Jelmer Vernooij
  • Date: 2010-11-06 18:40:27 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20101106184027-iclo8iim9equ6i8b
Tags: 0.9.0+bzr279-1
* New upstream snapshot.
* Bump standards version to 3.9.1 (no changes).
* Run testsuite during package build.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
import os
21
21
import shutil
22
22
import tempfile
23
 
import time
24
23
import weakref
25
24
 
26
25
from bzrlib import lru_cache, trace
27
 
from bzrlib.plugins.fastimport import branch_mapper, helpers
28
 
 
29
 
 
30
 
class _Cleanup(object):
31
 
    """This class makes sure we clean up when CacheManager goes away.
32
 
 
33
 
    We use a helper class to ensure that we are never in a refcycle.
34
 
    """
35
 
 
36
 
    def __init__(self, disk_blobs):
37
 
        self.disk_blobs = disk_blobs
38
 
        self.tempdir = None
39
 
        self.small_blobs = None
40
 
 
41
 
    def __del__(self):
42
 
        self.finalize()
43
 
 
44
 
    def finalize(self):
45
 
        if self.disk_blobs is not None:
46
 
            for info in self.disk_blobs.itervalues():
47
 
                if info[-1] is not None:
48
 
                    os.unlink(info[-1])
49
 
            self.disk_blobs = None
50
 
        if self.small_blobs is not None:
51
 
            self.small_blobs.close()
52
 
            self.small_blobs = None
53
 
        if self.tempdir is not None:
54
 
            shutils.rmtree(self.tempdir)
55
 
        
56
 
 
57
 
 
58
 
class _Cleanup(object):
59
 
    """This class makes sure we clean up when CacheManager goes away.
60
 
 
61
 
    We use a helper class to ensure that we are never in a refcycle.
62
 
    """
63
 
 
64
 
    def __init__(self, disk_blobs):
65
 
        self.disk_blobs = disk_blobs
66
 
        self.tempdir = None
67
 
        self.small_blobs = None
68
 
 
69
 
    def __del__(self):
70
 
        self.finalize()
71
 
 
72
 
    def finalize(self):
73
 
        if self.disk_blobs is not None:
74
 
            for info in self.disk_blobs.itervalues():
75
 
                if info[-1] is not None:
76
 
                    os.unlink(info[-1])
77
 
            self.disk_blobs = None
78
 
        if self.small_blobs is not None:
79
 
            self.small_blobs.close()
80
 
            self.small_blobs = None
81
 
        if self.tempdir is not None:
82
 
            shutils.rmtree(self.tempdir)
83
 
        
 
26
from bzrlib.plugins.fastimport import (
 
27
    branch_mapper,
 
28
    )
 
29
from fastimport.helpers import (
 
30
    single_plural,
 
31
    )
 
32
from fastimport.reftracker import (
 
33
    RefTracker,
 
34
    )
 
35
 
 
36
 
 
37
class _Cleanup(object):
 
38
    """This class makes sure we clean up when CacheManager goes away.
 
39
 
 
40
    We use a helper class to ensure that we are never in a refcycle.
 
41
    """
 
42
 
 
43
    def __init__(self, disk_blobs):
 
44
        self.disk_blobs = disk_blobs
 
45
        self.tempdir = None
 
46
        self.small_blobs = None
 
47
 
 
48
    def __del__(self):
 
49
        self.finalize()
 
50
 
 
51
    def finalize(self):
 
52
        if self.disk_blobs is not None:
 
53
            for info in self.disk_blobs.itervalues():
 
54
                if info[-1] is not None:
 
55
                    os.unlink(info[-1])
 
56
            self.disk_blobs = None
 
57
        if self.small_blobs is not None:
 
58
            self.small_blobs.close()
 
59
            self.small_blobs = None
 
60
        if self.tempdir is not None:
 
61
            shutil.rmtree(self.tempdir)
 
62
 
 
63
 
 
64
class _Cleanup(object):
 
65
    """This class makes sure we clean up when CacheManager goes away.
 
66
 
 
67
    We use a helper class to ensure that we are never in a refcycle.
 
68
    """
 
69
 
 
70
    def __init__(self, disk_blobs):
 
71
        self.disk_blobs = disk_blobs
 
72
        self.tempdir = None
 
73
        self.small_blobs = None
 
74
 
 
75
    def __del__(self):
 
76
        self.finalize()
 
77
 
 
78
    def finalize(self):
 
79
        if self.disk_blobs is not None:
 
80
            for info in self.disk_blobs.itervalues():
 
81
                if info[-1] is not None:
 
82
                    os.unlink(info[-1])
 
83
            self.disk_blobs = None
 
84
        if self.small_blobs is not None:
 
85
            self.small_blobs.close()
 
86
            self.small_blobs = None
 
87
        if self.tempdir is not None:
 
88
            shutil.rmtree(self.tempdir)
 
89
 
84
90
 
85
91
class CacheManager(object):
86
 
    
 
92
 
87
93
    _small_blob_threshold = 25*1024
88
94
    _sticky_cache_size = 300*1024*1024
89
95
    _sticky_flushed_size = 100*1024*1024
122
128
        # (path, branch_ref) -> file-ids - as generated.
123
129
        # (Use store_file_id/fetch_fileid methods rather than direct access.)
124
130
 
125
 
        # Head tracking: last ref, last id per ref & map of commit ids to ref*s*
126
 
        self.last_ref = None
127
 
        self.last_ids = {}
128
 
        self.heads = {}
129
 
 
130
131
        # Work out the blobs to make sticky - None means all
131
132
        self._blob_ref_counts = {}
132
133
        if info is not None:
145
146
        # than reinstantiate on every usage
146
147
        self.branch_mapper = branch_mapper.BranchMapper()
147
148
 
 
149
        self.reftracker = RefTracker()
 
150
 
148
151
    def dump_stats(self, note=trace.note):
149
152
        """Dump some statistics about what we cached."""
150
153
        # TODO: add in inventory stastistics
153
156
        self._show_stats_for(self.revision_ids, "revision-ids", note=note)
154
157
        # These aren't interesting so omit from the output, at least for now
155
158
        #self._show_stats_for(self._blobs, "other blobs", note=note)
156
 
        #self._show_stats_for(self.last_ids, "last-ids", note=note)
157
 
        #self._show_stats_for(self.heads, "heads", note=note)
 
159
        #self.reftracker.dump_stats(note=note)
158
160
 
159
161
    def _show_stats_for(self, dict, label, note=trace.note, tuple_key=False):
160
162
        """Dump statistics about a given dictionary.
176
178
                size = size / 1024
177
179
                unit = 'G'
178
180
        note("    %-12s: %8.1f %s (%d %s)" % (label, size, unit, count,
179
 
            helpers.single_plural(count, "item", "items")))
 
181
            single_plural(count, "item", "items")))
180
182
 
181
183
    def clear_all(self):
182
184
        """Free up any memory used by the caches."""
183
185
        self._blobs.clear()
184
186
        self._sticky_blobs.clear()
185
187
        self.revision_ids.clear()
186
 
        self.last_ids.clear()
187
 
        self.heads.clear()
 
188
        self.reftracker.clear()
188
189
        self.inventories.clear()
189
190
 
190
191
    def _flush_blobs_to_disk(self):
193
194
        total_blobs = len(sticky_blobs)
194
195
        blobs.sort(key=lambda k:len(sticky_blobs[k]))
195
196
        if self._tempdir is None:
196
 
            tempdir = tempfile.mkdtemp(prefix='bzr_fastimport_blobs-')
 
197
            tempdir = tempfile.mkdtemp(prefix='fastimport_blobs-')
197
198
            self._tempdir = tempdir
198
199
            self._cleanup.tempdir = self._tempdir
199
200
            self._cleanup.small_blobs = tempfile.TemporaryFile(
234
235
        trace.note('flushed %d/%d blobs w/ %.1fMB (%.1fMB small) to disk'
235
236
                   % (count, total_blobs, bytes / 1024. / 1024,
236
237
                      n_small_bytes / 1024. / 1024))
237
 
        
238
238
 
239
239
    def store_blob(self, id, data):
240
240
        """Store a blob of data."""
289
289
            self._sticky_memory_bytes -= len(content)
290
290
        return content
291
291
 
292
 
    def track_heads(self, cmd):
293
 
        """Track the repository heads given a CommitCommand.
294
 
        
295
 
        :param cmd: the CommitCommand
296
 
        :return: the list of parents in terms of commit-ids
297
 
        """
298
 
        # Get the true set of parents
299
 
        if cmd.from_ is not None:
300
 
            parents = [cmd.from_]
301
 
        else:
302
 
            last_id = self.last_ids.get(cmd.ref)
303
 
            if last_id is not None:
304
 
                parents = [last_id]
305
 
            else:
306
 
                parents = []
307
 
        parents.extend(cmd.merges)
308
 
 
309
 
        # Track the heads
310
 
        self.track_heads_for_ref(cmd.ref, cmd.id, parents)
311
 
        return parents
312
 
 
313
 
    def track_heads_for_ref(self, cmd_ref, cmd_id, parents=None):
314
 
        if parents is not None:
315
 
            for parent in parents:
316
 
                if parent in self.heads:
317
 
                    del self.heads[parent]
318
 
        self.heads.setdefault(cmd_id, set()).add(cmd_ref)
319
 
        self.last_ids[cmd_ref] = cmd_id
320
 
        self.last_ref = cmd_ref
 
292