|
|
@@ -698,12 +698,6 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
|
|
|
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()) {
|
|
|
@@ -712,6 +706,15 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
|
|
|
}
|
|
|
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);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -964,45 +967,24 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
|
|
|
final Map<String, BlobMetaData> 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<String> 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<String> 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 = List.copyOf(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<String> 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<String> 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) {
|