/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/transport/log.py

  • Committer: John Arbash Meinel
  • Date: 2009-06-18 18:18:36 UTC
  • mto: This revision was merged to the branch mainline in revision 4461.
  • Revision ID: john@arbash-meinel.com-20090618181836-biodfkat9a8eyzjz
The new add_inventory_by_delta is returning a CHKInventory when mapping from NULL
Which is completely valid, but 'broke' one of the tests.
So to fix it, changed the test to use CHKInventories on both sides, and add an __eq__
member. The nice thing is that CHKInventory.__eq__ is fairly cheap, since it only
has to check the root keys.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2007 Canonical Ltd
 
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
"""Transport decorator that logs transport operations to .bzr.log."""
 
18
 
 
19
 
 
20
# see also the transportstats plugin, which gives you some summary information
 
21
# in a machine-readable dump
 
22
 
 
23
import StringIO
 
24
import cStringIO
 
25
import time
 
26
import types
 
27
 
 
28
from bzrlib.trace import mutter
 
29
from bzrlib.transport.decorator import (
 
30
    TransportDecorator,
 
31
    )
 
32
from bzrlib.transport.trace import (
 
33
    DecoratorServer,
 
34
    TransportTraceDecorator,
 
35
    )
 
36
 
 
37
 
 
38
 
 
39
 
 
40
class TransportLogDecorator(TransportDecorator):
 
41
    """Decorator for Transports that logs interesting operations to .bzr.log.
 
42
 
 
43
    In general we want to log things that usually take a network round trip
 
44
    and may be slow.
 
45
 
 
46
    Not all operations are logged yet.
 
47
    """
 
48
 
 
49
    def __init__(self, *args, **kw):
 
50
        super(TransportLogDecorator, self).__init__(*args, **kw)
 
51
        def _make_hook(hookname):
 
52
            def _hook(relpath, *args, **kw):
 
53
                return self._log_and_call(hookname, relpath, *args, **kw)
 
54
            return _hook
 
55
        for methodname in (
 
56
            'append_bytes',
 
57
            'append_file',
 
58
            'copy_to',
 
59
            'delete',
 
60
            'get',
 
61
            'has',
 
62
            'open_write_stream',
 
63
            'mkdir',
 
64
            'move',
 
65
            'put_bytes', 'put_bytes_non_atomic', 'put_file put_file_non_atomic',
 
66
            'list_dir', 'lock_read', 'lock_write',
 
67
            'readv', 'rename', 'rmdir',
 
68
            'stat',
 
69
            'ulock',
 
70
            ):
 
71
            setattr(self, methodname, _make_hook(methodname))
 
72
 
 
73
    @classmethod
 
74
    def _get_url_prefix(self):
 
75
        return 'log+'
 
76
 
 
77
    def iter_files_recursive(self):
 
78
        # needs special handling because it does not have a relpath parameter
 
79
        mutter("%s %s"
 
80
            % ('iter_files_recursive', self._decorated.base))
 
81
        return self._call_and_log_result('iter_files_recursive', (), {})
 
82
 
 
83
    def _log_and_call(self, methodname, relpath, *args, **kwargs):
 
84
        if kwargs:
 
85
            kwargs_str = dict(kwargs)
 
86
        else:
 
87
            kwargs_str = ''
 
88
        mutter("%s %s %s %s"
 
89
               % (methodname, self._decorated.abspath(relpath),
 
90
                  self._shorten(self._strip_tuple_parens(args)),
 
91
                  kwargs_str))
 
92
        return self._call_and_log_result(methodname, (relpath,) + args, kwargs)
 
93
 
 
94
    def _call_and_log_result(self, methodname, args, kwargs):
 
95
        before = time.time()
 
96
        try:
 
97
            result = getattr(self._decorated, methodname)(*args, **kwargs)
 
98
        except Exception, e:
 
99
            mutter("  --> %s" % e)
 
100
            mutter("      %.03fs" % (time.time() - before))
 
101
            raise
 
102
        return self._show_result(before, methodname, result)
 
103
 
 
104
    def _show_result(self, before, methodname, result):
 
105
        result_len = None
 
106
        if isinstance(result, types.GeneratorType):
 
107
            # eagerly pull in all the contents, so that we can measure how
 
108
            # long it takes to get them.  this does make the behaviour a bit
 
109
            # different, but we hope not noticably so
 
110
            result = list(result)
 
111
        if isinstance(result, (cStringIO.OutputType, StringIO.StringIO)):
 
112
            val = repr(result.getvalue())
 
113
            result_len = len(val)
 
114
            shown_result = "%s(%s) (%d bytes)" % (result.__class__.__name__,
 
115
                self._shorten(val), result_len)
 
116
        elif methodname == 'readv':
 
117
            num_hunks = len(result)
 
118
            total_bytes = sum((len(d) for o,d in result))
 
119
            shown_result = "readv response, %d hunks, %d total bytes" % (
 
120
                num_hunks, total_bytes)
 
121
            result_len = total_bytes
 
122
        else:
 
123
            shown_result = self._shorten(self._strip_tuple_parens(result))
 
124
        mutter("  --> %s" % shown_result)
 
125
        # XXX: the time may be wrong when e.g. a generator object is returned from
 
126
        # an http readv, if the object is returned before the bulk data
 
127
        # is read.
 
128
        elapsed = time.time() - before
 
129
        if result_len and elapsed > 0:
 
130
            # this is the rate of higher-level data, not the raw network speed
 
131
            mutter("      %9.03fs %8dKB/s" % (elapsed, result_len/elapsed/1024))
 
132
        else:
 
133
            mutter("      %9.03fs" % (elapsed))
 
134
        return result
 
135
 
 
136
    def _shorten(self, x):
 
137
        if len(x) > 70:
 
138
            x = x[:67] + '...'
 
139
        return x
 
140
 
 
141
    def _strip_tuple_parens(self, t):
 
142
        t = repr(t)
 
143
        if t[0] == '(' and t[-1] == ')':
 
144
            t = t[1:-1]
 
145
        return t
 
146
 
 
147
 
 
148
class LogDecoratorServer(DecoratorServer):
 
149
    """Server for testing."""
 
150
 
 
151
    def get_decorator_class(self):
 
152
        return TransportLogDecorator
 
153
 
 
154
 
 
155
def get_test_permutations():
 
156
    """Return the permutations to be used in testing."""
 
157
    return [(TransportLogDecorator, LogDecoratorServer)]