@@ -199,6 +199,9 @@ public class IndexService extends AbstractIndexComponent implements IndicesClust
199
199
private final CompositeIndexSettings compositeIndexSettings ;
200
200
private final Consumer <IndexShard > replicator ;
201
201
private final Function <ShardId , ReplicationStats > segmentReplicationStatsProvider ;
202
+ private final Object refreshMutex = new Object ();
203
+ private volatile TimeValue refreshInterval ;
204
+ private volatile boolean shardLevelRefreshEnabled ;
202
205
203
206
public IndexService (
204
207
IndexSettings indexSettings ,
@@ -234,6 +237,7 @@ public IndexService(
234
237
BiFunction <IndexSettings , ShardRouting , TranslogFactory > translogFactorySupplier ,
235
238
Supplier <TimeValue > clusterDefaultRefreshIntervalSupplier ,
236
239
Supplier <Boolean > fixedRefreshIntervalSchedulingEnabled ,
240
+ boolean shardLevelRefreshEnabled ,
237
241
RecoverySettings recoverySettings ,
238
242
RemoteStoreSettings remoteStoreSettings ,
239
243
FileCache fileCache ,
@@ -310,8 +314,9 @@ public IndexService(
310
314
this .indexingOperationListeners = Collections .unmodifiableList (indexingOperationListeners );
311
315
this .clusterDefaultRefreshIntervalSupplier = clusterDefaultRefreshIntervalSupplier ;
312
316
this .fixedRefreshIntervalSchedulingEnabled = fixedRefreshIntervalSchedulingEnabled ;
317
+ this .shardLevelRefreshEnabled = shardLevelRefreshEnabled ;
318
+ this .refreshInterval = getRefreshInterval ();
313
319
// kick off async ops for the first shard in this index
314
- this .refreshTask = new AsyncRefreshTask (this );
315
320
this .trimTranslogTask = new AsyncTrimTranslogTask (this );
316
321
// disable these checks for ingestion source engine
317
322
if (!indexSettings .getIndexMetadata ().useIngestionSource ()) {
@@ -329,6 +334,10 @@ public IndexService(
329
334
this .replicator = replicator ;
330
335
this .segmentReplicationStatsProvider = segmentReplicationStatsProvider ;
331
336
updateFsyncTaskIfNecessary ();
337
+ if (shardLevelRefreshEnabled == false ) {
338
+ logger .debug ("shard level refresh is disabled for index [{}]" , indexSettings .getIndex ().getName ());
339
+ startIndexLevelRefreshTask ();
340
+ }
332
341
}
333
342
334
343
public IndexService (
@@ -365,6 +374,7 @@ public IndexService(
365
374
BiFunction <IndexSettings , ShardRouting , TranslogFactory > translogFactorySupplier ,
366
375
Supplier <TimeValue > clusterDefaultRefreshIntervalSupplier ,
367
376
Supplier <Boolean > fixedRefreshIntervalSchedulingEnabled ,
377
+ boolean shardLevelRefreshEnabled ,
368
378
RecoverySettings recoverySettings ,
369
379
RemoteStoreSettings remoteStoreSettings
370
380
) {
@@ -402,6 +412,7 @@ public IndexService(
402
412
translogFactorySupplier ,
403
413
clusterDefaultRefreshIntervalSupplier ,
404
414
fixedRefreshIntervalSchedulingEnabled ,
415
+ shardLevelRefreshEnabled ,
405
416
recoverySettings ,
406
417
remoteStoreSettings ,
407
418
null ,
@@ -704,7 +715,10 @@ protected void closeInternal() {
704
715
remoteStoreSettings ,
705
716
seedRemote ,
706
717
discoveryNodes ,
707
- segmentReplicationStatsProvider
718
+ segmentReplicationStatsProvider ,
719
+ shardLevelRefreshEnabled ,
720
+ fixedRefreshIntervalSchedulingEnabled ,
721
+ this ::getRefreshInterval
708
722
);
709
723
eventListener .indexShardStateChanged (indexShard , null , indexShard .state (), "shard created" );
710
724
eventListener .afterIndexShardCreated (indexShard );
@@ -1133,9 +1147,10 @@ private void updateReplicationTask() {
1133
1147
* 2. {@code index.refresh_interval} index setting changes.
1134
1148
*/
1135
1149
public void onRefreshIntervalChange () {
1136
- if (refreshTask . getInterval () .equals (getRefreshInterval ())) {
1150
+ if (refreshInterval .equals (getRefreshInterval ())) {
1137
1151
return ;
1138
1152
}
1153
+ refreshInterval = getRefreshInterval ();
1139
1154
// once we change the refresh interval we schedule yet another refresh
1140
1155
// to ensure we are in a clean and predictable state.
1141
1156
// it doesn't matter if we move from or to <code>-1</code> in both cases we want
@@ -1177,10 +1192,20 @@ private void updateFsyncTaskIfNecessary() {
1177
1192
}
1178
1193
1179
1194
private void rescheduleRefreshTasks () {
1180
- try {
1181
- refreshTask .close ();
1182
- } finally {
1183
- refreshTask = new AsyncRefreshTask (this );
1195
+ synchronized (refreshMutex ) {
1196
+ if (shardLevelRefreshEnabled ) {
1197
+ try {
1198
+ stopShardLevelRefreshTasks ();
1199
+ } finally {
1200
+ startShardLevelRefreshTasks ();
1201
+ }
1202
+ } else {
1203
+ try {
1204
+ stopIndexLevelRefreshTask ();
1205
+ } finally {
1206
+ startIndexLevelRefreshTask ();
1207
+ }
1208
+ }
1184
1209
}
1185
1210
}
1186
1211
@@ -1304,7 +1329,7 @@ private void sync(final Consumer<IndexShard> sync, final String source) {
1304
1329
* Gets the refresh interval seen by the index service. Index setting overrides takes the highest precedence.
1305
1330
* @return the refresh interval.
1306
1331
*/
1307
- private TimeValue getRefreshInterval () {
1332
+ public TimeValue getRefreshInterval () {
1308
1333
if (getIndexSettings ().isExplicitRefresh ()) {
1309
1334
return getIndexSettings ().getRefreshInterval ();
1310
1335
}
@@ -1584,4 +1609,60 @@ public boolean clearCaches(boolean queryCache, boolean fieldDataCache, String...
1584
1609
return clearedAtLeastOne ;
1585
1610
}
1586
1611
1612
+ /**
1613
+ * This method is called when the refresh level is changed from index level to shard level or vice versa.
1614
+ */
1615
+ public void onRefreshLevelChange (boolean newShardLevelRefreshVal ) {
1616
+ synchronized (refreshMutex ) {
1617
+ if (this .shardLevelRefreshEnabled != newShardLevelRefreshVal ) {
1618
+ boolean prevShardLevelRefreshVal = this .shardLevelRefreshEnabled ;
1619
+ this .shardLevelRefreshEnabled = newShardLevelRefreshVal ;
1620
+ // The refresh mode has changed from index level to shard level
1621
+ logger .info ("refresh tasks rescheduled oldVal={} newVal={}" , prevShardLevelRefreshVal , newShardLevelRefreshVal );
1622
+ if (newShardLevelRefreshVal ) {
1623
+ try {
1624
+ stopIndexLevelRefreshTask ();
1625
+ } finally {
1626
+ startShardLevelRefreshTasks ();
1627
+ }
1628
+ } else {
1629
+ try {
1630
+ stopShardLevelRefreshTasks ();
1631
+ } finally {
1632
+ startIndexLevelRefreshTask ();
1633
+ }
1634
+ }
1635
+ }
1636
+ }
1637
+ }
1638
+
1639
+ private void stopIndexLevelRefreshTask () {
1640
+ // The refresh task is expected to be non-null at this point.
1641
+ assert Objects .nonNull (refreshTask );
1642
+ refreshTask .close ();
1643
+ refreshTask = null ;
1644
+ }
1645
+
1646
+ private void startShardLevelRefreshTasks () {
1647
+ for (IndexShard shard : this .shards .values ()) {
1648
+ shard .startRefreshTask ();
1649
+ }
1650
+ }
1651
+
1652
+ private void stopShardLevelRefreshTasks () {
1653
+ for (IndexShard shard : this .shards .values ()) {
1654
+ shard .stopRefreshTask ();
1655
+ }
1656
+ }
1657
+
1658
+ private void startIndexLevelRefreshTask () {
1659
+ // The refresh task is expected to be null at this point.
1660
+ assert Objects .isNull (refreshTask );
1661
+ refreshTask = new AsyncRefreshTask (this );
1662
+ }
1663
+
1664
+ // Visible for testing
1665
+ boolean isShardLevelRefreshEnabled () {
1666
+ return shardLevelRefreshEnabled ;
1667
+ }
1587
1668
}
0 commit comments