Skip to content

Commit 9c9a904

Browse files
author
Ali Beyad
committed
Ensures pending index-* blobs are deleted when snapshotting. The
index-* blobs are generational files that maintain the snapshots in the repository. To write these atomically, we first write a `pending-index-*` blob, then move it to `index-*`, which also deletes `pending-index-*` in case its not a file-system level move (e.g. S3 repositories) . For example, to write the 5th generation of the index blob for the repository, we would first write the bytes to `pending-index-5` and then move `pending-index-5` to `index-5`. It is possible that we fail after writing `pending-index-5`, but before moving it to `index-5` or deleting `pending-index-5`. In this case, we will have a dangling `pending-index-5` blob laying around. Since snapshot elastic#5 would have failed, the next snapshot assumes a generation number of 5, so it tries to write to `index-5`, which first tries to write to `pending-index-5` before moving the blob to `index-5`. Since `pending-index-5` is leftover from the previous failure, the snapshot fails as it cannot overwrite this blob. This commit solves the problem by first, adding a UUID to the `pending-index-*` blobs, and secondly, strengthen the logic around failure to write the `index-*` generational blob to ensure pending files are deleted on cleanup. Closes elastic#21462
1 parent b43ed88 commit 9c9a904

File tree

1 file changed

+13
-6
lines changed

1 file changed

+13
-6
lines changed

core/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -867,16 +867,23 @@ private long listBlobsToGetLatestIndexId() throws IOException {
867867
}
868868

869869
private void writeAtomic(final String blobName, final BytesReference bytesRef) throws IOException {
870-
final String tempBlobName = "pending-" + blobName;
870+
final String tempBlobName = "pending-" + UUIDs.randomBase64UUID() + "-" + blobName;
871871
try (InputStream stream = bytesRef.streamInput()) {
872872
snapshotsBlobContainer.writeBlob(tempBlobName, stream, bytesRef.length());
873-
}
874-
try {
875873
snapshotsBlobContainer.move(tempBlobName, blobName);
876874
} catch (IOException ex) {
877-
// Move failed - try cleaning up
878-
snapshotsBlobContainer.deleteBlob(tempBlobName);
879-
throw ex;
875+
IOException exceptionToThrow = ex;
876+
try {
877+
snapshotsBlobContainer.deleteBlob(tempBlobName);
878+
} catch (NoSuchFileException e) {
879+
// the temp file does not exist, so writeBlob probably failed above,
880+
// exceptionToThrow will capture this and be thrown at the end
881+
} catch (IOException e) {
882+
if (exceptionToThrow == null) {
883+
exceptionToThrow = e;
884+
}
885+
}
886+
throw exceptionToThrow;
880887
}
881888
}
882889

0 commit comments

Comments
 (0)