13
13
# You should have received a copy of the GNU General Public License
14
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
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
"""Implementation of Transport that traces transport operations.
20
20
and then delegates it.
23
from bzrlib.transport import decorator
26
class TransportTraceDecorator(decorator.TransportDecorator):
23
from bzrlib.transport.decorator import TransportDecorator, DecoratorServer
26
class TransportTraceDecorator(TransportDecorator):
27
27
"""A tracing decorator for Transports.
29
29
Calls that potentially perform IO are logged to self._activity. The
33
33
Not all operations are logged at this point, if you need an unlogged
34
34
operation please add a test to the tests of this transport, for the logging
35
35
of the operation you want logged.
37
See also TransportLogDecorator, that records a machine-readable log in
38
memory for eg testing.
41
38
def __init__(self, url, _decorated=None, _from_transport=None):
42
39
"""Set the 'base' path where files will be stored.
44
41
_decorated is a private parameter for cloning.
46
super(TransportTraceDecorator, self).__init__(url, _decorated)
43
TransportDecorator.__init__(self, url, _decorated)
47
44
if _from_transport is None:
49
46
self._activity = []
101
98
def put_file(self, relpath, f, mode=None):
102
99
"""See Transport.put_file()."""
103
100
return self._decorated.put_file(relpath, f, mode)
105
102
def put_bytes(self, relpath, bytes, mode=None):
106
103
"""See Transport.put_bytes()."""
107
104
self._trace(('put_bytes', relpath, len(bytes), mode))
108
105
return self._decorated.put_bytes(relpath, bytes, mode)
110
def put_bytes_non_atomic(self, relpath, bytes, mode=None,
111
create_parent_dir=False, dir_mode=None):
112
"""See Transport.put_bytes_non_atomic."""
113
self._trace(('put_bytes_non_atomic', relpath, len(bytes), mode,
114
create_parent_dir, dir_mode))
115
return self._decorated.put_bytes_non_atomic(relpath, bytes, mode=mode,
116
create_parent_dir=create_parent_dir, dir_mode=dir_mode)
118
107
def listable(self):
119
108
"""See Transport.listable."""
120
109
return self._decorated.listable()
122
111
def iter_files_recursive(self):
123
112
"""See Transport.iter_files_recursive()."""
124
113
return self._decorated.iter_files_recursive()
126
115
def list_dir(self, relpath):
127
116
"""See Transport.list_dir()."""
128
117
return self._decorated.list_dir(relpath)
130
119
def readv(self, relpath, offsets, adjust_for_latency=False,
131
120
upper_limit=None):
132
# we override at the readv() level rather than _readv() so that any
133
# latency adjustments will be done by the underlying transport
121
"""See Transport.readv."""
134
122
self._trace(('readv', relpath, offsets, adjust_for_latency,
136
124
return self._decorated.readv(relpath, offsets, adjust_for_latency,
143
131
def rename(self, rel_from, rel_to):
144
132
self._activity.append(('rename', rel_from, rel_to))
145
133
return self._decorated.rename(rel_from, rel_to)
147
135
def rmdir(self, relpath):
148
136
"""See Transport.rmdir."""
149
self._trace(('rmdir', relpath))
150
137
return self._decorated.rmdir(relpath)
152
139
def stat(self, relpath):
169
156
self._activity.append(operation_tuple)
159
class TraceServer(DecoratorServer):
160
"""Server for the TransportTraceDecorator for testing with."""
162
def get_decorator_class(self):
163
return TransportTraceDecorator
172
166
def get_test_permutations():
173
167
"""Return the permutations to be used in testing."""
174
from bzrlib.tests import test_server
175
return [(TransportTraceDecorator, test_server.TraceServer)]
168
return [(TransportTraceDecorator, TraceServer)]