From 2541cc36aba2822a17f3048b05da1c59467a2bf7 Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Thu, 30 Apr 2015 04:42:25 +0000 Subject: [PATCH] RM-2162: Records Management patch RMv22DODModelSeparationModulePatch taking too long with large amount of records * added configuration property that allows existing DoD RM site to be converted to standard RM site * added deprecated properties back into rma namespace to avoid loss of data * patches to move properties into DoD namespace not executed if not required * removed a couple of references to moved properties that still existed * ensure address properties are moved if required +review RM git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/BRANCHES/V2.2.1.x@103185 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../alfresco-global.properties | 10 ++ .../model/recordsModel.xml | 67 +++++++++ .../patch/rm-patch-v22-context.xml | 8 +- .../dod5015/DOD5015Model.java | 2 + .../email/CustomEmailMappingServiceImpl.java | 10 +- .../patch/AbstractModulePatch.java | 12 +- .../patch/v22/RMv22DODCompliantSitePatch.java | 40 ++++-- .../RMv22DODModelSeparationModulePatch.java | 133 +++++++++++------- 8 files changed, 203 insertions(+), 79 deletions(-) diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties index 1270de1af6..c7dd143366 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties @@ -52,3 +52,13 @@ rm.dispositionlifecycletrigger.cronexpression=0 0/5 * * * ? # Indicates whether mandatory properties are checked before completing a record # rm.completerecord.mandatorypropertiescheck.enabled=true + +# +# Indicates whether the existing file plan is converted to a standard file plan during +# upgrade to V2.2, otherwise it will be converted to a DoD compliant file plan. +# +# Note that when converted to a standard file plan that DoD related record meta-data remains +# on the individual records and will not be visible in the UI, but can be assessed via +# deprecated model properties in the rma namespace. +# +rm.patch.v22.convertToStandardFilePlan=false diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml index 981675198a..e4957c7b11 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml @@ -735,6 +735,73 @@ d:text true + + + + + + + d:date + false + + + d:text + false + + true + false + false + + + + d:text + false + + true + false + false + + + + d:text + false + + true + false + false + + + + d:text + false + + true + false + false + + + + d:date + false + + + d:text + false + + true + false + false + + + + d:text + false + + true + false + false + + diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v22-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v22-context.xml index a9f5b2c601..ebe66b66e7 100755 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v22-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v22-context.xml @@ -4,7 +4,6 @@ - @@ -32,9 +31,9 @@ - + + - + @@ -101,6 +101,6 @@ - + \ No newline at end of file diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/dod5015/DOD5015Model.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/dod5015/DOD5015Model.java index 539add123f..3fcc87ac46 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/dod5015/DOD5015Model.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/dod5015/DOD5015Model.java @@ -46,6 +46,8 @@ public interface DOD5015Model QName PROP_MEDIA_TYPE = QName.createQName(DOD_URI, "mediaType"); QName PROP_FORMAT = QName.createQName(DOD_URI, "format"); QName PROP_DATE_RECEIVED = QName.createQName(DOD_URI, "dateReceived"); + QName PROP_ADDRESS = QName.createQName(DOD_URI, "address"); + QName PROP_OTHER_ADDRESS = QName.createQName(DOD_URI, "otherAddress"); // Scanned Record QName ASPECT_SCANNED_RECORD = QName.createQName(DOD_URI, "scannedRecord"); diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/email/CustomEmailMappingServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/email/CustomEmailMappingServiceImpl.java index 54aaacea30..904e9e50c0 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/email/CustomEmailMappingServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/email/CustomEmailMappingServiceImpl.java @@ -72,11 +72,11 @@ public class CustomEmailMappingServiceImpl extends AbstractLifecycleBean impleme /** Default custom mappings (TODO move to spring config) */ private static final CustomMapping[] DEFAULT_MAPPINGS = { - new CustomMapping("Date", "rma:dateReceived"), - new CustomMapping("messageTo", "rma:address"), - new CustomMapping("messageFrom", "rma:originator"), - new CustomMapping("messageSent", "rma:publicationDate"), - new CustomMapping("messageCc", "rma:otherAddress") + new CustomMapping("Date", "dod:dateReceived"), + new CustomMapping("messageTo", "dod:address"), + new CustomMapping("messageFrom", "dod:originator"), + new CustomMapping("messageSent", "dod:publicationDate"), + new CustomMapping("messageCc", "dod:otherAddress") }; /** Extractor */ diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/AbstractModulePatch.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/AbstractModulePatch.java index 54f526acb3..c3bed75b30 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/AbstractModulePatch.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/AbstractModulePatch.java @@ -18,6 +18,8 @@ */ package org.alfresco.module.org_alfresco_module_rm.patch; +import java.util.concurrent.TimeUnit; + import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.transaction.TransactionService; import org.apache.commons.logging.Log; @@ -73,12 +75,12 @@ public abstract class AbstractModulePatch implements ModulePatch, BeanNameAware modulePatchExecuter.register(this); } - protected void setTxnReadOnly(boolean txnReadOnly) + public void setTxnReadOnly(boolean txnReadOnly) { this.txnReadOnly = txnReadOnly; } - protected void setTxnRequiresNew(boolean txnRequiresNew) + public void setTxnRequiresNew(boolean txnRequiresNew) { this.txnRequiresNew = txnRequiresNew; } @@ -229,15 +231,19 @@ public abstract class AbstractModulePatch implements ModulePatch, BeanNameAware ",target=" + targetSchema); } + long startTime = System.nanoTime(); + // do patch in transaction transactionService.getRetryingTransactionHelper().doInTransaction( new ApplyCallback(), txnReadOnly, txnRequiresNew); + + long elapsedTime = System.nanoTime() - startTime; if (LOGGER.isInfoEnabled()) { - LOGGER.info(" ... module patch applied"); + LOGGER.info(" ... module patch applied in " + TimeUnit.NANOSECONDS.toMillis(elapsedTime) + "ms"); } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v22/RMv22DODCompliantSitePatch.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v22/RMv22DODCompliantSitePatch.java index e034b626ef..6d5cd5d907 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v22/RMv22DODCompliantSitePatch.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v22/RMv22DODCompliantSitePatch.java @@ -36,6 +36,9 @@ public class RMv22DODCompliantSitePatch extends AbstractModulePatch { /** QName DAO */ private QNameDAO qnameDAO; + + /** indicates whether we convert to a standard file plan or not */ + private boolean convertToStandardFilePlan = false; /** * @param qnameDAO QName DAO @@ -45,24 +48,35 @@ public class RMv22DODCompliantSitePatch extends AbstractModulePatch this.qnameDAO = qnameDAO; } + /** + * @param convertToStandardFilePlan convert to standard file if true, false otherwise + */ + public void setConvertToStandardFilePlan(boolean convertToStandardFilePlan) + { + this.convertToStandardFilePlan = convertToStandardFilePlan; + } + /** * @see org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch#applyInternal() */ @Override public void applyInternal() { - // ensure all existing sites are of the correct type - if (qnameDAO.getQName(RecordsManagementModel.TYPE_RM_SITE) != null && - qnameDAO.getQName(DOD5015Model.TYPE_DOD_5015_SITE) == null) - { - qnameDAO.updateQName(RecordsManagementModel.TYPE_RM_SITE, DOD5015Model.TYPE_DOD_5015_SITE); - } - - // ensure all the existing file plans are of the correct type - if (qnameDAO.getQName(RecordsManagementModel.TYPE_FILE_PLAN) != null && - qnameDAO.getQName(DOD5015Model.TYPE_DOD_5015_FILE_PLAN) == null) - { - qnameDAO.updateQName(RecordsManagementModel.TYPE_FILE_PLAN, DOD5015Model.TYPE_DOD_5015_FILE_PLAN); - } + if (!convertToStandardFilePlan) + { + // ensure all existing sites are of the correct type + if (qnameDAO.getQName(RecordsManagementModel.TYPE_RM_SITE) != null && + qnameDAO.getQName(DOD5015Model.TYPE_DOD_5015_SITE) == null) + { + qnameDAO.updateQName(RecordsManagementModel.TYPE_RM_SITE, DOD5015Model.TYPE_DOD_5015_SITE); + } + + // ensure all the existing file plans are of the correct type + if (qnameDAO.getQName(RecordsManagementModel.TYPE_FILE_PLAN) != null && + qnameDAO.getQName(DOD5015Model.TYPE_DOD_5015_FILE_PLAN) == null) + { + qnameDAO.updateQName(RecordsManagementModel.TYPE_FILE_PLAN, DOD5015Model.TYPE_DOD_5015_FILE_PLAN); + } + } } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v22/RMv22DODModelSeparationModulePatch.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v22/RMv22DODModelSeparationModulePatch.java index 5df14828f2..b2b0296f37 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v22/RMv22DODModelSeparationModulePatch.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v22/RMv22DODModelSeparationModulePatch.java @@ -20,7 +20,6 @@ package org.alfresco.module.org_alfresco_module_rm.patch.v22; import java.io.Serializable; import java.util.Collections; -import java.util.List; import java.util.Map; import org.alfresco.module.org_alfresco_module_rm.dod5015.DOD5015Model; @@ -28,7 +27,8 @@ import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch; import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.domain.patch.PatchDAO; -import org.alfresco.repo.domain.qname.QNameDAO; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; import org.alfresco.util.Pair; @@ -43,9 +43,9 @@ public class RMv22DODModelSeparationModulePatch extends AbstractModulePatch { /** query batch size */ private static final long BATCH_SIZE = 100000L; - - /** QName DAO */ - private QNameDAO qnameDAO; + + /** indicates whether we convert to a standard file plan or not */ + private boolean convertToStandardFilePlan = false; /** Patch DAO */ private PatchDAO patchDAO; @@ -61,16 +61,18 @@ public class RMv22DODModelSeparationModulePatch extends AbstractModulePatch DOD5015Model.PROP_PUBLICATION_DATE, DOD5015Model.PROP_MEDIA_TYPE, DOD5015Model.PROP_FORMAT, - DOD5015Model.PROP_DATE_RECEIVED + DOD5015Model.PROP_DATE_RECEIVED, + DOD5015Model.PROP_ADDRESS, + DOD5015Model.PROP_OTHER_ADDRESS }; - + /** - * @param qnameDAO QName DAO + * @param convertToStandardFilePlan convert to standard file if true, false otherwise */ - public void setQnameDAO(QNameDAO qnameDAO) + public void setConvertToStandardFilePlan(boolean convertToStandardFilePlan) { - this.qnameDAO = qnameDAO; - } + this.convertToStandardFilePlan = convertToStandardFilePlan; + } /** * @param patchDAO patch DAO @@ -94,50 +96,73 @@ public class RMv22DODModelSeparationModulePatch extends AbstractModulePatch @Override public void applyInternal() { - Long maxNodeId = patchDAO.getMaxAdmNodeID(); - long recordCount = patchDAO.getCountNodesWithAspects(Collections.singleton(ASPECT_RECORD)); - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug(" ... updating " + recordCount + " records"); - } + if (!convertToStandardFilePlan) + { + Long maxNodeId = patchDAO.getMaxAdmNodeID(); + long recordCount = patchDAO.getCountNodesWithAspects(Collections.singleton(ASPECT_RECORD)); + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug(" ... updating " + recordCount + " records in batches of " + BATCH_SIZE); + } + + // apply the DOD record aspect to all exiting records + int completed = 0; + for (Long i = 0L; i < maxNodeId; i+=BATCH_SIZE) + { + final Long finali = i; + Integer batchCount = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback() + { + int batchCount = 0; + + public Integer execute() throws Throwable + { + nodeDAO.getNodesWithAspects(Collections.singleton(ASPECT_RECORD), finali, finali + BATCH_SIZE, new NodeDAO.NodeRefQueryCallback() + { + public boolean handle(Pair nodePair) + { + // get the records properties + Map properties = nodeDAO.getNodeProperties(nodePair.getFirst()); + boolean changed = false; - // apply the DOD record aspect to all exiting records - int completed = 0; - Pair recordAspect = qnameDAO.getQName(ASPECT_RECORD); - if (recordAspect != null) - { - for (Long i = 0L; i < maxNodeId; i+=BATCH_SIZE) - { - List nodeIds = patchDAO.getNodesByAspectQNameId(recordAspect.getFirst(), i, i + BATCH_SIZE); - for (Long nodeId : nodeIds) - { - // get the records properties - Map properties = nodeDAO.getNodeProperties(nodeId); - - for (QName qname : qnames) - { - // if the record has any of the moved properties - QName origional = QName.createQName(RecordsManagementModel.RM_URI, qname.getLocalName()); - if (properties.containsKey(origional)) - { - // move the property value - Serializable value = properties.get(origional); - properties.put(qname, value); - properties.remove(origional); - } - } - - // set properties and add aspect - nodeDAO.setNodeProperties(nodeId, properties); - nodeDAO.addNodeAspects(nodeId, Collections.singleton(DOD5015Model.ASPECT_DOD_5015_RECORD)); - } + for (QName qname : qnames) + { + // if the record has any of the moved properties + QName origional = QName.createQName(RecordsManagementModel.RM_URI, qname.getLocalName()); + if (properties.containsKey(origional)) + { + // move the property value + Serializable value = properties.get(origional); + properties.put(qname, value); + properties.remove(origional); + changed = true; + } + } - completed += completed + nodeIds.size(); - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug(" ... completed " + completed + " of " + recordCount); - } - } - } + // set properties and add aspect + if (changed) + { + nodeDAO.setNodeProperties(nodePair.getFirst(), properties); + } + nodeDAO.addNodeAspects(nodePair.getFirst(), Collections.singleton(DOD5015Model.ASPECT_DOD_5015_RECORD)); + batchCount ++; + + return true; + } + }); + + return batchCount; + } + } , false, true); + + if (batchCount != 0) + { + completed = completed + batchCount; + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug(" ... completed " + completed + " of " + recordCount); + } + } + } + } } }