From 315320e9f8e95837a73705a2af46ce1d340aa353 Mon Sep 17 00:00:00 2001 From: David Jencks Date: Tue, 25 Mar 2008 00:52:23 +0000 Subject: [PATCH] AMQ-1254 Fix similarly to trunk, but with locking across classloaders git-svn-id: https://svn.apache.org/repos/asf/activemq/branches/activemq-4.1@640659 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/activemq/kaha/impl/KahaStore.java | 84 +++++++------------ .../org/apache/activemq/kaha/StoreTest.java | 12 +++ 2 files changed, 43 insertions(+), 53 deletions(-) diff --git a/activemq-core/src/main/java/org/apache/activemq/kaha/impl/KahaStore.java b/activemq-core/src/main/java/org/apache/activemq/kaha/impl/KahaStore.java index 09f7c0b846..1a5e61e8ec 100644 --- a/activemq-core/src/main/java/org/apache/activemq/kaha/impl/KahaStore.java +++ b/activemq-core/src/main/java/org/apache/activemq/kaha/impl/KahaStore.java @@ -20,17 +20,17 @@ package org.apache.activemq.kaha.impl; import java.io.File; import java.io.IOException; -import java.io.RandomAccessFile; import java.nio.channels.FileLock; +import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Map; -import java.util.Properties; import java.util.Set; + +import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap; import org.apache.activemq.kaha.IndexTypes; import org.apache.activemq.kaha.ListContainer; import org.apache.activemq.kaha.MapContainer; -import org.apache.activemq.kaha.RuntimeStoreException; import org.apache.activemq.kaha.Store; import org.apache.activemq.kaha.StoreLocation; import org.apache.activemq.kaha.impl.container.BaseContainerImpl; @@ -45,7 +45,6 @@ import org.apache.activemq.kaha.impl.index.IndexManager; import org.apache.activemq.kaha.impl.index.RedoStoreIndexItem; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap; /** * Store Implementation @@ -54,13 +53,14 @@ import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap; */ public class KahaStore implements Store{ - private static final String LOCK_FILE_NAME="store.lock"; private static final String DEFAULT_CONTAINER_NAME="kaha"; private final static String PROPERTY_PREFIX="org.apache.activemq.kaha.Store"; private final static boolean brokenFileLock="true".equals(System.getProperty(PROPERTY_PREFIX+".broken","false")); private final static boolean disableLocking="true".equals(System.getProperty(PROPERTY_PREFIX+"DisableLocking", "false")); - private static Set lockSet; + //according to the String javadoc, all constant strings are interned so this will be the same object throughout the vm + //and we can use it as a monitor for the lockset. + private final static String LOCKSET_MONITOR = PROPERTY_PREFIX + ".Lock.Monitor"; private static final Log log=LogFactory.getLog(KahaStore.class); private File directory; private IndexRootContainer mapsContainer; @@ -420,65 +420,43 @@ public class KahaStore implements Store{ } } - private synchronized void lock() throws IOException{ - if(!disableLocking&&directory!=null&&lock==null){ - Set set=getVmLockSet(); - synchronized(set){ - if(lock==null){ - if(!set.add(directory.getCanonicalPath())){ - throw new StoreLockedExcpetion("Kaha Store "+directory.getName() - +" is already opened by this application."); - } - if(!brokenFileLock){ - lock=rootIndexManager.getLock(); - if(lock==null){ - set.remove(directory.getCanonicalPath()); - throw new StoreLockedExcpetion("Kaha Store "+directory.getName() - +" is already opened by another application"); - } + private void lock() throws IOException { + synchronized (LOCKSET_MONITOR) { + if (!disableLocking && directory != null && lock == null) { + String key = getPropertyKey(); + String property = System.getProperty(key); + if (null == property) { + if (!brokenFileLock) { + lock = rootIndexManager.getLock(); + if (lock == null) { + throw new StoreLockedExcpetion("Kaha Store " + directory.getName() + " is already opened by another application"); + } else + System.setProperty(key, new Date().toString()); } + } else { //already locked + throw new StoreLockedExcpetion("Kaha Store " + directory.getName() + " is already opened by this application."); } } } } - private void unlock() throws IOException{ - if(!disableLocking&&directory!=null){ - Set set=getVmLockSet(); - synchronized(set){ - if(lock!=null){ - set.remove(directory.getCanonicalPath()); - if(lock.isValid()){ - lock.release(); - } - lock=null; + private void unlock() throws IOException { + synchronized (LOCKSET_MONITOR) { + if (!disableLocking && (null != directory) && (null != lock)) { + System.getProperties().remove(getPropertyKey()); + if (lock.isValid()) { + lock.release(); } + lock = null; } } } - - private void checkClosed(){ - if(closed){ - throw new RuntimeStoreException("The store is closed"); - } + + private String getPropertyKey() throws IOException { + //Is replaceAll() needed? Should test without it. + return getClass().getName() + ".lock." + directory.getCanonicalPath(); } - - - static private Set getVmLockSet(){ - if(lockSet==null){ - Properties properties=System.getProperties(); - synchronized(properties){ - lockSet=(Set)properties.get("org.apache.activemq.kaha.impl.KahaStore"); - if(lockSet==null){ - lockSet=new HashSet(); - } - properties.put(PROPERTY_PREFIX,lockSet); - } - } - return lockSet; - } - /** * scans the directory and builds up the IndexManager and DataManager * @throws IOException diff --git a/activemq-core/src/test/java/org/apache/activemq/kaha/StoreTest.java b/activemq-core/src/test/java/org/apache/activemq/kaha/StoreTest.java index 2540a24c0e..7302a15c1e 100644 --- a/activemq-core/src/test/java/org/apache/activemq/kaha/StoreTest.java +++ b/activemq-core/src/test/java/org/apache/activemq/kaha/StoreTest.java @@ -24,6 +24,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.activemq.kaha.impl.StoreLockedExcpetion; import junit.framework.TestCase; @@ -201,6 +202,17 @@ public class StoreTest extends TestCase{ } } + public void testLock() throws Exception{ + try { + store.doesListContainerExist("fred"); + Store s = getStore(); + s.doesListContainerExist("fred"); + }catch(StoreLockedExcpetion e) { + return; + } + fail("Expected to catch an exception"); + } + protected Store getStore() throws IOException{ return StoreFactory.open(name, "rw");