package krasa.frameswitcher.networking; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.intellij.openapi.diagnostic.Logger; import krasa.frameswitcher.networking.dto.InstanceClosed; import krasa.frameswitcher.networking.dto.PingResponse; import krasa.frameswitcher.networking.dto.ProjectClosed; import krasa.frameswitcher.networking.dto.ProjectOpened; import krasa.frameswitcher.networking.dto.ProjectsState; import krasa.frameswitcher.networking.dto.RemoteProject; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; public class RemoteInstancesState { private final Logger LOG = Logger.getInstance("#" + getClass().getCanonicalName()); public static final int MAX_KEEP_ALIVE_TIME = 10000; public volatile Map<UUID, Date> forRemoval = new HashMap<UUID, Date>(); public volatile List<UUID> actualActiveInstances = new ArrayList<UUID>(); public volatile Multimap<UUID, RemoteProject> remoteProjects = ArrayListMultimap.<UUID, RemoteProject>create(); public volatile Multimap<UUID, RemoteProject> remoteRecentProjects = ArrayListMultimap.<UUID, RemoteProject>create(); public synchronized Multimap<UUID, RemoteProject> getRemoteRecentProjects() { return ArrayListMultimap.create(remoteRecentProjects); } public synchronized Multimap<UUID, RemoteProject> getRemoteProjects() { return ArrayListMultimap.create(remoteProjects); } public synchronized void sweepRemoteInstance() { // just hope that all instances returned result in time final Set<UUID> remoteProjectsKeys = remoteProjects.keySet(); for (UUID uuid : actualActiveInstances) { if (!remoteProjectsKeys.contains(uuid)) { // //TODO LOG.warn("DESYNC"); return; } } final UUID[] remoteInstances = remoteProjectsKeys.toArray(new UUID[remoteProjectsKeys.size()]); for (UUID remoteInstance : remoteInstances) { if (!actualActiveInstances.contains(remoteInstance)) { if (forRemoval.containsKey(remoteInstance)) { if (new Date().getTime() - forRemoval.get(remoteInstance).getTime() > MAX_KEEP_ALIVE_TIME) { remoteProjects.removeAll(remoteInstance); remoteRecentProjects.removeAll(remoteInstance); forRemoval.remove(remoteInstance); } } else { forRemoval.put(remoteInstance, new Date()); } } } actualActiveInstances.clear(); } public synchronized void processPingResponse(PingResponse object) { actualActiveInstances.add(object.getUuid()); forRemoval.remove(object.getUuid()); } public synchronized void updateRemoteState(ProjectsState instanceStarted) { remoteRecentProjects.removeAll(instanceStarted.getUuid()); remoteProjects.removeAll(instanceStarted.getUuid()); remoteRecentProjects.putAll(instanceStarted.getUuid(), instanceStarted.getRecentRemoteProjects()); remoteProjects.putAll(instanceStarted.getUuid(), instanceStarted.getRemoteProjects()); } public synchronized void projectClosed(ProjectClosed projectClosed) { remoteProjects.remove(projectClosed.getUuid(), projectClosed.getRemoteProject()); remoteRecentProjects.put(projectClosed.getUuid(), projectClosed.getRemoteProject()); } public synchronized void projectOpened(ProjectOpened projectOpened) { remoteProjects.put(projectOpened.getUuid(), projectOpened.getRemoteProject()); remoteRecentProjects.remove(projectOpened.getUuid(), projectOpened.getRemoteProject()); } public synchronized void instanceClosed(InstanceClosed object) { remoteProjects.removeAll(object.getUuid()); remoteRecentProjects.removeAll(object.getUuid()); } }