~bzr-pqm/bzr/bzr.dev

2052.3.2 by John Arbash Meinel
Change Copyright .. by Canonical to Copyright ... Canonical
1
# Copyright (C) 2006 Canonical Ltd
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Tree creators for kernel-like trees"""
18
1943.1.1 by John Arbash Meinel
Create the kernel_like_tree rather than expecting the directory to exist. Required when the creator is called directly by another creator
19
import errno
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
20
import os
21
22
from bzrlib import (
23
    bzrdir,
24
    osutils,
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
25
    workingtree,
26
    xml5,
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
27
    )
28
29
from bzrlib.benchmarks.tree_creator import TreeCreator
30
31
32
class KernelLikeTreeCreator(TreeCreator):
2399.1.7 by John Arbash Meinel
Cleanup bzrlib/benchmarks/* so that everything at least has a valid doc string.
33
    """Create a basic tree with ~10k unversioned files"""
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
34
35
    def __init__(self, test, link_working=False, url=None):
36
        super(KernelLikeTreeCreator, self).__init__(test,
37
            tree_name='kernel_like_tree',
38
            link_working=link_working,
39
            link_bzr=False)
40
41
        self._url = url
42
43
    def create(self, root):
44
        """Create all the kernel files in the given location.
45
46
        This is overloaded for compatibility reasons.
47
        """
48
        if self._url is not None:
49
            b = bzrdir.BzrDir.create_branch_convenience(self._url)
50
            d = bzrdir.BzrDir.create(root)
51
            bzrlib.branch.BranchReferenceFormat().initialize(d, b)
52
            tree = d.create_workingtree()
53
        else:
54
            tree = bzrdir.BzrDir.create_standalone_workingtree(root)
55
56
        if not self._link_working or not self.is_caching_enabled():
57
            # Turns out that 'shutil.copytree()' is no faster than
58
            # just creating them. Probably the python overhead.
59
            # Plain _make_kernel_files takes 3-5s
60
            # cp -a takes 3s
61
            # using hardlinks takes < 1s.
62
            self._create_tree(root=root, in_cache=False)
63
            return tree
64
65
        self.ensure_cached()
66
        cache_dir = self._get_cache_dir()
67
        osutils.copy_tree(cache_dir, root,
68
                          handlers={'file':os.link})
69
        return tree
70
71
    def _create_tree(self, root, in_cache=False):
72
        # a kernel tree has ~10000 and 500 directory, with most files around 
73
        # 3-4 levels deep. 
74
        # we simulate this by three levels of dirs named 0-7, givin 512 dirs,
75
        # and 20 files each.
76
        files = []
77
        for outer in range(8):
78
            files.append("%s/" % outer)
79
            for middle in range(8):
80
                files.append("%s/%s/" % (outer, middle))
81
                for inner in range(8):
82
                    prefix = "%s/%s/%s/" % (outer, middle, inner)
83
                    files.append(prefix)
84
                    files.extend([prefix + str(foo) for foo in range(20)])
85
        cwd = osutils.getcwd()
1943.1.1 by John Arbash Meinel
Create the kernel_like_tree rather than expecting the directory to exist. Required when the creator is called directly by another creator
86
        try:
87
            os.mkdir(root)
88
        except OSError, e:
89
            if e.errno not in (errno.EEXIST,):
90
                raise
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
91
        os.chdir(root)
92
        self._test.build_tree(files)
93
        os.chdir(cwd)
94
        if in_cache:
95
            self._protect_files(root)
96
97
98
class KernelLikeAddedTreeCreator(TreeCreator):
2399.1.7 by John Arbash Meinel
Cleanup bzrlib/benchmarks/* so that everything at least has a valid doc string.
99
    """Create a tree with ~10k versioned but not committed files"""
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
100
101
    def __init__(self, test, link_working=False, hot_cache=True):
102
        super(KernelLikeAddedTreeCreator, self).__init__(test,
103
            tree_name='kernel_like_added_tree',
104
            link_working=link_working,
105
            link_bzr=False,
106
            hot_cache=hot_cache)
107
108
    def _create_tree(self, root, in_cache=False):
109
        """Create a kernel-like tree with the all files added
110
111
        :param root: The root directory to create the files
112
        :param in_cache: Is this being created in the cache dir?
113
        """
114
        kernel_creator = KernelLikeTreeCreator(self._test,
115
                                               link_working=in_cache)
116
        tree = kernel_creator.create(root=root)
117
118
        # Add everything to it
119
        tree.lock_write()
120
        try:
2568.2.7 by Robert Collins
Fix missed tests.
121
            tree.smart_add([root], recurse=True, save=True)
1908.2.16 by John Arbash Meinel
Move all the new TreeCreator classes into separate files.
122
            if in_cache:
123
                self._protect_files(root+'/.bzr')
124
        finally:
125
            tree.unlock()
126
        return tree
127
128
129
class KernelLikeCommittedTreeCreator(TreeCreator):
130
    """Create a tree with ~10K files, and a single commit adding all of them"""
131
132
    def __init__(self, test, link_working=False, link_bzr=False,
133
                 hot_cache=True):
134
        super(KernelLikeCommittedTreeCreator, self).__init__(test,
135
            tree_name='kernel_like_committed_tree',
136
            link_working=link_working,
137
            link_bzr=link_bzr,
138
            hot_cache=hot_cache)
139
140
    def _create_tree(self, root, in_cache=False):
141
        """Create a kernel-like tree with all files committed
142
143
        :param root: The root directory to create the files
144
        :param in_cache: Is this being created in the cache dir?
145
        """
146
        kernel_creator = KernelLikeAddedTreeCreator(self._test,
147
                                                    link_working=in_cache,
148
                                                    hot_cache=(not in_cache))
149
        tree = kernel_creator.create(root=root)
150
        tree.commit('first post', rev_id='r1')
151
152
        if in_cache:
153
            self._protect_files(root+'/.bzr')
154
        return tree
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
155
156
157
class KernelLikeInventoryCreator(TreeCreator):
158
    """Return just the memory representation of a committed kernel-like tree"""
159
160
    def __init__(self, test):
161
        super(KernelLikeInventoryCreator, self).__init__(test,
162
            tree_name='kernel_like_inventory',
163
            link_working=True,
164
            link_bzr=True,
165
            hot_cache=True)
166
167
    def ensure_cached(self):
168
        """Make sure we have a cached version of the kernel-like inventory"""
169
        cache_dir = self._get_cache_dir()
170
        if cache_dir is None:
171
            return
172
173
        if self.is_cached():
174
            return
175
176
        committed_creator = KernelLikeCommittedTreeCreator(self._test,
177
                                                           link_working=True,
178
                                                           link_bzr=True,
179
                                                           hot_cache=False)
180
        committed_creator.ensure_cached()
181
        committed_cache_dir = committed_creator._get_cache_dir()
182
        committed_tree = workingtree.WorkingTree.open(committed_cache_dir)
183
        rev_tree = committed_tree.basis_tree()
184
        os.mkdir(cache_dir)
185
        f = open(cache_dir+'/inventory', 'wb')
186
        try:
187
            xml5.serializer_v5.write_inventory(rev_tree.inventory, f)
188
        finally:
189
            f.close()
190
2399.1.7 by John Arbash Meinel
Cleanup bzrlib/benchmarks/* so that everything at least has a valid doc string.
191
    def create(self, root=None):
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
192
        """Create a kernel like inventory
193
2399.1.7 by John Arbash Meinel
Cleanup bzrlib/benchmarks/* so that everything at least has a valid doc string.
194
        :param root: Exists to mimic the base class, but this class
195
            returns only an in-memory Inventory, so it should always be None.
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
196
        :return: An Inventory object.
197
        """
2399.1.7 by John Arbash Meinel
Cleanup bzrlib/benchmarks/* so that everything at least has a valid doc string.
198
        assert root is None, "Cannot create a memory inventory in a on disk."
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
199
        cache_dir = self._get_cache_dir()
200
        if cache_dir is None:
201
            return self._create_and_return()
202
203
        self.ensure_cached()
204
        return self._open_cached(cache_dir)
205
206
    def _create_and_return(self):
207
        """Create a kernel-like tree, and return its inventory"""
208
        creator = KernelLikeCommittedTreeCreator(self._test,
209
                                                 link_working=True,
210
                                                 link_bzr=True,
211
                                                 hot_cache=False)
212
        tree = creator.create('.')
2817.2.1 by Robert Collins
* Inventory serialisation no longer double-sha's the content.
213
        basis = tree.basis_tree()
214
        basis.lock_read()
215
        try:
216
            return basis.inventory
217
        finally:
218
            basis.unlock()
1934.1.16 by John Arbash Meinel
Add a cache for a kernel-like inventory
219
220
    def _open_cached(self, cache_dir):
221
        f = open(cache_dir + '/inventory', 'rb')
222
        try:
223
            return xml5.serializer_v5.read_inventory(f)
224
        finally:
225
            f.close()