mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Merged V2.9 to HEAD
9845: Merged V2.2 to V2.9 9733: Merged V2.1 to V2.2 9281: Improvements to index AUTO recovery 9316: Fixed ETWOONE-193: Transactional caches not being cleaned up after rollback (2.1.4 regression) 9317: Fixed ETWOONE-194: Faster void handling during index tracking 9365: Improved performance for finding which snapshots have been indexed 9413: Support to retrieve read/write state of the transaction and ensure Lucene commits are handled last 9414: ACT-3245: Updating node properties and aspects don't bump the alf_node.version value 9415: Code cleanup: Removed unnecessary empty methods 9416: Fixed creation of multiple thread pools 9417: Full index recovery absorbs indexing exceptions by default 9418: Added AUTO index recovery option to sample in line with Wiki docs 9419: ETWOONE-194: Index tracking is too slow 9420: Fixed ETWOONE-201: Better logging and configurability for RetryingTransactionHelper 9421: Fixed ETWOONE-202: SPlit person cleanup doesn't break read-only transactions 9422: Follow up on CHK-3317: Removed use of JDK 1.6 NavigableMap interface 9423: Fixed unit test after CHK-3317 9424: More test fixes after CHK-3317 9425: Ensure that index tracking tests don't run too long. 9426: Made concurrent reindexing optional. It is on by default. 9509: ACT-3539: Mid-transaction locking on Lucene resources 9547: Multithreaded index tracking startup: Handle previously lagging single-threaded rebuilds git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@10592 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -27,20 +27,27 @@ package org.alfresco.repo.security.person;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.security.NoSuchPersonException;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.alfresco.util.EqualsHelper;
|
||||
import org.alfresco.util.GUID;
|
||||
|
||||
public class PersonTest extends BaseSpringTest
|
||||
{
|
||||
|
||||
private TransactionService transactionService;
|
||||
|
||||
private PersonService personService;
|
||||
|
||||
private NodeService nodeService;
|
||||
@@ -55,6 +62,7 @@ public class PersonTest extends BaseSpringTest
|
||||
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
transactionService = (TransactionService) applicationContext.getBean("transactionService");
|
||||
personService = (PersonService) applicationContext.getBean("personService");
|
||||
nodeService = (NodeService) applicationContext.getBean("nodeService");
|
||||
|
||||
@@ -66,6 +74,7 @@ public class PersonTest extends BaseSpringTest
|
||||
nodeService.deleteNode(nodeRef);
|
||||
}
|
||||
|
||||
personService.setCreateMissingPeople(true);
|
||||
}
|
||||
|
||||
protected void onTearDownInTransaction() throws Exception
|
||||
@@ -409,5 +418,143 @@ public class PersonTest extends BaseSpringTest
|
||||
}
|
||||
personService.getPerson("Derek");
|
||||
}
|
||||
|
||||
public void testReadOnlyTransactionHandling() throws Exception
|
||||
{
|
||||
// Kill the annoying Spring-managed txn
|
||||
super.setComplete();
|
||||
super.endTransaction();
|
||||
|
||||
boolean createMissingPeople = personService.createMissingPeople();
|
||||
assertTrue("Default should be to create missing people", createMissingPeople);
|
||||
|
||||
final String username = "Derek";
|
||||
// Make sure that the person is missing
|
||||
RetryingTransactionCallback<Object> deletePersonWork = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
personService.deletePerson(username);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(deletePersonWork, false, true);
|
||||
// Make a read-only transaction and check that we get NoSuchPersonException
|
||||
RetryingTransactionCallback<NodeRef> getMissingPersonWork = new RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
return personService.getPerson(username);
|
||||
}
|
||||
};
|
||||
try
|
||||
{
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(getMissingPersonWork, true, true);
|
||||
fail("Expected auto-creation of person to fail gracefully");
|
||||
}
|
||||
catch (NoSuchPersonException e)
|
||||
{
|
||||
// Expected
|
||||
}
|
||||
// It should work in a write transaction, though
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(getMissingPersonWork, false, true);
|
||||
}
|
||||
|
||||
public void testSplitPersonCleanup() throws Exception
|
||||
{
|
||||
// Kill the annoying Spring-managed txn
|
||||
super.setComplete();
|
||||
super.endTransaction();
|
||||
|
||||
boolean createMissingPeople = personService.createMissingPeople();
|
||||
assertTrue("Default should be to create missing people", createMissingPeople);
|
||||
|
||||
PersonServiceImpl personServiceImpl = (PersonServiceImpl) personService;
|
||||
personServiceImpl.setDuplicateMode("LEAVE");
|
||||
|
||||
// The user to duplicate
|
||||
final String duplicateUsername = GUID.generate();
|
||||
// Make sure that the person is missing
|
||||
RetryingTransactionCallback<Object> deletePersonWork = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
personService.deletePerson(duplicateUsername);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(deletePersonWork, false, true);
|
||||
// Fire off 10 threads to create the same person
|
||||
int threadCount = 10;
|
||||
final CountDownLatch startLatch = new CountDownLatch(threadCount);
|
||||
final CountDownLatch endLatch = new CountDownLatch(threadCount);
|
||||
final Map<String, NodeRef> cleanableNodeRefs = new HashMap<String, NodeRef>(17);
|
||||
Runnable createPersonRunnable = new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
final RetryingTransactionCallback<NodeRef> createPersonWork = new RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
// Wait for the trigger to start
|
||||
try { startLatch.await(); } catch (InterruptedException e) {}
|
||||
|
||||
// Trigger
|
||||
NodeRef personNodeRef = personService.getPerson(duplicateUsername);
|
||||
return personNodeRef;
|
||||
}
|
||||
};
|
||||
startLatch.countDown();
|
||||
try
|
||||
{
|
||||
NodeRef nodeRef = transactionService.getRetryingTransactionHelper().doInTransaction(createPersonWork, false, true);
|
||||
// Store the noderef for later checking
|
||||
String threadName = Thread.currentThread().getName();
|
||||
cleanableNodeRefs.put(threadName, nodeRef);
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
// Errrm
|
||||
e.printStackTrace();
|
||||
}
|
||||
endLatch.countDown();
|
||||
}
|
||||
};
|
||||
// Fire the threads
|
||||
for (int i = 0; i < threadCount; i++)
|
||||
{
|
||||
Thread thread = new Thread(createPersonRunnable);
|
||||
thread.setName(getName() + "-" + i);
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
}
|
||||
// Wait for the threads to have finished
|
||||
try { endLatch.await(60, TimeUnit.SECONDS); } catch (InterruptedException e) {}
|
||||
|
||||
// Now, get the user with full split person handling
|
||||
personServiceImpl.setDuplicateMode("DELETE");
|
||||
|
||||
RetryingTransactionCallback<NodeRef> getPersonWork = new RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
return personService.getPerson(duplicateUsername);
|
||||
}
|
||||
};
|
||||
NodeRef remainingNodeRef = transactionService.getRetryingTransactionHelper().doInTransaction(getPersonWork, false, true);
|
||||
// Should all be cleaned up now, but no way to check
|
||||
for (NodeRef nodeRef : cleanableNodeRefs.values())
|
||||
{
|
||||
if (nodeRef.equals(remainingNodeRef))
|
||||
{
|
||||
// This one should still be around
|
||||
continue;
|
||||
}
|
||||
if (nodeService.exists(nodeRef))
|
||||
{
|
||||
fail("Expected unused person noderef to have been cleaned up: " + nodeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user