Basic mutable read support.

This commit is contained in:
Itamar Turner-Trauring 2022-04-19 15:07:57 -04:00
parent f5c4513cd3
commit 21c3c50e37
2 changed files with 49 additions and 7 deletions

View File

@ -601,6 +601,49 @@ class HTTPServer(object):
)
return self._send_encoded(request, {"success": success, "data": read_data})
@_authorized_route(
_app,
set(),
"/v1/mutable/<storage_index:storage_index>/<int(signed=False):share_number>",
methods=["GET"],
)
def read_mutable_chunk(self, request, authorization, storage_index, share_number):
"""Read a chunk from a mutable."""
if request.getHeader("range") is None:
# TODO in follow-up ticket
raise NotImplementedError()
# TODO reduce duplication with immutable reads?
# TODO unit tests, perhaps shared if possible
range_header = parse_range_header(request.getHeader("range"))
if (
range_header is None
or range_header.units != "bytes"
or len(range_header.ranges) > 1 # more than one range
or range_header.ranges[0][1] is None # range without end
):
request.setResponseCode(http.REQUESTED_RANGE_NOT_SATISFIABLE)
return b""
offset, end = range_header.ranges[0]
# TODO limit memory usage
# https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3872
data = self._storage_server.slot_readv(
storage_index, [share_number], [(offset, end - offset)]
)[share_number][0]
# TODO reduce duplication?
request.setResponseCode(http.PARTIAL_CONTENT)
if len(data):
# For empty bodies the content-range header makes no sense since
# the end of the range is inclusive.
request.setHeader(
"content-range",
ContentRange("bytes", offset, offset + len(data)).to_header(),
)
return data
@implementer(IStreamServerEndpoint)
@attr.s

View File

@ -1195,18 +1195,17 @@ class _HTTPStorageServer(object):
def slot_readv(self, storage_index, shares, readv):
mutable_client = StorageClientMutables(self._http_client)
reads = {}
# TODO if shares list is empty, that means list all shares, so we need
# to do a query to get that.
assert shares # TODO replace with call to list shares
for share_number in shares:
share_reads = reads[share_number] = []
for (offset, length) in readv:
d = mutable_client.read_share_chunk(
r = yield mutable_client.read_share_chunk(
storage_index, share_number, offset, length
)
share_reads.append(d)
result = {
share_number: [(yield d) for d in share_reads]
for (share_number, reads) in reads.items()
}
defer.returnValue(result)
share_reads.append(r)
defer.returnValue(reads)
@defer.inlineCallbacks
def slot_testv_and_readv_and_writev(