3535import org .elasticsearch .common .unit .ByteSizeValue ;
3636import org .elasticsearch .common .util .concurrent .AbstractRunnable ;
3737import org .elasticsearch .common .xcontent .XContentBuilder ;
38+ import org .elasticsearch .core .internal .io .IOUtils ;
3839import org .elasticsearch .index .seqno .SequenceNumbers ;
3940import org .elasticsearch .index .translog .Translog ;
4041import org .elasticsearch .tasks .Task ;
@@ -80,48 +81,25 @@ void setChunkSize(ByteSizeValue chunkSize) { // only settable for tests
8081 }
8182
8283 public void resync (final IndexShard indexShard , final ActionListener <ResyncTask > listener ) {
83- ActionListener < ResyncTask > resyncListener = null ;
84+ Translog . Snapshot snapshot = null ;
8485 try {
8586 final long startingSeqNo = indexShard .getGlobalCheckpoint () + 1 ;
86- Translog .Snapshot snapshot = indexShard .newTranslogSnapshotFromMinSeqNo (startingSeqNo );
8787 final long maxSeqNo = indexShard .seqNoStats ().getMaxSeqNo ();
88- resyncListener = new ActionListener <ResyncTask >() {
89- @ Override
90- public void onResponse (final ResyncTask resyncTask ) {
91- try {
92- snapshot .close ();
93- listener .onResponse (resyncTask );
94- } catch (final Exception e ) {
95- onFailure (e );
96- }
97- }
98-
99- @ Override
100- public void onFailure (final Exception e ) {
101- try {
102- snapshot .close ();
103- } catch (final Exception inner ) {
104- e .addSuppressed (inner );
105- } finally {
106- listener .onFailure (e );
107- }
108- }
109- };
110- ShardId shardId = indexShard .shardId ();
111-
88+ final ShardId shardId = indexShard .shardId ();
11289 // Wrap translog snapshot to make it synchronized as it is accessed by different threads through SnapshotSender.
11390 // Even though those calls are not concurrent, snapshot.next() uses non-synchronized state and is not multi-thread-compatible
11491 // Also fail the resync early if the shard is shutting down
115- Translog .Snapshot wrappedSnapshot = new Translog .Snapshot () {
116-
92+ snapshot = indexShard .newTranslogSnapshotFromMinSeqNo (startingSeqNo );
93+ final Translog .Snapshot originalSnapshot = snapshot ;
94+ final Translog .Snapshot wrappedSnapshot = new Translog .Snapshot () {
11795 @ Override
11896 public synchronized void close () throws IOException {
119- snapshot .close ();
97+ originalSnapshot .close ();
12098 }
12199
122100 @ Override
123101 public synchronized int totalOperations () {
124- return snapshot .totalOperations ();
102+ return originalSnapshot .totalOperations ();
125103 }
126104
127105 @ Override
@@ -132,15 +110,40 @@ public synchronized Translog.Operation next() throws IOException {
132110 } else {
133111 assert state == IndexShardState .STARTED : "resync should only happen on a started shard, but state was: " + state ;
134112 }
135- return snapshot .next ();
113+ return originalSnapshot .next ();
136114 }
137115 };
116+ final ActionListener <ResyncTask > resyncListener = new ActionListener <ResyncTask >() {
117+ @ Override
118+ public void onResponse (final ResyncTask resyncTask ) {
119+ try {
120+ wrappedSnapshot .close ();
121+ listener .onResponse (resyncTask );
122+ } catch (final Exception e ) {
123+ onFailure (e );
124+ }
125+ }
126+
127+ @ Override
128+ public void onFailure (final Exception e ) {
129+ try {
130+ wrappedSnapshot .close ();
131+ } catch (final Exception inner ) {
132+ e .addSuppressed (inner );
133+ } finally {
134+ listener .onFailure (e );
135+ }
136+ }
137+ };
138+
138139 resync (shardId , indexShard .routingEntry ().allocationId ().getId (), indexShard .getPrimaryTerm (), wrappedSnapshot ,
139140 startingSeqNo , maxSeqNo , resyncListener );
140141 } catch (Exception e ) {
141- if (resyncListener != null ) {
142- resyncListener .onFailure (e );
143- } else {
142+ try {
143+ IOUtils .close (snapshot );
144+ } catch (IOException inner ) {
145+ e .addSuppressed (inner );
146+ } finally {
144147 listener .onFailure (e );
145148 }
146149 }
0 commit comments