Changed copy on write to occur during lookup, rather than after lookup.

Much carnage, but it's way faster.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3172 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Britt Park
2006-06-21 13:07:42 +00:00
parent 8cb3db78e3
commit 1318a5204b
14 changed files with 134 additions and 280 deletions

View File

@@ -58,13 +58,6 @@ interface AVMNode
*/
public void setVersionID(int version);
/**
* Perform a COW if required.
* @param lPath The lookup path.
* @return A 'copied' version of this node.
*/
public AVMNode copyOnWrite(Lookup lPath);
/**
* Possibly copy ourselves.
* @param lPath The Lookup for this node.

View File

@@ -148,47 +148,6 @@ abstract class AVMNodeImpl implements AVMNode, Serializable
return (AVMNode)query.uniqueResult();
}
/**
* Perform a copy on write on this node and recursively
* up to the repository root. This is a template method
* which farms out work to possiblyCopy().
* @param lPath The Lookup.
*/
public AVMNode copyOnWrite(Lookup lPath)
{
// Call the subclass's copy on write logic.
AVMNode newMe = possiblyCopy(lPath);
// No copying needed, so short circuit.
if (newMe == null)
{
return this;
}
String myName = lPath.getName();
lPath.upCurrentNode();
Repository repos = lPath.getRepository();
newMe.setVersionID(repos.getNextVersionID());
// Get our parent directory if we have one.
DirectoryNode parent = null;
if (!getIsRoot())
{
parent = (DirectoryNode)lPath.getCurrentNode();
}
if (parent != null)
{
// Recursive invocation.
DirectoryNode newParent =
(DirectoryNode)parent.copyOnWrite(lPath);
newParent.putChild(myName, newMe);
}
else // Null parent means root of repository.
{
repos.setNewRoot((DirectoryNode)newMe);
}
newMe.setRepository(repos);
newMe.setIsNew(true);
return newMe;
}
/**
* Set the owning repository for this.
* @param repo The owning repository.

View File

@@ -92,6 +92,7 @@ public class AVMServiceTest extends AVMServiceTestBase
// assertEquals("foo", listing.get(1).getName());
// /layer/b should contain foo, bar, and baz.
listing = fService.getDirectoryListing(-1, "main:/layer/b");
System.out.println(recursiveList("main", -1, true));
assertEquals(3, listing.size());
// assertEquals("bar", listing.get(0).getName());
// assertEquals("baz", listing.get(1).getName());
@@ -1114,6 +1115,7 @@ public class AVMServiceTest extends AVMServiceTestBase
catch (Exception e)
{
e.printStackTrace(System.err);
fail();
}
}

View File

@@ -50,7 +50,7 @@ public class AVMServiceTestBase extends TestCase
@Override
protected void setUp() throws Exception
{
HibernateHelper.GetSessionFactory().getStatistics().setStatisticsEnabled(true);
// HibernateHelper.GetSessionFactory().getStatistics().setStatisticsEnabled(true);
AVMServiceImpl service = new AVMServiceImpl();
service.setStorage("build/test-results/storage");
service.init(true);
@@ -66,9 +66,9 @@ public class AVMServiceTestBase extends TestCase
{
long now = System.currentTimeMillis();
System.out.println("Timing: " + (now - fStartTime) + "ms");
Statistics stats = HibernateHelper.GetSessionFactory().getStatistics();
stats.logSummary();
stats.clear();
// Statistics stats = HibernateHelper.GetSessionFactory().getStatistics();
// stats.logSummary();
// stats.clear();
HibernateHelper.Reset();
}

View File

@@ -46,7 +46,7 @@ public class AVMStressTest extends AVMServiceTestBase
System.out.println("Load time: " + (System.currentTimeMillis() - start));
List<AVMTester> testers = new ArrayList<AVMTester>();
List<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < 1; i++)
for (int i = 0; i < 8; i++)
{
AVMTester tester
= new AVMTester(400, // create file.
@@ -74,12 +74,12 @@ public class AVMStressTest extends AVMServiceTestBase
thread.start();
}
int exited = 0;
while (exited != 1)
while (exited != 8)
{
try
{
Thread.sleep(2000);
for (int i = 0; i < 1; i++)
for (int i = 0; i < 8; i++)
{
if (threads.get(i) == null)
{

View File

@@ -56,28 +56,11 @@ interface DirectoryNode extends AVMNode
*/
public AVMNodeDescriptor lookupChild(AVMNodeDescriptor mine, String name);
/**
* Add a child node. Fails if child already exists.
* Copy is possible.
* @param name The name to give the child.
* @param child The child to add.
* @param The lookup path.
*/
public boolean addChild(String name, AVMNode child, Lookup lPath);
/**
* Remove a child node. Fails if child does not exist.
* Copy is possible.
* @param name The name of the child to remove.
* @param lPath The lookup path.
*/
public boolean removeChild(String name, Lookup lPath);
/**
* Remove a child directly. No copy is possible.
* @param name The name of the child to remove.
*/
public void rawRemoveChild(String name);
public void removeChild(String name);
/**
* Get a directory listing.

View File

@@ -282,44 +282,6 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
}
}
/**
* Add a child to this directory and possibly COW.
* @param name The name of the child to add.
* @param child The child to add.
* @param lPath The Lookup.
* @return Whether the child was successfully added.
*/
public boolean addChild(String name, AVMNode child, Lookup lPath)
{
if (getChild(name) != null)
{
return false;
}
if (getDeleted(name) == null)
{
try
{
Lookup lookup = SuperRepository.GetInstance().lookupDirectory(-1, getUnderlying(lPath));
DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode();
if (dir.lookupChild(lookup, name, -1) != null)
{
return false;
}
}
catch (AVMException re)
{
if (re instanceof AVMCycleException)
{
throw re;
}
// Do nothing.
}
}
DirectoryNode toModify = (DirectoryNode)copyOnWrite(lPath);
toModify.putChild(name, child);
child.setRepository(lPath.getRepository());
return true;
}
/**
* Does this node directly contain the indicated node.
@@ -506,7 +468,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
* @param name The name of the child to remove.
*/
@SuppressWarnings("unchecked")
public void rawRemoveChild(String name)
public void removeChild(String name)
{
ChildEntry entry = getChild(name);
if (entry != null)
@@ -518,48 +480,6 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
SuperRepository.GetInstance().getSession().save(dc);
}
/**
* Remove a child by name. Possibly COW.
* @param name The name of the child to remove.
* @param lPath The Lookup.
* @return Whether the child was successfully removed.
*/
@SuppressWarnings("unchecked")
public boolean removeChild(String name, Lookup lPath)
{
// Can't delete something that is already deleted.
if (getDeleted(name) != null)
{
return false;
}
ChildEntry entry = getChild(name);
if (entry == null)
{
// See if the name is seen via indirection.
try
{
Lookup lookup = SuperRepository.GetInstance().lookupDirectory(-1, getUnderlying(lPath));
DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode();
if (dir.lookupChild(lookup, name, -1) == null)
{
return false;
}
}
catch (AVMException re)
{
if (re instanceof AVMCycleException)
{
throw re;
}
return false;
}
}
LayeredDirectoryNode toModify =
(LayeredDirectoryNode)copyOnWrite(lPath);
toModify.rawRemoveChild(name);
return true;
}
/**
* Get the type of this node.
* @return The type of this node.
@@ -596,8 +516,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
public void turnPrimary(Lookup lPath)
{
String path = lPath.getCurrentIndirection();
LayeredDirectoryNode toModify = (LayeredDirectoryNode)copyOnWrite(lPath);
toModify.rawSetPrimary(path);
rawSetPrimary(path);
}
/**
@@ -606,8 +525,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
*/
public void retarget(Lookup lPath, String target)
{
LayeredDirectoryNode toModify = (LayeredDirectoryNode)copyOnWrite(lPath);
toModify.rawSetPrimary(target);
rawSetPrimary(target);
}
/**
@@ -617,8 +535,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
*/
public void uncover(Lookup lPath, String name)
{
LayeredDirectoryNodeImpl toModify = (LayeredDirectoryNodeImpl)copyOnWrite(lPath);
DeletedChild dc = toModify.getDeleted(name);
DeletedChild dc = getDeleted(name);
if (dc != null)
{
SuperRepository.GetInstance().getSession().delete(dc);

View File

@@ -96,8 +96,10 @@ class Lookup
* Add a new node to the lookup.
* @param node The node to add.
* @param name The name of the node in the path.
* @param write Whether this is in the context of
* a write operation.
*/
public void add(AVMNode node, String name)
public void add(AVMNode node, String name, boolean write)
{
LookupComponent comp = new LookupComponent();
comp.setName(name);
@@ -109,6 +111,8 @@ class Lookup
}
else
{
// TODO The isDirectlyContained should be eliminated in favor of
// a cumulative state.
if (fPosition >= 0 && (!((DirectoryNode)fComponents.get(fPosition).getNode()).directlyContains(node) ||
!isDirectlyContained()))
{
@@ -127,20 +131,7 @@ class Lookup
}
else
{
String parentIndirection = fComponents.get(fPosition).getIndirection();
if (parentIndirection == null)
{
System.out.println("Oink!");
}
if (parentIndirection.endsWith("/")) // This currently is impossible because
// root dirs are always plain.
{
comp.setIndirection(parentIndirection + name);
}
else
{
comp.setIndirection(parentIndirection + "/" + name);
}
comp.setIndirection(computeIndirection(name));
}
fLayeredYet = true;
// Record the first layer seen.
@@ -151,10 +142,58 @@ class Lookup
}
fLowestLayerIndex = fPosition + 1;
}
// In a write context a plain directory contained in a layer will
// be copied so we will need to compute an indirection path.
else if (fLayeredYet && write)
{
comp.setIndirection(computeIndirection(name));
}
comp.setLowestLayerIndex(fLowestLayerIndex);
comp.setLayered(fLayeredYet);
fComponents.add(comp);
fPosition++;
// If we are in a write context do copy on write.
if (write)
{
// Possibly copy.
node = node.possiblyCopy(this);
if (node == null)
{
return;
}
// Node was copied.
fComponents.get(fPosition).setNode(node);
if (fPosition == 0)
{
// Inform the repository of a new root.
fRepository.setNewRoot((DirectoryNode)node);
return;
}
// Not the root. Check if we are the top layer and insert this into it's parent.
if (fPosition == fTopLayerIndex)
{
fTopLayer = (LayeredDirectoryNode)node;
}
((DirectoryNode)fComponents.get(fPosition - 1).getNode()).putChild(name, node);
}
}
/**
* A helper for keeping track of indirection.
* @param name The name of the being added node.
* @return The indirection for the being added node.
*/
private String computeIndirection(String name)
{
String parentIndirection = fComponents.get(fPosition).getIndirection();
if (parentIndirection.endsWith("/"))
{
return parentIndirection + name;
}
else
{
return parentIndirection + "/" + name;
}
}
/**

View File

@@ -72,27 +72,6 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory
}
}
/**
* Add a child to this directory, possibly doing a copy.
* @param name The name of the child.
* @param child The child node.
* @param lPath The lookup path to this directory.
* @return Success or failure.
*/
public boolean addChild(String name, AVMNode child, Lookup lPath)
{
// No, if a child with the given name exists. Note that uniqueness
// of names is built into the AVM, as opposed to being configurable.
if (getChild(name) != null)
{
return false;
}
DirectoryNode toModify = (DirectoryNode)copyOnWrite(lPath);
toModify.putChild(name, child);
child.setRepository(lPath.getRepository());
return true;
}
/**
* Does this directory directly contain the given node.
* @param node The node to check.
@@ -187,7 +166,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory
* @param name The name of the child to remove.
*/
@SuppressWarnings("unchecked")
public void rawRemoveChild(String name)
public void removeChild(String name)
{
ChildEntry entry = getChild(name);
if (entry != null)
@@ -196,24 +175,6 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory
}
}
/**
* Remove a child. Possibly copy.
* @param name The name of the child to remove.
* @param lPath The lookup path.
* @return Success or failure.
*/
public boolean removeChild(String name, Lookup lPath)
{
// Can't remove it if it's not there.
if (getChild(name) == null)
{
return false;
}
DirectoryNode toModify = (DirectoryNode)copyOnWrite(lPath);
toModify.rawRemoveChild(name);
return true;
}
/**
* Put a new child node into this directory. No copy.
* @param name The name of the child.
@@ -294,9 +255,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory
*/
public void turnPrimary(Lookup lPath)
{
LayeredDirectoryNode toModify = (LayeredDirectoryNode)copyOnWrite(lPath);
Lookup lookup = SuperRepository.GetInstance().lookup(-1, lPath.getRepresentedPath());
toModify.rawSetPrimary(lookup.getCurrentIndirection());
assert false : "Should never happen.";
}
/**
@@ -306,8 +265,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory
*/
public void retarget(Lookup lPath, String target)
{
LayeredDirectoryNode toModify = (LayeredDirectoryNode)copyOnWrite(lPath);
toModify.rawSetPrimary(target);
assert false : "Should never happen.";
}
/**

View File

@@ -156,17 +156,19 @@ interface Repository
* Lookup a node.
* @param version The version to look under.
* @param path The path to the node.
* @param write Whether this is in a write context.
* @return A Lookup object.
*/
public Lookup lookup(int version, String path);
public Lookup lookup(int version, String path, boolean write);
/**
* Lookup a directory.
* @param version The version to look under.
* @param path The path to the directory.
* @param write Whether this is in a write context.
* @return A Lookup object.
*/
public Lookup lookupDirectory(int version, String path);
public Lookup lookupDirectory(int version, String path, boolean write);
/**
* For a layered node, get its indirection.

View File

@@ -147,7 +147,7 @@ class RepositoryImpl implements Repository, Serializable
*/
public void createDirectory(String path, String name)
{
Lookup lPath = lookupDirectory(-1, path);
Lookup lPath = lookupDirectory(-1, path, true);
// lPath.acquireLocks();
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
if (dir.lookupChild(lPath, name, -1) != null)
@@ -168,7 +168,7 @@ class RepositoryImpl implements Repository, Serializable
newDir = new PlainDirectoryNodeImpl(this);
}
newDir.setVersionID(getNextVersionID());
dir.addChild(name, newDir, lPath);
dir.putChild(name, newDir);
}
/**
@@ -180,7 +180,7 @@ class RepositoryImpl implements Repository, Serializable
public void createLayeredDirectory(String srcPath, String dstPath,
String name)
{
Lookup lPath = lookupDirectory(-1, dstPath);
Lookup lPath = lookupDirectory(-1, dstPath, true);
// lPath.acquireLocks();
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
if (dir.lookupChild(lPath, name, -1) != null)
@@ -202,7 +202,7 @@ class RepositoryImpl implements Repository, Serializable
// Otherwise we issue a brand new layer id.
newDir.setLayerID(fSuper.issueLayerID());
}
dir.addChild(name, newDir, lPath);
dir.putChild(name, newDir);
newDir.setVersionID(getNextVersionID());
}
@@ -215,7 +215,7 @@ class RepositoryImpl implements Repository, Serializable
*/
public OutputStream createFile(String path, String name)
{
Lookup lPath = lookupDirectory(-1, path);
Lookup lPath = lookupDirectory(-1, path, true);
// lPath.acquireLocks();
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
if (dir.lookupChild(lPath, name, -1) != null)
@@ -224,7 +224,7 @@ class RepositoryImpl implements Repository, Serializable
}
PlainFileNodeImpl file = new PlainFileNodeImpl(this);
file.setVersionID(getNextVersionID());
dir.addChild(name, file, lPath);
dir.putChild(name, file);
return file.getContentForWrite().getOutputStream();
}
@@ -236,7 +236,7 @@ class RepositoryImpl implements Repository, Serializable
*/
public void createLayeredFile(String srcPath, String dstPath, String name)
{
Lookup lPath = lookupDirectory(-1, dstPath);
Lookup lPath = lookupDirectory(-1, dstPath, true);
// lPath.acquireLocks();
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
if (dir.lookupChild(lPath, name, -1) != null)
@@ -246,7 +246,7 @@ class RepositoryImpl implements Repository, Serializable
// TODO Reexamine decision to not check validity of srcPath.
LayeredFileNodeImpl newFile =
new LayeredFileNodeImpl(srcPath, this);
dir.addChild(name, newFile, lPath);
dir.putChild(name, newFile);
newFile.setVersionID(getNextVersionID());
}
@@ -258,7 +258,7 @@ class RepositoryImpl implements Repository, Serializable
*/
public InputStream getInputStream(int version, String path)
{
Lookup lPath = lookup(version, path);
Lookup lPath = lookup(version, path, false);
AVMNode node = lPath.getCurrentNode();
if (node.getType() != AVMNodeType.PLAIN_FILE &&
node.getType() != AVMNodeType.LAYERED_FILE)
@@ -278,7 +278,7 @@ class RepositoryImpl implements Repository, Serializable
*/
public Map<String, AVMNodeDescriptor> getListing(int version, String path)
{
Lookup lPath = lookupDirectory(version, path);
Lookup lPath = lookupDirectory(version, path, false);
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
Map<String, AVMNode> listing = dir.getListing(lPath);
Map<String, AVMNodeDescriptor> results = new TreeMap<String, AVMNodeDescriptor>();
@@ -298,7 +298,7 @@ class RepositoryImpl implements Repository, Serializable
*/
public OutputStream getOutputStream(String path)
{
Lookup lPath = lookup(-1, path);
Lookup lPath = lookup(-1, path, true);
// lPath.acquireLocks();
AVMNode node = lPath.getCurrentNode();
if (node.getType() != AVMNodeType.PLAIN_FILE &&
@@ -307,9 +307,8 @@ class RepositoryImpl implements Repository, Serializable
throw new AVMWrongTypeException("Not a file: " + path);
}
FileNode file = (FileNode)node;
file = (FileNode)file.copyOnWrite(lPath);
FileContent content = file.getContentForWrite();
return content.getOutputStream(); // TODO Do we really need fSuper?
return content.getOutputStream();
}
/**
@@ -326,7 +325,7 @@ class RepositoryImpl implements Repository, Serializable
{
throw new AVMException("Access denied: " + path);
}
Lookup lPath = lookup(version, path);
Lookup lPath = lookup(version, path, write);
// if (write)
// {
// lPath.acquireLocks();
@@ -341,7 +340,6 @@ class RepositoryImpl implements Repository, Serializable
FileContent content = null;
if (write)
{
file = (FileNode)file.copyOnWrite(lPath);
content = file.getContentForWrite();
}
else
@@ -359,14 +357,14 @@ class RepositoryImpl implements Repository, Serializable
public void removeNode(String path, String name)
{
// TODO Are we double checking for existence?
Lookup lPath = lookupDirectory(-1, path);
Lookup lPath = lookupDirectory(-1, path, true);
// lPath.acquireLocks();
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
if (dir.lookupChild(lPath, name, -1) == null)
{
throw new AVMNotFoundException("Does not exist: " + name);
}
dir.removeChild(name, lPath);
dir.removeChild(name);
}
/**
@@ -376,7 +374,7 @@ class RepositoryImpl implements Repository, Serializable
*/
public void uncover(String dirPath, String name)
{
Lookup lPath = lookup(-1, dirPath);
Lookup lPath = lookup(-1, dirPath, true);
// lPath.acquireLocks();
AVMNode node = lPath.getCurrentNode();
if (node.getType() != AVMNodeType.LAYERED_DIRECTORY)
@@ -475,9 +473,10 @@ class RepositoryImpl implements Repository, Serializable
* Lookup up a path.
* @param version The version to look in.
* @param path The path to look up.
* @param write Whether this is in the context of a write.
* @return A Lookup object.
*/
public Lookup lookup(int version, String path)
public Lookup lookup(int version, String path, boolean write)
{
// Make up a Lookup to hold the results.
Lookup result = new Lookup(this, fName);
@@ -507,7 +506,8 @@ class RepositoryImpl implements Repository, Serializable
}
// fSuper.getSession().lock(dir, LockMode.READ);
// Add an entry for the root.
result.add(dir, "");
result.add(dir, "", write);
dir = (DirectoryNode)result.getCurrentNode();
if (pathElements.length == 0)
{
return result;
@@ -527,9 +527,9 @@ class RepositoryImpl implements Repository, Serializable
{
throw new AVMWrongTypeException("Not a directory: " + pathElements[i]);
}
dir = (DirectoryNode)child;
// fSuper.getSession().lock(dir, LockMode.READ);
result.add(dir, pathElements[i]);
result.add(child, pathElements[i], write);
dir = (DirectoryNode)result.getCurrentNode();
}
// Now look up the last element.
AVMNode child = dir.lookupChild(result, pathElements[pathElements.length - 1], version);
@@ -538,7 +538,7 @@ class RepositoryImpl implements Repository, Serializable
throw new AVMNotFoundException("Not found: " + pathElements[pathElements.length - 1]);
}
// fSuper.getSession().lock(child, LockMode.READ);
result.add(child, pathElements[pathElements.length - 1]);
result.add(child, pathElements[pathElements.length - 1], write);
return result;
}
@@ -573,13 +573,14 @@ class RepositoryImpl implements Repository, Serializable
* Lookup a node and insist that it is a directory.
* @param version The version to look under.
* @param path The path to the directory.
* @param write Whether this is in a write context.
* @return A Lookup object.
*/
public Lookup lookupDirectory(int version, String path)
public Lookup lookupDirectory(int version, String path, boolean write)
{
// Just do a regular lookup and assert that the last element
// is a directory.
Lookup lPath = lookup(version, path);
Lookup lPath = lookup(version, path, write);
if (lPath.getCurrentNode().getType() != AVMNodeType.PLAIN_DIRECTORY &&
lPath.getCurrentNode().getType() != AVMNodeType.LAYERED_DIRECTORY)
{
@@ -596,7 +597,7 @@ class RepositoryImpl implements Repository, Serializable
*/
public String getIndirectionPath(int version, String path)
{
Lookup lPath = lookup(version, path);
Lookup lPath = lookup(version, path, false);
AVMNode node = lPath.getCurrentNode();
if (node.getType() == AVMNodeType.LAYERED_DIRECTORY)
{
@@ -615,7 +616,7 @@ class RepositoryImpl implements Repository, Serializable
*/
public void makePrimary(String path)
{
Lookup lPath = lookupDirectory(-1, path);
Lookup lPath = lookupDirectory(-1, path, true);
// lPath.acquireLocks();
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
if (!lPath.isLayered())
@@ -632,7 +633,7 @@ class RepositoryImpl implements Repository, Serializable
*/
public void retargetLayeredDirectory(String path, String target)
{
Lookup lPath = lookupDirectory(-1, path);
Lookup lPath = lookupDirectory(-1, path, true);
// lPath.acquireLocks();
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
if (!lPath.isLayered())

View File

@@ -32,7 +32,7 @@ public class SimultaneousLoadTest extends AVMServiceTestBase
{
try
{
int n = 16;
int n = 4;
for (int i = 0; i < n; i++)
{
fService.createDirectory("main:/", "d" + i);

View File

@@ -201,13 +201,13 @@ class SuperRepository
String [] pathParts = SplitPath(srcPath);
Repository srcRepo = getRepositoryByName(pathParts[0], false);
// fSession.get().lock(srcRepo, LockMode.READ);
Lookup sPath = srcRepo.lookup(version, pathParts[1]);
Lookup sPath = srcRepo.lookup(version, pathParts[1], false);
// Lookup the destination directory.
fLookupCount.set(1);
pathParts = SplitPath(dstPath);
Repository dstRepo = getRepositoryByName(pathParts[0], true);
// fSession.get().lock(dstRepo, LockMode.UPGRADE);
Lookup dPath = dstRepo.lookupDirectory(-1, pathParts[1]);
Lookup dPath = dstRepo.lookupDirectory(-1, pathParts[1], true);
// dPath.acquireLocks();
DirectoryNode dirNode = (DirectoryNode)dPath.getCurrentNode();
AVMNode srcNode = sPath.getCurrentNode();
@@ -235,7 +235,7 @@ class SuperRepository
}
dstNode.setVersionID(dstRepo.getNextVersionID());
dstNode.setAncestor(srcNode);
dirNode.addChild(name, dstNode, dPath);
dirNode.putChild(name, dstNode);
}
/**
@@ -287,7 +287,7 @@ class SuperRepository
String [] pathParts = SplitPath(srcPath);
Repository srcRepo = getRepositoryByName(pathParts[0], true);
// fSession.get().lock(srcRepo, LockMode.UPGRADE);
Lookup sPath = srcRepo.lookupDirectory(-1, pathParts[1]);
Lookup sPath = srcRepo.lookupDirectory(-1, pathParts[1], true);
// sPath.acquireLocks();
DirectoryNode srcDir = (DirectoryNode)sPath.getCurrentNode();
AVMNode srcNode = srcDir.lookupChild(sPath, srcName, -1);
@@ -299,7 +299,7 @@ class SuperRepository
pathParts = SplitPath(dstPath);
Repository dstRepo = getRepositoryByName(pathParts[0], true);
// fSession.get().lock(dstRepo, LockMode.UPGRADE);
Lookup dPath = dstRepo.lookupDirectory(-1, pathParts[1]);
Lookup dPath = dstRepo.lookupDirectory(-1, pathParts[1], true);
// dPath.acquireLocks();
DirectoryNode dstDir = (DirectoryNode)dPath.getCurrentNode();
AVMNode dstNode = dstDir.lookupChild(dPath, dstName, -1);
@@ -385,14 +385,9 @@ class SuperRepository
{
dstNode = new PlainFileNodeImpl((PlainFileNode)srcNode, dstRepo);
}
srcDir.removeChild(srcName, sPath);
fLookupCount.set(1);
pathParts = SplitPath(dstPath);
dPath = dstRepo.lookup(-1, pathParts[1]);
// dPath.acquireLocks();
dstDir = (DirectoryNode)dPath.getCurrentNode();
srcDir.removeChild(srcName);
dstNode.setVersionID(dstRepo.getNextVersionID());
dstDir.addChild(dstName, dstNode, dPath);
dstDir.putChild(dstName, dstNode);
dstNode.setAncestor(srcNode);
}
@@ -674,8 +669,8 @@ class SuperRepository
private Repository getRepositoryByName(String name, boolean write)
{
return (Repository)fSession.get().get(RepositoryImpl.class,
name,
write ? LockMode.UPGRADE : LockMode.READ);
name /* ,
write ? LockMode.UPGRADE : LockMode.READ */);
}
/**
@@ -711,7 +706,7 @@ class SuperRepository
String [] pathParts = SplitPath(path);
Repository rep = getRepositoryByName(pathParts[0], false);
// fSession.get().lock(rep, LockMode.READ);
return rep.lookup(version, pathParts[1]);
return rep.lookup(version, pathParts[1], false);
}
/**
@@ -746,14 +741,14 @@ class SuperRepository
public Lookup lookupDirectory(int version, String path)
{
fLookupCount.set(fLookupCount.get() + 1);
if (fLookupCount.get() > 10)
if (fLookupCount.get() > 50)
{
throw new AVMCycleException("Cycle in lookup.");
}
String [] pathParts = SplitPath(path);
Repository rep = getRepositoryByName(pathParts[0], false);
// fSession.get().lock(rep, LockMode.READ);
return rep.lookupDirectory(version, pathParts[1]);
return rep.lookupDirectory(version, pathParts[1], false);
}
/**

View File

@@ -27,6 +27,7 @@ import org.hibernate.SessionFactory;
import org.hibernate.StaleStateException;
import org.hibernate.Transaction;
import org.hibernate.exception.GenericJDBCException;
import org.hibernate.exception.LockAcquisitionException;
/**
* Helper for DAOs.
@@ -106,26 +107,30 @@ public class HibernateTxn
}
// If we've lost a race or we've deadlocked, retry.
if (t instanceof StaleStateException ||
t instanceof GenericJDBCException)
t instanceof GenericJDBCException ||
t instanceof LockAcquisitionException)
{
if (t instanceof StaleStateException)
{
System.err.println("Lost Race");
continue;
}
System.err.println("Deadlock");
try
else
{
long interval;
synchronized (fRandom)
System.err.println("Deadlock");
try
{
interval = fRandom.nextInt(1000);
long interval;
synchronized (fRandom)
{
interval = fRandom.nextInt(1000);
}
Thread.sleep(interval);
continue;
}
catch (InterruptedException ie)
{
// Do nothing.
}
Thread.sleep(interval);
}
catch (InterruptedException ie)
{
// Do nothing.
}
continue;
}