From accd81fc21e3a65486255081ea143fcd25319b80 Mon Sep 17 00:00:00 2001 From: Alan Davis Date: Fri, 27 Mar 2015 22:56:27 +0000 Subject: [PATCH] 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 --- .../AbstractManifestProcessorBase.java | 43 ++- .../repo/transfer/AlienProcessorImpl.java | 272 +++++++++++++++--- .../RepoPrimaryManifestProcessorImpl.java | 23 ++ .../RepoTertiaryManifestProcessorImpl.java | 144 +++++++++- 4 files changed, 427 insertions(+), 55 deletions(-) diff --git a/source/java/org/alfresco/repo/transfer/AbstractManifestProcessorBase.java b/source/java/org/alfresco/repo/transfer/AbstractManifestProcessorBase.java index 6b01a8e6a6..40e0de4cc9 100644 --- a/source/java/org/alfresco/repo/transfer/AbstractManifestProcessorBase.java +++ b/source/java/org/alfresco/repo/transfer/AbstractManifestProcessorBase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2010 Alfresco Software Limited. + * Copyright (C) 2005-2015 Alfresco Software Limited. * * This file is part of Alfresco * @@ -19,9 +19,13 @@ package org.alfresco.repo.transfer; import java.io.File; +import java.io.Serializable; +import java.util.List; +import java.util.Map; import javax.transaction.UserTransaction; +import org.alfresco.model.ContentModel; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode; 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.service.cmr.repository.ChildAssociationRef; 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.TransferProgress; 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); } + + /** + * Puts information about current childRef and its parentRef into log in TRACE level. Information includes 'name', 'fromRepositoryId', 'aliened' and + * 'invadedBy' properties. Additionally, collects the same information for children of childRef + * + * @param parentRef - {@link NodeRef} instance of child node + * @param childRef - {@link NodeRef} instance of parent of the childRef + * @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 properties = nodeService.getProperties(childRef); + Map 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 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()); + } } diff --git a/source/java/org/alfresco/repo/transfer/AlienProcessorImpl.java b/source/java/org/alfresco/repo/transfer/AlienProcessorImpl.java index 4f859ff19b..d422835977 100644 --- a/source/java/org/alfresco/repo/transfer/AlienProcessorImpl.java +++ b/source/java/org/alfresco/repo/transfer/AlienProcessorImpl.java @@ -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 . + */ package org.alfresco.repo.transfer; import java.io.Serializable; @@ -5,14 +23,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Stack; import java.util.Vector; import org.alfresco.model.ContentModel; -import org.alfresco.repo.node.NodeServicePolicies; 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.RunAsWork; import org.alfresco.service.cmr.dictionary.DictionaryService; @@ -148,7 +164,46 @@ public class AlienProcessorImpl implements AlienProcessor currentAssoc = null; } } - } + + if (log.isTraceEnabled()) + { + logInvasionHierarchy(childAssocRef.getParentRef(), childAssocRef.getChildRef()); + } + } + + /** + * Puts information about current childRef and its parentRef into log in TRACE level. Information includes 'name', 'fromRepositoryId', 'aliened' and + * 'invadedBy' properties. Additionally, collects the same information for children of childRef + * + * @param parentRef - {@link NodeRef} instance of child node + * @param childRef - {@link NodeRef} instance of parent of the childRef + */ + protected void logInvasionHierarchy(NodeRef parentRef, NodeRef childRef) + { + Map properties = nodeService.getProperties(childRef); + Map 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 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) { @@ -540,7 +595,7 @@ public class AlienProcessorImpl implements AlienProcessor ChildAssociationRef startingParent = nodeService.getPrimaryParent(nodeToPrune); Stack foldersToRecalculate = new Stack(); - + /** * Now go and do the pruning. */ @@ -554,25 +609,72 @@ public class AlienProcessorImpl implements AlienProcessor * if from the repo with multiple alien invasions - leave alone but process children */ NodeRef currentNodeRef = nodesToPrune.pop(); - + + Map 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); - + if(getNodeService().hasAspect(currentNodeRef, TransferModel.ASPECT_ALIEN)) { - // Yes this is an alien node - ListinvadedBy = (List)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_INVADED_BY); - if(invadedBy.contains(fromRepositoryId)) + if (log.isDebugEnabled()) { - // Yes we are invaded by fromRepositoryId - if(invadedBy.size() == 1) + 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 + List invadedBy = (List)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_INVADED_BY); + 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 + 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 - log.debug("pruned - deleted node:" + currentNodeRef); getNodeService().deleteNode(currentNodeRef); } 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 List refs = nodeService.getChildAssocsByPropertyValue(currentNodeRef, TransferModel.PROP_INVADED_BY, fromRepositoryId); for(ChildAssociationRef ref : refs) @@ -589,12 +691,24 @@ public class AlienProcessorImpl implements AlienProcessor */ 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); } } } 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 * @@ -602,10 +716,15 @@ public class AlienProcessorImpl implements AlienProcessor */ getNodeService().hasAspect(currentNodeRef, TransferModel.ASPECT_TRANSFERRED); { - String fromRepoId = (String)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID); - if(fromRepositoryId.equalsIgnoreCase(fromRepoId)) + if(fromRepositoryId.equalsIgnoreCase(initialRepoId)) { - log.debug("folder is from the transferring repository"); + if (log.isDebugEnabled()) + { + 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 List refs = getNodeService().getChildAssocs(currentNodeRef); for(ChildAssociationRef ref : refs) @@ -621,6 +740,13 @@ public class AlienProcessorImpl implements AlienProcessor */ 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); } } @@ -633,11 +759,24 @@ public class AlienProcessorImpl implements AlienProcessor // Current node does not contain alien nodes so it can be deleted. getNodeService().hasAspect(currentNodeRef, TransferModel.ASPECT_TRANSFERRED); { - String fromRepoId = (String)getNodeService().getProperty(currentNodeRef, TransferModel.PROP_FROM_REPOSITORY_ID); - if(fromRepositoryId.equalsIgnoreCase(fromRepoId)) + if (log.isDebugEnabled()) { - // we are invaded by a single repository - log.debug("pruned - deleted non alien node:" + currentNodeRef); + 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 + log.debug("pruned - deleted non alien node:" + currentNodeRef); + } + getNodeService().deleteNode(currentNodeRef); } } @@ -745,44 +884,97 @@ public class AlienProcessorImpl implements AlienProcessor */ private boolean recalcInvasion(NodeRef folderNodeRef, String fromRepositoryId) { - ListfolderInvadedBy = (List)nodeService.getProperty(folderNodeRef, TransferModel.PROP_INVADED_BY); - + if (log.isTraceEnabled()) + { + log.trace("#################"); + log.trace("#RECALC INVASION#"); + log.trace("#################"); + } + + List folderInvadedBy = (List)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 hasAlienChild = false; + //TODO need a more efficient query here List 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(); - ListchildInvadedBy = (List)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 properties = nodeService.getProperties(childNode); + List childInvadedBy = (List) 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; - break; } } - - if(!stillInvaded) + + if (!stillInvaded) { - log.debug("folder is no longer invaded by this repo:" + folderNodeRef); - folderInvadedBy.remove(fromRepositoryId); - if(folderInvadedBy.size() > 0) + if (log.isDebugEnabled()) { - 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); + } + + folderInvadedBy.remove(fromRepositoryId); + if (folderInvadedBy.size() > 0) + { + if (log.isDebugEnabled()) { + log.debug("Current folder HAS ANOTHER invasions. Updating the 'invadedBy' property..."); 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) { - log.debug("no longer alien:" + folderNodeRef); + if (log.isDebugEnabled()) + { + 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); } } - + + if (log.isTraceEnabled()) + { + log.trace("#################"); + log.trace("# COMPLETED #"); + log.trace("#################"); + } + return stillInvaded; } diff --git a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java index 281bbcd52b..186f7f6561 100644 --- a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java +++ b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java @@ -215,6 +215,12 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB // Does a corresponding node exist in this repo? 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. if (log.isDebugEnabled()) { @@ -222,6 +228,11 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB + resolvedNodes.resolvedChild); } update(node, resolvedNodes, primaryParentAssoc); + + if (log.isTraceEnabled()) + { + log.trace("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); + } } else { @@ -245,7 +256,19 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB { 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); + + if (log.isTraceEnabled()) + { + log.trace("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); + } } } diff --git a/source/java/org/alfresco/repo/transfer/RepoTertiaryManifestProcessorImpl.java b/source/java/org/alfresco/repo/transfer/RepoTertiaryManifestProcessorImpl.java index eb953263f6..0bc435503b 100644 --- a/source/java/org/alfresco/repo/transfer/RepoTertiaryManifestProcessorImpl.java +++ b/source/java/org/alfresco/repo/transfer/RepoTertiaryManifestProcessorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2010 Alfresco Software Limited. + * Copyright (C) 2009-2015 Alfresco Software Limited. * * This file is part of Alfresco * @@ -16,18 +16,21 @@ * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ - package org.alfresco.repo.transfer; import java.util.ArrayList; +import java.util.HashSet; 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.TransferManifestHeader; import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.cmr.transfer.TransferReceiver; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -102,16 +105,90 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor //TODO Use more efficient query here. List 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 parentAssocs = nodeService.getParentAssocs(nodeRef); + + if (log.isTraceEnabled()) + { + logInvasionHierarchy(parentAssocs.iterator().next().getParentRef(), nodeRef, nodeService, log); + } + } + List expectedChildNodeRefs = new ArrayList(); - + Set expectedChildNodePaths = new HashSet(); + + if (log.isDebugEnabled()) + { + log.debug("Expected children:"); + } + for(ChildAssociationRef ref : expectedChildren) { 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 actualChildren = nodeService.getChildAssocs(nodeRef); @@ -119,19 +196,35 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor /** * For each actual child association */ + if (log.isDebugEnabled()) + { + log.debug("Traversing ACTUAL children:"); + } + for(ChildAssociationRef child : actualChildren) { log.debug("checking child: " + child); if(child.isPrimary()) { + if (log.isTraceEnabled()) + { + logInvasionHierarchy(child.getParentRef(), child.getChildRef(), nodeService, log); + } + /** * yes it is a primary assoc * should it be there ? */ NodeRef childNodeRef = child.getChildRef(); - - if(!expectedChildNodeRefs.contains(childNodeRef)) + Path actualChildPath = nodeService.getPath(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 * it may need to be deleted. @@ -143,10 +236,16 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor { log.debug("an unexpected transferred 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" // the system that is transferring to this repo. + + if (log.isDebugEnabled()) + { + log.debug("'manifestRepositoryId': " + manifestRepositoryId); + } + if(fromRepositoryId != null && manifestRepositoryId != null) { 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); logComment("Transfer sync mode - node contains alien content so can't be deleted. " + childNodeRef); - alienProcessor.pruneNode(childNodeRef, fromRepositoryId); + alienProcessor.pruneNode(childNodeRef, manifestRepositoryId); } else { - // Node - log.debug("node not alien"); - if(manifestRepositoryId.equalsIgnoreCase(fromRepositoryId)) + // Node + if (log.isDebugEnabled()) { + 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. // Destination node if from the transferring repo and needs to be deleted. logDeleted(node.getNodeRef(), childNodeRef, nodeService.getPath(childNodeRef).toString()); 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..."); + } } } }