Merged V2.1 to HEAD

6486: Fix for AWC-1134 (Made minimum length for username and password configurable)
   6487: Added "copy.verbose" property to build script to list all files being copied in the 'deploy-tomcat-exploded' and 'deploy-webclient-changes' targets
   6488: Changed default CIFS server to remove underscore as it can cause problems with OpenOffice.
   6489: Fix for WCM-498 (Expired items that are deleted are not represented as such in the change request dialog or submit dialog)
   6490: Fix for WCM-446 and WCM-624. Multi-select and All operations in Modified Files list respect items in workflow and ignore them.
   6491: Fixes profoundly brain dead behavior in AVMLockingService.init().
   6492: Refactoring of LookupCache to be clustering compatible
   6493: Staging and locking changes
   6494: WCM Revert action moved to end of all action lists to avoid accidently clicking it (as it has no confirmation screen!)
   6496: Fixes for WCM-746 and WCM-747 - Edit File Properties and Edit Folder Properties working correctly again for AVM objects.
   6497: Enable virtualization server to be (re)started at any point prior or during the startup of the alfresco webapp (fixes WCM-750).
   6498: WCM-742 - moving locks from the preview sandbox to the main user sandbox.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6739 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-09-10 23:15:37 +00:00
parent 7a522e4b88
commit 1b272d6766
17 changed files with 1011 additions and 1224 deletions

View File

@@ -48,6 +48,7 @@ import org.alfresco.sandbox.SandboxConstants;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
import org.alfresco.service.cmr.avm.locking.AVMLockingService;
import org.alfresco.service.cmr.avmsync.AVMSyncService;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
@@ -86,6 +87,7 @@ public class AVMExpiredContentProcessor
protected Map<String, Map<String, List<String>>> expiredContent;
protected AVMService avmService;
protected AVMSyncService avmSyncService;
protected AVMService avmLockingAwareService;
protected NodeService nodeService;
protected WorkflowService workflowService;
protected PersonService personService;
@@ -157,6 +159,11 @@ public class AVMExpiredContentProcessor
{
this.searchService = searchService;
}
public void setAvmLockingAwareService(AVMService avmLockingAwareService)
{
this.avmLockingAwareService = avmLockingAwareService;
}
/**
* Executes the expired content processor.
@@ -305,7 +312,7 @@ public class AVMExpiredContentProcessor
if (logger.isDebugEnabled())
logger.debug("Examining expiration date for '" + nodePath + "': " +
expirationDateProp.getStringValue());
expirationDateProp);
if (expirationDateProp != null)
{
@@ -465,10 +472,10 @@ public class AVMExpiredContentProcessor
String path = workflowStoreName + ":/" + JNDIConstants.DIR_DEFAULT_WWW +
"/" + JNDIConstants.DIR_DEFAULT_APPBASE;
// DNS name mangle the property name - can only contain value DNS characters!
String dnsProp = SandboxConstants.PROP_DNS + DNSNameMangler.MakeDNSName(userStore, packageName);
String dnsProp = SandboxConstants.PROP_DNS + DNSNameMangler.MakeDNSName(stagingStore, packageName);
this.avmService.setStoreProperty(workflowStoreName, QName.createQName(null, dnsProp),
new PropertyValue(DataTypeDefinition.TEXT, path));
// the main workflow store depends on the main user store (dist=1)
String prop_key = SandboxConstants.PROP_BACKGROUND_LAYER + userStore;
this.avmService.setStoreProperty(workflowStoreName, QName.createQName(null, prop_key),
@@ -560,11 +567,10 @@ public class AVMExpiredContentProcessor
String pathInWorkflowStore = workflowStoreName + ":" + relPath;
// call forceCopy to make sure the path appears modified in the workflow
// sandbox, if the item is already modified or deleted this call has no
// effect.
this.avmService.forceCopy(pathInWorkflowStore);
// sandbox, if the item is already modified or deleted this call has no effect.
this.avmLockingAwareService.forceCopy(pathInWorkflowStore);
}
// convert package to workflow package
AVMNodeDescriptor packageDesc = avmService.lookup(-1, packagesPath);
NodeRef packageNodeRef = workflowService.createPackage(

View File

@@ -1,53 +0,0 @@
/**
*
*/
package org.alfresco.repo.avm;
import org.alfresco.repo.transaction.TransactionListenerAdapter;
/**
* This is the listener that cleans up the lookup cache on transaction
* rollback.
* @author britt
*/
public class AVMLookupCacheListener extends TransactionListenerAdapter
{
/**
* The lookup cache.
*/
private LookupCache fLookupCache;
/**
* A default constructor.
*/
public AVMLookupCacheListener()
{
}
/**
* Set the Lookup Cache.
* @param lookupCache
*/
public void setLookupCache(LookupCache lookupCache)
{
fLookupCache = lookupCache;
}
/* (non-Javadoc)
* @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterRollback()
*/
@Override
public void afterRollback()
{
fLookupCache.onRollback();
}
/* (non-Javadoc)
* @see org.alfresco.repo.transaction.TransactionListenerAdapter#afterCommit()
*/
@Override
public void afterCommit()
{
fLookupCache.onCommit();
}
}

View File

@@ -633,7 +633,6 @@ public class AVMRepository
{
throw new AVMNotFoundException("Store not found.");
}
fLookupCache.onDelete(pathParts[0]);
sPath = srcRepo.lookupDirectory(-1, pathParts[1], true);
if (sPath == null)
{
@@ -645,6 +644,7 @@ public class AVMRepository
{
throw new AVMNotFoundException("Not found: " + srcName);
}
fLookupCache.onDelete(pathParts[0]);
}
finally
{
@@ -659,7 +659,6 @@ public class AVMRepository
{
throw new AVMNotFoundException("Store not found.");
}
fLookupCache.onWrite(pathParts[0]);
Lookup dPath = dstRepo.lookupDirectory(-1, pathParts[1], true);
if (dPath == null)
{
@@ -761,6 +760,7 @@ public class AVMRepository
{
dstNode.setAncestor(srcNode);
}
fLookupCache.onWrite(pathParts[0]);
}
finally
{
@@ -808,10 +808,10 @@ public class AVMRepository
{
throw new AVMNotFoundException("Store not found.");
}
fLookupCache.onSnapshot(storeName);
Map<String, Integer> result = store.createSnapshot(tag, description, new HashMap<String, Integer>());
for (Map.Entry<String, Integer> entry : result.entrySet())
{
fLookupCache.onSnapshot(entry.getKey());
fCreateVersionTxnListener.versionCreated(entry.getKey(), entry.getValue());
}
return result;
@@ -1639,18 +1639,33 @@ public class AVMRepository
*/
public Lookup lookupDirectory(int version, String path)
{
fLookupCount.set(fLookupCount.get() + 1);
if (fLookupCount.get() > 50)
Integer count = fLookupCount.get();
try
{
throw new AVMCycleException("Cycle in lookup.");
if (count == null)
{
fLookupCount.set(1);
}
fLookupCount.set(fLookupCount.get() + 1);
if (fLookupCount.get() > 50)
{
throw new AVMCycleException("Cycle in lookup.");
}
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
{
return null;
}
return store.lookupDirectory(version, pathParts[1], false);
}
String [] pathParts = SplitPath(path);
AVMStore store = getAVMStoreByName(pathParts[0]);
if (store == null)
finally
{
return null;
if (count == null)
{
fLookupCount.set(null);
}
}
return store.lookupDirectory(version, pathParts[1], false);
}
/**

View File

@@ -36,12 +36,12 @@ public class AVMScaleTestP extends AVMServiceTestBase
{
public void testScaling()
{
int n = 4; // The number of BulkLoads to do.
int n = 250; // The number of BulkLoads to do.
int futzCount = 10; // The number of post snapshot modifications to make after each load.
String load = "/Users/britt/hibernate-3.1"; // The tree of stuff to load.
BulkLoader loader = new BulkLoader();
loader.setAvmService(fService);
loader.setPropertyCount(5);
loader.setPropertyCount(50);
BulkReader reader = new BulkReader();
reader.setAvmService(fService);
long lastTime = System.currentTimeMillis();

View File

@@ -36,8 +36,6 @@ import java.util.SortedMap;
import org.alfresco.repo.domain.DbAccessControlList;
import org.alfresco.repo.domain.PropertyValue;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.TransactionListener;
import org.alfresco.service.cmr.avm.AVMBadArgumentException;
import org.alfresco.service.cmr.avm.AVMException;
import org.alfresco.service.cmr.avm.AVMExistsException;
@@ -72,8 +70,6 @@ public class AVMServiceImpl implements AVMService
*/
private AVMRepository fAVMRepository;
private TransactionListener fTransactionListener;
/**
* Basic constructor for the service.
*/
@@ -90,15 +86,6 @@ public class AVMServiceImpl implements AVMService
fAVMRepository = avmRepository;
}
/**
* Set the transaction listener.
* @param transactionListener
*/
public void setTransactionListener(TransactionListener transactionListener)
{
fTransactionListener = transactionListener;
}
/**
* Get an InputStream from a file.
* @param version The version to look under.
@@ -139,7 +126,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Null path.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
return fAVMRepository.getOutputStream(path);
}
@@ -169,7 +155,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Null path.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
return fAVMRepository.createContentWriter(path);
}
@@ -361,7 +346,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
return fAVMRepository.createFile(path, name);
}
@@ -378,7 +362,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
// Save the contents to temp space.
File temp;
try
@@ -419,7 +402,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.createDirectory(path, name);
}
@@ -436,7 +418,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.createLayeredFile(srcPath, parent, name);
}
@@ -453,7 +434,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.createLayeredDirectory(srcPath, parent, name);
}
@@ -485,7 +465,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.createBranch(version, srcPath, dstPath, name);
}
@@ -501,7 +480,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal null argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.remove(parent, name);
}
@@ -520,7 +498,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Cannot remove root node: " + path);
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.remove(basePath[0], basePath[1]);
}
@@ -539,7 +516,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.rename(srcParent, srcName, dstParent, dstName);
}
@@ -554,7 +530,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal null argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.uncover(dirPath, name);
}
@@ -570,7 +545,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal null argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.flatten(dirPath, name);
}
@@ -616,7 +590,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Store is null.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
return fAVMRepository.createSnapshot(store, tag, description);
}
@@ -861,7 +834,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal null argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.retargetLayeredDirectory(path, target);
}
@@ -875,7 +847,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Path is null.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.makePrimary(path);
}
@@ -967,7 +938,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Null path.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.setOpacity(path, opacity);
}
@@ -1018,7 +988,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal null argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.setNodeProperty(path, name, value);
}
@@ -1033,7 +1002,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal null argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.setNodeProperties(path, properties);
}
@@ -1091,7 +1059,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal null argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.deleteNodeProperty(path, name);
}
@@ -1105,7 +1072,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Null path.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.deleteNodeProperties(path);
}
@@ -1208,7 +1174,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Invalid null argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.deleteStoreProperty(store, name);
}
@@ -1250,7 +1215,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Null Path.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
return fAVMRepository.getContentDataForWrite(path);
}
@@ -1268,7 +1232,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Null Path.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.setContentData(path, data);
}
@@ -1283,7 +1246,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal null argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.setMetaDataFrom(path, from);
}
@@ -1300,7 +1262,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal Null Argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.addAspect(path, aspectName);
}
@@ -1342,7 +1303,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Null path.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.removeAspect(path, aspectName);
}
@@ -1374,7 +1334,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal Null Argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.link(parentPath, name, toLink);
}
@@ -1388,7 +1347,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Null Path.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
return fAVMRepository.forceCopy(path);
}
@@ -1427,7 +1385,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal name.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
AVMNodeDescriptor srcDesc = lookup(srcVersion, srcPath);
recursiveCopy(srcVersion, srcDesc, dstPath, name);
}
@@ -1508,7 +1465,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Cannot revert store root: " + path);
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.revert(baseName[0], baseName[1], toRevertTo);
}
@@ -1521,7 +1477,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal Null Argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.setGuid(path, guid);
}
@@ -1534,7 +1489,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal Null Argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.setEncoding(path, encoding);
}
@@ -1547,7 +1501,6 @@ public class AVMServiceImpl implements AVMService
{
throw new AVMBadArgumentException("Illegal Null Argument.");
}
AlfrescoTransactionSupport.bindListener(fTransactionListener);
fAVMRepository.setMimeType(path, mimeType);
}
}

View File

@@ -347,136 +347,6 @@ public class AVMServiceTest extends AVMServiceTestBase
}
/**
* Test async indexing.
* @throws Exception
*/
public void testAsyncIndex() throws Exception
{
// Make sure the slate is clean ...
UserTransaction tx = fTransactionService.getUserTransaction();
tx.begin();
if(fService.getStore("avmAsynchronousTest") != null)
{
assertTrue(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest"));
fService.purgeStore("avmAsynchronousTest");
assertTrue(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest"));
assertFalse(fIndexingInterceptor.hasIndexBeenCreated("bananaStoreWoof"));
}
else
{
assertFalse(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest"));
}
StoreRef storeRef = AVMNodeConverter.ToStoreRef("avmAsynchronousTest");
Indexer indexer = fIndexerAndSearcher.getIndexer(storeRef);
if(indexer instanceof AVMLuceneIndexer)
{
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer)indexer;
avmIndexer.deleteIndex("avmAsynchronousTest", IndexMode.SYNCHRONOUS);
}
tx.commit();
tx = fTransactionService.getUserTransaction();
tx.begin();
assertEquals(-1, fIndexingInterceptor.getLastIndexedSnapshot("bananaStoreWoof"));
assertEquals(-1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest"));
tx.commit();
// TODO: Suspend and resume indexing in case we are really unlucky and hit an index before we expect it.
SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true);
ResultSet results;
results = searchService.query(storeRef, "lucene", "PATH:\"//.\"");
assertEquals(0, results.length());
results.close();
fService.createStore("avmAsynchronousTest");
tx = fTransactionService.getUserTransaction();
tx.begin();
assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest"));
tx.commit();
fService.createSnapshot("avmAsynchronousTest", null, null);
tx = fTransactionService.getUserTransaction();
tx.begin();
assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest"));
tx.commit();
results = searchService.query(storeRef, "lucene", "PATH:\"//.\"");
assertEquals(1, results.length());
results.close();
fService.createDirectory("avmAsynchronousTest:/", "a");
fService.createDirectory("avmAsynchronousTest:/a", "b");
fService.createDirectory("avmAsynchronousTest:/a/b", "c");
tx = fTransactionService.getUserTransaction();
tx.begin();
assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest"));
assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest"));
tx.commit();
fService.createSnapshot("avmAsynchronousTest", null, null);
tx = fTransactionService.getUserTransaction();
tx.begin();
assertEquals(1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest"));
assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest"));
assertFalse(fIndexingInterceptor.isIndexUpToDateAndSearchable("avmAsynchronousTest"));
assertEquals(IndexMode.ASYNCHRONOUS, fIndexingInterceptor.getIndexMode("avmAsynchronousTest"));
assertEquals(IndexMode.SYNCHRONOUS, fIndexingInterceptor.getIndexMode("main"));
assertTrue(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 0));
assertTrue(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 1));
assertFalse(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 2));
tx.commit();
results = searchService.query(storeRef, "lucene", "PATH:\"//.\"");
assertEquals(1, results.length());
results.close();
Thread.sleep(180000);
results = searchService.query(storeRef, "lucene", "PATH:\"//.\"");
assertEquals(4, results.length());
results.close();
tx = fTransactionService.getUserTransaction();
tx.begin();
assertEquals(1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest"));
assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest"));
assertTrue(fIndexingInterceptor.isIndexUpToDateAndSearchable("avmAsynchronousTest"));
tx.commit();
fService.purgeStore("avmAsynchronousTest");
results = searchService.query(storeRef, "lucene", "PATH:\"//.\"");
assertEquals(0, results.length());
results.close();
fService.createStore("avmAsynchronousTest");
fService.createSnapshot("avmAsynchronousTest", null, null);
fService.createDirectory("avmAsynchronousTest:/", "a");
fService.createDirectory("avmAsynchronousTest:/a", "b");
fService.createDirectory("avmAsynchronousTest:/a/b", "c");
fService.createSnapshot("avmAsynchronousTest", null, null);
fService.purgeStore("avmAsynchronousTest");
fService.createStore("avmAsynchronousTest");
fService.createSnapshot("avmAsynchronousTest", null, null);
fService.createDirectory("avmAsynchronousTest:/", "a");
fService.createDirectory("avmAsynchronousTest:/a", "b");
fService.createDirectory("avmAsynchronousTest:/a/b", "c");
fService.createSnapshot("avmAsynchronousTest", null, null);
Thread.sleep(180000);
results = searchService.query(storeRef, "lucene", "PATH:\"//.\"");
assertEquals(4, results.length());
results.close();
}
public void testForceCopyDeleted()
{
@@ -537,8 +407,16 @@ public class AVMServiceTest extends AVMServiceTestBase
fService.createBranch(1, "layer:/root", "branch:/", "branch");
fService.createSnapshot("branch", null, null);
fService.getFileOutputStream("main:/a/b/c/foo").close();
System.out.println("main 1");
System.out.println(recursiveList("main", 1, true));
System.out.println("branch 1");
System.out.println(recursiveList("branch", 1, true));
assertEquals(fService.lookup(1, "main:/a/b/c/foo").getId(), fService.lookup(1,
"branch:/branch/layer/b/c/foo").getId());
System.out.println("main -1");
System.out.println(recursiveList("main", -1, true));
System.out.println("branch -1");
System.out.println(recursiveList("branch", -1, true));
assertEquals(fService.lookup(-1, "main:/a/b/c/foo").getId(), fService.lookup(-1,
"branch:/branch/layer/b/c/foo").getId());
}
@@ -5641,4 +5519,135 @@ public class AVMServiceTest extends AVMServiceTestBase
fail();
}
}
/**
* Test async indexing.
* @throws Exception
*/
public void testAsyncIndex() throws Exception
{
// Make sure the slate is clean ...
UserTransaction tx = fTransactionService.getUserTransaction();
tx.begin();
if(fService.getStore("avmAsynchronousTest") != null)
{
assertTrue(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest"));
fService.purgeStore("avmAsynchronousTest");
assertTrue(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest"));
assertFalse(fIndexingInterceptor.hasIndexBeenCreated("bananaStoreWoof"));
}
else
{
assertFalse(fIndexingInterceptor.hasIndexBeenCreated("avmAsynchronousTest"));
}
StoreRef storeRef = AVMNodeConverter.ToStoreRef("avmAsynchronousTest");
Indexer indexer = fIndexerAndSearcher.getIndexer(storeRef);
if(indexer instanceof AVMLuceneIndexer)
{
AVMLuceneIndexer avmIndexer = (AVMLuceneIndexer)indexer;
avmIndexer.deleteIndex("avmAsynchronousTest", IndexMode.SYNCHRONOUS);
}
tx.commit();
tx = fTransactionService.getUserTransaction();
tx.begin();
assertEquals(-1, fIndexingInterceptor.getLastIndexedSnapshot("bananaStoreWoof"));
assertEquals(-1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest"));
tx.commit();
// TODO: Suspend and resume indexing in case we are really unlucky and hit an index before we expect it.
SearchService searchService = fIndexerAndSearcher.getSearcher(storeRef, true);
ResultSet results;
results = searchService.query(storeRef, "lucene", "PATH:\"//.\"");
assertEquals(0, results.length());
results.close();
fService.createStore("avmAsynchronousTest");
tx = fTransactionService.getUserTransaction();
tx.begin();
assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest"));
tx.commit();
fService.createSnapshot("avmAsynchronousTest", null, null);
tx = fTransactionService.getUserTransaction();
tx.begin();
assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest"));
tx.commit();
results = searchService.query(storeRef, "lucene", "PATH:\"//.\"");
assertEquals(1, results.length());
results.close();
fService.createDirectory("avmAsynchronousTest:/", "a");
fService.createDirectory("avmAsynchronousTest:/a", "b");
fService.createDirectory("avmAsynchronousTest:/a/b", "c");
tx = fTransactionService.getUserTransaction();
tx.begin();
assertEquals(0, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest"));
assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest"));
tx.commit();
fService.createSnapshot("avmAsynchronousTest", null, null);
tx = fTransactionService.getUserTransaction();
tx.begin();
assertEquals(1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest"));
assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest"));
assertFalse(fIndexingInterceptor.isIndexUpToDateAndSearchable("avmAsynchronousTest"));
assertEquals(IndexMode.ASYNCHRONOUS, fIndexingInterceptor.getIndexMode("avmAsynchronousTest"));
assertEquals(IndexMode.SYNCHRONOUS, fIndexingInterceptor.getIndexMode("main"));
assertTrue(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 0));
assertTrue(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 1));
assertFalse(fIndexingInterceptor.isSnapshotIndexed("avmAsynchronousTest", 2));
tx.commit();
results = searchService.query(storeRef, "lucene", "PATH:\"//.\"");
assertEquals(1, results.length());
results.close();
Thread.sleep(180000);
results = searchService.query(storeRef, "lucene", "PATH:\"//.\"");
assertEquals(4, results.length());
results.close();
tx = fTransactionService.getUserTransaction();
tx.begin();
assertEquals(1, fIndexingInterceptor.getLastIndexedSnapshot("avmAsynchronousTest"));
assertTrue(fIndexingInterceptor.isIndexUpToDate("avmAsynchronousTest"));
assertTrue(fIndexingInterceptor.isIndexUpToDateAndSearchable("avmAsynchronousTest"));
tx.commit();
fService.purgeStore("avmAsynchronousTest");
results = searchService.query(storeRef, "lucene", "PATH:\"//.\"");
assertEquals(0, results.length());
results.close();
fService.createStore("avmAsynchronousTest");
fService.createSnapshot("avmAsynchronousTest", null, null);
fService.createDirectory("avmAsynchronousTest:/", "a");
fService.createDirectory("avmAsynchronousTest:/a", "b");
fService.createDirectory("avmAsynchronousTest:/a/b", "c");
fService.createSnapshot("avmAsynchronousTest", null, null);
fService.purgeStore("avmAsynchronousTest");
fService.createStore("avmAsynchronousTest");
fService.createSnapshot("avmAsynchronousTest", null, null);
fService.createDirectory("avmAsynchronousTest:/", "a");
fService.createDirectory("avmAsynchronousTest:/a", "b");
fService.createDirectory("avmAsynchronousTest:/a/b", "c");
fService.createSnapshot("avmAsynchronousTest", null, null);
Thread.sleep(180000);
results = searchService.query(storeRef, "lucene", "PATH:\"//.\"");
assertEquals(4, results.length());
results.close();
}
}

View File

@@ -24,7 +24,6 @@
package org.alfresco.repo.avm;
import java.io.IOException;
import java.io.PrintStream;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@@ -39,9 +38,7 @@ import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
import org.alfresco.service.cmr.avm.locking.AVMLockingService;
import org.alfresco.service.cmr.avmsync.AVMSyncService;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
@@ -225,6 +222,7 @@ public class AVMServiceTestBase extends TestCase
Map<String, AVMNodeDescriptor> listing = fService.getDirectoryListing(version, path, true);
for (String name : listing.keySet())
{
System.err.println(name);
builder.append(recursiveList(basename + name, version, indent + 2, followLinks));
}
}

View File

@@ -214,11 +214,20 @@ public class AVMStoreImpl implements AVMStore, Serializable
{
continue;
}
fAVMRepository.forceCopy(entry.getPath());
// TODO This leaves the behavior of LayeredFiles not quite
// right.
/*
String parentName[] = AVMNodeConverter.SplitBase(entry.getPath());
parentName[0] = parentName[0].substring(parentName[0].indexOf(':') + 1);
lookup = lookupDirectory(-1, parentName[0], true);
DirectoryNode parent = (DirectoryNode)lookup.getCurrentNode();
AVMNode child = parent.lookupChild(lookup, parentName[1], false);
// TODO For debugging.
if (child == null)
{
System.err.println("Yoiks!");
}
// TODO This is funky. Need to look carefully to see that this call
// does exactly what's needed.
lookup.add(child, parentName[1], false);
@@ -232,6 +241,7 @@ public class AVMStoreImpl implements AVMStore, Serializable
newChild = ((LayeredFileNode)child).copyLiterally(lookup);
}
parent.putChild(parentName[1], newChild);
*/
}
// Clear out the new nodes.
List<AVMNode> newInRep = AVMDAOs.Instance().fAVMNodeDAO.getNewInStore(this);

View File

@@ -23,6 +23,7 @@
package org.alfresco.repo.avm;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@@ -34,8 +35,10 @@ import org.alfresco.util.Pair;
* from the root directory of a repository.
* @author britt
*/
class Lookup
class Lookup implements Serializable
{
private static final long serialVersionUID = -2844833688622561L;
/**
* Is this lookup valid?
*/

View File

@@ -3,14 +3,11 @@
*/
package org.alfresco.repo.avm;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.repo.avm.util.SimplePath;
import org.alfresco.repo.cache.SimpleCache;
import org.apache.log4j.Logger;
/**
@@ -21,42 +18,10 @@ public class LookupCache
{
private static Logger fgLogger = Logger.getLogger(LookupCache.class);
/**
* Per transaction lookup results to be added to the cache on successful
* commit.
*/
private ThreadLocal<Map<LookupKey, Lookup>> fToBeAdded;
/**
* Per transaction set of invalidated lookup keys.
*/
private ThreadLocal<Set<LookupKey>> fToBePurged;
/**
* The Map of of keys to lookups.
*/
private Map<LookupKey, Lookup> fCache;
/**
* The Map of time stamps to keys.
*/
private SortedMap<Long, LookupKey> fTimeStamps;
/**
* The inverse map of keys to timestamps.
*/
private Map<LookupKey, Long> fInverseTimeStamps;
/**
* The timestamp to next issue.
*/
private long fTimeStamp;
/**
* The maximum number of lines to have in the cache.
*/
private int fMaxSize;
private SimpleCache<LookupKey, Lookup> fCache;
/**
* Reference to the Node DAO.
@@ -73,13 +38,6 @@ public class LookupCache
*/
public LookupCache()
{
fCache = new HashMap<LookupKey, Lookup>();
fTimeStamps = new TreeMap<Long, LookupKey>();
fInverseTimeStamps = new HashMap<LookupKey, Long>();
fToBeAdded = new ThreadLocal<Map<LookupKey, Lookup>>();
fToBePurged = new ThreadLocal<Set<LookupKey>>();
fTimeStamp = 0L;
fMaxSize = 100;
}
/**
@@ -100,13 +58,9 @@ public class LookupCache
fAVMStoreDAO = dao;
}
/**
* Set the maximum cache size.
* @param maxSize
*/
public void setMaxSize(int maxSize)
public void setTransactionalCache(SimpleCache<LookupKey, Lookup> cache)
{
fMaxSize = maxSize;
fCache = cache;
}
/**
@@ -125,8 +79,14 @@ public class LookupCache
LookupKey key = new LookupKey(version, path, store.getName(), write, includeDeleted);
// Is it in the cache?
Lookup found = findInCache(key);
// TODO Testing.
// found = null;
if (found != null)
{
if (fgLogger.isDebugEnabled())
{
fgLogger.debug("Cache Hit: " + key + ", " + found.getCurrentNode().getId());
}
return found;
}
// Make up a Lookup to hold the results.
@@ -155,7 +115,7 @@ public class LookupCache
dir = (DirectoryNode)result.getCurrentNode();
if (path.size() == 1 && path.get(0).equals(""))
{
updateCache(key, result);
fCache.put(key, result);
return result;
}
// Now look up each path element in sequence up to one
@@ -184,7 +144,7 @@ public class LookupCache
return null;
}
result.add(child, path.get(path.size() - 1), write);
updateCache(key, result);
fCache.put(key, result);
return result;
}
@@ -195,24 +155,7 @@ public class LookupCache
*/
private synchronized Lookup findInCache(LookupKey key)
{
// Get the current transaction's purged set.
Set<LookupKey> purged = fToBePurged.get();
// Get the current transaction's added map.
Map<LookupKey, Lookup> added = fToBeAdded.get();
// See if it's cached in the transaction.
Lookup found = (added != null) ? added.get(key) : null;
// It's not.
if (found == null)
{
// If it's been purged in the transaction it is
// a miss.
if (purged != null && purged.contains(key))
{
return null;
}
found = fCache.get(key);
}
// Despite the odds, we found a hit.
Lookup found = fCache.get(key);
if (found != null)
{
// Get a freshened Lookup.
@@ -224,8 +167,6 @@ public class LookupCache
fgLogger.error("Invalid entry in cache: " + key);
return null;
}
// Prepare the cache for a timestamp update on commit.
updateCache(key, found);
return result;
}
// Alternatively for a read lookup a write can match.
@@ -234,18 +175,7 @@ public class LookupCache
// Make a copy of the key and set it to 'write'
LookupKey newKey = new LookupKey(key);
newKey.setWrite(true);
// Is it in the transaction's cache?
found = (added != null) ? added.get(newKey) : null;
// If not.
if (found == null)
{
// If it's been purged it's a miss.
if (purged != null && purged.contains(newKey))
{
return null;
}
found = fCache.get(newKey);
}
found = fCache.get(newKey);
if (found != null)
{
// We found it. Make a freshened copy of the Lookup.
@@ -257,103 +187,12 @@ public class LookupCache
fgLogger.error("Invalid entry in cache: " + newKey);
return null;
}
// Prepare the cache to update time stamp.
updateCache(newKey, found);
return result;
}
}
return null;
}
/**
* Add or update an entry in the cache.
* @param key
* @param lookup
*/
private void updateCache(LookupKey key, Lookup lookup)
{
// First, put it in the transaction scoped cache.
Map<LookupKey, Lookup> map = fToBeAdded.get();
if (map == null)
{
map = new HashMap<LookupKey, Lookup>();
}
map.put(key, lookup);
// Remove any corresponding entry from the purge list.
Set<LookupKey> purged = fToBePurged.get();
if (purged == null)
{
return;
}
purged.remove(key);
}
/**
* Called when a transaction has successfully committed,
* to make lookups from the transaction available to other transactions.
*/
public synchronized void onCommit()
{
// First get rid of all entries purged by the transaction.
Set<LookupKey> purged = fToBePurged.get();
if (purged != null)
{
purgeEntries(purged);
}
// Null out the thread local.
fToBePurged.set(null);
// Get and go through the transaction's added list.
Map<LookupKey, Lookup> added = fToBeAdded.get();
if (added == null)
{
return;
}
for (Map.Entry<LookupKey, Lookup> entry : added.entrySet())
{
LookupKey key = entry.getKey();
Lookup lookup = entry.getValue();
// If the cache already has the key, remove it.
if (fCache.containsKey(key))
{
fCache.remove(key);
Long oldTime = fInverseTimeStamps.get(key);
fInverseTimeStamps.remove(key);
fTimeStamps.remove(oldTime);
}
// Add the entry.
long timeStamp = fTimeStamp++;
fTimeStamps.put(timeStamp, key);
fInverseTimeStamps.put(key, timeStamp);
fCache.put(key, lookup);
// Check if we're over the limit and purge the
// LRU entry if we are.
if (fCache.size() > fMaxSize)
{
// Get rid of the oldest entry.
Long oldTime = fTimeStamps.firstKey();
LookupKey old = fTimeStamps.remove(oldTime);
fInverseTimeStamps.remove(old);
fCache.remove(old);
}
}
// Null out the ThreadLocal.
fToBeAdded.set(null);
}
/**
* Remove a Set of entries.
* @param keys The Set of entries.
*/
private void purgeEntries(Set<LookupKey> keys)
{
for (LookupKey key : keys)
{
fCache.remove(key);
Long time = fInverseTimeStamps.remove(key);
fTimeStamps.remove(time);
}
}
// Following are the cache invalidation calls.
/**
@@ -362,37 +201,25 @@ public class LookupCache
*/
public synchronized void onWrite(String storeName)
{
// Get or make up the purged Set for this transaction.
Set<LookupKey> purged = fToBePurged.get();
if (purged == null)
{
purged = new HashSet<LookupKey>();
fToBePurged.set(purged);
}
// Invalidate if it's a read lookup in the store, or
// any read lookup is it's layered.
for (Map.Entry<LookupKey, Lookup> entry : fCache.entrySet())
List<LookupKey> keys = new ArrayList<LookupKey>();
for (LookupKey key : fCache.getKeys())
{
if ((entry.getKey().getStoreName().equals(storeName) &&
!entry.getKey().isWrite()) ||
(!entry.getKey().isWrite() && entry.getValue().isLayered()))
{
purged.add(entry.getKey());
}
keys.add(key);
}
// Remove entries from the added set using the same criteria.
Map<LookupKey, Lookup> added = fToBeAdded.get();
if (added == null)
for (LookupKey key : keys)
{
return;
}
for (Map.Entry<LookupKey, Lookup> entry : added.entrySet())
{
if ((entry.getKey().getStoreName().equals(storeName) &&
!entry.getKey().isWrite()) ||
(!entry.getKey().isWrite() && entry.getValue().isLayered()))
Lookup value = fCache.get(key);
if ((key.getStoreName().equals(storeName) &&
!key.isWrite()) || value == null ||
(!key.isWrite() && value.isLayered()))
{
added.remove(entry.getKey());
if (fgLogger.isDebugEnabled())
{
fgLogger.debug("Invalidating: " + key + ", " + (value != null ? value.getCurrentNode().getId() : -2));
}
fCache.remove(key);
}
}
}
@@ -403,34 +230,23 @@ public class LookupCache
*/
public synchronized void onDelete(String storeName)
{
// Get or make up a fresh purged Set.
Set<LookupKey> purged = fToBePurged.get();
if (purged == null)
{
purged = new HashSet<LookupKey>();
fToBePurged.set(purged);
}
// Invalidate any entries that are in the store or are layered lookups.
for (Map.Entry<LookupKey, Lookup> entry : fCache.entrySet())
List<LookupKey> keys = new ArrayList<LookupKey>();
for (LookupKey key : fCache.getKeys())
{
if (entry.getKey().getStoreName().equals(storeName) ||
entry.getValue().isLayered())
{
purged.add(entry.getKey());
}
keys.add(key);
}
// Get rid of any similarly matching elements in the added list.
Map<LookupKey, Lookup> added = fToBeAdded.get();
if (added == null)
for (LookupKey key : keys)
{
return;
}
for (Map.Entry<LookupKey, Lookup> entry : added.entrySet())
{
if (entry.getKey().getStoreName().equals(storeName) ||
entry.getValue().isLayered())
Lookup value = fCache.get(key);
if (key.getStoreName().equals(storeName) ||
value == null || value.isLayered())
{
added.remove(entry.getKey());
if (fgLogger.isDebugEnabled())
{
fgLogger.debug("Invalidating: " + key + ", " + (value != null ? value.getCurrentNode().getId() : -2));
}
fCache.remove(key);
}
}
}
@@ -441,48 +257,31 @@ public class LookupCache
*/
public synchronized void onSnapshot(String storeName)
{
// Get or make up a purged set.
Set<LookupKey> purged = fToBePurged.get();
if (purged == null)
{
purged = new HashSet<LookupKey>();
fToBePurged.set(purged);
}
// Invalidate any entries that in the store and writes or
// any layered lookups.
for (Map.Entry<LookupKey, Lookup> entry : fCache.entrySet())
List<LookupKey> keys = new ArrayList<LookupKey>();
for (LookupKey key : fCache.getKeys())
{
if ((entry.getKey().getStoreName().equals(storeName) &&
entry.getKey().isWrite()) ||
entry.getValue().isLayered())
{
purged.add(entry.getKey());
}
keys.add(key);
}
// Remove from the added list by the same criteria.
Map<LookupKey, Lookup> added = fToBeAdded.get();
if (added == null)
for (LookupKey key : keys)
{
return;
}
for (Map.Entry<LookupKey, Lookup> entry : added.entrySet())
{
if ((entry.getKey().getStoreName().equals(storeName) &&
entry.getKey().isWrite()) ||
entry.getValue().isLayered())
Lookup value = fCache.get(key);
if ((key.getStoreName().equals(storeName) &&
key.isWrite()) ||
value == null || value.isLayered())
{
added.remove(entry.getKey());
if (fgLogger.isDebugEnabled())
{
fgLogger.debug("Invalidating: " + key + ", " + (value != null ? value.getCurrentNode().getId() : -2));
}
fCache.remove(key);
}
}
}
/**
* Called when a rollback has occurred.
*/
public synchronized void onRollback()
public synchronized void reset()
{
// Just toss the transaction level changes.
fToBeAdded.set(null);
fToBePurged.set(null);
fCache.clear();
}
}

View File

@@ -3,14 +3,18 @@
*/
package org.alfresco.repo.avm;
import java.io.Serializable;
import org.alfresco.repo.avm.util.SimplePath;
/**
* This is the key by which Lookup's are retrieved from the cache.
* @author britt
*/
public class LookupKey
public class LookupKey implements Serializable
{
private static final long serialVersionUID = 8471482833953423406L;
/**
* The name of the store.
*/

View File

@@ -3,12 +3,16 @@
*/
package org.alfresco.repo.avm.util;
import java.io.Serializable;
/**
* Holds a simple path.
* @author britt
*/
public class SimplePath
public class SimplePath implements Serializable
{
private static final long serialVersionUID = 2696828491008988470L;
/**
* The names of the path's components.
*/