mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-15 15:02:20 +00:00
Merged 5.2.N (5.2.1) to HEAD (5.2)
125039 cturlica: Merged 5.1.N (5.1.2) to 5.2.N (5.2.1) 124939 arebegea: Merged 5.0.N (5.0.4) to 5.1.N (5.1.2) 124889 jvonka: Merged 50N-NDB (5.0.4) to 5.0.N (5.0.4) 124745: MNT-15211: Follow-on (note: only affects NDB) - tweaks for further repo test fixes, including: - FileFolderServiceImplTest.testMove git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@127774 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1535,60 +1535,16 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
}
|
}
|
||||||
|
|
||||||
final Long newChildNodeId = newChildNode.getId();
|
final Long newChildNodeId = newChildNode.getId();
|
||||||
|
|
||||||
// Now update the primary parent assoc
|
// Now update the primary parent assoc
|
||||||
RetryingCallback<Integer> callback = new RetryingCallback<Integer>()
|
updatePrimaryParentAssocs(primaryParentAssoc,
|
||||||
{
|
newParentNode,
|
||||||
public Integer execute() throws Throwable
|
childNode,
|
||||||
{
|
newChildNodeId,
|
||||||
// Because we are retrying in-transaction i.e. absorbing exceptions, we need a Savepoint
|
childNodeName,
|
||||||
Savepoint savepoint = controlDAO.createSavepoint("DuplicateChildNodeNameException");
|
oldParentNodeId,
|
||||||
// We use the child node's UUID if there is no cm:name
|
assocTypeQName,
|
||||||
String childNodeNameToUse = childNodeName == null ? childNode.getUuid() : childNodeName;
|
assocQName);
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int updated = updatePrimaryParentAssocs(
|
|
||||||
newChildNodeId,
|
|
||||||
newParentNodeId,
|
|
||||||
assocTypeQName,
|
|
||||||
assocQName,
|
|
||||||
childNodeNameToUse);
|
|
||||||
controlDAO.releaseSavepoint(savepoint);
|
|
||||||
// Ensure we invalidate the name cache (the child version key might not have been 'bumped' by the last
|
|
||||||
// 'touch')
|
|
||||||
if (updated > 0 && primaryParentAssoc != null)
|
|
||||||
{
|
|
||||||
Pair<Long, QName> oldTypeQnamePair = qnameDAO.getQName(
|
|
||||||
primaryParentAssoc.getTypeQNameId());
|
|
||||||
if (oldTypeQnamePair != null)
|
|
||||||
{
|
|
||||||
childByNameCache.remove(new ChildByNameKey(oldParentNodeId, oldTypeQnamePair.getSecond(),
|
|
||||||
primaryParentAssoc.getChildNodeName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return updated;
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
controlDAO.rollbackToSavepoint(savepoint);
|
|
||||||
// DuplicateChildNodeNameException implements DoNotRetryException.
|
|
||||||
// There are some cases - FK violations, specifically - where we DO actually want to retry.
|
|
||||||
// Detecting this is done by looking for the related FK names, 'fk_alf_cass_*' in the error message
|
|
||||||
String lowerMsg = e.getMessage().toLowerCase();
|
|
||||||
if (lowerMsg.contains("fk_alf_cass_"))
|
|
||||||
{
|
|
||||||
throw new ConcurrencyFailureException("FK violation updating primary parent association for " + childNodeId, e);
|
|
||||||
}
|
|
||||||
// We assume that this is from the child cm:name constraint violation
|
|
||||||
throw new DuplicateChildNodeNameException(
|
|
||||||
newParentNode.getNodeRef(),
|
|
||||||
assocTypeQName,
|
|
||||||
childNodeName,
|
|
||||||
e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
childAssocRetryingHelper.doWithRetry(callback);
|
|
||||||
|
|
||||||
// Optimize for rename case
|
// Optimize for rename case
|
||||||
if (!EqualsHelper.nullSafeEquals(newParentNodeId, oldParentNodeId))
|
if (!EqualsHelper.nullSafeEquals(newParentNodeId, oldParentNodeId))
|
||||||
@@ -1615,6 +1571,94 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
return new Pair<Pair<Long, ChildAssociationRef>, Pair<Long, NodeRef>>(assocPair, nodePair);
|
return new Pair<Pair<Long, ChildAssociationRef>, Pair<Long, NodeRef>>(assocPair, nodePair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void updatePrimaryParentAssocs(
|
||||||
|
final ChildAssocEntity primaryParentAssoc,
|
||||||
|
final Node newParentNode,
|
||||||
|
final Node childNode,
|
||||||
|
final Long newChildNodeId,
|
||||||
|
final String childNodeName,
|
||||||
|
final Long oldParentNodeId,
|
||||||
|
final QName assocTypeQName,
|
||||||
|
final QName assocQName)
|
||||||
|
{
|
||||||
|
// Because we are retrying in-transaction i.e. absorbing exceptions, we need partial rollback &/or via savepoint if needed (eg. PostgreSQL)
|
||||||
|
RetryingCallback<Integer> callback = new RetryingCallback<Integer>()
|
||||||
|
{
|
||||||
|
public Integer execute() throws Throwable
|
||||||
|
{
|
||||||
|
return updatePrimaryParentAssocsImpl(primaryParentAssoc,
|
||||||
|
newParentNode,
|
||||||
|
childNode,
|
||||||
|
newChildNodeId,
|
||||||
|
childNodeName,
|
||||||
|
oldParentNodeId,
|
||||||
|
assocTypeQName,
|
||||||
|
assocQName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
childAssocRetryingHelper.doWithRetry(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int updatePrimaryParentAssocsImpl(
|
||||||
|
ChildAssocEntity primaryParentAssoc,
|
||||||
|
Node newParentNode,
|
||||||
|
Node childNode,
|
||||||
|
Long newChildNodeId,
|
||||||
|
String childNodeName,
|
||||||
|
Long oldParentNodeId,
|
||||||
|
QName assocTypeQName,
|
||||||
|
QName assocQName)
|
||||||
|
{
|
||||||
|
Long newParentNodeId = newParentNode.getId();
|
||||||
|
Long childNodeId = childNode.getId();
|
||||||
|
|
||||||
|
Savepoint savepoint = controlDAO.createSavepoint("DuplicateChildNodeNameException");
|
||||||
|
// We use the child node's UUID if there is no cm:name
|
||||||
|
String childNodeNameToUse = childNodeName == null ? childNode.getUuid() : childNodeName;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int updated = updatePrimaryParentAssocs(
|
||||||
|
newChildNodeId,
|
||||||
|
newParentNodeId,
|
||||||
|
assocTypeQName,
|
||||||
|
assocQName,
|
||||||
|
childNodeNameToUse);
|
||||||
|
controlDAO.releaseSavepoint(savepoint);
|
||||||
|
// Ensure we invalidate the name cache (the child version key might not have been 'bumped' by the last
|
||||||
|
// 'touch')
|
||||||
|
if (updated > 0 && primaryParentAssoc != null)
|
||||||
|
{
|
||||||
|
Pair<Long, QName> oldTypeQnamePair = qnameDAO.getQName(
|
||||||
|
primaryParentAssoc.getTypeQNameId());
|
||||||
|
if (oldTypeQnamePair != null)
|
||||||
|
{
|
||||||
|
childByNameCache.remove(new ChildByNameKey(oldParentNodeId, oldTypeQnamePair.getSecond(),
|
||||||
|
primaryParentAssoc.getChildNodeName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
controlDAO.rollbackToSavepoint(savepoint);
|
||||||
|
// DuplicateChildNodeNameException implements DoNotRetryException.
|
||||||
|
// There are some cases - FK violations, specifically - where we DO actually want to retry.
|
||||||
|
// Detecting this is done by looking for the related FK names, 'fk_alf_cass_*' in the error message
|
||||||
|
String lowerMsg = e.getMessage().toLowerCase();
|
||||||
|
if (lowerMsg.contains("fk_alf_cass_"))
|
||||||
|
{
|
||||||
|
throw new ConcurrencyFailureException("FK violation updating primary parent association for " + childNodeId, e);
|
||||||
|
}
|
||||||
|
// We assume that this is from the child cm:name constraint violation
|
||||||
|
throw new DuplicateChildNodeNameException(
|
||||||
|
newParentNode.getNodeRef(),
|
||||||
|
assocTypeQName,
|
||||||
|
childNodeName,
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean updateNode(Long nodeId, QName nodeTypeQName, Locale nodeLocale)
|
public boolean updateNode(Long nodeId, QName nodeTypeQName, Locale nodeLocale)
|
||||||
{
|
{
|
||||||
@@ -3143,7 +3187,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
// Index
|
// Index
|
||||||
assoc.setAssocIndex(-1);
|
assoc.setAssocIndex(-1);
|
||||||
|
|
||||||
Long assocId = newChildAssocImplInsert(assoc, assocTypeQName, childNodeName);
|
Long assocId = newChildAssocInsert(assoc, assocTypeQName, childNodeName);
|
||||||
|
|
||||||
// Persist it
|
// Persist it
|
||||||
assoc.setId(assocId);
|
assoc.setId(assocId);
|
||||||
@@ -3163,50 +3207,56 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
return assoc;
|
return assoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Long newChildAssocImplInsert(final ChildAssocEntity assoc, final QName assocTypeQName, final String childNodeName)
|
protected Long newChildAssocInsert(final ChildAssocEntity assoc, final QName assocTypeQName, final String childNodeName)
|
||||||
{
|
{
|
||||||
|
// Because we are retrying in-transaction i.e. absorbing exceptions, we need partial rollback &/or via savepoint if needed (eg. PostgreSQL)
|
||||||
RetryingCallback<Long> callback = new RetryingCallback<Long>()
|
RetryingCallback<Long> callback = new RetryingCallback<Long>()
|
||||||
{
|
{
|
||||||
public Long execute() throws Throwable
|
public Long execute() throws Throwable
|
||||||
{
|
{
|
||||||
Savepoint savepoint = controlDAO.createSavepoint("DuplicateChildNodeNameException");
|
return newChildAssocInsertImpl(assoc, assocTypeQName, childNodeName);
|
||||||
try
|
|
||||||
{
|
|
||||||
Long id = insertChildAssoc(assoc);
|
|
||||||
controlDAO.releaseSavepoint(savepoint);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
controlDAO.rollbackToSavepoint(savepoint);
|
|
||||||
// DuplicateChildNodeNameException implements DoNotRetryException.
|
|
||||||
|
|
||||||
// Allow real DB concurrency issues (e.g. DeadlockLoserDataAccessException) straight through for a retry
|
|
||||||
if (e instanceof ConcurrencyFailureException)
|
|
||||||
{
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
// There are some cases - FK violations, specifically - where we DO actually want to retry.
|
|
||||||
// Detecting this is done by looking for the related FK names, 'fk_alf_cass_*' in the error message
|
|
||||||
String lowerMsg = e.getMessage().toLowerCase();
|
|
||||||
if (lowerMsg.contains("fk_alf_cass_"))
|
|
||||||
{
|
|
||||||
throw new ConcurrencyFailureException("FK violation updating primary parent association:" + assoc, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We assume that this is from the child cm:name constraint violation
|
|
||||||
throw new DuplicateChildNodeNameException(
|
|
||||||
assoc.getParentNode().getNodeRef(),
|
|
||||||
assocTypeQName,
|
|
||||||
childNodeName,
|
|
||||||
e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Long assocId = childAssocRetryingHelper.doWithRetry(callback);
|
Long assocId = childAssocRetryingHelper.doWithRetry(callback);
|
||||||
return assocId;
|
return assocId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Long newChildAssocInsertImpl(final ChildAssocEntity assoc, final QName assocTypeQName, final String childNodeName)
|
||||||
|
{
|
||||||
|
Savepoint savepoint = controlDAO.createSavepoint("DuplicateChildNodeNameException");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Long id = insertChildAssoc(assoc);
|
||||||
|
controlDAO.releaseSavepoint(savepoint);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
controlDAO.rollbackToSavepoint(savepoint);
|
||||||
|
// DuplicateChildNodeNameException implements DoNotRetryException.
|
||||||
|
|
||||||
|
// Allow real DB concurrency issues (e.g. DeadlockLoserDataAccessException) straight through for a retry
|
||||||
|
if (e instanceof ConcurrencyFailureException)
|
||||||
|
{
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There are some cases - FK violations, specifically - where we DO actually want to retry.
|
||||||
|
// Detecting this is done by looking for the related FK names, 'fk_alf_cass_*' in the error message
|
||||||
|
String lowerMsg = e.getMessage().toLowerCase();
|
||||||
|
if (lowerMsg.contains("fk_alf_cass_"))
|
||||||
|
{
|
||||||
|
throw new ConcurrencyFailureException("FK violation updating primary parent association:" + assoc, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We assume that this is from the child cm:name constraint violation
|
||||||
|
throw new DuplicateChildNodeNameException(
|
||||||
|
assoc.getParentNode().getNodeRef(),
|
||||||
|
assocTypeQName,
|
||||||
|
childNodeName,
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<Long, ChildAssociationRef> newChildAssoc(
|
public Pair<Long, ChildAssociationRef> newChildAssoc(
|
||||||
@@ -3275,53 +3325,10 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
* TODO: See about pulling automatic cm:name update logic into this DAO
|
* TODO: See about pulling automatic cm:name update logic into this DAO
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setChildAssocsUniqueName(final Long childNodeId, final String childName)
|
public void setChildAssocsUniqueName(Long childNodeId, String childName)
|
||||||
{
|
{
|
||||||
RetryingCallback<Integer> callback = new RetryingCallback<Integer>()
|
Integer count = setChildAssocsUniqueNameImpl(childNodeId, childName);
|
||||||
{
|
|
||||||
public Integer execute() throws Throwable
|
|
||||||
{
|
|
||||||
int total = 0;
|
|
||||||
Savepoint savepoint = controlDAO.createSavepoint("DuplicateChildNodeNameException");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
for (ChildAssocEntity parentAssoc : getParentAssocsCached(childNodeId).getParentAssocs().values())
|
|
||||||
{
|
|
||||||
// Subtlety: We only update those associations for which name uniqueness checking is enforced.
|
|
||||||
// Such associations have a positive CRC
|
|
||||||
if (parentAssoc.getChildNodeNameCrc() <= 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Pair<Long, QName> oldTypeQnamePair = qnameDAO.getQName(parentAssoc.getTypeQNameId());
|
|
||||||
// Ensure we invalidate the name cache (the child version key might not be 'bumped' by the next
|
|
||||||
// 'touch')
|
|
||||||
if (oldTypeQnamePair != null)
|
|
||||||
{
|
|
||||||
childByNameCache.remove(new ChildByNameKey(parentAssoc.getParentNode().getId(),
|
|
||||||
oldTypeQnamePair.getSecond(), parentAssoc.getChildNodeName()));
|
|
||||||
}
|
|
||||||
int count = updateChildAssocUniqueName(parentAssoc.getId(), childName);
|
|
||||||
if (count <= 0)
|
|
||||||
{
|
|
||||||
// Should not be attempting to delete a deleted node
|
|
||||||
throw new ConcurrencyFailureException("Failed to update an existing parent association "
|
|
||||||
+ parentAssoc.getId());
|
|
||||||
}
|
|
||||||
total += count;
|
|
||||||
}
|
|
||||||
controlDAO.releaseSavepoint(savepoint);
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
controlDAO.rollbackToSavepoint(savepoint);
|
|
||||||
// We assume that this is from the child cm:name constraint violation
|
|
||||||
throw new DuplicateChildNodeNameException(null, null, childName, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Integer count = childAssocRetryingHelper.doWithRetry(callback);
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
// Touch the node; parent assocs are out of sync
|
// Touch the node; parent assocs are out of sync
|
||||||
@@ -3337,6 +3344,61 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
" Updated: " + count);
|
" Updated: " + count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected int setChildAssocsUniqueNameImpl(final Long childNodeId, final String childName)
|
||||||
|
{
|
||||||
|
// Because we are retrying in-transaction i.e. absorbing exceptions, we need partial rollback &/or via savepoint if needed (eg. PostgreSQL)
|
||||||
|
RetryingCallback<Integer> callback = new RetryingCallback<Integer>()
|
||||||
|
{
|
||||||
|
public Integer execute() throws Throwable
|
||||||
|
{
|
||||||
|
return updateChildAssocUniqueNameImpl(childNodeId, childName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return childAssocRetryingHelper.doWithRetry(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int updateChildAssocUniqueNameImpl(final Long childNodeId, final String childName)
|
||||||
|
{
|
||||||
|
int total = 0;
|
||||||
|
Savepoint savepoint = controlDAO.createSavepoint("DuplicateChildNodeNameException");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (ChildAssocEntity parentAssoc : getParentAssocsCached(childNodeId).getParentAssocs().values())
|
||||||
|
{
|
||||||
|
// Subtlety: We only update those associations for which name uniqueness checking is enforced.
|
||||||
|
// Such associations have a positive CRC
|
||||||
|
if (parentAssoc.getChildNodeNameCrc() <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Pair<Long, QName> oldTypeQnamePair = qnameDAO.getQName(parentAssoc.getTypeQNameId());
|
||||||
|
// Ensure we invalidate the name cache (the child version key might not be 'bumped' by the next
|
||||||
|
// 'touch')
|
||||||
|
if (oldTypeQnamePair != null)
|
||||||
|
{
|
||||||
|
childByNameCache.remove(new ChildByNameKey(parentAssoc.getParentNode().getId(),
|
||||||
|
oldTypeQnamePair.getSecond(), parentAssoc.getChildNodeName()));
|
||||||
|
}
|
||||||
|
int count = updateChildAssocUniqueName(parentAssoc.getId(), childName);
|
||||||
|
if (count <= 0)
|
||||||
|
{
|
||||||
|
// Should not be attempting to delete a deleted node
|
||||||
|
throw new ConcurrencyFailureException("Failed to update an existing parent association "
|
||||||
|
+ parentAssoc.getId());
|
||||||
|
}
|
||||||
|
total += count;
|
||||||
|
}
|
||||||
|
controlDAO.releaseSavepoint(savepoint);
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
controlDAO.rollbackToSavepoint(savepoint);
|
||||||
|
// We assume that this is from the child cm:name constraint violation
|
||||||
|
throw new DuplicateChildNodeNameException(null, null, childName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Pair<Long, ChildAssociationRef> getChildAssoc(Long assocId)
|
public Pair<Long, ChildAssociationRef> getChildAssoc(Long assocId)
|
||||||
|
@@ -54,7 +54,6 @@ import org.alfresco.repo.domain.node.TransactionQueryEntity;
|
|||||||
import org.alfresco.repo.domain.qname.QNameDAO;
|
import org.alfresco.repo.domain.qname.QNameDAO;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
import org.alfresco.service.cmr.repository.StoreRef;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
@@ -64,7 +63,6 @@ import org.apache.ibatis.session.ResultContext;
|
|||||||
import org.apache.ibatis.session.ResultHandler;
|
import org.apache.ibatis.session.ResultHandler;
|
||||||
import org.apache.ibatis.session.RowBounds;
|
import org.apache.ibatis.session.RowBounds;
|
||||||
import org.mybatis.spring.SqlSessionTemplate;
|
import org.mybatis.spring.SqlSessionTemplate;
|
||||||
import org.springframework.dao.ConcurrencyFailureException;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
|
||||||
@@ -1757,12 +1755,6 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
|
|||||||
*/
|
*/
|
||||||
public static class MySQLClusterNDB extends MySQL
|
public static class MySQLClusterNDB extends MySQL
|
||||||
{
|
{
|
||||||
// eg. see
|
|
||||||
// ArchiveAndRestoreTest.*,
|
|
||||||
// LargeArchiveAndRestoreTest.testCreateAndRestore (also bumped MaxNoOfFiredTriggers from 4000 to 12000)
|
|
||||||
// DbNodeServiceImplTest.testNodeStatus
|
|
||||||
// MultilingualDocumentAspectTest.testDeleteNode
|
|
||||||
// ...
|
|
||||||
@Override
|
@Override
|
||||||
protected Long newNodeImplInsert(NodeEntity node)
|
protected Long newNodeImplInsert(NodeEntity node)
|
||||||
{
|
{
|
||||||
@@ -1805,40 +1797,40 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eg. see DbNodeServiceImplTest.testDuplicateCatch
|
|
||||||
@Override
|
@Override
|
||||||
protected Long newChildAssocImplInsert(final ChildAssocEntity assoc, final QName assocTypeQName, final String childNodeName)
|
protected Long newChildAssocInsert(ChildAssocEntity assoc, QName assocTypeQName, String childNodeName)
|
||||||
{
|
{
|
||||||
try
|
// no in-txn retry / full rollback on sql exception
|
||||||
{
|
return newChildAssocInsertImpl(assoc, assocTypeQName, childNodeName);
|
||||||
Long id = insertChildAssoc(assoc);
|
}
|
||||||
return id;
|
|
||||||
}
|
@Override
|
||||||
catch (Throwable e)
|
protected int setChildAssocsUniqueNameImpl(Long childNodeId, String childName)
|
||||||
{
|
{
|
||||||
// DuplicateChildNodeNameException implements DoNotRetryException.
|
// no in-txn retry / full rollback on sql exception
|
||||||
|
return updateChildAssocUniqueNameImpl(childNodeId, childName);
|
||||||
// Allow real DB concurrency issues (e.g. DeadlockLoserDataAccessException) straight through for a retry
|
}
|
||||||
if (e instanceof ConcurrencyFailureException)
|
|
||||||
{
|
@Override
|
||||||
throw e;
|
protected void updatePrimaryParentAssocs(
|
||||||
}
|
ChildAssocEntity primaryParentAssoc,
|
||||||
|
Node newParentNode,
|
||||||
// There are some cases - FK violations, specifically - where we DO actually want to retry.
|
Node childNode,
|
||||||
// Detecting this is done by looking for the related FK names, 'fk_alf_cass_*' in the error message
|
Long newChildNodeId,
|
||||||
String lowerMsg = e.getMessage().toLowerCase();
|
String childNodeName,
|
||||||
if (lowerMsg.contains("fk_alf_cass_"))
|
Long oldParentNodeId,
|
||||||
{
|
QName assocTypeQName,
|
||||||
throw new ConcurrencyFailureException("FK violation updating primary parent association:" + assoc, e);
|
QName assocQName)
|
||||||
}
|
{
|
||||||
|
// no in-txn retry / full rollback on sql exception
|
||||||
// We assume that this is from the child cm:name constraint violation
|
updatePrimaryParentAssocsImpl(primaryParentAssoc,
|
||||||
throw new DuplicateChildNodeNameException(
|
newParentNode,
|
||||||
assoc.getParentNode().getNodeRef(),
|
childNode,
|
||||||
assocTypeQName,
|
newChildNodeId,
|
||||||
childNodeName,
|
childNodeName,
|
||||||
e);
|
oldParentNodeId,
|
||||||
}
|
assocTypeQName,
|
||||||
|
assocQName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user