@@ -399,12 +399,12 @@ public void deleteSnapshot(SnapshotId snapshotId, long repositoryStateId, Action
399399 final Map <String , BlobContainer > foundIndices ;
400400 final Set <String > rootBlobs ;
401401 try {
402- final RepositoryData repositoryData = getRepositoryData ();
402+ rootBlobs = blobContainer ().listBlobs ().keySet ();
403+ final RepositoryData repositoryData = getRepositoryData (latestGeneration (rootBlobs ));
403404 updatedRepositoryData = repositoryData .removeSnapshot (snapshotId );
404405 // Cache the indices that were found before writing out the new index-N blob so that a stuck master will never
405406 // delete an index that was created by another master node after writing this index-N blob.
406407 foundIndices = blobStore ().blobContainer (basePath ().add ("indices" )).children ();
407- rootBlobs = blobContainer ().listBlobs ().keySet ();
408408 writeIndexGen (updatedRepositoryData , repositoryStateId );
409409 } catch (Exception ex ) {
410410 listener .onFailure (new RepositoryException (metadata .name (), "failed to delete snapshot [" + snapshotId + "]" , ex ));
@@ -691,7 +691,20 @@ public void endVerification(String seed) {
691691 @ Override
692692 public RepositoryData getRepositoryData () {
693693 try {
694- final long indexGen = latestIndexBlobId ();
694+ return getRepositoryData (latestIndexBlobId ());
695+ } catch (NoSuchFileException ex ) {
696+ // repository doesn't have an index blob, its a new blank repo
697+ return RepositoryData .EMPTY ;
698+ } catch (IOException ioe ) {
699+ throw new RepositoryException (metadata .name (), "Could not determine repository generation from root blobs" , ioe );
700+ }
701+ }
702+
703+ private RepositoryData getRepositoryData (long indexGen ) {
704+ if (indexGen == RepositoryData .EMPTY_REPO_GEN ) {
705+ return RepositoryData .EMPTY ;
706+ }
707+ try {
695708 final String snapshotsIndexBlobName = INDEX_FILE_PREFIX + Long .toString (indexGen );
696709
697710 RepositoryData repositoryData ;
@@ -738,14 +751,14 @@ public boolean isReadOnly() {
738751 return readOnly ;
739752 }
740753
741- protected void writeIndexGen (final RepositoryData repositoryData , final long repositoryStateId ) throws IOException {
754+ protected void writeIndexGen (final RepositoryData repositoryData , final long expectedGen ) throws IOException {
742755 assert isReadOnly () == false ; // can not write to a read only repository
743- final long currentGen = latestIndexBlobId ();
744- if (currentGen != repositoryStateId ) {
756+ final long currentGen = repositoryData . getGenId ();
757+ if (currentGen != expectedGen ) {
745758 // the index file was updated by a concurrent operation, so we were operating on stale
746759 // repository data
747760 throw new RepositoryException (metadata .name (), "concurrent modification of the index-N file, expected current generation [" +
748- repositoryStateId + "], actual current generation [" + currentGen +
761+ expectedGen + "], actual current generation [" + currentGen +
749762 "] - possibly due to simultaneous snapshot deletion requests" );
750763 }
751764 final long newGen = currentGen + 1 ;
@@ -823,14 +836,15 @@ long readSnapshotIndexLatestBlob() throws IOException {
823836 }
824837
825838 private long listBlobsToGetLatestIndexId () throws IOException {
826- Map <String , BlobMetaData > blobs = blobContainer ().listBlobsByPrefix (INDEX_FILE_PREFIX );
839+ return latestGeneration (blobContainer ().listBlobsByPrefix (INDEX_FILE_PREFIX ).keySet ());
840+ }
841+
842+ private long latestGeneration (Collection <String > rootBlobs ) {
827843 long latest = RepositoryData .EMPTY_REPO_GEN ;
828- if (blobs .isEmpty ()) {
829- // no snapshot index blobs have been written yet
830- return latest ;
831- }
832- for (final BlobMetaData blobMetaData : blobs .values ()) {
833- final String blobName = blobMetaData .name ();
844+ for (String blobName : rootBlobs ) {
845+ if (blobName .startsWith (INDEX_FILE_PREFIX ) == false ) {
846+ continue ;
847+ }
834848 try {
835849 final long curr = Long .parseLong (blobName .substring (INDEX_FILE_PREFIX .length ()));
836850 latest = Math .max (latest , curr );
@@ -865,9 +879,9 @@ public void snapshotShard(Store store, MapperService mapperService, SnapshotId s
865879 throw new IndexShardSnapshotFailedException (shardId , "failed to list blobs" , e );
866880 }
867881
868- Tuple <BlobStoreIndexShardSnapshots , Integer > tuple = buildBlobStoreIndexShardSnapshots (blobs , shardContainer );
882+ Tuple <BlobStoreIndexShardSnapshots , Long > tuple = buildBlobStoreIndexShardSnapshots (blobs , shardContainer );
869883 BlobStoreIndexShardSnapshots snapshots = tuple .v1 ();
870- int fileListGeneration = tuple .v2 ();
884+ long fileListGeneration = tuple .v2 ();
871885
872886 if (snapshots .snapshots ().stream ().anyMatch (sf -> sf .snapshot ().equals (snapshotId .getName ()))) {
873887 throw new IndexShardSnapshotFailedException (shardId ,
@@ -1069,9 +1083,9 @@ private void deleteShardSnapshot(IndexId indexId, ShardId snapshotShardId, Snaps
10691083 throw new IndexShardSnapshotException (snapshotShardId , "Failed to list content of shard directory" , e );
10701084 }
10711085
1072- Tuple <BlobStoreIndexShardSnapshots , Integer > tuple = buildBlobStoreIndexShardSnapshots (blobs , shardContainer );
1086+ Tuple <BlobStoreIndexShardSnapshots , Long > tuple = buildBlobStoreIndexShardSnapshots (blobs , shardContainer );
10731087 BlobStoreIndexShardSnapshots snapshots = tuple .v1 ();
1074- int fileListGeneration = tuple .v2 ();
1088+ long fileListGeneration = tuple .v2 ();
10751089
10761090 try {
10771091 indexShardSnapshotFormat .delete (shardContainer , snapshotId .getUUID ());
@@ -1114,9 +1128,9 @@ private BlobStoreIndexShardSnapshot loadShardSnapshot(BlobContainer shardContain
11141128 * @param blobs list of blobs in the container
11151129 * @param reason a reason explaining why the shard index file is written
11161130 */
1117- private void finalizeShard (List <SnapshotFiles > snapshots , int fileListGeneration , Map <String , BlobMetaData > blobs ,
1131+ private void finalizeShard (List <SnapshotFiles > snapshots , long fileListGeneration , Map <String , BlobMetaData > blobs ,
11181132 String reason , BlobContainer shardContainer , ShardId shardId , SnapshotId snapshotId ) {
1119- final String indexGeneration = Integer .toString (fileListGeneration + 1 );
1133+ final String indexGeneration = Long .toString (fileListGeneration + 1 );
11201134 try {
11211135 final List <String > blobsToDelete ;
11221136 if (snapshots .isEmpty ()) {
@@ -1150,26 +1164,14 @@ private void finalizeShard(List<SnapshotFiles> snapshots, int fileListGeneration
11501164 * @param blobs list of blobs in repository
11511165 * @return tuple of BlobStoreIndexShardSnapshots and the last snapshot index generation
11521166 */
1153- private Tuple <BlobStoreIndexShardSnapshots , Integer > buildBlobStoreIndexShardSnapshots (Map <String , BlobMetaData > blobs ,
1167+ private Tuple <BlobStoreIndexShardSnapshots , Long > buildBlobStoreIndexShardSnapshots (Map <String , BlobMetaData > blobs ,
11541168 BlobContainer shardContainer ) {
1155- int latest = -1 ;
11561169 Set <String > blobKeys = blobs .keySet ();
1157- for (String name : blobKeys ) {
1158- if (name .startsWith (SNAPSHOT_INDEX_PREFIX )) {
1159- try {
1160- int gen = Integer .parseInt (name .substring (SNAPSHOT_INDEX_PREFIX .length ()));
1161- if (gen > latest ) {
1162- latest = gen ;
1163- }
1164- } catch (NumberFormatException ex ) {
1165- logger .warn ("failed to parse index file name [{}]" , name );
1166- }
1167- }
1168- }
1170+ long latest = latestGeneration (blobKeys );
11691171 if (latest >= 0 ) {
11701172 try {
11711173 final BlobStoreIndexShardSnapshots shardSnapshots =
1172- indexShardSnapshotsFormat .read (shardContainer , Integer .toString (latest ));
1174+ indexShardSnapshotsFormat .read (shardContainer , Long .toString (latest ));
11731175 return new Tuple <>(shardSnapshots , latest );
11741176 } catch (IOException e ) {
11751177 final String file = SNAPSHOT_INDEX_PREFIX + latest ;
0 commit comments