~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/medium.py

  • Committer: Aaron Bentley
  • Date: 2008-04-24 04:58:42 UTC
  • mfrom: (3377 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3380.
  • Revision ID: aaron@aaronbentley.com-20080424045842-0cajl9v6s4u52kaw
Merge 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
63
    def __init__(self, backing_transport, root_client_path='/'):
64
69
        self.backing_transport = backing_transport
65
70
        self.root_client_path = root_client_path
66
71
        self.finished = False
 
72
        self._push_back_buffer = None
 
73
 
 
74
    def _push_back(self, bytes):
 
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,))
 
83
        if bytes == '':
 
84
            return
 
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
67
94
 
68
95
    def serve(self):
69
96
        """Serve requests until the client disconnects."""
130
157
 
131
158
        :returns: a string of bytes ending in a newline (byte 0x0A).
132
159
        """
133
 
        # XXX: this duplicates SmartClientRequestProtocolOne._recv_tuple
134
 
        line = ''
135
 
        while not line or line[-1] != '\n':
136
 
            new_char = self._get_bytes(1)
137
 
            line += new_char
138
 
            if new_char == '':
 
160
        newline_pos = -1
 
161
        bytes = ''
 
162
        while newline_pos == -1:
 
163
            new_bytes = self._get_bytes(1)
 
164
            bytes += new_bytes
 
165
            if new_bytes == '':
139
166
                # Ran out of bytes before receiving a complete line.
140
 
                break
 
167
                return bytes
 
168
            newline_pos = bytes.find('\n')
 
169
        line = bytes[:newline_pos+1]
 
170
        self._push_back(bytes[newline_pos+1:])
141
171
        return line
142
 
 
 
172
 
143
173
 
144
174
class SmartServerSocketStreamMedium(SmartServerStreamMedium):
145
175
 
151
181
        """
152
182
        SmartServerStreamMedium.__init__(
153
183
            self, backing_transport, root_client_path=root_client_path)
154
 
        self.push_back = ''
155
184
        sock.setblocking(True)
156
185
        self.socket = sock
157
186
 
158
187
    def _serve_one_request_unguarded(self, protocol):
159
188
        while protocol.next_read_size():
160
 
            if self.push_back:
161
 
                protocol.accept_bytes(self.push_back)
162
 
                self.push_back = ''
163
 
            else:
164
 
                bytes = self._get_bytes(4096)
165
 
                if bytes == '':
166
 
                    self.finished = True
167
 
                    return
168
 
                protocol.accept_bytes(bytes)
 
189
            bytes = self._get_bytes(4096)
 
190
            if bytes == '':
 
191
                self.finished = True
 
192
                return
 
193
            protocol.accept_bytes(bytes)
169
194
        
170
 
        self.push_back = protocol.excess_buffer
 
195
        self._push_back(protocol.excess_buffer)
171
196
 
172
197
    def _get_bytes(self, desired_count):
 
198
        if self._push_back_buffer is not None:
 
199
            return self._get_push_back_buffer()
173
200
        # We ignore the desired_count because on sockets it's more efficient to
174
201
        # read 4k at a time.
175
202
        return self.socket.recv(4096)
221
248
            protocol.accept_bytes(bytes)
222
249
 
223
250
    def _get_bytes(self, desired_count):
 
251
        if self._push_back_buffer is not None:
 
252
            return self._get_push_back_buffer()
224
253
        return self._in.read(desired_count)
225
254
 
226
255
    def terminate_due_to_error(self):