diff --git a/source/java/org/alfresco/repo/avm/AVMRepository.java b/source/java/org/alfresco/repo/avm/AVMRepository.java index 1084131e40..7776e61db2 100644 --- a/source/java/org/alfresco/repo/avm/AVMRepository.java +++ b/source/java/org/alfresco/repo/avm/AVMRepository.java @@ -1285,4 +1285,38 @@ public class AVMRepository } dir.link(name, child); } + + /** + * Remove name without leaving behind a deleted node. Dangerous + * if used unwisely. + * @param lDir The layered directory node. + * @param name The name of the child. + */ + public void flatten(AVMNodeDescriptor lDir, String name) + { + AVMNode node = AVMContext.fgInstance.fAVMNodeDAO.getByID(lDir.getId()); + if (!(node instanceof LayeredDirectoryNode)) + { + throw new AVMWrongTypeException("Not a Layered Directory."); + } + LayeredDirectoryNode dir = (LayeredDirectoryNode)node; + if (!dir.getIsNew()) + { + throw new AVMException("Directory has not already been copied."); + } + dir.flatten(name); + } + + /** + * Force a copy on write. + * @param path The path to force. + */ + public void forceCopy(String path) + { + fLookupCount.set(1); + String [] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + // Just force a copy if needed by looking up in write mode. + store.lookup(-1, pathParts[1], true, false); + } } diff --git a/source/java/org/alfresco/repo/avm/AVMServiceImpl.java b/source/java/org/alfresco/repo/avm/AVMServiceImpl.java index 06323a2098..09df3b0f0b 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceImpl.java @@ -1083,4 +1083,35 @@ public class AVMServiceImpl implements AVMService } fAVMRepository.link(parent, name, child); } + + /** + * Flatten a direct child of a layered directory. This does + * the equivalent of removing the given child from the directory + * and then doing an uncover. This routine makes many dangerous + * assumptions and is only for use by AVMSyncService. Don't use it + * if you don't know precisely what you are doing. + * @param lDir The layered directory node. + * @param name The name to flatten. + */ + public void flatten(AVMNodeDescriptor lDir, String name) + { + if (lDir == null || name == null) + { + throw new AVMBadArgumentException("Illegal Null Argument."); + } + fAVMRepository.flatten(lDir, name); + } + + /** + * Force copy on write of a path. + * @param path The path to force. + */ + public void forceCopy(String path) + { + if (path == null) + { + throw new AVMBadArgumentException("Null Path."); + } + fAVMRepository.forceCopy(path); + } } diff --git a/source/java/org/alfresco/repo/avm/AVMSyncServiceImpl.java b/source/java/org/alfresco/repo/avm/AVMSyncServiceImpl.java index 8f0f293678..21cad20548 100644 --- a/source/java/org/alfresco/repo/avm/AVMSyncServiceImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMSyncServiceImpl.java @@ -593,6 +593,8 @@ public class AVMSyncServiceImpl implements AVMSyncService { return true; } + fAVMService.forceCopy(layer.getPath()); + layer = fAVMService.lookup(-1, layer.getPath()); // Grab the listing Map underListing = fAVMService.getDirectoryListing(underlying, true); @@ -608,16 +610,14 @@ public class AVMSyncServiceImpl implements AVMSyncService // We've found an identity so flatten it. if (topNode.getId() == bottomNode.getId()) { - fAVMService.removeNode(layer.getPath(), name); - fAVMService.uncover(layer.getPath(), name); + fAVMService.flatten(layer, name); } else { // Otherwise recursively flatten the children. if (flatten(topNode, bottomNode)) { - fAVMService.removeNode(layer.getPath(), name); - fAVMService.uncover(layer.getPath(), name); + fAVMService.flatten(layer, name); } else { diff --git a/source/java/org/alfresco/repo/avm/LayeredDirectoryNode.java b/source/java/org/alfresco/repo/avm/LayeredDirectoryNode.java index 8f6b67882d..fafa8f59ca 100644 --- a/source/java/org/alfresco/repo/avm/LayeredDirectoryNode.java +++ b/source/java/org/alfresco/repo/avm/LayeredDirectoryNode.java @@ -59,6 +59,12 @@ public interface LayeredDirectoryNode extends DirectoryNode, Layered */ public void uncover(Lookup lPath, String name); + /** + * Remove name without leaving behind a deleted node. + * @param name The name of the child to flatten. + */ + public void flatten(String name); + /** * Set the indirection. * @param indirection diff --git a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java index 259c474e6d..cb8badfdae 100644 --- a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java @@ -832,4 +832,17 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec ChildEntry newChild = new ChildEntryImpl(name, this, node); AVMContext.fgInstance.fChildEntryDAO.save(newChild); } + + /** + * Remove name without leaving behind a deleted node. + * @param name The name of the child to flatten. + */ + public void flatten(String name) + { + ChildEntry entry = AVMContext.fgInstance.fChildEntryDAO.getByNameParent(name, this); + if (entry != null) + { + AVMContext.fgInstance.fChildEntryDAO.delete(entry); + } + } } diff --git a/source/java/org/alfresco/service/cmr/avm/AVMService.java b/source/java/org/alfresco/service/cmr/avm/AVMService.java index 24c99f3c40..ada6e1c808 100644 --- a/source/java/org/alfresco/service/cmr/avm/AVMService.java +++ b/source/java/org/alfresco/service/cmr/avm/AVMService.java @@ -696,4 +696,21 @@ public interface AVMService * @param child The child node to link. */ public void link(AVMNodeDescriptor parent, String name, AVMNodeDescriptor child); + + /** + * Flatten a direct child of a layered directory. This does + * the equivalent of removing the given child from the directory + * and then doing an uncover. This routine makes many dangerous + * assumptions and is only for use by AVMSyncService. Don't use it + * if you don't know precisely what you are doing. + * @param lDir The layered directory node. + * @param name The name to flatten. + */ + public void flatten(AVMNodeDescriptor lDir, String name); + + /** + * Force copy on write of a path. + * @param path The path to force. + */ + public void forceCopy(String path); }