mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-31 21:41:33 +00:00
allow adjustable cache cleanup
This commit is contained in:
parent
46172fba28
commit
3fdac7eb10
7 changed files with 72 additions and 32 deletions
|
@ -236,6 +236,26 @@
|
||||||
</string-array>
|
</string-array>
|
||||||
<string name="default_network_select_value">NOMONONME</string>
|
<string name="default_network_select_value">NOMONONME</string>
|
||||||
|
|
||||||
|
<string name="menu_cache_age_select">Maximum Cache Age</string>
|
||||||
|
<string name="menu_cache_age_select_sum">Clean up cached story content after…</string>
|
||||||
|
<string name="menu_cache_age_select_opt_2d">2 days</string>
|
||||||
|
<string name="menu_cache_age_select_opt_7d">7 days</string>
|
||||||
|
<string name="menu_cache_age_select_opt_14d">14 days</string>
|
||||||
|
<string name="menu_cache_age_select_opt_30d">30 days</string>
|
||||||
|
<string-array name="cache_age_select_entries">
|
||||||
|
<item>@string/menu_cache_age_select_opt_2d</item>
|
||||||
|
<item>@string/menu_cache_age_select_opt_7d</item>
|
||||||
|
<item>@string/menu_cache_age_select_opt_14d</item>
|
||||||
|
<item>@string/menu_cache_age_select_opt_30d</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="cache_age_select_values">
|
||||||
|
<item>CACHE_AGE_2D</item>
|
||||||
|
<item>CACHE_AGE_7D</item>
|
||||||
|
<item>CACHE_AGE_14D</item>
|
||||||
|
<item>CACHE_AGE_30D</item>
|
||||||
|
</string-array>
|
||||||
|
<string name="default_cache_age_select_value">CACHE_AGE_30D</string>
|
||||||
|
|
||||||
<string name="settings_cat_feed_list">Feed List</string>
|
<string name="settings_cat_feed_list">Feed List</string>
|
||||||
|
|
||||||
<string name="settings_enable_row_global_shared">Show Global Shared Stories</string>
|
<string name="settings_enable_row_global_shared">Show Global Shared Stories</string>
|
||||||
|
|
|
@ -26,6 +26,14 @@
|
||||||
android:key="keep_old_stories"
|
android:key="keep_old_stories"
|
||||||
android:title="@string/settings_keep_old_stories"
|
android:title="@string/settings_keep_old_stories"
|
||||||
android:summary="@string/settings_keep_old_stories_sum" />
|
android:summary="@string/settings_keep_old_stories_sum" />
|
||||||
|
<ListPreference
|
||||||
|
android:key="cache_age_select"
|
||||||
|
android:title="@string/menu_cache_age_select"
|
||||||
|
android:dialogTitle="@string/menu_cache_age_select"
|
||||||
|
android:summary="@string/menu_cache_age_select_sum"
|
||||||
|
android:entries="@array/cache_age_select_entries"
|
||||||
|
android:entryValues="@array/cache_age_select_values"
|
||||||
|
android:defaultValue="@string/default_cache_age_select_value" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.newsblur.service;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.newsblur.util.FileCache;
|
import com.newsblur.util.FileCache;
|
||||||
|
import com.newsblur.util.PrefConstants;
|
||||||
import com.newsblur.util.PrefsUtils;
|
import com.newsblur.util.PrefsUtils;
|
||||||
|
|
||||||
public class CleanupService extends SubService {
|
public class CleanupService extends SubService {
|
||||||
|
@ -15,8 +16,6 @@ public class CleanupService extends SubService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void exec() {
|
protected void exec() {
|
||||||
if (!PrefsUtils.isTimeToCleanup(parent)) return;
|
|
||||||
|
|
||||||
gotWork();
|
gotWork();
|
||||||
|
|
||||||
com.newsblur.util.Log.d(this.getClass().getName(), "cleaning up old stories");
|
com.newsblur.util.Log.d(this.getClass().getName(), "cleaning up old stories");
|
||||||
|
@ -33,17 +32,15 @@ public class CleanupService extends SubService {
|
||||||
|
|
||||||
com.newsblur.util.Log.d(this.getClass().getName(), "cleaning up story image cache");
|
com.newsblur.util.Log.d(this.getClass().getName(), "cleaning up story image cache");
|
||||||
FileCache imageCache = FileCache.asStoryImageCache(parent);
|
FileCache imageCache = FileCache.asStoryImageCache(parent);
|
||||||
imageCache.cleanupUnusedOrOld(parent.dbHelper.getAllStoryImages());
|
imageCache.cleanupUnusedAndOld(parent.dbHelper.getAllStoryImages(), PrefsUtils.getMaxCachedAgeMillis(parent));
|
||||||
|
|
||||||
com.newsblur.util.Log.d(this.getClass().getName(), "cleaning up icon cache");
|
com.newsblur.util.Log.d(this.getClass().getName(), "cleaning up icon cache");
|
||||||
FileCache iconCache = FileCache.asIconCache(parent);
|
FileCache iconCache = FileCache.asIconCache(parent);
|
||||||
iconCache.cleanupOld();
|
iconCache.cleanupOld(PrefConstants.CACHE_AGE_VALUE_30D);
|
||||||
|
|
||||||
com.newsblur.util.Log.d(this.getClass().getName(), "cleaning up thumbnail cache");
|
com.newsblur.util.Log.d(this.getClass().getName(), "cleaning up thumbnail cache");
|
||||||
FileCache thumbCache = FileCache.asThumbnailCache(parent);
|
FileCache thumbCache = FileCache.asThumbnailCache(parent);
|
||||||
thumbCache.cleanupUnusedOrOld(parent.dbHelper.getAllStoryThumbnails());
|
thumbCache.cleanupUnusedAndOld(parent.dbHelper.getAllStoryThumbnails(), PrefsUtils.getMaxCachedAgeMillis(parent));
|
||||||
|
|
||||||
PrefsUtils.updateLastCleanupTime(parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean running() {
|
public static boolean running() {
|
||||||
|
|
|
@ -34,9 +34,6 @@ public class AppConstants {
|
||||||
// how often to rebuild the DB
|
// how often to rebuild the DB
|
||||||
public static final long VACUUM_TIME_MILLIS = 12L * 60L * 60L * 1000L;
|
public static final long VACUUM_TIME_MILLIS = 12L * 60L * 60L * 1000L;
|
||||||
|
|
||||||
// how often to clean up the DB
|
|
||||||
public static final long CLEANUP_TIME_MILLIS = 3L * 60L * 60L * 1000L;
|
|
||||||
|
|
||||||
// how often to trigger the BG service. slightly longer than how often we will find new stories,
|
// how often to trigger the BG service. slightly longer than how often we will find new stories,
|
||||||
// to account for the fact that it is approximate, and missing a cycle is bad.
|
// to account for the fact that it is approximate, and missing a cycle is bad.
|
||||||
public static final long BG_SERVICE_CYCLE_MILLIS = AUTO_SYNC_TIME_MILLIS + 30L * 1000L;
|
public static final long BG_SERVICE_CYCLE_MILLIS = AUTO_SYNC_TIME_MILLIS + 30L * 1000L;
|
||||||
|
|
|
@ -15,13 +15,11 @@ public class FileCache {
|
||||||
private static final long MIN_FREE_SPACE_BYTES = 250L * 1024L * 1024L;
|
private static final long MIN_FREE_SPACE_BYTES = 250L * 1024L * 1024L;
|
||||||
private static final Pattern POSTFIX_PATTERN = Pattern.compile("(\\.[a-zA-Z0-9]+)[^\\.]*$");
|
private static final Pattern POSTFIX_PATTERN = Pattern.compile("(\\.[a-zA-Z0-9]+)[^\\.]*$");
|
||||||
|
|
||||||
private final long maxFileAgeMillis;
|
|
||||||
private final int minValidCacheBytes;
|
private final int minValidCacheBytes;
|
||||||
|
|
||||||
private final File cacheDir;
|
private final File cacheDir;
|
||||||
|
|
||||||
private FileCache(Context context, String subdir, long maxFileAgeMillis, int minValidCacheBytes) {
|
private FileCache(Context context, String subdir, int minValidCacheBytes) {
|
||||||
this.maxFileAgeMillis = maxFileAgeMillis;
|
|
||||||
this.minValidCacheBytes = minValidCacheBytes;
|
this.minValidCacheBytes = minValidCacheBytes;
|
||||||
cacheDir = new File(context.getCacheDir(), subdir);
|
cacheDir = new File(context.getCacheDir(), subdir);
|
||||||
if (!cacheDir.exists()) {
|
if (!cacheDir.exists()) {
|
||||||
|
@ -30,17 +28,17 @@ public class FileCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileCache asStoryImageCache(Context context) {
|
public static FileCache asStoryImageCache(Context context) {
|
||||||
FileCache fc = new FileCache(context, "olimages", 30L * 24L * 60L * 60L * 1000L, 512);
|
FileCache fc = new FileCache(context, "olimages", 512);
|
||||||
return fc;
|
return fc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileCache asIconCache(Context context) {
|
public static FileCache asIconCache(Context context) {
|
||||||
FileCache fc = new FileCache(context, "icons", 45L * 24L * 60L * 60L * 1000L, 128);
|
FileCache fc = new FileCache(context, "icons", 128);
|
||||||
return fc;
|
return fc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileCache asThumbnailCache(Context context) {
|
public static FileCache asThumbnailCache(Context context) {
|
||||||
FileCache fc = new FileCache(context, "thumbs", 15L * 24L * 60L * 60L * 1000L, 256);
|
FileCache fc = new FileCache(context, "thumbs", 256);
|
||||||
return fc;
|
return fc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,22 +107,29 @@ public class FileCache {
|
||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanupOld() {
|
public void cleanupOld(long maxFileAgeMillis) {
|
||||||
try {
|
try {
|
||||||
|
int cleaned = 0;
|
||||||
File[] files = cacheDir.listFiles();
|
File[] files = cacheDir.listFiles();
|
||||||
if (files == null) return;
|
if (files == null) return;
|
||||||
|
com.newsblur.util.Log.i(this, String.format( "have %d files", files.length));
|
||||||
for (File f : files) {
|
for (File f : files) {
|
||||||
long timestamp = f.lastModified();
|
long timestamp = f.lastModified();
|
||||||
if (System.currentTimeMillis() > (timestamp + maxFileAgeMillis)) {
|
if (System.currentTimeMillis() > (timestamp + maxFileAgeMillis)) {
|
||||||
f.delete();
|
f.delete();
|
||||||
|
cleaned++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
com.newsblur.util.Log.i(this, String.format( "cleaned up %d files", cleaned));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
android.util.Log.e(FileCache.class.getName(), "exception cleaning up cache", e);
|
com.newsblur.util.Log.e(this, "exception cleaning up cache", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanupUnusedOrOld(Set<String> currentUrls) {
|
/**
|
||||||
|
* Clean up files in this cache that are both unused and past the specified age.
|
||||||
|
*/
|
||||||
|
public void cleanupUnusedAndOld(Set<String> currentUrls, long maxFileAgeMillis) {
|
||||||
// if there appear to be zero images in the system, a DB rebuild probably just
|
// if there appear to be zero images in the system, a DB rebuild probably just
|
||||||
// occured, so don't trust that data for cleanup
|
// occured, so don't trust that data for cleanup
|
||||||
if (currentUrls.size() == 0) return;
|
if (currentUrls.size() == 0) return;
|
||||||
|
@ -132,17 +137,21 @@ public class FileCache {
|
||||||
Set<String> currentFiles = new HashSet<String>(currentUrls.size());
|
Set<String> currentFiles = new HashSet<String>(currentUrls.size());
|
||||||
for (String url : currentUrls) currentFiles.add(getFileName(url));
|
for (String url : currentUrls) currentFiles.add(getFileName(url));
|
||||||
try {
|
try {
|
||||||
|
int cleaned = 0;
|
||||||
File[] files = cacheDir.listFiles();
|
File[] files = cacheDir.listFiles();
|
||||||
if (files == null) return;
|
if (files == null) return;
|
||||||
|
com.newsblur.util.Log.i(this, String.format( "have %d files", files.length));
|
||||||
for (File f : files) {
|
for (File f : files) {
|
||||||
long timestamp = f.lastModified();
|
long timestamp = f.lastModified();
|
||||||
if ((System.currentTimeMillis() > (timestamp + maxFileAgeMillis)) ||
|
if ((System.currentTimeMillis() > (timestamp + maxFileAgeMillis)) &&
|
||||||
(!currentFiles.contains(f.getName()))) {
|
(!currentFiles.contains(f.getName()))) {
|
||||||
f.delete();
|
f.delete();
|
||||||
|
cleaned++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
com.newsblur.util.Log.i(this, String.format( "cleaned up %d files", cleaned));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
android.util.Log.e(FileCache.class.getName(), "exception cleaning up cache", e);
|
com.newsblur.util.Log.e(this, "exception cleaning up cache", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,11 +62,21 @@ public class PrefConstants {
|
||||||
public static final String ENABLE_IMAGE_PREFETCH = "enable_image_prefetch";
|
public static final String ENABLE_IMAGE_PREFETCH = "enable_image_prefetch";
|
||||||
public static final String NETWORK_SELECT = "offline_network_select";
|
public static final String NETWORK_SELECT = "offline_network_select";
|
||||||
public static final String KEEP_OLD_STORIES = "keep_old_stories";
|
public static final String KEEP_OLD_STORIES = "keep_old_stories";
|
||||||
|
public static final String CACHE_AGE_SELECT = "cache_age_select";
|
||||||
|
|
||||||
public static final String NETWORK_SELECT_ANY = "ANY";
|
public static final String NETWORK_SELECT_ANY = "ANY";
|
||||||
public static final String NETWORK_SELECT_NOMO = "NOMO";
|
public static final String NETWORK_SELECT_NOMO = "NOMO";
|
||||||
public static final String NETWORK_SELECT_NOMONONME = "NOMONONME";
|
public static final String NETWORK_SELECT_NOMONONME = "NOMONONME";
|
||||||
|
|
||||||
|
public static final String CACHE_AGE_SELECT_2D = "CACHE_AGE_2D";
|
||||||
|
public static final String CACHE_AGE_SELECT_7D = "CACHE_AGE_7D";
|
||||||
|
public static final String CACHE_AGE_SELECT_14D = "CACHE_AGE_14D";
|
||||||
|
public static final String CACHE_AGE_SELECT_30D = "CACHE_AGE_30D";
|
||||||
|
public static final long CACHE_AGE_VALUE_2D = 1000L * 60L * 60L * 24L * 2L;
|
||||||
|
public static final long CACHE_AGE_VALUE_7D = 1000L * 60L * 60L * 24L * 7L;
|
||||||
|
public static final long CACHE_AGE_VALUE_14D = 1000L * 60L * 60L * 24L * 14L;
|
||||||
|
public static final long CACHE_AGE_VALUE_30D = 1000L * 60L * 60L * 24L * 30L;
|
||||||
|
|
||||||
public static final String ENABLE_ROW_GLOBAL_SHARED = "enable_row_global_shared";
|
public static final String ENABLE_ROW_GLOBAL_SHARED = "enable_row_global_shared";
|
||||||
public static final String ENABLE_ROW_INFREQUENT_STORIES = "enable_row_infrequent_stories";
|
public static final String ENABLE_ROW_INFREQUENT_STORIES = "enable_row_infrequent_stories";
|
||||||
|
|
||||||
|
|
|
@ -318,17 +318,6 @@ public class PrefsUtils {
|
||||||
prefs.edit().putLong(PrefConstants.LAST_VACUUM_TIME, (new Date()).getTime()).commit();
|
prefs.edit().putLong(PrefConstants.LAST_VACUUM_TIME, (new Date()).getTime()).commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isTimeToCleanup(Context context) {
|
|
||||||
SharedPreferences prefs = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
|
|
||||||
long lastTime = prefs.getLong(PrefConstants.LAST_CLEANUP_TIME, 1L);
|
|
||||||
return ( (lastTime + AppConstants.CLEANUP_TIME_MILLIS) < (new Date()).getTime() );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void updateLastCleanupTime(Context context) {
|
|
||||||
SharedPreferences prefs = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
|
|
||||||
prefs.edit().putLong(PrefConstants.LAST_CLEANUP_TIME, (new Date()).getTime()).commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static StoryOrder getStoryOrderForFeed(Context context, String feedId) {
|
public static StoryOrder getStoryOrderForFeed(Context context, String feedId) {
|
||||||
SharedPreferences prefs = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
|
SharedPreferences prefs = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
|
||||||
return StoryOrder.valueOf(prefs.getString(PrefConstants.FEED_STORY_ORDER_PREFIX + feedId, getDefaultStoryOrder(prefs).toString()));
|
return StoryOrder.valueOf(prefs.getString(PrefConstants.FEED_STORY_ORDER_PREFIX + feedId, getDefaultStoryOrder(prefs).toString()));
|
||||||
|
@ -660,6 +649,16 @@ public class PrefsUtils {
|
||||||
return prefs.getBoolean(PrefConstants.KEEP_OLD_STORIES, false);
|
return prefs.getBoolean(PrefConstants.KEEP_OLD_STORIES, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long getMaxCachedAgeMillis(Context context) {
|
||||||
|
SharedPreferences prefs = context.getSharedPreferences(PrefConstants.PREFERENCES, 0);
|
||||||
|
String val = prefs.getString(PrefConstants.CACHE_AGE_SELECT, PrefConstants.CACHE_AGE_SELECT_30D);
|
||||||
|
if (val.equals(PrefConstants.CACHE_AGE_SELECT_2D)) return PrefConstants.CACHE_AGE_VALUE_2D;
|
||||||
|
if (val.equals(PrefConstants.CACHE_AGE_SELECT_7D)) return PrefConstants.CACHE_AGE_VALUE_7D;
|
||||||
|
if (val.equals(PrefConstants.CACHE_AGE_SELECT_14D)) return PrefConstants.CACHE_AGE_VALUE_14D;
|
||||||
|
if (val.equals(PrefConstants.CACHE_AGE_SELECT_30D)) return PrefConstants.CACHE_AGE_VALUE_30D;
|
||||||
|
return PrefConstants.CACHE_AGE_VALUE_30D;
|
||||||
|
}
|
||||||
|
|
||||||
public static void applyThemePreference(Activity activity) {
|
public static void applyThemePreference(Activity activity) {
|
||||||
ThemeValue value = getSelectedTheme(activity);
|
ThemeValue value = getSelectedTheme(activity);
|
||||||
if (value == ThemeValue.LIGHT) {
|
if (value == ThemeValue.LIGHT) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue