# HG changeset patch # User Mario Torre # Date 1379492255 -7200 # Node ID ae64ab3629cae8f5e0e1c5ba44dc75d99844c145 # Parent 789a3be5013efa9ea288e5dbf081622a49153992 Host monitor API review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-August/007969.html reviewed-by: jerboaa diff -r 789a3be5013e -r ae64ab3629ca common/core/src/main/java/com/redhat/thermostat/common/ActionNotifier.java --- a/common/core/src/main/java/com/redhat/thermostat/common/ActionNotifier.java Wed Sep 18 10:16:49 2013 +0200 +++ b/common/core/src/main/java/com/redhat/thermostat/common/ActionNotifier.java Wed Sep 18 10:17:35 2013 +0200 @@ -68,6 +68,10 @@ fireAction(actionId, null); } + public int listenersCount() { + return listeners.size(); + } + public void fireAction(T actionId, Object payload) { ActionEvent action = new ActionEvent<>(source, actionId); action.setPayload(payload); diff -r 789a3be5013e -r ae64ab3629ca storage/core/pom.xml --- a/storage/core/pom.xml Wed Sep 18 10:16:49 2013 +0200 +++ b/storage/core/pom.xml Wed Sep 18 10:17:35 2013 +0200 @@ -69,6 +69,7 @@ com.redhat.thermostat.storage.model, com.redhat.thermostat.storage.dao, com.redhat.thermostat.storage.query, + com.redhat.thermostat.storage.monitor, <_nouses>true diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/main/java/com/redhat/thermostat/storage/internal/Activator.java --- a/storage/core/src/main/java/com/redhat/thermostat/storage/internal/Activator.java Wed Sep 18 10:16:49 2013 +0200 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/internal/Activator.java Wed Sep 18 10:17:35 2013 +0200 @@ -38,14 +38,16 @@ import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.UUID; 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.common.ApplicationService; +import com.redhat.thermostat.common.MultipleServiceTracker; +import com.redhat.thermostat.common.TimerFactory; import com.redhat.thermostat.storage.core.Storage; import com.redhat.thermostat.storage.core.WriterID; import com.redhat.thermostat.storage.dao.AgentInfoDAO; @@ -58,12 +60,16 @@ import com.redhat.thermostat.storage.internal.dao.HostInfoDAOImpl; import com.redhat.thermostat.storage.internal.dao.NetworkInterfaceInfoDAOImpl; import com.redhat.thermostat.storage.internal.dao.VmInfoDAOImpl; +import com.redhat.thermostat.storage.monitor.HostMonitor; +import com.redhat.thermostat.storage.monitor.NetworkMonitor; +import com.redhat.thermostat.storage.monitor.internal.HostMonitorImpl; +import com.redhat.thermostat.storage.monitor.internal.NetworkMonitorImpl; public class Activator implements BundleActivator { private static final String WRITER_UUID = UUID.randomUUID().toString(); - ServiceTracker tracker; + MultipleServiceTracker tracker; List> regs; public Activator() { @@ -71,44 +77,63 @@ } @Override - public void start(BundleContext context) throws Exception { + public void start(final BundleContext context) throws Exception { + Class[] deps = new Class[] { + Storage.class, + ApplicationService.class, + }; + // WriterID has to be registered unconditionally (at least not as part // of the Storage.class tracker, since that is only registered once // storage is connected). final WriterID writerID = new WriterIDImpl(WRITER_UUID); - ServiceRegistration reg = context.registerService(WriterID.class, writerID, null); + final ServiceRegistration reg = context.registerService(WriterID.class, writerID, null); regs.add(reg); - tracker = new ServiceTracker(context, Storage.class, null) { + tracker = new MultipleServiceTracker(context, deps, new MultipleServiceTracker.Action() { + @Override - public Storage addingService(ServiceReference reference) { - Storage storage = (Storage) super.addingService(reference); + public void dependenciesAvailable(Map services) { + + Storage storage = (Storage) services.get(Storage.class.getName()); AgentInfoDAO agentInfoDao = new AgentInfoDAOImpl(storage); + ServiceRegistration reg = context.registerService(AgentInfoDAO.class.getName(), agentInfoDao, null); regs.add(reg); + BackendInfoDAO backendInfoDao = new BackendInfoDAOImpl(storage); reg = context.registerService(BackendInfoDAO.class.getName(), backendInfoDao, null); regs.add(reg); + HostInfoDAO hostInfoDao = new HostInfoDAOImpl(storage, agentInfoDao); reg = context.registerService(HostInfoDAO.class.getName(), hostInfoDao, null); regs.add(reg); + NetworkInterfaceInfoDAO networkInfoDao = new NetworkInterfaceInfoDAOImpl(storage); reg = context.registerService(NetworkInterfaceInfoDAO.class.getName(), networkInfoDao, null); regs.add(reg); + VmInfoDAO vmInfoDao = new VmInfoDAOImpl(storage); reg = context.registerService(VmInfoDAO.class.getName(), vmInfoDao, null); regs.add(reg); - return storage; + + ApplicationService appService = (ApplicationService) services.get(ApplicationService.class.getName()); + TimerFactory timers = appService.getTimerFactory(); + NetworkMonitor networkMonitor = new NetworkMonitorImpl(timers, hostInfoDao); + reg = context.registerService(NetworkMonitor.class.getName(), networkMonitor, null); + regs.add(reg); + + HostMonitor hostMonitor = new HostMonitorImpl(timers, vmInfoDao); + reg = context.registerService(HostMonitor.class.getName(), hostMonitor, null); + regs.add(reg); } - + @Override - public void removedService(ServiceReference reference, - Storage service) { + public void dependenciesUnavailable() { unregisterServices(); - super.removedService(reference, service); } - }; - + }); + tracker.open(); } diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/main/java/com/redhat/thermostat/storage/monitor/HostMonitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/monitor/HostMonitor.java Wed Sep 18 10:17:35 2013 +0200 @@ -0,0 +1,62 @@ +/* + * 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 + * . + * + * 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.storage.monitor; + +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.VmRef; + +/** + * Monitors selected {@link HostRef} for {@link VmRef} lifecycle changes. + */ +public interface HostMonitor { + + public enum Action { + VM_ADDED, + VM_REMOVED, + } + + /** + * Adds this listener to the given {@link HostRef} + */ + void addHostChangeListener(HostRef host, ActionListener listener); + + /** + * Removes the listener to the given {@link HostRef} + */ + void removeHostChangeListener(HostRef host, ActionListener listener); +} diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/main/java/com/redhat/thermostat/storage/monitor/NetworkMonitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/monitor/NetworkMonitor.java Wed Sep 18 10:17:35 2013 +0200 @@ -0,0 +1,54 @@ +/* + * 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 + * . + * + * 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.storage.monitor; + +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.storage.core.HostRef; + +/** + * Monitors the network for addition, removals of new {@link HostRef}. + */ +public interface NetworkMonitor { + + public enum Action { + HOST_ADDED, + HOST_REMOVED, + } + + void addNetworkChangeListener(ActionListener listener); + void removeNetworkChangeListener(ActionListener listener); +} diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/main/java/com/redhat/thermostat/storage/monitor/internal/HostMonitorAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/monitor/internal/HostMonitorAction.java Wed Sep 18 10:17:35 2013 +0200 @@ -0,0 +1,85 @@ +/* + * 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 + * . + * + * 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.storage.monitor.internal; + +import java.util.ArrayList; +import java.util.Collection; + +import com.redhat.thermostat.common.ActionNotifier; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.dao.VmInfoDAO; +import com.redhat.thermostat.storage.model.VmInfo; +import com.redhat.thermostat.storage.monitor.HostMonitor; +import com.redhat.thermostat.storage.monitor.HostMonitor.Action; + +class HostMonitorAction extends MonitorAction { + + private VmInfoDAO vmsDao; + private HostRef host; + + public HostMonitorAction(ActionNotifier notifier, VmInfoDAO vmsDao, + HostRef host) + { + super(notifier); + this.host = host; + this.vmsDao = vmsDao; + } + + @Override + protected Action getAddAction() { + return HostMonitor.Action.VM_ADDED; + } + + @Override + protected Action getRemoveAction() { + return HostMonitor.Action.VM_REMOVED; + } + + @Override + protected Collection getNewReferences() { + Collection vms = vmsDao.getVMs(host); + Collection livingVMS = new ArrayList<>(); + for (VmRef vm : vms) { + VmInfo vmInfo = vmsDao.getVmInfo(vm); + if (vmInfo.isAlive()) { + livingVMS.add(vm); + } + } + return livingVMS; + } +} diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/main/java/com/redhat/thermostat/storage/monitor/internal/HostMonitorImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/monitor/internal/HostMonitorImpl.java Wed Sep 18 10:17:35 2013 +0200 @@ -0,0 +1,109 @@ +/* + * 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 + * . + * + * 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.storage.monitor.internal; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.ActionNotifier; +import com.redhat.thermostat.common.Pair; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.TimerFactory; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.dao.VmInfoDAO; +import com.redhat.thermostat.storage.monitor.HostMonitor; + +public class HostMonitorImpl implements HostMonitor { + + static final long DELAY = 200; + + private VmInfoDAO vmDao; + private TimerFactory timerFactory; + + private Map>> listeners; + + public HostMonitorImpl(TimerFactory timerFactory, VmInfoDAO vmDao) { + this.vmDao = vmDao; + this.timerFactory = timerFactory; + listeners = new ConcurrentHashMap<>(); + } + + Map>> getListeners() { + return listeners; + } + + @Override + public void addHostChangeListener(HostRef host, + ActionListener listener) + { + Pair> payload = + listeners.get(host); + if (payload == null) { + ActionNotifier notifier = new ActionNotifier<>(this); + Timer timer = timerFactory.createTimer(); + + timer.setTimeUnit(TimeUnit.MILLISECONDS); + timer.setDelay(DELAY); + timer.setSchedulingType(Timer.SchedulingType.FIXED_RATE); + timer.setAction(new HostMonitorAction(notifier, vmDao, host)); + timer.start(); + + payload = new Pair<>(timer, notifier); + listeners.put(host, payload); + } + + payload.getSecond().addActionListener(listener); + } + + @Override + public void removeHostChangeListener(HostRef host, + ActionListener listener) + { + Pair> payload = + listeners.get(host); + if (payload != null) { + ActionNotifier notifier = payload.getSecond(); + notifier.removeActionListener(listener); + if (notifier.listenersCount() == 0) { + payload.getFirst().stop(); + listeners.remove(host); + } + } + } +} diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/main/java/com/redhat/thermostat/storage/monitor/internal/MonitorAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/monitor/internal/MonitorAction.java Wed Sep 18 10:17:35 2013 +0200 @@ -0,0 +1,95 @@ +/* + * 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 + * . + * + * 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.storage.monitor.internal; + +import java.util.ArrayList; +import java.util.Collection; + +import com.redhat.thermostat.common.ActionNotifier; +import com.redhat.thermostat.storage.core.Ref; + +abstract class MonitorAction> implements Runnable { + + private static final String LOCK = new String("MonitorAction_LOCK"); + + private ActionNotifier notifier; + Collection references; + + public MonitorAction(ActionNotifier notifier) { + references = new ArrayList<>(); + this.notifier = notifier; + } + + @Override + public void run() { + Collection newReferences = getNewReferences(); + Collection _refs = null; + + synchronized (LOCK) { + _refs = new ArrayList<>(references); + references = new ArrayList<>(newReferences); + } + + handleRemovedHosts(_refs, newReferences); + handleAddedReferences(_refs, newReferences); + } + + private void handleAddedReferences(Collection currentReference, + Collection newReference) + { + Collection copy = new ArrayList<>(newReference); + copy.removeAll(currentReference); + for (R reference : copy) { + notifier.fireAction(getAddAction(), reference); + } + } + + private void handleRemovedHosts(Collection currentReference, + Collection newReference) + { + Collection copy = new ArrayList<>(currentReference); + copy.removeAll(newReference); + for (R reference : copy) { + notifier.fireAction(getRemoveAction(), reference); + } + } + + protected abstract A getAddAction(); + protected abstract A getRemoveAction(); + + protected abstract Collection getNewReferences(); +} diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/main/java/com/redhat/thermostat/storage/monitor/internal/NetworkMonitorAction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/monitor/internal/NetworkMonitorAction.java Wed Sep 18 10:17:35 2013 +0200 @@ -0,0 +1,74 @@ +/* + * 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 + * . + * + * 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.storage.monitor.internal; + +import java.util.Collection; + +import com.redhat.thermostat.common.ActionNotifier; + +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.dao.HostInfoDAO; + +import com.redhat.thermostat.storage.monitor.NetworkMonitor; +import com.redhat.thermostat.storage.monitor.NetworkMonitor.Action; + +class NetworkMonitorAction extends MonitorAction { + + private HostInfoDAO hostDAO; + + public NetworkMonitorAction(ActionNotifier notifier, + HostInfoDAO hostDAO) + { + super(notifier); + this.hostDAO = hostDAO; + } + + @Override + protected Action getAddAction() { + return NetworkMonitor.Action.HOST_ADDED; + } + + @Override + protected Action getRemoveAction() { + return NetworkMonitor.Action.HOST_REMOVED; + } + + @Override + protected Collection getNewReferences() { + return hostDAO.getAliveHosts(); + } +} diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/main/java/com/redhat/thermostat/storage/monitor/internal/NetworkMonitorImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/main/java/com/redhat/thermostat/storage/monitor/internal/NetworkMonitorImpl.java Wed Sep 18 10:17:35 2013 +0200 @@ -0,0 +1,82 @@ +/* + * 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 + * . + * + * 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.storage.monitor.internal; + +import java.util.concurrent.TimeUnit; + +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.ActionNotifier; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.TimerFactory; +import com.redhat.thermostat.storage.dao.HostInfoDAO; +import com.redhat.thermostat.storage.monitor.NetworkMonitor; + +public class NetworkMonitorImpl implements NetworkMonitor { + + public static final long DELAY = 1; + + protected final ActionNotifier notifier; + + private Timer timer; + + public NetworkMonitorImpl(TimerFactory timerFactory, HostInfoDAO hostDAO) { + + notifier = new ActionNotifier<>(this); + + timer = timerFactory.createTimer(); + timer.setTimeUnit(TimeUnit.SECONDS); + timer.setDelay(DELAY); + timer.setSchedulingType(Timer.SchedulingType.FIXED_RATE); + timer.setAction(new NetworkMonitorAction(notifier, hostDAO)); + } + + @Override + public void addNetworkChangeListener(ActionListener listener) { + notifier.addActionListener(listener); + if (notifier.listenersCount() == 1) { + timer.start(); + } + } + + @Override + public void removeNetworkChangeListener(ActionListener listener) { + notifier.removeActionListener(listener); + if (notifier.listenersCount() == 0) { + timer.stop(); + } + } +} diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/test/java/com/redhat/thermostat/storage/internal/ActivatorTest.java --- a/storage/core/src/test/java/com/redhat/thermostat/storage/internal/ActivatorTest.java Wed Sep 18 10:16:49 2013 +0200 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/internal/ActivatorTest.java Wed Sep 18 10:17:35 2013 +0200 @@ -40,9 +40,13 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import org.junit.Test; +import com.redhat.thermostat.common.ApplicationService; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.TimerFactory; import com.redhat.thermostat.storage.core.Storage; import com.redhat.thermostat.storage.core.WriterID; import com.redhat.thermostat.storage.dao.AgentInfoDAO; @@ -55,6 +59,10 @@ import com.redhat.thermostat.storage.internal.dao.HostInfoDAOImpl; import com.redhat.thermostat.storage.internal.dao.NetworkInterfaceInfoDAOImpl; import com.redhat.thermostat.storage.internal.dao.VmInfoDAOImpl; +import com.redhat.thermostat.storage.monitor.HostMonitor; +import com.redhat.thermostat.storage.monitor.NetworkMonitor; +import com.redhat.thermostat.storage.monitor.internal.HostMonitorImpl; +import com.redhat.thermostat.storage.monitor.internal.NetworkMonitorImpl; import com.redhat.thermostat.testutils.StubBundleContext; public class ActivatorTest { @@ -69,7 +77,7 @@ // WriterID should get registered unconditionally assertEquals("At least WriterID service must be registered", 1, context.getAllServices().size()); - assertEquals(1, context.getServiceListeners().size()); + assertEquals(2, context.getServiceListeners().size()); activator.stop(context); assertEquals(0, context.getAllServices().size()); @@ -80,7 +88,15 @@ public void verifyActivatorRegistersServices() throws Exception { StubBundleContext context = new StubBundleContext(); Storage storage = mock(Storage.class); + + ApplicationService appService = mock(ApplicationService.class); + TimerFactory timerFactory = mock(TimerFactory.class); + when(appService.getTimerFactory()).thenReturn(timerFactory); + + Timer timer = mock(Timer.class); + when(timerFactory.createTimer()).thenReturn(timer); + context.registerService(ApplicationService.class, appService, null); context.registerService(Storage.class, storage, null); Activator activator = new Activator(); @@ -98,7 +114,7 @@ assertEquals(0, context.getServiceListeners().size()); - assertEquals(1, context.getAllServices().size()); + assertEquals(2, context.getAllServices().size()); } @Test @@ -106,7 +122,15 @@ StubBundleContext context = new StubBundleContext(); Storage storage = mock(Storage.class); + ApplicationService appService = mock(ApplicationService.class); + TimerFactory timerFactory = mock(TimerFactory.class); + when(appService.getTimerFactory()).thenReturn(timerFactory); + + Timer timer = mock(Timer.class); + when(timerFactory.createTimer()).thenReturn(timer); + context.registerService(Storage.class, storage, null); + context.registerService(ApplicationService.class, appService, null); Activator activator = new Activator(); @@ -122,20 +146,30 @@ assertFalse(context.isServiceRegistered(WriterID.class.getName(), WriterIDImpl.class)); assertEquals(0, context.getServiceListeners().size()); - assertEquals(1, context.getAllServices().size()); + assertEquals(2, context.getAllServices().size()); } @Test public void verifyActivatorRegistersServicesMultipleTimes() throws Exception { StubBundleContext context = new StubBundleContext(); Storage storage = mock(Storage.class); + + ApplicationService appService = mock(ApplicationService.class); + TimerFactory timerFactory = mock(TimerFactory.class); + when(appService.getTimerFactory()).thenReturn(timerFactory); + Timer timer = mock(Timer.class); + when(timerFactory.createTimer()).thenReturn(timer); context.registerService(Storage.class, storage, null); + context.registerService(ApplicationService.class, appService, null); Activator activator = new Activator(); activator.start(context); + assertTrue(context.isServiceRegistered(NetworkMonitor.class.getName(), NetworkMonitorImpl.class)); + assertTrue(context.isServiceRegistered(HostMonitor.class.getName(), HostMonitorImpl.class)); + assertTrue(context.isServiceRegistered(HostInfoDAO.class.getName(), HostInfoDAOImpl.class)); assertTrue(context.isServiceRegistered(NetworkInterfaceInfoDAO.class.getName(), NetworkInterfaceInfoDAOImpl.class)); assertTrue(context.isServiceRegistered(VmInfoDAO.class.getName(), VmInfoDAOImpl.class)); @@ -146,10 +180,13 @@ activator.stop(context); assertEquals(0, context.getServiceListeners().size()); - assertEquals(1, context.getAllServices().size()); + assertEquals(2, context.getAllServices().size()); activator.start(context); + assertTrue(context.isServiceRegistered(NetworkMonitor.class.getName(), NetworkMonitorImpl.class)); + assertTrue(context.isServiceRegistered(HostMonitor.class.getName(), HostMonitorImpl.class)); + assertTrue(context.isServiceRegistered(HostInfoDAO.class.getName(), HostInfoDAOImpl.class)); assertTrue(context.isServiceRegistered(NetworkInterfaceInfoDAO.class.getName(), NetworkInterfaceInfoDAOImpl.class)); assertTrue(context.isServiceRegistered(VmInfoDAO.class.getName(), VmInfoDAOImpl.class)); @@ -160,7 +197,8 @@ activator.stop(context); assertEquals(0, context.getServiceListeners().size()); - assertEquals(1, context.getAllServices().size()); + assertEquals(2, context.getAllServices().size()); + } } diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/test/java/com/redhat/thermostat/storage/monitor/internal/HostMonitorActionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/monitor/internal/HostMonitorActionTest.java Wed Sep 18 10:17:35 2013 +0200 @@ -0,0 +1,151 @@ +/* + * 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 + * . + * + * 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.storage.monitor.internal; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.times; + +import java.util.ArrayList; +import java.util.Collection; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.common.ActionNotifier; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.core.VmRef; +import com.redhat.thermostat.storage.dao.VmInfoDAO; +import com.redhat.thermostat.storage.model.VmInfo; +import com.redhat.thermostat.storage.monitor.HostMonitor; +import com.redhat.thermostat.storage.monitor.HostMonitor.Action; + +public class HostMonitorActionTest { + + private VmInfoDAO vmsDAO; + + private ActionNotifier notifier; + + @SuppressWarnings("unchecked") + @Before + public void setup() { + vmsDAO = mock(VmInfoDAO.class); + notifier = mock(ActionNotifier.class); + } + + @Test + public void testAddRemoveVMS() { + + HostRef host = new HostRef("01", "01"); + + Collection currentVMs = new ArrayList<>(); + VmRef a = new VmRef(host, "0", 0, "a"); + VmRef b = new VmRef(host, "1", 1, "b"); + VmRef c = new VmRef(host, "2", 2, "c"); + VmRef d = new VmRef(host, "3", 3, "d"); + VmRef e = new VmRef(host, "4", 3, "e"); + + VmInfo info_a = mock(VmInfo.class); + when(info_a.isAlive()).thenReturn(true); + + VmInfo info_b = mock(VmInfo.class); + when(info_b.isAlive()).thenReturn(true); + + VmInfo info_c = mock(VmInfo.class); + when(info_c.isAlive()).thenReturn(true); + + VmInfo info_d = mock(VmInfo.class); + when(info_d.isAlive()).thenReturn(true); + + VmInfo info_e = mock(VmInfo.class); + when(info_e.isAlive()).thenReturn(false); + + when(vmsDAO.getVmInfo(a)).thenReturn(info_a); + when(vmsDAO.getVmInfo(b)).thenReturn(info_b); + when(vmsDAO.getVmInfo(c)).thenReturn(info_c); + when(vmsDAO.getVmInfo(d)).thenReturn(info_d); + when(vmsDAO.getVmInfo(e)).thenReturn(info_e); + + currentVMs.add(a); + currentVMs.add(b); + currentVMs.add(c); + currentVMs.add(d); + currentVMs.add(e); + + when(vmsDAO.getVMs(host)).thenReturn(currentVMs); + + + // the first result is to be notified of all those vms + HostMonitorAction action = new HostMonitorAction(notifier, vmsDAO, host); + action.run(); + + verify(notifier).fireAction(Action.VM_ADDED, a); + verify(notifier).fireAction(Action.VM_ADDED, b); + verify(notifier).fireAction(Action.VM_ADDED, c); + verify(notifier).fireAction(Action.VM_ADDED, d); + + verify(notifier,times(0)).fireAction(Action.VM_ADDED, e); + verify(notifier, times(0)).fireAction(Action.VM_REMOVED, eq(any(VmRef.class))); + + // now remove one vm from each side + currentVMs.remove(b); + currentVMs.remove(c); + + action.run(); + + verify(notifier).fireAction(Action.VM_REMOVED, b); + verify(notifier).fireAction(Action.VM_REMOVED, c); + + verify(notifier, times(0)).fireAction(Action.VM_ADDED, eq(any(VmRef.class))); + + when(info_a.isAlive()).thenReturn(false); + + // not that a process can ever become alive again :) + when(info_e.isAlive()).thenReturn(true); + + action.run(); + + verify(notifier,times(1)).fireAction(Action.VM_ADDED, e); + verify(notifier,times(1)).fireAction(Action.VM_REMOVED, a); + + verify(notifier, times(0)).fireAction(Action.VM_ADDED, eq(any(VmRef.class))); + verify(notifier, times(0)).fireAction(Action.VM_REMOVED, eq(any(VmRef.class))); + } +} diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/test/java/com/redhat/thermostat/storage/monitor/internal/HostMonitorImplTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/monitor/internal/HostMonitorImplTest.java Wed Sep 18 10:17:35 2013 +0200 @@ -0,0 +1,127 @@ +/* + * 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 + * . + * + * 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.storage.monitor.internal; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.times; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.ActionNotifier; +import com.redhat.thermostat.common.Pair; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.TimerFactory; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.dao.VmInfoDAO; +import com.redhat.thermostat.storage.monitor.HostMonitor; + +public class HostMonitorImplTest { + + private VmInfoDAO vmDao; + private TimerFactory timerFactory; + + @Before + public void setup() { + vmDao = mock(VmInfoDAO.class); + timerFactory = mock(TimerFactory.class); + } + + @SuppressWarnings("unchecked") + @Test + public void test() { + ActionListener listener1 = mock(ActionListener.class); + ActionListener listener2 = mock(ActionListener.class); + + Timer timer1 = mock(Timer.class); + when(timerFactory.createTimer()).thenReturn(timer1); + + HostRef host1 = new HostRef("0", "0"); + + HostMonitor monitor = new HostMonitorImpl(timerFactory, vmDao); + Map>> listeners = + ((HostMonitorImpl) monitor).getListeners(); + assertTrue(listeners.isEmpty()); + + monitor.addHostChangeListener(host1, listener1); + + assertEquals(1, listeners.size()); + + verify(timer1, times(1)).setTimeUnit(TimeUnit.MILLISECONDS); + verify(timer1, times(1)).setDelay(HostMonitorImpl.DELAY); + verify(timer1, times(1)).setSchedulingType(Timer.SchedulingType.FIXED_RATE); + verify(timer1, times(1)).start(); + + verify(timer1).setAction(any(HostMonitorAction.class)); + + monitor.addHostChangeListener(host1, listener2); + + assertEquals(1, listeners.size()); + + verify(timer1, times(1)).setTimeUnit(TimeUnit.MILLISECONDS); + verify(timer1, times(1)).setDelay(HostMonitorImpl.DELAY); + verify(timer1, times(1)).start(); + verify(timer1, times(1)).setSchedulingType(Timer.SchedulingType.FIXED_RATE); + + verify(timer1).setAction(any(HostMonitorAction.class)); + + monitor.removeHostChangeListener(host1, listener1); + verify(timer1, times(0)).stop(); + + assertEquals(1, listeners.size()); + monitor.removeHostChangeListener(host1, listener2); + + assertTrue(listeners.isEmpty()); + verify(timer1, times(1)).stop(); + + HostRef host2 = new HostRef("1", "1"); + + monitor.addHostChangeListener(host1, listener1); + monitor.addHostChangeListener(host2, listener2); + } + +} diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/test/java/com/redhat/thermostat/storage/monitor/internal/NetworkMonitorActionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/monitor/internal/NetworkMonitorActionTest.java Wed Sep 18 10:17:35 2013 +0200 @@ -0,0 +1,125 @@ +/* + * 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 + * . + * + * 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.storage.monitor.internal; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Collection; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.common.ActionNotifier; +import com.redhat.thermostat.storage.core.HostRef; +import com.redhat.thermostat.storage.dao.HostInfoDAO; +import com.redhat.thermostat.storage.monitor.NetworkMonitor; +import com.redhat.thermostat.storage.monitor.NetworkMonitor.Action; + +public class NetworkMonitorActionTest { + + private HostInfoDAO hostDAO; + + private ActionNotifier notifier; + + @SuppressWarnings("unchecked") + @Before + public void setup() { + hostDAO = mock(HostInfoDAO.class); + notifier = mock(ActionNotifier.class); + } + + @Test + public void testAddRemoveHost() { + + Collection currentHosts = new ArrayList<>(); + HostRef a = new HostRef("0", "a"); + HostRef b = new HostRef("1", "b"); + HostRef c = new HostRef("2", "c"); + HostRef d = new HostRef("3", "d"); + + currentHosts.add(a); + currentHosts.add(b); + currentHosts.add(c); + currentHosts.add(d); + + when(hostDAO.getAliveHosts()).thenReturn(currentHosts); + + // the first result is to be notified of all those hosts + NetworkMonitorAction action = new NetworkMonitorAction(notifier, hostDAO); + action.run(); + + verify(notifier).fireAction(Action.HOST_ADDED, a); + verify(notifier).fireAction(Action.HOST_ADDED, b); + verify(notifier).fireAction(Action.HOST_ADDED, c); + verify(notifier).fireAction(Action.HOST_ADDED, d); + + verify(notifier, times(0)).fireAction(Action.HOST_REMOVED, eq(any(HostRef.class))); + + // now remove a from the series, add e + HostRef e = new HostRef("4", "e"); + currentHosts.add(e); + currentHosts.remove(a); + + action.run(); + + verify(notifier).fireAction(Action.HOST_REMOVED, a); + verify(notifier).fireAction(Action.HOST_ADDED, e); + + // now add f from the series, no host removal + HostRef f = new HostRef("5", "f"); + currentHosts.add(f); + + action.run(); + + verify(notifier).fireAction(Action.HOST_ADDED, f); + verify(notifier, times(0)).fireAction(Action.HOST_REMOVED, eq(any(HostRef.class))); + + // now only remove f from the series, no other changes + currentHosts.remove(f); + + action.run(); + + verify(notifier).fireAction(Action.HOST_REMOVED, f); + verify(notifier, times(0)).fireAction(Action.HOST_ADDED, eq(any(HostRef.class))); + } +} diff -r 789a3be5013e -r ae64ab3629ca storage/core/src/test/java/com/redhat/thermostat/storage/monitor/internal/NetworkMonitorImplTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/storage/core/src/test/java/com/redhat/thermostat/storage/monitor/internal/NetworkMonitorImplTest.java Wed Sep 18 10:17:35 2013 +0200 @@ -0,0 +1,100 @@ +/* + * 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 + * . + * + * 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.storage.monitor.internal; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.times; + +import java.util.concurrent.TimeUnit; + +import org.junit.Before; +import org.junit.Test; + +import com.redhat.thermostat.common.ActionListener; +import com.redhat.thermostat.common.Timer; +import com.redhat.thermostat.common.TimerFactory; +import com.redhat.thermostat.storage.dao.HostInfoDAO; +import com.redhat.thermostat.storage.monitor.NetworkMonitor; +import com.redhat.thermostat.storage.monitor.NetworkMonitor.Action; + +public class NetworkMonitorImplTest { + + private HostInfoDAO hostDao; + private TimerFactory timerFactory; + + @Before + public void setup() { + hostDao = mock(HostInfoDAO.class); + timerFactory = mock(TimerFactory.class); + } + + @SuppressWarnings("unchecked") + @Test + public void test() { + + ActionListener listener1 = mock(ActionListener.class); + ActionListener listener2 = mock(ActionListener.class); + + Timer timer = mock(Timer.class); + when(timerFactory.createTimer()).thenReturn(timer); + + NetworkMonitor monitor = new NetworkMonitorImpl(timerFactory, hostDao); + monitor.addNetworkChangeListener(listener1); + + verify(timer).setTimeUnit(TimeUnit.SECONDS); + verify(timer).setDelay(NetworkMonitorImpl.DELAY); + verify(timer).setSchedulingType(Timer.SchedulingType.FIXED_RATE); + + verify(timer).start(); + verify(timer, times(0)).stop(); + + monitor.addNetworkChangeListener(listener2); + + verify(timer, times(1)).start(); + verify(timer, times(0)).stop(); + + monitor.removeNetworkChangeListener(listener1); + verify(timer, times(0)).stop(); + verify(timer, times(1)).start(); + + monitor.removeNetworkChangeListener(listener2); + verify(timer).stop(); + } + +}