Implement more of the writing logic.

This commit is contained in:
Itamar Turner-Trauring 2022-01-14 08:34:17 -05:00
parent f5437d9be7
commit 3bed067828
3 changed files with 36 additions and 9 deletions

View File

@ -198,7 +198,7 @@ class StorageClientImmutables(object):
"/v1/immutable/{}/{}".format(_encode_si(storage_index), share_number)
)
response = yield self._client._request(
"POST",
"PATCH",
url,
upload_secret=upload_secret,
data=data,

View File

@ -219,15 +219,35 @@ class HTTPServer(object):
)
def write_share_data(self, request, authorization, storage_index, share_number):
"""Write data to an in-progress immutable upload."""
# TODO parse the content-range header to get offset for writing
# TODO basic checks on validity of offset
# TODO basic check that body isn't infinite. require content-length? if so, needs t be in protocol spec.
storage_index = si_a2b(storage_index.encode("ascii"))
content_range = request.getHeader("content-range")
if content_range is None:
offset = 0
else:
offset = int(content_range.split()[1].split("-")[0])
# TODO basic checks on validity of start, offset, and content-range in general. also of share_number.
# TODO basic check that body isn't infinite. require content-length? or maybe we should require content-range (it's optional now)? if so, needs to be rflected in protocol spec.
data = request.content.read()
# TODO write to bucket at that offset.
try:
bucket = self._uploads[storage_index].shares[share_number]
except (KeyError, IndexError):
# TODO return 404
raise
# TODO check if it conflicts with existing data (probably underlying code already handles that) if so, CONFLICT.
finished = bucket.write(offset, data)
# TODO if it finished writing altogether, 201 CREATED. Otherwise 200 OK.
# TODO if raises ConflictingWriteError, return HTTP CONFLICT code.
if finished:
request.setResponseCode(http.CREATED)
else:
request.setResponseCode(http.OK)
# TODO spec says we should return missing ranges. but client doesn't
# actually use them? So is it actually useful?
return b""
@_authorized_route(
_app,

View File

@ -13,7 +13,7 @@ if PY2:
import os, stat, struct, time
from collections_extended import RangeMap
from collections_extended import RangeMap, MappedRange
from foolscap.api import Referenceable
@ -375,7 +375,10 @@ class BucketWriter(object):
def allocated_size(self):
return self._max_size
def write(self, offset, data):
def write(self, offset, data): # type: (int, bytes) -> bool
"""
Write data at given offset, return whether the upload is complete.
"""
# Delay the timeout, since we received data:
self._timeout.reset(30 * 60)
start = self._clock.seconds()
@ -399,6 +402,10 @@ class BucketWriter(object):
self.ss.add_latency("write", self._clock.seconds() - start)
self.ss.count("write")
# Return whether the whole thing has been written.
# TODO needs property test
return self._already_written.ranges() == [MappedRange(0, self._max_size, True)]
def close(self):
precondition(not self.closed)
self._timeout.cancel()