/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: Robert Collins
  • Date: 2010-05-05 00:05:29 UTC
  • mto: This revision was merged to the branch mainline in revision 5206.
  • Revision ID: robertc@robertcollins.net-20100505000529-ltmllyms5watqj5u
Make 'pydoc bzrlib.tests.build_tree_shape' useful.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
"""Transport decorator that logs transport operations to brz.log."""
 
17
"""Transport decorator that logs transport operations to .bzr.log."""
18
18
 
19
 
from __future__ import absolute_import
20
19
 
21
20
# see also the transportstats plugin, which gives you some summary information
22
21
# in a machine-readable dump
23
22
 
 
23
import StringIO
 
24
import cStringIO
24
25
import time
25
26
import types
26
27
 
27
 
from ..trace import mutter
28
 
from ..transport import decorator
 
28
from bzrlib.trace import mutter
 
29
from bzrlib.transport import decorator
29
30
 
30
31
 
31
32
class TransportLogDecorator(decorator.TransportDecorator):
32
 
    """Decorator for Transports that logs interesting operations to brz.log.
 
33
    """Decorator for Transports that logs interesting operations to .bzr.log.
33
34
 
34
35
    In general we want to log things that usually take a network round trip
35
36
    and may be slow.
36
37
 
37
38
    Not all operations are logged yet.
38
39
 
39
 
    See also TransportTraceDecorator, that records a machine-readable log in
 
40
    See also TransportTraceDecorator, that records a machine-readable log in 
40
41
    memory for eg testing.
41
42
    """
42
43
 
43
44
    def __init__(self, *args, **kw):
44
45
        super(TransportLogDecorator, self).__init__(*args, **kw)
45
 
 
46
46
        def _make_hook(hookname):
47
47
            def _hook(relpath, *args, **kw):
48
48
                return self._log_and_call(hookname, relpath, *args, **kw)
49
49
            return _hook
50
 
        # GZ 2017-05-21: Not all methods take relpath as first argument, for
51
 
        # instance copy_to takes list of relpaths. Also, unclear on url vs
52
 
        # filesystem path split. Needs tidying up.
53
50
        for methodname in (
54
 
                'append_bytes',
55
 
                'append_file',
56
 
                'copy_to',
57
 
                'delete',
58
 
                'get',
59
 
                'has',
60
 
                'open_write_stream',
61
 
                'mkdir',
62
 
                'move',
63
 
                'put_bytes', 'put_bytes_non_atomic', 'put_file put_file_non_atomic',
64
 
                'list_dir', 'lock_read', 'lock_write',
65
 
                'readv', 'rename', 'rmdir',
66
 
                'stat',
67
 
                'ulock',
68
 
                ):
 
51
            'append_bytes',
 
52
            'append_file',
 
53
            'copy_to',
 
54
            'delete',
 
55
            'get',
 
56
            'has',
 
57
            'open_write_stream',
 
58
            'mkdir',
 
59
            'move',
 
60
            'put_bytes', 'put_bytes_non_atomic', 'put_file put_file_non_atomic',
 
61
            'list_dir', 'lock_read', 'lock_write',
 
62
            'readv', 'rename', 'rmdir',
 
63
            'stat',
 
64
            'ulock',
 
65
            ):
69
66
            setattr(self, methodname, _make_hook(methodname))
70
67
 
71
68
    @classmethod
75
72
    def iter_files_recursive(self):
76
73
        # needs special handling because it does not have a relpath parameter
77
74
        mutter("%s %s"
78
 
               % ('iter_files_recursive', self._decorated.base))
 
75
            % ('iter_files_recursive', self._decorated.base))
79
76
        return self._call_and_log_result('iter_files_recursive', (), {})
80
77
 
81
78
    def _log_and_call(self, methodname, relpath, *args, **kwargs):
84
81
        else:
85
82
            kwargs_str = ''
86
83
        mutter("%s %s %s %s"
87
 
               % (methodname, relpath,
 
84
               % (methodname, self._decorated.abspath(relpath),
88
85
                  self._shorten(self._strip_tuple_parens(args)),
89
86
                  kwargs_str))
90
87
        return self._call_and_log_result(methodname, (relpath,) + args, kwargs)
93
90
        before = time.time()
94
91
        try:
95
92
            result = getattr(self._decorated, methodname)(*args, **kwargs)
96
 
        except Exception as e:
 
93
        except Exception, e:
97
94
            mutter("  --> %s" % e)
98
95
            mutter("      %.03fs" % (time.time() - before))
99
96
            raise
111
108
            return_result = iter(result)
112
109
        else:
113
110
            return_result = result
114
 
        # Is this an io object with a getvalue() method?
115
 
        getvalue = getattr(result, 'getvalue', None)
116
 
        if getvalue is not None:
117
 
            val = repr(getvalue())
 
111
        if isinstance(result, (cStringIO.OutputType, StringIO.StringIO)):
 
112
            val = repr(result.getvalue())
118
113
            result_len = len(val)
119
114
            shown_result = "%s(%s) (%d bytes)" % (result.__class__.__name__,
120
 
                                                  self._shorten(val), result_len)
 
115
                self._shorten(val), result_len)
121
116
        elif methodname == 'readv':
122
117
            num_hunks = len(result)
123
 
            total_bytes = sum((len(d) for o, d in result))
 
118
            total_bytes = sum((len(d) for o,d in result))
124
119
            shown_result = "readv response, %d hunks, %d total bytes" % (
125
120
                num_hunks, total_bytes)
126
121
            result_len = total_bytes
136
131
                # this is the rate of higher-level data, not the raw network
137
132
                # speed using base-10 units (see HACKING.txt).
138
133
                mutter("      %9.03fs %8dkB/s"
139
 
                       % (elapsed, result_len / elapsed / 1000))
 
134
                       % (elapsed, result_len/elapsed/1000))
140
135
            else:
141
136
                mutter("      %9.03fs" % (elapsed))
142
137
        return return_result
155
150
 
156
151
def get_test_permutations():
157
152
    """Return the permutations to be used in testing."""
158
 
    from ..tests import test_server
 
153
    from bzrlib.tests import test_server
159
154
    return [(TransportLogDecorator, test_server.LogDecoratorServer)]