Added pessimistic locking in several places to shut down deadlocks.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3252 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Britt Park 2006-06-26 16:43:35 +00:00
parent 64288d531d
commit c6dfeb1c9d
10 changed files with 72 additions and 31 deletions

View File

@ -35,7 +35,7 @@ public class AVMStressTest extends AVMServiceTestBase
{
try
{
int nCopies = 1;
int nCopies = 4;
int nThreads = 8;
BulkLoader loader = new BulkLoader(fService);
long start = System.currentTimeMillis();
@ -60,7 +60,7 @@ public class AVMStressTest extends AVMServiceTestBase
20, // modify file.
3200, // read file
10, // snapshot
10000, // # ops
1000, // # ops
fService,
"" + i);
tester.refresh();
@ -73,6 +73,7 @@ public class AVMStressTest extends AVMServiceTestBase
thread.start();
}
int exited = 0;
long sampStart = System.currentTimeMillis();
while (exited != nThreads)
{
try
@ -99,6 +100,22 @@ public class AVMStressTest extends AVMServiceTestBase
exited++;
}
}
/*
long now = System.currentTimeMillis();
if (now - sampStart > 30000)
{
System.err.println("RATE: " + (((long)AVMTester.GetCount()) * 1000 / (now - sampStart)));
for (AVMTester tester : testers)
{
tester.setExit();
}
for (Thread thread : threads)
{
thread.join();
}
fail();
}
*/
}
catch (InterruptedException e)
{

View File

@ -51,6 +51,7 @@ class AVMTester implements Runnable
private List<String> fAllFiles;
private static boolean fgFrozen = false;
private static int fgOpCount = 0;
/**
* The operation table.
@ -239,6 +240,7 @@ class AVMTester implements Runnable
snapshot();
break;
}
IncCount();
}
System.out.println(fAllPaths.size() + " fses in " + (System.currentTimeMillis() - startTime) +
"ms");
@ -615,4 +617,14 @@ class AVMTester implements Runnable
{
return fAllPaths.get(fgRandom.nextInt(fAllPaths.size()));
}
private static synchronized void IncCount()
{
++fgOpCount;
}
public static synchronized int GetCount()
{
return fgOpCount;
}
}

View File

@ -44,9 +44,9 @@ interface DirectoryNode extends AVMNode
* @param lPath The Lookup so far.
* @param name The name of the child to lookup.
* @param version The version to look under.
* @param visited A Set of full paths visited. Used for cycle checking.
* @param write Whether this is occuring in a write context.
*/
public AVMNode lookupChild(Lookup lPath, String name, int version);
public AVMNode lookupChild(Lookup lPath, String name, int version, boolean write);
/**
* Lookup a child node using an AVMNodeDescriptor as context.

View File

@ -19,6 +19,7 @@ package org.alfresco.repo.avm;
import java.util.List;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
@ -49,13 +50,16 @@ abstract class DirectoryNodeImpl extends AVMNodeImpl implements DirectoryNode
/**
* Retrieves the ChildEntry in this directory with the given name.
* @param name The name to look for.
* @param write Whether the child should be looked up for writing.
* @return The ChildEntry or null if not found.
*/
@SuppressWarnings("unchecked")
protected ChildEntry getChild(String name)
protected ChildEntry getChild(String name, boolean write)
{
Session sess = SuperRepository.GetInstance().getSession();
return (ChildEntry)sess.get(ChildEntryImpl.class, new ChildEntryImpl(name, this, null));
ChildEntry entry = (ChildEntry)sess.get(ChildEntryImpl.class, new ChildEntryImpl(name, this, null),
(write && getIsNew()) ? LockMode.UPGRADE : LockMode.READ);
return entry;
}
/**

View File

@ -381,17 +381,18 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
* @param lPath The Lookup.
* @param name The name we are looking.
* @param version The version in which we are looking.
* @param write Whether this lookup is occurring in a write context.
* @return The child or null if not found.
*/
@SuppressWarnings("unchecked")
public AVMNode lookupChild(Lookup lPath, String name, int version)
public AVMNode lookupChild(Lookup lPath, String name, int version, boolean write)
{
// If the name has been deleted quickly return.
if (getDeleted(name) != null)
{
return null;
}
ChildEntry entry = getChild(name);
ChildEntry entry = getChild(name, write);
if (entry != null)
{
return AVMNodeUnwrapper.Unwrap(entry.getChild());
@ -401,7 +402,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
{
Lookup lookup = SuperRepository.GetInstance().lookupDirectory(-1, getUnderlying(lPath));
DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode();
return dir.lookupChild(lookup, name, -1);
return dir.lookupChild(lookup, name, -1, false);
}
catch (AVMException re)
{
@ -429,7 +430,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
{
return null;
}
ChildEntry entry = getChild(name);
ChildEntry entry = getChild(name, false);
if (entry != null)
{
return entry.getChild().getDescriptor(mine.getPath(),
@ -440,7 +441,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
{
Lookup lookup = SuperRepository.GetInstance().lookupDirectory(-1, mine.getIndirection());
DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode();
AVMNode child = dir.lookupChild(lookup, name, -1);
AVMNode child = dir.lookupChild(lookup, name, -1, false);
if (child == null)
{
return null;
@ -464,7 +465,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
@SuppressWarnings("unchecked")
public void removeChild(String name)
{
ChildEntry entry = getChild(name);
ChildEntry entry = getChild(name, true);
if (entry != null)
{
SuperRepository.GetInstance().getSession().delete(entry);

View File

@ -126,14 +126,15 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory
* @param lPath The lookup path so far.
* @param name The name to lookup.
* @param version The version to look under.
* @param write Whether this is in a write context.
* @return The child or null.
*/
@SuppressWarnings("unchecked")
public AVMNode lookupChild(Lookup lPath, String name, int version)
public AVMNode lookupChild(Lookup lPath, String name, int version, boolean write)
{
// We're doing the hand unrolling of the proxy because
// Hibernate/CGLIB proxies are broken.
ChildEntry entry = getChild(name);
ChildEntry entry = getChild(name, write);
if (entry == null)
{
return null;
@ -153,7 +154,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory
{
throw new AVMBadArgumentException("Path is null.");
}
ChildEntry entry = getChild(name);
ChildEntry entry = getChild(name, false);
if (entry == null)
{
return null;
@ -168,7 +169,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory
@SuppressWarnings("unchecked")
public void removeChild(String name)
{
ChildEntry entry = getChild(name);
ChildEntry entry = getChild(name, true);
if (entry != null)
{
SuperRepository.GetInstance().getSession().delete(entry);

View File

@ -162,7 +162,7 @@ class RepositoryImpl implements Repository, Serializable
Lookup lPath = lookupDirectory(-1, path, true);
// lPath.acquireLocks();
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
if (dir.lookupChild(lPath, name, -1) != null)
if (dir.lookupChild(lPath, name, -1, true) != null)
{
throw new AVMExistsException("Child exists: " + name);
}
@ -195,7 +195,7 @@ class RepositoryImpl implements Repository, Serializable
Lookup lPath = lookupDirectory(-1, dstPath, true);
// lPath.acquireLocks();
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
if (dir.lookupChild(lPath, name, -1) != null)
if (dir.lookupChild(lPath, name, -1, true) != null)
{
throw new AVMExistsException("Child exists: " + name);
}
@ -230,7 +230,7 @@ class RepositoryImpl implements Repository, Serializable
Lookup lPath = lookupDirectory(-1, path, true);
// lPath.acquireLocks();
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
if (dir.lookupChild(lPath, name, -1) != null)
if (dir.lookupChild(lPath, name, -1, true) != null)
{
throw new AVMExistsException("Child exists: " + name);
}
@ -251,7 +251,7 @@ class RepositoryImpl implements Repository, Serializable
Lookup lPath = lookupDirectory(-1, dstPath, true);
// lPath.acquireLocks();
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
if (dir.lookupChild(lPath, name, -1) != null)
if (dir.lookupChild(lPath, name, -1, true) != null)
{
throw new AVMExistsException("Child exists: " + name);
}
@ -372,7 +372,7 @@ class RepositoryImpl implements Repository, Serializable
Lookup lPath = lookupDirectory(-1, path, true);
// lPath.acquireLocks();
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
if (dir.lookupChild(lPath, name, -1) == null)
if (dir.lookupChild(lPath, name, -1, true) == null)
{
throw new AVMNotFoundException("Does not exist: " + name);
}
@ -528,7 +528,7 @@ class RepositoryImpl implements Repository, Serializable
// before the end.
for (int i = 0; i < pathElements.length - 1; i++)
{
AVMNode child = dir.lookupChild(result, pathElements[i], version);
AVMNode child = dir.lookupChild(result, pathElements[i], version, write);
if (child == null)
{
throw new AVMNotFoundException("Not found: " + pathElements[i]);
@ -544,7 +544,7 @@ class RepositoryImpl implements Repository, Serializable
dir = (DirectoryNode)result.getCurrentNode();
}
// Now look up the last element.
AVMNode child = dir.lookupChild(result, pathElements[pathElements.length - 1], version);
AVMNode child = dir.lookupChild(result, pathElements[pathElements.length - 1], version, write);
if (child == null)
{
throw new AVMNotFoundException("Not found: " + pathElements[pathElements.length - 1]);

View File

@ -32,8 +32,8 @@ public class SimultaneousLoadTest extends AVMServiceTestBase
{
try
{
int n = 8;
int m = 1;
int n = 1;
int m = 8;
for (int i = 0; i < n; i++)
{
fService.createDirectory("main:/", "d" + i);
@ -42,7 +42,7 @@ public class SimultaneousLoadTest extends AVMServiceTestBase
Thread [] threads = new Thread[n];
for (int i = 0; i < n; i++)
{
Loader loader = new Loader("/Users/britt/stuff/" + i, "main:/d" + i, m);
Loader loader = new Loader("source", "main:/d" + i, m);
threads[i] = new Thread(loader);
threads[i].start();
}

View File

@ -298,7 +298,7 @@ class SuperRepository
Lookup sPath = srcRepo.lookupDirectory(-1, pathParts[1], true);
// sPath.acquireLocks();
DirectoryNode srcDir = (DirectoryNode)sPath.getCurrentNode();
AVMNode srcNode = srcDir.lookupChild(sPath, srcName, -1);
AVMNode srcNode = srcDir.lookupChild(sPath, srcName, -1, true);
if (srcNode == null)
{
throw new AVMNotFoundException("Not found: " + srcName);
@ -310,7 +310,7 @@ class SuperRepository
Lookup dPath = dstRepo.lookupDirectory(-1, pathParts[1], true);
// dPath.acquireLocks();
DirectoryNode dstDir = (DirectoryNode)dPath.getCurrentNode();
AVMNode dstNode = dstDir.lookupChild(dPath, dstName, -1);
AVMNode dstNode = dstDir.lookupChild(dPath, dstName, -1, true);
if (dstNode != null)
{
throw new AVMExistsException("Node exists: " + dstName);
@ -422,6 +422,7 @@ class SuperRepository
for (String repName : repositories)
{
Repository repo = getRepositoryByName(repName, true);
fSession.get().lock(repo, LockMode.UPGRADE);
// fSession.get().lock(repo, LockMode.UPGRADE);
repo.createSnapshot();
}
@ -434,6 +435,7 @@ class SuperRepository
public void createSnapshot(String repository)
{
Repository repo = getRepositoryByName(repository, true);
fSession.get().lock(repo, LockMode.UPGRADE);
// fSession.get().lock(repo, LockMode.UPGRADE);
repo.createSnapshot();
}
@ -694,12 +696,16 @@ class SuperRepository
private Repository getRepositoryByName(String name, boolean write)
{
Repository rep = (Repository)fSession.get().get(RepositoryImpl.class,
name /* ,
name, LockMode.READ /*,
write ? LockMode.UPGRADE : LockMode.READ*/);
if (rep == null)
{
throw new AVMNotFoundException("Repository not found: " + name);
}
if (write && !rep.getRoot().getIsNew())
{
fSession.get().lock(rep, LockMode.UPGRADE);
}
return rep;
}

View File

@ -88,7 +88,7 @@ public class HibernateTxn
}
*/
sess = fSessionFactory.openSession();
sess.setFlushMode(FlushMode.ALWAYS);
// sess.setFlushMode(FlushMode.ALWAYS);
txn = sess.beginTransaction();
callback.perform(sess);
txn.commit();