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
author Omair Majid <omajid@redhat.com>
date Fri, 22 Mar 2013 16:43:10 -0400
parents 90fa1f866982
children edaf77f17cbd
files thread/client-common/src/main/java/com/redhat/thermostat/thread/client/common/collector/impl/ThreadMXBeanCollector.java thread/client-common/src/test/java/com/redhat/thermostat/thread/client/common/collector/impl/ThreadCollectorTest.java thread/collector/src/main/java/com/redhat/thermostat/thread/collector/HarvesterCommand.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadBackend.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/ThreadHarvester.java thread/harvester/src/main/java/com/redhat/thermostat/thread/harvester/osgi/Activator.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadBackendTest.java thread/harvester/src/test/java/com/redhat/thermostat/thread/harvester/ThreadHarvesterTest.java
diffstat 8 files changed, 228 insertions(+), 122 deletions(-) [+]
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]);