summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyril Roelandt <cyril@redhat.com>2016-01-11 14:19:09 +0100
committerCyril Roelandt <cyril@redhat.com>2016-01-11 16:09:45 +0100
commit399aec1f81853d66c8319405c9170ac69e346e78 (patch)
tree18581ffa28443ee8cfae664f6aa1f7dccfd19805
parent434031792a6a3f2d84a95a5658d68b3b25a6f8dd (diff)
downloadglance_store-399aec1f81853d66c8319405c9170ac69e346e78.tar.gz
Swift store: do not send a 0 byte chunk
When a chunk of size 0 is added, it is immediately deleted. Swift might try to delete it before its creation is complete, though, leading to a race condition. Not sending this 0 byte chunk soves this issue. Co-Authored-By: Stuart McLaren <stuart.mclaren@hp.com> Change-Id: I2179a1e6e27a636bfca448fa18481eb11e64e6da Closes-Bug: #1518431
-rw-r--r--glance_store/_drivers/swift/store.py14
-rw-r--r--glance_store/exceptions.py4
-rw-r--r--glance_store/tests/unit/test_swift_store.py7
3 files changed, 14 insertions, 11 deletions
diff --git a/glance_store/_drivers/swift/store.py b/glance_store/_drivers/swift/store.py
index bdf4bbd..591b16d 100644
--- a/glance_store/_drivers/swift/store.py
+++ b/glance_store/_drivers/swift/store.py
@@ -551,6 +551,9 @@ class BaseStore(driver.Store):
location.container, chunk_name, reader,
content_length=content_length)
written_chunks.append(chunk_name)
+ except exceptions.ZeroSizeChunk:
+ LOG.debug('Not writing zero-length chunk')
+ break
except Exception:
# Delete orphaned segments from swift backend
with excutils.save_and_reraise_exception():
@@ -572,14 +575,6 @@ class BaseStore(driver.Store):
'chunk_etag': chunk_etag})
LOG.debug(msg)
- if bytes_read == 0:
- # Delete the last chunk, because it's of zero size.
- # This will happen if size == 0.
- LOG.debug("Deleting final zero-length chunk")
- connection.delete_object(location.container,
- chunk_name)
- break
-
chunk_id += 1
combined_chunks_size += bytes_read
@@ -960,6 +955,9 @@ class ChunkReader(object):
if i > left:
i = left
result = self.fd.read(i)
+ if len(result) == 0 and self.bytes_read == 0:
+ # fd was empty
+ raise exceptions.ZeroSizeChunk()
self.bytes_read += len(result)
self.checksum.update(result)
return result
diff --git a/glance_store/exceptions.py b/glance_store/exceptions.py
index ea7b61b..45c790d 100644
--- a/glance_store/exceptions.py
+++ b/glance_store/exceptions.py
@@ -81,6 +81,10 @@ class NotFound(GlanceStoreException):
message = _("Image %(image)s not found")
+class ZeroSizeChunk(GlanceStoreException):
+ message = _("Zero size chunk")
+
+
class UnknownScheme(GlanceStoreException):
message = _("Unknown scheme '%(scheme)s' found in URI")
diff --git a/glance_store/tests/unit/test_swift_store.py b/glance_store/tests/unit/test_swift_store.py
index a71024c..813f623 100644
--- a/glance_store/tests/unit/test_swift_store.py
+++ b/glance_store/tests/unit/test_swift_store.py
@@ -1500,10 +1500,11 @@ class TestChunkReader(base.StoreBaseTest):
bytes_read = 0
while True:
cr = swift.ChunkReader(infile, checksum, CHUNKSIZE)
- chunk = cr.read(CHUNKSIZE)
- bytes_read += len(chunk)
- if not chunk:
+ try:
+ chunk = cr.read(CHUNKSIZE)
+ except exceptions.ZeroSizeChunk:
break
+ bytes_read += len(chunk)
self.assertEqual(units.Ki, bytes_read)
data_file.close()
infile.close()