3636import java .util .Collection ;
3737import java .util .Collections ;
3838import java .util .HashMap ;
39- import java .util .LinkedHashSet ;
39+ import java .util .HashSet ;
4040import java .util .List ;
4141import java .util .Map ;
4242import java .util .Objects ;
43- import java .util .Set ;
4443import java .util .function .Function ;
4544import java .util .stream .Collectors ;
4645
@@ -90,7 +89,7 @@ public final class RepositoryData {
9089 /**
9190 * The snapshots that each index belongs to.
9291 */
93- private final Map <IndexId , Set <SnapshotId >> indexSnapshots ;
92+ private final Map <IndexId , List <SnapshotId >> indexSnapshots ;
9493
9594 private final Map <String , Version > snapshotVersions ;
9695
@@ -100,7 +99,7 @@ public final class RepositoryData {
10099 private final ShardGenerations shardGenerations ;
101100
102101 public RepositoryData (long genId , Map <String , SnapshotId > snapshotIds , Map <String , SnapshotState > snapshotStates ,
103- Map <String , Version > snapshotVersions , Map <IndexId , Set <SnapshotId >> indexSnapshots ,
102+ Map <String , Version > snapshotVersions , Map <IndexId , List <SnapshotId >> indexSnapshots ,
104103 ShardGenerations shardGenerations ) {
105104 this .genId = genId ;
106105 this .snapshotIds = Collections .unmodifiableMap (snapshotIds );
@@ -112,6 +111,8 @@ public RepositoryData(long genId, Map<String, SnapshotId> snapshotIds, Map<Strin
112111 this .snapshotVersions = snapshotVersions ;
113112 assert indices .values ().containsAll (shardGenerations .indices ()) : "ShardGenerations contained indices "
114113 + shardGenerations .indices () + " but snapshots only reference indices " + indices .values ();
114+ assert indexSnapshots .values ().stream ().noneMatch (snapshotIdList -> new HashSet <>(snapshotIdList ).size () != snapshotIdList .size ()) :
115+ "Found duplicate snapshot ids per index in [" + indexSnapshots + "]" ;
115116 }
116117
117118 protected RepositoryData copy () {
@@ -213,9 +214,17 @@ public RepositoryData addSnapshot(final SnapshotId snapshotId,
213214 newSnapshotStates .put (snapshotId .getUUID (), snapshotState );
214215 Map <String , Version > newSnapshotVersions = new HashMap <>(snapshotVersions );
215216 newSnapshotVersions .put (snapshotId .getUUID (), version );
216- Map <IndexId , Set <SnapshotId >> allIndexSnapshots = new HashMap <>(indexSnapshots );
217+ Map <IndexId , List <SnapshotId >> allIndexSnapshots = new HashMap <>(indexSnapshots );
217218 for (final IndexId indexId : shardGenerations .indices ()) {
218- allIndexSnapshots .computeIfAbsent (indexId , k -> new LinkedHashSet <>()).add (snapshotId );
219+ final List <SnapshotId > snapshotIds = allIndexSnapshots .get (indexId );
220+ if (snapshotIds == null ) {
221+ allIndexSnapshots .put (indexId , Collections .singletonList (snapshotId ));
222+ } else {
223+ final List <SnapshotId > copy = new ArrayList <>(snapshotIds .size () + 1 );
224+ copy .addAll (snapshotIds );
225+ copy .add (snapshotId );
226+ allIndexSnapshots .put (indexId , Collections .unmodifiableList (copy ));
227+ }
219228 }
220229 return new RepositoryData (genId , snapshots , newSnapshotStates , newSnapshotVersions , allIndexSnapshots ,
221230 ShardGenerations .builder ().putAll (this .shardGenerations ).putAll (shardGenerations ).build ());
@@ -253,23 +262,25 @@ public RepositoryData removeSnapshot(final SnapshotId snapshotId, final ShardGen
253262 newSnapshotStates .remove (snapshotId .getUUID ());
254263 final Map <String , Version > newSnapshotVersions = new HashMap <>(snapshotVersions );
255264 newSnapshotVersions .remove (snapshotId .getUUID ());
256- Map <IndexId , Set <SnapshotId >> indexSnapshots = new HashMap <>();
265+ Map <IndexId , List <SnapshotId >> indexSnapshots = new HashMap <>();
257266 for (final IndexId indexId : indices .values ()) {
258- Set <SnapshotId > set ;
259- Set <SnapshotId > snapshotIds = this .indexSnapshots .get (indexId );
267+ List <SnapshotId > remaining ;
268+ List <SnapshotId > snapshotIds = this .indexSnapshots .get (indexId );
260269 assert snapshotIds != null ;
261- if (snapshotIds .contains (snapshotId )) {
270+ final int listIndex = snapshotIds .indexOf (snapshotId );
271+ if (listIndex > -1 ) {
262272 if (snapshotIds .size () == 1 ) {
263273 // removing the snapshot will mean no more snapshots
264274 // have this index, so just skip over it
265275 continue ;
266276 }
267- set = new LinkedHashSet <>(snapshotIds );
268- set .remove (snapshotId );
277+ remaining = new ArrayList <>(snapshotIds );
278+ remaining .remove (listIndex );
279+ remaining = Collections .unmodifiableList (remaining );
269280 } else {
270- set = snapshotIds ;
281+ remaining = snapshotIds ;
271282 }
272- indexSnapshots .put (indexId , set );
283+ indexSnapshots .put (indexId , remaining );
273284 }
274285
275286 return new RepositoryData (genId , newSnapshotIds , newSnapshotStates , newSnapshotVersions , indexSnapshots ,
@@ -281,8 +292,8 @@ public RepositoryData removeSnapshot(final SnapshotId snapshotId, final ShardGen
281292 /**
282293 * Returns an immutable collection of the snapshot ids for the snapshots that contain the given index.
283294 */
284- public Set <SnapshotId > getSnapshots (final IndexId indexId ) {
285- Set <SnapshotId > snapshotIds = indexSnapshots .get (indexId );
295+ public List <SnapshotId > getSnapshots (final IndexId indexId ) {
296+ List <SnapshotId > snapshotIds = indexSnapshots .get (indexId );
286297 if (snapshotIds == null ) {
287298 throw new IllegalArgumentException ("unknown snapshot index " + indexId );
288299 }
@@ -384,7 +395,7 @@ public XContentBuilder snapshotsToXContent(final XContentBuilder builder, final
384395 builder .startObject (indexId .getName ());
385396 builder .field (INDEX_ID , indexId .getId ());
386397 builder .startArray (SNAPSHOTS );
387- Set <SnapshotId > snapshotIds = indexSnapshots .get (indexId );
398+ List <SnapshotId > snapshotIds = indexSnapshots .get (indexId );
388399 assert snapshotIds != null ;
389400 for (final SnapshotId snapshotId : snapshotIds ) {
390401 builder .value (snapshotId .getUUID ());
@@ -415,7 +426,7 @@ public static RepositoryData snapshotsFromXContent(final XContentParser parser,
415426 final Map <String , SnapshotId > snapshots = new HashMap <>();
416427 final Map <String , SnapshotState > snapshotStates = new HashMap <>();
417428 final Map <String , Version > snapshotVersions = new HashMap <>();
418- final Map <IndexId , Set <SnapshotId >> indexSnapshots = new HashMap <>();
429+ final Map <IndexId , List <SnapshotId >> indexSnapshots = new HashMap <>();
419430 final ShardGenerations .Builder shardGenerations = ShardGenerations .builder ();
420431
421432 if (parser .nextToken () == XContentParser .Token .START_OBJECT ) {
@@ -459,7 +470,7 @@ public static RepositoryData snapshotsFromXContent(final XContentParser parser,
459470 }
460471 while (parser .nextToken () != XContentParser .Token .END_OBJECT ) {
461472 final String indexName = parser .currentName ();
462- final Set <SnapshotId > snapshotIds = new LinkedHashSet <>();
473+ final List <SnapshotId > snapshotIds = new ArrayList <>();
463474 final List <String > gens = new ArrayList <>();
464475
465476 IndexId indexId = null ;
@@ -513,7 +524,7 @@ public static RepositoryData snapshotsFromXContent(final XContentParser parser,
513524 }
514525 }
515526 assert indexId != null ;
516- indexSnapshots .put (indexId , snapshotIds );
527+ indexSnapshots .put (indexId , Collections . unmodifiableList ( snapshotIds ) );
517528 for (int i = 0 ; i < gens .size (); i ++) {
518529 shardGenerations .put (indexId , i , gens .get (i ));
519530 }
0 commit comments