diff --git a/config/alfresco/action-services-context.xml b/config/alfresco/action-services-context.xml index 79b36a8294..b04f80f4e4 100644 --- a/config/alfresco/action-services-context.xml +++ b/config/alfresco/action-services-context.xml @@ -457,6 +457,18 @@ + + + + + + + + + false + + + diff --git a/config/alfresco/messages/action-config.properties b/config/alfresco/messages/action-config.properties index 4f1cf4e20a..12d3b36ed5 100644 --- a/config/alfresco/messages/action-config.properties +++ b/config/alfresco/messages/action-config.properties @@ -107,6 +107,10 @@ avm-revert-list.store.display-label=The name of the store being reverted, only n avm-revert-list.staging.display-label=The name of the staging store to flatten to. avm-revert-list.flatten-path.display-label=The store relative path that should be flattened. +avm-revert-to-version.title=Revert a Node to a particular version. +avm-revert-to-version.description=This reverts a Node to a particular version of that node. +avm-revert-to-version.to-revert.display-label=The AVM Node Descriptor of the version to revert to. + avm-undo-list.title=Make a list of Nodes in a store transparent to staging. avm-undo-list.description=This acts as a mistake eraser for a user's sandbox. avm-undo-list.node-list.display-label=The string encoded list of nodes to revert. diff --git a/source/java/org/alfresco/repo/avm/AVMCrawlTestP.java b/source/java/org/alfresco/repo/avm/AVMCrawlTestP.java index e723dbb67b..1c63b95967 100644 --- a/source/java/org/alfresco/repo/avm/AVMCrawlTestP.java +++ b/source/java/org/alfresco/repo/avm/AVMCrawlTestP.java @@ -36,8 +36,8 @@ public class AVMCrawlTestP extends AVMServiceTestBase public void testCrawl() { int n = 4; // Number of Threads. - int m = 12; // How many multiples of content to start with. - long runTime = 36000000; // 6 hours. + int m = 192; // How many multiples of content to start with. + long runTime = 3600000; // 6 hours. fService.purgeStore("main"); BulkLoader loader = new BulkLoader(); loader.setAvmService(fService); diff --git a/source/java/org/alfresco/repo/avm/AVMCrawler.java b/source/java/org/alfresco/repo/avm/AVMCrawler.java index d31f776795..5c623fa4c8 100644 --- a/source/java/org/alfresco/repo/avm/AVMCrawler.java +++ b/source/java/org/alfresco/repo/avm/AVMCrawler.java @@ -120,7 +120,7 @@ class AVMCrawler implements Runnable { List reps = fService.getStores(); fOpCount++; - AVMStoreDescriptor repDesc = reps.get(fRandom.nextInt(reps.size())); + AVMStoreDescriptor repDesc = reps.get(fRandom.nextInt(12)); Map rootListing = fService.getDirectoryListing(-1, repDesc.getName() + ":/"); fOpCount++; // Get all the directories in the root. diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index d19dd97c45..be9eea6350 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -36,6 +36,7 @@ import org.alfresco.model.ContentModel; import org.alfresco.model.WCMModel; import org.alfresco.repo.action.ActionImpl; import org.alfresco.repo.avm.actions.AVMRevertListAction; +import org.alfresco.repo.avm.actions.AVMRevertToVersionAction; import org.alfresco.repo.avm.actions.AVMUndoSandboxListAction; import org.alfresco.repo.avm.actions.SimpleAVMPromoteAction; import org.alfresco.repo.avm.actions.SimpleAVMSubmitAction; @@ -71,6 +72,52 @@ import org.alfresco.util.Pair; */ public class AVMServiceTest extends AVMServiceTestBase { + /** + * Test the revert to version action. + */ + public void testRevertToVersionAction() + { + try + { + setupBasicTree(); + fService.getFileOutputStream("main:/a/b/c/foo").close(); + fService.createSnapshot("main", "v1", null); + fService.getFileOutputStream("main:/a/b/c/foo").close(); + fService.createSnapshot("main", "v2", null); + fService.getFileOutputStream("main:/a/b/c/foo").close(); + fService.createSnapshot("main", "v3", null); + fService.getFileOutputStream("main:/a/b/c/foo").close(); + fService.createSnapshot("main", "v4", null); + fService.getFileOutputStream("main:/a/b/c/foo").close(); + fService.createSnapshot("main", "v5", null); + fService.getFileOutputStream("main:/a/b/c/foo").close(); + AVMNodeDescriptor desc = fService.lookup(-1, "main:/a/b/c/foo"); + List history = fService.getHistory(desc, 100); + AVMNodeDescriptor toRevert = history.get(3); + final ActionImpl action = new ActionImpl(null, + GUID.generate(), + AVMRevertToVersionAction.NAME); + action.setParameterValue(AVMRevertToVersionAction.TOREVERT, toRevert); + final AVMRevertToVersionAction revert = (AVMRevertToVersionAction)fContext.getBean("avm-revert-to-version"); + class TxnWork implements TransactionUtil.TransactionWork + { + public Object doWork() throws Exception + { + revert.execute(action, AVMNodeConverter.ToNodeRef(-1, "main:/a/b/c/foo")); + return null; + } + }; + TransactionUtil.executeInUserTransaction((TransactionService)fContext.getBean("transactionComponent"), + new TxnWork()); + assertEquals(toRevert.getId(), fService.lookup(-1, "main:/a/b/c/foo").getId()); + } + catch (Exception e) + { + e.printStackTrace(); + fail(); + } + } + /** * Test version numbering. */ @@ -333,15 +380,11 @@ public class AVMServiceTest extends AVMServiceTestBase final ActionImpl action = new ActionImpl(null, GUID.generate(), AVMRevertListAction.NAME); - List> versionPaths = - new ArrayList>(); - versionPaths.add(new Pair(-1, "area:/a/b")); + List paths = + new ArrayList(); + paths.add("area:/a/b"); action.setParameterValue(AVMRevertListAction.PARAM_VERSION, fService.getLatestSnapshotID("area")); - action.setParameterValue(AVMRevertListAction.PARAM_NODE_LIST, (Serializable)versionPaths); - action.setParameterValue(AVMRevertListAction.PARAM_FLATTEN, true); - action.setParameterValue(AVMRevertListAction.PARAM_STORE, "area"); - action.setParameterValue(AVMRevertListAction.PARAM_STAGING, "main"); - action.setParameterValue(AVMRevertListAction.PARAM_FLATTEN_PATH, "/a"); + action.setParameterValue(AVMRevertListAction.PARAM_NODE_LIST, (Serializable)paths); final AVMRevertListAction revert = (AVMRevertListAction)fContext.getBean("avm-revert-list"); class TxnWork implements TransactionUtil.TransactionWork { diff --git a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java index 2b6008d0fa..6df22abe01 100644 --- a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java @@ -484,7 +484,8 @@ public class AVMStoreImpl implements AVMStore, Serializable SortedMap results = new TreeMap(); for (String name : listing.keySet()) { - AVMNode child = listing.get(name); + // TODO consider doing this at a lower level. + AVMNode child = AVMNodeUnwrapper.Unwrap(listing.get(name)); AVMNodeDescriptor desc = child.getDescriptor(lPath, name); results.put(name, desc); } diff --git a/source/java/org/alfresco/repo/avm/actions/AVMRevertListAction.java b/source/java/org/alfresco/repo/avm/actions/AVMRevertListAction.java index f0a709eb11..7d682f1d0f 100644 --- a/source/java/org/alfresco/repo/avm/actions/AVMRevertListAction.java +++ b/source/java/org/alfresco/repo/avm/actions/AVMRevertListAction.java @@ -14,12 +14,10 @@ import org.alfresco.service.cmr.avmsync.AVMDifference; import org.alfresco.service.cmr.avmsync.AVMSyncService; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.util.Pair; import org.apache.log4j.Logger; /** * This action handles reverting a selected set of nodes to a particular version. - * The set of of nodes is passed in as a packed string (Obtained by VersionPathStuffer). * The actionedUponNodeRef is a dummy and can be null. * @author britt */ @@ -33,13 +31,6 @@ public class AVMRevertListAction extends ActionExecuterAbstractBase // The encoded list of nodes. public static final String PARAM_NODE_LIST = "node-list"; // Flag for whether we should flatten after revert. - public static final String PARAM_FLATTEN = "flatten"; - // If we are flattening, then this holds the staging store name. - public static final String PARAM_STAGING = "staging"; - // If we are flattening, then this holds the reverted store's name - public static final String PARAM_STORE = "store"; - // If we are flattening, then this holds the path "/foo/bar/baz" to flatten. - public static final String PARAM_FLATTEN_PATH = "flatten-path"; /** * The sync service. @@ -61,27 +52,18 @@ public class AVMRevertListAction extends ActionExecuterAbstractBase protected void executeImpl(Action action, NodeRef actionedUponNodeRef) { int revertVersion = (Integer)action.getParameterValue(PARAM_VERSION); - List> versionPaths = - (List>)action.getParameterValue(PARAM_NODE_LIST); + List paths = + (List)action.getParameterValue(PARAM_NODE_LIST); List diffs = new ArrayList(); - for (Pair item : versionPaths) + for (String path : paths) { List diffSet = - fSyncService.compare(revertVersion, item.getSecond(), - -1, item.getSecond(), null); + fSyncService.compare(revertVersion, path, + -1, path, null); diffs.addAll(diffSet); } String message = "Reverted to version " + revertVersion; fSyncService.update(diffs, null, false, false, true, true, message, message); - if (!(Boolean)action.getParameterValue(PARAM_FLATTEN)) - { - return; - } - String storeName = (String)action.getParameterValue(PARAM_STORE); - String flattenPath = (String)action.getParameterValue(PARAM_FLATTEN_PATH); - String stagingName = (String)action.getParameterValue(PARAM_STAGING); - fSyncService.flatten(storeName + ":" + flattenPath, - stagingName + ":" + flattenPath); } /* (non-Javadoc) @@ -100,25 +82,5 @@ public class AVMRevertListAction extends ActionExecuterAbstractBase DataTypeDefinition.ANY, true, getParamDisplayLabel(PARAM_NODE_LIST))); - paramList.add( - new ParameterDefinitionImpl(PARAM_FLATTEN, - DataTypeDefinition.BOOLEAN, - false, - getParamDisplayLabel(PARAM_FLATTEN))); - paramList.add( - new ParameterDefinitionImpl(PARAM_STAGING, - DataTypeDefinition.TEXT, - false, - getParamDisplayLabel(PARAM_STAGING))); - paramList.add( - new ParameterDefinitionImpl(PARAM_STORE, - DataTypeDefinition.TEXT, - false, - getParamDisplayLabel(PARAM_STORE))); - paramList.add( - new ParameterDefinitionImpl(PARAM_FLATTEN_PATH, - DataTypeDefinition.TEXT, - false, - getParamDisplayLabel(PARAM_FLATTEN_PATH))); } } diff --git a/source/java/org/alfresco/repo/avm/actions/AVMRevertToVersionAction.java b/source/java/org/alfresco/repo/avm/actions/AVMRevertToVersionAction.java new file mode 100644 index 0000000000..3f50a506a9 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/actions/AVMRevertToVersionAction.java @@ -0,0 +1,105 @@ +/** + * + */ +package org.alfresco.repo.avm.actions; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.repo.action.ParameterDefinitionImpl; +import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; +import org.alfresco.repo.avm.AVMNodeConverter; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.action.ParameterDefinition; +import org.alfresco.service.cmr.avm.AVMNodeDescriptor; +import org.alfresco.service.cmr.avm.AVMService; +import org.alfresco.service.cmr.avmsync.AVMDifference; +import org.alfresco.service.cmr.avmsync.AVMSyncService; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.util.Pair; +import org.apache.log4j.Logger; + +/** + * Revert a single path to a specified node. The path in head is passed + * as actionedUponNodeRef. The node to revert to is passed as an AVMNodeDescriptor + * parameter. + * @author britt + */ +public class AVMRevertToVersionAction extends ActionExecuterAbstractBase +{ + private static Logger fgLogger = Logger.getLogger(AVMRevertToVersionAction.class); + + public static final String NAME = "avm-revert-to-version"; + // The node to revert to. Passed as an AVMNodeDescriptor. + public static final String TOREVERT = "to-revert"; + + private AVMService fAVMService; + + private AVMSyncService fAVMSyncService; + + /** + * Set the AVMService. + */ + public void setAvmService(AVMService service) + { + fAVMService = service; + } + + /** + * Set the AVMSyncService. + */ + public void setAvmSyncService(AVMSyncService service) + { + fAVMSyncService = service; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef) + */ + @Override + protected void executeImpl(Action action, NodeRef actionedUponNodeRef) + { + Pair versionPath = + AVMNodeConverter.ToAVMVersionPath(actionedUponNodeRef); + String [] storePath = versionPath.getSecond().split(":"); + String store = storePath[0]; + AVMNodeDescriptor toRevert = + (AVMNodeDescriptor)action.getParameterValue(TOREVERT); + List> paths = fAVMService.getPaths(toRevert); + Pair found = new Pair(Integer.MAX_VALUE, ""); + for (Pair path : paths) + { + if (!path.getSecond().startsWith(store + ':')) + { + continue; + } + if (path.getFirst() < found.getFirst()) + { + found = path; + } + } + // TODO I believe that this should always have found not + // the initial found. Must confirm. + AVMDifference diff = new AVMDifference(found.getFirst(), found.getSecond(), + -1, versionPath.getSecond(), + AVMDifference.NEWER); + List diffs = new ArrayList(1); + diffs.add(diff); + String message = "Reverted " + versionPath.getSecond() + " to version in snapshot " + found.getFirst() + "."; + fAVMSyncService.update(diffs, null, false, false, true, true, "Reverted", message); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) + */ + @Override + protected void addParameterDefinitions(List paramList) + { + paramList.add( + new ParameterDefinitionImpl(TOREVERT, + DataTypeDefinition.ANY, + true, + getParamDisplayLabel(TOREVERT))); + } +}