package org.ovirt.engine.core.bll.network.macpool; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.apache.commons.lang.Validate; import org.ovirt.engine.core.common.errors.EngineError; import org.ovirt.engine.core.common.errors.EngineException; class MacsStorage { private final boolean allowDuplicates; private List<Range> ranges = new LinkedList<>(); private ObjectCounter<Long> customMacs; private int startIndexForEmptyRangeSearch = 0; public MacsStorage(boolean allowDuplicates) { this.allowDuplicates = allowDuplicates; customMacs = new ObjectCounter<>(this.allowDuplicates); } public Range addRange(long rangeStart, long rangeEnd) { return addRange(new Range(rangeStart, rangeEnd)); } Range addRange(Range range) { ranges.add(range); return range; } public boolean useMac(long mac) { return useMac(mac, allowDuplicates); } private boolean useMac(long mac, boolean allowDuplicates) { Range range = findIncludingRange(mac); if (range == null) { return customMacs.increase(mac, allowDuplicates); } else { return range.use(mac, allowDuplicates); } } public void useMacNoDuplicityCheck(long mac) { useMac(mac, true); } public boolean isMacInUse(long mac) { Range range = findIncludingRange(mac); return range == null ? customMacs.contains(mac) : range.isAllocated(mac); } public void freeMac(long mac) { Range range = findIncludingRange(mac); if (range == null) { customMacs.decrease(mac); } else { range.freeMac(mac); } } public boolean availableMacExist() { return getRangeWithAvailableMac() != null; } public List<Long> allocateAvailableMacs(int numberOfMacs) { if (getAvailableMacsCount() < numberOfMacs) { throw new EngineException(EngineError.MAC_POOL_NO_MACS_LEFT); } final List<Long> result = new ArrayList<>(numberOfMacs); int remainingMacs = numberOfMacs; while (remainingMacs > 0) { final Range rangeWithAvailableMac = getRangeWithAvailableMac(); Validate.notNull(rangeWithAvailableMac); final int availableMacsCount = rangeWithAvailableMac.getAvailableCount(); int allocatingMacsCount = availableMacsCount < remainingMacs ? availableMacsCount : remainingMacs; final List<Long> allocatedMacs = rangeWithAvailableMac.allocateMacs(allocatingMacsCount); remainingMacs -= allocatedMacs.size(); result.addAll(allocatedMacs); } return result; } Range getRangeWithAvailableMac() { int numberOfRanges = ranges.size(); Range range = findRangeWithAvailableMac(startIndexForEmptyRangeSearch, numberOfRanges, numberOfRanges); if (range != null) { return range; } return findRangeWithAvailableMac(0, startIndexForEmptyRangeSearch, numberOfRanges); } private Range findRangeWithAvailableMac(int startIndex, int endIndex, int numberOfRanges) { for(int i = startIndex; i < endIndex; i++) { Range range = ranges.get(i); boolean hasAvailableMacs = range.getAvailableCount() > 0; if (hasAvailableMacs) { startIndexForEmptyRangeSearch = (i + 1) % numberOfRanges; return range; } } return null; } public int getAvailableMacsCount() { int count = 0; for (Range range : ranges) { count += range.getAvailableCount(); } return count; } private Range findIncludingRange(long mac) { for (Range range : ranges) { if (range.contains(mac)) { return range; } } return null; } boolean isMacInRange(Long mac) { return findIncludingRange(mac) != null; } }