/* * Copyright (c) 2008-2011 EMC Corporation * All Rights Reserved */ package com.emc.storageos.volumecontroller.impl; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.TimeUnit; import org.apache.curator.framework.recipes.locks.InterProcessLock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.emc.storageos.coordinator.client.service.CoordinatorClient; import com.emc.storageos.coordinator.client.service.DistributedPersistentLock; import com.emc.storageos.coordinator.exceptions.CoordinatorException; import com.emc.storageos.volumecontroller.ControllerLockingService; public class ControllerLockingServiceImpl implements ControllerLockingService { private static final Logger log = LoggerFactory.getLogger(ControllerLockingServiceImpl.class); private CoordinatorClient _coordinator; private ThreadLocal<Map<String, InterProcessLock>> locks = new ThreadLocal<Map<String, InterProcessLock>>(); /** * Sets coordinator * * @param coordinator */ public void setCoordinator(CoordinatorClient coordinator) { _coordinator = coordinator; } @Override public boolean acquireLock(String lockName, long seconds) { if (lockName == null || lockName.isEmpty()) { return false; } try { InterProcessLock lock = getInterProcessLock(lockName); log.info("Attempting to acquire lock: " + lockName + (seconds > 0 ? (" for a maximum of " + seconds + " seconds.") : "")); return lock.acquire(seconds, TimeUnit.SECONDS); } catch (Exception e) { log.error(String.format("Acquire of mutex lock: %s failed with Exception: ", lockName), e); return false; } } @Override public boolean releaseLock(String lockName) { if (lockName == null || lockName.isEmpty()) { return false; } try { InterProcessLock lock = getInterProcessLock(lockName); lock.release(); synchronized(this) { if (!lock.isAcquiredInThisProcess()) { Map<String, InterProcessLock> lockMap = locks.get(); lockMap.remove(lockName); } } log.info("Released lock: " + lockName); return true; } catch (Exception e) { log.error(String.format("Acquire of mutex lock: %s failed with Exception: ", lockName), e); } return false; } /** * Get InterProcessLock object from thread local. We keep single thread * * @param lockName * @return InterProcessLock instance */ private InterProcessLock getInterProcessLock(String lockName) { Map<String, InterProcessLock> lockMap = locks.get(); if (lockMap == null) { lockMap = new WeakHashMap<String, InterProcessLock>(); locks.set(lockMap); } if (lockMap.containsKey(lockName)) { return lockMap.get(lockName); } InterProcessLock lock = _coordinator.getLock(lockName); lockMap.put(lockName, lock); return lock; } @Override public boolean acquirePersistentLock(String lockName, String clientName, long seconds) { if (lockName == null || lockName.isEmpty()) { return false; } try { Throwable t = null; DistributedPersistentLock lock = null; boolean acquired = false; if (seconds >= 0) { log.info("Attempting to acquire lock: " + lockName + (seconds > 0 ? (" for a maximum of " + seconds + " seconds.") : "")); while (seconds-- >= 0 && !acquired) { try { lock = _coordinator.getPersistentLock(lockName); acquired = lock.acquireLock(clientName); } catch (CoordinatorException ce) { t = ce; Thread.sleep(1000); } } } else if (seconds == -1) { log.info("Attempting to acquire lock: " + lockName + " for as long as it takes."); while (true) { try { lock = _coordinator.getPersistentLock(lockName); acquired = lock.acquireLock(clientName); } catch (CoordinatorException ce) { t = ce; Thread.sleep(1000); } } } else { log.error("Invalid value for seconds to acquireLock"); return false; } if (lock == null || !acquired) { if (t != null) { log.error(String.format("Acquisition of mutex lock: %s failed with Exception: ", lockName), t); } else { log.error(String.format("Acquisition of mutex lock: %s failed", lockName)); } return false; } log.info("Acquired lock: " + lockName); return true; } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; } catch (Exception e) { return false; } } @Override public boolean releasePersistentLock(String lockName, String clientName) { if (lockName == null || lockName.isEmpty()) { return false; } try { DistributedPersistentLock lock = _coordinator.getPersistentLock(lockName); if (lock != null) { boolean result = lock.releaseLock(clientName); log.info("Released lock: " + lockName); return result; } else { log.error(String.format("Release of mutex lock: %s failed: ", lockName)); } } catch (Exception e) { log.error(String.format("Release of mutex lock: %s failed with Exception: ", lockName), e); } return false; } }