@@ -419,8 +419,10 @@ public void deleteSnapshot(SnapshotId snapshotId, long repositoryStateId, Action
419419 // Delete snapshot from the index file, since it is the maintainer of truth of active snapshots
420420 final RepositoryData updatedRepositoryData ;
421421 final Map <String , BlobContainer > foundIndices ;
422+ final Set <String > rootBlobs ;
422423 try {
423- final RepositoryData repositoryData = getRepositoryData ();
424+ rootBlobs = blobContainer ().listBlobs ().keySet ();
425+ final RepositoryData repositoryData = getRepositoryData (latestGeneration (rootBlobs ));
424426 updatedRepositoryData = repositoryData .removeSnapshot (snapshotId );
425427 // Cache the indices that were found before writing out the new index-N blob so that a stuck master will never
426428 // delete an index that was created by another master node after writing this index-N blob.
@@ -666,7 +668,20 @@ public void endVerification(String seed) {
666668 @ Override
667669 public RepositoryData getRepositoryData () {
668670 try {
669- final long indexGen = latestIndexBlobId ();
671+ return getRepositoryData (latestIndexBlobId ());
672+ } catch (NoSuchFileException ex ) {
673+ // repository doesn't have an index blob, its a new blank repo
674+ return RepositoryData .EMPTY ;
675+ } catch (IOException ioe ) {
676+ throw new RepositoryException (metadata .name (), "Could not determine repository generation from root blobs" , ioe );
677+ }
678+ }
679+
680+ private RepositoryData getRepositoryData (long indexGen ) {
681+ if (indexGen == RepositoryData .EMPTY_REPO_GEN ) {
682+ return RepositoryData .EMPTY ;
683+ }
684+ try {
670685 final String snapshotsIndexBlobName = INDEX_FILE_PREFIX + Long .toString (indexGen );
671686
672687 RepositoryData repositoryData ;
@@ -694,14 +709,14 @@ public boolean isReadOnly() {
694709 return readOnly ;
695710 }
696711
697- protected void writeIndexGen (final RepositoryData repositoryData , final long repositoryStateId ) throws IOException {
712+ protected void writeIndexGen (final RepositoryData repositoryData , final long expectedGen ) throws IOException {
698713 assert isReadOnly () == false ; // can not write to a read only repository
699- final long currentGen = latestIndexBlobId ();
700- if (currentGen != repositoryStateId ) {
714+ final long currentGen = repositoryData . getGenId ();
715+ if (currentGen != expectedGen ) {
701716 // the index file was updated by a concurrent operation, so we were operating on stale
702717 // repository data
703718 throw new RepositoryException (metadata .name (), "concurrent modification of the index-N file, expected current generation [" +
704- repositoryStateId + "], actual current generation [" + currentGen +
719+ expectedGen + "], actual current generation [" + currentGen +
705720 "] - possibly due to simultaneous snapshot deletion requests" );
706721 }
707722 final long newGen = currentGen + 1 ;
@@ -767,14 +782,15 @@ long readSnapshotIndexLatestBlob() throws IOException {
767782 }
768783
769784 private long listBlobsToGetLatestIndexId () throws IOException {
770- Map <String , BlobMetaData > blobs = blobContainer ().listBlobsByPrefix (INDEX_FILE_PREFIX );
785+ return latestGeneration (blobContainer ().listBlobsByPrefix (INDEX_FILE_PREFIX ).keySet ());
786+ }
787+
788+ private long latestGeneration (Collection <String > rootBlobs ) {
771789 long latest = RepositoryData .EMPTY_REPO_GEN ;
772- if (blobs .isEmpty ()) {
773- // no snapshot index blobs have been written yet
774- return latest ;
775- }
776- for (final BlobMetaData blobMetaData : blobs .values ()) {
777- final String blobName = blobMetaData .name ();
790+ for (String blobName : rootBlobs ) {
791+ if (blobName .startsWith (INDEX_FILE_PREFIX ) == false ) {
792+ continue ;
793+ }
778794 try {
779795 final long curr = Long .parseLong (blobName .substring (INDEX_FILE_PREFIX .length ()));
780796 latest = Math .max (latest , curr );
@@ -809,9 +825,9 @@ public void snapshotShard(Store store, MapperService mapperService, SnapshotId s
809825 throw new IndexShardSnapshotFailedException (shardId , "failed to list blobs" , e );
810826 }
811827
812- Tuple <BlobStoreIndexShardSnapshots , Integer > tuple = buildBlobStoreIndexShardSnapshots (blobs , shardContainer );
828+ Tuple <BlobStoreIndexShardSnapshots , Long > tuple = buildBlobStoreIndexShardSnapshots (blobs , shardContainer );
813829 BlobStoreIndexShardSnapshots snapshots = tuple .v1 ();
814- int fileListGeneration = tuple .v2 ();
830+ long fileListGeneration = tuple .v2 ();
815831
816832 if (snapshots .snapshots ().stream ().anyMatch (sf -> sf .snapshot ().equals (snapshotId .getName ()))) {
817833 throw new IndexShardSnapshotFailedException (shardId ,
@@ -1013,9 +1029,9 @@ private void deleteShardSnapshot(IndexId indexId, ShardId snapshotShardId, Snaps
10131029 throw new IndexShardSnapshotException (snapshotShardId , "Failed to list content of shard directory" , e );
10141030 }
10151031
1016- Tuple <BlobStoreIndexShardSnapshots , Integer > tuple = buildBlobStoreIndexShardSnapshots (blobs , shardContainer );
1032+ Tuple <BlobStoreIndexShardSnapshots , Long > tuple = buildBlobStoreIndexShardSnapshots (blobs , shardContainer );
10171033 BlobStoreIndexShardSnapshots snapshots = tuple .v1 ();
1018- int fileListGeneration = tuple .v2 ();
1034+ long fileListGeneration = tuple .v2 ();
10191035
10201036 try {
10211037 indexShardSnapshotFormat .delete (shardContainer , snapshotId .getUUID ());
@@ -1058,9 +1074,9 @@ private BlobStoreIndexShardSnapshot loadShardSnapshot(BlobContainer shardContain
10581074 * @param blobs list of blobs in the container
10591075 * @param reason a reason explaining why the shard index file is written
10601076 */
1061- private void finalizeShard (List <SnapshotFiles > snapshots , int fileListGeneration , Map <String , BlobMetaData > blobs ,
1077+ private void finalizeShard (List <SnapshotFiles > snapshots , long fileListGeneration , Map <String , BlobMetaData > blobs ,
10621078 String reason , BlobContainer shardContainer , ShardId shardId , SnapshotId snapshotId ) {
1063- final String indexGeneration = Integer .toString (fileListGeneration + 1 );
1079+ final String indexGeneration = Long .toString (fileListGeneration + 1 );
10641080 try {
10651081 final List <String > blobsToDelete ;
10661082 if (snapshots .isEmpty ()) {
@@ -1094,26 +1110,14 @@ private void finalizeShard(List<SnapshotFiles> snapshots, int fileListGeneration
10941110 * @param blobs list of blobs in repository
10951111 * @return tuple of BlobStoreIndexShardSnapshots and the last snapshot index generation
10961112 */
1097- private Tuple <BlobStoreIndexShardSnapshots , Integer > buildBlobStoreIndexShardSnapshots (Map <String , BlobMetaData > blobs ,
1113+ private Tuple <BlobStoreIndexShardSnapshots , Long > buildBlobStoreIndexShardSnapshots (Map <String , BlobMetaData > blobs ,
10981114 BlobContainer shardContainer ) {
1099- int latest = -1 ;
11001115 Set <String > blobKeys = blobs .keySet ();
1101- for (String name : blobKeys ) {
1102- if (name .startsWith (SNAPSHOT_INDEX_PREFIX )) {
1103- try {
1104- int gen = Integer .parseInt (name .substring (SNAPSHOT_INDEX_PREFIX .length ()));
1105- if (gen > latest ) {
1106- latest = gen ;
1107- }
1108- } catch (NumberFormatException ex ) {
1109- logger .warn ("failed to parse index file name [{}]" , name );
1110- }
1111- }
1112- }
1116+ long latest = latestGeneration (blobKeys );
11131117 if (latest >= 0 ) {
11141118 try {
11151119 final BlobStoreIndexShardSnapshots shardSnapshots =
1116- indexShardSnapshotsFormat .read (shardContainer , Integer .toString (latest ));
1120+ indexShardSnapshotsFormat .read (shardContainer , Long .toString (latest ));
11171121 return new Tuple <>(shardSnapshots , latest );
11181122 } catch (IOException e ) {
11191123 final String file = SNAPSHOT_INDEX_PREFIX + latest ;
0 commit comments