Merged V2.1 to HEAD:

6556: AVM performance tweaks
   6557: WCM-758.
   6558: Fixes WCM-753.
   6559: better handling of rename, copy and paste for form instance data and renditions.  addresses WCM-752 and partially addresses WCM-559.
   6560: Renamed JndiTest.java until we decide to keep it or not.
   6561: Oops.
   6562: probable fix WCM-669      
   6563: Build fix after the removal of flushing suport 
   6564: Fix for WCM-728
   6566: Support for avm index clustering via tracking - WCM-762
   6567: Test fix after flush changes
   6568: Fixed AWC-1517: Can now create space based on existing top-level space
   6569: misc IE fixes.
   6570: Various changes to improve AVM import performance and submit performance.
   6571: Session flushing is now deprecated and doesn't fail with an exception.
   6572: Reduced the iteration count to stress nextResults calls a bit more
   6573: WS query sessions put back into cache after more results have been fetched.
   6574: AR-1347: RepositoryServiceSoapBindingStub.queryAssociated() returns nothing when direction=target
   6575: Fixed AR-1680: XPath metadata extraction now handles Node, NodeList and String return values
   6577: Fix for AWC-1518 (User Homes renaming issue, and unreported issue with client config overriding of users home location)


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6745 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-09-11 02:37:29 +00:00
parent 652b9406db
commit 19e1af2314
34 changed files with 2883 additions and 2279 deletions

View File

@@ -38,7 +38,6 @@ import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.version.VersionException; import javax.jcr.version.VersionException;
import org.alfresco.jcr.session.SessionImpl; import org.alfresco.jcr.session.SessionImpl;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
/** /**
@@ -107,7 +106,6 @@ public abstract class ItemImpl implements Item
*/ */
public void save() throws AccessDeniedException, ItemExistsException, ConstraintViolationException, InvalidItemStateException, ReferentialIntegrityException, VersionException, LockException, NoSuchNodeTypeException, RepositoryException public void save() throws AccessDeniedException, ItemExistsException, ConstraintViolationException, InvalidItemStateException, ReferentialIntegrityException, VersionException, LockException, NoSuchNodeTypeException, RepositoryException
{ {
AlfrescoTransactionSupport.flush();
} }
/* (non-Javadoc) /* (non-Javadoc)

View File

@@ -41,9 +41,9 @@ public class AVMCrawlTestP extends AVMServiceTestBase
*/ */
public void testCrawl() public void testCrawl()
{ {
int n = 4; // Number of Threads. int n = 8; // Number of Threads.
int m = 2; // How many multiples of content to start with. int m = 2; // How many multiples of content to start with.
long runTime = 3600000; // 1 Hour. . long runTime = 28800000; // 8 Hours. .
fService.purgeStore("main"); fService.purgeStore("main");
BulkLoader loader = new BulkLoader(); BulkLoader loader = new BulkLoader();
loader.setAvmService(fService); loader.setAvmService(fService);

View File

@@ -46,6 +46,7 @@ import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avm.AVMStoreDescriptor; import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
import org.alfresco.service.cmr.dictionary.AspectDefinition; import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.ClassDefinition; import org.alfresco.service.cmr.dictionary.ClassDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.InvalidAspectException; import org.alfresco.service.cmr.dictionary.InvalidAspectException;
import org.alfresco.service.cmr.dictionary.InvalidTypeException; import org.alfresco.service.cmr.dictionary.InvalidTypeException;
import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.dictionary.PropertyDefinition;
@@ -1194,7 +1195,12 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi
} }
} }
} }
values.put(qName, new PropertyValue(null, properties.get(qName))); DataTypeDefinition def = dictionaryService.getDataType(qName);
if (def == null)
{
def = dictionaryService.getDataType(properties.get(qName).getClass());
}
values.put(qName, new PropertyValue(def.getName(), properties.get(qName)));
} }
fAVMService.setNodeProperties(avmVersionPath.getSecond(), values); fAVMService.setNodeProperties(avmVersionPath.getSecond(), values);
// Invoke policy behaviors. // Invoke policy behaviors.
@@ -1287,7 +1293,12 @@ public class AVMNodeService extends AbstractNodeServiceImpl implements NodeServi
try try
{ {
// Map<QName, Serializable> propsBefore = getProperties(nodeRef); // Map<QName, Serializable> propsBefore = getProperties(nodeRef);
fAVMService.setNodeProperty(avmVersionPath.getSecond(), qname, new PropertyValue(null, value)); DataTypeDefinition def = dictionaryService.getDataType(qname);
if (def == null)
{
def = dictionaryService.getDataType(value.getClass());
}
fAVMService.setNodeProperty(avmVersionPath.getSecond(), qname, new PropertyValue(def.getName(), value));
// Map<QName, Serializable> propsAfter = getProperties(nodeRef); // Map<QName, Serializable> propsAfter = getProperties(nodeRef);
// Invoke policy behaviors. // Invoke policy behaviors.
// invokeOnUpdateNode(nodeRef); // invokeOnUpdateNode(nodeRef);

View File

@@ -639,7 +639,8 @@ public class AVMRepository
throw new AVMNotFoundException("Path not found."); throw new AVMNotFoundException("Path not found.");
} }
srcDir = (DirectoryNode)sPath.getCurrentNode(); srcDir = (DirectoryNode)sPath.getCurrentNode();
srcNode = srcDir.lookupChild(sPath, srcName, false); Pair<AVMNode, Boolean> temp = srcDir.lookupChild(sPath, srcName, false);
srcNode = (temp == null) ? null : temp.getFirst();
if (srcNode == null) if (srcNode == null)
{ {
throw new AVMNotFoundException("Not found: " + srcName); throw new AVMNotFoundException("Not found: " + srcName);
@@ -665,7 +666,8 @@ public class AVMRepository
throw new AVMNotFoundException("Path not found."); throw new AVMNotFoundException("Path not found.");
} }
DirectoryNode dstDir = (DirectoryNode)dPath.getCurrentNode(); DirectoryNode dstDir = (DirectoryNode)dPath.getCurrentNode();
AVMNode child = dstDir.lookupChild(dPath, dstName, true); Pair<AVMNode, Boolean> temp = dstDir.lookupChild(dPath, dstName, true);
AVMNode child = (temp == null) ? null : temp.getFirst();
if (child != null && child.getType() != AVMNodeType.DELETED_NODE) if (child != null && child.getType() != AVMNodeType.DELETED_NODE)
{ {
throw new AVMExistsException("Node exists: " + dstName); throw new AVMExistsException("Node exists: " + dstName);

View File

@@ -254,13 +254,13 @@ public class AVMServiceTest extends AVMServiceTestBase
props = new HashMap<QName, PropertyValue>(); props = new HashMap<QName, PropertyValue>();
QName n1 = QName.createQName("silly.uri", "Prop1"); QName n1 = QName.createQName("silly.uri", "Prop1");
PropertyValue p1 = new PropertyValue(null, new Date(System.currentTimeMillis())); PropertyValue p1 = new PropertyValue(DataTypeDefinition.DATETIME, new Date(System.currentTimeMillis()));
props.put(n1, p1); props.put(n1, p1);
QName n2 = QName.createQName("silly.uri", "Prop2"); QName n2 = QName.createQName("silly.uri", "Prop2");
PropertyValue p2 = new PropertyValue(null, "A String Property."); PropertyValue p2 = new PropertyValue(DataTypeDefinition.TEXT, "A String Property.");
props.put(n2, p2); props.put(n2, p2);
QName n3 = QName.createQName("silly.uri", "Prop3"); QName n3 = QName.createQName("silly.uri", "Prop3");
PropertyValue p3 = new PropertyValue(null, 42); PropertyValue p3 = new PropertyValue(DataTypeDefinition.INT, 42);
props.put(n3, p3); props.put(n3, p3);
fService.setNodeProperties("main:/a/b/c/bar", props); fService.setNodeProperties("main:/a/b/c/bar", props);
fService.createSnapshot("main", null, null); fService.createSnapshot("main", null, null);
@@ -5187,11 +5187,11 @@ public class AVMServiceTest extends AVMServiceTestBase
fService.addAspect("main:/a/b/c/foo", ContentModel.ASPECT_TITLED); fService.addAspect("main:/a/b/c/foo", ContentModel.ASPECT_TITLED);
fService.addAspect("main:/a/b/c/foo", ContentModel.ASPECT_AUDITABLE); fService.addAspect("main:/a/b/c/foo", ContentModel.ASPECT_AUDITABLE);
Map<QName, PropertyValue> properties = new HashMap<QName, PropertyValue>(); Map<QName, PropertyValue> properties = new HashMap<QName, PropertyValue>();
properties.put(ContentModel.PROP_ACCESSED, new PropertyValue(null, new Date(System.currentTimeMillis()))); properties.put(ContentModel.PROP_ACCESSED, new PropertyValue(DataTypeDefinition.DATETIME, new Date(System.currentTimeMillis())));
properties.put(ContentModel.PROP_CREATED, new PropertyValue(null, new Date(System.currentTimeMillis()))); properties.put(ContentModel.PROP_CREATED, new PropertyValue(DataTypeDefinition.DATETIME, new Date(System.currentTimeMillis())));
properties.put(ContentModel.PROP_MODIFIED, new PropertyValue(null, new Date(System.currentTimeMillis()))); properties.put(ContentModel.PROP_MODIFIED, new PropertyValue(DataTypeDefinition.DATETIME, new Date(System.currentTimeMillis())));
properties.put(ContentModel.PROP_CREATOR, new PropertyValue(null, "Giles")); properties.put(ContentModel.PROP_CREATOR, new PropertyValue(DataTypeDefinition.TEXT, "Giles"));
properties.put(ContentModel.PROP_MODIFIER, new PropertyValue(null, "Quentin")); properties.put(ContentModel.PROP_MODIFIER, new PropertyValue(DataTypeDefinition.TEXT, "Quentin"));
fService.setNodeProperties("main:/a/b/c/foo", properties); fService.setNodeProperties("main:/a/b/c/foo", properties);
fService.createSnapshot("main", null, null); fService.createSnapshot("main", null, null);

View File

@@ -59,6 +59,7 @@ import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.GUID; import org.alfresco.util.GUID;
import org.alfresco.util.Pair;
/** /**
* A Repository contains a current root directory and a list of * A Repository contains a current root directory and a list of
@@ -326,7 +327,8 @@ public class AVMStoreImpl implements AVMStore, Serializable
throw new AVMNotFoundException("Path " + path + " not found."); throw new AVMNotFoundException("Path " + path + " not found.");
} }
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
AVMNode child = dir.lookupChild(lPath, name, true); Pair<AVMNode, Boolean> temp = dir.lookupChild(lPath, name, true);
AVMNode child = (temp == null) ? null : temp.getFirst();
if (child != null && child.getType() != AVMNodeType.DELETED_NODE) if (child != null && child.getType() != AVMNodeType.DELETED_NODE)
{ {
throw new AVMExistsException("Child exists: " + name); throw new AVMExistsException("Child exists: " + name);
@@ -368,7 +370,8 @@ public class AVMStoreImpl implements AVMStore, Serializable
throw new AVMNotFoundException("Path " + dstPath + " not found."); throw new AVMNotFoundException("Path " + dstPath + " not found.");
} }
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
AVMNode child = dir.lookupChild(lPath, name, true); Pair<AVMNode, Boolean> temp = dir.lookupChild(lPath, name, true);
AVMNode child = (temp == null) ? null : temp.getFirst();
if (child != null && child.getType() != AVMNodeType.DELETED_NODE) if (child != null && child.getType() != AVMNodeType.DELETED_NODE)
{ {
throw new AVMExistsException("Child exists: " + name); throw new AVMExistsException("Child exists: " + name);
@@ -411,7 +414,8 @@ public class AVMStoreImpl implements AVMStore, Serializable
throw new AVMNotFoundException("Path " + path + " not found."); throw new AVMNotFoundException("Path " + path + " not found.");
} }
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
AVMNode child = dir.lookupChild(lPath, name, true); Pair<AVMNode, Boolean> temp = dir.lookupChild(lPath, name, true);
AVMNode child = (temp == null) ? null : temp.getFirst();
if (child != null && child.getType() != AVMNodeType.DELETED_NODE) if (child != null && child.getType() != AVMNodeType.DELETED_NODE)
{ {
throw new AVMExistsException("Child exists: " + name); throw new AVMExistsException("Child exists: " + name);
@@ -446,7 +450,8 @@ public class AVMStoreImpl implements AVMStore, Serializable
throw new AVMNotFoundException("Path " + path + " not found."); throw new AVMNotFoundException("Path " + path + " not found.");
} }
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
AVMNode child = dir.lookupChild(lPath, name, true); Pair<AVMNode, Boolean> temp = dir.lookupChild(lPath, name, true);
AVMNode child = (temp == null) ? null : temp.getFirst();
if (child != null && child.getType() != AVMNodeType.DELETED_NODE) if (child != null && child.getType() != AVMNodeType.DELETED_NODE)
{ {
throw new AVMExistsException("Child exists: " + name); throw new AVMExistsException("Child exists: " + name);
@@ -483,7 +488,8 @@ public class AVMStoreImpl implements AVMStore, Serializable
throw new AVMNotFoundException("Path " + dstPath + " not found."); throw new AVMNotFoundException("Path " + dstPath + " not found.");
} }
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
AVMNode child = dir.lookupChild(lPath, name, true); Pair<AVMNode, Boolean> temp = dir.lookupChild(lPath, name, true);
AVMNode child = (temp == null) ? null : temp.getFirst();
if (child != null && child.getType() != AVMNodeType.DELETED_NODE) if (child != null && child.getType() != AVMNodeType.DELETED_NODE)
{ {
throw new AVMExistsException("Child exists: " + name); throw new AVMExistsException("Child exists: " + name);
@@ -1431,7 +1437,8 @@ public class AVMStoreImpl implements AVMStore, Serializable
throw new AVMNotFoundException("Path " + path + " not found."); throw new AVMNotFoundException("Path " + path + " not found.");
} }
DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
AVMNode child = dir.lookupChild(lPath, name, true); Pair<AVMNode, Boolean> temp = dir.lookupChild(lPath, name, true);
AVMNode child = (temp == null) ? null : temp.getFirst();
if (child == null) if (child == null)
{ {
throw new AVMNotFoundException("Node not found: " + name); throw new AVMNotFoundException("Node not found: " + name);

View File

@@ -737,7 +737,15 @@ public class AVMSyncServiceImpl implements AVMSyncService
{ {
return true; return true;
} }
// layer = fAVMService.forceCopy(layer.getPath()); List<AVMDifference> diffs = compare(-1, layer.getPath(), -1, underlying.getPath(), null);
if (diffs.size() == 0)
{
for (String name : layerListing.keySet())
{
fAVMRepository.flatten(layer.getPath(), name);
}
return true;
}
// Grab the listing // Grab the listing
Map<String, AVMNodeDescriptor> underListing = Map<String, AVMNodeDescriptor> underListing =
fAVMService.getDirectoryListing(underlying, true); fAVMService.getDirectoryListing(underlying, true);

View File

@@ -27,6 +27,7 @@ import java.util.Map;
import java.util.SortedMap; import java.util.SortedMap;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.util.Pair;
/** /**
* The interface for Directory Nodes. * The interface for Directory Nodes.
@@ -54,7 +55,7 @@ public interface DirectoryNode extends AVMNode
* @param name The name of the child to lookup. * @param name The name of the child to lookup.
* @param includeDeleted Include deleted nodes or not. * @param includeDeleted Include deleted nodes or not.
*/ */
public AVMNode lookupChild(Lookup lPath, String name, boolean includeDeleted); public Pair<AVMNode, Boolean> lookupChild(Lookup lPath, String name, boolean includeDeleted);
/** /**
* Lookup a child node using an AVMNodeDescriptor as context. * Lookup a child node using an AVMNodeDescriptor as context.

View File

@@ -35,6 +35,7 @@ import org.alfresco.service.cmr.avm.AVMException;
import org.alfresco.service.cmr.avm.AVMExistsException; import org.alfresco.service.cmr.avm.AVMExistsException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMNotFoundException; import org.alfresco.service.cmr.avm.AVMNotFoundException;
import org.alfresco.util.Pair;
/** /**
* A layered directory node. A layered directory node points at * A layered directory node. A layered directory node points at
@@ -507,7 +508,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
* @return The child or null if not found. * @return The child or null if not found.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public AVMNode lookupChild(Lookup lPath, String name, boolean includeDeleted) public Pair<AVMNode, Boolean> lookupChild(Lookup lPath, String name, boolean includeDeleted)
{ {
ChildKey key = new ChildKey(this, name); ChildKey key = new ChildKey(this, name);
ChildEntry entry = AVMDAOs.Instance().fChildEntryDAO.get(key); ChildEntry entry = AVMDAOs.Instance().fChildEntryDAO.get(key);
@@ -517,7 +518,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
{ {
return null; return null;
} }
return AVMNodeUnwrapper.Unwrap(entry.getChild()); return new Pair<AVMNode, Boolean>(AVMNodeUnwrapper.Unwrap(entry.getChild()), true);
} }
// Don't check our underlying directory if we are opaque. // Don't check our underlying directory if we are opaque.
if (fOpacity) if (fOpacity)
@@ -529,7 +530,11 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
if (lookup != null) if (lookup != null)
{ {
DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode(); DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode();
AVMNode retVal = dir.lookupChild(lookup, name, includeDeleted); Pair<AVMNode, Boolean> retVal = dir.lookupChild(lookup, name, includeDeleted);
if (retVal != null)
{
retVal.setSecond(false);
}
lPath.setFinalStore(lookup.getFinalStore()); lPath.setFinalStore(lookup.getFinalStore());
return retVal; return retVal;
} }
@@ -573,12 +578,12 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
if (lookup != null) if (lookup != null)
{ {
DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode(); DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode();
AVMNode child = dir.lookupChild(lookup, name, includeDeleted); Pair<AVMNode, Boolean> child = dir.lookupChild(lookup, name, includeDeleted);
if (child == null) if (child == null)
{ {
return null; return null;
} }
return child.getDescriptor(lookup); return child.getFirst().getDescriptor(lookup);
} }
else else
{ {
@@ -613,7 +618,15 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
} }
else else
{ {
child = lookupChild(lPath, name, false); Pair<AVMNode, Boolean> temp = lookupChild(lPath, name, false);
if (temp == null)
{
child = null;
}
else
{
child = temp.getFirst();
}
indirect = true; indirect = true;
} }
if (child != null && (indirect || child.getStoreNew() == null || child.getAncestor() != null)) if (child != null && (indirect || child.getStoreNew() == null || child.getAncestor() != null))
@@ -893,7 +906,8 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec
throw new AVMBadArgumentException("Non primary layered directories cannot be linked."); throw new AVMBadArgumentException("Non primary layered directories cannot be linked.");
} }
// Look for an existing child of that name. // Look for an existing child of that name.
AVMNode existing = lookupChild(lPath, name, true); Pair<AVMNode, Boolean> temp = lookupChild(lPath, name, true);
AVMNode existing = (temp == null) ? null : temp.getFirst();
ChildKey key = new ChildKey(this, name); ChildKey key = new ChildKey(this, name);
if (existing != null) if (existing != null)
{ {

View File

@@ -218,7 +218,7 @@ class Lookup implements Serializable
* @param write Whether this is in the context of * @param write Whether this is in the context of
* a write operation. * a write operation.
*/ */
public void add(AVMNode node, String name, boolean write) public void add(AVMNode node, String name, boolean directlyContained, boolean write)
{ {
LookupComponent comp = new LookupComponent(); LookupComponent comp = new LookupComponent();
comp.setName(name); comp.setName(name);
@@ -226,7 +226,11 @@ class Lookup implements Serializable
if (fPosition >= 0 && fDirectlyContained && if (fPosition >= 0 && fDirectlyContained &&
fComponents.get(fPosition).getNode().getType() == AVMNodeType.LAYERED_DIRECTORY) fComponents.get(fPosition).getNode().getType() == AVMNodeType.LAYERED_DIRECTORY)
{ {
fDirectlyContained = ((DirectoryNode)fComponents.get(fPosition).getNode()).directlyContains(node); // if (directlyContained != ((DirectoryNode)fComponents.get(fPosition).getNode()).directlyContains(node))
// {
// System.err.println("Bloody Murder!");
// }
fDirectlyContained = directlyContained;
} }
if (!write) if (!write)
{ {

View File

@@ -8,6 +8,7 @@ import java.util.List;
import org.alfresco.repo.avm.util.SimplePath; import org.alfresco.repo.avm.util.SimplePath;
import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.util.Pair;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
@@ -104,14 +105,16 @@ public class LookupCache
} }
else else
{ {
dir = fAVMNodeDAO.getAVMStoreRoot(store, version); VersionRoot vRoot = AVMDAOs.Instance().fVersionRootDAO.getByVersionID(store, version);
dir = vRoot.getRoot();
// dir = fAVMNodeDAO.getAVMStoreRoot(store, version);
} }
if (dir == null) if (dir == null)
{ {
return null; return null;
} }
// Add an entry for the root. // Add an entry for the root.
result.add(dir, "", write); result.add(dir, "", true, write);
dir = (DirectoryNode)result.getCurrentNode(); dir = (DirectoryNode)result.getCurrentNode();
if (path.size() == 1 && path.get(0).equals("")) if (path.size() == 1 && path.get(0).equals(""))
{ {
@@ -122,28 +125,28 @@ public class LookupCache
// before the end. // before the end.
for (int i = 0; i < path.size() - 1; i++) for (int i = 0; i < path.size() - 1; i++)
{ {
AVMNode child = dir.lookupChild(result, path.get(i), includeDeleted); Pair<AVMNode, Boolean> child = dir.lookupChild(result, path.get(i), includeDeleted);
if (child == null) if (child == null)
{ {
return null; return null;
} }
// Every element that is not the last needs to be a directory. // Every element that is not the last needs to be a directory.
if (child.getType() != AVMNodeType.PLAIN_DIRECTORY && if (child.getFirst().getType() != AVMNodeType.PLAIN_DIRECTORY &&
child.getType() != AVMNodeType.LAYERED_DIRECTORY) child.getFirst().getType() != AVMNodeType.LAYERED_DIRECTORY)
{ {
return null; return null;
} }
result.add(child, path.get(i), write); result.add(child.getFirst(), path.get(i), child.getSecond(), write);
dir = (DirectoryNode)result.getCurrentNode(); dir = (DirectoryNode)result.getCurrentNode();
} }
// Now look up the last element. // Now look up the last element.
AVMNode child = dir.lookupChild(result, path.get(path.size() - 1), Pair<AVMNode, Boolean> child = dir.lookupChild(result, path.get(path.size() - 1),
includeDeleted); includeDeleted);
if (child == null) if (child == null)
{ {
return null; return null;
} }
result.add(child, path.get(path.size() - 1), write); result.add(child.getFirst(), path.get(path.size() - 1), child.getSecond(), write);
fCache.put(key, result); fCache.put(key, result);
return result; return result;
} }

View File

@@ -34,6 +34,7 @@ import org.alfresco.service.cmr.avm.AVMBadArgumentException;
import org.alfresco.service.cmr.avm.AVMExistsException; import org.alfresco.service.cmr.avm.AVMExistsException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMNotFoundException; import org.alfresco.service.cmr.avm.AVMNotFoundException;
import org.alfresco.util.Pair;
/** /**
* A plain directory. No monkey tricks except for possiblyCopy. * A plain directory. No monkey tricks except for possiblyCopy.
@@ -185,7 +186,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory
* @return The child or null. * @return The child or null.
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public AVMNode lookupChild(Lookup lPath, String name, boolean includeDeleted) public Pair<AVMNode, Boolean> lookupChild(Lookup lPath, String name, boolean includeDeleted)
{ {
ChildKey key = new ChildKey(this, name); ChildKey key = new ChildKey(this, name);
ChildEntry entry = AVMDAOs.Instance().fChildEntryDAO.get(key); ChildEntry entry = AVMDAOs.Instance().fChildEntryDAO.get(key);
@@ -196,7 +197,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory
} }
// We're doing the hand unrolling of the proxy because // We're doing the hand unrolling of the proxy because
// Hibernate/CGLIB proxies are broken. // Hibernate/CGLIB proxies are broken.
return AVMNodeUnwrapper.Unwrap(entry.getChild()); return new Pair<AVMNode, Boolean>(AVMNodeUnwrapper.Unwrap(entry.getChild()), true);
} }
/** /**

View File

@@ -51,7 +51,7 @@ public interface VersionRoot
/** /**
* @return the id * @return the id
*/ */
public long getId(); public Long getId();
/** /**
* @param id the id to set * @param id the id to set

View File

@@ -30,7 +30,7 @@ import java.io.Serializable;
* Hold a single version root. * Hold a single version root.
* @author britt * @author britt
*/ */
class VersionRootImpl implements VersionRoot, Serializable public class VersionRootImpl implements VersionRoot, Serializable
{ {
static final long serialVersionUID = 8826954538210455917L; static final long serialVersionUID = 8826954538210455917L;
@@ -126,7 +126,7 @@ class VersionRootImpl implements VersionRoot, Serializable
fCreator = creator; fCreator = creator;
} }
public long getId() public Long getId()
{ {
return fID; return fID;
} }

View File

@@ -2,169 +2,169 @@
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="org.alfresco.repo.avm"> <hibernate-mapping package="org.alfresco.repo.avm">
<typedef class="org.alfresco.repo.domain.hibernate.QNameUserType" name="QName"/> <typedef class="org.alfresco.repo.domain.hibernate.QNameUserType" name="QName"/>
<!-- AVMNodeBean is the abstract base for filesystem like objects. <!-- AVMNodeBean is the abstract base for filesystem like objects.
We're using the one table per class hierarchy strategy to implement We're using the one table per class hierarchy strategy to implement
polymorphism. --> polymorphism. -->
<class table="avm_nodes" abstract="true" <class table="avm_nodes" abstract="true"
name="AVMNodeImpl" name="AVMNodeImpl"
proxy="AVMNode" proxy="AVMNode"
optimistic-lock="version" optimistic-lock="version"
lazy="true"> lazy="true">
<cache usage="read-write"/> <cache usage="read-write"/>
<!-- The id is set programmatically using an Issuer. See below. --> <!-- The id is set programmatically using an Issuer. See below. -->
<id name="id" <id name="id"
column="id" column="id"
type="long"/> type="long"/>
<!-- I suppose this would be more efficient to encode type by an int. <!-- I suppose this would be more efficient to encode type by an int.
We'll see if using a string makes a difference. --> We'll see if using a string makes a difference. -->
<discriminator column="class_type" <discriminator column="class_type"
type="string" type="string"
length="20"/> length="20"/>
<!-- We're using hibernate's own versioning scheme for concurrency control. <!-- We're using hibernate's own versioning scheme for concurrency control.
I don't know how well that will play with a full Spring-JTA stack. --> I don't know how well that will play with a full Spring-JTA stack. -->
<version column="vers" <version column="vers"
name="vers" name="vers"
type="long"/> type="long"/>
<!-- This should really be not null, but I haven't figured out <!-- This should really be not null, but I haven't figured out
the right way to build the relation so that nullability constraints the right way to build the relation so that nullability constraints
won't cause violations in the db during saves. --> won't cause violations in the db during saves. -->
<property name="versionID" type="int" column="version_id" <property name="versionID" type="int" column="version_id"
not-null="true"/> not-null="true"/>
<property name="guid" type="string" length="36" column="guid"/> <property name="guid" type="string" length="36" column="guid"/>
<component name="basicAttributes" class="BasicAttributesImpl"> <component name="basicAttributes" class="BasicAttributesImpl">
<property name="creator" type="string" not-null="true"/> <property name="creator" type="string" not-null="true"/>
<property name="owner" type="string" not-null="true"/> <property name="owner" type="string" not-null="true"/>
<property name="lastModifier" type="string" not-null="true"/> <property name="lastModifier" type="string" not-null="true"/>
<property name="createDate" type="long" not-null="true"/> <property name="createDate" type="long" not-null="true"/>
<property name="modDate" type="long" not-null="true"/> <property name="modDate" type="long" not-null="true"/>
<property name="accessDate" type="long" not-null="true"/> <property name="accessDate" type="long" not-null="true"/>
</component> </component>
<property name="isRoot" column="is_root" type="boolean"/> <property name="isRoot" column="is_root" type="boolean"/>
<many-to-one name="storeNew" class="AVMStoreImpl" column="store_new_id" foreign-key="fk_avm_n_store"/> <many-to-one name="storeNew" class="AVMStoreImpl" column="store_new_id" foreign-key="fk_avm_n_store"/>
<!-- ACL --> <!-- ACL -->
<many-to-one name="acl" column="acl_id" foreign-key="fk_avm_n_acl" <many-to-one name="acl" column="acl_id" foreign-key="fk_avm_n_acl"
class="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl"/> class="org.alfresco.repo.domain.hibernate.DbAccessControlListImpl"/>
<set name="aspects" fetch="join" lazy="false" table="avm_aspects_new" cascade="all" optimistic-lock="true"> <set name="aspects" fetch="join" lazy="false" table="avm_aspects_new" cascade="all" optimistic-lock="true">
<cache usage="read-write"/> <cache usage="read-write"/>
<key column="id"/> <key column="id"/>
<element type="QName" not-null="true" column="name" length="200"/> <element type="QName" not-null="true" column="name" length="200"/>
</set> </set>
<map name="properties" fetch="join" lazy="false" table="avm_node_properties_new" cascade="all" optimistic-lock="true"> <map name="properties" fetch="join" lazy="false" table="avm_node_properties_new" cascade="all" optimistic-lock="true">
<cache usage="read-write"/> <cache usage="read-write"/>
<key column="node_id" not-null="true"/> <key column="node_id" not-null="true"/>
<map-key type="QName" length="200" column="qname"/> <map-key type="QName" length="200" column="qname"/>
<composite-element class="org.alfresco.repo.domain.PropertyValue"> <composite-element class="org.alfresco.repo.domain.PropertyValue">
<property name="actualType" column="actual_type" type="string" length="15" not-null="true" /> <property name="actualType" column="actual_type" type="string" length="15" not-null="true" />
<property name="multiValued" column="multi_valued" type="boolean" not-null="true" /> <property name="multiValued" column="multi_valued" type="boolean" not-null="true" />
<property name="persistedType" column="persisted_type" type="string" length="15" not-null="true" /> <property name="persistedType" column="persisted_type" type="string" length="15" not-null="true" />
<property name="booleanValue" column="boolean_value" type="boolean" /> <property name="booleanValue" column="boolean_value" type="boolean" />
<property name="longValue" column="long_value" type="long" /> <property name="longValue" column="long_value" type="long" />
<property name="floatValue" column="float_value" type="float" /> <property name="floatValue" column="float_value" type="float" />
<property name="doubleValue" column="double_value" type="double" /> <property name="doubleValue" column="double_value" type="double" />
<property name="stringValue" column="string_value" type="string" length="1024"/> <property name="stringValue" column="string_value" type="string" length="1024"/>
<property name="serializableValue" column="serializable_value" type="serializable" length="16384"/> <property name="serializableValue" column="serializable_value" type="serializable" length="16384"/>
</composite-element> </composite-element>
</map> </map>
<!-- Deleted nodes --> <!-- Deleted nodes -->
<subclass name="DeletedNodeImpl" <subclass name="DeletedNodeImpl"
proxy="DeletedNode" proxy="DeletedNode"
lazy="true" lazy="true"
discriminator-value="deletednode"> discriminator-value="deletednode">
<property name="deletedType" type="int"/> <property name="deletedType" type="int"/>
</subclass> </subclass>
<!-- Directories, two flavors. --> <!-- Directories, two flavors. -->
<subclass name="DirectoryNodeImpl" <subclass name="DirectoryNodeImpl"
proxy="DirectoryNode" proxy="DirectoryNode"
abstract="true" abstract="true"
lazy="true"> lazy="true">
<!-- A Layered Directory is our smart symlink thingy. --> <!-- A Layered Directory is our smart symlink thingy. -->
<subclass name="LayeredDirectoryNodeImpl" <subclass name="LayeredDirectoryNodeImpl"
proxy="LayeredDirectoryNode" proxy="LayeredDirectoryNode"
discriminator-value="layereddirectory" lazy="true"> discriminator-value="layereddirectory" lazy="true">
<!-- The layer id is an implementation trick to disambiguate <!-- The layer id is an implementation trick to disambiguate
exactly what layer is being refered to in various circumstances. --> exactly what layer is being refered to in various circumstances. -->
<property name="layerID" column="layer_id" type="long"/> <property name="layerID" column="layer_id" type="long"/>
<!-- The is the moral equivalent of the value of a symlink. --> <!-- The is the moral equivalent of the value of a symlink. -->
<property name="indirection" column="indirection" <property name="indirection" column="indirection"
type="string" length="511" /> type="string" length="511" />
<property name="indirectionVersion" type="int" column="indirection_version"/> <property name="indirectionVersion" type="int" column="indirection_version"/>
<!-- This marks a layered directory as either knowing itself what <!-- This marks a layered directory as either knowing itself what
it points at (true) or inheriting what it points at from its it points at (true) or inheriting what it points at from its
container (false). --> container (false). -->
<property name="primaryIndirection" <property name="primaryIndirection"
column="primary_indirection" type="boolean"/> column="primary_indirection" type="boolean"/>
<property name="opacity" column="opacity" type="boolean"/> <property name="opacity" column="opacity" type="boolean"/>
<!-- Map of names to DirectoryEntries. --> <!-- Map of names to DirectoryEntries. -->
</subclass> </subclass>
<!-- Just plain directories. --> <!-- Just plain directories. -->
<subclass name="PlainDirectoryNodeImpl" <subclass name="PlainDirectoryNodeImpl"
discriminator-value="plaindirectory" proxy="PlainDirectoryNode" lazy="true"> discriminator-value="plaindirectory" proxy="PlainDirectoryNode" lazy="true">
</subclass> </subclass>
</subclass> </subclass>
<!-- There are two kinds of files, plain and symlinky. --> <!-- There are two kinds of files, plain and symlinky. -->
<subclass name="FileNodeImpl" <subclass name="FileNodeImpl"
proxy="FileNode" proxy="FileNode"
abstract="true" abstract="true"
lazy="false"> lazy="false">
<!-- Plain files just have a reference to a Content object. --> <!-- Plain files just have a reference to a Content object. -->
<subclass discriminator-value="plainfile" <subclass discriminator-value="plainfile"
name="PlainFileNodeImpl" proxy="PlainFileNode" lazy="true"> name="PlainFileNodeImpl" proxy="PlainFileNode" lazy="true">
<property name="contentURL" column="content_url" type="string" length="128"/> <property name="contentURL" column="content_url" type="string" length="128"/>
<property name="mimeType" column="mime_type" type="string" length="64"/> <property name="mimeType" column="mime_type" type="string" length="64"/>
<property name="encoding" column="encoding" type="string" length="16"/> <property name="encoding" column="encoding" type="string" length="16"/>
<property name="length" column="length" type="long"/> <property name="length" column="length" type="long"/>
</subclass> </subclass>
<!-- Layered files are almost exactly copy on write symlinks. --> <!-- Layered files are almost exactly copy on write symlinks. -->
<subclass name="LayeredFileNodeImpl" <subclass name="LayeredFileNodeImpl"
discriminator-value="layeredfile" proxy="LayeredFileNode" lazy="true"> discriminator-value="layeredfile" proxy="LayeredFileNode" lazy="true">
<property name="indirection" type="string" length="511" <property name="indirection" type="string" length="511"
column="indirection" /> column="indirection" />
<property name="indirectionVersion" type="int" column="indirection_version"/> <property name="indirectionVersion" type="int" column="indirection_version"/>
</subclass> </subclass>
</subclass> </subclass>
</class> </class>
<!-- A store is the what we used to call a virtual repository. --> <!-- A store is the what we used to call a virtual repository. -->
<class table="avm_stores" name="AVMStoreImpl" <class table="avm_stores" name="AVMStoreImpl"
proxy="AVMStore" optimistic-lock="version"> proxy="AVMStore" optimistic-lock="version">
<cache usage="read-write"/> <cache usage="read-write"/>
<id name="id" column="id" type="long"> <id name="id" column="id" type="long">
<generator class="native"/> <generator class="native"/>
</id> </id>
<version name="vers" column="vers" type="long"/> <version name="vers" column="vers" type="long"/>
<property name="name" column="name" type="string" unique="true"/> <property name="name" column="name" type="string" unique="true"/>
<property type="int" name="nextVersionID" <property type="int" name="nextVersionID"
column="next_version_id" not-null="true"/> column="next_version_id" not-null="true"/>
<!-- Every AVMStore has a root directory that is the current root directory. --> <!-- Every AVMStore has a root directory that is the current root directory. -->
<many-to-one name="root" class="DirectoryNodeImpl" <many-to-one name="root" class="DirectoryNodeImpl"
column="current_root_id" cascade="save-update" foreign-key="fk_avm_s_root"> column="current_root_id" cascade="save-update" foreign-key="fk_avm_s_root">
</many-to-one> </many-to-one>
</class> </class>
<class name="VersionRootImpl" proxy="VersionRoot" table="avm_version_roots"> <class name="VersionRootImpl" proxy="VersionRoot" table="avm_version_roots">
<!-- <cache usage="read-write"/> --> <cache usage="read-write"/>
<id column="id" type="long"> <id name="id" column="id" type="long">
<generator class="native"></generator> <generator class="native"></generator>
</id> </id>
<natural-id> <natural-id>
<property name="versionID" type="int" not-null="true" <property name="versionID" type="int" not-null="true"
column="version_id" index="idx_avm_vr_version"> column="version_id" index="idx_avm_vr_version">
</property> </property>
<many-to-one name="avmStore" column="avm_store_id" <many-to-one name="avmStore" column="avm_store_id"
class="AVMStoreImpl" not-null="true" foreign-key="fk_avm_vr_store"> class="AVMStoreImpl" not-null="true" foreign-key="fk_avm_vr_store">
</many-to-one> </many-to-one>
</natural-id> </natural-id>
<property name="createDate" type="long" not-null="true" column="create_date"> <property name="createDate" type="long" not-null="true" column="create_date">
</property> </property>
<property name="creator" type="string" column="creator" <property name="creator" type="string" column="creator"
not-null="true"> not-null="true">
</property> </property>
<many-to-one name="root" class="DirectoryNodeImpl" <many-to-one name="root" class="DirectoryNodeImpl"
column="root_id" not-null="true" foreign-key="fk_avm_vr_root"> column="root_id" not-null="true" foreign-key="fk_avm_vr_root">
</many-to-one> </many-to-one>
<property name="tag" type="string" length="255" column="tag"/> <property name="tag" type="string" length="255" column="tag"/>
<property name="description" type="string" length="4000" column="description"/> <property name="description" type="string" length="4000" column="description"/>
</class> </class>
<class name="ChildEntryImpl" proxy="ChildEntry" table="avm_child_entries"> <class name="ChildEntryImpl" proxy="ChildEntry" table="avm_child_entries">
<cache usage="read-write"/> <cache usage="read-write"/>
<composite-id name="key" class="ChildKey"> <composite-id name="key" class="ChildKey">
@@ -173,25 +173,25 @@
</composite-id> </composite-id>
<many-to-one name="child" column="child_id" class="AVMNodeImpl" not-null="true" foreign-key="fk_avm_ce_child"/> <many-to-one name="child" column="child_id" class="AVMNodeImpl" not-null="true" foreign-key="fk_avm_ce_child"/>
</class> </class>
<class name="HistoryLinkImpl" proxy="HistoryLink" table="avm_history_links"> <class name="HistoryLinkImpl" proxy="HistoryLink" table="avm_history_links">
<composite-id> <composite-id>
<key-many-to-one name="ancestor" class="AVMNodeImpl" column="ancestor" foreign-key="fk_avm_hl_ancestor"/> <key-many-to-one name="ancestor" class="AVMNodeImpl" column="ancestor" foreign-key="fk_avm_hl_ancestor"/>
<key-many-to-one name="descendent" class="AVMNodeImpl" column="descendent" foreign-key="fk_avm_hl_desc"/> <key-many-to-one name="descendent" class="AVMNodeImpl" column="descendent" foreign-key="fk_avm_hl_desc"/>
</composite-id> </composite-id>
</class> </class>
<class name="MergeLinkImpl" proxy="MergeLink" table="avm_merge_links"> <class name="MergeLinkImpl" proxy="MergeLink" table="avm_merge_links">
<composite-id> <composite-id>
<key-many-to-one name="mfrom" class="AVMNodeImpl" column="mfrom" foreign-key="fk_avm_ml_from"/> <key-many-to-one name="mfrom" class="AVMNodeImpl" column="mfrom" foreign-key="fk_avm_ml_from"/>
<key-many-to-one name="mto" class="AVMNodeImpl" column="mto" foreign-key="fk_avm_ml_to"/> <key-many-to-one name="mto" class="AVMNodeImpl" column="mto" foreign-key="fk_avm_ml_to"/>
</composite-id> </composite-id>
</class> </class>
<class name="AVMNodePropertyImpl" proxy="AVMNodeProperty" table="avm_node_properties"> <class name="AVMNodePropertyImpl" proxy="AVMNodeProperty" table="avm_node_properties">
<id name="id" column="id" type="long"> <id name="id" column="id" type="long">
<generator class="native"/> <generator class="native"/>
</id> </id>
<many-to-one name="node" class="AVMNodeImpl" column="node_id" foreign-key="fk_avm_np_node"/> <many-to-one name="node" class="AVMNodeImpl" column="node_id" foreign-key="fk_avm_np_node"/>
<property name="name" column="qname" type="QName" length="200" index="idx_avm_np_name"/> <property name="name" column="qname" type="QName" length="200" index="idx_avm_np_name"/>
<component class="org.alfresco.repo.domain.PropertyValue" name="value"> <component class="org.alfresco.repo.domain.PropertyValue" name="value">
<property name="actualType" column="actual_type" type="string" length="15" not-null="true" /> <property name="actualType" column="actual_type" type="string" length="15" not-null="true" />
<property name="multiValued" column="multi_valued" type="boolean" not-null="true" /> <property name="multiValued" column="multi_valued" type="boolean" not-null="true" />
<property name="persistedType" column="persisted_type" type="string" length="15" not-null="true" /> <property name="persistedType" column="persisted_type" type="string" length="15" not-null="true" />
@@ -202,14 +202,14 @@
<property name="stringValue" column="string_value" type="string" length="1024"/> <property name="stringValue" column="string_value" type="string" length="1024"/>
<property name="serializableValue" column="serializable_value" type="serializable" length="16384"/> <property name="serializableValue" column="serializable_value" type="serializable" length="16384"/>
</component> </component>
</class> </class>
<class name="AVMStorePropertyImpl" proxy="AVMStoreProperty" table="avm_store_properties"> <class name="AVMStorePropertyImpl" proxy="AVMStoreProperty" table="avm_store_properties">
<id name="id" column="id" type="long"> <id name="id" column="id" type="long">
<generator class="native"/> <generator class="native"/>
</id> </id>
<many-to-one name="store" class="AVMStoreImpl" column="avm_store_id" foreign-key="fk_avm_sp_store"/> <many-to-one name="store" class="AVMStoreImpl" column="avm_store_id" foreign-key="fk_avm_sp_store"/>
<property name="name" column="qname" type="QName" length="200" index="idx_avm_sp_name"/> <property name="name" column="qname" type="QName" length="200" index="idx_avm_sp_name"/>
<component class="org.alfresco.repo.domain.PropertyValue" name="value"> <component class="org.alfresco.repo.domain.PropertyValue" name="value">
<property name="actualType" column="actual_type" type="string" length="15" not-null="true" /> <property name="actualType" column="actual_type" type="string" length="15" not-null="true" />
<property name="multiValued" column="multi_valued" type="boolean" not-null="true" /> <property name="multiValued" column="multi_valued" type="boolean" not-null="true" />
<property name="persistedType" column="persisted_type" type="string" length="15" not-null="true" /> <property name="persistedType" column="persisted_type" type="string" length="15" not-null="true" />
@@ -220,95 +220,95 @@
<property name="stringValue" column="string_value" type="string" length="1024"/> <property name="stringValue" column="string_value" type="string" length="1024"/>
<property name="serializableValue" column="serializable_value" type="serializable" length="16384"/> <property name="serializableValue" column="serializable_value" type="serializable" length="16384"/>
</component> </component>
</class> </class>
<!-- Aspect name table for AVM Nodes. --> <!-- Aspect name table for AVM Nodes. -->
<class name="AVMAspectNameImpl" proxy="AVMAspectName" table="avm_aspects"> <class name="AVMAspectNameImpl" proxy="AVMAspectName" table="avm_aspects">
<id name="id" column="id" type="long"> <id name="id" column="id" type="long">
<generator class="native"/> <generator class="native"/>
</id> </id>
<many-to-one name="node" class="AVMNodeImpl" column="node_id" foreign-key="fk_avm_asp_node"/> <many-to-one name="node" class="AVMNodeImpl" column="node_id" foreign-key="fk_avm_asp_node"/>
<property name="name" column="qname" type="QName" length="200"/> <property name="name" column="qname" type="QName" length="200"/>
</class> </class>
<!-- When a snapshot is created we stow away all of the layered <!-- When a snapshot is created we stow away all of the layered
nodes that were frozen by the snapshot so that subsequent nodes that were frozen by the snapshot so that subsequent
snapshots can find them and force copies. --> snapshots can find them and force copies. -->
<class name="VersionLayeredNodeEntryImpl" proxy="VersionLayeredNodeEntry" <class name="VersionLayeredNodeEntryImpl" proxy="VersionLayeredNodeEntry"
table="avm_version_layered_node_entry"> table="avm_version_layered_node_entry">
<composite-id> <composite-id>
<key-many-to-one name="version" class="VersionRootImpl" column="version_root_id"/> <key-many-to-one name="version" class="VersionRootImpl" column="version_root_id"/>
<key-property name="md5Sum" type="string" length="32" column="md5sum"/> <key-property name="md5Sum" type="string" length="32" column="md5sum"/>
</composite-id> </composite-id>
<property name="path" type="string" length="512" column="path"/> <property name="path" type="string" length="512" column="path"/>
</class> </class>
<query name="ChildEntry.DeleteByParent"> <query name="ChildEntry.DeleteByParent">
<![CDATA[ <![CDATA[
delete ChildEntryImpl ce delete ChildEntryImpl ce
where ce.key.parent = :parent where ce.key.parent = :parent
]]> ]]>
</query> </query>
<query name="AVMNode.GetNewInStore"> <query name="AVMNode.GetNewInStore">
<![CDATA[ <![CDATA[
from AVMNodeImpl an from AVMNodeImpl an
where an.storeNew = :store where an.storeNew = :store
]]> ]]>
</query> </query>
<query name="AVMNode.GetDescendents"> <query name="AVMNode.GetDescendents">
<![CDATA[ <![CDATA[
select hl.descendent select hl.descendent
from HistoryLinkImpl hl from HistoryLinkImpl hl
where hl.ancestor = :node where hl.ancestor = :node
]]> ]]>
</query> </query>
<query name="HistoryLink.ByAncestor"> <query name="HistoryLink.ByAncestor">
<![CDATA[ <![CDATA[
from HistoryLinkImpl hl from HistoryLinkImpl hl
where hl.ancestor = :node where hl.ancestor = :node
]]> ]]>
</query> </query>
<query name="AVMNode.GetMergedTo"> <query name="AVMNode.GetMergedTo">
<![CDATA[ <![CDATA[
select ml.mto select ml.mto
from MergeLinkImpl ml from MergeLinkImpl ml
where ml.mfrom = :merged where ml.mfrom = :merged
]]> ]]>
</query> </query>
<query name="MergeLink.ByFrom"> <query name="MergeLink.ByFrom">
<![CDATA[ <![CDATA[
from MergeLinkImpl ml from MergeLinkImpl ml
where ml.mfrom = :merged where ml.mfrom = :merged
]]> ]]>
</query> </query>
<query name="VersionRoot.GetVersionRoot"> <query name="VersionRoot.GetVersionRoot">
<![CDATA[ <![CDATA[
select v.root select v.root
from VersionRootImpl v from VersionRootImpl v
where where
v.avmStore = :store and v.versionID = :version v.avmStore = :store and v.versionID = :version
]]> ]]>
</query> </query>
<query name="VersionRoot.VersionByID"> <query name="VersionRoot.VersionByID">
<![CDATA[ <![CDATA[
from VersionRootImpl v from VersionRootImpl v
where where
v.avmStore = :store and v.versionID = :version v.avmStore = :store and v.versionID = :version
]]> ]]>
</query> </query>
<query name="FindOrphans"> <query name="FindOrphans">
<![CDATA[ <![CDATA[
from AVMNodeImpl an from AVMNodeImpl an
where where
an not in ( select ce.child an not in ( select ce.child
from ChildEntryImpl ce ) from ChildEntryImpl ce )
and an.isRoot = false and an.isRoot = false
]]> ]]>
</query> </query>
<query name="PlainFileNode.GetContentUrls"> <query name="PlainFileNode.GetContentUrls">
<![CDATA[ <![CDATA[
select select
pfn.contentURL pfn.contentURL
from from
PlainFileNodeImpl pfn PlainFileNodeImpl pfn
where pfn.contentURL is not null where pfn.contentURL is not null
]]> ]]>
</query> </query>

View File

@@ -24,12 +24,16 @@
package org.alfresco.repo.avm.hibernate; package org.alfresco.repo.avm.hibernate;
import java.util.Date; import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import org.alfresco.repo.avm.AVMNode; import org.alfresco.repo.avm.AVMNode;
import org.alfresco.repo.avm.AVMStore; import org.alfresco.repo.avm.AVMStore;
import org.alfresco.repo.avm.VersionRoot; import org.alfresco.repo.avm.VersionRoot;
import org.alfresco.repo.avm.VersionRootImpl;
import org.alfresco.repo.avm.VersionRootDAO; import org.alfresco.repo.avm.VersionRootDAO;
import org.alfresco.util.Pair;
import org.hibernate.Query; import org.hibernate.Query;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
@@ -40,12 +44,15 @@ import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
class VersionRootDAOHibernate extends HibernateDaoSupport implements class VersionRootDAOHibernate extends HibernateDaoSupport implements
VersionRootDAO VersionRootDAO
{ {
private LinkedHashMap<Pair<Long, Integer>, Long> fCache;
/** /**
* Do nothing constructor. * Do nothing constructor.
*/ */
public VersionRootDAOHibernate() public VersionRootDAOHibernate()
{ {
super(); super();
fCache = new LinkedHashMap<Pair<Long, Integer>, Long>();
} }
/** /**
@@ -128,12 +135,37 @@ class VersionRootDAOHibernate extends HibernateDaoSupport implements
* @param id The version id. * @param id The version id.
* @return The VersionRoot or null if not found. * @return The VersionRoot or null if not found.
*/ */
public VersionRoot getByVersionID(AVMStore store, int id) public synchronized VersionRoot getByVersionID(AVMStore store, int id)
{ {
Long vID = fCache.get(new Pair<Long, Integer>(store.getId(), id));
if (vID != null)
{
VersionRoot root = (VersionRoot)getSession().get(VersionRootImpl.class, vID);
if (root != null)
{
return root;
}
fCache.remove(new Pair<Long, Integer>(store.getId(), id));
}
Query query = getSession().getNamedQuery("VersionRoot.VersionByID"); Query query = getSession().getNamedQuery("VersionRoot.VersionByID");
query.setEntity("store", store); query.setEntity("store", store);
query.setInteger("version", id); query.setInteger("version", id);
return (VersionRoot)query.uniqueResult(); VersionRoot root = (VersionRoot)query.uniqueResult();
if (root != null)
{
vID = root.getId();
if (vID != null)
{
if (fCache.size() >= 10)
{
Iterator<Pair<Long, Integer>> iter = fCache.keySet().iterator();
iter.next();
iter.remove();
}
fCache.put(new Pair<Long, Integer>(store.getId(), id), vID);
}
}
return root;
} }
/** /**

View File

@@ -264,7 +264,7 @@ public class AVMLockingServiceImpl implements AVMLockingService
keys.add(lock.getWebProject()); keys.add(lock.getWebProject());
String digest = MD5.Digest(lock.getPath().getBytes()); String digest = MD5.Digest(lock.getPath().getBytes());
keys.add(digest); keys.add(digest);
if (fAttributeService.getAttribute(keys) != null) if (fAttributeService.exists(keys))
{ {
throw new AVMExistsException("Lock Exists: " + keys); throw new AVMExistsException("Lock Exists: " + keys);
} }
@@ -316,8 +316,7 @@ public class AVMLockingServiceImpl implements AVMLockingService
keys.add(WEB_PROJECTS); keys.add(WEB_PROJECTS);
keys.add(webProject); keys.add(webProject);
keys.add(pathKey); keys.add(pathKey);
Attribute lockData = fAttributeService.getAttribute(keys); if (!fAttributeService.exists(keys))
if (lockData == null)
{ {
return; return;
} }

View File

@@ -34,6 +34,7 @@ import java.util.Map;
import org.alfresco.repo.domain.PropertyValue; import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.service.cmr.avm.AVMException; import org.alfresco.service.cmr.avm.AVMException;
import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
/** /**
@@ -78,7 +79,7 @@ public class BulkLoader
Map<QName, PropertyValue> props = new HashMap<QName, PropertyValue>(); Map<QName, PropertyValue> props = new HashMap<QName, PropertyValue>();
for (int i = 0; i < fPropertyCount; i++) for (int i = 0; i < fPropertyCount; i++)
{ {
props.put(QName.createQName("silly", "prop" + i), new PropertyValue(null, "I am property " + i)); props.put(QName.createQName("silly", "prop" + i), new PropertyValue(DataTypeDefinition.TEXT, "I am property " + i));
} }
File file = new File(fsPath); File file = new File(fsPath);
String name = file.getName(); String name = file.getName();

View File

@@ -249,30 +249,16 @@ public class XPathMetadataExtracter extends AbstractMappingMetadataExtracter imp
{ {
String documentProperty = element.getKey(); String documentProperty = element.getKey();
XPathExpression xpathExpression = element.getValue(); XPathExpression xpathExpression = element.getValue();
// Execute it // Get the value, assuming it is a nodeset
NodeList nodeList = (NodeList) xpathExpression.evaluate(document, XPathConstants.NODESET);
// Convert the value
Serializable value = null; Serializable value = null;
int nodeCount = nodeList.getLength(); try
if (nodeCount == 0)
{ {
// No result value = getNodeSetValue(document, xpathExpression);
} }
else if (nodeCount == 1) catch (XPathExpressionException e)
{ {
Node node = nodeList.item(0); // That didn't work, so give it a try as a STRING
// Get the string value value = getStringValue(document, xpathExpression);
value = node.getTextContent();
}
else
{
// Make a collection of the values
ArrayList<String> stringValues = new ArrayList<String>(5);
for (int i = 0; i < nodeCount; i++)
{
stringValues.add(nodeList.item(i).getTextContent());
}
value = stringValues;
} }
// Put the value // Put the value
rawProperties.put(documentProperty, value); rawProperties.put(documentProperty, value);
@@ -281,6 +267,57 @@ public class XPathMetadataExtracter extends AbstractMappingMetadataExtracter imp
return rawProperties; return rawProperties;
} }
private Serializable getStringValue(Document document, XPathExpression xpathExpression) throws XPathExpressionException
{
String value = (String) xpathExpression.evaluate(document, XPathConstants.STRING);
// Done
return value;
}
private Serializable getNodeSetValue(Document document, XPathExpression xpathExpression) throws XPathExpressionException
{
// Execute it
NodeList nodeList = null;
try
{
nodeList = (NodeList) xpathExpression.evaluate(document, XPathConstants.NODESET);
}
catch (XPathExpressionException e)
{
// Expression didn't evaluate to a nodelist
if (logger.isDebugEnabled())
{
logger.debug("Unable to evaluate expression and return a NODESET: " + xpathExpression);
}
throw e;
}
// Convert the value
Serializable value = null;
int nodeCount = nodeList.getLength();
if (nodeCount == 0)
{
// No result
}
else if (nodeCount == 1)
{
Node node = nodeList.item(0);
// Get the string value
value = node.getTextContent();
}
else
{
// Make a collection of the values
ArrayList<String> stringValues = new ArrayList<String>(5);
for (int i = 0; i < nodeCount; i++)
{
stringValues.add(nodeList.item(i).getTextContent());
}
value = stringValues;
}
// Done
return value;
}
/** /**
* A utility method to convert mapping properties to the Map form. * A utility method to convert mapping properties to the Map form.
* *

View File

@@ -600,6 +600,23 @@ public class FileFolderServiceImpl implements FileFolderService
NamespaceService.CONTENT_MODEL_1_0_URI, NamespaceService.CONTENT_MODEL_1_0_URI,
QName.createValidLocalName(newName)); QName.createValidLocalName(newName));
QName targetParentType = nodeService.getType(targetParentRef);
// Fix AWC-1517
QName assocTypeQname = null;
if (dictionaryService.isSubClass(targetParentType, ContentModel.TYPE_FOLDER))
{
assocTypeQname = ContentModel.ASSOC_CONTAINS; // cm:folder -> cm:contains
}
else if (dictionaryService.isSubClass(targetParentType, ContentModel.TYPE_CONTAINER))
{
assocTypeQname = ContentModel.ASSOC_CHILDREN; // sys:container -> sys:children
}
else
{
throw new InvalidTypeException("Unexpected type (" + targetParentType + ") for target parent: " + targetParentRef);
}
// move or copy // move or copy
NodeRef targetNodeRef = null; NodeRef targetNodeRef = null;
if (move) if (move)
@@ -611,7 +628,7 @@ public class FileFolderServiceImpl implements FileFolderService
ChildAssociationRef newAssocRef = nodeService.moveNode( ChildAssociationRef newAssocRef = nodeService.moveNode(
sourceNodeRef, sourceNodeRef,
targetParentRef, targetParentRef,
assocRef.getTypeQName(), assocTypeQname,
qname); qname);
targetNodeRef = newAssocRef.getChildRef(); targetNodeRef = newAssocRef.getChildRef();
} }
@@ -629,7 +646,7 @@ public class FileFolderServiceImpl implements FileFolderService
targetNodeRef = copyService.copy( targetNodeRef = copyService.copy(
sourceNodeRef, sourceNodeRef,
targetParentRef, targetParentRef,
assocRef.getTypeQName(), assocTypeQname,
qname, qname,
true); true);
} }

View File

@@ -31,6 +31,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
@@ -84,7 +85,8 @@ public class MLContentInterceptor implements MethodInterceptor
NodeRef nodeRef = (NodeRef) args[0]; NodeRef nodeRef = (NodeRef) args[0];
// Shortcut it if the node is not an empty translation // Shortcut it if the node is not an empty translation
if (!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION)) if (nodeRef.getStoreRef().getProtocol().equals(StoreRef.PROTOCOL_AVM) ||
!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{ {
return invocation.proceed(); return invocation.proceed();
} }

View File

@@ -40,6 +40,7 @@ import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.MLText; import org.alfresco.service.cmr.repository.MLText;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.EqualsHelper; import org.alfresco.util.EqualsHelper;
@@ -251,7 +252,7 @@ public class MLPropertyInterceptor implements MethodInterceptor
*/ */
private NodeRef getPivotNodeRef(NodeRef nodeRef) private NodeRef getPivotNodeRef(NodeRef nodeRef)
{ {
if (nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION)) if (!nodeRef.getStoreRef().getProtocol().equals(StoreRef.PROTOCOL_AVM) && nodeService.hasAspect(nodeRef, ContentModel.ASPECT_MULTILINGUAL_EMPTY_TRANSLATION))
{ {
return multilingualContentService.getPivotTranslation(nodeRef); return multilingualContentService.getPivotTranslation(nodeRef);
} }

View File

@@ -355,7 +355,7 @@ public class ArchiveAndRestoreTest extends TestCase
verifyNodeExistence(bb_, true); verifyNodeExistence(bb_, true);
// flush // flush
AlfrescoTransactionSupport.flush(); //AlfrescoTransactionSupport.flush();
// check that the required properties are present and correct // check that the required properties are present and correct
Map<QName, Serializable> bb_Properties = nodeService.getProperties(bb_); Map<QName, Serializable> bb_Properties = nodeService.getProperties(bb_);
@@ -383,7 +383,7 @@ public class ArchiveAndRestoreTest extends TestCase
verifyChildAssocExistence(childAssocBtoBB_, true); verifyChildAssocExistence(childAssocBtoBB_, true);
// flush // flush
AlfrescoTransactionSupport.flush(); //AlfrescoTransactionSupport.flush();
// restore the node // restore the node
nodeService.restoreNode(b_, null, null, null); nodeService.restoreNode(b_, null, null, null);
@@ -398,7 +398,7 @@ public class ArchiveAndRestoreTest extends TestCase
nodeService.deleteNode(a); nodeService.deleteNode(a);
// flush // flush
AlfrescoTransactionSupport.flush(); //AlfrescoTransactionSupport.flush();
// restore in reverse order // restore in reverse order
nodeService.restoreNode(a_, null, null, null); nodeService.restoreNode(a_, null, null, null);
@@ -414,7 +414,7 @@ public class ArchiveAndRestoreTest extends TestCase
nodeService.deleteNode(b); nodeService.deleteNode(b);
// flush // flush
AlfrescoTransactionSupport.flush(); //AlfrescoTransactionSupport.flush();
// restore in reverse order // restore in reverse order
nodeService.restoreNode(b_, null, null, null); nodeService.restoreNode(b_, null, null, null);
@@ -430,7 +430,7 @@ public class ArchiveAndRestoreTest extends TestCase
nodeService.deleteNode(b); nodeService.deleteNode(b);
// flush // flush
AlfrescoTransactionSupport.flush(); //AlfrescoTransactionSupport.flush();
// in restoring 'a' first, there will be some associations that won't be recreated // in restoring 'a' first, there will be some associations that won't be recreated
nodeService.restoreNode(a_, null, null, null); nodeService.restoreNode(a_, null, null, null);
@@ -486,7 +486,7 @@ public class ArchiveAndRestoreTest extends TestCase
cumulatedArchiveTimeNs += (end - start); cumulatedArchiveTimeNs += (end - start);
// flush // flush
AlfrescoTransactionSupport.flush(); //AlfrescoTransactionSupport.flush();
// now restore // now restore
start = System.nanoTime(); start = System.nanoTime();

View File

@@ -29,7 +29,6 @@ import java.lang.reflect.Method;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.node.BaseNodeServiceTest; import org.alfresco.repo.node.BaseNodeServiceTest;
import org.alfresco.repo.node.db.DbNodeServiceImpl; import org.alfresco.repo.node.db.DbNodeServiceImpl;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.TransactionResourceInterceptor; import org.alfresco.repo.transaction.TransactionResourceInterceptor;
import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
@@ -53,7 +52,7 @@ public class SessionSizeManagementTest extends BaseNodeServiceTest
{ {
try try
{ {
Class clazz = SessionSizeManagementTest.class; Class<SessionSizeManagementTest> clazz = SessionSizeManagementTest.class;
createNodesMethod = clazz.getMethod( createNodesMethod = clazz.getMethod(
"createNodes", "createNodes",
new Class[] {NodeService.class, Integer.TYPE, Boolean.TYPE}); new Class[] {NodeService.class, Integer.TYPE, Boolean.TYPE});
@@ -118,9 +117,6 @@ public class SessionSizeManagementTest extends BaseNodeServiceTest
NodeService nodeService = getNodeService(); NodeService nodeService = getNodeService();
createNodes(nodeService, LOAD_COUNT, false); createNodes(nodeService, LOAD_COUNT, false);
// We can't check the session size as this is dependent on machine speed // We can't check the session size as this is dependent on machine speed
// Now flush integrity to be sure things are not broken
AlfrescoTransactionSupport.flush();
} }
/** /**
@@ -136,8 +132,5 @@ public class SessionSizeManagementTest extends BaseNodeServiceTest
} }
createNodes(nodeService, LOAD_COUNT, true); createNodes(nodeService, LOAD_COUNT, true);
// Now flush integrity to be sure things are not broken
AlfrescoTransactionSupport.flush();
} }
} }

View File

@@ -1,5 +1,6 @@
package org.alfresco.repo.node.index; package org.alfresco.repo.node.index;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import org.alfresco.repo.node.index.FullIndexRecoveryComponent.RecoveryMode; import org.alfresco.repo.node.index.FullIndexRecoveryComponent.RecoveryMode;
@@ -51,14 +52,12 @@ public class AVMFullIndexRecoveryComponent extends AbstractReindexComponent
this.lockServer = lockServer; this.lockServer = lockServer;
} }
public void setAvmService(AVMService avmService) public void setAvmService(AVMService avmService)
{ {
this.avmService = avmService; this.avmService = avmService;
} }
public void setAvmSnapShotTriggeredIndexingMethodInterceptor( public void setAvmSnapShotTriggeredIndexingMethodInterceptor(AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor)
AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor)
{ {
this.avmSnapShotTriggeredIndexingMethodInterceptor = avmSnapShotTriggeredIndexingMethodInterceptor; this.avmSnapShotTriggeredIndexingMethodInterceptor = avmSnapShotTriggeredIndexingMethodInterceptor;
} }
@@ -72,77 +71,180 @@ public class AVMFullIndexRecoveryComponent extends AbstractReindexComponent
private void processStores() private void processStores()
{ {
List<AVMStoreDescriptor> stores = avmService.getStores(); List<AVMStoreDescriptor> stores = avmService.getStores();
if(stores.size() == 0) LinkedHashMap<String, RecoveryMode> actions = new LinkedHashMap<String, RecoveryMode>();
if (stores.size() == 0)
{ {
return; return;
} }
int count = 0; switch (recoveryMode)
int tracker = -1;
logger.info("Checking indexes for AVM Stores");
for (AVMStoreDescriptor store : stores)
{ {
if (isShuttingDown()) case AUTO:
case VALIDATE:
int count = 0;
int tracker = -1;
if (logger.isDebugEnabled())
{ {
return; logger.debug("Checking indexes for AVM Stores: " + recoveryMode);
} }
processStore(store.getName()); for (AVMStoreDescriptor store : stores)
count++;
if (count*10l/stores.size() > tracker)
{ {
tracker = (int)(count*10l/stores.size()); if (isShuttingDown())
logger.info(" Stores "+(tracker*10)+"% complete"); {
return;
}
actions.put(store.getName(), checkStore(store.getName()));
count++;
if (count * 10l / stores.size() > tracker)
{
tracker = (int) (count * 10l / stores.size());
if (logger.isDebugEnabled())
{
logger.debug(" Store check " + (tracker * 10) + "% complete");
}
}
}
if (logger.isDebugEnabled())
{
logger.debug("Finished checking indexes for AVM Stores");
}
break;
case FULL:
case NONE:
for (AVMStoreDescriptor store : stores)
{
if (isShuttingDown())
{
return;
}
actions.put(store.getName(), checkStore(store.getName()));
}
break;
default:
}
int full = 0;
int auto = 0;
int invalid = 0;
for (String store : actions.keySet())
{
RecoveryMode mode = actions.get(store);
switch (mode)
{
case AUTO:
auto++;
break;
case FULL:
full++;
break;
case VALIDATE:
invalid++;
break;
case NONE:
default:
} }
} }
logger.info("Finished checking indexes for AVM Stores");
if (recoveryMode != RecoveryMode.NONE)
{
if (logger.isDebugEnabled())
{
logger.debug("Invalid indexes: " + invalid);
logger.debug("Indexes for full rebuild: " + full);
logger.debug("Indexes for auto update: " + auto);
}
}
int count = 0;
int tracker = -1;
int total = full + auto;
if (total > 0)
{
logger.info("Rebuilding indexes for " + total + " AVM Stores");
for (String store : actions.keySet())
{
RecoveryMode mode = actions.get(store);
if (isShuttingDown())
{
return;
}
if ((mode == RecoveryMode.FULL) || (mode == RecoveryMode.AUTO))
{
processStore(store, mode);
count++;
}
if (count * 10l / total > tracker)
{
tracker = (int) (count * 10l / total);
logger.info(" Reindex " + (tracker * 10) + "% complete");
}
}
logger.info("Finished rebuilding indexes for AVM Stores");
}
} }
private void processStore(String store) private RecoveryMode checkStore(String store)
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("Performing AVM index recovery for type: " + recoveryMode + " on store " + store); logger.debug("Checking AVM store for index recovery: " + recoveryMode + " on store " + store);
} }
// do we just ignore // do we just ignore
if (recoveryMode == RecoveryMode.NONE) if (recoveryMode == RecoveryMode.NONE)
{ {
return; return RecoveryMode.NONE;
} }
// check the level of cover required
boolean fullRecoveryRequired = false; // Nothing to do for unindexed stores
if (avmSnapShotTriggeredIndexingMethodInterceptor.getIndexMode(store) == IndexMode.UNINDEXED)
{
if (!avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated(store))
{
logger.warn(" Index for avm store " + store + " is out of date");
return recoveryMode;
}
else
{
return RecoveryMode.NONE;
}
}
if (recoveryMode == RecoveryMode.FULL) // no validate required if (recoveryMode == RecoveryMode.FULL) // no validate required
{ {
fullRecoveryRequired = true; return RecoveryMode.FULL;
} }
else else
// validate first // validate first
{ {
if(avmSnapShotTriggeredIndexingMethodInterceptor.getIndexMode(store) == IndexMode.UNINDEXED) if (!avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated(store))
{ {
return; logger.warn(" Index for avm store " + store + " is out of date");
return recoveryMode;
} }
int lastActualSnapshotId = avmService.getLatestSnapshotID(store); int lastActualSnapshotId = avmService.getLatestSnapshotID(store);
if (lastActualSnapshotId <= 0) if (lastActualSnapshotId <= 0)
{ {
return; return RecoveryMode.NONE;
} }
int lastIndexedSnapshotId = avmSnapShotTriggeredIndexingMethodInterceptor.getLastIndexedSnapshot(store); int lastIndexedSnapshotId = avmSnapShotTriggeredIndexingMethodInterceptor.getLastIndexedSnapshot(store);
if (lastActualSnapshotId != lastIndexedSnapshotId) if (lastActualSnapshotId != lastIndexedSnapshotId)
{ {
logger.warn("Index for avm store " + store + " is out of date"); logger.warn(" Index for avm store " + store + " is out of date");
// this store isn't up to date return recoveryMode;
if (recoveryMode == RecoveryMode.VALIDATE) }
{ else
// the store is out of date - validation failed {
} return recoveryMode.NONE;
else if (recoveryMode == RecoveryMode.AUTO)
{
fullRecoveryRequired = true;
}
} }
} }
}
private void processStore(String store, RecoveryMode mode)
{
// put the server into read-only mode for the duration // put the server into read-only mode for the duration
boolean allowWrite = !transactionService.isReadOnly(); boolean allowWrite = !transactionService.isReadOnly();
try try
@@ -153,11 +255,8 @@ public class AVMFullIndexRecoveryComponent extends AbstractReindexComponent
transactionService.setAllowWrite(false); transactionService.setAllowWrite(false);
} }
// do we need to perform a full recovery recoverStore(store, mode);
if (fullRecoveryRequired)
{
recoverStore(store);
}
} }
finally finally
{ {
@@ -167,56 +266,97 @@ public class AVMFullIndexRecoveryComponent extends AbstractReindexComponent
} }
private void recoverStore(String store) private void recoverStore(String store, RecoveryMode mode)
{ {
int tracker = -1; int tracker = -1;
int latest = avmService.getLatestSnapshotID(store);
if(latest <= 0)
{
return;
}
logger.info("Recovery for "+store);
if(!avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated(store)) if (mode == RecoveryMode.AUTO)
{
logger.info(" Auto recovering index for " + store);
}
else if (mode == RecoveryMode.FULL)
{
logger.info(" Rebuilding index for " + store);
}
if (!avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated(store))
{ {
avmSnapShotTriggeredIndexingMethodInterceptor.createIndex(store); avmSnapShotTriggeredIndexingMethodInterceptor.createIndex(store);
} }
for (int i = 0; i <= latest; i++)
int latest = avmService.getLatestSnapshotID(store);
if (latest <= 0)
{ {
if (isShuttingDown()) return;
}
boolean wasRecovered = false;
if (avmSnapShotTriggeredIndexingMethodInterceptor.getIndexMode(store) != IndexMode.UNINDEXED)
{
for (int i = 0; i <= latest; i++)
{ {
return; if (isShuttingDown())
} {
recoverSnapShot(store, i); return;
if (i*10l/latest > tracker) }
{ wasRecovered = recoverSnapShot(store, i, mode, wasRecovered);
tracker = (int)(i*10l/latest); if (i * 10l / latest > tracker)
logger.info(" Store "+store +" "+(tracker*10)+"% complete"); {
tracker = (int) (i * 10l / latest);
if (logger.isDebugEnabled())
{
logger.debug(" Store " + store + " " + (tracker * 10) + "% complete");
}
}
} }
} }
logger.info("Recovery for "+store+" done"); if (logger.isDebugEnabled())
{
logger.debug(" Index updated for " + store);
}
} }
private void recoverSnapShot(final String store, final int id) private boolean recoverSnapShot(final String store, final int id, final RecoveryMode mode, final boolean wasRecovered)
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
logger.debug("Reindexing avm store: " + store + " snapshot id " + id); logger.debug(" Reindexing avm store: " + store + " snapshot id " + id);
} }
RetryingTransactionCallback<Object> reindexWork = new RetryingTransactionCallback<Object>() RetryingTransactionCallback<Boolean> reindexWork = new RetryingTransactionCallback<Boolean>()
{ {
public Object execute() throws Exception public Boolean execute() throws Exception
{ {
if (!avmSnapShotTriggeredIndexingMethodInterceptor.isSnapshotIndexed(store, id)) if (wasRecovered)
{ {
avmSnapShotTriggeredIndexingMethodInterceptor.indexSnapshot(store, id - 1, id); avmSnapShotTriggeredIndexingMethodInterceptor.indexSnapshot(store, id - 1, id);
return true;
} }
// done else
return null; {
if (mode == RecoveryMode.AUTO)
{
if (!avmSnapShotTriggeredIndexingMethodInterceptor.isSnapshotIndexed(store, id))
{
avmSnapShotTriggeredIndexingMethodInterceptor.indexSnapshot(store, id - 1, id);
return true;
}
else
{
return wasRecovered;
}
}
else
{
avmSnapShotTriggeredIndexingMethodInterceptor.indexSnapshot(store, id - 1, id);
return true;
}
}
} }
}; };
transactionService.getRetryingTransactionHelper().doInTransaction(reindexWork, true, true); return transactionService.getRetryingTransactionHelper().doInTransaction(reindexWork, true, true);
// done // done
} }

View File

@@ -0,0 +1,129 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.node.index;
import java.util.List;
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Track and update when snapshots are created and indexed in a cluster
*/
public class AVMRemoteSnapshotTracker extends AbstractReindexComponent
{
private static Log logger = LogFactory.getLog(AVMRemoteSnapshotTracker.class);
private AVMService avmService;
private AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor;
public void setAvmService(AVMService avmService)
{
this.avmService = avmService;
}
public void setAvmSnapShotTriggeredIndexingMethodInterceptor(AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor)
{
this.avmSnapShotTriggeredIndexingMethodInterceptor = avmSnapShotTriggeredIndexingMethodInterceptor;
}
@Override
protected void reindexImpl()
{
processStores();
}
/**
* Loop throught the avm stores and compare the latest snapshot to that in the index.
* Update the index if it has fallen behind.
*
*/
private void processStores()
{
List<AVMStoreDescriptor> stores = avmService.getStores();
if (stores.size() == 0)
{
return;
}
boolean upToDate;
do
{
upToDate = true;
for (AVMStoreDescriptor store : stores)
{
if (isShuttingDown())
{
break;
}
int current = avmService.getLatestSnapshotID(store.getName());
int lastIndexed = avmSnapShotTriggeredIndexingMethodInterceptor.getLastIndexedSnapshot(store.getName());
if (lastIndexed < current)
{
if(logger.isDebugEnabled())
{
logger.debug("Updating index for store "+store.getName()+" from snapshot "+lastIndexed+ " to "+current);
}
recoverSnapShot(store.getName(), lastIndexed, current);
upToDate = false;
}
}
}
while(!upToDate);
}
/**
* Do the index update in one lump (not individual snapshots)
*
* @param store
* @param lastIndexed
* @param current
*/
private void recoverSnapShot(final String store, final int lastIndexed, final int current)
{
RetryingTransactionCallback<Object> reindexWork = new RetryingTransactionCallback<Object>()
{
public Object execute() throws Exception
{
if(lastIndexed == -1)
{
avmSnapShotTriggeredIndexingMethodInterceptor.createIndex(store);
}
avmSnapShotTriggeredIndexingMethodInterceptor.indexSnapshot(store, lastIndexed, current);
return null;
}
};
transactionService.getRetryingTransactionHelper().doInTransaction(reindexWork, true);
}
}

View File

@@ -0,0 +1,206 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.node.index;
import javax.transaction.Status;
import javax.transaction.UserTransaction;
import org.alfresco.repo.content.ContentStore;
import org.alfresco.repo.node.db.NodeDaoService;
import org.alfresco.repo.search.AVMSnapShotTriggeredIndexingMethodInterceptor;
import org.alfresco.repo.search.Indexer;
import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.transaction.TransactionServiceImpl;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.BaseSpringTest;
/**
* Test that the index tracker catches up
*
* @author andyh
*/
public class AVMRemoteSnapshotTrackerTest extends BaseSpringTest
{
private AuthenticationComponent authenticationComponent;
private AVMService avmService;
private AVMSnapShotTriggeredIndexingMethodInterceptor avmSnapShotTriggeredIndexingMethodInterceptor;
private TransactionService transactionService;
private UserTransaction testTX;
private SearchService searchService;
private NodeService nodeService;
private FullTextSearchIndexer ftsIndexer;
private Indexer indexer;
private NodeDaoService nodeDaoService;
public AVMRemoteSnapshotTrackerTest()
{
// TODO Auto-generated constructor stub
}
@Override
protected void onSetUpInTransaction() throws Exception
{
super.onSetUpInTransaction();
ServiceRegistry serviceRegistry = (ServiceRegistry) applicationContext.getBean(ServiceRegistry.SERVICE_REGISTRY);
avmService = (AVMService) applicationContext.getBean("AVMService");
avmSnapShotTriggeredIndexingMethodInterceptor = (AVMSnapShotTriggeredIndexingMethodInterceptor) applicationContext.getBean("avmSnapShotTriggeredIndexingMethodInterceptor");
transactionService = (TransactionService) applicationContext.getBean("transactionComponent");
searchService = serviceRegistry.getSearchService();
nodeService = serviceRegistry.getNodeService();
ftsIndexer = (FullTextSearchIndexer) applicationContext.getBean("LuceneFullTextSearchIndexer");
indexer = (Indexer) applicationContext.getBean("indexerComponent");
nodeDaoService = (NodeDaoService) applicationContext.getBean("nodeDaoService");
testTX = transactionService.getUserTransaction();
testTX.begin();
authenticationComponent = (AuthenticationComponent) applicationContext.getBean("authenticationComponent");
authenticationComponent.setSystemUserAsCurrentUser();
}
@Override
protected void onTearDownInTransaction() throws Exception
{
if (testTX.getStatus() == Status.STATUS_ACTIVE)
{
testTX.rollback();
}
try
{
authenticationComponent.clearCurrentSecurityContext();
}
catch (Throwable e)
{
// do nothing
}
super.onTearDownInTransaction();
}
public void testCatchUp()
{
assertFalse(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("one"));
assertFalse(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("two"));
assertFalse(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("three"));
assertFalse(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("four"));
// initial state
avmService.createStore("one");
//assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("one"));
avmService.createDirectory("one:/", "a");
avmService.createSnapshot("one", null, null);
avmService.createStore("two");
avmService.createDirectory("two:/", "a");
avmService.createStore("three");
// Check state
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("one"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.isIndexUpToDate("one"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("two"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.isIndexUpToDate("two"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("three"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.isIndexUpToDate("three"));
assertFalse(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("four"));
// Disable the indexer and do updates
avmSnapShotTriggeredIndexingMethodInterceptor.setEnableIndexing(false);
// one unchanged
// two snap shot
avmService.createSnapshot("two", null, null);
// three update and snapshot
avmService.createDirectory("three:/", "a");
avmService.createSnapshot("three", null, null);
// four create
avmService.createStore("four");
avmService.createDirectory("four:/", "a");
avmService.createSnapshot("four", null, null);
avmService.createDirectory("four:/", "b");
avmService.createSnapshot("four", null, null);
//
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("one"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.isIndexUpToDate("one"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("two"));
assertFalse(avmSnapShotTriggeredIndexingMethodInterceptor.isIndexUpToDate("two"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("three"));
assertFalse(avmSnapShotTriggeredIndexingMethodInterceptor.isIndexUpToDate("three"));
assertFalse(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("four"));
assertFalse(avmSnapShotTriggeredIndexingMethodInterceptor.isIndexUpToDate("four"));
avmSnapShotTriggeredIndexingMethodInterceptor.setEnableIndexing(true);
AVMRemoteSnapshotTracker tracker = new AVMRemoteSnapshotTracker();
tracker.setAuthenticationComponent(authenticationComponent);
tracker.setAvmService(avmService);
tracker.setAvmSnapShotTriggeredIndexingMethodInterceptor(avmSnapShotTriggeredIndexingMethodInterceptor);
tracker.setTransactionService((TransactionServiceImpl) transactionService);
tracker.setFtsIndexer(ftsIndexer);
tracker.setIndexer(indexer);
tracker.setNodeDaoService(nodeDaoService);
tracker.setNodeService(nodeService);
tracker.setSearcher(searchService);
tracker.reindex();
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("one"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.isIndexUpToDate("one"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("two"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.isIndexUpToDate("two"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("three"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.isIndexUpToDate("three"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.hasIndexBeenCreated("four"));
assertTrue(avmSnapShotTriggeredIndexingMethodInterceptor.isIndexUpToDate("four"));
}
}

View File

@@ -469,6 +469,7 @@ public class AVMSnapShotTriggeredIndexingMethodInterceptor implements MethodInte
if (indexer instanceof AVMLuceneIndexer) if (indexer instanceof AVMLuceneIndexer)
{ {
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer; AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer) indexer;
avmIndexer.flushPending();
return avmIndexer.hasIndexBeenCreated(store); return avmIndexer.hasIndexBeenCreated(store);
} }
return false; return false;

View File

@@ -1545,16 +1545,30 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
} }
} }
public boolean hasIndexBeenCreated(String store) public boolean hasIndexBeenCreated(String store)
{ {
IndexReader mainReader = null; return hasIndexBeenCreatedimpl(store, IndexChannel.MAIN) || hasIndexBeenCreatedimpl(store, IndexChannel.DELTA);
}
public boolean hasIndexBeenCreatedimpl(String store, IndexChannel channel)
{
IndexReader reader = null;
try try
{ {
mainReader = getReader(); if (channel == IndexChannel.DELTA)
{
flushPending();
reader = getDeltaReader();
}
else
{
reader = getReader();
}
TermDocs termDocs = null; TermDocs termDocs = null;
try try
{ {
termDocs = mainReader.termDocs(new Term("ISROOT", "T")); termDocs = reader.termDocs(new Term("ISROOT", "T"));
return termDocs.next(); return termDocs.next();
} }
finally finally
@@ -1573,9 +1587,17 @@ public class AVMLuceneIndexerImpl extends AbstractLuceneIndexerImpl<String> impl
{ {
try try
{ {
if (mainReader != null)
if (reader != null)
{ {
mainReader.close(); if (channel == IndexChannel.DELTA)
{
closeDeltaReader();
}
else
{
reader.close();
}
} }
} }
catch (IOException e) catch (IOException e)

View File

@@ -35,7 +35,6 @@ import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.node.integrity.IntegrityChecker; import org.alfresco.repo.node.integrity.IntegrityChecker;
import org.alfresco.repo.search.impl.lucene.LuceneIndexerAndSearcher; import org.alfresco.repo.search.impl.lucene.LuceneIndexerAndSearcher;
import org.alfresco.service.cmr.rule.RuleService;
import org.alfresco.util.GUID; import org.alfresco.util.GUID;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -352,22 +351,13 @@ public abstract class AlfrescoTransactionSupport
} }
/** /**
* Flush in-transaction resources. A transaction must be active. * No-op
* <p>
* The flush may include:
* <ul>
* <li>{@link TransactionalDao#flush()}</li>
* <li>{@link RuleService#executePendingRules()}</li>
* <li>{@link IntegrityChecker#checkIntegrity()}</li>
* </ul>
* *
* @deprecated No longer does anything
*/ */
public static void flush() public static void flush()
{ {
// get transaction-local synchronization // No-op
TransactionSynchronizationImpl synch = getSynchronization();
// flush
synch.flush();
} }
/** /**
@@ -548,15 +538,6 @@ public abstract class AlfrescoTransactionSupport
return sb.toString(); return sb.toString();
} }
/**
* Performs the in-transaction flushing. Typically done during a transaction or
* before commit.
*/
public void flush()
{
throw new UnsupportedOperationException("Manual flush no longer supported.");
}
/** /**
* @see AlfrescoTransactionSupport#SESSION_SYNCHRONIZATION_ORDER * @see AlfrescoTransactionSupport#SESSION_SYNCHRONIZATION_ORDER
*/ */
@@ -589,7 +570,7 @@ public abstract class AlfrescoTransactionSupport
/** /**
* Pre-commit cleanup. * Pre-commit cleanup.
* <p> * <p>
* Ensures that the session resources are {@link #flush() flushed}. * Ensures that the session transaction listeners are property executed.
* The Lucene indexes are then prepared. * The Lucene indexes are then prepared.
*/ */
@Override @Override

View File

@@ -157,10 +157,6 @@ public class AlfrescoTransactionSupportTest extends TestCase
// register it // register it
AlfrescoTransactionSupport.bindListener(listener); AlfrescoTransactionSupport.bindListener(listener);
// test flush
AlfrescoTransactionSupport.flush();
assertTrue("flush not called on listener", strings.contains("flush"));
// test commit // test commit
txn.commit(); txn.commit();
assertTrue("beforeCommit not called on listener", strings.contains("beforeCommit")); assertTrue("beforeCommit not called on listener", strings.contains("beforeCommit"));

View File

@@ -34,11 +34,7 @@ package org.alfresco.repo.transaction;
public interface TransactionListener public interface TransactionListener
{ {
/** /**
* Allows the listener to flush any consuming resources. This mechanism is * @deprecated No longer supported
* used primarily during long-lived transactions to ensure that system resources
* are not used up.
* <p>
* This method must not be used for implementing business logic.
*/ */
void flush(); void flush();

View File

@@ -13,3 +13,4 @@ description=cm:description
multi-value-text=test:multi-value-text multi-value-text=test:multi-value-text
multi-value-node=test:multi-value-node multi-value-node=test:multi-value-node
complex-node=test:complex-node complex-node=test:complex-node
element-name=test:element-name

View File

@@ -11,3 +11,4 @@ description=/projectDescription/comment/text()
multi-value-text=/projectDescription/natures/nature/text() multi-value-text=/projectDescription/natures/nature/text()
multi-value-node=/projectDescription/natures/nature multi-value-node=/projectDescription/natures/nature
complex-node=/projectDescription/natures complex-node=/projectDescription/natures
element-name=name(/projectDescription)