Merge "Purge StoreWriteQueue items to avoid system health issues" into oc-dev

This commit is contained in:
Jorim Jaggi
2017-05-19 12:26:43 +00:00
committed by Android (Google) Code Review
2 changed files with 72 additions and 4 deletions

View File

@@ -39,6 +39,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
/**
* Persists {@link TaskSnapshot}s to disk.
@@ -55,10 +56,13 @@ class TaskSnapshotPersister {
private static final int QUALITY = 95;
private static final String PROTO_EXTENSION = ".proto";
private static final String BITMAP_EXTENSION = ".jpg";
private static final int MAX_STORE_QUEUE_DEPTH = 2;
@GuardedBy("mLock")
private final ArrayDeque<WriteQueueItem> mWriteQueue = new ArrayDeque<>();
@GuardedBy("mLock")
private final ArrayDeque<StoreWriteQueueItem> mStoreQueueItems = new ArrayDeque<>();
@GuardedBy("mLock")
private boolean mQueueIdling;
@GuardedBy("mLock")
private boolean mPaused;
@@ -153,11 +157,22 @@ class TaskSnapshotPersister {
@GuardedBy("mLock")
private void sendToQueueLocked(WriteQueueItem item) {
mWriteQueue.offer(item);
item.onQueuedLocked();
ensureStoreQueueDepthLocked();
if (!mPaused) {
mLock.notifyAll();
}
}
@GuardedBy("mLock")
private void ensureStoreQueueDepthLocked() {
while (mStoreQueueItems.size() > MAX_STORE_QUEUE_DEPTH) {
final StoreWriteQueueItem item = mStoreQueueItems.poll();
mWriteQueue.remove(item);
Slog.i(TAG, "Queue is too deep! Purged item with taskid=" + item.mTaskId);
}
}
private File getDirectory(int userId) {
return new File(mDirectoryResolver.getSystemDirectoryForUser(userId), SNAPSHOTS_DIRNAME);
}
@@ -202,6 +217,9 @@ class TaskSnapshotPersister {
next = null;
} else {
next = mWriteQueue.poll();
if (next != null) {
next.onDequeuedLocked();
}
}
}
if (next != null) {
@@ -226,6 +244,18 @@ class TaskSnapshotPersister {
private abstract class WriteQueueItem {
abstract void write();
/**
* Called when this queue item has been put into the queue.
*/
void onQueuedLocked() {
}
/**
* Called when this queue item has been taken out of the queue.
*/
void onDequeuedLocked() {
}
}
private class StoreWriteQueueItem extends WriteQueueItem {
@@ -239,6 +269,16 @@ class TaskSnapshotPersister {
mSnapshot = snapshot;
}
@Override
void onQueuedLocked() {
mStoreQueueItems.offer(this);
}
@Override
void onDequeuedLocked() {
mStoreQueueItems.remove(this);
}
@Override
void write() {
if (!createDirectory(mUserId)) {

View File

@@ -90,14 +90,42 @@ public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBa
long ms = SystemClock.elapsedRealtime();
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
mPersister.persistSnapshot(3, mTestUserId, createSnapshot());
mPersister.persistSnapshot(4, mTestUserId, createSnapshot());
mPersister.persistSnapshot(5, mTestUserId, createSnapshot());
mPersister.persistSnapshot(6, mTestUserId, createSnapshot());
mPersister.removeObsoleteFiles(new ArraySet<>(), new int[] { mTestUserId });
mPersister.removeObsoleteFiles(new ArraySet<>(), new int[] { mTestUserId });
mPersister.removeObsoleteFiles(new ArraySet<>(), new int[] { mTestUserId });
mPersister.removeObsoleteFiles(new ArraySet<>(), new int[] { mTestUserId });
mPersister.waitForQueueEmpty();
assertTrue(SystemClock.elapsedRealtime() - ms > 500);
}
/**
* Tests that too many store write queue items are being purged.
*/
@Test
public void testPurging() {
mPersister.persistSnapshot(100, mTestUserId, createSnapshot());
mPersister.waitForQueueEmpty();
mPersister.setPaused(true);
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
mPersister.removeObsoleteFiles(new ArraySet<>(), new int[] { mTestUserId });
mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
mPersister.persistSnapshot(3, mTestUserId, createSnapshot());
mPersister.persistSnapshot(4, mTestUserId, createSnapshot());
mPersister.setPaused(false);
mPersister.waitForQueueEmpty();
// Make sure 1,2 were purged but removeObsoleteFiles wasn't.
final File[] existsFiles = new File[] {
new File(sFilesDir.getPath() + "/snapshots/3.proto"),
new File(sFilesDir.getPath() + "/snapshots/4.proto")};
final File[] nonExistsFiles = new File[] {
new File(sFilesDir.getPath() + "/snapshots/100.proto"),
new File(sFilesDir.getPath() + "/snapshots/1.proto"),
new File(sFilesDir.getPath() + "/snapshots/1.proto")};
assertTrueForFiles(existsFiles, File::exists, " must exist");
assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist");
}
@Test
public void testGetTaskId() {
RemoveObsoleteFilesQueueItem removeObsoleteFilesQueueItem =