This is an automated email from the ASF dual-hosted git repository. daim pushed a commit to branch OAK-11912 in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
commit adcba2f7ec10ebb9c72cb2436c7a31cba1df732d Author: rishabhdaim <[email protected]> AuthorDate: Tue Oct 14 10:07:10 2025 +0530 OAK-11912 : created DirectExecutorServiuce in oak-commons --- .../internal/concurrent/DirectExecutorService.java | 64 +++++++++++++++++ .../commons/internal/concurrent/ExecutorUtils.java | 6 +- .../concurrent/DirectExecutorServiceTest.java | 84 ++++++++++++++++++++++ .../internal/concurrent/ExecutorUtilsTest.java | 75 +++++++++++++++++++ 4 files changed, 228 insertions(+), 1 deletion(-) diff --git a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/internal/concurrent/DirectExecutorService.java b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/internal/concurrent/DirectExecutorService.java new file mode 100644 index 0000000000..834e5e69cc --- /dev/null +++ b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/internal/concurrent/DirectExecutorService.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.jackrabbit.oak.commons.internal.concurrent; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.concurrent.AbstractExecutorService; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.TimeUnit; + +public class DirectExecutorService extends AbstractExecutorService { + + private volatile boolean shutdown = false; + + @Override + public void shutdown() { + shutdown = true; + } + + @Override + public @NotNull List<Runnable> shutdownNow() { + shutdown = true; + return List.of(); + } + + @Override + public boolean isShutdown() { + return shutdown; + } + + @Override + public boolean isTerminated() { + return shutdown; + } + + @Override + public boolean awaitTermination(long timeout, TimeUnit unit) { + return shutdown; + } + + @Override + public void execute(Runnable command) { + if (shutdown) throw new RejectedExecutionException("Executor is shut down"); + command.run(); + } +} + diff --git a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/internal/concurrent/ExecutorUtils.java b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/internal/concurrent/ExecutorUtils.java index da71da98bc..4ef9de91e1 100644 --- a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/internal/concurrent/ExecutorUtils.java +++ b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/internal/concurrent/ExecutorUtils.java @@ -18,8 +18,8 @@ */ package org.apache.jackrabbit.oak.commons.internal.concurrent; - import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; /** * Util methods for {@link java.util.concurrent.Executor} @@ -32,4 +32,8 @@ public class ExecutorUtils { public static Executor directExecutor() { return DirectExecutor.INSTANCE; } + + public static ExecutorService newDirectExecutorService() { + return new DirectExecutorService(); + } } diff --git a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/internal/concurrent/DirectExecutorServiceTest.java b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/internal/concurrent/DirectExecutorServiceTest.java new file mode 100644 index 0000000000..890de00ddd --- /dev/null +++ b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/internal/concurrent/DirectExecutorServiceTest.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.jackrabbit.oak.commons.internal.concurrent; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.TimeUnit; + +/** + * Unit cases for DirectExecutorService + */ +public class DirectExecutorServiceTest { + + private DirectExecutorService executor; + + @Before + public void setUp() { + executor = new DirectExecutorService(); + } + + @Test + public void testRunnableRunsInCallingThread() { + final Thread[] runThread = new Thread[1]; + executor.execute(() -> runThread[0] = Thread.currentThread()); + // Should be main test thread, not a pool thread + Assert.assertEquals(Thread.currentThread(), runThread[0]); + } + + @Test + public void testCallableReturnsValue() throws Exception { + Future<String> future = executor.submit(() -> "hello"); + Assert.assertEquals("hello", future.get()); + } + + @Test + public void testShutdownBehavior() { + Assert.assertFalse(executor.isShutdown()); + executor.shutdown(); + Assert.assertTrue(executor.isShutdown()); + Assert.assertTrue(executor.isTerminated()); + } + + @Test + public void testShutdownNowBehavior() { + Assert.assertFalse(executor.isShutdown()); + executor.shutdownNow(); + Assert.assertTrue(executor.isShutdown()); + Assert.assertTrue(executor.isTerminated()); + Assert.assertEquals(0, executor.shutdownNow().size()); // It doesn't queue tasks + } + + @Test(expected = RejectedExecutionException.class) + public void testRejectsTaskAfterShutdown() { + executor.shutdown(); + executor.execute(() -> {}); + } + + @Test + public void testAwaitTerminationReturnsTrue() { + executor.shutdown(); + Assert.assertTrue(executor.awaitTermination(100, TimeUnit.MILLISECONDS)); + } + +} \ No newline at end of file diff --git a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/internal/concurrent/ExecutorUtilsTest.java b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/internal/concurrent/ExecutorUtilsTest.java new file mode 100644 index 0000000000..20b9c81b83 --- /dev/null +++ b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/internal/concurrent/ExecutorUtilsTest.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.jackrabbit.oak.commons.internal.concurrent; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +/** + * Unit cases for ExecutorUtils + */ +public class ExecutorUtilsTest { + + @Test + public void testDirectExecutorHasOnlyOneInstance() { + Executor executor = ExecutorUtils.directExecutor(); + Assert.assertSame(ExecutorUtils.directExecutor(), executor); + } + + @Test + public void testDirectExecutorRunsInCallingThread() { + Executor executor = ExecutorUtils.directExecutor(); + final Thread[] runThread = new Thread[1]; + executor.execute(() -> runThread[0] = Thread.currentThread()); + Assert.assertEquals(Thread.currentThread(), runThread[0]); + } + + + @Test + public void testDirectExecutorServiceReturnNewInstance() { + ExecutorService executorService = ExecutorUtils.newDirectExecutorService(); + Assert.assertNotSame(ExecutorUtils.newDirectExecutorService(), executorService); + } + + @Test + public void testNewDirectExecutorServiceRunsInCallingThread() { + Executor executor = ExecutorUtils.newDirectExecutorService(); + final Thread[] runThread = new Thread[1]; + executor.execute(() -> runThread[0] = Thread.currentThread()); + Assert.assertEquals(Thread.currentThread(), runThread[0]); + } + + @Test + public void testNewDirectExecutorServiceReturnsDirectExecutorService() { + Object executorService = ExecutorUtils.newDirectExecutorService(); + Assert.assertTrue(executorService instanceof DirectExecutorService); + } + + @Test + public void testNewDirectExecutorServiceCallableReturnsValue() throws Exception { + DirectExecutorService executorService = (DirectExecutorService) ExecutorUtils.newDirectExecutorService(); + Future<String> future = executorService.submit(() -> "test"); + Assert.assertEquals("test", future.get()); + } + +} \ No newline at end of file
