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
This commit is contained in:
Britt Park
2006-07-03 16:36:31 +00:00
parent 92a7348a43
commit 37843668a4
9 changed files with 163 additions and 6 deletions

View File

@@ -18,6 +18,7 @@
package org.alfresco.repo.avm; package org.alfresco.repo.avm;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.ArrayList; import java.util.ArrayList;
@@ -171,10 +172,13 @@ class AVMCrawler implements Runnable
for (int i = 0; i < 1; i++) for (int i = 0; i < 1; i++)
{ {
String name = randomName(); String name = randomName();
PrintStream out = new PrintStream(fService.createFile(dir.getPath(), name)); fService.createFile(dir.getPath(), name,
new ByteArrayInputStream(("I am " + name).getBytes()));
fOpCount++; fOpCount++;
out.println("I am " + name); // PrintStream out = new PrintStream(fService.createFile(dir.getPath(), name));
out.close(); // fOpCount++;
// out.println("I am " + name);
// out.close();
} }
// 1 in 100 times create a directory. // 1 in 100 times create a directory.
if (fRandom.nextInt(100) == 0) if (fRandom.nextInt(100) == 0)

View File

@@ -86,6 +86,15 @@ public interface AVMService
*/ */
public OutputStream createFile(String path, String name); 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. * Create a new directory.
* @param path The simple absolute path to the parent. * @param path The simple absolute path to the parent.

View File

@@ -18,6 +18,8 @@
package org.alfresco.repo.avm; package org.alfresco.repo.avm;
import java.io.File; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
@@ -356,6 +358,58 @@ public class AVMServiceImpl implements AVMService
return doit.out; 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) /* (non-Javadoc)
* @see org.alfresco.repo.avm.AVMService#createFolder(java.lang.String, java.lang.String) * @see org.alfresco.repo.avm.AVMService#createFolder(java.lang.String, java.lang.String)
*/ */

View File

@@ -18,6 +18,7 @@
package org.alfresco.repo.avm; package org.alfresco.repo.avm;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
@@ -47,8 +48,8 @@ public class AVMServiceTest extends AVMServiceTestBase
fService.createDirectory("main:/", "a"); fService.createDirectory("main:/", "a");
fService.createDirectory("main:/a", "b"); fService.createDirectory("main:/a", "b");
fService.createDirectory("main:/a", "c"); fService.createDirectory("main:/a", "c");
fService.createFile("main:/a/b", "foo").close(); fService.createFile("main:/a/b", "foo", new ByteArrayInputStream("I am foo.".getBytes()));
fService.createFile("main:/a/c", "bar").close(); fService.createFile("main:/a/c", "bar", new ByteArrayInputStream("I am bar.".getBytes()));
fService.createSnapshot("main"); fService.createSnapshot("main");
// History is unchanged. // History is unchanged.
checkHistory(history, "main"); checkHistory(history, "main");

View File

@@ -92,6 +92,36 @@ class FileContentImpl implements FileContent, Serializable
SuperRepository.GetInstance().getSession().save(this); 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. * Copy constructor, sort of.
* @param other The content to copy from. * @param other The content to copy from.

View File

@@ -17,6 +17,8 @@
package org.alfresco.repo.avm; package org.alfresco.repo.avm;
import java.io.File;
/** /**
* A plain old file. Contains a Content object. * A plain old file. Contains a Content object.
@@ -50,6 +52,18 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode
repos.getSuperRepository().getSession().save(this); 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. * Copy on write constructor.
* @param other The node we are being copied from. * @param other The node we are being copied from.

View File

@@ -16,6 +16,7 @@
*/ */
package org.alfresco.repo.avm; package org.alfresco.repo.avm;
import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
@@ -73,6 +74,14 @@ interface Repository
* @return An OutputStream. * @return An OutputStream.
*/ */
public OutputStream createFile(String path, String name); 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. * Create a new layered file.

View File

@@ -17,6 +17,7 @@
package org.alfresco.repo.avm; package org.alfresco.repo.avm;
import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
@@ -241,10 +242,30 @@ class RepositoryImpl implements Repository, Serializable
PlainFileNodeImpl file = new PlainFileNodeImpl(this); PlainFileNodeImpl file = new PlainFileNodeImpl(this);
file.setVersionID(getNextVersionID()); file.setVersionID(getNextVersionID());
dir.putChild(name, file); dir.putChild(name, file);
file.updateModTime(); dir.updateModTime();
return file.getContentForWrite().getOutputStream(); 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. * Create a new layered file.
* @param srcPath The target indirection for the layered file. * @param srcPath The target indirection for the layered file.

View File

@@ -17,6 +17,7 @@
package org.alfresco.repo.avm; package org.alfresco.repo.avm;
import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
@@ -117,6 +118,20 @@ class SuperRepository
return rep.createFile(pathParts[1], name); 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. * Create a new directory.
* @param path The path to the containing directory. * @param path The path to the containing directory.