Merged V3.2 to HEAD

17294: Fix for ETHREEOH-3194 - It's impossible to find Blogs and Discussions by title.
   17301: Activity Service fixes (ETHREEOH-1362 & ETHREEOH-1741)
   17302: Fix for ETHREEOH-2849 JPG to GIF transformation fails when using imagemagick cmd line options listed in our wiki
   17305: AVM - fix AVMStoreDescriptor ( creator/createDate) returned by getStores
   17306: Fix for ETHREEOH-1578 - Incorrect behavior of Calendar in Month view ...
   17318: Merged V3.1 to V3.2
      17317: Fix for ETHREEOH-3236 It is impossible to change start location, everything is reverted to My Alfresco
   17320: Merged V3.1 to V3.2
      17287 - Fix for ETHREEOH-110- It is impossible to browse events by tags
   17326: iBatis mapping fixes for AVM on Oracle (including ETHREEOH-3205)
   17327: Merged V3.1 to V3.2
      17324: Fix for ETHREEOH-2723 Script error appears when trying to edit Home Space Name for user
   17329: Merged V3.1 to V3.2
      17180: Merged V2.2 to V3.1
         17164: Fixes for deletion of large hierarchies: (ETHREEOH-2161 and ETHREEOH-2650)
         17179: (RECORD ONLY) Merged V3.1 to V2.2 ...
   17330: Fix for SiteActivityTest failure (caused by earlier -ve test data)
   17331: Merged V3.1 to V3.2
      17190: Further fixes for ETHREEOH-2161: Delete process hangs when deleting large directory structure (with rules applied)
      17207: Fix fallout from work on ETHREEOH-2161: Delete process hangs when deleting large directory structure (with rules applied)
      17215: Added back firing of policies for archive stores
   17351: Build fix check in to DBNodeService.    Will be followed by full fix when available.
   17353: Applied TransactionListenerAdapter
___________________________________________________________________
Modified: svn:mergeinfo
   Reverse-merged /alfresco/BRANCHES/V3.1:r13091
   Merged /alfresco/BRANCHES/V2.2:r13089,13091,14190-14191,14199,14210,14216,14229,14655,14825,14869,17164,17179
   Merged /alfresco/BRANCHES/V3.1:r17180,17190,17207,17215,17287,17317,17324
   Merged /alfresco/BRANCHES/V3.2:r17294,17301-17302,17305-17306,17318,17320,17326-17327,17329-17331,17351,17353


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18056 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2010-01-15 11:09:09 +00:00
parent 354faccbc3
commit e2fbd4a8de
24 changed files with 1671 additions and 1446 deletions

View File

@@ -1008,54 +1008,92 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
{
private NodeService nodeService;
private List<NodeRef> deletedNodeRefs;
private List<NodeRef> beforeDeleteNodeRefs;
public BadOnDeleteNodePolicy(NodeService nodeService, List<NodeRef> deletedNodeRefs)
private boolean onDeleteCreateChild = true;
public BadOnDeleteNodePolicy(NodeService nodeService,
List<NodeRef> beforeDeleteNodeRefs,
List<NodeRef> deletedNodeRefs)
{
this.nodeService = nodeService;
this.beforeDeleteNodeRefs = beforeDeleteNodeRefs;
this.deletedNodeRefs = deletedNodeRefs;
}
public void beforeDeleteNode(NodeRef nodeRef)
{
// add a new child to the child, i.e. just before it is deleted
ChildAssociationRef assocRef = nodeService.createNode(
// add the child to the list
beforeDeleteNodeRefs.add(nodeRef);
if(onDeleteCreateChild)
{
// add a new child to the child, i.e. just before it is deleted
ChildAssociationRef assocRef = nodeService.createNode(
nodeRef,
ASSOC_TYPE_QNAME_TEST_CHILDREN,
QName.createQName("pre-delete new child"),
ContentModel.TYPE_CONTAINER);
// set some child node properties
nodeService.setProperty(nodeRef, PROP_QNAME_BOOLEAN_VALUE, "true");
// add an aspect to the child
nodeService.addAspect(nodeRef, ASPECT_QNAME_TEST_TITLED, null);
// set some child node properties
nodeService.setProperty(nodeRef, PROP_QNAME_BOOLEAN_VALUE, "true");
// add an aspect to the child
nodeService.addAspect(nodeRef, ASPECT_QNAME_TEST_TITLED, null);
}
}
public void onDeleteNode(ChildAssociationRef childAssocRef, boolean isArchivedNode)
{
// add the child to the list
deletedNodeRefs.add(childAssocRef.getChildRef());
// now perform some nasties on the node's parent, i.e. add a new child
NodeRef parentRef = childAssocRef.getParentRef();
NodeRef childRef = childAssocRef.getChildRef();
ChildAssociationRef assocRef = nodeService.createNode(
if(onDeleteCreateChild)
{
// now perform some nasties on the node's parent, i.e. add a new child
NodeRef parentRef = childAssocRef.getParentRef();
NodeRef childRef = childAssocRef.getChildRef();
ChildAssociationRef assocRef = nodeService.createNode(
parentRef,
ASSOC_TYPE_QNAME_TEST_CHILDREN,
QName.createQName("post-delete new child"),
ContentModel.TYPE_CONTAINER);
}
}
private void setOnDeleteCreateChild(boolean onDeleteCreateChild)
{
this.onDeleteCreateChild = onDeleteCreateChild;
}
private boolean isOnDeleteCreateChild()
{
return onDeleteCreateChild;
}
}
public void testDelete() throws Exception
{
final List<NodeRef> beforeDeleteNodeRefs = new ArrayList<NodeRef>(5);
final List<NodeRef> deletedNodeRefs = new ArrayList<NodeRef>(5);
NodeServicePolicies.OnDeleteNodePolicy policy = new BadOnDeleteNodePolicy(nodeService, deletedNodeRefs);
BadOnDeleteNodePolicy nasty = new BadOnDeleteNodePolicy(nodeService, beforeDeleteNodeRefs, deletedNodeRefs);
nasty.setOnDeleteCreateChild(false);
NodeServicePolicies.OnDeleteNodePolicy policy = nasty;
// bind to listen to the deletion of a node
policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "onDeleteNode"),
policy,
new JavaBehaviour(policy, "onDeleteNode"));
policyComponent.bindClassBehaviour(
QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
policy,
new JavaBehaviour(policy, "beforeDeleteNode"));
// build the node and commit the node graph
Map<QName, ChildAssociationRef> assocRefs = buildNodeGraph(nodeService, rootNodeRef);
NodeRef n1Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "root_p_n1")).getChildRef();
@@ -1072,11 +1110,86 @@ public abstract class BaseNodeServiceTest extends BaseSpringTest
assertEquals("Node not cascade deleted", 0, countNodesByReference(n6Ref));
assertEquals("Node not cascade deleted", 0, countNodesByReference(n8Ref));
// check before delete delete policy has been called
assertTrue("n1Ref before delete policy not called", beforeDeleteNodeRefs.contains(n1Ref));
assertTrue("n3Ref before delete policy not called", beforeDeleteNodeRefs.contains(n3Ref));
assertTrue("n6Ref before delete policy not called", beforeDeleteNodeRefs.contains(n6Ref));
assertTrue("n8Ref before delete policy not called", beforeDeleteNodeRefs.contains(n8Ref));
// check delete policy has been called
assertTrue("n1Ref delete policy not called", deletedNodeRefs.contains(n1Ref));
assertTrue("n3Ref delete policy not called", deletedNodeRefs.contains(n3Ref));
assertTrue("n6Ref delete policy not called", deletedNodeRefs.contains(n6Ref));
assertTrue("n8Ref delete policy not called", deletedNodeRefs.contains(n8Ref));
// commit to check
setComplete();
endTransaction();
}
// /**
// * This test is similar to the test above but the delete policies do nasty stuff such as
// * creating children of the soon to be deleted children.
// *
// * In particular, it verifies that we don't get stuck in an infinite loop.
// * @throws Exception
// */
// public void testDeleteWithBadlyBehavedPolicies() throws Exception
// {
// try
// {
// final List<NodeRef> beforeDeleteNodeRefs = new ArrayList<NodeRef>(5);
// final List<NodeRef> deletedNodeRefs = new ArrayList<NodeRef>(5);
//
// BadOnDeleteNodePolicy nasty = new BadOnDeleteNodePolicy(nodeService, beforeDeleteNodeRefs, deletedNodeRefs);
// nasty.setOnDeleteCreateChild(true);
// NodeServicePolicies.OnDeleteNodePolicy policy = nasty;
//
// // bind to listen to the deletion of a node
// policyComponent.bindClassBehaviour(
// QName.createQName(NamespaceService.ALFRESCO_URI, "onDeleteNode"),
// policy,
// new JavaBehaviour(policy, "onDeleteNode"));
//
// policyComponent.bindClassBehaviour(
// QName.createQName(NamespaceService.ALFRESCO_URI, "beforeDeleteNode"),
// policy,
// new JavaBehaviour(policy, "beforeDeleteNode"));
//
// // build the node and commit the node graph
// Map<QName, ChildAssociationRef> assocRefs = buildNodeGraph(nodeService, rootNodeRef);
// NodeRef n1Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "root_p_n1")).getChildRef();
// NodeRef n3Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "n1_p_n3")).getChildRef();
// NodeRef n4Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "n2_p_n4")).getChildRef();
// NodeRef n6Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "n3_p_n6")).getChildRef();
// NodeRef n8Ref = assocRefs.get(QName.createQName(BaseNodeServiceTest.NAMESPACE, "n6_p_n8")).getChildRef();
//
// // delete n1
// nodeService.deleteNode(n1Ref);
//
// // turn off nasty policy - may upset other tests
// nasty.setOnDeleteCreateChild(false);
//
// // Just a cut down set of tests to validate that something has happened, the real point of the test is to see how
// // the end of the transaction fails.
//
// assertEquals("Node not directly deleted", 0, countNodesByReference(n1Ref));
// assertTrue("n1Ref before delete policy not called", beforeDeleteNodeRefs.contains(n1Ref));
// assertTrue("n1Ref delete policy not called", deletedNodeRefs.contains(n1Ref));
//
// // commit to check
// setComplete();
// endTransaction();
// fail("test has not detected orphan children");
// }
// catch (Exception e)
// {
// // We expect to get here with this test.
// e.printStackTrace();
// }
// }
@SuppressWarnings("unchecked")
private int countChildrenOfNode(NodeRef nodeRef)
{

View File

@@ -42,12 +42,12 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.domain.Node;
import org.alfresco.repo.node.AbstractNodeServiceImpl;
import org.alfresco.repo.node.StoreArchiveMap;
import org.alfresco.repo.node.cleanup.AbstractNodeCleanupWorker;
import org.alfresco.repo.node.db.NodeDaoService.NodeRefQueryCallback;
import org.alfresco.repo.node.index.NodeIndexer;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.TransactionListener;
import org.alfresco.repo.transaction.TransactionListenerAdapter;
import org.alfresco.repo.transaction.TransactionalResourceHelper;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
@@ -94,13 +94,12 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
private NodeDaoService nodeDaoService;
private StoreArchiveMap storeArchiveMap;
private NodeService avmNodeService;
private NodeIndexer nodeIndexer;
private boolean cascadeInTransaction;
private NodeIndexer nodeIndexer;
private final static String KEY_PRE_COMMIT_ADD_NODE = "DbNodeServiceImpl.PreCommitAddNode";
public DbNodeServiceImpl()
{
storeArchiveMap = new StoreArchiveMap(); // in case it is not set
cascadeInTransaction = true;
}
public void setNodeDaoService(NodeDaoService nodeDaoService)
@@ -128,15 +127,11 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
}
/**
* Set whether store delete and archive operations must cascade to all children
* in the same transaction.
*
* @param cascadeInTransaction <tt>true</tt> (default) to cascade during
* delete and archive
* @deprecated the functionality did not see wide enough usage to warrant the maintenance
*/
public void setCascadeInTransaction(boolean cascadeInTransaction)
{
this.cascadeInTransaction = cascadeInTransaction;
logger.warn("NodeService property 'cascadeInTransaction' is no longer available.");
}
/**
@@ -339,12 +334,81 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
addMissingAspects(childNodePair, propertiesBefore, propertiesAfter);
addMissingAspects(parentNodePair, assocTypeQName);
/**
* track new node ref so we can validate its path.
*
* it may be valid now, but who knows what will happen between
* now and commit!
*/
trackNewNodeRef(childAssocRef.getChildRef());
// Index
nodeIndexer.indexCreateNode(childAssocRef);
// done
return childAssocRef;
}
/**
* Track a new node ref so we can validate its path at commit time.
*
* It may have a valid path now, but who knows what will happen between
* now and commit!
*
* @param newNodeRef the node to track
*/
private void trackNewNodeRef(NodeRef newNodeRef)
{
// // bind a pre-commit listener to validate any new node associations
// Set<NodeRef> newNodes = TransactionalResourceHelper.getSet(KEY_PRE_COMMIT_ADD_NODE);
// if (newNodes.size() == 0)
// {
// PreCommitNewNodeListener listener = new PreCommitNewNodeListener();
// AlfrescoTransactionSupport.bindListener(listener);
// }
// newNodes.add(newNodeRef);
}
/**
* loose interest in tracking a node ref
*
* for example if its been deleted or moved
* @param nodeRef the node ref to untrack
*/
private void untrackNodeRef(NodeRef nodeRef)
{
// Set<NodeRef> newNodes = TransactionalResourceHelper.getSet(KEY_PRE_COMMIT_ADD_NODE);
// if (newNodes.size() > 0)
// {
// newNodes.remove(nodeRef);
// }
}
private class PreCommitNewNodeListener extends TransactionListenerAdapter
{
@Override
public void beforeCommit(boolean readOnly)
{
if (readOnly)
{
return;
}
Set<NodeRef> nodeRefs = TransactionalResourceHelper.getSet(KEY_PRE_COMMIT_ADD_NODE);
// for (NodeRef nodeRef : nodeRefs)
// {
// // Need to check for exists the node may be created
// // and deleted within the same transaction
// if(exists(nodeRef))
// {
// System.out.println("Checking bideRef " + nodeRef);
// // Check that the primary path is valid for this node
// getPaths(nodeRef, false);
// }
// }
nodeRefs.clear();
}
}
/**
* Adds all the default aspects and properties required for the given type.
@@ -798,10 +862,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
invokeBeforeDeleteNode(nodeRef);
// Cascade delecte as required
if (cascadeInTransaction)
{
deletePrimaryChildrenNotArchived(nodePair, true);
}
deletePrimaryChildrenNotArchived(nodePair);
// perform a normal deletion
nodeDaoService.deleteNode(nodeId);
// Invoke policy behaviours
@@ -820,17 +881,18 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
*/
archiveNode(nodeRef, archiveStoreRef);
}
// remove the deleted node from the list of new nodes
untrackNodeRef(nodeRef);
}
/**
* delete primary children - private method for deleteNode.
*
* recurses through children when deleting a node. Does not archive.
*
* @param nodePair
* @param cascade
*/
private void deletePrimaryChildrenNotArchived(Pair<Long, NodeRef> nodePair, boolean cascade)
private void deletePrimaryChildrenNotArchived(Pair<Long, NodeRef> nodePair)
{
Long nodeId = nodePair.getFirst();
// Get the node's primary children
@@ -859,10 +921,10 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
};
// Get all the QNames to remove
nodeDaoService.getPrimaryChildAssocs(nodeId, callback);
// Each child must be deleted
for (Pair<Long, NodeRef> childNodePair : childNodePairs)
{
nodeDaoService.getPrimaryChildAssocs(nodeId, callback);
// Each child must be deleted
for (Pair<Long, NodeRef> childNodePair : childNodePairs)
{
// Fire node policies. This ensures that each node in the hierarchy gets a notification fired.
Long childNodeId = childNodePair.getFirst();
NodeRef childNodeRef = childNodePair.getSecond();
@@ -872,16 +934,16 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
invokeBeforeDeleteNode(childNodeRef);
// Cascade first, if required.
// Cascade first
// This ensures that the beforeDelete policy is fired for all nodes in the hierarchy before
// the actual delete starts.
if (cascade)
{
deletePrimaryChildrenNotArchived(childNodePair, true);
}
deletePrimaryChildrenNotArchived(childNodePair);
// Delete the child
nodeDaoService.deleteNode(childNodeId);
invokeOnDeleteNode(childParentAssocRef, childNodeType, childNodeQNames, false);
// loose interest in tracking this node ref
untrackNodeRef(childNodeRef);
}
}
@@ -2197,12 +2259,8 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
invokeOnMoveNode(oldParentAssocRef, newParentAssocRef);
}
// If we have to cascade in the transaction, then pull the children over to the new store
if (cascadeInTransaction)
{
// Pull children to the new store
pullNodeChildrenToSameStore(newNodeToMovePair, true, true);
}
// Pull children to the new store
pullNodeChildrenToSameStore(newNodeToMovePair, true);
// Done
return newParentAssocRef;
@@ -2231,7 +2289,7 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
* do not need to be remade. If the children are in the same store, only the <code>indexChildren</code>
* value is needed.
*/
private void pullNodeChildrenToSameStore(Pair<Long, NodeRef> nodePair, boolean cascade, boolean indexChildren)
private void pullNodeChildrenToSameStore(Pair<Long, NodeRef> nodePair, boolean indexChildren)
{
Long nodeId = nodePair.getFirst();
NodeRef nodeRef = nodePair.getSecond();
@@ -2291,7 +2349,6 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
// Index
if (indexChildren)
{
nodeIndexer.indexDeleteNode(oldParentAssocPair.getSecond());
nodeIndexer.indexCreateNode(newParentAssocPair.getSecond());
}
else
@@ -2302,11 +2359,8 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
// Fire node policies. This ensures that each node in the hierarchy gets a notification fired.
invokeOnDeleteNode(oldParentAssocPair.getSecond(), childNodeTypeQName, childNodeAspectQNames, true);
invokeOnCreateNode(newParentAssocPair.getSecond());
// Cascade, if required
if (cascade)
{
pullNodeChildrenToSameStore(newChildNodePair, cascade, indexChildren);
}
// Cascade
pullNodeChildrenToSameStore(newChildNodePair, indexChildren);
}
}
@@ -2418,107 +2472,4 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
nodeDaoService.setChildNameUnique(assocId, newName);
}
}
public static class MoveChildrenToCorrectStore extends AbstractNodeCleanupWorker
{
@Override
protected List<String> doCleanInternal() throws Throwable
{
return dbNodeService.moveChildrenToCorrectStore();
}
};
private List<String> moveChildrenToCorrectStore()
{
List<String> results = new ArrayList<String>(1000);
// Repeat the process for each store
List<Pair<Long, StoreRef>> storePairs = nodeDaoService.getStores();
for (Pair<Long, StoreRef> storePair : storePairs)
{
List<String> storeResults = moveChildrenToCorrectStore(storePair.getFirst());
results.addAll(storeResults);
}
return results;
}
private List<String> moveChildrenToCorrectStore(final Long storeId)
{
final List<Pair<Long, NodeRef>> parentNodePairs = new ArrayList<Pair<Long, NodeRef>>(100);
final NodeRefQueryCallback callback = new NodeRefQueryCallback()
{
public boolean handle(Pair<Long, NodeRef> nodePair)
{
parentNodePairs.add(nodePair);
return true;
}
};
RetryingTransactionCallback<Object> getNodesCallback = new RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
nodeDaoService.getNodesWithChildrenInDifferentStore(storeId, Long.MIN_VALUE, 100, callback);
// Done
return null;
}
};
transactionService.getRetryingTransactionHelper().doInTransaction(getNodesCallback, true, true);
// Process the nodes in random order
Collections.shuffle(parentNodePairs);
// Iterate and operate
List<String> results = new ArrayList<String>(100);
for (final Pair<Long, NodeRef> parentNodePair : parentNodePairs)
{
RetryingTransactionCallback<String> fixNodesCallback = new RetryingTransactionCallback<String>()
{
public String execute() throws Throwable
{
// Pull the children to the same store with full indexing - but don't cascade.
pullNodeChildrenToSameStore(parentNodePair, true, true);
// Done
return null;
}
};
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
txnHelper.setMaxRetries(1);
try
{
txnHelper.doInTransaction(fixNodesCallback, false, true);
String msg =
"Moved child nodes to parent node's store: \n" +
" Parent node: " + parentNodePair.getFirst();
results.add(msg);
}
catch (Throwable e)
{
String msg =
"Failed to move child nodes to parent node's store." +
" Set log level to WARN for this class to get exception log: \n" +
" Parent node: " + parentNodePair.getFirst() + "\n" +
" Error: " + e.getMessage();
// It failed; do a full log in WARN mode
if (logger.isWarnEnabled())
{
logger.warn(msg, e);
}
else
{
logger.error(msg);
}
results.add(msg);
}
}
// Done
if (logger.isDebugEnabled())
{
StringBuilder sb = new StringBuilder(256);
sb.append("Moved children to correct stores: \n")
.append(" Results:\n");
for (String msg : results)
{
sb.append(" ").append(msg).append("\n");
}
logger.debug(sb.toString());
}
return results;
}
}

View File

@@ -38,8 +38,6 @@ import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.node.BaseNodeServiceTest;
import org.alfresco.repo.node.StoreArchiveMap;
import org.alfresco.repo.node.cleanup.NodeCleanupRegistry;
import org.alfresco.repo.node.db.NodeDaoService.NodePropertyHandler;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
@@ -50,7 +48,6 @@ import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.MLText;
import org.alfresco.service.cmr.repository.NodeRef;
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.RegexQNamePattern;
import org.alfresco.service.transaction.TransactionService;
@@ -73,7 +70,6 @@ public class DbNodeServiceImplTest extends BaseNodeServiceTest
{
// Force cascading
DbNodeServiceImpl dbNodeServiceImpl = (DbNodeServiceImpl) applicationContext.getBean("dbNodeServiceImpl");
dbNodeServiceImpl.setCascadeInTransaction(true);
return (NodeService) applicationContext.getBean("dbNodeService");
}
@@ -402,49 +398,6 @@ public class DbNodeServiceImplTest extends BaseNodeServiceTest
nodeService.deleteNode(nodeRef);
}
public void testCleanup() throws Exception
{
@SuppressWarnings("unchecked")
StoreArchiveMap storeArchiveMap = (StoreArchiveMap) applicationContext.getBean("storeArchiveMap");
DbNodeServiceImpl ns = (DbNodeServiceImpl) applicationContext.getBean("dbNodeServiceImpl");
ns.setCascadeInTransaction(false);
NodeRef parentNodeRef = nodeService.createNode(
rootNodeRef,
ASSOC_TYPE_QNAME_TEST_CHILDREN,
QName.createQName(NAMESPACE, this.getName()),
ContentModel.TYPE_FOLDER).getChildRef();
NodeRef childNodeRef = nodeService.createNode(
parentNodeRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName(NAMESPACE, this.getName()),
ContentModel.TYPE_FOLDER).getChildRef();
// Ensure that the archive feature is enabled
StoreRef archiveStoreRef = ns.createStore("test", getName() + "-" + System.currentTimeMillis());
storeArchiveMap.put(parentNodeRef.getStoreRef(), archiveStoreRef);
// Delete parent. Cascade is OFF, so children should be left in their current store.
ns.deleteNode(parentNodeRef);
// Check that the node n1 is in the archive store
assertFalse("Parent should be deleted", ns.exists(parentNodeRef));
NodeRef parentArchiveRef = new NodeRef(archiveStoreRef, parentNodeRef.getId());
assertTrue("Parent should be in the archive store", ns.exists(parentArchiveRef));
// Force a commit here
setComplete();
endTransaction();
NodeCleanupRegistry nodeCleanupRegistry = new NodeCleanupRegistry();
DbNodeServiceImpl.MoveChildrenToCorrectStore worker = new DbNodeServiceImpl.MoveChildrenToCorrectStore();
worker.setTransactionService(transactionService);
worker.setDbNodeService(ns);
worker.setNodeDaoService(nodeDaoService);
// Run cleanup
worker.doClean();
}
/**
* Adds a property to a node and checks that it can be found using the low-level DB query
*/

View File

@@ -357,6 +357,8 @@ public interface NodeDaoService
* @param minNodeId the min node ID to return
* @param count the maximum number of results
* @param resultsCallback the node callback
*
* @deprecated Since 2.2SP6, 3.1SP2, 3.2: not performant and not relevant to any use-cases
*/
@DirtySessionAnnotation(markDirty=false)
public void getNodesWithChildrenInDifferentStore(

View File

@@ -3232,6 +3232,9 @@ public class HibernateNodeDaoServiceImpl
// Done
}
/**
* @deprecated Not performant. Do not use.
*/
public void getNodesWithChildrenInDifferentStore(
final Long storeId,
final Long minNodeId,