Author: ozeigermann
Date: Fri Aug 17 17:25:19 2007
New Revision: 567193
URL: http://svn.apache.org/viewvc?view=rev&rev=567193
Log:
Added removal of unused locks to avoid out of memory
Modified:
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/AbstractLockManager.java
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/SimpleLockManager.java
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/locks/ResourceRWLock.java
Modified:
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/AbstractLockManager.java
URL:
http://svn.apache.org/viewvc/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/AbstractLockManager.java?view=diff&rev=567193&r1=567192&r2=567193
==============================================================================
---
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/AbstractLockManager.java
(original)
+++
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/AbstractLockManager.java
Fri Aug 17 17:25:19 2007
@@ -45,6 +45,8 @@
release();
}
+ abstract protected void release();
+
@Override
public void startWork(long timeout, TimeUnit unit) {
if (isWorking()) {
@@ -98,19 +100,6 @@
long remainingTime = computeRemainingTime(thread);
return (remainingTime < 0);
- }
-
- protected void release() {
- Set<Lock> locks = locksForThreads.get(Thread.currentThread());
- // graceful reaction...
- if (locks == null) {
- return;
- }
- for (Lock lock : locks) {
- lock.unlock();
- }
-
- locksForThreads.remove(Thread.currentThread());
}
protected static class KeyEntry<K, M> {
Modified:
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java
URL:
http://svn.apache.org/viewvc/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java?view=diff&rev=567193&r1=567192&r2=567193
==============================================================================
---
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java
(original)
+++
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/RWLockManager.java
Fri Aug 17 17:25:19 2007
@@ -18,21 +18,64 @@
import java.util.Collection;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
+import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.transaction.locking.AbstractLockManager.KeyEntry;
import org.apache.commons.transaction.locking.LockException.Code;
import org.apache.commons.transaction.locking.locks.ResourceRWLock;
public class RWLockManager<K, M> extends AbstractLockManager<K, M> implements
LockManager<K, M> {
- protected ConcurrentHashMap<KeyEntry<K, M>, ResourceRWLock> locks = new
ConcurrentHashMap<KeyEntry<K, M>, ResourceRWLock>();
-
+ private Log log = LogFactory.getLog(getClass());
+
+ protected ConcurrentHashMap<KeyEntry<K, M>, ResourceRWLock> allLocks = new
ConcurrentHashMap<KeyEntry<K, M>, ResourceRWLock>();
+
private long absolutePrewaitTime = -1;
+
private long prewaitTimeDivisor = 10;
+ protected void release() {
+ Set<Lock> locks = locksForThreads.get(Thread.currentThread());
+ // graceful reaction...
+ if (locks == null) {
+ return;
+ }
+
+ // first release all locks
+ for (Lock lock : locks) {
+ lock.unlock();
+ }
+
+ // then remove all locks that are no longer needed to avoid out of
+ // memory
+ removeUnsuedLocks();
+
+ locksForThreads.remove(Thread.currentThread());
+ }
+
+ protected void removeUnsuedLocks() {
+ Set<Entry<KeyEntry<K, M>, ResourceRWLock>> locksToCheck =
allLocks.entrySet();
+ for (Entry<KeyEntry<K, M>, ResourceRWLock> entry : locksToCheck) {
+ KeyEntry<K, M> keyEntry = entry.getKey();
+ ResourceRWLock lock = entry.getValue();
+
+ // remove lock if no other thread holds a it
+ if (lock.isUnacquired()) {
+ // only remove if no one else has modified it in the meantime
+ if (allLocks.remove(keyEntry, lock)) {
+ log.debug("Completely removing unused lock" + lock);
+ }
+ }
+ }
+ }
+
protected ResourceRWLock create(String name) {
return new ResourceRWLock(name);
}
@@ -46,7 +89,7 @@
String resourceName = entry.toString();
ResourceRWLock rwlock = create(resourceName);
- ResourceRWLock existingLock = locks.putIfAbsent(entry, rwlock);
+ ResourceRWLock existingLock = allLocks.putIfAbsent(entry, rwlock);
if (existingLock != null)
rwlock = existingLock;
Set<Lock> locksForThisThread =
locksForThreads.get(Thread.currentThread());
@@ -132,7 +175,8 @@
}
long getPrewaitTime(long timeMsecs) {
- if (absolutePrewaitTime != -1) return absolutePrewaitTime;
+ if (absolutePrewaitTime != -1)
+ return absolutePrewaitTime;
return timeMsecs / prewaitTimeDivisor;
}
Modified:
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/SimpleLockManager.java
URL:
http://svn.apache.org/viewvc/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/SimpleLockManager.java?view=diff&rev=567193&r1=567192&r2=567193
==============================================================================
---
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/SimpleLockManager.java
(original)
+++
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/SimpleLockManager.java
Fri Aug 17 17:25:19 2007
@@ -43,7 +43,7 @@
LockManager<K, M> {
private Log logger = LogFactory.getLog(getClass());
- protected ConcurrentHashMap<KeyEntry<K, M>, ReentrantLock> locks = new
ConcurrentHashMap<KeyEntry<K, M>, ReentrantLock>();
+ protected ConcurrentHashMap<KeyEntry<K, M>, ReentrantLock> allLocks = new
ConcurrentHashMap<KeyEntry<K, M>, ReentrantLock>();
protected ReentrantLock create() {
return new ReentrantLock();
@@ -56,7 +56,7 @@
KeyEntry<K, M> entry = new KeyEntry<K, M>(key, managedResource);
ReentrantLock lock = create();
- ReentrantLock existingLock = locks.putIfAbsent(entry, lock);
+ ReentrantLock existingLock = allLocks.putIfAbsent(entry, lock);
if (existingLock != null)
lock = existingLock;
Set<Lock> locks = locksForThreads.get(Thread.currentThread());
Modified:
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/locks/ResourceRWLock.java
URL:
http://svn.apache.org/viewvc/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/locks/ResourceRWLock.java?view=diff&rev=567193&r1=567192&r2=567193
==============================================================================
---
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/locks/ResourceRWLock.java
(original)
+++
commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/locks/ResourceRWLock.java
Fri Aug 17 17:25:19 2007
@@ -88,6 +88,10 @@
waiterThreads.remove(current);
}
+ public boolean isUnacquired() {
+ return sync.isUnacquired();
+ }
+
public class InnerLock {
public ResourceRWLock getResourceRWLock() {
return ResourceRWLock.this;
@@ -195,6 +199,20 @@
private final int WRITE_LOCK = -1;
+ public boolean isUnacquired() {
+ return getState() == NO_LOCK;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Sync) {
+ Sync otherSync = (Sync) obj;
+ return (getState() == otherSync.getState() && readerThreads
+ .equals(otherSync.readerThreads));
+ }
+ return false;
+ }
+
protected boolean tryRelease(int unsused) {
Thread current = Thread.currentThread();
// gracefully return in case we do not even have the lock
@@ -202,7 +220,8 @@
return true;
setExclusiveOwnerThread(null);
// if we release an exclusive lock, this can only mean we are the
- // only who possibly could and the only possible outcome is that
+ // only one who possibly could do this and the only possible
outcome
+ // is that
// afterwards there are no more locks
setState(NO_LOCK);
return true;
@@ -325,5 +344,14 @@
}
};
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ResourceRWLock) {
+ return sync.equals(((ResourceRWLock) obj).sync);
+ }
+ return false;
+
+ }
}