mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
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:
@@ -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.
|
||||
|
@@ -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.
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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.
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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.";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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.
|
||||
|
@@ -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())
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user