mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
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:
@@ -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);
|
||||
|
@@ -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++;
|
||||
}
|
||||
|
@@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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 :
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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>
|
||||
|
@@ -143,6 +143,7 @@ public class RetryingTransactionAdvice implements MethodInterceptor
|
||||
}
|
||||
if (shouldRetry)
|
||||
{
|
||||
fgLogger.warn("Retry #" + (count + 1));
|
||||
continue;
|
||||
}
|
||||
throw e;
|
||||
|
Reference in New Issue
Block a user