protected void prepareTargetForTranslog(final int totalTranslogOps) throws IOException { StopWatch stopWatch = new StopWatch().start(); logger.trace( "{} recovery [phase1] to {}: prepare remote engine for translog", request.shardId(), request.targetNode()); final long startEngineStart = stopWatch.totalTime().millis(); // Send a request preparing the new shard's translog to receive // operations. This ensures the shard engine is started and disables // garbage collection (not the JVM's GC!) of tombstone deletes cancellableThreads.executeIO( () -> recoveryTarget.prepareForTranslogOperations( totalTranslogOps, shard.segmentStats(false).getMaxUnsafeAutoIdTimestamp())); stopWatch.stop(); response.startTime = stopWatch.totalTime().millis() - startEngineStart; logger.trace( "{} recovery [phase1] to {}: remote engine start took [{}]", request.shardId(), request.targetNode(), stopWatch.totalTime()); }
/** * Perform phase2 of the recovery process * * <p>Phase2 takes a snapshot of the current translog *without* acquiring the write lock (however, * the translog snapshot is a point-in-time view of the translog). It then sends each translog * operation to the target node so it can be replayed into the new shard. * * <p>{@code InternalEngine#recover} is responsible for taking the snapshot of the translog and * releasing it once all 3 phases of recovery are complete */ @Override public void phase2(Translog.Snapshot snapshot) throws ElasticsearchException { if (shard.state() == IndexShardState.CLOSED) { throw new IndexShardClosedException(request.shardId()); } cancellableThreads.checkForCancel(); logger.trace("{} recovery [phase2] to {}: start", request.shardId(), request.targetNode()); StopWatch stopWatch = new StopWatch().start(); cancellableThreads.execute( new Interruptable() { @Override public void run() throws InterruptedException { // Send a request preparing the new shard's translog to receive // operations. This ensures the shard engine is started and disables // garbage collection (not the JVM's GC!) of tombstone deletes transportService .submitRequest( request.targetNode(), RecoveryTarget.Actions.PREPARE_TRANSLOG, new RecoveryPrepareForTranslogOperationsRequest( request.recoveryId(), request.shardId(), shard.translog().estimatedNumberOfOperations()), TransportRequestOptions.options() .withTimeout(recoverySettings.internalActionTimeout()), EmptyTransportResponseHandler.INSTANCE_SAME) .txGet(); } }); stopWatch.stop(); response.startTime = stopWatch.totalTime().millis(); logger.trace( "{} recovery [phase2] to {}: start took [{}]", request.shardId(), request.targetNode(), stopWatch.totalTime()); logger.trace( "{} recovery [phase2] to {}: updating current mapping to master", request.shardId(), request.targetNode()); // Ensure that the mappings are synced with the master node updateMappingOnMaster(); logger.trace( "{} recovery [phase2] to {}: sending transaction log operations", request.shardId(), request.targetNode()); stopWatch = new StopWatch().start(); // Send all the snapshot's translog operations to the target int totalOperations = sendSnapshot(snapshot); stopWatch.stop(); logger.trace( "{} recovery [phase2] to {}: took [{}]", request.shardId(), request.targetNode(), stopWatch.totalTime()); response.phase2Time = stopWatch.totalTime().millis(); response.phase2Operations = totalOperations; }