Java tutorial
/** * 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 com.cloudera.llama.am.impl; import com.cloudera.llama.am.api.LlamaAM; import com.cloudera.llama.am.api.NodeInfo; import com.cloudera.llama.util.Clock; import com.cloudera.llama.util.LlamaException; import com.cloudera.llama.am.api.LlamaAMListener; import com.cloudera.llama.am.api.PlacedReservation; import com.cloudera.llama.am.api.Reservation; import com.cloudera.llama.am.api.TestUtils; import com.cloudera.llama.util.ManualClock; import com.cloudera.llama.util.UUID; import org.apache.hadoop.conf.Configuration; import org.junit.Assert; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; public class TestGangAntiDeadlockLlamaAM { @Test public void testBackedOffReservation() { PlacedReservationImpl pr = new PlacedReservationImpl(UUID.randomUUID(), TestUtils.createReservation(UUID.randomUUID(), 1, true)); long now = System.currentTimeMillis(); GangAntiDeadlockLlamaAM.BackedOffReservation br1 = new GangAntiDeadlockLlamaAM.BackedOffReservation(pr, 0); Assert.assertEquals(pr, br1.getReservation()); Assert.assertTrue(System.currentTimeMillis() - now >= br1.getDelay(TimeUnit.MILLISECONDS)); GangAntiDeadlockLlamaAM.BackedOffReservation br2 = new GangAntiDeadlockLlamaAM.BackedOffReservation(pr, 100); Assert.assertTrue(System.currentTimeMillis() - now + 100 >= br1.getDelay(TimeUnit.MILLISECONDS)); Assert.assertTrue(br1.compareTo(br2) < 0); } private static Set<String> EXPECTED = new HashSet<String>(); private static ManualClock testClock = new ManualClock(); static { EXPECTED.add("start"); EXPECTED.add("stop"); EXPECTED.add("isRunning"); EXPECTED.add("getNodes"); EXPECTED.add("reserve"); EXPECTED.add("getReservation"); EXPECTED.add("releaseReservation"); EXPECTED.add("releaseReservationsForClientId"); EXPECTED.add("addListener"); EXPECTED.add("removeListener"); EXPECTED.add("releaseReservationsForQueue"); Clock.setClock(testClock); } public class MyGangAntiDeadlockLlamaAM extends GangAntiDeadlockLlamaAM { public MyGangAntiDeadlockLlamaAM(Configuration conf, LlamaAM llamaAM) { super(conf, llamaAM); } @Override void startDeadlockResolverThread() { } } public class MyLlamaAM extends LlamaAMImpl { private boolean running; Set<String> invoked; Map<UUID, PlacedReservationImpl> reservations; protected MyLlamaAM(Configuration conf) { super(conf); invoked = new HashSet<String>(); reservations = new HashMap<UUID, PlacedReservationImpl>(); } @Override public void start() throws LlamaException { running = true; invoked.add("start"); } @Override public void stop() { running = false; invoked.add("stop"); } @Override public boolean isRunning() { invoked.add("isRunning"); return running; } @Override public List<NodeInfo> getNodes() throws LlamaException { invoked.add("getNodes"); return null; } @Override public void reserve(UUID reservationId, Reservation reservation) throws LlamaException { invoked.add("reserve"); PlacedReservationImpl pr = new PlacedReservationImpl(reservationId, reservation); reservations.put(reservationId, pr); } @Override public PlacedReservation getReservation(UUID reservationId) throws LlamaException { invoked.add("getReservation"); return reservations.get(reservationId); } @Override public PlacedReservation releaseReservation(UUID handle, UUID reservationId, boolean doNotCache) throws LlamaException { invoked.add("releaseReservation"); PlacedReservationImpl r = reservations.remove(reservationId); if (r != null) { r.setStatus(PlacedReservation.Status.RELEASED); } return r; } @Override public List<PlacedReservation> releaseReservationsForHandle(UUID handle, boolean doNotCache) throws LlamaException { invoked.add("releaseReservationsForClientId"); List<PlacedReservation> list = new ArrayList<PlacedReservation>(); Iterator<Map.Entry<UUID, PlacedReservationImpl>> it = reservations.entrySet().iterator(); while (it.hasNext()) { Map.Entry<UUID, PlacedReservationImpl> entry = it.next(); if (entry.getValue().getHandle().equals(handle)) { it.remove(); entry.getValue().setStatus(PlacedReservation.Status.RELEASED); list.add(entry.getValue()); } } return list; } @Override public List<PlacedReservation> releaseReservationsForQueue(String queue, boolean doNotCache) throws LlamaException { invoked.add("releaseReservationsForQueue"); List<PlacedReservation> list = new ArrayList<PlacedReservation>(); Iterator<Map.Entry<UUID, PlacedReservationImpl>> it = reservations.entrySet().iterator(); while (it.hasNext()) { Map.Entry<UUID, PlacedReservationImpl> entry = it.next(); if (entry.getValue().getQueue().equals(queue)) { it.remove(); entry.getValue().setStatus(PlacedReservation.Status.RELEASED); list.add(entry.getValue()); } } return list; } @Override public void emptyCacheForQueue(String queue) throws LlamaException { } @Override public void addListener(LlamaAMListener listener) { invoked.add("addListener"); super.addListener(listener); } @Override public void removeListener(LlamaAMListener listener) { invoked.add("removeListener"); super.removeListener(listener); } @Override public void dispatch(LlamaAMEventImpl event) { super.dispatch(event); } } private static final long NO_ALLOCATION_LIMIT = 50; private static final long BACKOFF_PERCENT = 50; private static final long BACKOFF_MIN_DELAY = 100; private static final long BACKOFF_MAX_DELAY = 150; private Configuration createGangConfig() { Configuration conf = new Configuration(false); conf.setLong(LlamaAM.GANG_ANTI_DEADLOCK_NO_ALLOCATION_LIMIT_KEY, NO_ALLOCATION_LIMIT); conf.setLong(LlamaAM.GANG_ANTI_DEADLOCK_BACKOFF_PERCENT_KEY, BACKOFF_PERCENT); conf.setLong(LlamaAM.GANG_ANTI_DEADLOCK_BACKOFF_MIN_DELAY_KEY, BACKOFF_MIN_DELAY); conf.setLong(LlamaAM.GANG_ANTI_DEADLOCK_BACKOFF_MAX_DELAY_KEY, BACKOFF_MAX_DELAY); return conf; } @SuppressWarnings("unchecked") private void testDelegate(boolean gang) throws Exception { Configuration conf = createGangConfig(); MyLlamaAM am = new MyLlamaAM(conf); GangAntiDeadlockLlamaAM gAm = new GangAntiDeadlockLlamaAM(conf, am); Assert.assertFalse(gAm.isRunning()); gAm.start(); Assert.assertTrue(gAm.isRunning()); gAm.getNodes(); gAm.addListener(null); gAm.removeListener(null); UUID handle = UUID.randomUUID(); Reservation reservation = TestUtils.createReservation(handle, 1, gang); Assert.assertTrue(gAm.localReservations.isEmpty()); Assert.assertTrue(gAm.backedOffReservations.isEmpty()); Assert.assertTrue(am.reservations.isEmpty()); UUID id = gAm.reserve(reservation); Assert.assertEquals(gang, !gAm.localReservations.isEmpty()); Assert.assertTrue(gAm.backedOffReservations.isEmpty()); gAm.getReservation(id); Assert.assertTrue(am.reservations.containsKey(id)); gAm.releaseReservation(handle, id, false); Assert.assertTrue(gAm.localReservations.isEmpty()); Assert.assertTrue(gAm.backedOffReservations.isEmpty()); Assert.assertFalse(am.reservations.containsKey(id)); gAm.releaseReservationsForHandle(UUID.randomUUID(), false); gAm.releaseReservationsForQueue("q", false); gAm.stop(); Assert.assertFalse(gAm.isRunning()); Assert.assertEquals(EXPECTED, am.invoked); } @Test public void testDelegateNoGang() throws Exception { testDelegate(false); } @Test public void testDelegateGang() throws Exception { testDelegate(true); } @Test @SuppressWarnings("unchecked") public void testGangReserveAllocate() throws Exception { Configuration conf = createGangConfig(); MyLlamaAM am = new MyLlamaAM(conf); GangAntiDeadlockLlamaAM gAm = new GangAntiDeadlockLlamaAM(conf, am); try { gAm.start(); long lastAllocation = gAm.timeOfLastAllocation; Reservation reservation = TestUtils.createReservation(UUID.randomUUID(), 1, true); PlacedReservation pr = gAm.getReservation(gAm.reserve(reservation)); Assert.assertFalse(gAm.localReservations.isEmpty()); LlamaAMEventImpl event = new LlamaAMEventImpl(); PlacedReservationImpl pri = (PlacedReservationImpl) pr; pri.setStatus(PlacedReservation.Status.ALLOCATED); pri.getPlacedResourceImpls().get(0).setAllocationInfo(pr.getResources().get(0).getLocationAsk(), pr.getResources().get(0).getCpuVCoresAsk(), pr.getResources().get(0).getMemoryMbsAsk()); event.addReservation(pr); event.addResource(am.reservations.get(pr.getReservationId()).getPlacedResources().get(0)); Assert.assertEquals(lastAllocation, gAm.timeOfLastAllocation); am.dispatch(event); Assert.assertNotSame(lastAllocation, gAm.timeOfLastAllocation); Assert.assertTrue(gAm.localReservations.isEmpty()); } finally { gAm.stop(); } } @Test @SuppressWarnings("unchecked") public void testGangReserveReject() throws Exception { Configuration conf = createGangConfig(); MyLlamaAM am = new MyLlamaAM(conf); GangAntiDeadlockLlamaAM gAm = new GangAntiDeadlockLlamaAM(conf, am); try { gAm.start(); long lastAllocation = gAm.timeOfLastAllocation; Reservation reservation = TestUtils.createReservation(UUID.randomUUID(), 1, true); PlacedReservation pr = gAm.getReservation(gAm.reserve(reservation)); Assert.assertFalse(gAm.localReservations.isEmpty()); LlamaAMEventImpl event = new LlamaAMEventImpl(); ((PlacedReservationImpl) pr).setStatus(PlacedReservation.Status.REJECTED); event.addReservation(pr); Assert.assertEquals(lastAllocation, gAm.timeOfLastAllocation); am.dispatch(event); Assert.assertEquals(lastAllocation, gAm.timeOfLastAllocation); Assert.assertTrue(gAm.localReservations.isEmpty()); } finally { gAm.stop(); } } @Test @SuppressWarnings("unchecked") public void testGangReserveBackoffReReserve() throws Exception { LlamaAMEventImpl event1 = new LlamaAMEventImpl(); Configuration conf = createGangConfig(); MyLlamaAM am = new MyLlamaAM(conf); GangAntiDeadlockLlamaAM gAm = new MyGangAntiDeadlockLlamaAM(conf, am); try { gAm.start(); //reserve UUID handle = UUID.randomUUID(); Reservation reservation1 = TestUtils.createReservation(handle, 1, true); UUID id1 = gAm.reserve(reservation1); long placedOn1 = gAm.getReservation(id1).getPlacedOn(); testClock.increment(1); Reservation reservation2 = TestUtils.createReservation(handle, 1, true); UUID id2 = gAm.reserve(reservation2); long placedOn2 = gAm.getReservation(id2).getPlacedOn(); testClock.increment(1); Reservation reservation3 = TestUtils.createReservation(handle, 1, true); UUID id3 = gAm.reserve(reservation3); long placedOn3 = gAm.getReservation(id3).getPlacedOn(); testClock.increment(1); Reservation reservation4 = TestUtils.createReservation(handle, 1, true); UUID id4 = gAm.reserve(reservation4); long placedOn4 = gAm.getReservation(id4).getPlacedOn(); Assert.assertNotNull(gAm.getReservation(id1)); Assert.assertNotNull(gAm.getReservation(id2)); Assert.assertNotNull(gAm.getReservation(id3)); Assert.assertNotNull(gAm.getReservation(id4)); Assert.assertEquals(4, am.reservations.size()); Assert.assertEquals(4, gAm.localReservations.size()); Assert.assertEquals(0, gAm.backedOffReservations.size()); Assert.assertEquals(4, gAm.submittedReservations.size()); //deadlock avoidance without victims gAm.timeOfLastAllocation = System.currentTimeMillis(); long sleep = gAm.deadlockAvoidance(event1); Assert.assertTrue(NO_ALLOCATION_LIMIT >= sleep); Assert.assertEquals(4, am.reservations.size()); Assert.assertEquals(4, gAm.localReservations.size()); Assert.assertEquals(0, gAm.backedOffReservations.size()); Assert.assertEquals(4, gAm.submittedReservations.size()); //deadlock avoidance with victims gAm.timeOfLastAllocation = System.currentTimeMillis() - NO_ALLOCATION_LIMIT - 1; sleep = gAm.deadlockAvoidance(event1); Assert.assertEquals(NO_ALLOCATION_LIMIT, sleep); Assert.assertEquals(2, am.reservations.size()); Assert.assertEquals(4, gAm.localReservations.size()); Assert.assertEquals(2, gAm.backedOffReservations.size()); Assert.assertEquals(2, gAm.submittedReservations.size()); //2nd deadlock avoidance with victims gAm.timeOfLastAllocation = System.currentTimeMillis() - NO_ALLOCATION_LIMIT; sleep = gAm.deadlockAvoidance(event1); Assert.assertEquals(NO_ALLOCATION_LIMIT, sleep); Assert.assertEquals(1, am.reservations.size()); Assert.assertEquals(4, gAm.localReservations.size()); Assert.assertEquals(3, gAm.backedOffReservations.size()); Assert.assertEquals(1, gAm.submittedReservations.size()); //allocation of survivors LlamaAMEventImpl event2 = new LlamaAMEventImpl(); for (PlacedReservation pr : am.reservations.values()) { ((PlacedReservationImpl) pr).setStatus(PlacedReservation.Status.ALLOCATED); event2.addReservation(pr); } am.dispatch(event2); Assert.assertEquals(1, am.reservations.size()); Assert.assertEquals(3, gAm.localReservations.size()); Assert.assertEquals(3, gAm.backedOffReservations.size()); Assert.assertEquals(0, gAm.submittedReservations.size()); sleep = gAm.reReserveBackOffs(event2); Assert.assertTrue(BACKOFF_MAX_DELAY > sleep); Thread.sleep(BACKOFF_MAX_DELAY + 10); sleep = gAm.reReserveBackOffs(event2); Assert.assertEquals(Long.MAX_VALUE, sleep); Assert.assertEquals(4, am.reservations.size()); Assert.assertEquals(3, gAm.localReservations.size()); Assert.assertEquals(0, gAm.backedOffReservations.size()); Assert.assertEquals(3, gAm.submittedReservations.size()); //verify placedOn value is same as original Assert.assertEquals(placedOn1, gAm.getReservation(id1).getPlacedOn()); Assert.assertEquals(placedOn2, gAm.getReservation(id2).getPlacedOn()); Assert.assertEquals(placedOn3, gAm.getReservation(id3).getPlacedOn()); Assert.assertEquals(placedOn4, gAm.getReservation(id4).getPlacedOn()); } finally { gAm.stop(); } } @Test @SuppressWarnings("unchecked") public void testReleaseReservation() throws Exception { Configuration conf = createGangConfig(); MyLlamaAM am = new MyLlamaAM(conf); GangAntiDeadlockLlamaAM gAm = new MyGangAntiDeadlockLlamaAM(conf, am); try { gAm.start(); //reserve UUID handle = UUID.randomUUID(); Reservation reservation1 = TestUtils.createReservation(handle, 1, true); UUID id1 = gAm.reserve(reservation1); Reservation reservation2 = TestUtils.createReservation(handle, 1, true); UUID id2 = gAm.reserve(reservation2); Reservation reservation3 = TestUtils.createReservation(handle, 1, true); UUID id3 = gAm.reserve(reservation3); Reservation reservation4 = TestUtils.createReservation(handle, 1, true); UUID id4 = gAm.reserve(reservation4); LlamaAMEventImpl event1 = new LlamaAMEventImpl(); //deadlock avoidance with victims gAm.timeOfLastAllocation = System.currentTimeMillis() - NO_ALLOCATION_LIMIT - 1; long sleep = gAm.deadlockAvoidance(event1); Assert.assertEquals(NO_ALLOCATION_LIMIT, sleep); Assert.assertEquals(2, am.reservations.size()); Assert.assertEquals(4, gAm.localReservations.size()); Assert.assertEquals(2, gAm.backedOffReservations.size()); Assert.assertEquals(2, gAm.submittedReservations.size()); List<UUID> ids = Arrays.asList(id1, id2, id3, id4); for (UUID id : ids) { PlacedReservation pr = gAm.releaseReservation(handle, id, false); Assert.assertNotNull(pr); Assert.assertEquals(PlacedReservation.Status.RELEASED, pr.getStatus()); } } finally { gAm.stop(); } } @Test @SuppressWarnings("unchecked") public void testReleaseReservationsForHandle() throws Exception { Configuration conf = createGangConfig(); MyLlamaAM am = new MyLlamaAM(conf); GangAntiDeadlockLlamaAM gAm = new MyGangAntiDeadlockLlamaAM(conf, am); try { gAm.start(); //reserve UUID handle = UUID.randomUUID(); Reservation reservation1 = TestUtils.createReservation(handle, 1, true); gAm.reserve(reservation1); Reservation reservation2 = TestUtils.createReservation(handle, 1, true); gAm.reserve(reservation2); Reservation reservation3 = TestUtils.createReservation(handle, 1, true); gAm.reserve(reservation3); Reservation reservation4 = TestUtils.createReservation(handle, 1, true); gAm.reserve(reservation4); LlamaAMEventImpl event1 = new LlamaAMEventImpl(); //deadlock avoidance with victims gAm.timeOfLastAllocation = System.currentTimeMillis() - NO_ALLOCATION_LIMIT - 1; long sleep = gAm.deadlockAvoidance(event1); Assert.assertEquals(NO_ALLOCATION_LIMIT, sleep); Assert.assertEquals(2, am.reservations.size()); Assert.assertEquals(4, gAm.localReservations.size()); Assert.assertEquals(2, gAm.backedOffReservations.size()); Assert.assertEquals(2, gAm.submittedReservations.size()); List<PlacedReservation> prs = gAm.releaseReservationsForHandle(handle, false); Assert.assertEquals(4, prs.size()); for (PlacedReservation pr : prs) { Assert.assertEquals(PlacedReservation.Status.RELEASED, pr.getStatus()); } } finally { gAm.stop(); } } @Test @SuppressWarnings("unchecked") public void testReleaseReservationsForQueue() throws Exception { Configuration conf = createGangConfig(); MyLlamaAM am = new MyLlamaAM(conf); GangAntiDeadlockLlamaAM gAm = new MyGangAntiDeadlockLlamaAM(conf, am); try { gAm.start(); //reserve UUID handle = UUID.randomUUID(); Reservation reservation1 = TestUtils.createReservation(handle, 1, true); gAm.reserve(reservation1); Reservation reservation2 = TestUtils.createReservation(handle, 1, true); gAm.reserve(reservation2); Reservation reservation3 = TestUtils.createReservation(handle, 1, true); gAm.reserve(reservation3); Reservation reservation4 = TestUtils.createReservation(handle, 1, true); gAm.reserve(reservation4); LlamaAMEventImpl event1 = new LlamaAMEventImpl(); //deadlock avoidance with victims gAm.timeOfLastAllocation = System.currentTimeMillis() - NO_ALLOCATION_LIMIT - 1; long sleep = gAm.deadlockAvoidance(event1); Assert.assertEquals(NO_ALLOCATION_LIMIT, sleep); Assert.assertEquals(2, am.reservations.size()); Assert.assertEquals(4, gAm.localReservations.size()); Assert.assertEquals(2, gAm.backedOffReservations.size()); Assert.assertEquals(2, gAm.submittedReservations.size()); List<PlacedReservation> prs = gAm.releaseReservationsForQueue("q", false); Assert.assertEquals(4, prs.size()); for (PlacedReservation pr : prs) { Assert.assertEquals(PlacedReservation.Status.RELEASED, pr.getStatus()); } } finally { gAm.stop(); } } }