diff --git a/source/java/org/alfresco/repo/avm/AVMStressTest.java b/source/java/org/alfresco/repo/avm/AVMStressTest.java index 6ea608f407..bf85d0f514 100644 --- a/source/java/org/alfresco/repo/avm/AVMStressTest.java +++ b/source/java/org/alfresco/repo/avm/AVMStressTest.java @@ -36,10 +36,17 @@ public class AVMStressTest extends AVMServiceTestBase try { BulkLoader loader = new BulkLoader(fService); - loader.recursiveLoad("source", "main:/"); + long start = System.currentTimeMillis(); + for (int i = 0; i < 1; i++) + { + fService.createDirectory("main:/", "" + i); + loader.recursiveLoad("source", "main:/" + i); + fService.createSnapshot("main"); + } + System.out.println("Load time: " + (System.currentTimeMillis() - start)); List testers = new ArrayList(); List threads = new ArrayList(); - for (int i = 0; i < 8; i++) + for (int i = 0; i < 1; i++) { AVMTester tester = new AVMTester(400, // create file. @@ -54,7 +61,10 @@ public class AVMStressTest extends AVMServiceTestBase 10000, // # ops fService, "" + i); - tester.Refresh(); + if (i == 0) + { + tester.Refresh(); + } Thread thread = new Thread(tester); testers.add(tester); threads.add(thread); @@ -64,12 +74,12 @@ public class AVMStressTest extends AVMServiceTestBase thread.start(); } int exited = 0; - while (exited != 8) + while (exited != 1) { try { Thread.sleep(2000); - for (int i = 0; i < 8; i++) + for (int i = 0; i < 1; i++) { if (threads.get(i) == null) { diff --git a/source/java/org/alfresco/repo/avm/FileContent.java b/source/java/org/alfresco/repo/avm/FileContent.java index 2c942e6535..923052df56 100644 --- a/source/java/org/alfresco/repo/avm/FileContent.java +++ b/source/java/org/alfresco/repo/avm/FileContent.java @@ -40,25 +40,22 @@ interface FileContent /** * Get an input stream from the content. - * @param superRepo The SuperRepository. * @return An InputStream. */ - public InputStream getInputStream(SuperRepository superRepo); + public InputStream getInputStream(); /** * Get an output stream to the content. - * @param superRepo The SuperRepository. * @return an OutputStream. */ - public OutputStream getOutputStream(SuperRepository superRepo); + public OutputStream getOutputStream(); /** * Get a random access file to this content. - * @param superRepo The SuperRepository. * @param access The mode to open the file in. * @return A RandomAccessFile. */ - public RandomAccessFile getRandomAccess(SuperRepository superRepo, String access); + public RandomAccessFile getRandomAccess(String access); /** * Delete the contents of this from the backing store. @@ -70,7 +67,7 @@ interface FileContent * @param superRepo * @return The length of the file. */ - public long getLength(SuperRepository superRepo); + public long getLength(); /** * Get the object id. diff --git a/source/java/org/alfresco/repo/avm/FileContentImpl.java b/source/java/org/alfresco/repo/avm/FileContentImpl.java index f86d5d8296..81fcc54c54 100644 --- a/source/java/org/alfresco/repo/avm/FileContentImpl.java +++ b/source/java/org/alfresco/repo/avm/FileContentImpl.java @@ -73,38 +73,37 @@ class FileContentImpl implements FileContent, Serializable /** * Make a brand new one. - * @param superRepo The SuperRepository. - * @param source A possibly null stream to get data from. + * @param id The id for this content. */ - public FileContentImpl(SuperRepository superRepo) + public FileContentImpl(long id) { - fID = superRepo.issueContentID(); + fID = id; fRefCount = 1; // Initialize the contents. try { - OutputStream out = getOutputStream(superRepo); + OutputStream out = getOutputStream(); out.close(); } catch (IOException ie) { throw new AVMException("File data error.", ie); } - superRepo.getSession().save(this); + SuperRepository.GetInstance().getSession().save(this); } /** * Copy constructor, sort of. * @param other The content to copy from. - * @param superRepo The SuperRepository. + * @param id The id for this content. */ - public FileContentImpl(FileContent other, SuperRepository superRepo) + public FileContentImpl(FileContent other, long id) { - fID = superRepo.issueContentID(); + fID = id; fRefCount = 1; // Copy the contents from other to this. - BufferedInputStream in = new BufferedInputStream(other.getInputStream(superRepo)); - BufferedOutputStream out = new BufferedOutputStream(this.getOutputStream(superRepo)); + BufferedInputStream in = new BufferedInputStream(other.getInputStream()); + BufferedOutputStream out = new BufferedOutputStream(getOutputStream()); try { byte [] buff = new byte[4096]; // Nyah, nyah. @@ -121,7 +120,7 @@ class FileContentImpl implements FileContent, Serializable { throw new AVMException("I/O failure in Copy on Write.", ie); } - superRepo.getSession().save(this); + SuperRepository.GetInstance().getSession().save(this); } /** @@ -144,40 +143,38 @@ class FileContentImpl implements FileContent, Serializable /** * Get an InputStream from this FileContent. - * @param superRepo The SuperRepository (to get backing store location from). * @return An InputStream. */ - public InputStream getInputStream(SuperRepository superRepo) + public InputStream getInputStream() { try { - return new FileInputStream(getContentPath(superRepo)); + return new FileInputStream(getContentPath()); } catch (IOException ie) { - throw new AVMException("Could not open for reading: " + getContentPath(superRepo), ie); + throw new AVMException("Could not open for reading: " + getContentPath(), ie); } } /** * Gets an ouptut stream to this node. - * @param superRepo The SuperRepository. * @return An OutputStream. */ - public OutputStream getOutputStream(SuperRepository superRepo) + public OutputStream getOutputStream() { try { - File dir = new File(getDirectoryPath(superRepo)); + File dir = new File(getDirectoryPath()); if (!dir.exists()) { dir.mkdirs(); } - return new FileOutputStream(getContentPath(superRepo)); + return new FileOutputStream(getContentPath()); } catch (IOException ie) { - throw new AVMException("Could not open for writing: " + getContentPath(superRepo), ie); + throw new AVMException("Could not open for writing: " + getContentPath(), ie); } } @@ -189,15 +186,15 @@ class FileContentImpl implements FileContent, Serializable * @param access The access more for RandomAccessFile. * @return A RandomAccessFile. */ - public RandomAccessFile getRandomAccess(SuperRepository superRepo, String access) + public RandomAccessFile getRandomAccess(String access) { try { - return new RandomAccessFile(getContentPath(superRepo), access); + return new RandomAccessFile(getContentPath(), access); } catch (IOException ie) { - throw new AVMException("Could not open for random access: " + getContentPath(superRepo), ie); + throw new AVMException("Could not open for random access: " + getContentPath(), ie); } } @@ -206,45 +203,42 @@ class FileContentImpl implements FileContent, Serializable */ public void delete() { - File file = new File(getContentPath(SuperRepository.GetInstance())); + File file = new File(getContentPath()); file.delete(); } /** * Get the length of this content. - * @param superRepo The SuperRepository * @return The length of the content. */ - public long getLength(SuperRepository superRepo) + public long getLength() { - File file = new File(getContentPath(superRepo)); + File file = new File(getContentPath()); return file.length(); } /** * Retrieve the full path for this content. - * @param superRepo * @return The full path for this content. */ - private synchronized String getContentPath(SuperRepository superRepo) + private synchronized String getContentPath() { if (fName == null) { - calcPathData(superRepo); + calcPathData(); } return fName; } /** * Get the directory path for this content. - * @param superRepo * @return The directory path. */ - private synchronized String getDirectoryPath(SuperRepository superRepo) + private synchronized String getDirectoryPath() { if (fPath == null) { - calcPathData(superRepo); + calcPathData(); } return fPath; } @@ -252,7 +246,7 @@ class FileContentImpl implements FileContent, Serializable /** * Calculate the path data. */ - private void calcPathData(SuperRepository superRepo) + private void calcPathData() { Formatter form = new Formatter(new StringBuilder()); form.format("%016x", fID); @@ -263,7 +257,7 @@ class FileContentImpl implements FileContent, Serializable (fID & 0xff0000) >> 16, (fID & 0xff00) >> 8); String dir = form.toString(); - fPath = superRepo.getStorageRoot() + dir; + fPath = SuperRepository.GetInstance().getStorageRoot() + dir; fName = fPath + "/" + name; } diff --git a/source/java/org/alfresco/repo/avm/FileNode.java b/source/java/org/alfresco/repo/avm/FileNode.java index 266b3c05e1..7d9ca08885 100644 --- a/source/java/org/alfresco/repo/avm/FileNode.java +++ b/source/java/org/alfresco/repo/avm/FileNode.java @@ -31,8 +31,7 @@ interface FileNode extends AVMNode /** * Get the content object for writing. This will do COW * as needed. - * @param The repository. * @return A FileContent object. */ - public FileContent getContentForWrite(Repository repo); + public FileContent getContentForWrite(); } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java index 4084266bff..ab1e638ef2 100644 --- a/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredDirectoryNodeImpl.java @@ -299,7 +299,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec { try { - Lookup lookup = lPath.getRepository().getSuperRepository().lookupDirectory(-1, getUnderlying(lPath)); + Lookup lookup = SuperRepository.GetInstance().lookupDirectory(-1, getUnderlying(lPath)); DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode(); if (dir.lookupChild(lookup, name, -1) != null) { @@ -343,7 +343,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec Map baseListing = null; try { - Lookup lookup = lPath.getRepository().getSuperRepository().lookupDirectory(-1, getUnderlying(lPath)); + Lookup lookup = SuperRepository.GetInstance().lookupDirectory(-1, getUnderlying(lPath)); DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode(); baseListing = dir.getListing(lookup); } @@ -443,7 +443,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec // Not here so check our indirection. try { - Lookup lookup = lPath.getRepository().getSuperRepository().lookupDirectory(-1, getUnderlying(lPath)); + Lookup lookup = SuperRepository.GetInstance().lookupDirectory(-1, getUnderlying(lPath)); DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode(); return dir.lookupChild(lookup, name, -1); } @@ -538,7 +538,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec // See if the name is seen via indirection. try { - Lookup lookup = lPath.getRepository().getSuperRepository().lookupDirectory(-1, getUnderlying(lPath)); + Lookup lookup = SuperRepository.GetInstance().lookupDirectory(-1, getUnderlying(lPath)); DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode(); if (dir.lookupChild(lookup, name, -1) == null) { @@ -621,7 +621,7 @@ class LayeredDirectoryNodeImpl extends DirectoryNodeImpl implements LayeredDirec DeletedChild dc = toModify.getDeleted(name); if (dc != null) { - lPath.getRepository().getSuperRepository().getSession().delete(dc); + SuperRepository.GetInstance().getSession().delete(dc); } } diff --git a/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java index 442765b0ca..9a4a6eeebf 100644 --- a/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java @@ -69,7 +69,7 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode public AVMNode possiblyCopy(Lookup lPath) { // LayeredFileNodes are always copied. - Lookup lookup = lPath.getRepository().getSuperRepository().lookup(-1, fIndirection); + Lookup lookup = SuperRepository.GetInstance().lookup(-1, fIndirection); AVMNode indirect = lookup.getCurrentNode(); if (indirect.getType() != AVMNodeType.LAYERED_FILE && indirect.getType() != AVMNodeType.PLAIN_FILE) @@ -113,10 +113,9 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode /** * Get File Content for writing. Should never be called. - * @param repo The Repository. * @return Always null. */ - public FileContent getContentForWrite(Repository repo) + public FileContent getContentForWrite() { assert false : "Never happens"; return null; diff --git a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java index bb4b0dbf74..fbf3654949 100644 --- a/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/PlainDirectoryNodeImpl.java @@ -295,7 +295,7 @@ class PlainDirectoryNodeImpl extends DirectoryNodeImpl implements PlainDirectory public void turnPrimary(Lookup lPath) { LayeredDirectoryNode toModify = (LayeredDirectoryNode)copyOnWrite(lPath); - Lookup lookup = lPath.getRepository().getSuperRepository().lookup(-1, lPath.getRepresentedPath()); + Lookup lookup = SuperRepository.GetInstance().lookup(-1, lPath.getRepresentedPath()); toModify.rawSetPrimary(lookup.getCurrentIndirection()); } diff --git a/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java index 0dfa6c6eb0..9441b23194 100644 --- a/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java @@ -47,7 +47,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode public PlainFileNodeImpl(Repository repos) { super(repos.getSuperRepository().issueID(), repos); - fContent = new FileContentImpl(repos.getSuperRepository()); + fContent = new FileContentImpl(SuperRepository.GetInstance().issueContentID()); repos.getSuperRepository().getSession().save(this); } @@ -114,13 +114,12 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode /** * Get content for writing. - * @param repo The Repository. */ - public FileContent getContentForWrite(Repository repo) + public FileContent getContentForWrite() { if (fContent.getRefCount() > 1) { - fContent = new FileContentImpl(fContent, repo.getSuperRepository()); + fContent = new FileContentImpl(fContent, SuperRepository.GetInstance().issueContentID()); } return fContent; } @@ -157,8 +156,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode null, false, -1, - getContentForRead() - .getLength(lPath.getRepository().getSuperRepository())); + getContentForRead().getLength()); } /** @@ -185,8 +183,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode null, false, -1, - getContentForRead() - .getLength(getRepository().getSuperRepository())); + getContentForRead().getLength()); } /** diff --git a/source/java/org/alfresco/repo/avm/RepositoryImpl.java b/source/java/org/alfresco/repo/avm/RepositoryImpl.java index 2ac3a65ac3..397496cdd8 100644 --- a/source/java/org/alfresco/repo/avm/RepositoryImpl.java +++ b/source/java/org/alfresco/repo/avm/RepositoryImpl.java @@ -224,7 +224,7 @@ class RepositoryImpl implements Repository, Serializable PlainFileNodeImpl file = new PlainFileNodeImpl(this); file.setVersionID(getNextVersionID()); dir.addChild(name, file, lPath); - return file.getContentForWrite(this).getOutputStream(fSuper); + return file.getContentForWrite().getOutputStream(); } /** @@ -266,7 +266,7 @@ class RepositoryImpl implements Repository, Serializable } FileNode file = (FileNode)node; FileContent content = file.getContentForRead(); - return content.getInputStream(fSuper); + return content.getInputStream(); } /** @@ -309,8 +309,8 @@ class RepositoryImpl implements Repository, Serializable } FileNode file = (FileNode)node; file = (FileNode)file.copyOnWrite(lPath); - FileContent content = file.getContentForWrite(this); - return content.getOutputStream(fSuper); // TODO Do we really need fSuper? + FileContent content = file.getContentForWrite(); + return content.getOutputStream(); // TODO Do we really need fSuper? } /** @@ -343,13 +343,13 @@ class RepositoryImpl implements Repository, Serializable if (write) { file = (FileNode)file.copyOnWrite(lPath); - content = file.getContentForWrite(this); + content = file.getContentForWrite(); } else { content = file.getContentForRead(); } - return content.getRandomAccess(fSuper, access); + return content.getRandomAccess(access); } /** diff --git a/source/java/org/alfresco/repo/avm/SimultaneousLoadTest.java b/source/java/org/alfresco/repo/avm/SimultaneousLoadTest.java new file mode 100644 index 0000000000..add30cc31d --- /dev/null +++ b/source/java/org/alfresco/repo/avm/SimultaneousLoadTest.java @@ -0,0 +1,94 @@ +/* + * 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 org.alfresco.repo.avm.util.BulkLoader; + +/** + * This tests loading content simultaneously. + * @author britt + */ +public class SimultaneousLoadTest extends AVMServiceTestBase +{ + /** + * Test loading content simultaneously. + */ + public void testSimultaneousLoad() + { + try + { + int n = 16; + for (int i = 0; i < n; i++) + { + fService.createDirectory("main:/", "d" + i); + } + fService.createSnapshot("main"); + Thread [] threads = new Thread[n]; + for (int i = 0; i < n; i++) + { + Loader loader = new Loader("source", "main:/d" + i); + threads[i] = new Thread(loader); + threads[i].start(); + } + for (int i = 0; i < n; i++) + { + threads[i].join(); + } + } + catch (Exception e) + { + e.printStackTrace(System.err); + fail(); + } + } + + private class Loader implements Runnable + { + /** + * The BulkLoader. + */ + private BulkLoader fLoader; + + /** + * The source directory. + */ + private String fSource; + + /** + * The destination path. + */ + private String fDestination; + + /** + * Set up. + * @param source Source directory. + * @param destination Destination path. + */ + public Loader(String source, String destination) + { + fLoader = new BulkLoader(fService); + fSource = source; + fDestination = destination; + } + + public void run() + { + fLoader.recursiveLoad(fSource, fDestination); + } + } +} diff --git a/source/java/org/alfresco/repo/avm/SuperRepository.java b/source/java/org/alfresco/repo/avm/SuperRepository.java index b1c6bda5f3..31ce8c8bda 100644 --- a/source/java/org/alfresco/repo/avm/SuperRepository.java +++ b/source/java/org/alfresco/repo/avm/SuperRepository.java @@ -528,7 +528,7 @@ class SuperRepository throw new AVMWrongTypeException("Not a file."); } FileNode file = (FileNode)node; - return file.getContentForRead().getInputStream(SuperRepository.GetInstance()); + return file.getContentForRead().getInputStream(); } /** diff --git a/source/java/org/alfresco/repo/avm/util/BulkLoader.java b/source/java/org/alfresco/repo/avm/util/BulkLoader.java index 8f29ba4aec..8ce5a8d50c 100644 --- a/source/java/org/alfresco/repo/avm/util/BulkLoader.java +++ b/source/java/org/alfresco/repo/avm/util/BulkLoader.java @@ -72,7 +72,6 @@ public class BulkLoader */ public void recursiveLoad(String fsPath, String repPath) { - System.out.println(fsPath); File file = new File(fsPath); String name = file.getName(); if (file.isDirectory())