Update StorageStrategyFactory to not sort, but just iterate and find the first

This commit is contained in:
Darren Shepherd 2013-10-23 16:36:31 -07:00
parent b747549597
commit f3e968b983
3 changed files with 82 additions and 77 deletions

View File

@ -18,7 +18,6 @@
*/
package org.apache.cloudstack.engine.subsystem.api.storage;
import java.util.Collection;
import java.util.Map;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation;
@ -28,18 +27,10 @@ import com.cloud.storage.Snapshot;
public interface StorageStrategyFactory {
Collection<DataMotionStrategy> getDataMotionStrategies(DataObject srcData, DataObject destData);
DataMotionStrategy getDataMotionStrategy(DataObject srcData, DataObject destData);
Collection<DataMotionStrategy> getDataMotionStrategies(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost);
DataMotionStrategy getDataMotionStrategy(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost);
Collection<SnapshotStrategy> getSnapshotStrategies(Snapshot snapshot, SnapshotOperation op);
SnapshotStrategy getSnapshotStrategy(Snapshot snapshot, SnapshotOperation op);
}

View File

@ -19,10 +19,8 @@
package org.apache.cloudstack.storage.helper;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import javax.inject.Inject;
@ -30,10 +28,10 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionStrategy;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation;
import org.apache.cloudstack.engine.subsystem.api.storage.StorageStrategyFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation;
import com.cloud.host.Host;
import com.cloud.storage.Snapshot;
@ -44,23 +42,8 @@ public class StorageStrategyFactoryImpl implements StorageStrategyFactory {
List<DataMotionStrategy> dataMotionStrategies;
@Override
public DataMotionStrategy getDataMotionStrategy(DataObject srcData, DataObject destData) {
return first(getDataMotionStrategies(srcData, destData));
}
@Override
public DataMotionStrategy getDataMotionStrategy(Map<VolumeInfo, DataStore> volumeMap, Host srcHost, Host destHost) {
return first(getDataMotionStrategies(volumeMap, srcHost, destHost));
}
@Override
public SnapshotStrategy getSnapshotStrategy(Snapshot snapshot, SnapshotOperation op) {
return first(getSnapshotStrategies(snapshot, op));
}
@Override
public Collection<DataMotionStrategy> getDataMotionStrategies(final DataObject srcData, final DataObject destData) {
return sort(dataMotionStrategies, new CanHandle<DataMotionStrategy>() {
public DataMotionStrategy getDataMotionStrategy(final DataObject srcData, final DataObject destData) {
return bestMatch(dataMotionStrategies, new CanHandle<DataMotionStrategy>() {
@Override
public StrategyPriority canHandle(DataMotionStrategy strategy) {
return strategy.canHandle(srcData, destData);
@ -69,8 +52,8 @@ public class StorageStrategyFactoryImpl implements StorageStrategyFactory {
}
@Override
public Collection<DataMotionStrategy> getDataMotionStrategies(final Map<VolumeInfo, DataStore> volumeMap, final Host srcHost, final Host destHost) {
return sort(dataMotionStrategies, new CanHandle<DataMotionStrategy>() {
public DataMotionStrategy getDataMotionStrategy(final Map<VolumeInfo, DataStore> volumeMap, final Host srcHost, final Host destHost) {
return bestMatch(dataMotionStrategies, new CanHandle<DataMotionStrategy>() {
@Override
public StrategyPriority canHandle(DataMotionStrategy strategy) {
return strategy.canHandle(volumeMap, srcHost, destHost);
@ -79,8 +62,8 @@ public class StorageStrategyFactoryImpl implements StorageStrategyFactory {
}
@Override
public Collection<SnapshotStrategy> getSnapshotStrategies(final Snapshot snapshot, final SnapshotOperation op) {
return sort(snapshotStrategies, new CanHandle<SnapshotStrategy>() {
public SnapshotStrategy getSnapshotStrategy(final Snapshot snapshot, final SnapshotOperation op) {
return bestMatch(snapshotStrategies, new CanHandle<SnapshotStrategy>() {
@Override
public StrategyPriority canHandle(SnapshotStrategy strategy) {
return strategy.canHandle(snapshot, op);
@ -88,30 +71,22 @@ public class StorageStrategyFactoryImpl implements StorageStrategyFactory {
});
}
private static <T> Collection<T> sort(Collection<T> collection, final CanHandle<T> canHandle) {
private static <T> T bestMatch(Collection<T> collection, final CanHandle<T> canHandle) {
if (collection.size() == 0)
return null;
TreeSet<T> resultSet = new TreeSet<T>(new Comparator<T>() {
@Override
public int compare(T o1, T o2) {
int i1 = canHandle.canHandle(o1).ordinal();
int i2 = canHandle.canHandle(o2).ordinal();
return new Integer(i2).compareTo(new Integer(i1));
}
});
StrategyPriority highestPriority = StrategyPriority.CANT_HANDLE;
for ( T test : collection ) {
if ( canHandle.canHandle(test) != StrategyPriority.CANT_HANDLE ) {
resultSet.add(test);
T strategyToUse = null;
for (T strategy : collection) {
StrategyPriority priority = canHandle.canHandle(strategy);
if (priority.ordinal() > highestPriority.ordinal()) {
highestPriority = priority;
strategyToUse = strategy;
}
}
return resultSet;
}
private static <T> T first(Collection<T> resultSet) {
return resultSet.size() == 0 ? null : resultSet.iterator().next();
return strategyToUse;
}
private static interface CanHandle<T> {

View File

@ -16,23 +16,23 @@
// under the License.
package org.apache.cloudstack.engine.subsystem.api.storage;
import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotStrategy.SnapshotOperation;
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
import org.apache.cloudstack.storage.helper.StorageStrategyFactoryImpl;
import org.junit.Test;
import com.cloud.host.Host;
import com.cloud.storage.Snapshot;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
public class StrategyPriorityTest {
@Test
@ -50,17 +50,30 @@ public class StrategyPriorityTest {
doReturn(StrategyPriority.HIGHEST).when(highestStrategy).canHandle(any(Snapshot.class), any(SnapshotOperation.class));
List<SnapshotStrategy> strategies = new ArrayList<SnapshotStrategy>(5);
strategies.addAll(Arrays.asList(defaultStrategy, pluginStrategy, hyperStrategy, cantHandleStrategy, highestStrategy));
SnapshotStrategy strategy = null;
StorageStrategyFactoryImpl factory = new StorageStrategyFactoryImpl();
factory.setSnapshotStrategies(strategies);
Iterator<SnapshotStrategy> iter = factory.getSnapshotStrategies(mock(Snapshot.class), SnapshotOperation.TAKE).iterator();
assertEquals("Highest was not 1st.", highestStrategy, iter.next());
assertEquals("Plugin was not 2nd.", pluginStrategy, iter.next());
assertEquals("Hypervisor was not 3rd.", hyperStrategy, iter.next());
assertEquals("Default was not 4th.", defaultStrategy, iter.next());
assertTrue("Can't Handle was not 5th.", !iter.hasNext());
strategies.add(cantHandleStrategy);
strategy = factory.getSnapshotStrategy(mock(Snapshot.class), SnapshotOperation.TAKE);
assertEquals("A strategy was found when it shouldn't have been.", null, strategy);
strategies.add(defaultStrategy);
strategy = factory.getSnapshotStrategy(mock(Snapshot.class), SnapshotOperation.TAKE);
assertEquals("Default strategy was not picked.", defaultStrategy, strategy);
strategies.add(hyperStrategy);
strategy = factory.getSnapshotStrategy(mock(Snapshot.class), SnapshotOperation.TAKE);
assertEquals("Hypervisor strategy was not picked.", hyperStrategy, strategy);
strategies.add(pluginStrategy);
strategy = factory.getSnapshotStrategy(mock(Snapshot.class), SnapshotOperation.TAKE);
assertEquals("Plugin strategy was not picked.", pluginStrategy, strategy);
strategies.add(highestStrategy);
strategy = factory.getSnapshotStrategy(mock(Snapshot.class), SnapshotOperation.TAKE);
assertEquals("Highest strategy was not picked.", highestStrategy, strategy);
}
@Test
@ -78,17 +91,30 @@ public class StrategyPriorityTest {
doReturn(StrategyPriority.HIGHEST).when(highestStrategy).canHandle(any(DataObject.class), any(DataObject.class));
List<DataMotionStrategy> strategies = new ArrayList<DataMotionStrategy>(5);
strategies.addAll(Arrays.asList(defaultStrategy, pluginStrategy, hyperStrategy, cantHandleStrategy, highestStrategy));
DataMotionStrategy strategy = null;
StorageStrategyFactoryImpl factory = new StorageStrategyFactoryImpl();
factory.setDataMotionStrategies(strategies);
Iterator<DataMotionStrategy> iter = factory.getDataMotionStrategies(mock(DataObject.class), mock(DataObject.class)).iterator();
assertEquals("Highest was not 1st.", highestStrategy, iter.next());
assertEquals("Plugin was not 2nd.", pluginStrategy, iter.next());
assertEquals("Hypervisor was not 3rd.", hyperStrategy, iter.next());
assertEquals("Default was not 4th.", defaultStrategy, iter.next());
assertTrue("Can't Handle was not 5th.", !iter.hasNext());
strategies.add(cantHandleStrategy);
strategy = factory.getDataMotionStrategy(mock(DataObject.class), mock(DataObject.class));
assertEquals("A strategy was found when it shouldn't have been.", null, strategy);
strategies.add(defaultStrategy);
strategy = factory.getDataMotionStrategy(mock(DataObject.class), mock(DataObject.class));
assertEquals("Default strategy was not picked.", defaultStrategy, strategy);
strategies.add(hyperStrategy);
strategy = factory.getDataMotionStrategy(mock(DataObject.class), mock(DataObject.class));
assertEquals("Hypervisor strategy was not picked.", hyperStrategy, strategy);
strategies.add(pluginStrategy);
strategy = factory.getDataMotionStrategy(mock(DataObject.class), mock(DataObject.class));
assertEquals("Plugin strategy was not picked.", pluginStrategy, strategy);
strategies.add(highestStrategy);
strategy = factory.getDataMotionStrategy(mock(DataObject.class), mock(DataObject.class));
assertEquals("Highest strategy was not picked.", highestStrategy, strategy);
}
@Test
@ -107,16 +133,29 @@ public class StrategyPriorityTest {
doReturn(StrategyPriority.HIGHEST).when(highestStrategy).canHandle(any(Map.class), any(Host.class), any(Host.class));
List<DataMotionStrategy> strategies = new ArrayList<DataMotionStrategy>(5);
strategies.addAll(Arrays.asList(defaultStrategy, pluginStrategy, hyperStrategy, cantHandleStrategy, highestStrategy));
DataMotionStrategy strategy = null;
StorageStrategyFactoryImpl factory = new StorageStrategyFactoryImpl();
factory.setDataMotionStrategies(strategies);
Iterator<DataMotionStrategy> iter = factory.getDataMotionStrategies(mock(Map.class), mock(Host.class), mock(Host.class)).iterator();
assertEquals("Highest was not 1st.", highestStrategy, iter.next());
assertEquals("Plugin was not 2nd.", pluginStrategy, iter.next());
assertEquals("Hypervisor was not 3rd.", hyperStrategy, iter.next());
assertEquals("Default was not 4th.", defaultStrategy, iter.next());
assertTrue("Can't Handle was not 5th.", !iter.hasNext());
strategies.add(cantHandleStrategy);
strategy = factory.getDataMotionStrategy(mock(Map.class), mock(Host.class), mock(Host.class));
assertEquals("A strategy was found when it shouldn't have been.", null, strategy);
strategies.add(defaultStrategy);
strategy = factory.getDataMotionStrategy(mock(Map.class), mock(Host.class), mock(Host.class));
assertEquals("Default strategy was not picked.", defaultStrategy, strategy);
strategies.add(hyperStrategy);
strategy = factory.getDataMotionStrategy(mock(Map.class), mock(Host.class), mock(Host.class));
assertEquals("Hypervisor strategy was not picked.", hyperStrategy, strategy);
strategies.add(pluginStrategy);
strategy = factory.getDataMotionStrategy(mock(Map.class), mock(Host.class), mock(Host.class));
assertEquals("Plugin strategy was not picked.", pluginStrategy, strategy);
strategies.add(highestStrategy);
strategy = factory.getDataMotionStrategy(mock(Map.class), mock(Host.class), mock(Host.class));
assertEquals("Highest strategy was not picked.", highestStrategy, strategy);
}
}