74
75
return urllib2.Request.get_method(self)
77
def get_url(url, method=None):
78
def get_url(url, method=None, ranges=None):
79
mutter("get_url %s", url)
84
mutter("get_url %s [%s]", url, rangestring)
80
85
manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
81
86
url = extract_auth(url, manager)
82
87
auth_handler = urllib2.HTTPBasicAuthHandler(manager)
191
198
raise TransportError(orig_error=e)
193
def get(self, relpath, decode=False):
194
"""Get the file at the given relative path.
196
:param relpath: The relative path to the file
200
def _get(self, relpath, decode=False, ranges=None):
200
203
path = self.abspath(relpath)
204
return get_url(path, ranges=ranges)
202
205
except urllib2.HTTPError, e:
203
206
mutter('url error code: %s for has url: %r', e.code, path)
204
207
if e.code == 404:
214
217
% (self.abspath(relpath), str(e)),
220
def get(self, relpath, decode=False):
221
"""Get the file at the given relative path.
223
:param relpath: The relative path to the file
225
return self._get(relpath, decode=decode)
227
def readv(self, relpath, offsets):
228
"""Get parts of the file at the given relative path.
230
:offsets: A list of (offset, size) tuples.
231
:return: A list or generator of (offset, data) tuples
233
# this is not quite regular enough to have a single driver routine and
234
# helper method in Transport.
235
def do_combined_read(combined_offsets):
236
# read one coalesced block
238
for offset, size in combined_offsets:
240
mutter('readv coalesced %d reads.', len(combined_offsets))
241
offset = combined_offsets[0][0]
242
ranges = 'bytes=%d-%d' % (offset, offset + total_size - 1)
243
response = self._get(relpath, ranges=ranges)
244
if response.code == 206:
245
for off, size in combined_offsets:
246
yield off, response.read(size)
247
elif response.code == 200:
248
data = response.read(offset + total_size)[offset:offset + total_size]
250
for offset, size in combined_offsets:
251
yield offset, data[pos:pos + size]
257
pending_offsets = deque(offsets)
258
combined_offsets = []
259
while len(pending_offsets):
260
offset, size = pending_offsets.popleft()
261
if not combined_offsets:
262
combined_offsets = [[offset, size]]
264
if (len (combined_offsets) < 50 and
265
combined_offsets[-1][0] + combined_offsets[-1][1] == offset):
267
combined_offsets.append([offset, size])
269
# incompatible, or over the threshold issue a read and yield
270
pending_offsets.appendleft((offset, size))
271
for result in do_combined_read(combined_offsets):
273
combined_offsets = []
274
# whatever is left is a single coalesced request
275
if len(combined_offsets):
276
for result in do_combined_read(combined_offsets):
217
279
def put(self, relpath, f, mode=None):
218
280
"""Copy the file-like or string object into the location.