diff options
author | Valentin David <valentin.david@codethink.co.uk> | 2018-11-16 15:28:45 +0100 |
---|---|---|
committer | Valentin David <valentin.david@codethink.co.uk> | 2018-11-28 15:29:52 +0100 |
commit | 8d2946ffd3af038ee33e28c724f3662c7042c573 (patch) | |
tree | 915a160b8f1ee97e772344bf8ebe276e9466005c /buildstream | |
parent | 5ef19a0b31df84caed1e41719ef7ea5c6bd8a8bc (diff) | |
download | buildstream-8d2946ffd3af038ee33e28c724f3662c7042c573.tar.gz |
"Fallocate" object disk space to avoid getting NOSPC error when writing
This locks the temporary object file so that cleanup does not need to
be done for every write.
Diffstat (limited to 'buildstream')
-rw-r--r-- | buildstream/_artifactcache/casserver.py | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/buildstream/_artifactcache/casserver.py b/buildstream/_artifactcache/casserver.py index 56e61f915..15301cf5e 100644 --- a/buildstream/_artifactcache/casserver.py +++ b/buildstream/_artifactcache/casserver.py @@ -24,6 +24,7 @@ import signal import sys import tempfile import uuid +import errno import click import grpc @@ -190,17 +191,34 @@ class _ByteStreamServicer(bytestream_pb2_grpc.ByteStreamServicer): context.set_code(grpc.StatusCode.NOT_FOUND) return response - try: - _clean_up_cache(self.cas, client_digest.size_bytes) - except ArtifactTooLargeException as e: - context.set_code(grpc.StatusCode.RESOURCE_EXHAUSTED) - context.set_details(str(e)) - return response + while True: + if client_digest.size_bytes == 0: + break + try: + _clean_up_cache(self.cas, client_digest.size_bytes) + except ArtifactTooLargeException as e: + context.set_code(grpc.StatusCode.RESOURCE_EXHAUSTED) + context.set_details(str(e)) + return response + + try: + os.posix_fallocate(out.fileno(), 0, client_digest.size_bytes) + break + except OSError as e: + # Multiple upload can happen in the same time + if e.errno != errno.ENOSPC: + raise + elif request.resource_name: # If it is set on subsequent calls, it **must** match the value of the first request. if request.resource_name != resource_name: context.set_code(grpc.StatusCode.FAILED_PRECONDITION) return response + + if (offset + len(request.data)) > client_digest.size_bytes: + context.set_code(grpc.StatusCode.FAILED_PRECONDITION) + return response + out.write(request.data) offset += len(request.data) if request.finish_write: |