package org.ovirt.engine.core.bll.network.macpool; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import org.apache.commons.collections.CollectionUtils; import org.ovirt.engine.core.compat.Guid; import org.ovirt.engine.core.utils.lock.LockedObjectFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @ApplicationScoped public class DecoratedMacPoolFactory { private static final Logger log = LoggerFactory.getLogger(DecoratedMacPoolFactory.class); @Inject private LockedObjectFactory lockedObjectFactory; private final Map<Guid, ReentrantReadWriteLock> poolLocks = new HashMap<>(); public DecoratedMacPoolFactory() { } public DecoratedMacPoolFactory(LockedObjectFactory lockedObjectFactory) { this.lockedObjectFactory = lockedObjectFactory; } public MacPool createDecoratedPool(MacPool macPool, List<MacPoolDecorator> decorators) { MacPool lockedPool = lockedObjectFactory.createLockingInstance(macPool, MacPool.class, lockForMacPool(macPool.getId())); MacPool decoratedPool = decoratePool(lockedPool, decorators); log.debug("MacPool {} decorated as {}.", macPool, decoratedPool); return decoratedPool; } private synchronized ReentrantReadWriteLock lockForMacPool(Guid macPoolId) { if (poolLocks.containsKey(macPoolId)) { log.debug("Returning cached read/write lock for macPoolId={}", macPoolId); return poolLocks.get(macPoolId); } log.debug("Creating read/write lock for macPoolId={}", macPoolId); ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); poolLocks.put(macPoolId, lock); return lock; } /** * Decorates actual pool with given decorators, applying first passed decorator on actual pool, * next on decorated object from previous step etc. * * @param macPool actual pool instance * @param decorators collection of decorators @return decorated pool. */ private MacPool decoratePool(MacPool macPool, List<MacPoolDecorator> decorators) { if (CollectionUtils.isEmpty(decorators)) { log.debug("No MacPoolDecorators were passed to decorate pool {}. ", macPool); return macPool; } MacPool result = macPool; log.debug("Decorating MacPool {} with decorators: {}.", Arrays.toString(decorators.toArray())); for (MacPoolDecorator decorator : decorators) { decorator.setMacPool(result); result = decorator; } return result; } }