2929import org .elasticsearch .common .metrics .CounterMetric ;
3030import org .elasticsearch .common .settings .Settings ;
3131import org .elasticsearch .common .unit .ByteSizeValue ;
32+ import org .elasticsearch .common .unit .TimeValue ;
3233import org .elasticsearch .common .util .CombinedRateLimiter ;
3334import org .elasticsearch .index .Index ;
34- import org .elasticsearch .index .IndexSettings ;
3535import org .elasticsearch .index .engine .EngineException ;
3636import org .elasticsearch .index .shard .IndexShard ;
3737import org .elasticsearch .index .shard .IndexShardRecoveryException ;
7272import java .util .Map ;
7373import java .util .Set ;
7474import java .util .function .LongConsumer ;
75+ import java .util .function .Supplier ;
76+
7577
7678/**
7779 * This repository relies on a remote cluster for Ccr restores. It is read-only so it can only be used to
@@ -288,32 +290,33 @@ public void restoreShard(IndexShard indexShard, SnapshotId snapshotId, Version v
288290 String name = metadata .name ();
289291 try (RestoreSession restoreSession = openSession (name , remoteClient , leaderShardId , indexShard , recoveryState )) {
290292 restoreSession .restoreFiles ();
293+ updateMappings (remoteClient , leaderIndex , restoreSession .mappingVersion , client , indexShard .routingEntry ().index ());
291294 } catch (Exception e ) {
292295 throw new IndexShardRestoreFailedException (indexShard .shardId (), "failed to restore snapshot [" + snapshotId + "]" , e );
293296 }
294-
295- maybeUpdateMappings (client , remoteClient , leaderIndex , indexShard .indexSettings ());
296297 }
297298
298299 @ Override
299300 public IndexShardSnapshotStatus getShardSnapshotStatus (SnapshotId snapshotId , Version version , IndexId indexId , ShardId leaderShardId ) {
300301 throw new UnsupportedOperationException ("Unsupported for repository of type: " + TYPE );
301302 }
302303
303- private void maybeUpdateMappings (Client localClient , Client remoteClient , Index leaderIndex , IndexSettings followerIndexSettings ) {
304- ClusterStateRequest clusterStateRequest = CcrRequests .metaDataRequest (leaderIndex .getName ());
305- ClusterStateResponse clusterState = remoteClient .admin ().cluster ().state (clusterStateRequest )
306- .actionGet (ccrSettings .getRecoveryActionTimeout ());
307- IndexMetaData leaderIndexMetadata = clusterState .getState ().metaData ().getIndexSafe (leaderIndex );
308- long leaderMappingVersion = leaderIndexMetadata .getMappingVersion ();
309-
310- if (leaderMappingVersion > followerIndexSettings .getIndexMetaData ().getMappingVersion ()) {
311- Index followerIndex = followerIndexSettings .getIndex ();
312- assert leaderIndexMetadata .getMappings ().size () == 1 : "expected exactly one mapping, but got [" +
313- leaderIndexMetadata .getMappings ().size () + "]" ;
314- MappingMetaData mappingMetaData = leaderIndexMetadata .getMappings ().iterator ().next ().value ;
315- PutMappingRequest putMappingRequest = CcrRequests .putMappingRequest (followerIndex .getName (), mappingMetaData );
316- localClient .admin ().indices ().putMapping (putMappingRequest ).actionGet (ccrSettings .getRecoveryActionTimeout ());
304+ private void updateMappings (Client leaderClient , Index leaderIndex , long leaderMappingVersion ,
305+ Client followerClient , Index followerIndex ) {
306+ final PlainActionFuture <IndexMetaData > indexMetadataFuture = new PlainActionFuture <>();
307+ final long startTimeInNanos = System .nanoTime ();
308+ final Supplier <TimeValue > timeout = () -> {
309+ final long elapsedInNanos = System .nanoTime () - startTimeInNanos ;
310+ return TimeValue .timeValueNanos (ccrSettings .getRecoveryActionTimeout ().nanos () - elapsedInNanos );
311+ };
312+ CcrRequests .getIndexMetadata (leaderClient , leaderIndex , leaderMappingVersion , 0L , timeout , indexMetadataFuture );
313+ final IndexMetaData leaderIndexMetadata = indexMetadataFuture .actionGet (ccrSettings .getRecoveryActionTimeout ());
314+ assert leaderIndexMetadata .getMappings ().size () == 1 : "expected exactly one mapping, but got [" +
315+ leaderIndexMetadata .getMappings ().size () + "]" ;
316+ MappingMetaData mappingMetaData = leaderIndexMetadata .getMappings ().iterator ().next ().value ;
317+ if (mappingMetaData != null ) {
318+ final PutMappingRequest putMappingRequest = CcrRequests .putMappingRequest (followerIndex .getName (), mappingMetaData );
319+ followerClient .admin ().indices ().putMapping (putMappingRequest ).actionGet (ccrSettings .getRecoveryActionTimeout ());
317320 }
318321 }
319322
@@ -323,7 +326,7 @@ private RestoreSession openSession(String repositoryName, Client remoteClient, S
323326 PutCcrRestoreSessionAction .PutCcrRestoreSessionResponse response = remoteClient .execute (PutCcrRestoreSessionAction .INSTANCE ,
324327 new PutCcrRestoreSessionRequest (sessionUUID , leaderShardId )).actionGet (ccrSettings .getRecoveryActionTimeout ());
325328 return new RestoreSession (repositoryName , remoteClient , sessionUUID , response .getNode (), indexShard , recoveryState ,
326- response .getStoreFileMetaData (), ccrSettings , throttledTime ::inc );
329+ response .getStoreFileMetaData (), response . getMappingVersion (), ccrSettings , throttledTime ::inc );
327330 }
328331
329332 private static class RestoreSession extends FileRestoreContext implements Closeable {
@@ -334,17 +337,19 @@ private static class RestoreSession extends FileRestoreContext implements Closea
334337 private final String sessionUUID ;
335338 private final DiscoveryNode node ;
336339 private final Store .MetadataSnapshot sourceMetaData ;
340+ private final long mappingVersion ;
337341 private final CcrSettings ccrSettings ;
338342 private final LongConsumer throttleListener ;
339343
340344 RestoreSession (String repositoryName , Client remoteClient , String sessionUUID , DiscoveryNode node , IndexShard indexShard ,
341- RecoveryState recoveryState , Store .MetadataSnapshot sourceMetaData , CcrSettings ccrSettings ,
342- LongConsumer throttleListener ) {
345+ RecoveryState recoveryState , Store .MetadataSnapshot sourceMetaData , long mappingVersion ,
346+ CcrSettings ccrSettings , LongConsumer throttleListener ) {
343347 super (repositoryName , indexShard , SNAPSHOT_ID , recoveryState , BUFFER_SIZE );
344348 this .remoteClient = remoteClient ;
345349 this .sessionUUID = sessionUUID ;
346350 this .node = node ;
347351 this .sourceMetaData = sourceMetaData ;
352+ this .mappingVersion = mappingVersion ;
348353 this .ccrSettings = ccrSettings ;
349354 this .throttleListener = throttleListener ;
350355 }
0 commit comments