You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@manifoldcf.apache.org by kw...@apache.org on 2014/01/22 17:17:47 UTC
svn commit: r1560404 - in
/manifoldcf/branches/CONNECTORS-867/framework/core/src:
main/java/org/apache/manifoldcf/core/lockmanager/
test/java/org/apache/manifoldcf/core/lockmanager/
Author: kwright
Date: Wed Jan 22 16:17:46 2014
New Revision: 1560404
URL: http://svn.apache.org/r1560404
Log:
Revamp of how locks are managed, which seems logically correct but doesn't yet pass tests.
Added:
manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockGate.java (with props)
Modified:
manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/BaseLockManager.java
manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/FileLockObject.java
manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockObject.java
manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockPool.java
manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperLockObject.java
manifoldcf/branches/CONNECTORS-867/framework/core/src/test/java/org/apache/manifoldcf/core/lockmanager/TestZooKeeperLocks.java
Modified: manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/BaseLockManager.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/BaseLockManager.java?rev=1560404&r1=1560403&r2=1560404&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/BaseLockManager.java (original)
+++ manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/BaseLockManager.java Wed Jan 22 16:17:46 2014
@@ -41,6 +41,9 @@ public class BaseLockManager implements
protected final static int TYPE_WRITENONEX = 2;
protected final static int TYPE_WRITE = 3;
+ // This is the local thread ID
+ protected final Long threadID;
+
// These are for locks which putatitively cross JVM boundaries.
// In this implementation, they ar strictly local, and are distinct from sections
// just because of the namespace issues.
@@ -60,6 +63,7 @@ public class BaseLockManager implements
public BaseLockManager()
throws ManifoldCFException
{
+ threadID = new Long(Thread.currentThread().getId());
}
// Node synchronization
@@ -734,14 +738,14 @@ public class BaseLockManager implements
public final void enterNonExWriteLock(String lockKey)
throws ManifoldCFException
{
- enterNonExWrite(lockKey, "lock", localLocks, getGlobalLockPool());
+ enterNonExWrite(threadID, lockKey, "lock", localLocks, getGlobalLockPool());
}
@Override
public final void enterNonExWriteLockNoWait(String lockKey)
throws ManifoldCFException, LockException
{
- enterNonExWriteNoWait(lockKey, "lock", localLocks, getGlobalLockPool());
+ enterNonExWriteNoWait(threadID, lockKey, "lock", localLocks, getGlobalLockPool());
}
/** Leave a non-exclusive write lock.
@@ -760,14 +764,14 @@ public class BaseLockManager implements
public final void enterWriteLock(String lockKey)
throws ManifoldCFException
{
- enterWrite(lockKey, "lock", localLocks, getGlobalLockPool());
+ enterWrite(threadID, lockKey, "lock", localLocks, getGlobalLockPool());
}
@Override
public final void enterWriteLockNoWait(String lockKey)
throws ManifoldCFException, LockException
{
- enterWriteNoWait(lockKey, "lock", localLocks, getGlobalLockPool());
+ enterWriteNoWait(threadID, lockKey, "lock", localLocks, getGlobalLockPool());
}
@Override
@@ -783,14 +787,14 @@ public class BaseLockManager implements
public final void enterReadLock(String lockKey)
throws ManifoldCFException
{
- enterRead(lockKey, "lock", localLocks, getGlobalLockPool());
+ enterRead(threadID, lockKey, "lock", localLocks, getGlobalLockPool());
}
@Override
public final void enterReadLockNoWait(String lockKey)
throws ManifoldCFException, LockException
{
- enterReadNoWait(lockKey, "lock", localLocks, getGlobalLockPool());
+ enterReadNoWait(threadID, lockKey, "lock", localLocks, getGlobalLockPool());
}
@Override
@@ -806,14 +810,14 @@ public class BaseLockManager implements
public final void enterLocks(String[] readLocks, String[] nonExWriteLocks, String[] writeLocks)
throws ManifoldCFException
{
- enter(readLocks, nonExWriteLocks, writeLocks, "lock", localLocks, getGlobalLockPool());
+ enter(threadID, readLocks, nonExWriteLocks, writeLocks, "lock", localLocks, getGlobalLockPool());
}
@Override
public final void enterLocksNoWait(String[] readLocks, String[] nonExWriteLocks, String[] writeLocks)
throws ManifoldCFException, LockException
{
- enterNoWait(readLocks, nonExWriteLocks, writeLocks, "lock", localLocks, getGlobalLockPool());
+ enterNoWait(threadID, readLocks, nonExWriteLocks, writeLocks, "lock", localLocks, getGlobalLockPool());
}
/** Leave multiple locks
@@ -841,7 +845,7 @@ public class BaseLockManager implements
public final void enterReadCriticalSection(String sectionKey)
throws ManifoldCFException
{
- enterRead(sectionKey, "critical section", localSections, mySections);
+ enterRead(threadID, sectionKey, "critical section", localSections, mySections);
}
/** Leave a named, read critical section (NOT a lock). Critical sections never cross JVM boundaries.
@@ -865,7 +869,7 @@ public class BaseLockManager implements
public final void enterNonExWriteCriticalSection(String sectionKey)
throws ManifoldCFException
{
- enterNonExWrite(sectionKey, "critical section", localSections, mySections);
+ enterNonExWrite(threadID, sectionKey, "critical section", localSections, mySections);
}
/** Leave a named, non-exclusive write critical section (NOT a lock). Critical sections never cross JVM boundaries.
@@ -889,7 +893,7 @@ public class BaseLockManager implements
public final void enterWriteCriticalSection(String sectionKey)
throws ManifoldCFException
{
- enterWrite(sectionKey, "critical section", localSections, mySections);
+ enterWrite(threadID, sectionKey, "critical section", localSections, mySections);
}
/** Leave a named, exclusive critical section (NOT a lock). Critical sections never cross JVM boundaries.
@@ -913,7 +917,7 @@ public class BaseLockManager implements
public final void enterCriticalSections(String[] readSectionKeys, String[] nonExSectionKeys, String[] writeSectionKeys)
throws ManifoldCFException
{
- enter(readSectionKeys, nonExSectionKeys, writeSectionKeys, "critical section", localSections, mySections);
+ enter(threadID, readSectionKeys, nonExSectionKeys, writeSectionKeys, "critical section", localSections, mySections);
}
/** Leave multiple critical sections simultaneously.
@@ -931,7 +935,7 @@ public class BaseLockManager implements
// Protected methods
- protected static void enterNonExWrite(String lockKey, String description, LocalLockPool localLocks, LockPool crossLocks)
+ protected static void enterNonExWrite(Long threadID, String lockKey, String description, LocalLockPool localLocks, LockPool crossLocks)
throws ManifoldCFException
{
if (Logging.lock.isDebugEnabled())
@@ -959,10 +963,10 @@ public class BaseLockManager implements
// to know if we already have a a read lock.
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
try
{
- lo.enterNonExWriteLock();
+ lo.enterNonExWriteLock(threadID);
break;
}
catch (InterruptedException e)
@@ -979,7 +983,7 @@ public class BaseLockManager implements
Logging.lock.debug(" Successfully obtained "+description+"!");
}
- protected static void enterNonExWriteNoWait(String lockKey, String description, LocalLockPool localLocks, LockPool crossLocks)
+ protected static void enterNonExWriteNoWait(Long threadID, String lockKey, String description, LocalLockPool localLocks, LockPool crossLocks)
throws ManifoldCFException, LockException
{
if (Logging.lock.isDebugEnabled())
@@ -1008,12 +1012,12 @@ public class BaseLockManager implements
// to know if we already have a a read lock.
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
try
{
synchronized (lo)
{
- lo.enterNonExWriteLockNoWait();
+ lo.enterNonExWriteLockNoWait(threadID);
break;
}
}
@@ -1056,7 +1060,7 @@ public class BaseLockManager implements
{
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
try
{
lo.leaveNonExWriteLock();
@@ -1091,7 +1095,7 @@ public class BaseLockManager implements
}
}
- protected static void enterWrite(String lockKey, String description, LocalLockPool localLocks, LockPool crossLocks)
+ protected static void enterWrite(Long threadID, String lockKey, String description, LocalLockPool localLocks, LockPool crossLocks)
throws ManifoldCFException
{
if (Logging.lock.isDebugEnabled())
@@ -1120,10 +1124,10 @@ public class BaseLockManager implements
// it's illegal.
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
try
{
- lo.enterWriteLock();
+ lo.enterWriteLock(threadID);
break;
}
catch (InterruptedException e)
@@ -1140,7 +1144,7 @@ public class BaseLockManager implements
Logging.lock.debug(" Successfully obtained "+description+"!");
}
- protected static void enterWriteNoWait(String lockKey, String description, LocalLockPool localLocks, LockPool crossLocks)
+ protected static void enterWriteNoWait(Long threadID, String lockKey, String description, LocalLockPool localLocks, LockPool crossLocks)
throws ManifoldCFException, LockException
{
if (Logging.lock.isDebugEnabled())
@@ -1169,12 +1173,12 @@ public class BaseLockManager implements
// it's illegal.
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
try
{
synchronized (lo)
{
- lo.enterWriteLockNoWait();
+ lo.enterWriteLockNoWait(threadID);
break;
}
}
@@ -1216,7 +1220,7 @@ public class BaseLockManager implements
{
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
try
{
lo.leaveWriteLock();
@@ -1251,7 +1255,7 @@ public class BaseLockManager implements
}
}
- protected static void enterRead(String lockKey, String description, LocalLockPool localLocks, LockPool crossLocks)
+ protected static void enterRead(Long threadID, String lockKey, String description, LocalLockPool localLocks, LockPool crossLocks)
throws ManifoldCFException
{
if (Logging.lock.isDebugEnabled())
@@ -1273,10 +1277,10 @@ public class BaseLockManager implements
// We don't own a local read lock. Get one.
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
try
{
- lo.enterReadLock();
+ lo.enterReadLock(threadID);
break;
}
catch (InterruptedException e)
@@ -1293,7 +1297,7 @@ public class BaseLockManager implements
Logging.lock.debug(" Successfully obtained "+description+"!");
}
- protected static void enterReadNoWait(String lockKey, String description, LocalLockPool localLocks, LockPool crossLocks)
+ protected static void enterReadNoWait(Long threadID, String lockKey, String description, LocalLockPool localLocks, LockPool crossLocks)
throws ManifoldCFException, LockException
{
if (Logging.lock.isDebugEnabled())
@@ -1314,12 +1318,12 @@ public class BaseLockManager implements
// We don't own a local read lock. Get one.
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
try
{
synchronized (lo)
{
- lo.enterReadLockNoWait();
+ lo.enterReadLockNoWait(threadID);
break;
}
}
@@ -1359,7 +1363,7 @@ public class BaseLockManager implements
{
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
try
{
lo.leaveReadLock();
@@ -1411,7 +1415,7 @@ public class BaseLockManager implements
}
}
- protected static void enter(String[] readLocks, String[] nonExWriteLocks, String[] writeLocks, String description, LocalLockPool localLocks, LockPool crossLocks)
+ protected static void enter(Long threadID, String[] readLocks, String[] nonExWriteLocks, String[] writeLocks, String description, LocalLockPool localLocks, LockPool crossLocks)
throws ManifoldCFException
{
if (Logging.lock.isDebugEnabled())
@@ -1473,10 +1477,10 @@ public class BaseLockManager implements
// We don't own a local write lock. Get one.
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
try
{
- lo.enterWriteLock();
+ lo.enterWriteLock(threadID);
break;
}
catch (ExpiredObjectException e)
@@ -1501,10 +1505,10 @@ public class BaseLockManager implements
// We don't own a local write lock. Get one.
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
try
{
- lo.enterNonExWriteLock();
+ lo.enterNonExWriteLock(threadID);
break;
}
catch (ExpiredObjectException e)
@@ -1522,10 +1526,10 @@ public class BaseLockManager implements
// We don't own a local read lock. Get one.
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
try
{
- lo.enterReadLock();
+ lo.enterReadLock(threadID);
break;
}
catch (ExpiredObjectException e)
@@ -1596,7 +1600,7 @@ public class BaseLockManager implements
}
}
- protected static void enterNoWait(String[] readLocks, String[] nonExWriteLocks, String[] writeLocks, String description, LocalLockPool localLocks, LockPool crossLocks)
+ protected static void enterNoWait(Long threadID, String[] readLocks, String[] nonExWriteLocks, String[] writeLocks, String description, LocalLockPool localLocks, LockPool crossLocks)
throws ManifoldCFException, LockException
{
if (Logging.lock.isDebugEnabled())
@@ -1658,12 +1662,12 @@ public class BaseLockManager implements
// We don't own a local write lock. Get one.
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
synchronized (lo)
{
try
{
- lo.enterWriteLockNoWait();
+ lo.enterWriteLockNoWait(threadID);
break;
}
catch (ExpiredObjectException e)
@@ -1689,12 +1693,12 @@ public class BaseLockManager implements
// We don't own a local write lock. Get one.
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
synchronized (lo)
{
try
{
- lo.enterNonExWriteLockNoWait();
+ lo.enterNonExWriteLockNoWait(threadID);
break;
}
catch (ExpiredObjectException e)
@@ -1713,12 +1717,12 @@ public class BaseLockManager implements
// We don't own a local read lock. Get one.
while (true)
{
- LockObject lo = crossLocks.getObject(lockKey);
+ LockGate lo = crossLocks.getObject(lockKey);
synchronized (lo)
{
try
{
- lo.enterReadLockNoWait();
+ lo.enterReadLockNoWait(threadID);
break;
}
catch (ExpiredObjectException e)
Modified: manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/FileLockObject.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/FileLockObject.java?rev=1560404&r1=1560403&r2=1560404&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/FileLockObject.java (original)
+++ manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/FileLockObject.java Wed Jan 22 16:17:46 2014
@@ -92,7 +92,7 @@ public class FileLockObject extends Lock
}
@Override
- protected void clearGlobalWriteLock()
+ protected void clearGlobalWriteLockNoWait()
throws ManifoldCFException, LockException, InterruptedException
{
if (isSync)
@@ -136,7 +136,7 @@ public class FileLockObject extends Lock
}
@Override
- protected void clearGlobalNonExWriteLock()
+ protected void clearGlobalNonExWriteLockNoWait()
throws ManifoldCFException, LockException, InterruptedException
{
if (isSync)
@@ -185,7 +185,7 @@ public class FileLockObject extends Lock
}
@Override
- protected void clearGlobalReadLock()
+ protected void clearGlobalReadLockNoWait()
throws ManifoldCFException, LockException, InterruptedException
{
if (isSync)
Added: manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockGate.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockGate.java?rev=1560404&view=auto
==============================================================================
--- manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockGate.java (added)
+++ manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockGate.java Wed Jan 22 16:17:46 2014
@@ -0,0 +1,227 @@
+/* $Id$ */
+
+/**
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.manifoldcf.core.lockmanager;
+
+import java.util.*;
+import java.io.*;
+import org.apache.manifoldcf.core.interfaces.*;
+
+/** This class creates a first-come, first-serve local queue for locks.
+* The usage model is as follows:
+* (1) There is one lock gate per key for all threads.
+* (2) The LockGate replaces LockObjects in the pool, but each LockGate refers to
+* a LockObject. They are separate objects though because they require separate locking.
+* (3) When a lock is desired, the appropriate LockGate method is called to obtain
+* the lock. This method places the thread ID onto the queue, and waits until
+* the thread ID reaches the head of the queue before executing the lock request.
+* (4) Only when the lock request is successful, or is aborted, is the thread ID
+* removed from the queue. Write requests therefore serve to block read requests
+* until the write request is serviced.
+* Preferred structure:
+* <wait_for_permission>
+* try {
+* ... obtain the lock ...
+* } finally {
+* <release_permission>
+* }
+* Problem: Delay in obtaining a lock causes LockGate to "back up". This is because
+* the thread ID is not removed before the thread blocks waiting to get the lock.
+* One solution: Don't block while holding permission open. But this defeats the whole
+* point of the priority queue, which is to reserve locks in the order they are requested.
+* A second solution is to work through threadRequests object notifications so that we
+* can break out of those waits too. So there may be a lockpool reference locked against threadRequests
+* that also gets cleared etc.
+*/
+public class LockGate
+{
+ protected final List<Long> threadRequests = new ArrayList<Long>();
+ protected final LockObject lockObject;
+ protected final Object lockKey;
+ protected LockPool lockPool;
+
+ public LockGate(Object lockKey, LockObject lockObject, LockPool lockPool)
+ {
+ this.lockKey = lockKey;
+ this.lockObject = lockObject;
+ this.lockPool = lockPool;
+ }
+
+ public synchronized void makeInvalid()
+ {
+ this.lockPool = null;
+ lockObject.makeInvalid();
+ }
+
+ protected void waitForPermission(Long threadID)
+ throws InterruptedException, ExpiredObjectException
+ {
+ synchronized (this)
+ {
+ threadRequests.add(threadID);
+ }
+
+ // Now, wait until we are #1
+ while (true)
+ {
+ synchronized (this)
+ {
+ if (lockPool == null)
+ throw new ExpiredObjectException("Invalid");
+
+ if (threadRequests.get(0).equals(threadID))
+ return;
+
+ wait();
+ }
+ }
+ }
+
+ protected void freePermission(Long threadID)
+ {
+ synchronized (this)
+ {
+ threadRequests.remove(threadID);
+ notifyAll();
+ }
+ }
+
+ public void enterWriteLock(Long threadID)
+ throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ {
+ waitForPermission(threadID);
+ try
+ {
+ lockObject.enterWriteLock();
+ }
+ finally
+ {
+ freePermission(threadID);
+ }
+ }
+
+ public void enterWriteLockNoWait(Long threadID)
+ throws ManifoldCFException, LockException, LocalLockException, InterruptedException, ExpiredObjectException
+ {
+ waitForPermission(threadID);
+ try
+ {
+ lockObject.enterWriteLockNoWait();
+ }
+ finally
+ {
+ freePermission(threadID);
+ }
+ }
+
+ public void leaveWriteLock()
+ throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ {
+ // Leave, and if we succeed, flush from pool.
+ lockObject.leaveWriteLock();
+ synchronized (this)
+ {
+ if (lockPool == null)
+ throw new ExpiredObjectException("Invalid");
+ lockPool.releaseObject(lockKey, this);
+ }
+ }
+
+ public void enterNonExWriteLock(Long threadID)
+ throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ {
+ waitForPermission(threadID);
+ try
+ {
+ lockObject.enterNonExWriteLock();
+ }
+ finally
+ {
+ freePermission(threadID);
+ }
+ }
+
+ public void enterNonExWriteLockNoWait(Long threadID)
+ throws ManifoldCFException, LockException, LocalLockException, InterruptedException, ExpiredObjectException
+ {
+ waitForPermission(threadID);
+ try
+ {
+ lockObject.enterNonExWriteLockNoWait();
+ }
+ finally
+ {
+ freePermission(threadID);
+ }
+ }
+
+ public void leaveNonExWriteLock()
+ throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ {
+ // Leave, and if we succeed, flush from pool.
+ lockObject.leaveNonExWriteLock();
+ synchronized (this)
+ {
+ if (lockPool == null)
+ throw new ExpiredObjectException("Invalid");
+ lockPool.releaseObject(lockKey, this);
+ }
+ }
+
+ public void enterReadLock(Long threadID)
+ throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ {
+ waitForPermission(threadID);
+ try
+ {
+ lockObject.enterReadLock();
+ }
+ finally
+ {
+ freePermission(threadID);
+ }
+ }
+
+ public void enterReadLockNoWait(Long threadID)
+ throws ManifoldCFException, LockException, LocalLockException, InterruptedException, ExpiredObjectException
+ {
+ waitForPermission(threadID);
+ try
+ {
+ lockObject.enterReadLockNoWait();
+ }
+ finally
+ {
+ freePermission(threadID);
+ }
+ }
+
+ public void leaveReadLock()
+ throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ {
+ // Leave, and if we succeed, flush from pool.
+ lockObject.leaveReadLock();
+ synchronized (this)
+ {
+ if (lockPool == null)
+ throw new ExpiredObjectException("Invalid");
+ lockPool.releaseObject(lockKey, this);
+ }
+ }
+
+}
Propchange: manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockGate.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockGate.java
------------------------------------------------------------------------------
svn:keywords = Id
Modified: manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockObject.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockObject.java?rev=1560404&r1=1560403&r2=1560404&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockObject.java (original)
+++ manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockObject.java Wed Jan 22 16:17:46 2014
@@ -32,9 +32,9 @@ public class LockObject
protected final Object lockKey;
private LockPool lockPool;
- private boolean obtainedWrite = false; // Set to true if this object already owns the permission to exclusively write
- private int obtainedRead = 0; // Set to a count if this object already owns the permission to read
- private int obtainedNonExWrite = 0; // Set to a count if this object already owns the permission to non-exclusively write
+ private volatile boolean obtainedWrite = false; // Set to true if this object already owns the permission to exclusively write
+ private volatile int obtainedRead = 0; // Set to a count if this object already owns the permission to read
+ private volatile int obtainedNonExWrite = 0; // Set to a count if this object already owns the permission to non-exclusively write
protected static final String LOCKEDANOTHERTHREAD = "Locked by another thread in this JVM";
protected static final String LOCKEDANOTHERJVM = "Locked by another JVM";
@@ -54,36 +54,33 @@ public class LockObject
/** This method WILL NOT BE CALLED UNLESS we are actually committing a write lock for the
* first time for a given thread.
*/
- public void enterWriteLock()
+ public synchronized void enterWriteLock()
throws ManifoldCFException, InterruptedException, ExpiredObjectException
{
+ if (lockPool == null)
+ throw new ExpiredObjectException("Invalid");
+
while (true)
{
+ if (lockPool == null)
+ throw new ExpiredObjectException("Invalid");
+
try
{
- synchronized (this)
- {
- if (lockPool == null)
- throw new ExpiredObjectException("Invalid");
-
- while (true)
- {
- try
- {
- enterWriteLockNoWait();
- return;
- }
- catch (LocalLockException le)
- {
- wait();
- }
- }
- }
+ // Does another thread in this JVM have the writelock?
+ if (obtainedWrite)
+ throw new LocalLockException(LOCKEDANOTHERTHREAD);
+ // Got the write token!
+ if (obtainedRead > 0 || obtainedNonExWrite > 0)
+ throw new LocalLockException(LOCKEDANOTHERTHREAD);
+ // Attempt to obtain a global write lock
+ obtainGlobalWriteLock();
+ obtainedWrite = true;
+ return;
}
- catch (LockException le2)
+ catch (LocalLockException le)
{
- // Cross JVM lock; sleep!
- ManifoldCF.sleep(10);
+ wait();
}
}
}
@@ -117,94 +114,100 @@ public class LockObject
{
}
-
- public void leaveWriteLock()
- throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ protected void obtainGlobalWriteLock()
+ throws ManifoldCFException, InterruptedException
{
while (true)
{
try
{
- synchronized (this)
- {
- if (lockPool == null)
- throw new ExpiredObjectException("Invalid");
-
- if (obtainedWrite == false)
- throw new RuntimeException("JVM failure: Don't hold lock for object "+this.toString());
- obtainedWrite = false;
- try
- {
- clearGlobalWriteLock();
- }
- catch (LockException le)
- {
- obtainedWrite = true;
- throw le;
- }
- catch (Error e)
- {
- obtainedWrite = true;
- throw e;
- }
- catch (RuntimeException e)
- {
- obtainedWrite = true;
- throw e;
- }
-
- // Lock is free, so release this object from the pool
- lockPool.releaseObject(lockKey,this);
-
- notifyAll();
- return;
- }
+ obtainGlobalWriteLockNoWait();
+ return;
}
- catch (LockException le)
+ catch (LockException e)
{
- ManifoldCF.sleep(10);
- // Loop around
+ // Cross JVM lock; sleep!
+ ManifoldCF.sleep(10L);
}
}
+ }
+
+ public synchronized void leaveWriteLock()
+ throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ {
+ if (lockPool == null)
+ throw new ExpiredObjectException("Invalid");
+
+ if (obtainedWrite == false)
+ throw new RuntimeException("JVM failure: Don't hold lock for object "+this.toString());
+ obtainedWrite = false;
+ try
+ {
+ clearGlobalWriteLock();
+ }
+ catch (Error e)
+ {
+ obtainedWrite = true;
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ obtainedWrite = true;
+ throw e;
+ }
+ notifyAll();
}
- protected void clearGlobalWriteLock()
+ protected void clearGlobalWriteLockNoWait()
throws ManifoldCFException, LockException, InterruptedException
{
}
- public void enterNonExWriteLock()
- throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ protected void clearGlobalWriteLock()
+ throws ManifoldCFException, InterruptedException
{
while (true)
{
try
{
- synchronized (this)
- {
- if (lockPool == null)
- throw new ExpiredObjectException("Invalid");
+ clearGlobalWriteLockNoWait();
+ return;
+ }
+ catch (LockException e)
+ {
+ ManifoldCF.sleep(10L);
+ }
+ }
+ }
+
+ public synchronized void enterNonExWriteLock()
+ throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ {
+ // System.out.println("Entering write lock for resource "+lockFileName);
+ while (true)
+ {
+ if (lockPool == null)
+ throw new ExpiredObjectException("Invalid");
- // System.out.println("Entering write lock for resource "+lockFileName);
- while (true)
- {
- try
- {
- enterNonExWriteLockNoWait();
- return;
- }
- catch (LocalLockException le)
- {
- wait();
- }
- }
+ try
+ {
+ // Does another thread in this JVM have the lock?
+ if (obtainedWrite || obtainedRead > 0)
+ throw new LocalLockException(LOCKEDANOTHERTHREAD);
+ // We've got the local non-ex write token
+ if (obtainedNonExWrite > 0)
+ {
+ obtainedNonExWrite++;
+ return;
}
+ obtainGlobalNonExWriteLock();
+ obtainedNonExWrite++;
+ return;
}
- catch (LockException le2)
+ catch (LocalLockException le)
{
- // Cross JVM lock; sleep!
- ManifoldCF.sleep(10);
+ wait();
}
}
}
@@ -240,102 +243,100 @@ public class LockObject
{
}
-
- public void leaveNonExWriteLock()
- throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ protected void obtainGlobalNonExWriteLock()
+ throws ManifoldCFException, InterruptedException
{
- // System.out.println("Releasing non-ex-write lock for resource "+lockFileName.toString());
while (true)
{
try
{
- synchronized (this)
- {
- if (lockPool == null)
- throw new ExpiredObjectException("Invalid");
-
- if (obtainedNonExWrite == 0)
- throw new RuntimeException("JVM error: Don't hold lock for object "+this.toString());
- obtainedNonExWrite--;
- if (obtainedNonExWrite > 0)
- return;
-
- try
- {
- clearGlobalNonExWriteLock();
- }
- catch (LockException le)
- {
- obtainedNonExWrite++;
- throw le;
- }
- catch (Error e)
- {
- obtainedNonExWrite++;
- throw e;
- }
- catch (RuntimeException e)
- {
- obtainedNonExWrite++;
- throw e;
- }
-
- // Lock is free, so release this object from the pool
- lockPool.releaseObject(lockKey,this);
-
- notifyAll();
- break;
- }
+ obtainGlobalNonExWriteLockNoWait();
+ return;
}
- catch (LockException le)
+ catch (LockException e)
{
- ManifoldCF.sleep(10);
- // Loop around
+ // Cross JVM lock; sleep!
+ ManifoldCF.sleep(10L);
}
}
- // System.out.println("Non-ex Write lock released for resource "+lockFileName.toString());
}
- protected void clearGlobalNonExWriteLock()
+ public synchronized void leaveNonExWriteLock()
+ throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ {
+ if (lockPool == null)
+ throw new ExpiredObjectException("Invalid");
+
+ if (obtainedNonExWrite == 0)
+ throw new RuntimeException("JVM error: Don't hold lock for object "+this.toString());
+ obtainedNonExWrite--;
+ if (obtainedNonExWrite > 0)
+ return;
+
+ try
+ {
+ clearGlobalNonExWriteLock();
+ }
+ catch (Error e)
+ {
+ obtainedNonExWrite++;
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ obtainedNonExWrite++;
+ throw e;
+ }
+
+ notifyAll();
+ }
+
+ protected void clearGlobalNonExWriteLockNoWait()
throws ManifoldCFException, LockException, InterruptedException
{
}
+ protected void clearGlobalNonExWriteLock()
+ throws ManifoldCFException, InterruptedException
+ {
+ while (true)
+ {
+ try
+ {
+ clearGlobalNonExWriteLockNoWait();
+ return;
+ }
+ catch (LockException e)
+ {
+ ManifoldCF.sleep(10L);
+ }
+ }
+ }
- public void enterReadLock()
+ public synchronized void enterReadLock()
throws ManifoldCFException, InterruptedException, ExpiredObjectException
{
- // if (lockFileName != null)
- // System.out.println("Entering read lock for resource "+lockFileName.toString()+" "+toString());
while (true)
{
+ if (lockPool == null)
+ throw new ExpiredObjectException("Invalid");
try
{
- synchronized (this)
+ if (obtainedWrite || obtainedNonExWrite > 0)
+ throw new LocalLockException(LOCKEDANOTHERTHREAD);
+ if (obtainedRead > 0)
{
- if (lockPool == null)
- throw new ExpiredObjectException("Invalid");
-
- while (true)
- {
- try
- {
- enterReadLockNoWait();
- // if (lockFileName != null)
- // System.out.println("Obtained read permission for resource "+lockFileName.toString());
- return;
- }
- catch (LocalLockException le)
- {
- wait();
- }
- }
+ obtainedRead++;
+ return;
}
+ // Got the read token locally!
+ obtainGlobalReadLock();
+ obtainedRead = 1;
+ return;
}
- catch (LockException le)
+ catch (LocalLockException le)
{
- ManifoldCF.sleep(10);
- // Loop around
+ wait();
}
}
}
@@ -355,7 +356,6 @@ public class LockObject
}
// Got the read token locally!
obtainGlobalReadLockNoWait();
-
obtainedRead = 1;
}
@@ -364,65 +364,74 @@ public class LockObject
{
}
-
- public void leaveReadLock()
- throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ protected void obtainGlobalReadLock()
+ throws ManifoldCFException, InterruptedException
{
while (true)
{
try
{
- synchronized (this)
- {
- if (lockPool == null)
- throw new ExpiredObjectException("Invalid");
-
- if (obtainedRead == 0)
- throw new RuntimeException("JVM error: Don't hold lock for object "+this.toString());
- obtainedRead--;
- if (obtainedRead > 0)
- {
- return;
- }
- try
- {
- clearGlobalReadLock();
- }
- catch (LockException le)
- {
- obtainedRead++;
- throw le;
- }
- catch (Error e)
- {
- obtainedRead++;
- throw e;
- }
- catch (RuntimeException e)
- {
- obtainedRead++;
- throw e;
- }
-
- // Lock is free, so release this object from the pool
- lockPool.releaseObject(lockKey,this);
-
- notifyAll();
- return;
- }
+ obtainGlobalReadLockNoWait();
+ return;
}
- catch (LockException le)
+ catch (LockException e)
{
- ManifoldCF.sleep(10);
- // Loop around
+ // Cross JVM lock; sleep!
+ ManifoldCF.sleep(10L);
}
}
}
+
+ public synchronized void leaveReadLock()
+ throws ManifoldCFException, InterruptedException, ExpiredObjectException
+ {
+ if (lockPool == null)
+ throw new ExpiredObjectException("Invalid");
- protected void clearGlobalReadLock()
+ if (obtainedRead == 0)
+ throw new RuntimeException("JVM error: Don't hold lock for object "+this.toString());
+ obtainedRead--;
+ if (obtainedRead > 0)
+ return;
+ try
+ {
+ clearGlobalReadLock();
+ }
+ catch (Error e)
+ {
+ obtainedRead++;
+ throw e;
+ }
+ catch (RuntimeException e)
+ {
+ obtainedRead++;
+ throw e;
+ }
+
+ notifyAll();
+ }
+
+ protected void clearGlobalReadLockNoWait()
throws ManifoldCFException, LockException, InterruptedException
{
}
+ protected void clearGlobalReadLock()
+ throws ManifoldCFException, InterruptedException
+ {
+ while (true)
+ {
+ try
+ {
+ clearGlobalReadLockNoWait();
+ return;
+ }
+ catch (LockException e)
+ {
+ ManifoldCF.sleep(10L);
+ }
+ }
+ }
+
}
Modified: manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockPool.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockPool.java?rev=1560404&r1=1560403&r2=1560404&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockPool.java (original)
+++ manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/LockPool.java Wed Jan 22 16:17:46 2014
@@ -21,15 +21,13 @@ package org.apache.manifoldcf.core.lockm
import java.util.*;
import java.io.*;
-/** Base class of all lock pools. A lock pool is a global set of lock objects looked up by
-* a key. Lock object instantiation differs for different kinds of lock objects, so this
-* base class is expected to be extended accordingly.
+/** Lock pool class. This is a pool of LockGate objects.
*/
public class LockPool
{
public static final String _rcsid = "@(#)$Id: LockPool.java 988245 2010-08-23 18:39:35Z kwright $";
- protected final Map<Object,LockObject> myLocks = new HashMap<Object,LockObject>();
+ protected final Map<Object,LockGate> myLocks = new HashMap<Object,LockGate>();
protected final LockObjectFactory factory;
@@ -38,20 +36,21 @@ public class LockPool
this.factory = factory;
}
- public synchronized LockObject getObject(Object lockKey)
+ public synchronized LockGate getObject(Object lockKey)
{
- LockObject lo = myLocks.get(lockKey);
- if (lo == null)
+ LockGate lg = myLocks.get(lockKey);
+ if (lg == null)
{
- lo = factory.newLockObject(this,lockKey);
- myLocks.put(lockKey,lo);
+ LockObject lo = factory.newLockObject(this,lockKey);
+ lg = new LockGate(lockKey,lo,this);
+ myLocks.put(lockKey,lg);
}
- return lo;
+ return lg;
}
- public synchronized void releaseObject(Object lockKey, LockObject lockObject)
+ public synchronized void releaseObject(Object lockKey, LockGate lockGate)
{
- lockObject.makeInvalid();
+ lockGate.makeInvalid();
myLocks.remove(lockKey);
}
}
Modified: manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperLockObject.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperLockObject.java?rev=1560404&r1=1560403&r2=1560404&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperLockObject.java (original)
+++ manifoldcf/branches/CONNECTORS-867/framework/core/src/main/java/org/apache/manifoldcf/core/lockmanager/ZooKeeperLockObject.java Wed Jan 22 16:17:46 2014
@@ -69,7 +69,7 @@ public class ZooKeeperLockObject extends
}
@Override
- protected void clearGlobalWriteLock()
+ protected void clearGlobalWriteLockNoWait()
throws ManifoldCFException, LockException, InterruptedException
{
if (currentConnection == null)
@@ -102,7 +102,7 @@ public class ZooKeeperLockObject extends
}
@Override
- protected void clearGlobalNonExWriteLock()
+ protected void clearGlobalNonExWriteLockNoWait()
throws ManifoldCFException, LockException, InterruptedException
{
if (currentConnection == null)
@@ -135,7 +135,7 @@ public class ZooKeeperLockObject extends
}
@Override
- protected void clearGlobalReadLock()
+ protected void clearGlobalReadLockNoWait()
throws ManifoldCFException, LockException, InterruptedException
{
if (currentConnection == null)
Modified: manifoldcf/branches/CONNECTORS-867/framework/core/src/test/java/org/apache/manifoldcf/core/lockmanager/TestZooKeeperLocks.java
URL: http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-867/framework/core/src/test/java/org/apache/manifoldcf/core/lockmanager/TestZooKeeperLocks.java?rev=1560404&r1=1560403&r2=1560404&view=diff
==============================================================================
--- manifoldcf/branches/CONNECTORS-867/framework/core/src/test/java/org/apache/manifoldcf/core/lockmanager/TestZooKeeperLocks.java (original)
+++ manifoldcf/branches/CONNECTORS-867/framework/core/src/test/java/org/apache/manifoldcf/core/lockmanager/TestZooKeeperLocks.java Wed Jan 22 16:17:46 2014
@@ -117,12 +117,12 @@ public class TestZooKeeperLocks extends
}
- protected static void enterReadLock(LockObject lo)
+ protected static void enterReadLock(Long threadID, LockGate lo)
throws Exception
{
try
{
- lo.enterReadLock();
+ lo.enterReadLock(threadID);
}
catch (ExpiredObjectException e)
{
@@ -130,7 +130,7 @@ public class TestZooKeeperLocks extends
}
}
- protected static void leaveReadLock(LockObject lo)
+ protected static void leaveReadLock(LockGate lo)
throws Exception
{
try
@@ -143,12 +143,12 @@ public class TestZooKeeperLocks extends
}
}
- protected static void enterWriteLock(LockObject lo)
+ protected static void enterWriteLock(Long threadID, LockGate lo)
throws Exception
{
try
{
- lo.enterWriteLock();
+ lo.enterWriteLock(threadID);
}
catch (ExpiredObjectException e)
{
@@ -156,7 +156,7 @@ public class TestZooKeeperLocks extends
}
}
- protected static void leaveWriteLock(LockObject lo)
+ protected static void leaveWriteLock(LockGate lo)
throws Exception
{
try
@@ -175,7 +175,8 @@ public class TestZooKeeperLocks extends
protected final LockObjectFactory factory;
protected final Object lockKey;
protected final AtomicInteger ai;
-
+ protected final Long threadID;
+
protected Throwable exception = null;
public ReaderThread(LockObjectFactory factory, Object lockKey, AtomicInteger ai)
@@ -184,6 +185,7 @@ public class TestZooKeeperLocks extends
this.factory = factory;
this.lockKey = lockKey;
this.ai = ai;
+ this.threadID = Thread.currentThread().getId();
}
public void run()
@@ -193,13 +195,13 @@ public class TestZooKeeperLocks extends
// Create a new lock pool since that is the best way to insure real
// zookeeper action.
LockPool lp = new LockPool(factory);
- LockObject lo;
+ LockGate lo;
// First test: count all reader threads inside read lock.
// This guarantees that read locks are non-exclusive.
// Enter read lock
System.out.println("Entering read lock");
lo = lp.getObject(lockKey);
- enterReadLock(lo);
+ enterReadLock(threadID,lo);
try
{
System.out.println(" Read lock entered!");
@@ -223,7 +225,7 @@ public class TestZooKeeperLocks extends
{
System.out.println("Waiting for all write threads to succeed...");
lo = lp.getObject(lockKey);
- enterReadLock(lo);
+ enterReadLock(threadID,lo);
try
{
// The writer thread will increment the counter twice for every thread, both times within the lock.
@@ -263,7 +265,8 @@ public class TestZooKeeperLocks extends
protected final LockObjectFactory factory;
protected final Object lockKey;
protected final AtomicInteger ai;
-
+ protected final Long threadID;
+
protected Throwable exception = null;
public WriterThread(LockObjectFactory factory, Object lockKey, AtomicInteger ai)
@@ -272,6 +275,7 @@ public class TestZooKeeperLocks extends
this.factory = factory;
this.lockKey = lockKey;
this.ai = ai;
+ this.threadID = Thread.currentThread().getId();
}
public void run()
@@ -282,12 +286,12 @@ public class TestZooKeeperLocks extends
// zookeeper action.
// LockPool is a dummy
LockPool lp = new LockPool(factory);
- LockObject lo;
+ LockGate lo;
// Take write locks but free them if read is what's active
while (true)
{
lo = lp.getObject(lockKey);
- enterWriteLock(lo);
+ enterWriteLock(threadID,lo);
System.out.println("Made it into write lock");
try
{
@@ -306,7 +310,7 @@ public class TestZooKeeperLocks extends
// Get write lock, increment twice, and leave write lock
lo = lp.getObject(lockKey);
- enterWriteLock(lo);
+ enterWriteLock(threadID,lo);
try
{
if ((ai.get() - readerThreadCount) % 2 == 1)