| /******************************************************************************* |
| * Copyright (c) 2014, 2019 Red Hat. |
| * |
| * This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 |
| * which is available at https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Red Hat - Initial Contribution |
| *******************************************************************************/ |
| package org.eclipse.linuxtools.internal.docker.core; |
| |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.TimeUnit; |
| |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.linuxtools.docker.core.Activator; |
| import org.eclipse.linuxtools.docker.core.IDockerConnection; |
| import org.eclipse.linuxtools.docker.core.IDockerContainer; |
| import org.eclipse.linuxtools.docker.core.IDockerContainerListener; |
| |
| public class DockerContainerRefreshManager implements IDockerContainerListener { |
| |
| private static DockerContainerRefreshManager instance; |
| private final long DEFAULT_REFRESH_TIME = 15; |
| |
| private Map<IDockerConnection, ContainerRefreshThread> refreshThreadMap; |
| |
| private DockerContainerRefreshManager() { |
| this.refreshThreadMap = new HashMap<>(); |
| } |
| |
| public static DockerContainerRefreshManager getInstance() { |
| if (instance == null) |
| instance = new DockerContainerRefreshManager(); |
| return instance; |
| } |
| |
| /** |
| * @return an immutable {@link Set} of all the {@link IDockerConnection} |
| * that are monitored |
| */ |
| public Set<IDockerConnection> getConnections() { |
| return Collections.unmodifiableSet(this.refreshThreadMap.keySet()); |
| } |
| |
| @Override |
| public synchronized void listChanged( |
| final IDockerConnection connection, |
| final List<IDockerContainer> dclist) { |
| if (!this.refreshThreadMap.containsKey(connection)) { |
| long refreshRateInSeconds = Platform.getPreferencesService() |
| .getLong("org.eclipse.linuxtools.docker.ui", //$NON-NLS-1$ |
| "containerRefreshTime", DEFAULT_REFRESH_TIME, null); //$NON-NLS-1$ |
| final ContainerRefreshThread rt = new ContainerRefreshThread( |
| connection, |
| TimeUnit.SECONDS.toMillis(refreshRateInSeconds)); |
| rt.start(); |
| this.refreshThreadMap.put(connection, rt); |
| } |
| } |
| |
| /** |
| * Stops and remove the {@link ContainerRefreshThread} associated with the |
| * given {@link IDockerConnection}. |
| * |
| * @param connection |
| * the connection that was monitored |
| */ |
| public synchronized void removeContainerRefreshThread( |
| final IDockerConnection connection) { |
| if (this.refreshThreadMap.containsKey(connection)) { |
| final ContainerRefreshThread containerRefreshThread = refreshThreadMap.get(connection); |
| containerRefreshThread.stopMonitoring(); |
| this.refreshThreadMap.remove(connection); |
| } |
| } |
| |
| /** |
| * Method to reset the refresh rate for updating container lists |
| * |
| * @param seconds |
| * - time to wait between refreshes |
| */ |
| public void setRefreshTime(long seconds) { |
| if (seconds >= 5) { |
| long refreshRate = TimeUnit.SECONDS.toMillis(seconds); |
| for (ContainerRefreshThread t : this.refreshThreadMap.values()) { |
| t.setSleepTime(refreshRate); |
| } |
| } |
| } |
| |
| /** |
| * ContainerRefreshThread class is used to update the container lists for a |
| * particular connection as short as needed to keep the UI updated on a |
| * regular basis. |
| * |
| */ |
| private class ContainerRefreshThread extends Thread { |
| |
| private IDockerConnection connection; |
| private long sleepTime; |
| private boolean kill; |
| private boolean monitor; |
| |
| public ContainerRefreshThread(IDockerConnection connection, |
| long sleepTime) { |
| this.connection = connection; |
| this.sleepTime = sleepTime; |
| this.monitor = true; |
| } |
| |
| /** |
| * Stop this {@link ContainerRefreshThread} to monitor changes for the |
| * associated {@link IDockerConnection} (after it was removed, for |
| * example) |
| */ |
| public void stopMonitoring() { |
| monitor = false; |
| } |
| |
| public IDockerConnection getConnection() { |
| return connection; |
| } |
| |
| public synchronized long getSleepTime() { |
| return sleepTime; |
| } |
| |
| public synchronized void setSleepTime(long newTime) { |
| sleepTime = newTime; |
| this.interrupt(); |
| } |
| |
| public void kill() { |
| kill = true; |
| this.interrupt(); |
| } |
| |
| @Override |
| public void run() { |
| while (monitor) { |
| try { |
| Thread.sleep(getSleepTime()); |
| // After sleep period, update the containers list, but make |
| // sure the refreshManager isn't notified since that |
| // is what triggered this to begin with. |
| synchronized (instance) { |
| // monitoring may have been switched off while the |
| // thread was sleeping |
| if (monitor) { |
| // connection.removeContainerListener(instance); |
| ((DockerConnection) connection).getContainers(true); |
| // connection.addContainerListener(instance); |
| } |
| } |
| } catch (InterruptedException e) { |
| if (kill) |
| break; |
| // otherwise..continue |
| } |
| } |
| Activator.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, |
| "Stopped monitor container changes for connection '" |
| + connection.getName() + "'")); |
| } |
| } |
| |
| /*** |
| * Method to kill all threads at shutdown. |
| */ |
| public void killAllThreads() { |
| for (ContainerRefreshThread rt : this.refreshThreadMap.values()) { |
| rt.kill(); |
| this.refreshThreadMap.remove(rt.getConnection()); |
| } |
| } |
| |
| /** |
| * This methods clears the map of threads that monitor the connections. This |
| * method should only be called during the tests. |
| */ |
| public void reset() { |
| this.refreshThreadMap.clear(); |
| |
| } |
| } |