~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/medium.py

Merge from bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
 
54
54
    The server passes requests through to an underlying backing transport, 
55
55
    which will typically be a LocalTransport looking at the server's filesystem.
 
56
 
 
57
    :ivar _push_back_buffer: a str of bytes that have been read from the stream
 
58
        but not used yet, or None if there are no buffered bytes.  Subclasses
 
59
        should make sure to exhaust this buffer before reading more bytes from
 
60
        the stream.  See also the _push_back method.
56
61
    """
57
62
 
58
 
    def __init__(self, backing_transport):
 
63
    def __init__(self, backing_transport, root_client_path='/'):
59
64
        """Construct new server.
60
65
 
61
66
        :param backing_transport: Transport for the directory served.
62
67
        """
63
68
        # backing_transport could be passed to serve instead of __init__
64
69
        self.backing_transport = backing_transport
 
70
        self.root_client_path = root_client_path
65
71
        self.finished = False
66
 
        self.push_back = None
 
72
        self._push_back_buffer = None
67
73
 
68
74
    def _push_back(self, bytes):
69
 
        assert self.push_back is None, (
70
 
            "_push_back called when self.push is %r" % (self.push_back,))
 
75
        """Return unused bytes to the medium, because they belong to the next
 
76
        request(s).
 
77
 
 
78
        This sets the _push_back_buffer to the given bytes.
 
79
        """
 
80
        assert self._push_back_buffer is None, (
 
81
            "_push_back called when self._push_back_buffer is %r"
 
82
            % (self._push_back_buffer,))
71
83
        if bytes == '':
72
84
            return
73
 
        self.push_back = bytes
 
85
        self._push_back_buffer = bytes
 
86
 
 
87
    def _get_push_back_buffer(self):
 
88
        assert self._push_back_buffer != '', (
 
89
            '%s._push_back_buffer should never be the empty string, '
 
90
            'which can be confused with EOF' % (self,))
 
91
        bytes = self._push_back_buffer
 
92
        self._push_back_buffer = None
 
93
        return bytes
74
94
 
75
95
    def serve(self):
76
96
        """Serve requests until the client disconnects."""
101
121
            bytes = bytes[len(REQUEST_VERSION_TWO):]
102
122
        else:
103
123
            protocol_class = SmartServerRequestProtocolOne
104
 
        protocol = protocol_class(self.backing_transport, self._write_out)
 
124
        protocol = protocol_class(
 
125
            self.backing_transport, self._write_out, self.root_client_path)
105
126
        protocol.accept_bytes(bytes)
106
127
        return protocol
107
128
 
152
173
 
153
174
class SmartServerSocketStreamMedium(SmartServerStreamMedium):
154
175
 
155
 
    def __init__(self, sock, backing_transport):
 
176
    def __init__(self, sock, backing_transport, root_client_path='/'):
156
177
        """Constructor.
157
178
 
158
179
        :param sock: the socket the server will read from.  It will be put
159
180
            into blocking mode.
160
181
        """
161
 
        SmartServerStreamMedium.__init__(self, backing_transport)
 
182
        SmartServerStreamMedium.__init__(
 
183
            self, backing_transport, root_client_path=root_client_path)
162
184
        sock.setblocking(True)
163
185
        self.socket = sock
164
186
 
165
187
    def _serve_one_request_unguarded(self, protocol):
166
188
        while protocol.next_read_size():
167
 
            if self.push_back:
168
 
                protocol.accept_bytes(self.push_back)
169
 
                self.push_back = None
170
 
            else:
171
 
                bytes = self._get_bytes(4096)
172
 
                if bytes == '':
173
 
                    self.finished = True
174
 
                    return
175
 
                protocol.accept_bytes(bytes)
 
189
            bytes = self._get_bytes(4096)
 
190
            if bytes == '':
 
191
                self.finished = True
 
192
                return
 
193
            protocol.accept_bytes(bytes)
176
194
        
177
195
        self._push_back(protocol.excess_buffer)
178
196
 
179
197
    def _get_bytes(self, desired_count):
 
198
        if self._push_back_buffer is not None:
 
199
            return self._get_push_back_buffer()
180
200
        # We ignore the desired_count because on sockets it's more efficient to
181
201
        # read 4k at a time.
182
 
        if self.push_back is not None:
183
 
            assert self.push_back != '', (
184
 
                'self.push_back should never be the empty string, which can be '
185
 
                'confused with EOF')
186
 
            bytes = self.push_back
187
 
            self.push_back = None
188
 
            return bytes
189
202
        return self.socket.recv(4096)
190
203
    
191
204
    def terminate_due_to_error(self):
235
248
            protocol.accept_bytes(bytes)
236
249
 
237
250
    def _get_bytes(self, desired_count):
238
 
        if self.push_back is not None:
239
 
            assert self.push_back != '', (
240
 
                'self.push_back should never be the empty string, which can be '
241
 
                'confused with EOF')
242
 
            bytes = self.push_back
243
 
            self.push_back = None
244
 
            return bytes
 
251
        if self._push_back_buffer is not None:
 
252
            return self._get_push_back_buffer()
245
253
        return self._in.read(desired_count)
246
254
 
247
255
    def terminate_due_to_error(self):