1717import org .elasticsearch .common .util .concurrent .EsExecutors ;
1818import org .elasticsearch .core .PathUtils ;
1919import org .elasticsearch .core .PathUtilsForTesting ;
20+ import org .elasticsearch .core .TimeValue ;
21+ import org .elasticsearch .core .Tuple ;
2022import org .elasticsearch .env .Environment ;
2123import org .elasticsearch .env .NodeEnvironment ;
2224import org .elasticsearch .env .TestEnvironment ;
3436import java .nio .file .attribute .FileAttributeView ;
3537import java .nio .file .attribute .FileStoreAttributeView ;
3638import java .nio .file .spi .FileSystemProvider ;
39+ import java .util .ArrayDeque ;
3740import java .util .ArrayList ;
41+ import java .util .Deque ;
3842import java .util .IdentityHashMap ;
3943import java .util .LinkedHashSet ;
4044import java .util .List ;
4145import java .util .concurrent .CountDownLatch ;
46+ import java .util .concurrent .Executor ;
4247import java .util .concurrent .TimeUnit ;
4348import java .util .concurrent .atomic .AtomicLong ;
4449
@@ -61,7 +66,7 @@ public class ThreadPoolMergeExecutorServiceDiskSpaceTests extends ESTestCase {
6166 private static String bPathPart ;
6267 private static int mergeExecutorThreadCount ;
6368 private static Settings settings ;
64- private static TestThreadPool testThreadPool ;
69+ private static CapturingThreadPool testThreadPool ;
6570 private static NodeEnvironment nodeEnvironment ;
6671
6772 @ BeforeClass
@@ -86,7 +91,7 @@ public static void installMockUsableSpaceFS() throws Exception {
8691 settingsBuilder .put (ThreadPoolMergeScheduler .USE_THREAD_POOL_MERGE_SCHEDULER_SETTING .getKey (), true );
8792 }
8893 settings = settingsBuilder .build ();
89- testThreadPool = new TestThreadPool ("test" , settings );
94+ testThreadPool = new CapturingThreadPool ("test" , settings );
9095 nodeEnvironment = new NodeEnvironment (settings , TestEnvironment .newEnvironment (settings ));
9196 }
9297
@@ -99,6 +104,21 @@ public static void removeMockUsableSpaceFS() {
99104 nodeEnvironment .close ();
100105 }
101106
107+ static class CapturingThreadPool extends TestThreadPool {
108+ final List <Tuple <TimeValue , Cancellable >> scheduledTasks = new ArrayList <>();
109+
110+ CapturingThreadPool (String name , Settings settings ) {
111+ super (name , settings );
112+ }
113+
114+ @ Override
115+ public Cancellable scheduleWithFixedDelay (Runnable command , TimeValue interval , Executor executor ) {
116+ Cancellable cancellable = super .scheduleWithFixedDelay (command , interval , executor );
117+ scheduledTasks .add (new Tuple <>(interval , cancellable ));
118+ return cancellable ;
119+ }
120+ }
121+
102122 static class TestMockUsableSpaceFileSystemProvider extends FilterFileSystemProvider {
103123
104124 TestMockUsableSpaceFileSystemProvider (FileSystem inner ) {
@@ -243,6 +263,51 @@ public void testAvailableDiskSpaceMonitorWithDefaultSettings() throws Exception
243263 }
244264 }
245265
266+ public void testDiskSpaceMonitorStartsAsDisabled () throws Exception {
267+ aFileStore .usableSpace = randomLongBetween (1L , 100L );
268+ aFileStore .totalSpace = randomLongBetween (1L , 100L );
269+ aFileStore .throwIoException = randomBoolean ();
270+ bFileStore .usableSpace = randomLongBetween (1L , 100L );
271+ bFileStore .totalSpace = randomLongBetween (1L , 100L );
272+ bFileStore .throwIoException = randomBoolean ();
273+ Settings .Builder settingsBuilder = Settings .builder ().put (settings );
274+ if (randomBoolean ()) {
275+ settingsBuilder .put (ThreadPoolMergeExecutorService .INDICES_MERGE_DISK_CHECK_INTERVAL_SETTING .getKey (), "0" );
276+ } else {
277+ settingsBuilder .put (ThreadPoolMergeExecutorService .INDICES_MERGE_DISK_CHECK_INTERVAL_SETTING .getKey (), "0s" );
278+ }
279+ Settings settings = settingsBuilder .build ();
280+ ClusterSettings clusterSettings = ClusterSettings .createBuiltInClusterSettings (settings );
281+ LinkedHashSet <ByteSizeValue > availableDiskSpaceUpdates = new LinkedHashSet <>();
282+ try (
283+ var diskSpacePeriodicMonitor = ThreadPoolMergeExecutorService .startDiskSpaceMonitoring (
284+ testThreadPool ,
285+ nodeEnvironment .dataPaths (),
286+ clusterSettings ,
287+ (availableDiskSpace ) -> {
288+ synchronized (availableDiskSpaceUpdates ) {
289+ availableDiskSpaceUpdates .add (availableDiskSpace );
290+ }
291+ }
292+ )
293+ ) {
294+ assertThat (diskSpacePeriodicMonitor .isScheduled (), is (false ));
295+ assertThat (availableDiskSpaceUpdates .size (), is (1 ));
296+ assertThat (availableDiskSpaceUpdates .getLast ().getBytes (), is (Long .MAX_VALUE ));
297+ // updating monitoring interval should enable the monitor
298+ String intervalSettingValue = randomFrom ("1s" , "123ms" , "5ns" , "2h" );
299+ clusterSettings .applySettings (
300+ Settings .builder ()
301+ .put (ThreadPoolMergeExecutorService .INDICES_MERGE_DISK_CHECK_INTERVAL_SETTING .getKey (), intervalSettingValue )
302+ .build ()
303+ );
304+ assertThat (diskSpacePeriodicMonitor .isScheduled (), is (true ));
305+ assertThat (testThreadPool .scheduledTasks .size (), is (1 ));
306+ }
307+ aFileStore .throwIoException = false ;
308+ bFileStore .throwIoException = false ;
309+ }
310+
246311 public void testAvailableDiskSpaceMonitorWhenFileSystemStatErrors () throws Exception {
247312 aFileStore .usableSpace = randomLongBetween (1L , 100L );
248313 aFileStore .totalSpace = randomLongBetween (1L , 100L );
0 commit comments