mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-08 14:51:49 +00:00
Merged 5.1.N (5.1.1) to HEAD (5.1)
113397 tvalkevych: Merged 5.0.N (5.0.3) to 5.1.N (5.1.1) 113290 adavis: Merged V4.2-BUG-FIX (4.2.6) to 5.0.N (5.0.3) 113278 adavis: Merged V4.1-BUG-FIX (4.1.11) to V4.2-BUG-FIX (4.2.6) 112985 amorarasu: Merged DEV to V4.1-BUG-FIX (4.1.11) 111742: MNT-10305: DeletedNodeCleanupWorker should be improved - Delete in multiple statements, filtering by transactions with commit time in a time interval. 112722: Improved the algorithm that sets appropriate time windows for delete, based on the evolution of the purge process. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@123576 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
(
|
(
|
||||||
select max(txn.id) from alf_transaction txn
|
select max(txn.id) from alf_transaction txn
|
||||||
where
|
where
|
||||||
|
txn.commit_time_ms >= #{minCommitTime} and
|
||||||
txn.commit_time_ms < #{maxCommitTime}
|
txn.commit_time_ms < #{maxCommitTime}
|
||||||
)
|
)
|
||||||
]]>
|
]]>
|
||||||
@@ -30,7 +31,8 @@
|
|||||||
where
|
where
|
||||||
node.type_qname_id = #{typeQNameId} and
|
node.type_qname_id = #{typeQNameId} and
|
||||||
alf_node_properties.node_id = node.id and
|
alf_node_properties.node_id = node.id and
|
||||||
txn.commit_time_ms < #{maxCommitTime}
|
(txn.commit_time_ms >= #{minCommitTime} and
|
||||||
|
txn.commit_time_ms < #{maxCommitTime})
|
||||||
)
|
)
|
||||||
]]>
|
]]>
|
||||||
</delete>
|
</delete>
|
||||||
|
@@ -11,7 +11,8 @@
|
|||||||
join alf_transaction txn on (txn.id = n.transaction_id)
|
join alf_transaction txn on (txn.id = n.transaction_id)
|
||||||
where
|
where
|
||||||
n.type_qname_id = #{typeQNameId} and
|
n.type_qname_id = #{typeQNameId} and
|
||||||
txn.commit_time_ms < #{maxCommitTime}
|
(txn.commit_time_ms >= #{minCommitTime} and
|
||||||
|
txn.commit_time_ms < #{maxCommitTime})
|
||||||
]]>
|
]]>
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
@@ -22,7 +23,8 @@
|
|||||||
join alf_transaction txn on (txn.id = n.transaction_id)
|
join alf_transaction txn on (txn.id = n.transaction_id)
|
||||||
where
|
where
|
||||||
n.type_qname_id = #{typeQNameId} and
|
n.type_qname_id = #{typeQNameId} and
|
||||||
txn.commit_time_ms < #{maxCommitTime}
|
(txn.commit_time_ms >= #{minCommitTime} and
|
||||||
|
txn.commit_time_ms < #{maxCommitTime})
|
||||||
]]>
|
]]>
|
||||||
</delete>
|
</delete>
|
||||||
|
|
||||||
|
@@ -2039,9 +2039,9 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int purgeNodes(long maxTxnCommitTimeMs)
|
public int purgeNodes(long fromTxnCommitTimeMs, long toTxnCommitTimeMs)
|
||||||
{
|
{
|
||||||
return deleteNodesByCommitTime(maxTxnCommitTimeMs);
|
return deleteNodesByCommitTime(fromTxnCommitTimeMs, toTxnCommitTimeMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -4908,7 +4908,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
Long optionalOldSharedAlcIdInAdditionToNull,
|
Long optionalOldSharedAlcIdInAdditionToNull,
|
||||||
Long newSharedAlcId);
|
Long newSharedAlcId);
|
||||||
protected abstract int deleteNodeById(Long nodeId);
|
protected abstract int deleteNodeById(Long nodeId);
|
||||||
protected abstract int deleteNodesByCommitTime(long maxTxnCommitTimeMs);
|
protected abstract int deleteNodesByCommitTime(long fromTxnCommitTimeMs, long toTxnCommitTimeMs);
|
||||||
protected abstract NodeEntity selectNodeById(Long id);
|
protected abstract NodeEntity selectNodeById(Long id);
|
||||||
protected abstract NodeEntity selectNodeByNodeRef(NodeRef nodeRef);
|
protected abstract NodeEntity selectNodeByNodeRef(NodeRef nodeRef);
|
||||||
protected abstract List<Node> selectNodesByUuids(Long storeId, SortedSet<String> uuids);
|
protected abstract List<Node> selectNodesByUuids(Long storeId, SortedSet<String> uuids);
|
||||||
|
@@ -323,12 +323,13 @@ public interface NodeDAO extends NodeBulkLoader
|
|||||||
public void deleteNode(Long nodeId);
|
public void deleteNode(Long nodeId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Purge deleted nodes where their participating transactions are older than a given time.
|
* Purge deleted nodes where their participating transactions are in-between the given time interval.
|
||||||
*
|
*
|
||||||
* @param maxTxnCommitTimeMs ignore transactions created <i>after</i> this time
|
* @param fromTxnCommitTimeMs from commit time
|
||||||
|
* @param toTxnCommitTimeMs to commit time
|
||||||
* @return Returns the number of deleted nodes purged
|
* @return Returns the number of deleted nodes purged
|
||||||
*/
|
*/
|
||||||
public int purgeNodes(long maxTxnCommitTimeMs);
|
public int purgeNodes(long fromTxnCommitTimeMs, long toTxnCommitTimeMs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Properties
|
* Properties
|
||||||
|
@@ -388,7 +388,7 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int deleteNodesByCommitTime(long maxTxnCommitTimeMs)
|
protected int deleteNodesByCommitTime(long fromTxnCommitTimeMs, long toTxnCommitTimeMs)
|
||||||
{
|
{
|
||||||
// Get the deleted nodes
|
// Get the deleted nodes
|
||||||
Pair<Long, QName> deletedTypePair = qnameDAO.getQName(ContentModel.TYPE_DELETED);
|
Pair<Long, QName> deletedTypePair = qnameDAO.getQName(ContentModel.TYPE_DELETED);
|
||||||
@@ -399,7 +399,8 @@ public class NodeDAOImpl extends AbstractNodeDAOImpl
|
|||||||
}
|
}
|
||||||
TransactionQueryEntity query = new TransactionQueryEntity();
|
TransactionQueryEntity query = new TransactionQueryEntity();
|
||||||
query.setTypeQNameId(deletedTypePair.getFirst());
|
query.setTypeQNameId(deletedTypePair.getFirst());
|
||||||
query.setMaxCommitTime(maxTxnCommitTimeMs);
|
query.setMinCommitTime(fromTxnCommitTimeMs);
|
||||||
|
query.setMaxCommitTime(toTxnCommitTimeMs);
|
||||||
// TODO: Fix ALF-16030 Use ON DELETE CASCADE for node aspects and properties
|
// TODO: Fix ALF-16030 Use ON DELETE CASCADE for node aspects and properties
|
||||||
// First clean up properties
|
// First clean up properties
|
||||||
template.delete(DELETE_NODE_PROPS_BY_TXN_COMMIT_TIME, query);
|
template.delete(DELETE_NODE_PROPS_BY_TXN_COMMIT_TIME, query);
|
||||||
|
@@ -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
|
||||||
*
|
*
|
||||||
@@ -101,42 +101,59 @@ public class DeletedNodeCleanupWorker extends AbstractNodeCleanupWorker
|
|||||||
{
|
{
|
||||||
final List<String> results = new ArrayList<String>(100);
|
final List<String> results = new ArrayList<String>(100);
|
||||||
|
|
||||||
final long maxCommitTimeMs = System.currentTimeMillis() - minAge;
|
final long maxCommitTime = System.currentTimeMillis() - minAge;
|
||||||
|
long fromCommitTime = nodeDAO.getMinUnusedTxnCommitTime().longValue();
|
||||||
|
|
||||||
RetryingTransactionCallback<Integer> purgeNodesCallback = new RetryingTransactionCallback<Integer>()
|
|
||||||
{
|
|
||||||
public Integer execute() throws Throwable
|
|
||||||
{
|
|
||||||
return nodeDAO.purgeNodes(maxCommitTimeMs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// TODO: Add error catching and decrement the maxCommitTimeMs to reduce DB resource usage
|
|
||||||
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||||
txnHelper.setMaxRetries(5); // Limit number of retries
|
txnHelper.setMaxRetries(5); // Limit number of retries
|
||||||
txnHelper.setRetryWaitIncrementMs(1000); // 1 second to allow other cleanups time to get through
|
txnHelper.setRetryWaitIncrementMs(1000); // 1 second to allow other cleanups time to get through
|
||||||
// Get nodes to delete
|
|
||||||
Integer purgeCount = new Integer(0);
|
long loopPurgeSize = purgeSize;
|
||||||
// Purge nodes
|
Long purgeCount = new Long(0);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Ensure we keep the lock
|
||||||
|
refreshLock();
|
||||||
|
|
||||||
|
long toCommitTime = fromCommitTime + loopPurgeSize;
|
||||||
|
if(toCommitTime > maxCommitTime)
|
||||||
|
{
|
||||||
|
toCommitTime = maxCommitTime;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
DeleteNodesByTransactionsCallback purgeNodesCallback = new DeleteNodesByTransactionsCallback(nodeDAO, fromCommitTime, toCommitTime);
|
||||||
purgeCount = txnHelper.doInTransaction(purgeNodesCallback, false, true);
|
purgeCount = txnHelper.doInTransaction(purgeNodesCallback, false, true);
|
||||||
if (purgeCount.intValue() > 0)
|
|
||||||
|
if (purgeCount.longValue() > 0)
|
||||||
{
|
{
|
||||||
String msg =
|
String msg =
|
||||||
"Purged old nodes: \n" +
|
"Purged old nodes: \n" +
|
||||||
" Max commit time: " + maxCommitTimeMs + "\n" +
|
" From commit time (ms): " + fromCommitTime + "\n" +
|
||||||
|
" To commit time (ms): " + toCommitTime + "\n" +
|
||||||
" Purge count: " + purgeCount;
|
" Purge count: " + purgeCount;
|
||||||
results.add(msg);
|
results.add(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fromCommitTime += loopPurgeSize;
|
||||||
|
|
||||||
|
// If the delete succeeded, double the loopPurgeSize
|
||||||
|
loopPurgeSize *= 2L;
|
||||||
|
if (loopPurgeSize > purgeSize)
|
||||||
|
{
|
||||||
|
loopPurgeSize = purgeSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Throwable e)
|
catch (Throwable e)
|
||||||
{
|
{
|
||||||
String msg =
|
String msg =
|
||||||
"Failed to purge nodes." +
|
"Failed to purge nodes. \n" +
|
||||||
" If the purgable set is too large for the available DB resources \n" +
|
" If the purgable set is too large for the available DB resources \n" +
|
||||||
" then the nodes can be purged manually as well. \n" +
|
" then the nodes can be purged manually as well. \n" +
|
||||||
" Set log level to WARN for this class to get exception log: \n" +
|
" Set log level to WARN for this class to get exception log: \n" +
|
||||||
" Max commit time: " + maxCommitTimeMs + "\n" +
|
" From commit time (ms): " + fromCommitTime + "\n" +
|
||||||
|
" To commit time (ms): " + toCommitTime + "\n" +
|
||||||
" Error: " + e.getMessage();
|
" Error: " + e.getMessage();
|
||||||
// It failed; do a full log in WARN mode
|
// It failed; do a full log in WARN mode
|
||||||
if (logger.isWarnEnabled())
|
if (logger.isWarnEnabled())
|
||||||
@@ -148,7 +165,33 @@ public class DeletedNodeCleanupWorker extends AbstractNodeCleanupWorker
|
|||||||
logger.error(msg);
|
logger.error(msg);
|
||||||
}
|
}
|
||||||
results.add(msg);
|
results.add(msg);
|
||||||
|
|
||||||
|
// If delete failed, halve the loopPurgeSize and try again
|
||||||
|
loopPurgeSize /= 2L;
|
||||||
|
// If the purge size drops below 10% of the original size, the entire process must stop
|
||||||
|
if (loopPurgeSize < 0.1 * purgeSize)
|
||||||
|
{
|
||||||
|
msg ="Failed to purge nodes. \n" +
|
||||||
|
" The purge time interval dropped below 10% of the original size (" + purgeSize + "), so the purging process was stopped.";
|
||||||
|
if (logger.isWarnEnabled())
|
||||||
|
{
|
||||||
|
logger.warn(msg, e);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.error(msg);
|
||||||
|
}
|
||||||
|
results.add(msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fromCommitTime >= maxCommitTime)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@@ -170,16 +213,16 @@ public class DeletedNodeCleanupWorker extends AbstractNodeCleanupWorker
|
|||||||
final long maxCommitTime = System.currentTimeMillis() - minAge;
|
final long maxCommitTime = System.currentTimeMillis() - minAge;
|
||||||
long fromCommitTime = nodeDAO.getMinUnusedTxnCommitTime().longValue();
|
long fromCommitTime = nodeDAO.getMinUnusedTxnCommitTime().longValue();
|
||||||
|
|
||||||
|
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
||||||
|
txnHelper.setMaxRetries(5); // Limit number of retries
|
||||||
|
txnHelper.setRetryWaitIncrementMs(1000); // 1 second to allow other cleanups time to get through
|
||||||
|
|
||||||
// delete unused transactions in batches of size 'purgeTxnBlockSize'
|
// delete unused transactions in batches of size 'purgeTxnBlockSize'
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Ensure we keep the lock
|
// Ensure we keep the lock
|
||||||
refreshLock();
|
refreshLock();
|
||||||
|
|
||||||
RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
|
|
||||||
txnHelper.setMaxRetries(5); // Limit number of retries
|
|
||||||
txnHelper.setRetryWaitIncrementMs(1000); // 1 second to allow other cleanups time to get through
|
|
||||||
|
|
||||||
long toCommitTime = fromCommitTime + purgeSize;
|
long toCommitTime = fromCommitTime + purgeSize;
|
||||||
if(toCommitTime >= maxCommitTime)
|
if(toCommitTime >= maxCommitTime)
|
||||||
{
|
{
|
||||||
@@ -232,26 +275,53 @@ public class DeletedNodeCleanupWorker extends AbstractNodeCleanupWorker
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
private static abstract class DeleteByTransactionsCallback implements RetryingTransactionCallback<Long>
|
||||||
* Delete a block of unused transactions
|
|
||||||
*/
|
|
||||||
private static class DeleteTransactionsCallback implements RetryingTransactionCallback<Long>
|
|
||||||
{
|
{
|
||||||
private NodeDAO nodeDAO;
|
protected NodeDAO nodeDAO;
|
||||||
private long fromCommitTime;
|
protected long fromCommitTime;
|
||||||
private long toCommitTime;
|
protected long toCommitTime;
|
||||||
|
|
||||||
DeleteTransactionsCallback(NodeDAO nodeDAO, long fromCommitTime, long toCommitTime)
|
DeleteByTransactionsCallback(NodeDAO nodeDAO, long fromCommitTime, long toCommitTime)
|
||||||
{
|
{
|
||||||
this.nodeDAO = nodeDAO;
|
this.nodeDAO = nodeDAO;
|
||||||
this.fromCommitTime = fromCommitTime;
|
this.fromCommitTime = fromCommitTime;
|
||||||
this.toCommitTime = toCommitTime;
|
this.toCommitTime = toCommitTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract Long execute() throws Throwable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete a block of unused transactions
|
||||||
|
*/
|
||||||
|
private static class DeleteTransactionsCallback extends DeleteByTransactionsCallback
|
||||||
|
{
|
||||||
|
DeleteTransactionsCallback(NodeDAO nodeDAO, long fromCommitTime, long toCommitTime)
|
||||||
|
{
|
||||||
|
super(nodeDAO, fromCommitTime, toCommitTime);
|
||||||
|
}
|
||||||
|
|
||||||
public Long execute() throws Throwable
|
public Long execute() throws Throwable
|
||||||
{
|
{
|
||||||
long count = nodeDAO.deleteTxnsUnused(fromCommitTime, toCommitTime);
|
long count = nodeDAO.deleteTxnsUnused(fromCommitTime, toCommitTime);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Purge a block of deleted nodes and their properties
|
||||||
|
*/
|
||||||
|
private static class DeleteNodesByTransactionsCallback extends DeleteByTransactionsCallback
|
||||||
|
{
|
||||||
|
DeleteNodesByTransactionsCallback(NodeDAO nodeDAO, long fromCommitTime, long toCommitTime)
|
||||||
|
{
|
||||||
|
super(nodeDAO, fromCommitTime, toCommitTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long execute() throws Throwable
|
||||||
|
{
|
||||||
|
long count = nodeDAO.purgeNodes(fromCommitTime, toCommitTime);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user