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 | |
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.
-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: |