diff --git a/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java b/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java index f23c5aae1d1ec..df54a3c5c4f77 100644 --- a/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java +++ b/server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java @@ -728,12 +728,6 @@ protected void writeIndexGen(final RepositoryData repositoryData, final long rep final String indexBlob = INDEX_FILE_PREFIX + Long.toString(newGen); logger.debug("Repository [{}] writing new index generational blob [{}]", metadata.name(), indexBlob); writeAtomic(indexBlob, snapshotsBytes, true); - // delete the N-2 index file if it exists, keep the previous one around as a backup - if (isReadOnly() == false && newGen - 2 >= 0) { - final String oldSnapshotIndexFile = INDEX_FILE_PREFIX + Long.toString(newGen - 2); - blobContainer().deleteBlobIgnoringIfNotExists(oldSnapshotIndexFile); - } - // write the current generation to the index-latest file final BytesReference genBytes; try (BytesStreamOutput bStream = new BytesStreamOutput()) { @@ -742,6 +736,15 @@ protected void writeIndexGen(final RepositoryData repositoryData, final long rep } logger.debug("Repository [{}] updating index.latest with generation [{}]", metadata.name(), newGen); writeAtomic(INDEX_LATEST_BLOB, genBytes, false); + // delete the N-2 index file if it exists, keep the previous one around as a backup + if (newGen - 2 >= 0) { + final String oldSnapshotIndexFile = INDEX_FILE_PREFIX + Long.toString(newGen - 2); + try { + blobContainer().deleteBlobIgnoringIfNotExists(oldSnapshotIndexFile); + } catch (IOException e) { + logger.warn("Failed to clean up old index blob [{}]", oldSnapshotIndexFile); + } + } } /** @@ -995,45 +998,24 @@ protected void finalize(final List snapshots, final Map blobs, final String reason) { final String indexGeneration = Integer.toString(fileListGeneration); - final BlobStoreIndexShardSnapshots updatedSnapshots = new BlobStoreIndexShardSnapshots(snapshots); try { - // Delete temporary index files first, as we might otherwise fail in the next step creating the new index file if an earlier - // attempt to write an index file with this generation failed mid-way after creating the temporary file. - final List blobNames = - blobs.keySet().stream().filter(FsBlobContainer::isTempBlobName).collect(Collectors.toList()); - try { - blobContainer.deleteBlobsIgnoringIfNotExists(blobNames); - } catch (IOException e) { - logger.warn(() -> new ParameterizedMessage("[{}][{}] failed to delete index blobs during finalization", - snapshotId, shardId), e); - throw e; - } - - // If we deleted all snapshots, we don't need to create a new index file - if (snapshots.size() > 0) { + final List blobsToDelete; + if (snapshots.isEmpty()) { + // If we deleted all snapshots, we don't need to create a new index file and simply delete all the blobs we found + blobsToDelete = new ArrayList<>(blobs.keySet()); + } else { + final BlobStoreIndexShardSnapshots updatedSnapshots = new BlobStoreIndexShardSnapshots(snapshots); indexShardSnapshotsFormat.writeAtomic(updatedSnapshots, blobContainer, indexGeneration); + // Delete all previous index-N, data-blobs that are not referenced by the new index-N and temporary blobs + blobsToDelete = blobs.keySet().stream().filter(blob -> + blob.startsWith(SNAPSHOT_INDEX_PREFIX) + || blob.startsWith(DATA_BLOB_PREFIX) && updatedSnapshots.findNameFile(canonicalName(blob)) == null + || FsBlobContainer.isTempBlobName(blob)).collect(Collectors.toList()); } - - // Delete old index files - final List indexBlobs = - blobs.keySet().stream().filter(blob -> blob.startsWith(SNAPSHOT_INDEX_PREFIX)).collect(Collectors.toList()); - try { - blobContainer.deleteBlobsIgnoringIfNotExists(indexBlobs); - } catch (IOException e) { - logger.warn(() -> new ParameterizedMessage("[{}][{}] failed to delete index blobs during finalization", - snapshotId, shardId), e); - throw e; - } - - // Delete all blobs that don't exist in a snapshot - final List orphanedBlobs = blobs.keySet().stream() - .filter(blobName -> - blobName.startsWith(DATA_BLOB_PREFIX) && updatedSnapshots.findNameFile(canonicalName(blobName)) == null) - .collect(Collectors.toList()); try { - blobContainer.deleteBlobsIgnoringIfNotExists(orphanedBlobs); + blobContainer.deleteBlobsIgnoringIfNotExists(blobsToDelete); } catch (IOException e) { - logger.warn(() -> new ParameterizedMessage("[{}][{}] failed to delete data blobs during finalization", + logger.warn(() -> new ParameterizedMessage("[{}][{}] failed to delete blobs during finalization", snapshotId, shardId), e); } } catch (IOException e) {