mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-02-02 01:08:20 +00:00
Implement more of the writing logic.
This commit is contained in:
parent
f5437d9be7
commit
3bed067828
@ -198,7 +198,7 @@ class StorageClientImmutables(object):
|
|||||||
"/v1/immutable/{}/{}".format(_encode_si(storage_index), share_number)
|
"/v1/immutable/{}/{}".format(_encode_si(storage_index), share_number)
|
||||||
)
|
)
|
||||||
response = yield self._client._request(
|
response = yield self._client._request(
|
||||||
"POST",
|
"PATCH",
|
||||||
url,
|
url,
|
||||||
upload_secret=upload_secret,
|
upload_secret=upload_secret,
|
||||||
data=data,
|
data=data,
|
||||||
|
@ -219,15 +219,35 @@ class HTTPServer(object):
|
|||||||
)
|
)
|
||||||
def write_share_data(self, request, authorization, storage_index, share_number):
|
def write_share_data(self, request, authorization, storage_index, share_number):
|
||||||
"""Write data to an in-progress immutable upload."""
|
"""Write data to an in-progress immutable upload."""
|
||||||
# TODO parse the content-range header to get offset for writing
|
storage_index = si_a2b(storage_index.encode("ascii"))
|
||||||
# TODO basic checks on validity of offset
|
content_range = request.getHeader("content-range")
|
||||||
# TODO basic check that body isn't infinite. require content-length? if so, needs t be in protocol spec.
|
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()
|
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(
|
@_authorized_route(
|
||||||
_app,
|
_app,
|
||||||
|
@ -13,7 +13,7 @@ if PY2:
|
|||||||
|
|
||||||
import os, stat, struct, time
|
import os, stat, struct, time
|
||||||
|
|
||||||
from collections_extended import RangeMap
|
from collections_extended import RangeMap, MappedRange
|
||||||
|
|
||||||
from foolscap.api import Referenceable
|
from foolscap.api import Referenceable
|
||||||
|
|
||||||
@ -375,7 +375,10 @@ class BucketWriter(object):
|
|||||||
def allocated_size(self):
|
def allocated_size(self):
|
||||||
return self._max_size
|
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:
|
# Delay the timeout, since we received data:
|
||||||
self._timeout.reset(30 * 60)
|
self._timeout.reset(30 * 60)
|
||||||
start = self._clock.seconds()
|
start = self._clock.seconds()
|
||||||
@ -399,6 +402,10 @@ class BucketWriter(object):
|
|||||||
self.ss.add_latency("write", self._clock.seconds() - start)
|
self.ss.add_latency("write", self._clock.seconds() - start)
|
||||||
self.ss.count("write")
|
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):
|
def close(self):
|
||||||
precondition(not self.closed)
|
precondition(not self.closed)
|
||||||
self._timeout.cancel()
|
self._timeout.cancel()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user