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); + } +}