Merge "Resolving race condition while writing recent taskids" into nyc-mr1-dev

This commit is contained in:
TreeHugger Robot
2016-08-26 00:39:42 +00:00
committed by Android (Google) Code Review
2 changed files with 49 additions and 40 deletions

View File

@@ -87,6 +87,8 @@ public class TaskPersister {
private final RecentTasks mRecentTasks; private final RecentTasks mRecentTasks;
private final SparseArray<SparseBooleanArray> mTaskIdsInFile = new SparseArray<>(); private final SparseArray<SparseBooleanArray> mTaskIdsInFile = new SparseArray<>();
private final File mTaskIdsDir; private final File mTaskIdsDir;
// To lock file operations in TaskPersister
private final Object mIoLock = new Object();
/** /**
* Value determines write delay mode as follows: < 0 We are Flushing. No delays between writes * Value determines write delay mode as follows: < 0 We are Flushing. No delays between writes
@@ -195,6 +197,7 @@ public class TaskPersister {
return mTaskIdsInFile.get(userId).clone(); return mTaskIdsInFile.get(userId).clone();
} }
final SparseBooleanArray persistedTaskIds = new SparseBooleanArray(); final SparseBooleanArray persistedTaskIds = new SparseBooleanArray();
synchronized (mIoLock) {
BufferedReader reader = null; BufferedReader reader = null;
String line; String line;
try { try {
@@ -212,20 +215,19 @@ public class TaskPersister {
} finally { } finally {
IoUtils.closeQuietly(reader); IoUtils.closeQuietly(reader);
} }
}
mTaskIdsInFile.put(userId, persistedTaskIds); mTaskIdsInFile.put(userId, persistedTaskIds);
return persistedTaskIds.clone(); return persistedTaskIds.clone();
} }
@VisibleForTesting @VisibleForTesting
void maybeWritePersistedTaskIdsForUser(@NonNull SparseBooleanArray taskIds, int userId) { void writePersistedTaskIdsForUser(@NonNull SparseBooleanArray taskIds, int userId) {
if (userId < 0) { if (userId < 0) {
return; return;
} }
SparseBooleanArray persistedIdsInFile = mTaskIdsInFile.get(userId);
if (persistedIdsInFile != null && persistedIdsInFile.equals(taskIds)) {
return;
}
final File persistedTaskIdsFile = getUserPersistedTaskIdsFile(userId); final File persistedTaskIdsFile = getUserPersistedTaskIdsFile(userId);
synchronized (mIoLock) {
BufferedWriter writer = null; BufferedWriter writer = null;
try { try {
writer = new BufferedWriter(new FileWriter(persistedTaskIdsFile)); writer = new BufferedWriter(new FileWriter(persistedTaskIdsFile));
@@ -240,7 +242,7 @@ public class TaskPersister {
} finally { } finally {
IoUtils.closeQuietly(writer); IoUtils.closeQuietly(writer);
} }
mTaskIdsInFile.put(userId, taskIds.clone()); }
} }
void unloadUserDataFromMemory(int userId) { void unloadUserDataFromMemory(int userId) {
@@ -543,16 +545,23 @@ public class TaskPersister {
} }
private void writeTaskIdsFiles() { private void writeTaskIdsFiles() {
int candidateUserIds[]; SparseArray<SparseBooleanArray> changedTaskIdsPerUser = new SparseArray<>();
synchronized (mService) { synchronized (mService) {
candidateUserIds = mRecentTasks.usersWithRecentsLoadedLocked(); for (int userId : mRecentTasks.usersWithRecentsLoadedLocked()) {
SparseBooleanArray taskIdsToSave = mRecentTasks.mPersistedTaskIds.get(userId);
SparseBooleanArray persistedIdsInFile = mTaskIdsInFile.get(userId);
if (persistedIdsInFile != null && persistedIdsInFile.equals(taskIdsToSave)) {
continue;
} else {
SparseBooleanArray taskIdsToSaveCopy = taskIdsToSave.clone();
mTaskIdsInFile.put(userId, taskIdsToSaveCopy);
changedTaskIdsPerUser.put(userId, taskIdsToSaveCopy);
} }
SparseBooleanArray taskIdsToSave;
for (int userId : candidateUserIds) {
synchronized (mService) {
taskIdsToSave = mRecentTasks.mPersistedTaskIds.get(userId).clone();
} }
maybeWritePersistedTaskIdsForUser(taskIdsToSave, userId); }
for (int i = 0; i < changedTaskIdsPerUser.size(); i++) {
writePersistedTaskIdsForUser(changedTaskIdsPerUser.valueAt(i),
changedTaskIdsPerUser.keyAt(i));
} }
} }

View File

@@ -62,7 +62,7 @@ public class TaskPersisterTest extends AndroidTestCase {
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
taskIdsOnFile.put(getRandomTaskIdForUser(testUserId), true); taskIdsOnFile.put(getRandomTaskIdForUser(testUserId), true);
} }
mTaskPersister.maybeWritePersistedTaskIdsForUser(taskIdsOnFile, testUserId); mTaskPersister.writePersistedTaskIdsForUser(taskIdsOnFile, testUserId);
SparseBooleanArray newTaskIdsOnFile = mTaskPersister SparseBooleanArray newTaskIdsOnFile = mTaskPersister
.loadPersistedTaskIdsForUser(testUserId); .loadPersistedTaskIdsForUser(testUserId);
assertTrue("TaskIds written differ from TaskIds read back from file", assertTrue("TaskIds written differ from TaskIds read back from file",