Merged BRANCHES/DEV/THOR1 to HEAD:

32606: THOR-659: Caching Content Store blocked readers


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@32633 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Matt Ward
2011-12-08 10:24:56 +00:00
parent 264b0f323f
commit 2ec53219cb
2 changed files with 117 additions and 8 deletions

View File

@@ -49,6 +49,7 @@ public class ContentCacheImpl implements ContentCache
{ {
private static final Log log = LogFactory.getLog(ContentCacheImpl.class); private static final Log log = LogFactory.getLog(ContentCacheImpl.class);
private static final String CACHE_FILE_EXT = ".bin"; private static final String CACHE_FILE_EXT = ".bin";
private static final String CACHE_FILE_TEMP_EXT = ".tmp";
private File cacheRoot; private File cacheRoot;
private SimpleCache<Key, String> memoryStore; private SimpleCache<Key, String> memoryStore;
@@ -130,12 +131,13 @@ public class ContentCacheImpl implements ContentCache
@Override @Override
public boolean put(String contentUrl, ContentReader source) public boolean put(String contentUrl, ContentReader source)
{ {
File cacheFile = createCacheFile(); File tempFile = createCacheFile();
// Copy the content from the source into a cache file // Copy the content from the source into a cache file
if (source.getSize() > 0L) if (source.getSize() > 0L)
{ {
source.getContent(cacheFile); source.getContent(tempFile);
File cacheFile = renameTempToActive(tempFile);
// Add a record of the cached file to the in-memory cache. // Add a record of the cached file to the in-memory cache.
recordCacheEntries(contentUrl, cacheFile); recordCacheEntries(contentUrl, cacheFile);
return true; return true;
@@ -158,7 +160,7 @@ public class ContentCacheImpl implements ContentCache
*/ */
private File createCacheFile() private File createCacheFile()
{ {
File file = new File(cacheRoot, createNewCacheFilePath()); File file = new File(cacheRoot, createNewTempCacheFilePath());
File parentDir = file.getParentFile(); File parentDir = file.getParentFile();
parentDir.mkdirs(); parentDir.mkdirs();
return file; return file;
@@ -192,8 +194,8 @@ public class ContentCacheImpl implements ContentCache
public ContentWriter getWriter(final String url) public ContentWriter getWriter(final String url)
{ {
// Get a writer to a cache file. // Get a writer to a cache file.
final File cacheFile = createCacheFile(); final File tempFile = createCacheFile();
ContentWriter writer = new FileContentWriter(cacheFile, url, null); final CacheWriter writer = new CacheWriter(tempFile, url);
// Attach a listener to populate the in-memory store when done writing. // Attach a listener to populate the in-memory store when done writing.
writer.addListener(new ContentStreamListener() writer.addListener(new ContentStreamListener()
@@ -201,6 +203,8 @@ public class ContentCacheImpl implements ContentCache
@Override @Override
public void contentStreamClosed() throws ContentIOException public void contentStreamClosed() throws ContentIOException
{ {
final File cacheFile = renameTempToActive(tempFile);
writer.setCacheFile(cacheFile);
recordCacheEntries(url, cacheFile); recordCacheEntries(url, cacheFile);
} }
}); });
@@ -208,6 +212,38 @@ public class ContentCacheImpl implements ContentCache
return writer; return writer;
} }
private File renameTempToActive(File tempFile)
{
String fullPath = tempFile.getPath();
int extIndex = fullPath.lastIndexOf(CACHE_FILE_TEMP_EXT);
if (extIndex > 0)
{
String prefix = fullPath.substring(0, extIndex);
File dest = new File(prefix + CACHE_FILE_EXT);
boolean renamed = tempFile.renameTo(dest);
if (renamed)
{
return dest;
}
else
{
throw new IllegalStateException(
"Temp file couldn't be renamed to active cache file, temp=" +
tempFile.getPath() +
", dest=" +
dest.getPath());
}
}
else
{
throw new IllegalArgumentException("Invalid temp file name: " + tempFile.getPath());
}
}
/** /**
* Creates a relative path for a new cache file. The path is based * Creates a relative path for a new cache file. The path is based
* upon the current date/time: year/month/day/hour/minute/guid.bin * upon the current date/time: year/month/day/hour/minute/guid.bin
@@ -216,6 +252,16 @@ public class ContentCacheImpl implements ContentCache
* @return The relative path for the new cache file. * @return The relative path for the new cache file.
*/ */
public static String createNewCacheFilePath() public static String createNewCacheFilePath()
{
return createNewCacheFilePath(false);
}
private static String createNewTempCacheFilePath()
{
return createNewCacheFilePath(true);
}
private static String createNewCacheFilePath(boolean tempFile)
{ {
Calendar calendar = new GregorianCalendar(); Calendar calendar = new GregorianCalendar();
int year = calendar.get(Calendar.YEAR); int year = calendar.get(Calendar.YEAR);
@@ -230,7 +276,17 @@ public class ContentCacheImpl implements ContentCache
.append(day).append('/') .append(day).append('/')
.append(hour).append('/') .append(hour).append('/')
.append(minute).append('/') .append(minute).append('/')
.append(GUID.generate()).append(CACHE_FILE_EXT); .append(GUID.generate());
if (tempFile)
{
sb.append(CACHE_FILE_TEMP_EXT);
}
else
{
sb.append(CACHE_FILE_EXT);
}
return sb.toString(); return sb.toString();
} }
@@ -386,4 +442,59 @@ public class ContentCacheImpl implements ContentCache
} }
} }
} }
/**
* This FileContentWriter subclass allows for the temp cache file
* to be renamed to a cache file proper, e.g filename.tmp becomes
* filename.bin
*
* @author Matt Ward
*/
public static class CacheWriter extends FileContentWriter
{
private File cacheFile = null;
public CacheWriter(File file, String url)
{
super(file, url, null);
}
public void setCacheFile(File file)
{
cacheFile = file;
}
@Override
public File getFile()
{
if (cacheFile != null)
{
return cacheFile;
}
return super.getFile();
}
@Override
protected ContentReader createReader() throws ContentIOException
{
FileContentReader reader = new FileContentReader(getFile(), getContentUrl());
// TODO: what about reader.setAllowRandomAccess(this.allowRandomAccess); ?
return reader;
}
@Override
public long getSize()
{
File file = getFile();
if (file == null)
return 0L;
else if (!file.exists())
return 0L;
else
return file.length();
}
}
} }

View File

@@ -255,8 +255,6 @@ public class StandardQuotaStrategyTest
writerThread.start(); writerThread.start();
} }
// StandardQuotaStrategyTest.afterClass();
} }