Limit DropBox storage to 1000 files (by default).

Also does trimming asynchronously (not directly in the broadcast receiver).

Bug: 2541253
Change-Id: I7daf8bc618e2dce68a98571f5f7fbce4df1d6a76
This commit is contained in:
Dan Egnor
2010-03-24 17:48:20 -07:00
parent 3e8b72ac6e
commit 3a8b0c18a4
3 changed files with 78 additions and 11 deletions

View File

@@ -2902,6 +2902,12 @@ public final class Settings {
*/
public static final String DROPBOX_AGE_SECONDS =
"dropbox_age_seconds";
/**
* Maximum number of entry files which {@link android.os.IDropBox} will keep around.
* @hide
*/
public static final String DROPBOX_MAX_FILES =
"dropbox_max_files";
/**
* Maximum amount of disk space used by {@link android.os.IDropBox} no matter what.
* @hide

View File

@@ -61,10 +61,11 @@ import java.util.zip.GZIPOutputStream;
*/
public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
private static final String TAG = "DropBoxManagerService";
private static final int DEFAULT_RESERVE_PERCENT = 10;
private static final int DEFAULT_QUOTA_PERCENT = 10;
private static final int DEFAULT_QUOTA_KB = 5 * 1024;
private static final int DEFAULT_AGE_SECONDS = 3 * 86400;
private static final int DEFAULT_MAX_FILES = 1000;
private static final int DEFAULT_QUOTA_KB = 5 * 1024;
private static final int DEFAULT_QUOTA_PERCENT = 10;
private static final int DEFAULT_RESERVE_PERCENT = 10;
private static final int QUOTA_RESCAN_MILLIS = 5000;
private static final boolean PROFILE_DUMP = false;
@@ -99,12 +100,20 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
@Override
public void onReceive(Context context, Intent intent) {
mCachedQuotaUptimeMillis = 0; // Force a re-check of quota size
try {
init();
trimToFit();
} catch (IOException e) {
Slog.e(TAG, "Can't init", e);
}
// Run the initialization in the background (not this main thread).
// The init() and trimToFit() methods are synchronized, so they still
// block other users -- but at least the onReceive() call can finish.
new Thread() {
public void run() {
try {
init();
trimToFit();
} catch (IOException e) {
Slog.e(TAG, "Can't init", e);
}
}
}.start();
}
};
@@ -631,10 +640,12 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
int ageSeconds = Settings.Secure.getInt(mContentResolver,
Settings.Secure.DROPBOX_AGE_SECONDS, DEFAULT_AGE_SECONDS);
int maxFiles = Settings.Secure.getInt(mContentResolver,
Settings.Secure.DROPBOX_MAX_FILES, DEFAULT_MAX_FILES);
long cutoffMillis = System.currentTimeMillis() - ageSeconds * 1000;
while (!mAllFiles.contents.isEmpty()) {
EntryFile entry = mAllFiles.contents.first();
if (entry.timestampMillis > cutoffMillis) break;
if (entry.timestampMillis > cutoffMillis && mAllFiles.contents.size() < maxFiles) break;
FileList tag = mFilesByTag.get(entry.tag);
if (tag != null && tag.contents.remove(entry)) tag.blocks -= entry.blocks;
@@ -673,7 +684,7 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
// A single circular buffer (a la logcat) would be simpler, but this
// way we can handle fat/bursty data (like 1MB+ bugreports, 300KB+
// kernel crash dumps, and 100KB+ ANR reports) without swamping small,
// well-behaved data // streams (event statistics, profile data, etc).
// well-behaved data streams (event statistics, profile data, etc).
//
// Deleted files are replaced with zero-length tombstones to mark what
// was lost. Tombstones are expunged by age (see above).

View File

@@ -39,6 +39,7 @@ public class DropBoxTest extends AndroidTestCase {
public void tearDown() throws Exception {
ContentResolver cr = getContext().getContentResolver();
Settings.Secure.putString(cr, Settings.Secure.DROPBOX_AGE_SECONDS, "");
Settings.Secure.putString(cr, Settings.Secure.DROPBOX_MAX_FILES, "");
Settings.Secure.putString(cr, Settings.Secure.DROPBOX_QUOTA_KB, "");
Settings.Secure.putString(cr, Settings.Secure.DROPBOX_TAG_PREFIX + "DropBoxTest", "");
}
@@ -457,6 +458,55 @@ public class DropBoxTest extends AndroidTestCase {
e0.close();
}
public void testFileCountLimits() throws Exception {
File dir = getEmptyDir("testFileCountLimits");
DropBoxManagerService service = new DropBoxManagerService(getContext(), dir);
DropBoxManager dropbox = new DropBoxManager(service);
dropbox.addText("DropBoxTest", "TEST0");
dropbox.addText("DropBoxTest", "TEST1");
dropbox.addText("DropBoxTest", "TEST2");
dropbox.addText("DropBoxTest", "TEST3");
dropbox.addText("DropBoxTest", "TEST4");
dropbox.addText("DropBoxTest", "TEST5");
// Verify 6 files added
DropBoxManager.Entry e0 = dropbox.getNextEntry(null, 0);
DropBoxManager.Entry e1 = dropbox.getNextEntry(null, e0.getTimeMillis());
DropBoxManager.Entry e2 = dropbox.getNextEntry(null, e1.getTimeMillis());
DropBoxManager.Entry e3 = dropbox.getNextEntry(null, e2.getTimeMillis());
DropBoxManager.Entry e4 = dropbox.getNextEntry(null, e3.getTimeMillis());
DropBoxManager.Entry e5 = dropbox.getNextEntry(null, e4.getTimeMillis());
assertTrue(null == dropbox.getNextEntry(null, e5.getTimeMillis()));
assertEquals("TEST0", e0.getText(80));
assertEquals("TEST5", e5.getText(80));
e0.close();
e1.close();
e2.close();
e3.close();
e4.close();
e5.close();
// Limit to 3 files and add one more entry
ContentResolver cr = getContext().getContentResolver();
Settings.Secure.putString(cr, Settings.Secure.DROPBOX_MAX_FILES, "3");
dropbox.addText("DropBoxTest", "TEST6");
// Verify only 3 files left
DropBoxManager.Entry f0 = dropbox.getNextEntry(null, 0);
DropBoxManager.Entry f1 = dropbox.getNextEntry(null, f0.getTimeMillis());
DropBoxManager.Entry f2 = dropbox.getNextEntry(null, f1.getTimeMillis());
assertTrue(null == dropbox.getNextEntry(null, f2.getTimeMillis()));
assertEquals("TEST4", f0.getText(80));
assertEquals("TEST5", f1.getText(80));
assertEquals("TEST6", f2.getText(80));
f0.close();
f1.close();
f2.close();
}
public void testCreateDropBoxManagerWithInvalidDirectory() throws Exception {
// If created with an invalid directory, the DropBoxManager should suffer quietly
// and fail all operations (this is how it survives a full disk).