From 37843668a47a762e7799594209b86c3a1576ff84 Mon Sep 17 00:00:00 2001 From: Britt Park Date: Mon, 3 Jul 2006 16:36:31 +0000 Subject: [PATCH] A new flavor of createFile. Slightly slower. Significantly safer. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3277 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../org/alfresco/repo/avm/AVMCrawler.java | 10 ++-- .../org/alfresco/repo/avm/AVMService.java | 9 ++++ .../org/alfresco/repo/avm/AVMServiceImpl.java | 54 +++++++++++++++++++ .../org/alfresco/repo/avm/AVMServiceTest.java | 5 +- .../alfresco/repo/avm/FileContentImpl.java | 30 +++++++++++ .../alfresco/repo/avm/PlainFileNodeImpl.java | 14 +++++ .../org/alfresco/repo/avm/Repository.java | 9 ++++ .../org/alfresco/repo/avm/RepositoryImpl.java | 23 +++++++- .../alfresco/repo/avm/SuperRepository.java | 15 ++++++ 9 files changed, 163 insertions(+), 6 deletions(-) diff --git a/source/java/org/alfresco/repo/avm/AVMCrawler.java b/source/java/org/alfresco/repo/avm/AVMCrawler.java index 12ea1193ed..2785a53a1f 100644 --- a/source/java/org/alfresco/repo/avm/AVMCrawler.java +++ b/source/java/org/alfresco/repo/avm/AVMCrawler.java @@ -18,6 +18,7 @@ package org.alfresco.repo.avm; import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.util.ArrayList; @@ -171,10 +172,13 @@ class AVMCrawler implements Runnable for (int i = 0; i < 1; i++) { String name = randomName(); - PrintStream out = new PrintStream(fService.createFile(dir.getPath(), name)); + fService.createFile(dir.getPath(), name, + new ByteArrayInputStream(("I am " + name).getBytes())); fOpCount++; - out.println("I am " + name); - out.close(); +// 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) diff --git a/source/java/org/alfresco/repo/avm/AVMService.java b/source/java/org/alfresco/repo/avm/AVMService.java index ba30de6377..167874562b 100644 --- a/source/java/org/alfresco/repo/avm/AVMService.java +++ b/source/java/org/alfresco/repo/avm/AVMService.java @@ -86,6 +86,15 @@ public interface AVMService */ public OutputStream createFile(String path, String name); + /** + * Create a new File. Guarantees that the entire contents of the + * input stream will be loaded atomically. + * @param path The path to the parent directory. + * @param name The name for the new file. + * @param in An input stream with data for the file. + */ + public void createFile(String path, String name, InputStream in); + /** * Create a new directory. * @param path The simple absolute path to the parent. diff --git a/source/java/org/alfresco/repo/avm/AVMServiceImpl.java b/source/java/org/alfresco/repo/avm/AVMServiceImpl.java index a56f6d04a2..1ebdac6809 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceImpl.java @@ -18,6 +18,8 @@ package org.alfresco.repo.avm; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; @@ -356,6 +358,58 @@ public class AVMServiceImpl implements AVMService return doit.out; } + /** + * Create a file with content specified by the InputStream. + * Guaranteed to be created atomically. + * @param path The path to the containing directory. + * @param name The name to give the file. + * @param in An InputStream containing data for file. + */ + public void createFile(final String path, final String name, InputStream in) + { + if (path == null || name == null || in == null) + { + throw new AVMBadArgumentException("Illegal null argument."); + } + // Save the contents to temp space. + File dir = new File(fStorage); + final File temp; + try + { + temp = File.createTempFile("alf", "tmp", dir); + OutputStream out = new FileOutputStream(temp); + byte [] buff = new byte[8192]; + int read; + while ((read = in.read(buff)) != -1) + { + out.write(buff, 0, read); + } + out.close(); + in.close(); + } + catch (IOException ie) + { + throw new AVMException("I/O Error."); + } + class HTxnCallback implements HibernateTxnCallback + { + public void perform(Session session) + { + fSuperRepository.setSession(session); + fSuperRepository.createFile(path, name, temp); + } + } + HTxnCallback doit = new HTxnCallback(); + try + { + fTransaction.perform(doit, true); + } + finally + { + temp.delete(); + } + } + /* (non-Javadoc) * @see org.alfresco.repo.avm.AVMService#createFolder(java.lang.String, java.lang.String) */ diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index 3e2fd97685..a0f068536c 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -18,6 +18,7 @@ package org.alfresco.repo.avm; import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.RandomAccessFile; @@ -47,8 +48,8 @@ public class AVMServiceTest extends AVMServiceTestBase fService.createDirectory("main:/", "a"); fService.createDirectory("main:/a", "b"); fService.createDirectory("main:/a", "c"); - fService.createFile("main:/a/b", "foo").close(); - fService.createFile("main:/a/c", "bar").close(); + fService.createFile("main:/a/b", "foo", new ByteArrayInputStream("I am foo.".getBytes())); + fService.createFile("main:/a/c", "bar", new ByteArrayInputStream("I am bar.".getBytes())); fService.createSnapshot("main"); // History is unchanged. checkHistory(history, "main"); diff --git a/source/java/org/alfresco/repo/avm/FileContentImpl.java b/source/java/org/alfresco/repo/avm/FileContentImpl.java index e99fe293f5..ea6423c88c 100644 --- a/source/java/org/alfresco/repo/avm/FileContentImpl.java +++ b/source/java/org/alfresco/repo/avm/FileContentImpl.java @@ -92,6 +92,36 @@ class FileContentImpl implements FileContent, Serializable SuperRepository.GetInstance().getSession().save(this); } + /** + * Initialize with the given content. + * @param id + * @param content + */ + public FileContentImpl(long id, File content) + { + fID = id; + fRefCount = 1; + // Initialize the contents. + try + { + OutputStream out = getOutputStream(); + InputStream in = new FileInputStream(content); + byte [] buff = new byte[8192]; + int count; + while ((count = in.read(buff)) != -1) + { + out.write(buff, 0, count); + } + out.close(); + in.close(); + } + catch (IOException ie) + { + throw new AVMException("I/O Error.", ie); + } + SuperRepository.GetInstance().getSession().save(this); + } + /** * Copy constructor, sort of. * @param other The content to copy from. diff --git a/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java index b3f18fc901..effcb87367 100644 --- a/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java @@ -17,6 +17,8 @@ package org.alfresco.repo.avm; +import java.io.File; + /** * A plain old file. Contains a Content object. @@ -50,6 +52,18 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode repos.getSuperRepository().getSession().save(this); } + /** + * Create a new plain file with given content. + * @param repos The repository. + * @param content The content to set. + */ + public PlainFileNodeImpl(Repository repos, File content) + { + super(repos.getSuperRepository().issueID(), repos); + fContent = new FileContentImpl(SuperRepository.GetInstance().issueContentID(), content); + repos.getSuperRepository().getSession().save(this); + } + /** * Copy on write constructor. * @param other The node we are being copied from. diff --git a/source/java/org/alfresco/repo/avm/Repository.java b/source/java/org/alfresco/repo/avm/Repository.java index 26ef1d39d7..ebebf65f9c 100644 --- a/source/java/org/alfresco/repo/avm/Repository.java +++ b/source/java/org/alfresco/repo/avm/Repository.java @@ -16,6 +16,7 @@ */ package org.alfresco.repo.avm; +import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; @@ -73,6 +74,14 @@ interface Repository * @return An OutputStream. */ public OutputStream createFile(String path, String name); + + /** + * Create a file with the given contents. + * @param path The path to the containing directory. + * @param name The name to give the file. + * @param data The contents of the file. + */ + public void createFile(String path, String name, File data); /** * Create a new layered file. diff --git a/source/java/org/alfresco/repo/avm/RepositoryImpl.java b/source/java/org/alfresco/repo/avm/RepositoryImpl.java index d4b68b4ecc..a4839655a6 100644 --- a/source/java/org/alfresco/repo/avm/RepositoryImpl.java +++ b/source/java/org/alfresco/repo/avm/RepositoryImpl.java @@ -17,6 +17,7 @@ package org.alfresco.repo.avm; +import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; @@ -241,10 +242,30 @@ class RepositoryImpl implements Repository, Serializable PlainFileNodeImpl file = new PlainFileNodeImpl(this); file.setVersionID(getNextVersionID()); dir.putChild(name, file); - file.updateModTime(); + dir.updateModTime(); return file.getContentForWrite().getOutputStream(); } + /** + * Create a file with the given contents. + * @param path The path to the containing directory. + * @param name The name to give the new file. + * @param data The contents. + */ + public void createFile(String path, String name, File data) + { + Lookup lPath = lookupDirectory(-1, path, true); + DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode(); + if (dir.lookupChild(lPath, name, -1, true) != null) + { + throw new AVMExistsException("Child exists: " + name); + } + PlainFileNodeImpl file = new PlainFileNodeImpl(this, data); + file.setVersionID(getNextVersionID()); + dir.putChild(name, file); + dir.updateModTime(); + } + /** * Create a new layered file. * @param srcPath The target indirection for the layered file. diff --git a/source/java/org/alfresco/repo/avm/SuperRepository.java b/source/java/org/alfresco/repo/avm/SuperRepository.java index f70cb02cd6..ef1dbed174 100644 --- a/source/java/org/alfresco/repo/avm/SuperRepository.java +++ b/source/java/org/alfresco/repo/avm/SuperRepository.java @@ -17,6 +17,7 @@ package org.alfresco.repo.avm; +import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; @@ -117,6 +118,20 @@ class SuperRepository return rep.createFile(pathParts[1], name); } + /** + * Create a file with the given File as content. + * @param path The path to the containing directory. + * @param name The name to give the file. + * @param data The file contents. + */ + public void createFile(String path, String name, File data) + { + fLookupCount.set(1); + String[] pathParts = SplitPath(path); + Repository rep = getRepositoryByName(pathParts[0], true); + rep.createFile(pathParts[1], name, data); + } + /** * Create a new directory. * @param path The path to the containing directory.