package jetbrains.buildServer.clouds.vmware.tasks; import com.intellij.openapi.diagnostic.Logger; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import jetbrains.buildServer.Used; import jetbrains.buildServer.clouds.base.tasks.UpdateInstancesTask; import jetbrains.buildServer.clouds.vmware.VMWareCloudClient; import jetbrains.buildServer.clouds.vmware.VmwareCloudImage; import jetbrains.buildServer.clouds.vmware.VmwareCloudInstance; import jetbrains.buildServer.clouds.vmware.connector.VMWareApiConnector; import org.jetbrains.annotations.NotNull; /** * Created by sergeypak on 26/10/2016. */ public class VmwarePooledUpdateInstanceTask extends UpdateInstancesTask<VmwareCloudInstance, VmwareCloudImage, VMWareCloudClient> { private static final Logger LOG = Logger.getInstance(VmwarePooledUpdateInstanceTask.class.getName()); private volatile List<VMWareCloudClient> myClients = new CopyOnWriteArrayList<>(); private final List<VMWareCloudClient> myNewClients = new ArrayList<>(); private volatile AtomicBoolean myAlreadyRunning = new AtomicBoolean(false); private final PooledTaskObsoleteHandler myHandler; public VmwarePooledUpdateInstanceTask(@NotNull final VMWareApiConnector connector, @NotNull final VMWareCloudClient client, @NotNull final PooledTaskObsoleteHandler obsoleteHandler) { super(connector, client); myHandler = obsoleteHandler; } @Used("tests") public VmwarePooledUpdateInstanceTask(@NotNull final VMWareApiConnector connector, @NotNull final VMWareCloudClient client, @NotNull final PooledTaskObsoleteHandler obsoleteHandler, @Used("Tests") final long stuckTimeMillis, @Used("Tests") final boolean rethrowException ) { super(connector, client, stuckTimeMillis, rethrowException); myHandler = obsoleteHandler; } public void run(){ super.run(); } /** * Only run if the client is the top one in the list */ public void runIfNecessary(@NotNull final VMWareCloudClient client){ if (!myAlreadyRunning.compareAndSet(false, true)) return; try { synchronized (this) { if (myNewClients.size() != 0) { myClients.addAll(myNewClients); myNewClients.clear(); } } if (myClients.size() == 0) { return; } if (client != myClients.get(0)) { return; } run(); myClients.forEach(VMWareCloudClient::setInitializedIfNecessary); } finally { myAlreadyRunning.set(false); } } @NotNull @Override protected Collection<VmwareCloudImage> getImages() { return myClients.stream() .flatMap(client->client.getImages().stream()) .collect(Collectors.toList()); } public void addClient(@NotNull VMWareCloudClient client){ synchronized (this) { myNewClients.add(client); } } public void removeClient(@NotNull VMWareCloudClient client){ synchronized (this) { myClients.remove(client); myNewClients.remove(client); if (myClients.isEmpty() && myNewClients.isEmpty()){ myHandler.pooledTaskObsolete(this); } } } public String getKey(){ return myConnector.getKey(); } public interface PooledTaskObsoleteHandler { void pooledTaskObsolete(@NotNull VmwarePooledUpdateInstanceTask task); } }