/*
* Copyright LGPL3
* YES Technology Association
* http://yestech.org
*
* http://www.opensource.org/licenses/lgpl-3.0.html
*/
package org.yestech.lib.concurrency;
import com.hazelcast.core.Hazelcast;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Represents a concurrency lock manager
*/
@SuppressWarnings("unchecked")
public class LockManager {
final private static LockManager instance = new LockManager();
//TODO: use a try cache that can persist to disk and expire old locks
final private static ConcurrentMap<String, Object> locks = new ConcurrentHashMap<String, Object>();
final private ReentrantLock objectLock = new ReentrantLock();
final private ReentrantLock readWriteLock = new ReentrantLock();
/**
* Creates or retrieve a previous lock associated with the key.
*
* @param key key associated with the lock.
* @param type Type of lock to return
* @return The Lock
*/
public static <L> L getLock(String key, LockType type) {
L lock;
if (LockType.DISTRIBUTED.equals(type)) {
lock = (L) Hazelcast.getLock(key);
} else {
lock = (L) locks.get(key);
if (lock == null) {
lock = (L)instance.retrieveLock(key, type);
}
}
return lock;
}
private Object retrieveLock(String key, LockType type) {
Object lock;
if (LockType.OBJECT.equals(type)) {
lock = createObjectLock(key);
} else if (LockType.READ_WRITE.equals(type)) {
lock = createReadWriteLock(key);
} else {
throw new IllegalArgumentException("Not a valid type: " + type);
}
return lock;
}
private Object createReadWriteLock(String key) {
Object lock;
try {
readWriteLock.lock();
lock = locks.get(key);
if (lock == null) {
lock = new ReentrantReadWriteLock();
locks.put(key, lock);
}
} finally {
readWriteLock.unlock();
}
return lock;
}
private Object createObjectLock(String key) {
Object lock;
try {
objectLock.lock();
lock = locks.get(key);
if (lock == null) {
lock = new ReentrantLock();
locks.put(key, lock);
}
} finally {
objectLock.unlock();
}
return lock;
}
}