Commit c9d224fb authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Added LockManager to have local and distributed Locks.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@8323 b35dd754-fafc-0310-a699-88a17e54d16e
parent 51751317
/**
* $RCSfile: $
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.util.lock;
import org.jivesoftware.util.TaskEngine;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* LockFactory to be used when not running in cluster mode. The locks returned by this
* factory are only visibile within this JVM.
*
* @author Gaston Dombiak
*/
public class LocalLockFactory implements LockFactory {
private TimerTask maintenanceTask;
private Map<Object, WeakReference<Lock>> locks = new ConcurrentHashMap<Object, WeakReference<Lock>>();
public Lock getLock(Object key) {
WeakReference<Lock> lockRef;
Lock lock;
Object lockKey = key;
if (key instanceof String) {
lockKey = ((String) key).intern();
}
synchronized (lockKey) {
lockRef = locks.get(key);
lock = lockRef != null ? lockRef.get() : null;
if (lockRef == null || lock == null) {
lock = new ReentrantLock(true);
lockRef = new WeakReference<Lock>(lock);
locks.put(key, lockRef);
}
}
return lock;
}
public void start() {
// Remove entries in the locks Map that are no longer used
maintenanceTask = new TimerTask() {
public void run() {
for (Map.Entry<Object, WeakReference<Lock>> entry : locks.entrySet()) {
if (entry.getValue().get() == null) {
locks.remove(entry.getKey());
}
}
}
};
TaskEngine.getInstance().scheduleAtFixedRate(maintenanceTask, 30000, 60000);
}
public void shutdown() {
TaskEngine.getInstance().cancelScheduledTask(maintenanceTask);
// Clean up existing locks
locks.clear();
}
}
/**
* $RCSfile: $
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.util.lock;
import java.util.concurrent.locks.Lock;
/**
* Factory that creates new Locks for specified keys and keeps them in memory until they
* are no longer needed.
*
* @author Gaston Dombiak
*/
public interface LockFactory {
/**
* Returns an existing lock on the specified key or creates a new one if none was found. This
* operation should be thread safe.
*
* @param key the object that defines the visibility or scope of the lock.
* @return an existing lock on the specified key or creates a new one if none was found.
*/
Lock getLock(Object key);
/**
* Message sent when a new factory is set to the {@link org.jivesoftware.util.lock.LockManager}.
* Implementors could start maintenance tasks.
*/
void start();
/**
* Message sent when an already used factory by {@link org.jivesoftware.util.lock.LockManager}
* is replaced by another factory. Implementors should stop maintenance tasks.
*/
void shutdown();
}
/**
* $RCSfile: $
* $Revision: $
* $Date: $
*
* Copyright (C) 2007 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.util.lock;
import java.util.concurrent.locks.Lock;
/**
* Manager of {@link Lock Locks} that could be valid when running within a cluster or when in local mode.
* By default the LockManager will use a {@link org.jivesoftware.util.lock.LocalLockFactory} but
* you can set new factories by sending {@link #setLockFactory(LockFactory)}.
*
* @author Gaston Dombiak
*/
public class LockManager {
private static LockFactory lockFactory;
static {
setLockFactory(new LocalLockFactory());
}
/**
* Returns the existing lock factory being used for creating new Locks.
*
* @return the existing lock factory being used for creating new Locks.
*/
public static LockFactory getLockFactory() {
return lockFactory;
}
/**
* Sets the lock factory to use for creating new Locks. If <tt>null</tt> then
* use {@link LocalLockFactory}.
*
* @param lockFactory the new lock factory to use for creating new Locks.
*/
public static void setLockFactory(LockFactory lockFactory) {
// Shutdown old factory
if (LockManager.lockFactory != null) {
LockManager.lockFactory.shutdown();
}
LockManager.lockFactory = lockFactory;
// Start new factory
if (LockManager.lockFactory != null) {
LockManager.lockFactory.start();
}
}
/**
* Returns an existing {@link Lock} on the specified key or creates a new one if none was found. This
* operation should be thread safe. Successive calls with the same key may or may not return
* the same {@link Lock}. However, different threads asking for the same Lock at the same time will
* get the same Lock object.
*
* @param key the object that defines the visibility or scope of the lock.
* @return an existing lock on the specified key or creates a new one if none was found.
*/
public static Lock getLock(Object key) {
return lockFactory.getLock(key);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment