Create RecoveryTarget once we reset the source

RecoveryTarget increments a reference on the store once it's
created. If we fail to return the instance from the reset method
we leak a reference causing shard locks to not be released. This
change creates the reference in the return statement to ensure no
references are leaked
This commit is contained in:
Simon Willnauer 2016-07-19 11:54:52 +02:00
parent 52b1b3e31f
commit f79fb4ada7
2 changed files with 6 additions and 5 deletions

View File

@ -85,7 +85,7 @@ public class RecoveriesCollection {
RecoveryTarget status = ref.status();
RecoveryTarget resetRecovery = status.resetRecovery();
if (onGoingRecoveries.replace(id, status, resetRecovery) == false) {
resetRecovery.cancel("replace failed");
resetRecovery.cancel("replace failed"); // this is important otherwise we leak a reference to the store
throw new IllegalStateException("failed to replace recovery target");
}
}

View File

@ -87,7 +87,7 @@ public class RecoveryTarget extends AbstractRefCounted implements RecoveryTarget
private final Map<String, String> tempFileNames = ConcurrentCollections.newConcurrentMap();
private RecoveryTarget(RecoveryTarget copyFrom) { // copy constructor
this(copyFrom.indexShard(), copyFrom.sourceNode(), copyFrom.listener, copyFrom.cancellableThreads, copyFrom.recoveryId());
this(copyFrom.indexShard, copyFrom.sourceNode, copyFrom.listener, copyFrom.cancellableThreads, copyFrom.recoveryId);
}
public RecoveryTarget(IndexShard indexShard, DiscoveryNode sourceNode, RecoveryTargetService.RecoveryListener listener) {
@ -163,17 +163,18 @@ public class RecoveryTarget extends AbstractRefCounted implements RecoveryTarget
/**
* Closes the current recovery target and returns a
* clone to reset the ongoing recovery
* clone to reset the ongoing recovery.
* Note: the returned target must be canceled, failed or finished
* in order to release all it's reference.
*/
RecoveryTarget resetRecovery() throws IOException {
ensureRefCount();
RecoveryTarget copy = new RecoveryTarget(this);
if (finished.compareAndSet(false, true)) {
// release the initial reference. recovery files will be cleaned as soon as ref count goes to zero, potentially now
decRef();
}
indexShard.performRecoveryRestart();
return copy;
return new RecoveryTarget(this);
}
/**