|
@@ -37,11 +37,13 @@ import java.io.IOException;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Collections;
|
|
|
+import java.util.ConcurrentModificationException;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.concurrent.ConcurrentMap;
|
|
|
+import java.util.concurrent.CyclicBarrier;
|
|
|
|
|
|
import org.apache.commons.logging.Log;
|
|
|
import org.apache.commons.logging.LogFactory;
|
|
@@ -61,6 +63,7 @@ import org.apache.hadoop.yarn.api.records.ResourceRequest;
|
|
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
|
|
import org.apache.hadoop.yarn.factories.RecordFactory;
|
|
|
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
|
|
|
+import org.apache.hadoop.yarn.server.resourcemanager.MockRM;
|
|
|
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
|
|
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
|
|
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppState;
|
|
@@ -2353,6 +2356,89 @@ public class TestLeafQueue {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ @Test
|
|
|
+ public void testConcurrentAccess() throws Exception {
|
|
|
+ YarnConfiguration conf = new YarnConfiguration();
|
|
|
+ MockRM rm = new MockRM();
|
|
|
+ rm.init(conf);
|
|
|
+ rm.start();
|
|
|
+
|
|
|
+ final String queue = "default";
|
|
|
+ final String user = "user";
|
|
|
+ CapacityScheduler cs = (CapacityScheduler) rm.getResourceScheduler();
|
|
|
+ final LeafQueue defaultQueue = (LeafQueue) cs.getQueue(queue);
|
|
|
+
|
|
|
+ final List<FiCaSchedulerApp> listOfApps =
|
|
|
+ createListOfApps(10000, user, defaultQueue);
|
|
|
+
|
|
|
+ final CyclicBarrier cb = new CyclicBarrier(2);
|
|
|
+ final List<ConcurrentModificationException> conException =
|
|
|
+ new ArrayList<ConcurrentModificationException>();
|
|
|
+
|
|
|
+ Thread submitAndRemove = new Thread(new Runnable() {
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+
|
|
|
+ for (FiCaSchedulerApp fiCaSchedulerApp : listOfApps) {
|
|
|
+ defaultQueue.submitApplicationAttempt(fiCaSchedulerApp, user);
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ cb.await();
|
|
|
+ } catch (Exception e) {
|
|
|
+ // Ignore
|
|
|
+ }
|
|
|
+ for (FiCaSchedulerApp fiCaSchedulerApp : listOfApps) {
|
|
|
+ defaultQueue.finishApplicationAttempt(fiCaSchedulerApp, queue);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, "SubmitAndRemoveApplicationAttempt Thread");
|
|
|
+
|
|
|
+ Thread getAppsInQueue = new Thread(new Runnable() {
|
|
|
+ List<ApplicationAttemptId> apps = new ArrayList<ApplicationAttemptId>();
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ try {
|
|
|
+ try {
|
|
|
+ cb.await();
|
|
|
+ } catch (Exception e) {
|
|
|
+ // Ignore
|
|
|
+ }
|
|
|
+ defaultQueue.collectSchedulerApplications(apps);
|
|
|
+ } catch (ConcurrentModificationException e) {
|
|
|
+ conException.add(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }, "GetAppsInQueue Thread");
|
|
|
+
|
|
|
+ submitAndRemove.start();
|
|
|
+ getAppsInQueue.start();
|
|
|
+
|
|
|
+ submitAndRemove.join();
|
|
|
+ getAppsInQueue.join();
|
|
|
+
|
|
|
+ assertTrue("ConcurrentModificationException is thrown",
|
|
|
+ conException.isEmpty());
|
|
|
+ rm.stop();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<FiCaSchedulerApp> createListOfApps(int noOfApps, String user,
|
|
|
+ LeafQueue defaultQueue) {
|
|
|
+ List<FiCaSchedulerApp> appsLists = new ArrayList<FiCaSchedulerApp>();
|
|
|
+ for (int i = 0; i < noOfApps; i++) {
|
|
|
+ ApplicationAttemptId appAttemptId_0 =
|
|
|
+ TestUtils.getMockApplicationAttemptId(i, 0);
|
|
|
+ FiCaSchedulerApp app_0 =
|
|
|
+ new FiCaSchedulerApp(appAttemptId_0, user, defaultQueue,
|
|
|
+ mock(ActiveUsersManager.class), spyRMContext);
|
|
|
+ appsLists.add(app_0);
|
|
|
+ }
|
|
|
+ return appsLists;
|
|
|
+ }
|
|
|
+
|
|
|
private CapacitySchedulerContext mockCSContext(
|
|
|
CapacitySchedulerConfiguration csConf, Resource clusterResource) {
|
|
|
CapacitySchedulerContext csContext = mock(CapacitySchedulerContext.class);
|