Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cap concurrent removal DownloadManager.Tasks #126

Merged
merged 1 commit into from
Aug 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -174,6 +174,7 @@ default void onWaitingForRequirementsChanged(
private static final int MSG_RELEASE = 12;

private static final String TAG = "DownloadManager";
private static final int MAX_REMOVE_TASK_COUNT = 1;

private final Context context;
private final WritableDownloadIndex downloadIndex;
Expand Down Expand Up @@ -709,6 +710,7 @@ private static final class InternalHandler extends Handler {
private int maxParallelDownloads;
private int minRetryCount;
private int activeDownloadTaskCount;
private int activeRemoveTaskCount;

public InternalHandler(
HandlerThread thread,
Expand Down Expand Up @@ -1060,6 +1062,10 @@ private void syncRemovingDownload(@Nullable Task activeTask, Download download)
return;
}

if (activeRemoveTaskCount >= MAX_REMOVE_TASK_COUNT) {
return;
}

// We can start a remove task.
Downloader downloader = downloaderFactory.createDownloader(download.request);
activeTask =
Expand All @@ -1071,6 +1077,7 @@ private void syncRemovingDownload(@Nullable Task activeTask, Download download)
minRetryCount,
/* internalHandler= */ this);
activeTasks.put(download.request.id, activeTask);
activeRemoveTaskCount++;
activeTask.start();
}

Expand Down Expand Up @@ -1100,7 +1107,9 @@ private void onTaskStopped(Task task) {
activeTasks.remove(downloadId);

boolean isRemove = task.isRemove;
if (!isRemove && --activeDownloadTaskCount == 0) {
if (isRemove) {
activeRemoveTaskCount--;
} else if (--activeDownloadTaskCount == 0) {
removeMessages(MSG_UPDATE_PROGRESS);
}

Expand Down
Expand Up @@ -713,7 +713,61 @@ public void mergeRequest_completedWithStopReason_becomesStopped() {
assertEqualIgnoringUpdateTime(mergedDownload, expectedDownload);
}

@Test
public void remove_tasks_run_sequentially()
throws Throwable {
DefaultDownloadIndex defaultDownloadIndex =
new DefaultDownloadIndex(TestUtil.getInMemoryDatabaseProvider());
defaultDownloadIndex.putDownload(
new Download(
new DownloadRequest.Builder(ID1, Uri.EMPTY).build(),
Download.STATE_REMOVING,
0,
1,
2,
Download.STOP_REASON_NONE,
Download.FAILURE_REASON_NONE
)
);
defaultDownloadIndex.putDownload(
new Download(
new DownloadRequest.Builder(ID2, Uri.EMPTY).build(),
Download.STATE_RESTARTING,
0,
1,
2,
Download.STOP_REASON_NONE,
Download.FAILURE_REASON_NONE
)
);
setupDownloadManager(100, defaultDownloadIndex);

// The second removal should wait and the first one should be able to complete.
FakeDownloader downloader0 = getDownloaderAt(0);
assertNoDownloaderAt(1);
downloader0.assertId(ID1);
downloader0.assertRemoveStarted();
downloader0.finish();
assertRemoved(ID1);

// The second removal can start once the first one has completed, and removes a download with
// state STATE_RESTARTING, so it should result in a new download being queued.
FakeDownloader downloader1 = getDownloaderAt(1);
downloader1.assertId(ID2);
downloader1.assertRemoveStarted();
downloader1.finish();
assertQueued(ID2);
}

private void setupDownloadManager(int maxParallelDownloads) throws Exception {
setupDownloadManager(
maxParallelDownloads, new DefaultDownloadIndex(TestUtil.getInMemoryDatabaseProvider())
);
}

private void setupDownloadManager(
int maxParallelDownloads, WritableDownloadIndex writableDownloadIndex
) throws Exception {
if (downloadManager != null) {
releaseDownloadManager();
}
Expand All @@ -723,7 +777,7 @@ private void setupDownloadManager(int maxParallelDownloads) throws Exception {
downloadManager =
new DownloadManager(
ApplicationProvider.getApplicationContext(),
new DefaultDownloadIndex(TestUtil.getInMemoryDatabaseProvider()),
writableDownloadIndex,
new FakeDownloaderFactory());
downloadManager.setMaxParallelDownloads(maxParallelDownloads);
downloadManager.setMinRetryCount(MIN_RETRY_COUNT);
Expand Down