From c4ae3bd5fa42b36c207fc64e5c5fca26f2fa69a5 Mon Sep 17 00:00:00 2001 From: Britt Park Date: Thu, 21 Dec 2006 18:19:54 +0000 Subject: [PATCH] Clears up problems submitting deleted files via workflow. Still need to systematically go through DeletedNode implementation to make sure it's fully first class. Adding some debugging code that throws exceptions if it detects certain kinds of races. It can be turned off but I want to leave it on until GA. And, you'll need to start from a clean database as the AVM schema have changed. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@4683 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../org/alfresco/repo/avm/AVMCrawlTestP.java | 2 +- .../org/alfresco/repo/avm/AVMCrawler.java | 8 ++- .../org/alfresco/repo/avm/AVMNodeImpl.java | 31 ++++++++++++ .../alfresco/repo/avm/AVMSyncServiceImpl.java | 2 +- .../org/alfresco/repo/avm/ChildEntryImpl.java | 21 ++++++++ .../alfresco/repo/avm/DeletedNodeImpl.java | 16 +++++- .../repo/avm/LayeredDirectoryNodeImpl.java | 32 ++++++++++++ .../repo/avm/PlainDirectoryNodeImpl.java | 12 +++++ .../alfresco/repo/avm/hibernate/AVM.hbm.xml | 18 ++++--- .../RetryingTransactionAdvice.java | 1 + .../service/cmr/avm/AVMReadOnlyException.java | 50 +++++++++++++++++++ 11 files changed, 180 insertions(+), 13 deletions(-) create mode 100644 source/java/org/alfresco/service/cmr/avm/AVMReadOnlyException.java diff --git a/source/java/org/alfresco/repo/avm/AVMCrawlTestP.java b/source/java/org/alfresco/repo/avm/AVMCrawlTestP.java index eabe3139a8..bf3ac318d4 100644 --- a/source/java/org/alfresco/repo/avm/AVMCrawlTestP.java +++ b/source/java/org/alfresco/repo/avm/AVMCrawlTestP.java @@ -37,7 +37,7 @@ public class AVMCrawlTestP extends AVMServiceTestBase { int n = 4; // Number of Threads. int m = 12; // How many multiples of content to start with. - long runTime = 7200000; // 6 hours. + long runTime = 28800000; // 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 37ea42cbc7..a3f64d6785 100644 --- a/source/java/org/alfresco/repo/avm/AVMCrawler.java +++ b/source/java/org/alfresco/repo/avm/AVMCrawler.java @@ -169,6 +169,7 @@ class AVMCrawler implements Runnable for (int i = 0; i < 2; i++) { String path = files.get(fRandom.nextInt(files.size())).getPath(); + System.out.println("Modifying: " + path); PrintStream out = new PrintStream(fService.getFileOutputStream(path)); out.println("I am " + path); out.close(); @@ -181,6 +182,7 @@ class AVMCrawler implements Runnable for (int i = 0; i < 1; i++) { String name = randomName(); + System.out.println("Creating File: " + name); fService.createFile(dir.getPath(), name, new ByteArrayInputStream(("I am " + name).getBytes())); fOpCount++; @@ -190,6 +192,7 @@ class AVMCrawler implements Runnable if (fRandom.nextInt(100) == 0) { String name = randomName(); + System.out.println("Creating Directory: " + name); fService.createDirectory(dir.getPath(), name); fOpCount++; } @@ -199,8 +202,10 @@ class AVMCrawler implements Runnable if (fRandom.nextInt(100) == 0) { List names = new ArrayList(listing.keySet()); + String name = names.get(fRandom.nextInt(names.size())); + System.out.println("Removing: " + name); fService.removeNode(dir.getPath(), - names.get(fRandom.nextInt(names.size()))); + name); fOpCount++; } } @@ -216,6 +221,7 @@ class AVMCrawler implements Runnable } if (fRandom.nextInt(16) == 0) { + System.out.println("Snapshotting: " + repDesc.getName()); fService.createSnapshot(repDesc.getName(), null, null); fOpCount++; } diff --git a/source/java/org/alfresco/repo/avm/AVMNodeImpl.java b/source/java/org/alfresco/repo/avm/AVMNodeImpl.java index 9b677244d7..a9be1cd879 100644 --- a/source/java/org/alfresco/repo/avm/AVMNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMNodeImpl.java @@ -25,6 +25,7 @@ import java.util.Map; import org.alfresco.repo.avm.util.RawServices; import org.alfresco.repo.domain.DbAccessControlList; import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.service.cmr.avm.AVMReadOnlyException; import org.alfresco.service.namespace.QName; /** @@ -33,6 +34,8 @@ import org.alfresco.service.namespace.QName; */ public abstract class AVMNodeImpl implements AVMNode, Serializable { + protected static final boolean DEBUG = true; + /** * The Object ID. */ @@ -284,6 +287,10 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable */ public void updateModTime() { + if (DEBUG) + { + checkReadOnly(); + } String user = RawServices.Instance().getAuthenticationComponent().getCurrentUserName(); if (user == null) @@ -356,6 +363,10 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable */ public void setProperty(QName name, PropertyValue value) { + if (DEBUG) + { + checkReadOnly(); + } AVMNodeProperty prop = AVMDAOs.Instance().fAVMNodePropertyDAO.get(this, name); if (prop != null) { @@ -376,6 +387,10 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable */ public void setProperties(Map properties) { + if (DEBUG) + { + checkReadOnly(); + } for (QName name : properties.keySet()) { setProperty(name, properties.get(name)); @@ -418,6 +433,10 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable */ public void deleteProperty(QName name) { + if (DEBUG) + { + checkReadOnly(); + } AVMDAOs.Instance().fAVMNodePropertyDAO.delete(this, name); } @@ -426,6 +445,10 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable */ public void deleteProperties() { + if (DEBUG) + { + checkReadOnly(); + } AVMDAOs.Instance().fAVMNodePropertyDAO.deleteAll(this); } @@ -464,4 +487,12 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable { return fStoreNew; } + + protected void checkReadOnly() + { + if (getStoreNew() == null) + { + throw new AVMReadOnlyException("Write Operation on R/O Node."); + } + } } diff --git a/source/java/org/alfresco/repo/avm/AVMSyncServiceImpl.java b/source/java/org/alfresco/repo/avm/AVMSyncServiceImpl.java index e6392a4814..8d9987189f 100644 --- a/source/java/org/alfresco/repo/avm/AVMSyncServiceImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMSyncServiceImpl.java @@ -382,7 +382,7 @@ public class AVMSyncServiceImpl implements AVMSyncService case AVMDifference.NEWER : { // You can't delete what isn't there. - linkIn(dstParts[0], dstParts[1], srcDesc, excluder, dstDesc != null); + linkIn(dstParts[0], dstParts[1], srcDesc, excluder, dstDesc != null && !dstDesc.isDeleted()); continue; } case AVMDifference.OLDER : diff --git a/source/java/org/alfresco/repo/avm/ChildEntryImpl.java b/source/java/org/alfresco/repo/avm/ChildEntryImpl.java index 2b2c2c71a4..89d8fa16a1 100644 --- a/source/java/org/alfresco/repo/avm/ChildEntryImpl.java +++ b/source/java/org/alfresco/repo/avm/ChildEntryImpl.java @@ -37,6 +37,11 @@ public class ChildEntryImpl implements ChildEntry, Serializable */ private AVMNode fChild; + /** + * Version for optimistic locking. + */ + private long fVers; + /** * Default constructor for Hibernate. */ @@ -121,4 +126,20 @@ public class ChildEntryImpl implements ChildEntry, Serializable { return fKey.hashCode(); } + + /** + * Setter. + */ + public void setVers(long vers) + { + fVers = vers; + } + + /** + * Getter. + */ + public long getVers() + { + return fVers; + } } diff --git a/source/java/org/alfresco/repo/avm/DeletedNodeImpl.java b/source/java/org/alfresco/repo/avm/DeletedNodeImpl.java index 9f2c01ff4a..4c8241dc5a 100644 --- a/source/java/org/alfresco/repo/avm/DeletedNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/DeletedNodeImpl.java @@ -50,6 +50,17 @@ public class DeletedNodeImpl extends AVMNodeImpl implements DeletedNode super(id, store); } + public DeletedNodeImpl(DeletedNode other, + AVMStore store) + { + super(store.getAVMRepository().issueID(), store); + AVMDAOs.Instance().fAVMNodeDAO.save(this); + AVMDAOs.Instance().fAVMNodeDAO.flush(); + copyProperties(other); + copyAspects(other); + copyACLs(other); + } + /** * Setter. */ @@ -71,8 +82,9 @@ public class DeletedNodeImpl extends AVMNodeImpl implements DeletedNode */ public AVMNode copy(Lookup lPath) { - assert false; - return null; + AVMNode newMe = new DeletedNodeImpl(this, lPath.getAVMStore()); + newMe.setAncestor(this); + return newMe; } /** diff --git a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java index cf07381390..b720cf1f33 100644 --- a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java @@ -280,6 +280,10 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec */ public void putChild(String name, AVMNode node) { + if (DEBUG) + { + checkReadOnly(); + } ChildKey key = new ChildKey(this, name); ChildEntry existing = AVMDAOs.Instance().fChildEntryDAO.get(key); if (existing != null) @@ -548,6 +552,10 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec @SuppressWarnings("unchecked") public void removeChild(Lookup lPath, String name) { + if (DEBUG) + { + checkReadOnly(); + } ChildKey key = new ChildKey(this, name); ChildEntry entry = AVMDAOs.Instance().fChildEntryDAO.get(key); AVMNode child = null; @@ -607,6 +615,10 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec */ public void rawSetPrimary(String path) { + if (DEBUG) + { + checkReadOnly(); + } fIndirection = path; fPrimaryIndirection = true; } @@ -617,6 +629,10 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec */ public void turnPrimary(Lookup lPath) { + if (DEBUG) + { + checkReadOnly(); + } String path = lPath.getCurrentIndirection(); rawSetPrimary(path); } @@ -627,6 +643,10 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec */ public void retarget(Lookup lPath, String target) { + if (DEBUG) + { + checkReadOnly(); + } rawSetPrimary(target); } @@ -637,6 +657,10 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec */ public void uncover(Lookup lPath, String name) { + if (DEBUG) + { + checkReadOnly(); + } ChildKey key = new ChildKey(this, name); ChildEntry entry = AVMDAOs.Instance().fChildEntryDAO.get(key); if (entry.getChild().getType() != AVMNodeType.DELETED_NODE) @@ -800,6 +824,10 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec */ public void link(Lookup lPath, String name, AVMNodeDescriptor toLink) { + if (DEBUG) + { + checkReadOnly(); + } AVMNode node = AVMDAOs.Instance().fAVMNodeDAO.getByID(toLink.getId()); if (node == null) { @@ -840,6 +868,10 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec */ public void flatten(String name) { + if (DEBUG) + { + checkReadOnly(); + } ChildKey key = new ChildKey(this, name); ChildEntry entry = AVMDAOs.Instance().fChildEntryDAO.get(key); if (entry != null) diff --git a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java index 9735e50dfc..4422a68b59 100644 --- a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java @@ -220,6 +220,10 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory @SuppressWarnings("unchecked") public void removeChild(Lookup lPath, String name) { + if (DEBUG) + { + checkReadOnly(); + } ChildKey key = new ChildKey(this, name); ChildEntry entry = AVMDAOs.Instance().fChildEntryDAO.get(key); if (entry != null) @@ -254,6 +258,10 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory */ public void putChild(String name, AVMNode node) { + if (DEBUG) + { + checkReadOnly(); + } ChildKey key = new ChildKey(this, name); ChildEntry existing = AVMDAOs.Instance().fChildEntryDAO.get(key); if (existing != null) @@ -434,6 +442,10 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory */ public void link(Lookup lPath, String name, AVMNodeDescriptor toLink) { + if (DEBUG) + { + checkReadOnly(); + } // Assure that the incoming node exists. AVMNode node = AVMDAOs.Instance().fAVMNodeDAO.getByID(toLink.getId()); if (node == null) diff --git a/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml b/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml index 9f3616b570..1d90b1ef35 100644 --- a/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml +++ b/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml @@ -139,14 +139,16 @@ - - - - - - - + + + + + + + + diff --git a/source/java/org/alfresco/repo/transaction/RetryingTransactionAdvice.java b/source/java/org/alfresco/repo/transaction/RetryingTransactionAdvice.java index 8491d58bd6..a69638dd33 100644 --- a/source/java/org/alfresco/repo/transaction/RetryingTransactionAdvice.java +++ b/source/java/org/alfresco/repo/transaction/RetryingTransactionAdvice.java @@ -143,6 +143,7 @@ public class RetryingTransactionAdvice implements MethodInterceptor } if (shouldRetry) { + fgLogger.warn("Retry #" + (count + 1)); continue; } throw e; diff --git a/source/java/org/alfresco/service/cmr/avm/AVMReadOnlyException.java b/source/java/org/alfresco/service/cmr/avm/AVMReadOnlyException.java new file mode 100644 index 0000000000..86d1f8416c --- /dev/null +++ b/source/java/org/alfresco/service/cmr/avm/AVMReadOnlyException.java @@ -0,0 +1,50 @@ +/** + * + */ +package org.alfresco.service.cmr.avm; + +/** + * A Debugging exception. + * @author britt + */ +public class AVMReadOnlyException extends AVMException +{ + private static final long serialVersionUID = 5074287797390504317L; + + /** + * @param msgId + */ + public AVMReadOnlyException(String msgId) + { + super(msgId); + } + + /** + * @param msgId + * @param msgParams + */ + public AVMReadOnlyException(String msgId, Object[] msgParams) + { + super(msgId, msgParams); + } + + /** + * @param msgId + * @param cause + */ + public AVMReadOnlyException(String msgId, Throwable cause) + { + super(msgId, cause); + } + + /** + * @param msgId + * @param msgParams + * @param cause + */ + public AVMReadOnlyException(String msgId, Object[] msgParams, + Throwable cause) + { + super(msgId, msgParams, cause); + } +}