diff --git a/source/java/org/alfresco/repo/avm/AVMCrawlTest.java b/source/java/org/alfresco/repo/avm/AVMCrawlTest.java new file mode 100644 index 0000000000..22f1d99575 --- /dev/null +++ b/source/java/org/alfresco/repo/avm/AVMCrawlTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ + +package org.alfresco.repo.avm; + +import java.util.ArrayList; +import java.util.List; + +import org.alfresco.repo.avm.util.BulkLoader; + + +/** + * Another performance test that runs simultaneous crawlers that + * do operations with locality of reference. + * @author britt + */ +public class AVMCrawlTest extends AVMServiceTestBase +{ + /** + * Do the crawl test. + */ + public void testCrawl() + { + int n = 4; // Number of Threads. + int m = 1; // How many multiples of content to start with. + long runTime = 1200000; // Ten minutes + fService.purgeRepository("main"); + BulkLoader loader = new BulkLoader(fService); + for (int i = 0; i < m; i++) + { + fService.createRepository("d" + i); + loader.recursiveLoad("source", "d" + i + ":/"); + fService.createSnapshot("d" + i); + } + long startTime = System.currentTimeMillis(); + List crawlers = new ArrayList(); + List threads = new ArrayList(); + for (int i = 0; i < n; i++) + { + crawlers.add(new AVMCrawler(fService)); + threads.add(new Thread(crawlers.get(i))); + threads.get(i).start(); + } + while (true) + { + try + { + Thread.sleep(5000); + // Check that none of the crawlers has errored out. + for (AVMCrawler crawler : crawlers) + { + if (crawler.getError()) + { + for (AVMCrawler craw : crawlers) + { + craw.setDone(); + } + for (Thread thread : threads) + { + try + { + thread.join(); + } + catch (InterruptedException ie) + { + // Do nothing. + } + } + fail(); + } + } + } + catch (InterruptedException ie) + { + // Do nothing. + } + long now = System.currentTimeMillis(); + if (now - startTime > runTime) + { + break; + } + } + for (AVMCrawler crawler : crawlers) + { + crawler.setDone(); + } + for (Thread thread : threads) + { + try + { + thread.join(); + } + catch (InterruptedException ie) + { + // Do nothing. + } + } + long ops = 0L; + for (AVMCrawler crawler : crawlers) + { + ops += crawler.getOpCount(); + } + long time = System.currentTimeMillis() - startTime; + System.out.println("Ops/Sec: " + (ops * 1000L / time)); + } +} diff --git a/source/java/org/alfresco/repo/avm/AVMCrawler.java b/source/java/org/alfresco/repo/avm/AVMCrawler.java new file mode 100644 index 0000000000..12ea1193ed --- /dev/null +++ b/source/java/org/alfresco/repo/avm/AVMCrawler.java @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2006 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ + +package org.alfresco.repo.avm; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Random; + + +/** + * This is another tester designed to emulate more typical use patterns. + * @author britt + */ +class AVMCrawler implements Runnable +{ + /** + * The AVMService to use. + */ + private AVMService fService; + + /** + * The Operation count. + */ + private int fOpCount; + + /** + * Whether we are done. + */ + private boolean fDone; + + /** + * Whether an error has occurred. + */ + private boolean fError; + + /** + * Random number generator. + */ + private Random fRandom; + + /** + * Make up a new one. + * @param service The AVMService. + */ + public AVMCrawler(AVMService service) + { + fService = service; + fOpCount = 0; + fDone = false; + fError = false; + fRandom = new Random(); + } + + /** + * Tell this thread it is done. + */ + public void setDone() + { + fDone = true; + } + + /** + * Is this thread in an error state. + */ + public boolean getError() + { + return fError; + } + + /** + * Implementation of run. + */ + public void run() + { + try + { + while (!fDone) + { + doCrawl(); + } + } + catch (Exception e) + { + fError = true; + } + } + + /** + * Do one crawl. + */ + public void doCrawl() + { + try + { + List reps = fService.getRepositories(); + fOpCount++; + RepositoryDescriptor repDesc = reps.get(fRandom.nextInt(reps.size())); + Map rootListing = fService.getDirectoryListing(-1, repDesc.getName() + ":/"); + fOpCount++; + // Get all the directories in the root. + List dirs = new ArrayList(); + for (AVMNodeDescriptor desc : rootListing.values()) + { + if (desc.isDirectory()) + { + dirs.add(desc); + } + } + AVMNodeDescriptor dir = dirs.get(fRandom.nextInt(dirs.size())); + while (dir != null) + { + Map listing = fService.getDirectoryListing(-1, dir.getPath()); + fOpCount++; + List files = new ArrayList(); + dirs = new ArrayList(); + for (AVMNodeDescriptor desc : listing.values()) + { + if (desc.isDirectory()) + { + dirs.add(desc); + } + else + { + files.add(desc); + } + } + // Read some files if there are any. + if (files.size() > 0) + { + for (int i = 0; i < 6; i++) + { + BufferedReader + reader = new BufferedReader + (new InputStreamReader + (fService.getFileInputStream(-1, files.get(fRandom.nextInt(files.size())).getPath()))); + fOpCount++; + String line = reader.readLine(); + System.out.println(line); + reader.close(); + } + // Modify some files. + for (int i = 0; i < 2; i++) + { + String path = files.get(fRandom.nextInt(files.size())).getPath(); + PrintStream out = new PrintStream(fService.getFileOutputStream(path)); + out.println("I am " + path); + out.close(); + fOpCount++; + } + } + // Create some files. + for (int i = 0; i < 1; i++) + { + String name = randomName(); + PrintStream out = new PrintStream(fService.createFile(dir.getPath(), name)); + fOpCount++; + out.println("I am " + name); + out.close(); + } + // 1 in 100 times create a directory. + if (fRandom.nextInt(100) == 0) + { + String name = randomName(); + fService.createDirectory(dir.getPath(), name); + fOpCount++; + } + if (listing.size() > 0) + { + // 1 in 100 times remove something + if (fRandom.nextInt(100) == 0) + { + List names = new ArrayList(listing.keySet()); + fService.removeNode(dir.getPath(), + names.get(fRandom.nextInt(names.size()))); + fOpCount++; + } + } + if (dirs.size() > 0) + { + dir = dirs.get(fRandom.nextInt(dirs.size())); + } + else + { + dir = null; + } + } + if (fRandom.nextInt(16) == 0) + { + fService.createSnapshot(repDesc.getName()); + fOpCount++; + } + } + catch (Exception e) + { + if (e instanceof AVMNotFoundException || + e instanceof AVMExistsException) + { + return; + } + e.printStackTrace(System.err); + throw new AVMException("Failure", e); + } + } + + /** + * Get a random two character string. + * @return A random name. + */ + private String randomName() + { + char [] chars = new char[2]; + chars[0] = (char)('a' + fRandom.nextInt(26)); + chars[1] = (char)('a' + fRandom.nextInt(26)); + return new String(chars); + } + + /** + * Get the operation count. + */ + public int getOpCount() + { + return fOpCount; + } +} + + diff --git a/source/java/org/alfresco/repo/avm/AVMNode.java b/source/java/org/alfresco/repo/avm/AVMNode.java index d1db9d4cf2..55162a750a 100644 --- a/source/java/org/alfresco/repo/avm/AVMNode.java +++ b/source/java/org/alfresco/repo/avm/AVMNode.java @@ -76,13 +76,21 @@ interface AVMNode */ public int getType(); + + /** + * Get the descriptor for this node. + * @param The Lookup. + * @return The descriptor for this node. + */ + public AVMNodeDescriptor getDescriptor(Lookup lPath, String name); + /** * Get the descriptor for this node. * @param The Lookup. * @return The descriptor for this node. */ public AVMNodeDescriptor getDescriptor(Lookup lPath); - + /** * Get a node descriptor for this node. * @param parentPath The parent path. diff --git a/source/java/org/alfresco/repo/avm/AVMNodeDescriptor.java b/source/java/org/alfresco/repo/avm/AVMNodeDescriptor.java index 50aa9dd5bb..88c1666f5b 100644 --- a/source/java/org/alfresco/repo/avm/AVMNodeDescriptor.java +++ b/source/java/org/alfresco/repo/avm/AVMNodeDescriptor.java @@ -31,6 +31,11 @@ public class AVMNodeDescriptor */ private String fPath; + /** + * The base name of the path. + */ + private String fName; + /** * The type of this node. AVMNodeType constants. */ @@ -113,22 +118,24 @@ public class AVMNodeDescriptor * @param layerID The layer id. * @param length The file length. */ - public AVMNodeDescriptor(String path, - int type, - String creator, - String owner, - String lastModifier, - long createDate, - long modDate, - long accessDate, - long id, - int versionID, - String indirection, + public AVMNodeDescriptor(String path, + String name, + int type, + String creator, + String owner, + String lastModifier, + long createDate, + long modDate, + long accessDate, + long id, + int versionID, + String indirection, boolean isPrimary, - long layerID, - long length) + long layerID, + long length) { fPath = path; + fName = name; fType = type; fCreator = creator; fOwner = owner; @@ -342,6 +349,14 @@ public class AVMNodeDescriptor return fLength; } + /** + * Get the name of the node. + */ + public String getName() + { + return fName; + } + /** * Get a debuggable string representation of this. * @return A string representation of this. diff --git a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java index 818dea9c57..5037635342 100644 --- a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java @@ -537,6 +537,40 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec } } + /** + * Get the descriptor for this node. + * @param The Lookup. + * @return A descriptor. + */ + public AVMNodeDescriptor getDescriptor(Lookup lPath, String name) + { + BasicAttributes attrs = getBasicAttributes(); + String path = lPath.getRepresentedPath(); + if (path.endsWith("/")) + { + path = path + name; + } + else + { + path = path + "/" + name; + } + return new AVMNodeDescriptor(path, + name, + AVMNodeType.LAYERED_DIRECTORY, + attrs.getCreator(), + attrs.getOwner(), + attrs.getLastModifier(), + attrs.getCreateDate(), + attrs.getModDate(), + attrs.getAccessDate(), + getId(), + getVersionID(), + getUnderlying(lPath), + fPrimaryIndirection, + fLayerID, + -1); + } + /** * Get the descriptor for this node. * @param The Lookup. @@ -545,7 +579,10 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec public AVMNodeDescriptor getDescriptor(Lookup lPath) { BasicAttributes attrs = getBasicAttributes(); - return new AVMNodeDescriptor(lPath.getRepresentedPath(), + String path = lPath.getRepresentedPath(); + String name = path.substring(path.lastIndexOf("/") + 1); + return new AVMNodeDescriptor(path, + name, AVMNodeType.LAYERED_DIRECTORY, attrs.getCreator(), attrs.getOwner(), @@ -583,6 +620,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec parentIndirection + "/" + name; } return new AVMNodeDescriptor(path, + name, AVMNodeType.LAYERED_DIRECTORY, attrs.getCreator(), attrs.getOwner(), diff --git a/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java index 1504b9a012..7750149973 100644 --- a/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java @@ -141,6 +141,40 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode return "[LF:" + getId() + ":" + fIndirection + "]"; } + /** + * Get the descriptor for this node. + * @param The Lookup. + * @return A descriptor. + */ + public AVMNodeDescriptor getDescriptor(Lookup lPath, String name) + { + BasicAttributes attrs = getBasicAttributes(); + String path = lPath.getRepresentedPath(); + if (path.endsWith("/")) + { + path = path + name; + } + else + { + path = path + "/" + name; + } + return new AVMNodeDescriptor(path, + name, + AVMNodeType.LAYERED_FILE, + attrs.getCreator(), + attrs.getOwner(), + attrs.getLastModifier(), + attrs.getCreateDate(), + attrs.getModDate(), + attrs.getAccessDate(), + getId(), + getVersionID(), + getUnderlying(lPath), + false, + -1, + 0); + } + /** * Get the descriptor for this node. * @param The Lookup. @@ -149,7 +183,9 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode public AVMNodeDescriptor getDescriptor(Lookup lPath) { BasicAttributes attrs = getBasicAttributes(); - return new AVMNodeDescriptor(lPath.getRepresentedPath(), + String path = lPath.getRepresentedPath(); + return new AVMNodeDescriptor(path, + path.substring(path.lastIndexOf("/") + 1), AVMNodeType.LAYERED_FILE, attrs.getCreator(), attrs.getOwner(), @@ -177,6 +213,7 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode BasicAttributes attrs = getBasicAttributes(); String path = parentPath.endsWith("/") ? parentPath + name : parentPath + "/" + name; return new AVMNodeDescriptor(path, + name, AVMNodeType.LAYERED_FILE, attrs.getCreator(), attrs.getOwner(), diff --git a/source/java/org/alfresco/repo/avm/Lookup.java b/source/java/org/alfresco/repo/avm/Lookup.java index 0b265c9670..f024bcbae0 100644 --- a/source/java/org/alfresco/repo/avm/Lookup.java +++ b/source/java/org/alfresco/repo/avm/Lookup.java @@ -338,6 +338,11 @@ class Lookup return builder.toString(); } + public String getBaseName() + { + return fComponents.get(fPosition).getName(); + } + /** * Acquire locks for writing, in path lookup order. */ diff --git a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java index 7dbb573a62..41a3d45bb7 100644 --- a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java @@ -263,6 +263,40 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory assert false : "Should never happen."; } + /** + * Get the descriptor for this node. + * @param The Lookup. + * @return A descriptor. + */ + public AVMNodeDescriptor getDescriptor(Lookup lPath, String name) + { + BasicAttributes attrs = getBasicAttributes(); + String path = lPath.getRepresentedPath(); + if (path.endsWith("/")) + { + path = path + name; + } + else + { + path = path + "/" + name; + } + return new AVMNodeDescriptor(path, + name, + AVMNodeType.PLAIN_DIRECTORY, + attrs.getCreator(), + attrs.getOwner(), + attrs.getLastModifier(), + attrs.getCreateDate(), + attrs.getModDate(), + attrs.getAccessDate(), + getId(), + getVersionID(), + null, + false, + -1, + -1); + } + /** * Get the descriptor for this node. * @param The Lookup. @@ -271,7 +305,9 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory public AVMNodeDescriptor getDescriptor(Lookup lPath) { BasicAttributes attrs = getBasicAttributes(); - return new AVMNodeDescriptor(lPath.getRepresentedPath(), + String path = lPath.getRepresentedPath(); + return new AVMNodeDescriptor(path, + path.substring(path.lastIndexOf("/") + 1), AVMNodeType.PLAIN_DIRECTORY, attrs.getCreator(), attrs.getOwner(), @@ -299,6 +335,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory BasicAttributes attrs = getBasicAttributes(); String path = parentPath.endsWith("/") ? parentPath + name : parentPath + "/" + name; return new AVMNodeDescriptor(path, + name, AVMNodeType.PLAIN_DIRECTORY, attrs.getCreator(), attrs.getOwner(), diff --git a/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java index 265f18c40e..527a16a1c7 100644 --- a/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java @@ -131,6 +131,40 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode return "[PF:" + getId() + "]"; } + /** + * Get the descriptor for this node. + * @param The Lookup. + * @return A descriptor. + */ + public AVMNodeDescriptor getDescriptor(Lookup lPath, String name) + { + BasicAttributes attrs = getBasicAttributes(); + String path = lPath.getRepresentedPath(); + if (path.endsWith("/")) + { + path = path + name; + } + else + { + path = path + "/" + name; + } + return new AVMNodeDescriptor(path, + name, + AVMNodeType.PLAIN_FILE, + attrs.getCreator(), + attrs.getOwner(), + attrs.getLastModifier(), + attrs.getCreateDate(), + attrs.getModDate(), + attrs.getAccessDate(), + getId(), + getVersionID(), + null, + false, + -1, + getContentForRead().getLength()); + } + /** * Get the descriptor for this node. * @param The Lookup. @@ -139,7 +173,9 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode public AVMNodeDescriptor getDescriptor(Lookup lPath) { BasicAttributes attrs = getBasicAttributes(); - return new AVMNodeDescriptor(lPath.getRepresentedPath(), + String path = lPath.getRepresentedPath(); + return new AVMNodeDescriptor(path, + path.substring(path.lastIndexOf("/") + 1), AVMNodeType.PLAIN_FILE, attrs.getCreator(), attrs.getOwner(), @@ -167,6 +203,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode BasicAttributes attrs = getBasicAttributes(); String path = parentPath.endsWith("/") ? parentPath + name : parentPath + "/" + name; return new AVMNodeDescriptor(path, + name, AVMNodeType.PLAIN_FILE, attrs.getCreator(), attrs.getOwner(), diff --git a/source/java/org/alfresco/repo/avm/RepositoryImpl.java b/source/java/org/alfresco/repo/avm/RepositoryImpl.java index b00176affe..86f3a77f72 100644 --- a/source/java/org/alfresco/repo/avm/RepositoryImpl.java +++ b/source/java/org/alfresco/repo/avm/RepositoryImpl.java @@ -297,7 +297,7 @@ class RepositoryImpl implements Repository, Serializable for (String name : listing.keySet()) { AVMNode child = listing.get(name); - AVMNodeDescriptor desc = child.getDescriptor(lPath); + AVMNodeDescriptor desc = child.getDescriptor(lPath, name); results.put(name, desc); } return results;