diff --git a/source/java/org/alfresco/opencmis/CMISConnector.java b/source/java/org/alfresco/opencmis/CMISConnector.java index 8104d638f1..a2fa993ca1 100644 --- a/source/java/org/alfresco/opencmis/CMISConnector.java +++ b/source/java/org/alfresco/opencmis/CMISConnector.java @@ -2376,13 +2376,23 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen for (String aspect : aspectsToRemove) { aspectType = aspect; - nodeService.removeAspect(nodeRef, getType(aspect).getAlfrescoName()); + TypeDefinitionWrapper type = getType(aspect); + if (type == null) + { + throw new CmisInvalidArgumentException("Invalid aspect: " + aspectType); + } + nodeService.removeAspect(nodeRef, type.getAlfrescoName()); } for (String aspect : aspectsToAdd) { aspectType = aspect; - nodeService.addAspect(nodeRef, getType(aspect).getAlfrescoName(), + TypeDefinitionWrapper type = getType(aspect); + if (type == null) + { + throw new CmisInvalidArgumentException("Invalid aspect: " + aspectType); + } + nodeService.addAspect(nodeRef, type.getAlfrescoName(), Collections. emptyMap()); } } diff --git a/source/java/org/alfresco/repo/admin/RepositoryState.java b/source/java/org/alfresco/repo/admin/RepositoryState.java index 97519efa9a..6c65ad5c9f 100644 --- a/source/java/org/alfresco/repo/admin/RepositoryState.java +++ b/source/java/org/alfresco/repo/admin/RepositoryState.java @@ -18,6 +18,8 @@ */ package org.alfresco.repo.admin; +import java.util.concurrent.locks.ReentrantReadWriteLock; + /** * @author Andy * @@ -25,16 +27,32 @@ package org.alfresco.repo.admin; public class RepositoryState { private boolean bootstrapping; + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); public boolean isBootstrapping() { - return bootstrapping; + this.lock.readLock().lock(); + try + { + return bootstrapping; + } + finally + { + this.lock.readLock().unlock(); + } } public void setBootstrapping(boolean bootstrapping) { - this.bootstrapping = bootstrapping; + this.lock.writeLock().lock(); + try + { + this.bootstrapping = bootstrapping; + } + finally + { + this.lock.writeLock().unlock(); + } } - } diff --git a/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java b/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java index cd1ba4b97c..10e0a36f8a 100644 --- a/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java +++ b/source/java/org/alfresco/repo/domain/node/AbstractNodeDAOImpl.java @@ -3867,30 +3867,6 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO completedPaths.add(pathToSave); } - if (!hasParents && !parentAssocInfo.isStoreRoot()) - { - // We appear to have an orphaned node. But we may just have a temporarily out of sync clustered cache or a - // transaction that started ages before the one that committed the cache content!. So double check the node - // isn't actually deleted. - if (logger.isDebugEnabled()) - { - logger.debug("Stale cache detected for Node #" + currentNodeId + ": removing from cache."); - } - invalidateNodeCaches(currentNodeId); - - Status currentNodeStatus = getNodeRefStatus(currentNodeRef); - if (currentNodeStatus == null || currentNodeStatus.isDeleted()) - { - // Force a retry. The cached node was stale - throw new DataIntegrityViolationException("Stale cache detected for Node #" + currentNodeId); - } - - // We have a corrupt repository - non-root node has a missing parent ?! - bindFixAssocAndCollectLostAndFound(currentNodePair, "nonRootNodeWithoutParents", null, false); - - // throw - error will be logged and then bound txn listener (afterRollback) will be called - throw new NonRootNodeWithoutParentsException(currentNodePair); - } // walk up each parent association for (Map.Entry entry : parentAssocInfo.getParentAssocs().entrySet()) { @@ -4113,6 +4089,19 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO value = loadParentAssocs(node.getNodeVersionKey()); parentAssocsCache.put(cacheKey, value); } + + // We have already validated on loading that we have a list in sync with the child node, so if the list is still + // empty we have an integrity problem + if (value.getPrimaryParentAssoc() == null && !value.isStoreRoot()) + { + Pair currentNodePair = node.getNodePair(); + // We have a corrupt repository - non-root node has a missing parent ?! + bindFixAssocAndCollectLostAndFound(currentNodePair, "nonRootNodeWithoutParents", null, false); + + // throw - error will be logged and then bound txn listener (afterRollback) will be called + throw new NonRootNodeWithoutParentsException(currentNodePair); + } + return value; } @@ -4185,7 +4174,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO // and the lack of parent associations will be cached, anyway. // But to match earlier fixes of ALF-12393, we do a double-check of the node's details NodeEntity nodeCheckFromDb = selectNodeById(nodeId); - if (nodeCheckFromDb == null || !nodeCheckFromDb.getNodeVersionKey().equals(nodeVersionKey)) + if (nodeCheckFromDb == null || nodeCheckFromDb.getDeleted(qnameDAO) || !nodeCheckFromDb.getNodeVersionKey().equals(nodeVersionKey)) { // The node is gone or has moved on in version invalidateNodeCaches(nodeId); diff --git a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java index 35e4574a57..e7487b95d4 100644 --- a/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java +++ b/source/java/org/alfresco/repo/model/filefolder/FileFolderServiceImpl.java @@ -1367,9 +1367,14 @@ public class FileFolderServiceImpl implements FileFolderService NodeRef folderNodeRef = searchSimple(parentNodeRef, pathElement); if (folderNodeRef == null) { - StringBuilder sb = new StringBuilder(128); - sb.append("Folder not found: " + currentPath); - throw new FileNotFoundException(sb.toString()); + if (mustExist) + { + throw new FileNotFoundException("Folder not found: " + currentPath); + } + else + { + return null; + } } parentNodeRef = folderNodeRef; } diff --git a/source/java/org/alfresco/repo/node/NodeServiceTest.java b/source/java/org/alfresco/repo/node/NodeServiceTest.java index bcc8f15166..0a3dd3c21b 100644 --- a/source/java/org/alfresco/repo/node/NodeServiceTest.java +++ b/source/java/org/alfresco/repo/node/NodeServiceTest.java @@ -53,6 +53,7 @@ import org.alfresco.repo.node.NodeServicePolicies.OnUpdateNodePolicy; import org.alfresco.repo.node.NodeServicePolicies.OnUpdatePropertiesPolicy; import org.alfresco.repo.node.db.NodeHierarchyWalker; import org.alfresco.repo.node.db.NodeHierarchyWalker.VisitedNode; +import org.alfresco.repo.node.index.NodeIndexer; import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.Policy; @@ -101,6 +102,7 @@ public class NodeServiceTest extends TestCase protected ServiceRegistry serviceRegistry; protected NodeService nodeService; + protected NodeIndexer nodeIndexer; protected NodeDAO nodeDAO; private TransactionService txnService; private PolicyComponent policyComponent; @@ -120,6 +122,7 @@ public class NodeServiceTest extends TestCase serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); nodeService = serviceRegistry.getNodeService(); + nodeIndexer = (NodeIndexer) ctx.getBean("nodeIndexer"); nodeDAO = (NodeDAO) ctx.getBean("nodeDAO"); txnService = serviceRegistry.getTransactionService(); policyComponent = (PolicyComponent) ctx.getBean("policyComponent"); @@ -1245,16 +1248,25 @@ public class NodeServiceTest extends TestCase // forcefully remove the primary parent assoc final Long childNodeId = (Long)nodeService.getProperty(childNodeRef, ContentModel.PROP_NODE_DBID); - txnService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + // We'll need to disable indexing to do this or the transaction will be thrown out + nodeIndexer.setDisabled(true); + try { - @Override - public Void execute() throws Throwable + txnService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() { - Pair assocPair = nodeDAO.getPrimaryParentAssoc(childNodeId); - nodeDAO.deleteChildAssoc(assocPair.getFirst()); - return null; - } - }); + @Override + public Void execute() throws Throwable + { + Pair assocPair = nodeDAO.getPrimaryParentAssoc(childNodeId); + nodeDAO.deleteChildAssoc(assocPair.getFirst()); + return null; + } + }); + } + finally + { + nodeIndexer.setDisabled(false); + } } // Now need to identify the problem nodes diff --git a/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java b/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java index 44f984cd78..5bf1fd1460 100644 --- a/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java +++ b/source/java/org/alfresco/repo/tenant/MultiTAdminServiceImpl.java @@ -449,6 +449,8 @@ public class MultiTAdminServiceImpl implements TenantAdminService, ApplicationCo { final String tenantDomain = getTenantDomain(tenantDomainIn); + AuthenticationUtil.setMtEnabled(true); // in case this is the 1st tenant + initTenant(tenantDomain, contentRoot); try