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
This commit is contained in:
Britt Park
2006-12-21 18:19:54 +00:00
parent b666af0eee
commit c4ae3bd5fa
11 changed files with 180 additions and 13 deletions

View File

@@ -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);

View File

@@ -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<String> names = new ArrayList<String>(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++;
}

View File

@@ -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<QName, PropertyValue> 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.");
}
}
}

View File

@@ -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 :

View File

@@ -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;
}
}

View File

@@ -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;
}
/**

View File

@@ -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)

View File

@@ -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)

View File

@@ -139,14 +139,16 @@
<property name="tag" type="string" length="255" column="tag"/>
<property name="description" type="string" length="8192" column="description"/>
</class>
<class name="ChildEntryImpl" proxy="ChildEntry" table="avm_child_entries">
<cache usage="read-write"/>
<composite-id name="key" class="ChildKey">
<key-many-to-one name="parent" column="parent_id" class="DirectoryNodeImpl"/>
<key-property name="name" column="name" type="string" length="160"/>
</composite-id>
<many-to-one name="child" column="child_id" class="AVMNodeImpl"
not-null="true"/>
<class name="ChildEntryImpl" proxy="ChildEntry" table="avm_child_entries"
optimistic-lock="version">
<cache usage="read-write"/>
<composite-id name="key" class="ChildKey">
<key-many-to-one name="parent" column="parent_id" class="DirectoryNodeImpl"/>
<key-property name="name" column="name" type="string" length="160"/>
</composite-id>
<version name="vers" column="vers" type="long"/>
<many-to-one name="child" column="child_id" class="AVMNodeImpl"
not-null="true"/>
</class>
<class name="HistoryLinkImpl" proxy="HistoryLink" table="avm_history_links">
<composite-id>

View File

@@ -143,6 +143,7 @@ public class RetryingTransactionAdvice implements MethodInterceptor
}
if (shouldRetry)
{
fgLogger.warn("Retry #" + (count + 1));
continue;
}
throw e;

View File

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