package org.jenkinsci.plugins.ewm.strategies;

import hudson.AbortException;
import org.jenkinsci.plugins.ewm.DiskAllocationStrategy;
import org.jenkinsci.plugins.ewm.DiskInfoProvider;
import org.jenkinsci.plugins.ewm.definitions.Disk;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

/**
 * Base class that selects the {@link Disk} with the highest speed provided by the
 * {@link #getDiskSpeed(DiskInfoProvider)} method
 *
 * @author Alexandru Somai
 */
public abstract class AbstractDiskSpeedStrategy extends DiskAllocationStrategy {

    @Nonnull
    @Override
    public Disk allocateDisk(@Nonnull List<Disk> disks) throws IOException {
        long estimatedWorkspaceSize = getEstimatedWorkspaceSize();

        Iterator<Disk> iterator = disks.iterator();
        Disk candidate = null;

        // try to find at least one Disk candidate that has usable space >= estimated workspace size
        while (iterator.hasNext()) {
            Disk next = iterator.next();
            long usableSpace = retrieveUsableSpace(next);
            if (usableSpace >= estimatedWorkspaceSize) {
                // found a possible candidate that has the usable space >= estimate workspace size
                candidate = next;
                break;
            }
        }

        if (candidate == null) {
            // there is no Disk that has usable space >= estimated workspace size
            String message = String.format("Couldn't find any Disk with at least %s KB usable space", estimatedWorkspaceSize);
            throw new AbortException(message);
        }

        // found a possible candidate, continue searching for another disk with speed > candidate's speed
        double candidateSpeed = getDiskSpeed(candidate.getDiskInfo());
        while (iterator.hasNext()) {
            Disk next = iterator.next();
            double nextSpeed = getDiskSpeed(next.getDiskInfo());
            long usableSpace = retrieveUsableSpace(next);
            if (nextSpeed > candidateSpeed && usableSpace >= estimatedWorkspaceSize) {
                // found another Disk that has higher speed than the candidate's speed
                // and the usable space >= estimated workspace size
                candidate = next;
                candidateSpeed = nextSpeed;
            }
        }

        return candidate;
    }

    /**
     * Override this method to return the speed property on which the selection should be made.
     *
     * @param diskInfo the {@link DiskInfoProvider} that contains R/W {@link Disk} speed
     * @return the value represented by the R/W speed
     */
    protected abstract int getDiskSpeed(@Nonnull DiskInfoProvider diskInfo);
}

@@ -295,35 +295,8 @@
 on;%0A
-import java.util.Iterator;%0A
 impo
@@ -743,271 +743,73 @@
 ();%0A
-%0A        Iterator%3CDisk%3E iterator = disks.iterator();%0A        Disk candidate = null;%0A%0A        // try to find at least one Disk candidate that has usable space %3E= estimated workspace size%0A        while (iterator.hasNext()) %7B%0A            Disk next = iterator.next();
+        Disk candidate = null;%0A%0A        for (Disk disk : disks) %7B
 %0A   
@@ -848,39 +848,40 @@
 ieveUsableSpace(
-next
+disk
 );%0A
+%0A
             if (
@@ -880,16 +880,37 @@
     if (
+candidate == null && 
 usableSp
@@ -1025,16 +1025,17 @@
 estimate
+d
  workspa
@@ -1074,34 +1074,11 @@
 e = 
-next;%0A                brea
+dis
 k;%0A 
@@ -1090,35 +1090,29 @@
       %7D%0A
-   
+%0A
      
-%7D%0A%0A
        
- 
 if (cand
@@ -1113,25 +1113,25 @@
  (candidate 
-=
+!
 = null) %7B%0A  
@@ -1144,281 +1144,14 @@
     
-// there is no Disk that has usable space %3E= estimated workspace size%0A            String message = String.format(%22Couldn't find any Disk with at least %25s KB usable space%22, estimatedWorkspaceSize);%0A            throw new AbortException(message);%0A        %7D%0A%0A        // found a
+    //
  pos
@@ -1242,22 +1242,27 @@
         
+     
-double
+   int
  candida
@@ -1322,101 +1322,24 @@
     
-while (iterator.hasNext()) %7B%0A            Disk next = iterator.next();%0A            double next
+        int disk
 Spee
@@ -1355,20 +1355,20 @@
 skSpeed(
-next
+disk
 .getDisk
@@ -1380,66 +1380,13 @@
 ));%0A
+%0A
     
-        long usableSpace = retrieveUsableSpace(next);%0A
     
@@ -1397,20 +1397,20 @@
     if (
-next
+disk
 Speed %3E 
@@ -1476,32 +1476,36 @@
                 
+    
 // found another
@@ -1505,17 +1505,17 @@
 another 
-D
+d
 isk that
@@ -1558,35 +1558,16 @@
 's speed
-%0A                //
  and the
@@ -1616,32 +1616,36 @@
                 
+   
+ 
 candidate = next
@@ -1644,71 +1644,345 @@
 e = 
-next;%0A                candidateSpeed = nextSpeed;%0A            %7D
+disk;%0A                %7D%0A            %7D%0A        %7D%0A%0A        if (candidate == null) %7B%0A            // there is no disk that has usable space %3E= estimated workspace size%0A            String message = String.format(%22Couldn't find any Disk with at least %25s KB usable space%22, estimatedWorkspaceSize);%0A            throw new AbortException(message);
 %0A   

Improve disk allocation strategy implementation