mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Merged BRANCHES/DEV/THOR1 to HEAD:
30970: THOR-217: when the quota is met or exceeded, then next time the cleaner runs it must use some strategy to make some space git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@30974 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -27,6 +27,9 @@ import java.io.File;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
import org.alfresco.repo.content.caching.CacheFileProps;
|
import org.alfresco.repo.content.caching.CacheFileProps;
|
||||||
import org.alfresco.repo.content.caching.CachingContentStore;
|
import org.alfresco.repo.content.caching.CachingContentStore;
|
||||||
@@ -36,6 +39,7 @@ import org.alfresco.service.cmr.repository.ContentReader;
|
|||||||
import org.alfresco.util.ApplicationContextHelper;
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
import org.alfresco.util.GUID;
|
import org.alfresco.util.GUID;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
@@ -96,7 +100,7 @@ public class CachedContentCleanupJobTest
|
|||||||
// a 'reverse lookup' in the cache (i.e. cache.contains(Key.forCacheFile(...))), or there will be no
|
// a 'reverse lookup' in the cache (i.e. cache.contains(Key.forCacheFile(...))), or there will be no
|
||||||
// URL determinable for the file.
|
// URL determinable for the file.
|
||||||
UrlSource urlSource = UrlSource.values()[i % UrlSource.values().length];
|
UrlSource urlSource = UrlSource.values()[i % UrlSource.values().length];
|
||||||
File cacheFile = createCacheFile(urlSource, i, false);
|
File cacheFile = createCacheFile(urlSource, false);
|
||||||
files[i] = cacheFile;
|
files[i] = cacheFile;
|
||||||
totalSize += cacheFile.length();
|
totalSize += cacheFile.length();
|
||||||
}
|
}
|
||||||
@@ -126,7 +130,7 @@ public class CachedContentCleanupJobTest
|
|||||||
File[] oldFiles = new File[numFiles];
|
File[] oldFiles = new File[numFiles];
|
||||||
for (int i = 0; i < numFiles; i++)
|
for (int i = 0; i < numFiles; i++)
|
||||||
{
|
{
|
||||||
oldFiles[i] = createCacheFile(UrlSource.REVERSE_CACHE_LOOKUP, i, false);
|
oldFiles[i] = createCacheFile(UrlSource.REVERSE_CACHE_LOOKUP, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sleep to make sure 'old' files really are older than minFileAgeMillis
|
// Sleep to make sure 'old' files really are older than minFileAgeMillis
|
||||||
@@ -136,7 +140,7 @@ public class CachedContentCleanupJobTest
|
|||||||
long newFilesTotalSize = 0;
|
long newFilesTotalSize = 0;
|
||||||
for (int i = 0; i < numFiles; i++)
|
for (int i = 0; i < numFiles; i++)
|
||||||
{
|
{
|
||||||
newFiles[i] = createCacheFile(UrlSource.REVERSE_CACHE_LOOKUP, i, false);
|
newFiles[i] = createCacheFile(UrlSource.REVERSE_CACHE_LOOKUP, false);
|
||||||
newFilesTotalSize += newFiles[i].length();
|
newFilesTotalSize += newFiles[i].length();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +173,7 @@ public class CachedContentCleanupJobTest
|
|||||||
{
|
{
|
||||||
// Make sure it's in the cache - all the files will be in the cache, so the
|
// Make sure it's in the cache - all the files will be in the cache, so the
|
||||||
// cleaner won't clean any up once it has finished aggressively reclaiming space.
|
// cleaner won't clean any up once it has finished aggressively reclaiming space.
|
||||||
files[i] = createCacheFile(UrlSource.REVERSE_CACHE_LOOKUP, i, true);
|
files[i] = createCacheFile(UrlSource.REVERSE_CACHE_LOOKUP, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// How much space to reclaim - seven files worth (all files are same size)
|
// How much space to reclaim - seven files worth (all files are same size)
|
||||||
@@ -199,32 +203,29 @@ public class CachedContentCleanupJobTest
|
|||||||
assertEquals("Incorrect total size of files deleted", sevenFilesSize, cleaner.getSizeFilesDeleted());
|
assertEquals("Incorrect total size of files deleted", sevenFilesSize, cleaner.getSizeFilesDeleted());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore()
|
|
||||||
@Test
|
@Test
|
||||||
public void standardCleanAfterAggressiveFinished() throws InterruptedException
|
public void standardCleanAfterAggressiveFinished() throws InterruptedException
|
||||||
{
|
{
|
||||||
int numFiles = 30;
|
// Don't use numFiles > 59! as we're using this for the minute element in the cache file path.
|
||||||
int newerFilesIndex = 14;
|
final int numFiles = 30;
|
||||||
File[] files = new File[numFiles];
|
File[] files = new File[numFiles];
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < numFiles; i++)
|
for (int i = 0; i < numFiles; i++)
|
||||||
{
|
{
|
||||||
if (i == newerFilesIndex)
|
Calendar calendar = new GregorianCalendar(2010, 12, 2, 17, i);
|
||||||
{
|
|
||||||
// Files after this sleep will definitely be in 'newer' directories.
|
|
||||||
Thread.sleep(2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i >= 21 && i <= 24)
|
if (i >= 21 && i <= 24)
|
||||||
{
|
{
|
||||||
// 21 to 24 will be deleted after the aggressive deletions (once the cleaner has returned
|
// 21 to 24 will be deleted after the aggressive deletions (once the cleaner has returned
|
||||||
// to normal cleaning), because they are not in the cache.
|
// to normal cleaning), because they are not in the cache.
|
||||||
files[i] = createCacheFile(UrlSource.NOT_PRESENT, i, false);
|
files[i] = createCacheFile(calendar, UrlSource.NOT_PRESENT, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// All other files will be in the cache
|
// All other files will be in the cache
|
||||||
files[i] = createCacheFile(UrlSource.REVERSE_CACHE_LOOKUP, i, true);
|
files[i] = createCacheFile(calendar, UrlSource.REVERSE_CACHE_LOOKUP, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,43 +234,27 @@ public class CachedContentCleanupJobTest
|
|||||||
long sevenFilesSize = 7 * fileSize;
|
long sevenFilesSize = 7 * fileSize;
|
||||||
|
|
||||||
// We'll get it to clean seven files worth aggressively and then it will continue non-aggressively.
|
// We'll get it to clean seven files worth aggressively and then it will continue non-aggressively.
|
||||||
// It will delete the older files aggressively (i.e. the ones prior to the two second sleep) and
|
// It will delete the older files aggressively (i.e. even if they are actively in the cache) and
|
||||||
// then will examine the new files for potential deletion.
|
// then will examine the new files for potential deletion.
|
||||||
// Since some of the newer files are not in the cache, it will delete those.
|
// Since some of the newer files are not in the cache, it will delete those too.
|
||||||
cleaner.executeAggressive("standardCleanAfterAggressiveFinished()", sevenFilesSize);
|
cleaner.executeAggressive("standardCleanAfterAggressiveFinished()", sevenFilesSize);
|
||||||
|
|
||||||
for (int i = 0; i < numFiles; i++)
|
for (int i = 0; i < numFiles; i++)
|
||||||
{
|
{
|
||||||
File f = files[i];
|
if (i < 7)
|
||||||
String newerOrOlder = ((i >= newerFilesIndex) ? "newer" : "older");
|
|
||||||
System.out.println("files[" + i + "] = " + newerOrOlder + " file, exists=" + f.exists());
|
|
||||||
}
|
|
||||||
|
|
||||||
int numOlderFilesDeleted = 0;
|
|
||||||
for (int i = 0; i < newerFilesIndex; i++)
|
|
||||||
{
|
|
||||||
if (!files[i].exists())
|
|
||||||
{
|
{
|
||||||
numOlderFilesDeleted++;
|
assertFalse("First 7 files should have been aggressively cleaned", files[i].exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= 21 && i <= 24)
|
||||||
|
{
|
||||||
|
assertFalse("Files with indexes 21-24 should have been deleted", files[i].exists());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertEquals("Wrong number of older files deleted", 7, numOlderFilesDeleted);
|
|
||||||
|
|
||||||
int numNewerFilesDeleted = 0;
|
|
||||||
for (int i = newerFilesIndex; i < numFiles; i++)
|
|
||||||
{
|
|
||||||
if (!files[i].exists())
|
|
||||||
{
|
|
||||||
numNewerFilesDeleted++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertEquals("Wrong number of newer files deleted", 4, numNewerFilesDeleted);
|
|
||||||
|
|
||||||
// The cleaner should have recorded the correct number of deletions
|
|
||||||
assertEquals("Incorrect number of deleted files", 11, cleaner.getNumFilesDeleted());
|
assertEquals("Incorrect number of deleted files", 11, cleaner.getNumFilesDeleted());
|
||||||
assertEquals("Incorrect total size of files deleted", (11*fileSize), cleaner.getSizeFilesDeleted());
|
assertEquals("Incorrect total size of files deleted", (11*fileSize), cleaner.getSizeFilesDeleted());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void emptyParentDirectoriesAreDeleted() throws FileNotFoundException
|
public void emptyParentDirectoriesAreDeleted() throws FileNotFoundException
|
||||||
{
|
{
|
||||||
@@ -292,14 +277,14 @@ public class CachedContentCleanupJobTest
|
|||||||
// A non-advisable setting but useful for testing, maxDeleteWatchCount of zero
|
// A non-advisable setting but useful for testing, maxDeleteWatchCount of zero
|
||||||
// which should result in immediate deletion upon discovery of content no longer in the cache.
|
// which should result in immediate deletion upon discovery of content no longer in the cache.
|
||||||
cleaner.setMaxDeleteWatchCount(0);
|
cleaner.setMaxDeleteWatchCount(0);
|
||||||
File file = createCacheFile(UrlSource.NOT_PRESENT, 0, false);
|
File file = createCacheFile(UrlSource.NOT_PRESENT, false);
|
||||||
|
|
||||||
cleaner.handle(file);
|
cleaner.handle(file);
|
||||||
checkFilesDeleted(file);
|
checkFilesDeleted(file);
|
||||||
|
|
||||||
// Anticipated to be the most common setting: maxDeleteWatchCount of 1.
|
// Anticipated to be the most common setting: maxDeleteWatchCount of 1.
|
||||||
cleaner.setMaxDeleteWatchCount(1);
|
cleaner.setMaxDeleteWatchCount(1);
|
||||||
file = createCacheFile(UrlSource.NOT_PRESENT, 0, false);
|
file = createCacheFile(UrlSource.NOT_PRESENT, false);
|
||||||
|
|
||||||
cleaner.handle(file);
|
cleaner.handle(file);
|
||||||
checkWatchCountForCacheFile(file, 1);
|
checkWatchCountForCacheFile(file, 1);
|
||||||
@@ -309,7 +294,7 @@ public class CachedContentCleanupJobTest
|
|||||||
|
|
||||||
// Check that some other arbitrary figure for maxDeleteWatchCount works correctly.
|
// Check that some other arbitrary figure for maxDeleteWatchCount works correctly.
|
||||||
cleaner.setMaxDeleteWatchCount(3);
|
cleaner.setMaxDeleteWatchCount(3);
|
||||||
file = createCacheFile(UrlSource.NOT_PRESENT, 0, false);
|
file = createCacheFile(UrlSource.NOT_PRESENT, false);
|
||||||
|
|
||||||
cleaner.handle(file);
|
cleaner.handle(file);
|
||||||
checkWatchCountForCacheFile(file, 1);
|
checkWatchCountForCacheFile(file, 1);
|
||||||
@@ -366,10 +351,16 @@ public class CachedContentCleanupJobTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private File createCacheFile(UrlSource urlSource, boolean putInCache)
|
||||||
private File createCacheFile(UrlSource urlSource, int fileNum, boolean putInCache)
|
|
||||||
{
|
{
|
||||||
File file = new File(cacheRoot, ContentCacheImpl.createNewCacheFilePath());
|
Calendar calendar = new GregorianCalendar();
|
||||||
|
return createCacheFile(calendar, urlSource, putInCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
private File createCacheFile(Calendar calendar, /*int year, int month, int day, int hour, int minute,*/
|
||||||
|
UrlSource urlSource, boolean putInCache)
|
||||||
|
{
|
||||||
|
File file = new File(cacheRoot, createNewCacheFilePath(calendar));
|
||||||
file.getParentFile().mkdirs();
|
file.getParentFile().mkdirs();
|
||||||
writeSampleContent(file);
|
writeSampleContent(file);
|
||||||
String contentUrl = makeContentUrl();
|
String contentUrl = makeContentUrl();
|
||||||
@@ -399,6 +390,32 @@ public class CachedContentCleanupJobTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mimick functionality of ContentCacheImpl.createNewCacheFilePath()
|
||||||
|
* but allowing a specific date (rather than 'now') to be used.
|
||||||
|
*
|
||||||
|
* @param calendar
|
||||||
|
* @return Path to use for cache file.
|
||||||
|
*/
|
||||||
|
private String createNewCacheFilePath(Calendar calendar)
|
||||||
|
{
|
||||||
|
int year = calendar.get(Calendar.YEAR);
|
||||||
|
int month = calendar.get(Calendar.MONTH) + 1; // 0-based
|
||||||
|
int day = calendar.get(Calendar.DAY_OF_MONTH);
|
||||||
|
int hour = calendar.get(Calendar.HOUR_OF_DAY);
|
||||||
|
int minute = calendar.get(Calendar.MINUTE);
|
||||||
|
// create the URL
|
||||||
|
StringBuilder sb = new StringBuilder(20);
|
||||||
|
sb.append(year).append('/')
|
||||||
|
.append(month).append('/')
|
||||||
|
.append(day).append('/')
|
||||||
|
.append(hour).append('/')
|
||||||
|
.append(minute).append('/')
|
||||||
|
.append(GUID.generate()).append(".bin");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private String makeContentUrl()
|
private String makeContentUrl()
|
||||||
{
|
{
|
||||||
return "protocol://some/made/up/url/" + GUID.generate();
|
return "protocol://some/made/up/url/" + GUID.generate();
|
||||||
|
Reference in New Issue
Block a user