JobLockService implementation

- Provides transaction-aware locking
 - Post-transaction cleanup is automatically done
 - Retrying for lock acquisition is handled internally as well
 - Downgraded the lock concurrency tests for the build machine (maybe 50 threads was too much)
 - Deadlock tests added for the high-level locking


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@13968 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2009-04-15 19:16:38 +00:00
parent 5bda334c22
commit 389f996f29
12 changed files with 863 additions and 10 deletions

View File

@@ -117,7 +117,7 @@ public abstract class AbstractLockDAOImpl implements LockDAO
{
throw new LockAcquisitionException(
LockAcquisitionException.ERR_EXCLUSIVE_LOCK_EXISTS,
lockQName, lockToken);
lockQName, lockToken, existingLock);
}
existingLocksMap.put(existingLock, existingLock);
}

View File

@@ -335,7 +335,7 @@ public class LockDAOTest extends TestCase
public synchronized void testConcurrentLockAquisition() throws Exception
{
ReentrantLock threadLock = new ReentrantLock();
GetLockThread[] threads = new GetLockThread[50];
GetLockThread[] threads = new GetLockThread[5];
for (int i = 0; i < threads.length; i++)
{
threads[i] = new GetLockThread(threadLock);
@@ -346,7 +346,7 @@ public class LockDAOTest extends TestCase
waitLoop:
for (int waitLoop = 0; waitLoop < 50; waitLoop++)
{
wait(2000L);
wait(1000L);
for (int i = 0; i < threads.length; i++)
{
if (!threads[i].done)

View File

@@ -37,6 +37,8 @@ import org.alfresco.util.EqualsHelper;
*/
public class LockEntity
{
public static final Long CONST_LONG_ZERO = new Long(0L);
private Long id;
private Long version;
private Long sharedResourceId;
@@ -71,6 +73,18 @@ public class LockEntity
}
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(512);
sb.append("LockEntity")
.append("[ ID=").append(id)
.append(", sharedResourceId=").append(sharedResourceId)
.append(", exclusiveResourceId=").append(exclusiveResourceId)
.append("]");
return sb.toString();
}
/**
* Determine if the lock is logically exclusive. A lock is <b>exclusive</b> if the
* shared lock resource matches the exclusive lock resource.
@@ -111,9 +125,20 @@ public class LockEntity
this.version = version;
}
/**
* Increments the version number or resets it if it reaches a large number
*/
public void incrementVersion()
{
this.version = new Long(version.longValue() + 1L);
long currentVersion = version.longValue();
if (currentVersion >= 10E6)
{
this.version = CONST_LONG_ZERO;
}
else
{
this.version = new Long(version.longValue() + 1L);
}
}
/**

View File

@@ -41,7 +41,6 @@ import org.springframework.orm.ibatis.SqlMapClientTemplate;
*/
public class LockDAOImpl extends AbstractLockDAOImpl
{
private static final Long CONST_LONG_ZERO = new Long(0L);
private static final String SELECT_LOCKRESOURCE_BY_QNAME = "select.LockResourceByQName";
private static final String SELECT_LOCK_BY_ID = "select.LockByID";
private static final String SELECT_LOCK_BY_KEY = "select.LockByKey";
@@ -73,7 +72,7 @@ public class LockDAOImpl extends AbstractLockDAOImpl
protected LockResourceEntity createLockResource(Long qnameNamespaceId, String qnameLocalName)
{
LockResourceEntity lockResource = new LockResourceEntity();
lockResource.setVersion(CONST_LONG_ZERO);
lockResource.setVersion(LockEntity.CONST_LONG_ZERO);
lockResource.setQnameNamespaceId(qnameNamespaceId);
lockResource.setQnameLocalName(qnameLocalName);
Long id = (Long) template.insert(INSERT_LOCKRESOURCE, lockResource);
@@ -120,7 +119,7 @@ public class LockDAOImpl extends AbstractLockDAOImpl
long timeToLive)
{
LockEntity lock = new LockEntity();
lock.setVersion(CONST_LONG_ZERO);
lock.setVersion(LockEntity.CONST_LONG_ZERO);
lock.setSharedResourceId(sharedResourceId);
lock.setExclusiveResourceId(exclusiveResourceId);
lock.setLockToken(lockToken);