Mercurial > hg > release > thermostat-0.7
changeset 1047:7dc61d031410
Publish VM capabilities to storage whenever a VM starts
Reviewed-by: neugens
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-March/006166.html
line wrap: on
line diff
--- a/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/collector/impl/ThreadMXBeanCollector.java Fri Mar 22 13:05:51 2013 -0400 +++ b/thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/collector/impl/ThreadMXBeanCollector.java Fri Mar 22 16:43:10 2013 -0400 @@ -230,33 +230,7 @@ @Override public VMThreadCapabilities getVMThreadCapabilities() { - VMThreadCapabilities caps = threadDao.loadCapabilities(ref); - if (caps == null) { - Request harvester = createRequest(); - harvester.setParameter(HarvesterCommand.class.getName(), HarvesterCommand.VM_CAPS.name()); - harvester.setParameter(HarvesterCommand.VM_ID.name(), ref.getIdString()); - - final CountDownLatch latch = new CountDownLatch(1); - harvester.addListener(new RequestResponseListener() { - @Override - public void fireComplete(Request request, Response response) { - latch.countDown(); - } - }); - - - try { - enqueueRequest(harvester); - latch.await(); - // FIXME there is no guarantee that data is now present in storage - caps = threadDao.loadCapabilities(ref); - } catch (InterruptedException ignore) { - caps = new VMThreadCapabilities(); - } catch (CommandException e) { - logger.log(Level.WARNING, "Failed to enqueue request", e); - } - } return caps; }
--- a/thread/client-common/src/test/java/com/redhat/thermostat/thread/client/common/collector/impl/ThreadCollectorTest.java Fri Mar 22 13:05:51 2013 -0400 +++ b/thread/client-common/src/test/java/com/redhat/thermostat/thread/client/common/collector/impl/ThreadCollectorTest.java Fri Mar 22 16:43:10 2013 -0400 @@ -36,14 +36,12 @@ package com.redhat.thermostat.thread.client.common.collector.impl; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; -import static org.junit.Assert.fail; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -92,93 +90,31 @@ @Test public void testVMCapabilitiesNotInDAO() throws Exception { - VMThreadCapabilities resCaps = mock(VMThreadCapabilities.class); - when(threadDao.loadCapabilities(reference)).thenReturn(null).thenReturn(resCaps); - - final RequestQueue requestQueue = mock(RequestQueue.class); - context.registerService(RequestQueue.class, requestQueue, null); - - final ArgumentCaptor<RequestResponseListener> captor = ArgumentCaptor.forClass(RequestResponseListener.class); - doNothing().when(request).addListener(captor.capture()); + when(threadDao.loadCapabilities(reference)).thenReturn(null); - doAnswer(new Answer<Void>() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - Request req = (Request) invocation.getArguments()[0]; - assertSame(request, req); - - RequestResponseListener listener = captor.getValue(); - listener.fireComplete(null, null); - - return null; - } - - }).when(requestQueue).putRequest(request); - - ThreadCollector collector = new ThreadMXBeanCollector(context, reference) { - @Override - Request createRequest() { - return request; - } - }; + ThreadCollector collector = new ThreadMXBeanCollector(context, reference); collector.setAgentInfoDao(agentDao); collector.setThreadDao(threadDao); VMThreadCapabilities caps = collector.getVMThreadCapabilities(); - - verify(request).setParameter(HarvesterCommand.class.getName(), HarvesterCommand.VM_CAPS.name()); - verify(request).setParameter(HarvesterCommand.VM_ID.name(), "00101010"); - verify(requestQueue).putRequest(request); - - verify(threadDao, times(2)).loadCapabilities(reference); - assertSame(resCaps, caps); - } - - @Test - public void testVMCapabilitiesNoRequestQueue() throws Exception { - VMThreadCapabilities resCaps = mock(VMThreadCapabilities.class); - when(threadDao.loadCapabilities(reference)).thenReturn(null).thenReturn(resCaps); - - ThreadCollector collector = new ThreadMXBeanCollector(context, reference) { - @Override - Request createRequest() { - return request; - } - }; - collector.setAgentInfoDao(agentDao); - collector.setThreadDao(threadDao); - - VMThreadCapabilities caps = collector.getVMThreadCapabilities(); - - verify(request).setParameter(HarvesterCommand.class.getName(), HarvesterCommand.VM_CAPS.name()); - verify(request).setParameter(HarvesterCommand.VM_ID.name(), "00101010"); - - verify(threadDao, times(1)).loadCapabilities(reference); - assertNull(caps); + verify(threadDao).loadCapabilities(reference); + assertEquals(null, caps); } @Test public void testVMCapabilitiesInDAO() throws Exception { - StubBundleContext context = new StubBundleContext(); - VMThreadCapabilities resCaps = mock(VMThreadCapabilities.class); when(threadDao.loadCapabilities(reference)).thenReturn(resCaps); - ThreadCollector collector = new ThreadMXBeanCollector(context, reference) { - @Override - Request createRequest() { - fail(); - return null; - } - }; + ThreadCollector collector = new ThreadMXBeanCollector(context, reference); collector.setAgentInfoDao(agentDao); collector.setThreadDao(threadDao); VMThreadCapabilities caps = collector.getVMThreadCapabilities(); - verify(threadDao, times(1)).loadCapabilities(reference); + verify(threadDao).loadCapabilities(reference); assertSame(resCaps, caps); }
--- a/thread/collector/src/main/java/com/redhat/thermostat/thread/collector/HarvesterCommand.java Fri Mar 22 13:05:51 2013 -0400 +++ b/thread/collector/src/main/java/com/redhat/thermostat/thread/collector/HarvesterCommand.java Fri Mar 22 16:43:10 2013 -0400 @@ -40,7 +40,6 @@ START, STOP, - VM_CAPS, IS_COLLECTING, VM_ID;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadBackend.java Fri Mar 22 16:43:10 2013 -0400 @@ -0,0 +1,107 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.harvester; + +import com.redhat.thermostat.agent.VmStatusListener; +import com.redhat.thermostat.agent.VmStatusListenerRegistrar; +import com.redhat.thermostat.agent.command.ReceiverRegistry; +import com.redhat.thermostat.backend.BaseBackend; +import com.redhat.thermostat.common.Version; + +public class ThreadBackend extends BaseBackend implements VmStatusListener { + + private final ReceiverRegistry registry; + private final ThreadHarvester harvester; + + private boolean active = false; + private VmStatusListenerRegistrar vmListener; + + public ThreadBackend(Version version, VmStatusListenerRegistrar registrar, ReceiverRegistry registry, ThreadHarvester harvester) { + super("VM Thread Backend", "Gathers thread information about a JVM", "Red Hat, Inc", version.getVersionNumber()); + + this.vmListener = registrar; + this.registry = registry; + this.harvester = harvester; + } + + @Override + public int getOrderValue() { + return ORDER_THREAD_GROUP; + } + + @Override + public boolean activate() { + if (active) { + return true; + } + vmListener.register(this); + registry.registerReceiver(harvester); + active = true; + return true; + } + + @Override + public boolean deactivate() { + if (!active) { + return true; + } + vmListener.unregister(this); + registry.unregisterReceivers(); + active = false; + return true; + } + + @Override + public boolean isActive() { + return active; + } + + @Override + public void vmStatusChanged(Status newStatus, int pid) { + switch (newStatus) { + case VM_STARTED: case VM_ACTIVE: + /* this is blocking */ + harvester.saveVmCaps(String.valueOf(pid)); + break; + case VM_STOPPED: + default: + /* nothing to do */ + break; + } + } + +}
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadHarvester.java Fri Mar 22 13:05:51 2013 -0400 +++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadHarvester.java Fri Mar 22 16:43:10 2013 -0400 @@ -89,12 +89,6 @@ result = stopHarvester(vmId); break; } - case VM_CAPS: { - // this is blocking - String vmId = request.getParameter(HarvesterCommand.VM_ID.name()); - result = saveVmCaps(vmId); - break; - } case IS_COLLECTING: { // this is blocking too String vmId = request.getParameter(HarvesterCommand.VM_ID.name()); @@ -126,7 +120,7 @@ return harvester.start(); } - private boolean saveVmCaps(String vmId) { + boolean saveVmCaps(String vmId) { Harvester harvester = getHarvester(vmId); return harvester.saveVmCaps(); }
--- a/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/osgi/Activator.java Fri Mar 22 13:05:51 2013 -0400 +++ b/thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/osgi/Activator.java Fri Mar 22 16:43:10 2013 -0400 @@ -42,10 +42,15 @@ import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; import org.osgi.util.tracker.ServiceTracker; +import com.redhat.thermostat.agent.VmStatusListenerRegistrar; import com.redhat.thermostat.agent.command.ReceiverRegistry; +import com.redhat.thermostat.backend.Backend; +import com.redhat.thermostat.common.Version; import com.redhat.thermostat.thread.dao.ThreadDao; +import com.redhat.thermostat.thread.harvester.ThreadBackend; import com.redhat.thermostat.thread.harvester.ThreadHarvester; public class Activator implements BundleActivator { @@ -53,17 +58,26 @@ private ScheduledExecutorService executor = Executors.newScheduledThreadPool(24); private ServiceTracker threadDaoTracker; + private ServiceRegistration backendRegistration; private ReceiverRegistry registry; private ThreadHarvester harvester; + private ThreadBackend backend; @Override public void start(final BundleContext context) throws Exception { harvester = new ThreadHarvester(executor); + registry = new ReceiverRegistry(context); + VmStatusListenerRegistrar vmListener = new VmStatusListenerRegistrar(context); - registry = new ReceiverRegistry(context); - registry.registerReceiver(harvester); + /* + * dont register anything just yet, let the backend handle the + * registration, deregistration it when it's activated or deactivated + */ + + backend = new ThreadBackend(new Version(context.getBundle()), vmListener, registry, harvester); + backendRegistration = context.registerService(Backend.class, backend, null); threadDaoTracker = new ServiceTracker(context, ThreadDao.class.getName(), null) { @Override @@ -85,6 +99,12 @@ @Override public void stop(BundleContext context) throws Exception { + if (backend.isActive()) { + backend.deactivate(); + } + + backendRegistration.unregister(); + threadDaoTracker.close(); if (executor != null) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadBackendTest.java Fri Mar 22 16:43:10 2013 -0400 @@ -0,0 +1,90 @@ +/* + * Copyright 2012, 2013 Red Hat, Inc. + * + * This file is part of Thermostat. + * + * Thermostat is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * Thermostat is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Thermostat; see the file COPYING. If not see + * <http://www.gnu.org/licenses/>. + * + * Linking this code with other modules is making a combined work + * based on this code. Thus, the terms and conditions of the GNU + * General Public License cover the whole combination. + * + * As a special exception, the copyright holders of this code give + * you permission to link this code with independent modules to + * produce an executable, regardless of the license terms of these + * independent modules, and to copy and distribute the resulting + * executable under terms of your choice, provided that you also + * meet, for each linked independent module, the terms and conditions + * of the license of that module. An independent module is a module + * which is not derived from or based on this code. If you modify + * this code, you may extend this exception to your version of the + * library, but you are not obligated to do so. If you do not wish + * to do so, delete this exception statement from your version. + */ + +package com.redhat.thermostat.thread.harvester; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.agent.VmStatusListenerRegistrar; +import com.redhat.thermostat.agent.command.ReceiverRegistry; +import com.redhat.thermostat.common.Version; + +public class ThreadBackendTest { + + private Version version; + private VmStatusListenerRegistrar vmListenerRegistrar; + private ReceiverRegistry receiverRegistry; + private ThreadHarvester threadHarvester; + + private ThreadBackend backend; + + @Before + public void setUp() { + version = mock(Version.class); + when(version.getVersionNumber()).thenReturn("foobar"); + vmListenerRegistrar = mock(VmStatusListenerRegistrar.class); + receiverRegistry = mock(ReceiverRegistry.class); + threadHarvester = mock(ThreadHarvester.class); + + backend = new ThreadBackend(version, vmListenerRegistrar, receiverRegistry, threadHarvester); + } + + @Test + public void testActivate() { + assertTrue(backend.activate()); + + verify(vmListenerRegistrar).register(backend); + verify(receiverRegistry).registerReceiver(threadHarvester); + } + + @Test + public void testDeactivate() { + assertTrue(backend.activate()); + assertTrue(backend.isActive()); + assertTrue(backend.deactivate()); + assertFalse(backend.isActive()); + + verify(vmListenerRegistrar).unregister(backend); + verify(receiverRegistry).unregisterReceivers(); + } +}
--- a/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadHarvesterTest.java Fri Mar 22 13:05:51 2013 -0400 +++ b/thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadHarvesterTest.java Fri Mar 22 16:43:10 2013 -0400 @@ -129,18 +129,10 @@ public void testSaveVmCaps() { ScheduledExecutorService executor = mock(ScheduledExecutorService.class); ThreadDao dao = mock(ThreadDao.class); - Request request = mock(Request.class); final boolean[] getHarvesterCalled = new boolean[1]; final Harvester harverster = mock(Harvester.class); - ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class); - - when(request.getParameter(captor.capture())). - thenReturn(HarvesterCommand.VM_CAPS.name()). - thenReturn("42"). - thenReturn("0xcafe"); - ThreadHarvester threadHarvester = new ThreadHarvester(executor) { @Override Harvester getHarvester(String vmId) { @@ -152,13 +144,7 @@ } }; threadHarvester.setThreadDao(dao); - threadHarvester.receive(request); - - List<String> values = captor.getAllValues(); - assertEquals(2, values.size()); - - assertEquals(HarvesterCommand.class.getName(), values.get(0)); - assertEquals(HarvesterCommand.VM_ID.name(), values.get(1)); + threadHarvester.saveVmCaps("42"); assertTrue(getHarvesterCalled[0]);