A real, if brute force, fix for cycle detection during lookups.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@4106 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Britt Park
2006-10-12 18:10:17 +00:00
parent b6514af611
commit 0774219b75
2 changed files with 714 additions and 380 deletions

View File

@@ -108,14 +108,20 @@ public class AVMRepository
public OutputStream createFile(String path, String name)
{
fLookupCount.set(1);
try
{
String[] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
{
if (store == null) {
throw new AVMNotFoundException("Store not found.");
}
return store.createFile(pathParts[1], name);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Create a file with the given File as content.
@@ -126,6 +132,8 @@ public class AVMRepository
public void createFile(String path, String name, File data)
{
fLookupCount.set(1);
try
{
String[] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -134,6 +142,11 @@ public class AVMRepository
}
store.createFile(pathParts[1], name, data);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Create a new directory.
@@ -143,6 +156,8 @@ public class AVMRepository
public void createDirectory(String path, String name)
{
fLookupCount.set(1);
try
{
String[] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -151,6 +166,11 @@ public class AVMRepository
}
store.createDirectory(pathParts[1], name);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Create a new directory. This assumes that the parent is already
@@ -207,6 +227,8 @@ public class AVMRepository
throw new AVMCycleException("Cycle would be created.");
}
fLookupCount.set(1);
try
{
String[] pathParts = SplitPath(dstPath);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -215,6 +237,11 @@ public class AVMRepository
}
store.createLayeredDirectory(srcPath, pathParts[1], name);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Create a new layered file.
@@ -225,6 +252,8 @@ public class AVMRepository
public void createLayeredFile(String srcPath, String dstPath, String name)
{
fLookupCount.set(1);
try
{
String[] pathParts = SplitPath(dstPath);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -233,6 +262,11 @@ public class AVMRepository
}
store.createLayeredFile(srcPath, pathParts[1], name);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Create a new AVMStore.
@@ -266,7 +300,11 @@ public class AVMRepository
}
// Lookup the src node.
fLookupCount.set(1);
String [] pathParts = SplitPath(srcPath);
String [] pathParts;
Lookup sPath;
try
{
pathParts = SplitPath(srcPath);
AVMStore srcRepo = getAVMStoreByName(pathParts[0]);
if (srcRepo == null)
{
@@ -276,13 +314,20 @@ public class AVMRepository
{
version = srcRepo.createSnapshot();
}
Lookup sPath = srcRepo.lookup(version, pathParts[1], false, false);
sPath = srcRepo.lookup(version, pathParts[1], false, false);
if (sPath == null)
{
throw new AVMNotFoundException("Path not found.");
}
}
finally
{
fLookupCount.set(null);
}
// Lookup the destination directory.
fLookupCount.set(1);
try
{
pathParts = SplitPath(dstPath);
AVMStore dstRepo = getAVMStoreByName(pathParts[0]);
if (dstRepo == null)
@@ -323,6 +368,11 @@ public class AVMRepository
dirNode.putChild(name, dstNode);
dirNode.updateModTime();
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get an output stream to a file.
@@ -332,6 +382,8 @@ public class AVMRepository
public OutputStream getOutputStream(String path)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -340,6 +392,11 @@ public class AVMRepository
}
return store.getOutputStream(pathParts[1]);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Rename a node.
@@ -357,24 +414,37 @@ public class AVMRepository
throw new AVMCycleException("Cyclic rename.");
}
fLookupCount.set(1);
String [] pathParts = SplitPath(srcPath);
String [] pathParts;
Lookup sPath;
DirectoryNode srcDir;
AVMNode srcNode;
try
{
pathParts = SplitPath(srcPath);
AVMStore srcRepo = getAVMStoreByName(pathParts[0]);
if (srcRepo == null)
{
throw new AVMNotFoundException("Store not found.");
}
Lookup sPath = srcRepo.lookupDirectory(-1, pathParts[1], true);
sPath = srcRepo.lookupDirectory(-1, pathParts[1], true);
if (sPath == null)
{
throw new AVMNotFoundException("Path not found.");
}
DirectoryNode srcDir = (DirectoryNode)sPath.getCurrentNode();
AVMNode srcNode = srcDir.lookupChild(sPath, srcName, false);
srcDir = (DirectoryNode)sPath.getCurrentNode();
srcNode = srcDir.lookupChild(sPath, srcName, false);
if (srcNode == null)
{
throw new AVMNotFoundException("Not found: " + srcName);
}
}
finally
{
fLookupCount.set(null);
}
fLookupCount.set(1);
try
{
pathParts = SplitPath(dstPath);
AVMStore dstRepo = getAVMStoreByName(pathParts[0]);
if (dstRepo == null)
@@ -477,6 +547,11 @@ public class AVMRepository
dstDir.updateModTime();
dstNode.setAncestor(srcNode);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Uncover a deleted name in a layered directory.
@@ -486,6 +561,8 @@ public class AVMRepository
public void uncover(String dirPath, String name)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(dirPath);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -494,6 +571,11 @@ public class AVMRepository
}
store.uncover(pathParts[1], name);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Snapshot the given repositories.
@@ -538,6 +620,8 @@ public class AVMRepository
public void remove(String path, String name)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -546,6 +630,11 @@ public class AVMRepository
}
store.removeNode(pathParts[1], name);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get rid of all content that lives only in the given AVMStore.
@@ -603,6 +692,8 @@ public class AVMRepository
public InputStream getInputStream(int version, String path)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -611,6 +702,11 @@ public class AVMRepository
}
return store.getInputStream(version, pathParts[1]);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get a listing of a directory.
@@ -623,6 +719,8 @@ public class AVMRepository
boolean includeDeleted)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -631,6 +729,11 @@ public class AVMRepository
}
return store.getListing(version, pathParts[1], includeDeleted);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get the list of nodes directly contained in a directory.
@@ -642,6 +745,8 @@ public class AVMRepository
boolean includeDeleted)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -650,6 +755,11 @@ public class AVMRepository
}
return store.getListingDirect(version, pathParts[1], includeDeleted);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get the list of nodes directly contained in a directory.
@@ -685,6 +795,8 @@ public class AVMRepository
public SortedMap<String, AVMNodeDescriptor> getListing(AVMNodeDescriptor dir, boolean includeDeleted)
{
fLookupCount.set(1);
try
{
AVMNode node = AVMDAOs.Instance().fAVMNodeDAO.getByID(dir.getId());
if (node == null)
{
@@ -698,6 +810,11 @@ public class AVMRepository
DirectoryNode dirNode = (DirectoryNode)node;
return dirNode.getListing(dir, includeDeleted);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get the names of deleted nodes in a directory.
@@ -708,6 +825,8 @@ public class AVMRepository
public List<String> getDeleted(int version, String path)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -716,6 +835,11 @@ public class AVMRepository
}
return store.getDeleted(version, pathParts[1]);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get descriptors of all AVMStores.
@@ -808,6 +932,8 @@ public class AVMRepository
public String getIndirectionPath(int version, String path)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -816,6 +942,11 @@ public class AVMRepository
}
return store.getIndirectionPath(version, pathParts[1]);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get the next version id for the given AVMStore.
@@ -879,10 +1010,10 @@ public class AVMRepository
{
fLookupCount.set(count + 1);
}
// if (fLookupCount.get() > 50)
// {
// throw new AVMCycleException("Cycle in lookup.");
// }
if (fLookupCount.get() > 50)
{
throw new AVMCycleException("Cycle in lookup.");
}
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -909,7 +1040,9 @@ public class AVMRepository
*/
public AVMNodeDescriptor lookup(AVMNodeDescriptor dir, String name, boolean includeDeleted)
{
fLookupCount.set(0);
fLookupCount.set(1);
try
{
AVMNode node = AVMDAOs.Instance().fAVMNodeDAO.getByID(dir.getId());
if (node == null)
{
@@ -923,6 +1056,11 @@ public class AVMRepository
DirectoryNode dirNode = (DirectoryNode)node;
return dirNode.lookupChild(dir, name, includeDeleted);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get all the paths to a particular node.
@@ -1105,6 +1243,8 @@ public class AVMRepository
public LayeringDescriptor getLayeringInfo(int version, String path)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1120,6 +1260,11 @@ public class AVMRepository
lookup.getAVMStore().getDescriptor(),
lookup.getFinalStore().getDescriptor());
}
finally
{
fLookupCount.set(null);
}
}
/**
* Lookup a directory specifically.
@@ -1129,10 +1274,11 @@ public class AVMRepository
*/
public Lookup lookupDirectory(int version, String path)
{
// if (fLookupCount.get() > 50)
// {
// throw new AVMCycleException("Cycle in lookup.");
// }
fLookupCount.set(fLookupCount.get() + 1);
if (fLookupCount.get() > 50)
{
throw new AVMCycleException("Cycle in lookup.");
}
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1164,6 +1310,8 @@ public class AVMRepository
public void makePrimary(String path)
{
fLookupCount.set(1);
try
{
String[] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1172,6 +1320,11 @@ public class AVMRepository
}
store.makePrimary(pathParts[1]);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Change what a layered directory points at.
@@ -1181,6 +1334,8 @@ public class AVMRepository
public void retargetLayeredDirectory(String path, String target)
{
fLookupCount.set(1);
try
{
String[] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1189,6 +1344,11 @@ public class AVMRepository
}
store.retargetLayeredDirectory(pathParts[1], target);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get the history chain for a node.
@@ -1229,6 +1389,8 @@ public class AVMRepository
public void setOpacity(String path, boolean opacity)
{
fLookupCount.set(1);
try
{
String[] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1237,6 +1399,11 @@ public class AVMRepository
}
store.setOpacity(pathParts[1], opacity);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Set a property on a node.
@@ -1247,6 +1414,8 @@ public class AVMRepository
public void setNodeProperty(String path, QName name, PropertyValue value)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1255,6 +1424,11 @@ public class AVMRepository
}
store.setNodeProperty(pathParts[1], name, value);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Set a collection of properties at once.
@@ -1264,6 +1438,8 @@ public class AVMRepository
public void setNodeProperties(String path, Map<QName, PropertyValue> properties)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1272,6 +1448,11 @@ public class AVMRepository
}
store.setNodeProperties(pathParts[1], properties);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get a property by name for a node.
@@ -1283,6 +1464,8 @@ public class AVMRepository
public PropertyValue getNodeProperty(int version, String path, QName name)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1291,6 +1474,11 @@ public class AVMRepository
}
return store.getNodeProperty(version, pathParts[1], name);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get a Map of all the properties of a node.
@@ -1301,6 +1489,8 @@ public class AVMRepository
public Map<QName, PropertyValue> getNodeProperties(int version, String path)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1309,6 +1499,11 @@ public class AVMRepository
}
return store.getNodeProperties(version, pathParts[1]);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Delete a single property from a node.
@@ -1318,6 +1513,8 @@ public class AVMRepository
public void deleteNodeProperty(String path, QName name)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1326,6 +1523,11 @@ public class AVMRepository
}
store.deleteNodeProperty(pathParts[1], name);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Delete all properties on a node.
@@ -1334,6 +1536,8 @@ public class AVMRepository
public void deleteNodeProperties(String path)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1342,6 +1546,11 @@ public class AVMRepository
}
store.deleteNodeProperties(pathParts[1]);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Set a property on a store. Overwrites if property exists.
@@ -1533,10 +1742,17 @@ public class AVMRepository
public ContentData getContentDataForRead(int version, String path)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
return store.getContentDataForRead(version, pathParts[1]);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get the ContentData for a file for writing.
@@ -1546,6 +1762,8 @@ public class AVMRepository
public ContentData getContentDataForWrite(String path)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1554,6 +1772,11 @@ public class AVMRepository
}
return store.getContentDataForWrite(pathParts[1]);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Set the ContentData on a file.
@@ -1563,6 +1786,8 @@ public class AVMRepository
public void setContentData(String path, ContentData data)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1571,6 +1796,11 @@ public class AVMRepository
}
store.setContentData(pathParts[1], data);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get the single instance of AVMRepository.
@@ -1584,6 +1814,8 @@ public class AVMRepository
public void setMetaDataFrom(String path, AVMNodeDescriptor from)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1597,6 +1829,11 @@ public class AVMRepository
}
store.setMetaDataFrom(pathParts[1], fromNode);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Add an aspect to an AVM Node.
@@ -1606,6 +1843,8 @@ public class AVMRepository
public void addAspect(String path, QName aspectName)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1614,6 +1853,11 @@ public class AVMRepository
}
store.addAspect(pathParts[1], aspectName);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get all the aspects on an AVM node.
@@ -1624,6 +1868,8 @@ public class AVMRepository
public List<QName> getAspects(int version, String path)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1632,6 +1878,11 @@ public class AVMRepository
}
return store.getAspects(version, pathParts[1]);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Remove an aspect and all associated properties from a node.
@@ -1641,6 +1892,8 @@ public class AVMRepository
public void removeAspect(String path, QName aspectName)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1649,6 +1902,11 @@ public class AVMRepository
}
store.removeAspect(pathParts[1], aspectName);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Does a node have a particular aspect.
@@ -1660,6 +1918,8 @@ public class AVMRepository
public boolean hasAspect(int version, String path, QName aspectName)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1668,6 +1928,11 @@ public class AVMRepository
}
return store.hasAspect(version, pathParts[1], aspectName);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Set the ACL on a node.
@@ -1677,6 +1942,8 @@ public class AVMRepository
public void setACL(String path, DbAccessControlList acl)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1685,6 +1952,11 @@ public class AVMRepository
}
store.setACL(pathParts[1], acl);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Get the ACL on a node.
@@ -1695,6 +1967,8 @@ public class AVMRepository
public DbAccessControlList getACL(int version, String path)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1703,6 +1977,11 @@ public class AVMRepository
}
return store.getACL(version, pathParts[1]);
}
finally
{
fLookupCount.set(null);
}
}
/**
* Link a node into a directory, directly.
@@ -1713,6 +1992,8 @@ public class AVMRepository
public void link(String parentPath, String name, AVMNodeDescriptor toLink)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(parentPath);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1721,6 +2002,11 @@ public class AVMRepository
}
store.link(pathParts[1], name, toLink);
}
finally
{
fLookupCount.set(null);
}
}
/**
* This is the danger version of link. It must be called on
@@ -1754,6 +2040,8 @@ public class AVMRepository
public void flatten(String path, String name)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1774,6 +2062,11 @@ public class AVMRepository
dir.flatten(name);
AVMDAOs.Instance().fAVMNodeDAO.flush();
}
finally
{
fLookupCount.set(null);
}
}
/**
* Force a copy on write.
@@ -1782,6 +2075,8 @@ public class AVMRepository
public AVMNodeDescriptor forceCopy(String path)
{
fLookupCount.set(1);
try
{
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
@@ -1797,4 +2092,9 @@ public class AVMRepository
AVMNode node = lPath.getCurrentNode();
return node.getDescriptor(lPath);
}
finally
{
fLookupCount.set(null);
}
}
}

View File

@@ -40,6 +40,7 @@ import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.transaction.TransactionUtil;
import org.alfresco.service.cmr.avm.AVMBadArgumentException;
import org.alfresco.service.cmr.avm.AVMCycleException;
import org.alfresco.service.cmr.avm.AVMException;
import org.alfresco.service.cmr.avm.AVMExistsException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
@@ -65,6 +66,39 @@ import org.alfresco.util.Pair;
*/
public class AVMServiceTest extends AVMServiceTestBase
{
/**
* Test cyclic lookup behavior.
*/
public void testCyclicLookup()
{
try
{
fService.createDirectory("main:/", "a");
fService.createFile("main:/a", "foo").close();
for (int i = 0; i < 1000; i++)
{
fService.lookup(-1, "main:/a/bar");
}
fService.lookup(-1, "main:/a/foo");
fService.createLayeredDirectory("main:/c", "main:/", "b");
fService.createLayeredDirectory("main:/b", "main:/", "c");
try
{
fService.lookup(-1, "main:/b/bar");
fail();
}
catch (AVMCycleException ce)
{
// Do nothing; this means success.
}
}
catch (Exception e)
{
e.printStackTrace(System.err);
fail();
}
}
/**
* Test getting all paths for a node.
*