Mercurial > hg > release > thermostat-1.4
changeset 1833:2649ea55de87
Profiler controller correctly restores state after changing selected VM
Reviewed-by: omajid
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2015-October/016758.html
PR2672
author | Andrew Azores <aazores@redhat.com> |
---|---|
date | Tue, 13 Oct 2015 17:16:38 -0400 |
parents | ffd37dfffbdd |
children | 7db129297a73 |
files | vm-profiler/client-swing/src/main/java/com/redhat/thermostat/vm/profiler/client/swing/internal/VmProfileController.java vm-profiler/client-swing/src/test/java/com/redhat/thermostat/vm/profiler/client/swing/internal/VmProfileControllerTest.java |
diffstat | 2 files changed, 244 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/vm-profiler/client-swing/src/main/java/com/redhat/thermostat/vm/profiler/client/swing/internal/VmProfileController.java Tue Oct 13 12:48:05 2015 -0400 +++ b/vm-profiler/client-swing/src/main/java/com/redhat/thermostat/vm/profiler/client/swing/internal/VmProfileController.java Tue Oct 13 17:16:38 2015 -0400 @@ -41,7 +41,9 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import com.redhat.thermostat.client.command.RequestQueue; @@ -82,7 +84,9 @@ public class VmProfileController implements InformationServiceController<VmRef> { + static final String STATE_MAP_KEY = "vmProfileControllerRestoreBundle"; private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer(); + private static final Map<VmRef, SaveState> STATE_BUNDLE_MAP = new HashMap<>(); private final ApplicationService service; private final ProgressNotifier notifier; @@ -99,8 +103,8 @@ private Clock clock; private boolean profilingStartOrStopRequested = false; - private ProfileStatusChange previousStatus; + private ProfilingState profilingState = ProfilingState.STOPPED; private ProgressHandle progressDisplay; @@ -112,7 +116,7 @@ this(service, notifier, agentInfoDao, vmInfoDao, dao, queue, new SystemClock(), new SwingVmProfileView(), vm); } - VmProfileController(ApplicationService service, ProgressNotifier notifier, + VmProfileController(final ApplicationService service, ProgressNotifier notifier, AgentInfoDAO agentInfoDao, VmInfoDAO vmInfoDao, ProfileDAO dao, RequestQueue queue, Clock clock, final VmProfileView view, VmRef vm) { @@ -126,6 +130,10 @@ this.view = view; this.vm = vm; + if (service.getApplicationCache().getAttribute(STATE_MAP_KEY) == null) { + service.getApplicationCache().addAttribute(STATE_MAP_KEY, STATE_BUNDLE_MAP); + } + // TODO dispose the timer when done updater = service.getTimerFactory().createTimer(); updater.setSchedulingType(SchedulingType.FIXED_DELAY); @@ -146,9 +154,11 @@ public void actionPerformed(ActionEvent<Action> actionEvent) { switch (actionEvent.getActionId()) { case HIDDEN: + saveState(); updater.stop(); break; case VISIBLE: + restoreState(); view.setViewControlsEnabled(isAlive()); updater.start(); break; @@ -182,11 +192,33 @@ view.setViewControlsEnabled(isAlive()); } + private void saveState() { + SaveState bundle = new SaveState(previousStatus, profilingStartOrStopRequested, profilingState); + Map<VmRef, SaveState> map = ((Map<VmRef, SaveState>) service.getApplicationCache().getAttribute(STATE_MAP_KEY)); + map.put(vm, bundle); + service.getApplicationCache().addAttribute(STATE_MAP_KEY, map); + } + + private void restoreState() { + SaveState bundle = ((Map<VmRef, SaveState>) service.getApplicationCache().getAttribute(STATE_MAP_KEY)).get(vm); + profilingStartOrStopRequested = bundle != null && bundle.isProfilingStartOrStopRequested(); + previousStatus = bundle == null ? null : bundle.getProfileStatusChange(); + profilingState = bundle == null ? ProfilingState.STOPPED : bundle.getProfilingState(); + if (previousStatus != null) { + profilingState = getProfilingState(previousStatus, profilingStartOrStopRequested); + } + view.setProfilingState(profilingState); + } + private void startProfiling() { + profilingState = ProfilingState.STARTING; + view.setProfilingState(profilingState); setProgressNotificationAndSendRequest(true); } private void stopProfiling() { + profilingState = ProfilingState.STOPPING; + view.setProfilingState(profilingState); setProgressNotificationAndSendRequest(false); } @@ -211,6 +243,9 @@ hideProgressNotificationIfVisible(); profilingStartOrStopRequested = false; + profilingState = ProfilingState.DISABLED; + view.setProfilingState(profilingState); + view.setViewControlsEnabled(false); break; } } @@ -220,23 +255,11 @@ } private void updateViewWithCurrentProfilingStatus() { - ProfilingState profilingState = ProfilingState.STOPPED; - ProfileStatusChange currentStatus = profileDao.getLatestStatus(vm); if (currentStatus != null) { - boolean currentlyActive = currentStatus.isStarted(); - if (currentlyActive && profilingStartOrStopRequested) { - profilingState = ProfilingState.STARTING; - } else if (currentlyActive) { - profilingState = ProfilingState.STARTED; - } else if (profilingStartOrStopRequested) { - profilingState = ProfilingState.STOPPING; - } else { - profilingState = ProfilingState.STOPPED; - } + profilingState = getProfilingState(currentStatus, profilingStartOrStopRequested); } - view.setViewControlsEnabled(isAlive()); if (!isAlive()) { view.setProfilingState(ProfilingState.DISABLED); } else if (profilingStartOrStopRequested) { @@ -254,12 +277,25 @@ previousStatus = currentStatus; } + private ProfilingState getProfilingState(ProfileStatusChange profileStatusChange, boolean profilingStartOrStopRequested) { + ProfilingState profilingState; + boolean currentlyActive = profileStatusChange.isStarted(); + if (currentlyActive && profilingStartOrStopRequested) { + profilingState = ProfilingState.STARTING; + } else if (currentlyActive) { + profilingState = ProfilingState.STARTED; + } else if (profilingStartOrStopRequested) { + profilingState = ProfilingState.STOPPING; + } else { + profilingState = ProfilingState.STOPPED; + } + return profilingState; + } + private void showProgressNotification(boolean start) { if (start) { - view.setProfilingState(ProfilingState.STARTING); progressDisplay = new ProgressHandle(translator.localize(LocaleResources.STARTING_PROFILING)); } else { - view.setProfilingState(ProfilingState.STOPPING); progressDisplay = new ProgressHandle(translator.localize(LocaleResources.STOPPING_PROFILING)); } progressDisplay.setIndeterminate(true); @@ -323,4 +359,28 @@ return Long.compare(o1.timeStamp, o2.timeStamp); } } + + static class SaveState { + private final ProfileStatusChange profileStatusChange; + private final boolean profilingStartOrStopRequested; + private final ProfilingState profilingState; + + public SaveState(ProfileStatusChange profileStatusChange, boolean profilingStartOrStopRequested, ProfilingState profilingState) { + this.profileStatusChange = profileStatusChange; + this.profilingStartOrStopRequested = profilingStartOrStopRequested; + this.profilingState = profilingState; + } + + public ProfileStatusChange getProfileStatusChange() { + return profileStatusChange; + } + + public boolean isProfilingStartOrStopRequested() { + return profilingStartOrStopRequested; + } + + public ProfilingState getProfilingState() { + return profilingState; + } + } }
--- a/vm-profiler/client-swing/src/test/java/com/redhat/thermostat/vm/profiler/client/swing/internal/VmProfileControllerTest.java Tue Oct 13 12:48:05 2015 -0400 +++ b/vm-profiler/client-swing/src/test/java/com/redhat/thermostat/vm/profiler/client/swing/internal/VmProfileControllerTest.java Tue Oct 13 17:16:38 2015 -0400 @@ -36,9 +36,16 @@ package com.redhat.thermostat.vm.profiler.client.swing.internal; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyMap; import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -49,9 +56,14 @@ import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; +import com.redhat.thermostat.common.ApplicationCache; +import org.hamcrest.core.IsNull; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; @@ -96,6 +108,7 @@ private Timer timer; private ApplicationService appService; + private ApplicationCache appCache; private ProgressNotifier notifier; private AgentInfoDAO agentInfoDao; private VmInfoDAO vmInfoDao; @@ -119,6 +132,9 @@ appService = mock(ApplicationService.class); when(appService.getTimerFactory()).thenReturn(timerFactory); + appCache = mock(ApplicationCache.class); + when(appService.getApplicationCache()).thenReturn(appCache); + notifier = mock(ProgressNotifier.class); agentInfoDao = mock(AgentInfoDAO.class); @@ -147,6 +163,7 @@ @Test public void timerRunsWhenVisible() throws Exception { + when(appCache.getAttribute(any(String.class))).thenReturn(new HashMap<>()); controller = createController(); verify(timer, never()).start(); @@ -161,6 +178,7 @@ @Test public void timerStopsWhenHidden() throws Exception { + when(appCache.getAttribute(any(String.class))).thenReturn(new HashMap<>()); controller = createController(); verify(timer, never()).start(); @@ -198,7 +216,7 @@ assertEquals(1, resultList.size()); assertEquals(PROFILE_TIMESTAMP, resultList.get(0).timeStamp); - verify(view, times(2)).setViewControlsEnabled(true); + verify(view, atLeastOnce()).setViewControlsEnabled(true); } @Test @@ -315,6 +333,154 @@ verify(view).setProfilingDetailData(isA(ProfilingResult.class)); } + @Test + public void testSavesStateOnViewHidden() throws Exception { + Map<VmRef, VmProfileController.SaveState> map = new HashMap<>(); + when(appCache.getAttribute(any(String.class))).thenReturn(map); + controller = createController(); + + ArgumentCaptor<ActionListener> actionListenerCaptor = ArgumentCaptor.forClass(ActionListener.class); + verify(view).addActionListener(actionListenerCaptor.capture()); + + actionListenerCaptor.getValue().actionPerformed(new ActionEvent(view, Action.HIDDEN)); + + verify(appCache).addAttribute(VmProfileController.STATE_MAP_KEY, any(anyMap().getClass())); + assertThat(map.keySet(), is(equalTo(Collections.singleton(vm)))); + VmProfileController.SaveState state = map.get(vm); + assertThat(state, is(notNullValue())); + assertThat(state.isProfilingStartOrStopRequested(), is(false)); + assertThat(state.getProfilingState(), is(VmProfileView.ProfilingState.STOPPED)); + assertThat(state.getProfileStatusChange(), is(equalTo(null))); + } + + @Test + public void testRestoresStateOnViewVisible() throws Exception { + when(appCache.getAttribute(any(String.class))).thenReturn(new HashMap<>()); + controller = createController(); + + ArgumentCaptor<ActionListener> actionListenerCaptor = ArgumentCaptor.forClass(ActionListener.class); + verify(view).addActionListener(actionListenerCaptor.capture()); + + actionListenerCaptor.getValue().actionPerformed(new ActionEvent(view, Action.VISIBLE)); + + verify(appCache, atLeastOnce()).getAttribute(VmProfileController.STATE_MAP_KEY); + verify(view, atLeastOnce()).setProfilingState(any(VmProfileView.ProfilingState.class)); + verify(view, atLeastOnce()).setViewControlsEnabled(anyBoolean()); + } + + @Test + public void testRestoresStateCorrectlyWhenPreviousStateSetStarting() throws Exception { + ProfileStatusChange psc = mock(ProfileStatusChange.class); + when(psc.isStarted()).thenReturn(true); + // should ignore the DISABLED argument because a previous state (psc) is available + VmProfileController.SaveState state = new VmProfileController.SaveState(psc, true, VmProfileView.ProfilingState.DISABLED); + doRestoreTest(state); + + verify(view, atLeastOnce()).setProfilingState(VmProfileView.ProfilingState.STARTING); + verify(view, atLeastOnce()).setViewControlsEnabled(true); + } + + @Test + public void testRestoresStateCorrectlyWhenPreviousStateSetStarted() throws Exception { + ProfileStatusChange psc = mock(ProfileStatusChange.class); + when(psc.isStarted()).thenReturn(true); + // should ignore the DISABLED argument because a previous state (psc) is available + VmProfileController.SaveState state = new VmProfileController.SaveState(psc, false, VmProfileView.ProfilingState.DISABLED); + doRestoreTest(state); + + verify(view, atLeastOnce()).setProfilingState(VmProfileView.ProfilingState.STARTED); + verify(view, atLeastOnce()).setViewControlsEnabled(true); + } + + @Test + public void testRestoresStateCorrectlyWhenPreviousStateSetStopping() throws Exception { + ProfileStatusChange psc = mock(ProfileStatusChange.class); + when(psc.isStarted()).thenReturn(false); + // should ignore the DISABLED argument because a previous state (psc) is available + VmProfileController.SaveState state = new VmProfileController.SaveState(psc, true, VmProfileView.ProfilingState.DISABLED); + doRestoreTest(state); + + verify(view, atLeastOnce()).setProfilingState(VmProfileView.ProfilingState.STOPPING); + verify(view, atLeastOnce()).setViewControlsEnabled(true); + } + + @Test + public void testRestoresStateCorrectlyWhenPreviousStateSetStopped() throws Exception { + ProfileStatusChange psc = mock(ProfileStatusChange.class); + when(psc.isStarted()).thenReturn(false); + // should ignore the DISABLED argument because a previous state (psc) is available + VmProfileController.SaveState state = new VmProfileController.SaveState(psc, false, VmProfileView.ProfilingState.DISABLED); + doRestoreTest(state); + + verify(view, atLeastOnce()).setProfilingState(VmProfileView.ProfilingState.STOPPED); + verify(view, atLeastOnce()).setViewControlsEnabled(true); + } + + @Test + public void testRestoresStateCorrectlyWhenPreviousStateUnsetProfilingDisabled() throws Exception { + // no ProfilingStatusChange to rely on so fall back on the ProfilingState + VmProfileController.SaveState state = new VmProfileController.SaveState(null, false, VmProfileView.ProfilingState.DISABLED); + doRestoreTest(state); + + verify(view, atLeastOnce()).setProfilingState(VmProfileView.ProfilingState.DISABLED); + verify(view, atLeastOnce()).setViewControlsEnabled(true); + } + + @Test + public void testRestoresStateCorrectlyWhenPreviousStateUnsetProfilingStarting() throws Exception { + // no ProfilingStatusChange to rely on so fall back on the ProfilingState + VmProfileController.SaveState state = new VmProfileController.SaveState(null, false, VmProfileView.ProfilingState.STARTING); + doRestoreTest(state); + + verify(view, atLeastOnce()).setProfilingState(VmProfileView.ProfilingState.STARTING); + verify(view, atLeastOnce()).setViewControlsEnabled(true); + } + + @Test + public void testRestoresStateCorrectlyWhenPreviousStateUnsetProfilingStarted() throws Exception { + // no ProfilingStatusChange to rely on so fall back on the ProfilingState + VmProfileController.SaveState state = new VmProfileController.SaveState(null, false, VmProfileView.ProfilingState.STARTED); + doRestoreTest(state); + + verify(view, atLeastOnce()).setProfilingState(VmProfileView.ProfilingState.STARTED); + verify(view, atLeastOnce()).setViewControlsEnabled(true); + } + + @Test + public void testRestoresStateCorrectlyWhenPreviousStateUnsetProfilingStopping() throws Exception { + // no ProfilingStatusChange to rely on so fall back on the ProfilingState + VmProfileController.SaveState state = new VmProfileController.SaveState(null, false, VmProfileView.ProfilingState.STOPPING); + doRestoreTest(state); + + verify(view, atLeastOnce()).setProfilingState(VmProfileView.ProfilingState.STOPPING); + verify(view, atLeastOnce()).setViewControlsEnabled(true); + } + + @Test + public void testRestoresStateCorrectlyWhenPreviousStateUnsetProfilingStopped() throws Exception { + // no ProfilingStatusChange to rely on so fall back on the ProfilingState + VmProfileController.SaveState state = new VmProfileController.SaveState(null, false, VmProfileView.ProfilingState.STOPPED); + doRestoreTest(state); + + verify(view, atLeastOnce()).setProfilingState(VmProfileView.ProfilingState.STOPPED); + verify(view, atLeastOnce()).setViewControlsEnabled(true); + } + + private void doRestoreTest(VmProfileController.SaveState saveState) { + Map<VmRef, VmProfileController.SaveState> map = new HashMap<>(); + + map.put(vm, saveState); + when(appCache.getAttribute(any(String.class))).thenReturn(map); + controller = createController(); + + ArgumentCaptor<ActionListener> actionListenerCaptor = ArgumentCaptor.forClass(ActionListener.class); + verify(view).addActionListener(actionListenerCaptor.capture()); + + actionListenerCaptor.getValue().actionPerformed(new ActionEvent(view, Action.VISIBLE)); + + verify(appCache, atLeastOnce()).getAttribute(VmProfileController.STATE_MAP_KEY); + } + private VmProfileController createController() { return new VmProfileController(appService, notifier, agentInfoDao, vmInfoDao, profileDao, queue, clock, view, vm); }