A handful of more involved tests. Surprisingly few things needed fixing.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@2962 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Britt Park
2006-05-23 22:47:15 +00:00
parent a5d07e1069
commit d800048a10
13 changed files with 318 additions and 20 deletions

89
source/java/ehcache.xml Normal file
View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="java.io.tmpdir"/>
<cacheManagerEventListenerFactory class="" properties=""/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.hibernate.AVMNodeBeanImpl"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.hibernate.ContentBeanImpl"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.hibernate.Issuer"
maxElementsInMemory="10"
eternal="true"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.hibernate.RepositoryBeanImpl"
maxElementsInMemory="1000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.hibernate.LayeredDirectoryNodeBeanImpl"
maxElementsInMemory="1000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.hibernate.PlainDirectoryNodeBeanImpl"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.hibernate.RepositoryBeanImpl.newNodes"
maxElementsInMemory="1000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.hibernate.LayeredDirectoryNodeBeanImpl.added"
maxElementsInMemory="1000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.hibernate.PlainDirectoryNodeBeanImpl.children"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.hibernate.RepositoryBeanImpl.roots"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
<cache name="org.alfresco.repo.avm.hibernate.LayeredDirectoryNodeBeanImpl.deleted"
maxElementsInMemory="1000"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>

View File

@@ -10,13 +10,15 @@
<property name="current_session_context_class">thread</property> <property name="current_session_context_class">thread</property>
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property> <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="show_sql">false</property> <property name="show_sql">false</property>
<property name="order_updates">true</property> <property name="order_updates">false</property>
<property name="connection.isolation">2</property> <property name="connection.isolation">2</property>
<property name="c3p0.min_size">5</property> <property name="c3p0.min_size">5</property>
<property name="c3p0.max_size">20</property> <property name="c3p0.max_size">20</property>
<property name="c3p0.timeout">900</property> <property name="c3p0.timeout">900</property>
<property name="c3p0.max_statements">500</property> <property name="c3p0.max_statements">500</property>
<!-- <property name="cache.use_query_cache">true</property> --> <property name="default_batch_fetch_size">16</property>
<property name="jdbc.batch_versioned_data">true</property>
<property name="cache.use_query_cache">false</property>
<mapping resource="org/alfresco/repo/avm/hibernate/AVM.hbm.xml"/> <mapping resource="org/alfresco/repo/avm/hibernate/AVM.hbm.xml"/>
</session-factory> </session-factory>
</hibernate-configuration> </hibernate-configuration>

View File

@@ -138,7 +138,7 @@ public interface AVMService
* @param repName The name of the repository. * @param repName The name of the repository.
* @return The latest version id of the repository. * @return The latest version id of the repository.
*/ */
public long getLatestVersionID(String repName); public int getLatestVersionID(String repName);
/** /**
* Snapshot the given repositories. When this is called everything that has been added, * Snapshot the given repositories. When this is called everything that has been added,

View File

@@ -23,6 +23,7 @@ import java.io.PrintStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TreeMap;
import org.alfresco.repo.avm.hibernate.HibernateHelper; import org.alfresco.repo.avm.hibernate.HibernateHelper;
import org.alfresco.repo.avm.impl.AVMServiceImpl; import org.alfresco.repo.avm.impl.AVMServiceImpl;
@@ -282,15 +283,19 @@ public class AVMServiceTest extends TestCase
try try
{ {
setupBasicTree(); setupBasicTree();
System.out.println(recursiveList("main", -1)); TreeMap<Integer, String> history = new TreeMap<Integer, String>();
checkHistory(history, "main");
System.out.println(history.get(0));
fService.removeNode("main:/a/b/c", "foo"); fService.removeNode("main:/a/b/c", "foo");
fService.createSnapshot("main"); fService.createSnapshot("main");
System.out.println(recursiveList("main", -1)); checkHistory(history, "main");
System.out.println(history.get(1));
List<FolderEntry> l = fService.getDirectoryListing(-1, "main:/a/b/c"); List<FolderEntry> l = fService.getDirectoryListing(-1, "main:/a/b/c");
assertEquals(1, l.size()); assertEquals(1, l.size());
fService.removeNode("main:/d", "e"); fService.removeNode("main:/d", "e");
fService.createSnapshot("main"); fService.createSnapshot("main");
System.out.println(recursiveList("main", -1)); checkHistory(history, "main");
System.out.println(history.get(2));
l = fService.getDirectoryListing(-1, "main:/d"); l = fService.getDirectoryListing(-1, "main:/d");
assertEquals(0, l.size()); assertEquals(0, l.size());
} }
@@ -411,6 +416,188 @@ public class AVMServiceTest extends TestCase
} }
} }
/**
* Test COW in various circumstances.
*/
public void testDeepCOW()
{
try
{
// Makes a layer on top of a layer on top of a plain directory.
// Assures that the correct layers are copied when files
// are added in the two layers.
fService.createDirectory("main:/", "a");
fService.createDirectory("main:/a", "b");
fService.createSnapshot("main");
List<FolderEntry> listing = fService.getDirectoryListing(-1, "main:/a");
assertEquals(1, listing.size());
assertEquals("b", listing.get(0).getName());
fService.createLayeredDirectory("main:/a", "main:/", "c");
fService.createLayeredDirectory("main:/c", "main:/", "d");
fService.createFile("main:/d/b", "foo.txt");
fService.createSnapshot("main");
System.out.println(recursiveList("main", -1));
listing = fService.getDirectoryListing(-1, "main:/d/b");
assertEquals(1, listing.size());
assertEquals("foo.txt", listing.get(0).getName());
fService.createFile("main:/c/b", "bar.txt");
fService.createSnapshot("main");
System.out.println(recursiveList("main", -1));
listing = fService.getDirectoryListing(-1, "main:/c/b");
assertEquals(1, listing.size());
assertEquals("bar.txt", listing.get(0).getName());
listing = fService.getDirectoryListing(-1, "main:/d/b");
assertEquals(2, listing.size());
assertEquals("bar.txt", listing.get(0).getName());
assertEquals("foo.txt", listing.get(1).getName());
fService.rename("main:/", "c", "main:/", "e");
fService.createSnapshot("main");
System.out.println(recursiveList("main", -1));
listing = fService.getDirectoryListing(-1, "main:/d/b");
assertEquals(1, listing.size());
assertEquals("foo.txt", listing.get(0).getName());
}
catch (Exception e)
{
e.printStackTrace(System.err);
fail();
}
}
/**
* Test branching and layering interaction.
*/
public void testBranchAndLayer()
{
try
{
// Create a simple directory hierarchy.
fService.createDirectory("main:/", "a");
fService.createDirectory("main:/a", "b");
fService.createFile("main:/a/b", "c.txt");
fService.createFile("main:/a/b", "d.txt");
fService.createFile("main:/a", "e.txt");
fService.createSnapshot("main");
// Make a branch off of a.
fService.createBranch(-1, "main:/a", "main:/", "branch");
fService.createSnapshot("main");
// The branch should contain exactly the same things as the thing
// it branched from.
String original = recursiveList("main:/a", -1, 0);
original = original.substring(original.indexOf('\n'));
String branch = recursiveList("main:/branch", -1, 0);
branch = branch.substring(branch.indexOf('\n'));
assertEquals(original, branch);
// Make a layer pointing to /branch/b
fService.createLayeredDirectory("main:/branch/b", "main:/", "layer");
fService.createSnapshot("main");
// The new layer should contain exactly the same things as the thing it is layered to.
original = recursiveList("main:/branch/b", -1, 0);
original = original.substring(original.indexOf('\n'));
String layer = recursiveList("main:/layer", -1, 0);
layer = layer.substring(layer.indexOf('\n'));
assertEquals(original, layer);
// Make a modification in /a/b, the original branch.
PrintStream out = new PrintStream(fService.getFileOutputStream("main:/a/b/c.txt"));
out.println("I am c, modified in main:/a/b.");
out.close();
fService.createSnapshot("main");
// The layer should still have identical content to /branch/b.
original = recursiveList("main:/branch/b", -1, 0);
original = original.substring(original.indexOf('\n'));
layer = recursiveList("main:/layer", -1, 0);
layer = layer.substring(layer.indexOf('\n'));
assertEquals(original, layer);
// But the layer won't have contents identical to /a/b's
original = recursiveList("main:/a/b", -1, 0);
original = original.substring(original.indexOf('\n'));
assertFalse(original.equals(layer));
// Make a modification in /branch/b
out = new PrintStream(fService.getFileOutputStream("main:/branch/b/d.txt"));
out.println("I am d, modified in main:/branch/b");
out.close();
fService.createSnapshot("main");
// The layer contents should be identical to the latest contents of /branch/b.
original = recursiveList("main:/branch/b", -1, 0);
original = original.substring(original.indexOf('\n'));
layer = recursiveList("main:/layer", -1, 0);
layer = layer.substring(layer.indexOf('\n'));
assertEquals(original, layer);
}
catch (Exception e)
{
e.printStackTrace(System.err);
fail();
}
}
/**
* Test basic Layering.
*/
public void testLayering()
{
try
{
// Make some directories;
fService.createDirectory("main:/", "a");
fService.createDirectory("main:/a", "b");
fService.createDirectory("main:/a/b", "c");
fService.createDirectory("main:/a/b/c", "d");
fService.createSnapshot("main");
// Now make some layers. Three to be precise.
fService.createLayeredDirectory("main:/a", "main:/", "e");
fService.createLayeredDirectory("main:/e", "main:/", "f");
fService.createLayeredDirectory("main:/f", "main:/", "g");
fService.createSnapshot("main");
// e, f, g should all have the same contents as a.
String a = recursiveList("main:/a", -1, 0);
a = a.substring(a.indexOf('\n'));
String e = recursiveList("main:/e", -1, 0);
e = e.substring(e.indexOf('\n'));
String f = recursiveList("main:/f", -1, 0);
f = f.substring(f.indexOf('\n'));
String g = recursiveList("main:/g", -1, 0);
g = g.substring(g.indexOf('\n'));
assertEquals(a, e);
assertEquals(a, f);
assertEquals(a, g);
// Now make a file in /g/b/c/d and /f/b/c/d
fService.createFile("main:/g/b/c/d", "foo");
fService.createFile("main:/f/b/c/d", "bar");
fService.createSnapshot("main");
// /g/b/c/d should contain foo and bar.
List<FolderEntry> listing = fService.getDirectoryListing(-1, "main:/g/b/c/d");
assertEquals(2, listing.size());
assertEquals("bar", listing.get(0).getName());
assertEquals("foo", listing.get(1).getName());
// /f/b/c/d should contain just bar.
listing = fService.getDirectoryListing(-1, "main:/f/b/c/d");
assertEquals(1, listing.size());
assertEquals("bar", listing.get(0).getName());
// Now do something in the bottom layer.
fService.createFile("main:/a/b/c", "baz");
fService.createSnapshot("main");
// /e/b/c should contain baz and d
listing = fService.getDirectoryListing(-1, "main:/e/b/c");
assertEquals(2, listing.size());
assertEquals("baz", listing.get(0).getName());
assertEquals("d", listing.get(1).getName());
// Now add something in the e layer.
fService.createFile("main:/e/b/c/d", "bing");
fService.createSnapshot("main");
// /f/b/c/d should now contain bar and bing.
listing = fService.getDirectoryListing(-1, "main:/f/b/c/d");
assertEquals(2, listing.size());
assertEquals("bar", listing.get(0).getName());
assertEquals("bing", listing.get(1).getName());
System.out.println(recursiveList("main", -1));
}
catch (Exception e)
{
e.printStackTrace(System.err);
}
}
/** /**
* Test adding 100 files to each directory. * Test adding 100 files to each directory.
*/ */
@@ -434,6 +621,7 @@ public class AVMServiceTest extends TestCase
} }
} }
fService.createSnapshot("main"); fService.createSnapshot("main");
System.out.println(recursiveList("main", -1));
} }
catch (Exception e) catch (Exception e)
{ {
@@ -506,4 +694,17 @@ public class AVMServiceTest extends TestCase
toSnapshot.add("main"); toSnapshot.add("main");
fService.createSnapshot(toSnapshot); fService.createSnapshot(toSnapshot);
} }
/**
* Check that history has not been screwed up.
*/
private void checkHistory(TreeMap<Integer, String> history, String repName)
{
for (Integer i : history.keySet())
{
assertEquals(history.get(i), recursiveList(repName, i));
}
int latest = fService.getLatestVersionID(repName);
history.put(latest - 1, recursiveList(repName, -1));
}
} }

View File

@@ -69,11 +69,10 @@ public class FileContent
{ {
fData = new ContentBeanImpl(superRepo.issueContentID()); fData = new ContentBeanImpl(superRepo.issueContentID());
fData.setRefCount(1); fData.setRefCount(1);
BufferedOutputStream out = new BufferedOutputStream(getOutputStream(superRepo));
// Make an empty file. // Make an empty file.
try try
{ {
out.close(); getOutputStream(superRepo).close();
} }
catch (IOException ie) catch (IOException ie)
{ {

View File

@@ -120,7 +120,8 @@ public class LayeredDirectoryNode extends DirectoryNode implements Layered
} }
/** /**
* Construct one from a PlainDirectoryNode. * Construct one from a PlainDirectoryNode. Called when a COW is performed in a layered
* context.
* @param other The PlainDirectoryNode. * @param other The PlainDirectoryNode.
* @param repos The Repository we should belong to. * @param repos The Repository we should belong to.
* @param lPath The Lookup object. * @param lPath The Lookup object.
@@ -129,6 +130,7 @@ public class LayeredDirectoryNode extends DirectoryNode implements Layered
Repository repos, Repository repos,
Lookup lPath) Lookup lPath)
{ {
// TODO Fix this yada, yada.
BasicAttributesBean attrs = new BasicAttributesBeanImpl(other.getDataBean().getBasicAttributes()); BasicAttributesBean attrs = new BasicAttributesBeanImpl(other.getDataBean().getBasicAttributes());
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
attrs.setModDate(time); attrs.setModDate(time);

View File

@@ -121,7 +121,8 @@ public class Lookup
else else
{ {
String parentIndirection = fComponents.get(fPosition).getIndirection(); String parentIndirection = fComponents.get(fPosition).getIndirection();
if (parentIndirection.endsWith("/")) if (parentIndirection.endsWith("/")) // TODO This currently is impossible because
// root dirs are always plain.
{ {
comp.setIndirection(parentIndirection + name); comp.setIndirection(parentIndirection + name);
} }

View File

@@ -200,7 +200,7 @@ public class PlainDirectoryNode extends DirectoryNode
/** /**
* Put a new child node into this directory. No copy. * Put a new child node into this directory. No copy.
* @param name The namke of the child. * @param name The name of the child.
* @param node The node to add. * @param node The node to add.
*/ */
public void putChild(String name, AVMNode node) public void putChild(String name, AVMNode node)

View File

@@ -218,7 +218,7 @@ public interface SuperRepository
* @param name The name of the repository. * @param name The name of the repository.
* @return The latest version id for the given repository. * @return The latest version id for the given repository.
*/ */
public long getLatestVersionID(String name); public int getLatestVersionID(String name);
/** /**
* Get the indirection path for a layered node. * Get the indirection path for a layered node.

View File

@@ -106,7 +106,7 @@
a Repository as special so that its absence of parents will a Repository as special so that its absence of parents will
not cause it to be vacuumed away. TODO: for ease of queries, not cause it to be vacuumed away. TODO: for ease of queries,
this probably wants to be in the base class. --> this probably wants to be in the base class. -->
<property name="isRoot" column="is_root" type="boolean" /> <property name="isRoot" column="is_root" type="boolean"/>
<!-- A map of names to DirectoryEntries. In the AVM world, it makes sense <!-- A map of names to DirectoryEntries. In the AVM world, it makes sense
that nodes don't know there own names, only their containers do. --> that nodes don't know there own names, only their containers do. -->
<map name="children" cascade="all" fetch="join" lazy="true"> <map name="children" cascade="all" fetch="join" lazy="true">
@@ -197,7 +197,7 @@
</map> </map>
<!-- NewNodes keeps track of those nodes created since the last <!-- NewNodes keeps track of those nodes created since the last
'snapshot' operation. --> 'snapshot' operation. -->
<set table="new_nodes" name="newNodes" cascade="all"> <set table="new_nodes" name="newNodes" fetch="join" lazy="true" cascade="all">
<cache usage="read-write"/> <cache usage="read-write"/>
<key column="repository_id"/> <key column="repository_id"/>
<many-to-many class="AVMNodeBeanImpl" <many-to-many class="AVMNodeBeanImpl"

View File

@@ -328,11 +328,11 @@ public class AVMServiceImpl implements AVMService
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.repo.avm.AVMService#getLatestVersionID(java.lang.String) * @see org.alfresco.repo.avm.AVMService#getLatestVersionID(java.lang.String)
*/ */
public long getLatestVersionID(final String repName) public int getLatestVersionID(final String repName)
{ {
class HTxnCallback implements HibernateTxnCallback class HTxnCallback implements HibernateTxnCallback
{ {
public long latestVersionID; public int latestVersionID;
public void perform(Session session) public void perform(Session session)
{ {

View File

@@ -297,8 +297,8 @@ public class RepositoryImpl implements Repository
} }
FileNode file = (FileNode)node; FileNode file = (FileNode)node;
file = (FileNode)file.copyOnWrite(lPath); file = (FileNode)file.copyOnWrite(lPath);
FileContent content = file.getContentForWrite(this); FileContent content = file.getContentForWrite(this);
return content.getOutputStream(fSuper); return content.getOutputStream(fSuper); // TODO Do we really need fSuper?
} }
/* (non-Javadoc) /* (non-Javadoc)
@@ -403,7 +403,7 @@ public class RepositoryImpl implements Repository
public Lookup lookup(int version, String path) public Lookup lookup(int version, String path)
{ {
// Make up a Lookup to hold the results. // Make up a Lookup to hold the results.
Lookup result = new Lookup(this, fData.getName()); Lookup result = new Lookup(this, fData.getName()); // TODO redundant.
if (path.length() == 0) if (path.length() == 0)
{ {
throw new AlfrescoRuntimeException("Invalid path: " + path); throw new AlfrescoRuntimeException("Invalid path: " + path);

View File

@@ -36,6 +36,7 @@ import org.alfresco.repo.avm.Repository;
import org.alfresco.repo.avm.SuperRepository; import org.alfresco.repo.avm.SuperRepository;
import org.alfresco.repo.avm.hibernate.Issuer; import org.alfresco.repo.avm.hibernate.Issuer;
import org.alfresco.repo.avm.hibernate.RepositoryBean; import org.alfresco.repo.avm.hibernate.RepositoryBean;
import org.alfresco.repo.avm.hibernate.RepositoryBeanImpl;
import org.hibernate.Query; import org.hibernate.Query;
import org.hibernate.Session; import org.hibernate.Session;
@@ -483,7 +484,7 @@ public class SuperRepositoryImpl implements SuperRepository
/* (non-Javadoc) /* (non-Javadoc)
* @see org.alfresco.repo.avm.SuperRepository#getLatestVersionID(java.lang.String) * @see org.alfresco.repo.avm.SuperRepository#getLatestVersionID(java.lang.String)
*/ */
public long getLatestVersionID(String name) public int getLatestVersionID(String name)
{ {
Repository rep = getRepositoryByName(name); Repository rep = getRepositoryByName(name);
return rep.getLatestVersion(); return rep.getLatestVersion();
@@ -496,9 +497,12 @@ public class SuperRepositoryImpl implements SuperRepository
*/ */
private Repository getRepositoryByName(String name) private Repository getRepositoryByName(String name)
{ {
/*
Query query = fSession.createQuery("from RepositoryBeanImpl r where r.name = :name"); Query query = fSession.createQuery("from RepositoryBeanImpl r where r.name = :name");
query.setString("name", name); query.setString("name", name);
return new RepositoryImpl(this, (RepositoryBean)query.uniqueResult()); return new RepositoryImpl(this, (RepositoryBean)query.uniqueResult());
*/
return new RepositoryImpl(this, (RepositoryBean)fSession.get(RepositoryBeanImpl.class, name));
} }
/* (non-Javadoc) /* (non-Javadoc)