Merged HEAD-BUG-FIX (5.1/Cloud) to HEAD (5.1/Cloud)

99766: Merged 5.0.N (5.0.2) to HEAD-BUG-FIX (5.1/Cloud)
      99697: Merged V4.2-BUG-FIX (4.2.5) to 5.0.N (5.0.2)
         99632: Merged V4.1-BUG-FIX (4.1.10) to V4.2-BUG-FIX (4.2.5)
            99437: MNT-11219 and MNT-13533: Merged DEV. V4.1-BUG-FIX (4.1.10) to V4.1-BUG-FIX (4.1.10):
                98490: MNT-11219: Incorrect behavior during alternate replication from multiple repositories.
                    - Pruning has been changed to be done for 'manifestRepositoryId' instead of 'fromRepositoryId', to avoid removals for repositories for which replication has not been initiated. Also the calculation of invasions has been modified to take into account the situation, when the folder is invaded only by one repository (by the source repository, from which this folder has come; MNT-11219). Additionally, the 'expectedChildNodeRefs' initialization was modified to resolve nodes from another repository by path, to avoid comparison of NodeRefs of two different repositories. This modification removes redundant and dangerous pruning. And it is needed for both MNT-11219 and MNT-13533


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@100493 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Alan Davis
2015-03-27 22:56:27 +00:00
parent 783c24a2a5
commit accd81fc21
4 changed files with 427 additions and 55 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2010 Alfresco Software Limited. * Copyright (C) 2005-2015 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -19,9 +19,13 @@
package org.alfresco.repo.transfer; package org.alfresco.repo.transfer;
import java.io.File; import java.io.File;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import javax.transaction.UserTransaction; import javax.transaction.UserTransaction;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode; import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode;
import org.alfresco.repo.transfer.manifest.TransferManifestHeader; import org.alfresco.repo.transfer.manifest.TransferManifestHeader;
@@ -30,6 +34,7 @@ import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode;
import org.alfresco.repo.transfer.manifest.TransferManifestProcessor; import org.alfresco.repo.transfer.manifest.TransferManifestProcessor;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
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.transfer.TransferException; import org.alfresco.service.cmr.transfer.TransferException;
import org.alfresco.service.cmr.transfer.TransferProgress; import org.alfresco.service.cmr.transfer.TransferProgress;
import org.alfresco.service.cmr.transfer.TransferReceiver; import org.alfresco.service.cmr.transfer.TransferReceiver;
@@ -270,4 +275,40 @@ public abstract class AbstractManifestProcessorBase implements TransferManifestP
{ {
receiver.getProgressMonitor().logMoved(transferId, sourceNode, destNode, oldPath, newParent, newPath); receiver.getProgressMonitor().logMoved(transferId, sourceNode, destNode, oldPath, newParent, newPath);
} }
/**
* Puts information about current <code>childRef</code> and its <code>parentRef</code> into log in TRACE level. Information includes 'name', 'fromRepositoryId', 'aliened' and
* 'invadedBy' properties. Additionally, collects the same information for children of <code>childRef</code>
*
* @param parentRef - {@link NodeRef} instance of child node
* @param childRef - {@link NodeRef} instance of parent of the <code>childRef</code>
* @param nodeService - {@link NodeService} instance to get properties and checking other states
* @param log - {@link Log} instance to put log for appropriate class
*/
protected void logInvasionHierarchy(NodeRef parentRef, NodeRef childRef, NodeService nodeService, Log log)
{
Map<QName, Serializable> properties = nodeService.getProperties(childRef);
Map<QName, Serializable> parentProperties = nodeService.getProperties(parentRef);
StringBuilder message = new StringBuilder("Information about '").append(properties.get(ContentModel.PROP_NAME)).append("' node:\n fromRepositoryId: ").append(
properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)).append("\n").append(" invadedBy: ").append(properties.get(TransferModel.PROP_INVADED_BY)).append("\n")
.append(" alien: ").append(nodeService.hasAspect(childRef, TransferModel.ASPECT_ALIEN)).append("\n").append(" repositoryId: ").append(
properties.get(TransferModel.PROP_REPOSITORY_ID)).append("\n").append(" parent: ").append(parentProperties.get(ContentModel.PROP_NAME)).append("(")
.append(parentProperties.get(TransferModel.PROP_FROM_REPOSITORY_ID)).append(")").append(parentProperties.get(TransferModel.PROP_INVADED_BY)).append(": ").append(
nodeService.hasAspect(parentRef, TransferModel.ASPECT_ALIEN)).append("\n").append(" children:\n");
List<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(childRef);
if ((null != childAssocs) && !childAssocs.isEmpty())
{
for (ChildAssociationRef child : childAssocs)
{
properties = nodeService.getProperties(child.getChildRef());
message.append(" ").append(properties.get(ContentModel.PROP_NAME)).append("(").append(properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)).append(")")
.append(properties.get(TransferModel.PROP_INVADED_BY)).append(": ").append(nodeService.hasAspect(child.getChildRef(), TransferModel.ASPECT_ALIEN)).append(
"\n");
}
}
log.trace(message.toString());
}
} }

View File

@@ -1,3 +1,21 @@
/*
* Copyright (C) 2005-2015 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.transfer; package org.alfresco.repo.transfer;
import java.io.Serializable; import java.io.Serializable;
@@ -5,14 +23,12 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Stack; import java.util.Stack;
import java.util.Vector; import java.util.Vector;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.node.NodeServicePolicies;
import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.policy.BehaviourFilter;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.Behaviour.NotificationFrequency;
import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -148,6 +164,45 @@ public class AlienProcessorImpl implements AlienProcessor
currentAssoc = null; currentAssoc = null;
} }
} }
if (log.isTraceEnabled())
{
logInvasionHierarchy(childAssocRef.getParentRef(), childAssocRef.getChildRef());
}
}
/**
* Puts information about current <code>childRef</code> and its <code>parentRef</code> into log in TRACE level. Information includes 'name', 'fromRepositoryId', 'aliened' and
* 'invadedBy' properties. Additionally, collects the same information for children of <code>childRef</code>
*
* @param parentRef - {@link NodeRef} instance of child node
* @param childRef - {@link NodeRef} instance of parent of the <code>childRef</code>
*/
protected void logInvasionHierarchy(NodeRef parentRef, NodeRef childRef)
{
Map<QName, Serializable> properties = nodeService.getProperties(childRef);
Map<QName, Serializable> parentProperties = nodeService.getProperties(parentRef);
StringBuilder message = new StringBuilder("Information about '").append(properties.get(ContentModel.PROP_NAME)).append("' node:\n fromRepositoryId: ").append(
properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)).append("\n").append(" invadedBy: ").append(properties.get(TransferModel.PROP_INVADED_BY)).append("\n")
.append(" alien: ").append(nodeService.hasAspect(childRef, TransferModel.ASPECT_ALIEN)).append("\n").append(" repositoryId: ").append(
properties.get(TransferModel.PROP_REPOSITORY_ID)).append("\n").append(" parent: ").append(parentProperties.get(ContentModel.PROP_NAME)).append("(")
.append(parentProperties.get(TransferModel.PROP_FROM_REPOSITORY_ID)).append(")").append(parentProperties.get(TransferModel.PROP_INVADED_BY)).append(": ").append(
nodeService.hasAspect(parentRef, TransferModel.ASPECT_ALIEN)).append("\n").append(" children:\n");
List<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(childRef);
if ((null != childAssocs) && !childAssocs.isEmpty())
{
for (ChildAssociationRef child : childAssocs)
{
properties = nodeService.getProperties(child.getChildRef());
message.append(" ").append(properties.get(ContentModel.PROP_NAME)).append("(").append(properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)).append(")")
.append(properties.get(TransferModel.PROP_INVADED_BY)).append(": ").append(nodeService.hasAspect(child.getChildRef(), TransferModel.ASPECT_ALIEN)).append(
"\n");
}
}
log.trace(message.toString());
} }
public void beforeDeleteAlien(NodeRef deletedNodeRef, ChildAssociationRef oldAssoc) public void beforeDeleteAlien(NodeRef deletedNodeRef, ChildAssociationRef oldAssoc)
@@ -555,24 +610,71 @@ public class AlienProcessorImpl implements AlienProcessor
*/ */
NodeRef currentNodeRef = nodesToPrune.pop(); NodeRef currentNodeRef = nodesToPrune.pop();
Map<QName, Serializable> properties = null;
if (log.isDebugEnabled())
{
properties = nodeService.getProperties(currentNodeRef);
}
if (log.isDebugEnabled())
{
log.debug("Current nodeRef (name: \"" + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)
+ "\", manifestId: \"" + fromRepositoryId + "\")" + currentNodeRef);
}
log.debug("pruneNode:" + currentNodeRef); log.debug("pruneNode:" + currentNodeRef);
if(getNodeService().hasAspect(currentNodeRef, TransferModel.ASPECT_ALIEN)) if(getNodeService().hasAspect(currentNodeRef, TransferModel.ASPECT_ALIEN))
{ {
if (log.isDebugEnabled())
{
log.debug("Current nodeRef has ASPECT_ALIEN (name: \"" + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \""
+ properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + "\", manifestId: \"" + fromRepositoryId + "\")");
}
// Yes this is an alien node // Yes this is an alien node
List<String>invadedBy = (List<String>)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_INVADED_BY); List<String> invadedBy = (List<String>)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_INVADED_BY);
if(invadedBy.contains(fromRepositoryId)) String initialRepoId = (String) getNodeService().getProperty(currentNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID);
if (log.isDebugEnabled())
{ {
log.debug("Current nodeRef has PROP_INVADED_BY (name: \"" + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \""
+ properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + "\", manifestId: \"" + fromRepositoryId + "\"): " + invadedBy);
}
if ((null != invadedBy) && invadedBy.contains(fromRepositoryId))
{
if (log.isDebugEnabled())
{
log.debug("Current nodeRef's PROP_INVADED_BY contains current manifestId (name: \"" + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \""
+ properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + "\", manifestId: \"" + fromRepositoryId + "\")");
}
// Yes we are invaded by fromRepositoryId // Yes we are invaded by fromRepositoryId
if(invadedBy.size() == 1) if ((1 == invadedBy.size()) && fromRepositoryId.equalsIgnoreCase(initialRepoId))
{ {
if (log.isDebugEnabled())
{
log
.debug("Current nodeRef has only 1 element in PROP_INVADED_BY. Also MANIFEST_ID and INITIAL_REPOSITORY_ID are the same. Deleting the node... (name: \""
+ properties.get(ContentModel.PROP_NAME)
+ "\", fromRepositoryId: \""
+ properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)
+ "\", manifestId: \"" + fromRepositoryId + "\")");
}
// we are invaded by a single repository which must be fromRepositoryId // we are invaded by a single repository which must be fromRepositoryId
log.debug("pruned - deleted node:" + currentNodeRef);
getNodeService().deleteNode(currentNodeRef); getNodeService().deleteNode(currentNodeRef);
} }
else else
{ {
log.debug("folder has multiple invaders"); if (log.isDebugEnabled())
{
log.debug("Current 'nodeRef' has more than 1 element in PROP_INVADED_BY. Adding its children to 'nodesToPrune' list... (name: \""
+ properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)
+ "\", manifestId: \"" + fromRepositoryId + "\")");
}
// multiple invasion - so it must be a folder // multiple invasion - so it must be a folder
List<ChildAssociationRef> refs = nodeService.getChildAssocsByPropertyValue(currentNodeRef, TransferModel.PROP_INVADED_BY, fromRepositoryId); List<ChildAssociationRef> refs = nodeService.getChildAssocsByPropertyValue(currentNodeRef, TransferModel.PROP_INVADED_BY, fromRepositoryId);
for(ChildAssociationRef ref : refs) for(ChildAssociationRef ref : refs)
@@ -589,12 +691,24 @@ public class AlienProcessorImpl implements AlienProcessor
*/ */
if(!foldersToRecalculate.contains(currentNodeRef)) if(!foldersToRecalculate.contains(currentNodeRef))
{ {
if (log.isDebugEnabled())
{
log.debug("Current 'nodeRef' is not in 'foldersToRecalculate' list. Adding it to the list... (name: \"" + properties.get(ContentModel.PROP_NAME)
+ "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + "\", manifestId: \"" + fromRepositoryId + "\")");
}
foldersToRecalculate.push(currentNodeRef); foldersToRecalculate.push(currentNodeRef);
} }
} }
} }
else else
{ {
if (log.isDebugEnabled())
{
log.debug("Current \"nodeRef\"'s PROP_INVADED_BY does not contain current 'manifestId' (name: \"" + properties.get(ContentModel.PROP_NAME)
+ "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + "\", manifestId: \"" + fromRepositoryId + "\")");
}
/** /**
* Current node has been invaded by another repository * Current node has been invaded by another repository
* *
@@ -602,10 +716,15 @@ public class AlienProcessorImpl implements AlienProcessor
*/ */
getNodeService().hasAspect(currentNodeRef, TransferModel.ASPECT_TRANSFERRED); getNodeService().hasAspect(currentNodeRef, TransferModel.ASPECT_TRANSFERRED);
{ {
String fromRepoId = (String)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID); if(fromRepositoryId.equalsIgnoreCase(initialRepoId))
if(fromRepositoryId.equalsIgnoreCase(fromRepoId)) {
if (log.isDebugEnabled())
{ {
log.debug("folder is from the transferring repository"); log.debug("folder is from the transferring repository");
log.debug("Current nodeRef has more than 1 element in PROP_INVADED_BY. Adding its children to 'nodesToPrune' list... (name: \""
+ properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)
+ "\", manifestId: \"" + fromRepositoryId + "\")");
}
// invaded from somewhere else - so it must be a folder // invaded from somewhere else - so it must be a folder
List<ChildAssociationRef> refs = getNodeService().getChildAssocs(currentNodeRef); List<ChildAssociationRef> refs = getNodeService().getChildAssocs(currentNodeRef);
for(ChildAssociationRef ref : refs) for(ChildAssociationRef ref : refs)
@@ -621,6 +740,13 @@ public class AlienProcessorImpl implements AlienProcessor
*/ */
if(!foldersToRecalculate.contains(currentNodeRef)) if(!foldersToRecalculate.contains(currentNodeRef))
{ {
if (log.isDebugEnabled())
{
log.debug("Current 'nodeRef' is not in 'foldersToRecalculate' list. Adding it to the list... (name: \""
+ properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)
+ "\", manifestId: \"" + fromRepositoryId + "\")");
}
foldersToRecalculate.push(currentNodeRef); foldersToRecalculate.push(currentNodeRef);
} }
} }
@@ -633,11 +759,24 @@ public class AlienProcessorImpl implements AlienProcessor
// Current node does not contain alien nodes so it can be deleted. // Current node does not contain alien nodes so it can be deleted.
getNodeService().hasAspect(currentNodeRef, TransferModel.ASPECT_TRANSFERRED); getNodeService().hasAspect(currentNodeRef, TransferModel.ASPECT_TRANSFERRED);
{ {
String fromRepoId = (String)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID); if (log.isDebugEnabled())
if(fromRepositoryId.equalsIgnoreCase(fromRepoId))
{ {
log.debug("Current 'nodeRef' does not have ASPECT_ALIEN (name: \"" + properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \""
+ properties.get(TransferModel.PROP_FROM_REPOSITORY_ID) + "\", manifestId: \"" + fromRepositoryId + "\")");
}
String initialRepoId = (String) getNodeService().getProperty(currentNodeRef, TransferModel.PROP_REPOSITORY_ID);
if(fromRepositoryId.equalsIgnoreCase(initialRepoId))
{
if (log.isDebugEnabled())
{
log.debug("Current \"nodeRef\"'s has PROP_FROM_REPOSITORY_ID equal to current 'manifestId'. Deleting the node... (name: \""
+ properties.get(ContentModel.PROP_NAME) + "\", fromRepositoryId: \"" + properties.get(TransferModel.PROP_FROM_REPOSITORY_ID)
+ "\", manifestId: \"" + fromRepositoryId + "\")");
// we are invaded by a single repository // we are invaded by a single repository
log.debug("pruned - deleted non alien node:" + currentNodeRef); log.debug("pruned - deleted non alien node:" + currentNodeRef);
}
getNodeService().deleteNode(currentNodeRef); getNodeService().deleteNode(currentNodeRef);
} }
} }
@@ -745,44 +884,97 @@ public class AlienProcessorImpl implements AlienProcessor
*/ */
private boolean recalcInvasion(NodeRef folderNodeRef, String fromRepositoryId) private boolean recalcInvasion(NodeRef folderNodeRef, String fromRepositoryId)
{ {
List<String>folderInvadedBy = (List<String>)nodeService.getProperty(folderNodeRef, TransferModel.PROP_INVADED_BY); if (log.isTraceEnabled())
{
log.trace("#################");
log.trace("#RECALC INVASION#");
log.trace("#################");
}
List<String> folderInvadedBy = (List<String>)nodeService.getProperty(folderNodeRef, TransferModel.PROP_INVADED_BY);
if (log.isDebugEnabled())
{
log.debug("Node(" + nodeService.getProperty(folderNodeRef, ContentModel.PROP_NAME) + ")" + folderInvadedBy + ": checking '" + fromRepositoryId + "' id...");
}
boolean stillInvaded = false; boolean stillInvaded = false;
boolean hasAlienChild = false;
//TODO need a more efficient query here //TODO need a more efficient query here
List<ChildAssociationRef> refs = nodeService.getChildAssocs(folderNodeRef); List<ChildAssociationRef> refs = nodeService.getChildAssocs(folderNodeRef);
for(ChildAssociationRef ref : refs)
if (log.isDebugEnabled())
{
log.debug("Children count: " + refs.size());
log.debug("Is alien: " + nodeService.hasAspect(folderNodeRef, TransferModel.ASPECT_ALIEN));
}
String parentRepositoryId = (String) nodeService.getProperty(folderNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID);
for (ChildAssociationRef ref : refs)
{ {
NodeRef childNode = ref.getChildRef(); NodeRef childNode = ref.getChildRef();
List<String>childInvadedBy = (List<String>)getNodeService().getProperty(childNode, TransferModel.PROP_INVADED_BY);
if(childInvadedBy != null && childInvadedBy.contains(fromRepositoryId)) if (log.isTraceEnabled())
{ {
log.debug("folder is still invaded"); logInvasionHierarchy(folderNodeRef, childNode);
}
Map<QName, Serializable> properties = nodeService.getProperties(childNode);
List<String> childInvadedBy = (List<String>) properties.get(TransferModel.PROP_INVADED_BY);
String childRepositoryId = (String) properties.get(TransferModel.PROP_FROM_REPOSITORY_ID);
hasAlienChild = hasAlienChild || parentRepositoryId.equalsIgnoreCase(childRepositoryId);
if (!stillInvaded && (null != childInvadedBy) && (childInvadedBy.contains(fromRepositoryId) || fromRepositoryId.equalsIgnoreCase(childRepositoryId)))
{
if (log.isDebugEnabled())
{
log.debug("This child contains current 'fromRepositoryId'. Current folder is still invaded by this repository");
}
stillInvaded = true; stillInvaded = true;
break;
} }
} }
if(!stillInvaded) if (!stillInvaded)
{ {
if (log.isDebugEnabled())
{
log.debug("Current folder is not invaded by this repository. Updating 'invadedBy' property...");
log.debug("folder is no longer invaded by this repo:" + folderNodeRef); log.debug("folder is no longer invaded by this repo:" + folderNodeRef);
}
folderInvadedBy.remove(fromRepositoryId); folderInvadedBy.remove(fromRepositoryId);
if(folderInvadedBy.size() > 0) if (folderInvadedBy.size() > 0)
{ {
if(log.isDebugEnabled()) if (log.isDebugEnabled())
{ {
log.debug("Current folder HAS ANOTHER invasions. Updating the 'invadedBy' property...");
log.debug("still invaded by:" + folderInvadedBy); log.debug("still invaded by:" + folderInvadedBy);
} }
getNodeService().setProperty(folderNodeRef, TransferModel.PROP_INVADED_BY, (Serializable)folderInvadedBy);
getNodeService().setProperty(folderNodeRef, TransferModel.PROP_INVADED_BY, (Serializable) folderInvadedBy);
} }
else else if (!hasAlienChild)
{
if (log.isDebugEnabled())
{ {
log.debug("no longer alien:" + folderNodeRef); log.debug("no longer alien:" + folderNodeRef);
log.debug("This invasion was the last one for the current folder. Removing aspect 'ALIEN' completely...");
}
getNodeService().removeAspect(folderNodeRef, TransferModel.ASPECT_ALIEN); getNodeService().removeAspect(folderNodeRef, TransferModel.ASPECT_ALIEN);
} }
} }
if (log.isTraceEnabled())
{
log.trace("#################");
log.trace("# COMPLETED #");
log.trace("#################");
}
return stillInvaded; return stillInvaded;
} }

View File

@@ -215,6 +215,12 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
// Does a corresponding node exist in this repo? // Does a corresponding node exist in this repo?
if (resolvedNodes.resolvedChild != null) if (resolvedNodes.resolvedChild != null)
{ {
if (log.isTraceEnabled())
{
log.trace("REPO_PRIMARY_MANIFEST_PROCESSOR - node DOES exist!");
logInvasionHierarchy(resolvedNodes.resolvedParent, resolvedNodes.resolvedChild, nodeService, log);
}
// Yes, the corresponding node does exist. Update it. // Yes, the corresponding node does exist. Update it.
if (log.isDebugEnabled()) if (log.isDebugEnabled())
{ {
@@ -222,6 +228,11 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
+ resolvedNodes.resolvedChild); + resolvedNodes.resolvedChild);
} }
update(node, resolvedNodes, primaryParentAssoc); update(node, resolvedNodes, primaryParentAssoc);
if (log.isTraceEnabled())
{
log.trace("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
}
} }
else else
{ {
@@ -245,7 +256,19 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
{ {
log.debug("Incoming noderef has no corresponding local noderef: " + node.getNodeRef()); log.debug("Incoming noderef has no corresponding local noderef: " + node.getNodeRef());
} }
if (log.isTraceEnabled())
{
log.trace("REPO_PRIMARY_MANIFEST_PROCESSOR - node DOES NOT esist yet! Name: '" + node.getProperties().get(ContentModel.PROP_NAME) + "', parentPath: '"
+ node.getParentPath() + "'");
}
create(node, resolvedNodes, primaryParentAssoc); create(node, resolvedNodes, primaryParentAssoc);
if (log.isTraceEnabled())
{
log.trace("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
}
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2009-2010 Alfresco Software Limited. * Copyright (C) 2009-2015 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -16,18 +16,21 @@
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.alfresco.repo.transfer; package org.alfresco.repo.transfer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import org.alfresco.repo.transfer.CorrespondingNodeResolver.ResolvedParentChildPair;
import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode; import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode;
import org.alfresco.repo.transfer.manifest.TransferManifestHeader; import org.alfresco.repo.transfer.manifest.TransferManifestHeader;
import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode; import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode;
import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef;
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.Path;
import org.alfresco.service.cmr.transfer.TransferReceiver; import org.alfresco.service.cmr.transfer.TransferReceiver;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -103,15 +106,89 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor
//TODO Use more efficient query here. //TODO Use more efficient query here.
List<ChildAssociationRef> expectedChildren = node.getChildAssocs(); List<ChildAssociationRef> expectedChildren = node.getChildAssocs();
if (log.isDebugEnabled())
{
log.debug("Checking node in TERTIARY_MANIFEST_PROCESSOR");
}
if ((null != resolvedNodes.resolvedParent) && nodeService.exists(resolvedNodes.resolvedParent))
{
if (log.isTraceEnabled())
{
logInvasionHierarchy(resolvedNodes.resolvedParent, nodeRef, nodeService, log);
}
}
else
{
List<ChildAssociationRef> parentAssocs = nodeService.getParentAssocs(nodeRef);
if (log.isTraceEnabled())
{
logInvasionHierarchy(parentAssocs.iterator().next().getParentRef(), nodeRef, nodeService, log);
}
}
List<NodeRef> expectedChildNodeRefs = new ArrayList<NodeRef>(); List<NodeRef> expectedChildNodeRefs = new ArrayList<NodeRef>();
Set<Path> expectedChildNodePaths = new HashSet<Path>();
if (log.isDebugEnabled())
{
log.debug("Expected children:");
}
for(ChildAssociationRef ref : expectedChildren) for(ChildAssociationRef ref : expectedChildren)
{ {
if(log.isDebugEnabled()) if(log.isDebugEnabled())
{ {
log.debug("expecting child node" + ref); log.debug("Expecting child node " + ref);
}
NodeRef childRef = null;
if (nodeService.exists(ref.getChildRef()))
{
childRef = ref.getChildRef();
if (log.isTraceEnabled())
{
logInvasionHierarchy(nodeRef, ref.getChildRef(), nodeService, log);
}
}
else
{
Path parentPath = node.getParentPath();
parentPath = parentPath.subPath(0, (parentPath.size() - 1));
parentPath.append(new Path.ChildAssocElement(ref));
ResolvedParentChildPair resolvedChild = nodeResolver.resolveCorrespondingNode(ref.getChildRef(), ref, parentPath);
if (null != resolvedChild.resolvedChild)
{
childRef = resolvedChild.resolvedChild;
if (log.isDebugEnabled())
{
log.debug("The node has been RESOLVED!");
}
if (log.isTraceEnabled())
{
logInvasionHierarchy(resolvedChild.resolvedParent, resolvedChild.resolvedChild, nodeService, log);
}
}
else
{
if (log.isDebugEnabled())
{
log.debug("The node DOES NOT exist in current repository! Processing will be made by its PATH!");
}
expectedChildNodePaths.add(parentPath);
}
}
if (null != childRef)
{
expectedChildNodeRefs.add(childRef);
} }
expectedChildNodeRefs.add(ref.getChildRef());
} }
List<ChildAssociationRef> actualChildren = nodeService.getChildAssocs(nodeRef); List<ChildAssociationRef> actualChildren = nodeService.getChildAssocs(nodeRef);
@@ -119,19 +196,35 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor
/** /**
* For each actual child association * For each actual child association
*/ */
if (log.isDebugEnabled())
{
log.debug("Traversing ACTUAL children:");
}
for(ChildAssociationRef child : actualChildren) for(ChildAssociationRef child : actualChildren)
{ {
log.debug("checking child: " + child); log.debug("checking child: " + child);
if(child.isPrimary()) if(child.isPrimary())
{ {
if (log.isTraceEnabled())
{
logInvasionHierarchy(child.getParentRef(), child.getChildRef(), nodeService, log);
}
/** /**
* yes it is a primary assoc * yes it is a primary assoc
* should it be there ? * should it be there ?
*/ */
NodeRef childNodeRef = child.getChildRef(); NodeRef childNodeRef = child.getChildRef();
Path actualChildPath = nodeService.getPath(childNodeRef);
if(!expectedChildNodeRefs.contains(childNodeRef)) if(!expectedChildNodeRefs.contains(childNodeRef) && !expectedChildNodePaths.contains(actualChildPath))
{ {
if (log.isDebugEnabled())
{
log.debug("This child IS NOT EXPECTED!");
}
/** /**
* An unexpected child - if this node has been transferred then * An unexpected child - if this node has been transferred then
* it may need to be deleted. * it may need to be deleted.
@@ -143,10 +236,16 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor
{ {
log.debug("an unexpected transferred child node:" + child); log.debug("an unexpected transferred child node:" + child);
logComment("Transfer sync mode - checking unexpected child node:" + child); logComment("Transfer sync mode - checking unexpected child node:" + child);
String fromRepositoryId = (String)nodeService.getProperty(childNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID); String fromRepositoryId = (String) nodeService.getProperty(childNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID);
// Yes this is a transferred node. When syncing we only delete nodes that are "from" // Yes this is a transferred node. When syncing we only delete nodes that are "from"
// the system that is transferring to this repo. // the system that is transferring to this repo.
if (log.isDebugEnabled())
{
log.debug("'manifestRepositoryId': " + manifestRepositoryId);
}
if(fromRepositoryId != null && manifestRepositoryId != null) if(fromRepositoryId != null && manifestRepositoryId != null)
{ {
if(nodeService.hasAspect(childNodeRef, TransferModel.ASPECT_ALIEN)) if(nodeService.hasAspect(childNodeRef, TransferModel.ASPECT_ALIEN))
@@ -157,19 +256,36 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor
*/ */
log.debug("node to be deleted contains alien content so needs to be pruned." + childNodeRef); log.debug("node to be deleted contains alien content so needs to be pruned." + childNodeRef);
logComment("Transfer sync mode - node contains alien content so can't be deleted. " + childNodeRef); logComment("Transfer sync mode - node contains alien content so can't be deleted. " + childNodeRef);
alienProcessor.pruneNode(childNodeRef, fromRepositoryId); alienProcessor.pruneNode(childNodeRef, manifestRepositoryId);
} }
else else
{ {
// Node // Node
log.debug("node not alien"); if (log.isDebugEnabled())
if(manifestRepositoryId.equalsIgnoreCase(fromRepositoryId))
{ {
log.debug("Node not alien. Trying to delete the node...");
}
String initialRepositoryId = (String) nodeService.getProperty(childNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID);
if(manifestRepositoryId.equalsIgnoreCase(initialRepositoryId))
{
if (log.isDebugEnabled())
{
log.debug("Replication is initiated from the same repository from which this node was transferred! Deleting");
}
// Yes the manifest repository Id and the from repository Id match. // Yes the manifest repository Id and the from repository Id match.
// Destination node if from the transferring repo and needs to be deleted. // Destination node if from the transferring repo and needs to be deleted.
logDeleted(node.getNodeRef(), childNodeRef, nodeService.getPath(childNodeRef).toString()); logDeleted(node.getNodeRef(), childNodeRef, nodeService.getPath(childNodeRef).toString());
nodeService.deleteNode(childNodeRef); nodeService.deleteNode(childNodeRef);
log.debug("deleted node:" + childNodeRef); }
else
{
if (log.isDebugEnabled())
{
log
.debug("It is not an alien, but 'fromRepositoryId' is not equal to the 'manifestRepositoryId'! Cannot delete the foreign node...");
}
} }
} }
} }