fix write race condition

This commit is contained in:
Victor Shyba 2019-02-08 02:38:27 -03:00
parent c06ec6cd69
commit 141d68a2cd
2 changed files with 9 additions and 4 deletions

View file

@ -66,7 +66,7 @@ class BlobFile:
self.verified: asyncio.Event = asyncio.Event(loop=self.loop)
self.finished_writing = asyncio.Event(loop=loop)
self.blob_write_lock = asyncio.Lock(loop=loop)
if os.path.isfile(os.path.join(blob_dir, blob_hash)):
if self.file_exists:
length = int(os.stat(os.path.join(blob_dir, blob_hash)).st_size)
self.length = length
self.verified.set()
@ -74,6 +74,10 @@ class BlobFile:
self.saved_verified_blob = False
self.blob_completed_callback = blob_completed_callback
@property
def file_exists(self):
return os.path.isfile(self.file_path)
def writer_finished(self, writer: HashBlobWriter):
def callback(finished: asyncio.Future):
try:
@ -116,7 +120,7 @@ class BlobFile:
self.verified.set()
def open_for_writing(self) -> HashBlobWriter:
if os.path.exists(self.file_path):
if self.file_exists:
raise OSError(f"File already exists '{self.file_path}'")
fut = asyncio.Future(loop=self.loop)
writer = HashBlobWriter(self.blob_hash, self.get_length, fut)

View file

@ -137,7 +137,7 @@ class BlobExchangeClientProtocol(asyncio.Protocol):
self.transport = None
async def download_blob(self, blob: 'BlobFile') -> typing.Tuple[bool, typing.Optional[asyncio.Transport]]:
if blob.get_is_verified():
if blob.get_is_verified() or blob.file_exists:
return False, self.transport
try:
self.blob, self.writer, self._blob_bytes_received = blob, blob.open_for_writing(), 0
@ -175,7 +175,8 @@ async def request_blob(loop: asyncio.BaseEventLoop, blob: 'BlobFile', address: s
Returns [<downloaded blob>, <keep connection>]
"""
if blob.get_is_verified():
if blob.get_is_verified() or blob.file_exists:
# file exists but not verified means someone is writing right now, give it time, come back later
return False, connected_transport
protocol = BlobExchangeClientProtocol(loop, blob_download_timeout)
if connected_transport and not connected_transport.is_closing():