changeset 1744:a23998f093d2

Add new API for tracking a command's dependencies Reviewed-by: omajid Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2015-September/015729.html PR2605
author Severin Gehwolf <sgehwolf@redhat.com>
date Wed, 02 Sep 2015 17:54:51 +0200
parents ca91f13ef261
children 0e4c60a50547
files common/core/src/main/java/com/redhat/thermostat/common/cli/DependencyServices.java common/core/src/test/java/com/redhat/thermostat/common/cli/DependencyServicesTest.java vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/ShowGcNameCommand.java vm-profiler/client-cli/src/main/java/com/redhat/thermostat/vm/profiler/client/cli/internal/DependencyServices.java vm-profiler/client-cli/src/main/java/com/redhat/thermostat/vm/profiler/client/cli/internal/ProfileVmCommand.java vm-profiler/client-cli/src/test/java/com/redhat/thermostat/vm/profiler/client/cli/internal/DependencyServicesTest.java
diffstat 6 files changed, 182 insertions(+), 188 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/main/java/com/redhat/thermostat/common/cli/DependencyServices.java	Wed Sep 02 17:54:51 2015 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2012-2015 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.common.cli;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Contains dependencies for a command.
+ *
+ * Provides ways to add ({@link #addService(Class, Object)}), remove (
+ * {@link #removeService(Class)}) and fetch ({@link #getService(Class)})
+ * services. Fetching has timeout support.
+ */
+public class DependencyServices {
+
+    private Map<Class<?>, BlockingQueue<?>> serviceHolder = new HashMap<>();
+
+    private <T> BlockingQueue<T> getHolder(Class<T> serviceClass) {
+        if (!serviceHolder.containsKey(serviceClass)) {
+            serviceHolder.put(serviceClass, new LinkedBlockingQueue<T>(1));
+        }
+        return (BlockingQueue<T>) serviceHolder.get(serviceClass);
+    }
+
+    /** @throws IllegalArgumentException if service is already added */
+    public <T> void addService(Class<T> serviceClass, T item) {
+        Objects.requireNonNull(item);
+        BlockingQueue<T> holder = getHolder(serviceClass);
+        boolean added = holder.offer(item);
+        if (!added) {
+            throw new IllegalArgumentException("service is already being tracked");
+        }
+    }
+
+    public <T> void removeService(Class<T> serviceClass) {
+        BlockingQueue<T> holder = getHolder(serviceClass);
+        if (holder.peek() != null) {
+            holder.remove();
+        }
+    }
+
+    /** @return the service, or {@code null} */
+    public <T> T getService(Class<T> serviceClass) {
+        BlockingQueue<T> holder = getHolder(serviceClass);
+        try {
+            // a crappy version of peek()-with-timeout
+            T retValue = holder.poll(500, TimeUnit.MILLISECONDS);
+            if (retValue != null) {
+                holder.add(retValue);
+            }
+            return retValue;
+        } catch (InterruptedException e) {
+            return null;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/core/src/test/java/com/redhat/thermostat/common/cli/DependencyServicesTest.java	Wed Sep 02 17:54:51 2015 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012-2015 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.common.cli;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+
+public class DependencyServicesTest {
+
+    @Test
+    public void uninjectedServiceIsNotAvailable() throws Exception {
+        DependencyServices services = new DependencyServices();
+
+        assertNull(services.getService(Object.class));
+    }
+
+    @Test
+    public void injectedServiceIsAvailable() throws Exception {
+        DependencyServices services = new DependencyServices();
+        services.addService(Object.class, services);
+
+        assertEquals(services, services.getService(Object.class));
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void injectingSameServiceTwiceIsAnError() {
+        DependencyServices services = new DependencyServices();
+        services.addService(Object.class, services);
+        services.addService(Object.class, services);
+    }
+
+    @Test
+    public void injectedAndRemovedServiceIsNotAvailable() {
+        DependencyServices services = new DependencyServices();
+        services.addService(Object.class, services);
+
+        services.removeService(Object.class);
+        assertNull(services.getService(Object.class));
+    }
+}
--- a/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/ShowGcNameCommand.java	Wed Sep 02 18:49:42 2015 +0200
+++ b/vm-gc/command/src/main/java/com/redhat/thermostat/vm/gc/command/internal/ShowGcNameCommand.java	Wed Sep 02 17:54:51 2015 +0200
@@ -38,13 +38,12 @@
 
 import java.io.PrintStream;
 import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
 
 import com.redhat.thermostat.client.cli.HostVMArguments;
 import com.redhat.thermostat.common.cli.AbstractCommand;
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandException;
+import com.redhat.thermostat.common.cli.DependencyServices;
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.storage.core.VmId;
@@ -62,18 +61,15 @@
     static final String REGISTER_NAME = "show-gc-name";
     private static final Translate<LocaleResources> translator = LocaleResources.createLocalizer();
     private static final GcCommonNameMapper mapper = new GcCommonNameMapper();
-    private CountDownLatch servicesAvailableLatch = new CountDownLatch(2); // vmInfo dao and vmGcStat dao
+    private final DependencyServices services = new DependencyServices();
     private VmInfoDAO vmInfoDao;
     private VmGcStatDAO gcDao;
     
     @Override
     public void run(CommandContext ctx) throws CommandException {
-        try {
-            servicesAvailableLatch.await(500, TimeUnit.MILLISECONDS);
-        } catch (InterruptedException e) {
-            throw new CommandException(translator.localize(LocaleResources.COMMAND_INTERRUPTED));
-        }
-        
+        this.vmInfoDao = services.getService(VmInfoDAO.class);
+        this.gcDao = services.getService(VmGcStatDAO.class);
+    	
         requireNonNull(vmInfoDao, translator.localize(LocaleResources.VM_SERVICE_UNAVAILABLE));
         requireNonNull(gcDao, translator.localize(LocaleResources.GC_STAT_DAO_SERVICE_UNAVAILABLE));
         
@@ -91,19 +87,16 @@
     }
     
     void setVmInfo(VmInfoDAO vmInfoDAO) {
-        this.vmInfoDao = vmInfoDAO;
-        servicesAvailableLatch.countDown();
+        services.addService(VmInfoDAO.class, vmInfoDAO);
     }
     
     void setVmGcStat(VmGcStatDAO vmGcStat) {
-        this.gcDao = vmGcStat;
-        servicesAvailableLatch.countDown();
+        services.addService(VmGcStatDAO.class, vmGcStat);
     }
     
     void servicesUnavailable() {
-        this.gcDao = null;
-        this.vmInfoDao = null;
-        servicesAvailableLatch = new CountDownLatch(2);
+        services.removeService(VmInfoDAO.class);
+        services.removeService(VmGcStatDAO.class);
     }
     
     /**
--- a/vm-profiler/client-cli/src/main/java/com/redhat/thermostat/vm/profiler/client/cli/internal/DependencyServices.java	Wed Sep 02 18:49:42 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright 2012-2015 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.vm.profiler.client.cli.internal;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Contains dependencies for a command.
- *
- * Provides ways to add ({@link #addService(Class, Object)}), remove (
- * {@link #removeService(Class)}) and fetch ({@link #getService(Class)})
- * services. Fetching has timeout support.
- */
-public class DependencyServices {
-
-    private Map<Class<?>, BlockingQueue<?>> serviceHolder = new HashMap<>();
-
-    private <T> BlockingQueue<T> getHolder(Class<T> serviceClass) {
-        if (!serviceHolder.containsKey(serviceClass)) {
-            serviceHolder.put(serviceClass, new LinkedBlockingQueue<T>(1));
-        }
-        return (BlockingQueue<T>) serviceHolder.get(serviceClass);
-    }
-
-    /** @throws IllegalArgumentException if service is already added */
-    public <T> void addService(Class<T> serviceClass, T item) {
-        Objects.requireNonNull(item);
-        BlockingQueue<T> holder = getHolder(serviceClass);
-        boolean added = holder.offer(item);
-        if (!added) {
-            throw new IllegalArgumentException("service is already being tracked");
-        }
-    }
-
-    public <T> void removeService(Class<T> serviceClass) {
-        BlockingQueue<T> holder = getHolder(serviceClass);
-        if (holder.peek() != null) {
-            holder.remove();
-        }
-    }
-
-    /** @return the service, or {@code null} */
-    public <T> T getService(Class<T> serviceClass) {
-        BlockingQueue<T> holder = getHolder(serviceClass);
-        try {
-            // a crappy version of peek()-with-timeout
-            T retValue = holder.poll(500, TimeUnit.MILLISECONDS);
-            if (retValue != null) {
-                holder.add(retValue);
-            }
-            return retValue;
-        } catch (InterruptedException e) {
-            return null;
-        }
-    }
-
-}
--- a/vm-profiler/client-cli/src/main/java/com/redhat/thermostat/vm/profiler/client/cli/internal/ProfileVmCommand.java	Wed Sep 02 18:49:42 2015 +0200
+++ b/vm-profiler/client-cli/src/main/java/com/redhat/thermostat/vm/profiler/client/cli/internal/ProfileVmCommand.java	Wed Sep 02 17:54:51 2015 +0200
@@ -50,6 +50,7 @@
 import com.redhat.thermostat.common.cli.CommandContext;
 import com.redhat.thermostat.common.cli.CommandException;
 import com.redhat.thermostat.common.cli.Console;
+import com.redhat.thermostat.common.cli.DependencyServices;
 import com.redhat.thermostat.common.command.Request;
 import com.redhat.thermostat.common.command.RequestResponseListener;
 import com.redhat.thermostat.common.command.Response;
--- a/vm-profiler/client-cli/src/test/java/com/redhat/thermostat/vm/profiler/client/cli/internal/DependencyServicesTest.java	Wed Sep 02 18:49:42 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright 2012-2015 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.vm.profiler.client.cli.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import org.junit.Test;
-
-public class DependencyServicesTest {
-
-    @Test
-    public void uninjectedServiceIsNotAvailable() throws Exception {
-        DependencyServices services = new DependencyServices();
-
-        assertNull(services.getService(Object.class));
-    }
-
-    @Test
-    public void injectedServiceIsAvailable() throws Exception {
-        DependencyServices services = new DependencyServices();
-        services.addService(Object.class, services);
-
-        assertEquals(services, services.getService(Object.class));
-    }
-
-    @Test(expected=IllegalArgumentException.class)
-    public void injectingSameServiceTwiceIsAnError() {
-        DependencyServices services = new DependencyServices();
-        services.addService(Object.class, services);
-        services.addService(Object.class, services);
-    }
-
-    @Test
-    public void injectedAndRemovedServiceIsNotAvailable() {
-        DependencyServices services = new DependencyServices();
-        services.addService(Object.class, services);
-
-        services.removeService(Object.class);
-        assertNull(services.getService(Object.class));
-    }
-}