<commit_before>/*
 * Copyright (c) 2015 LingoChamp Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.liulishuo.filedownloader.services;


import android.text.TextUtils;

import com.liulishuo.filedownloader.IThreadPoolMonitor;
import com.liulishuo.filedownloader.database.FileDownloadDatabase;
import com.liulishuo.filedownloader.download.CustomComponentHolder;
import com.liulishuo.filedownloader.download.DownloadLaunchRunnable;
import com.liulishuo.filedownloader.download.DownloadRunnable;
import com.liulishuo.filedownloader.model.ConnectionModel;
import com.liulishuo.filedownloader.model.FileDownloadHeader;
import com.liulishuo.filedownloader.model.FileDownloadModel;
import com.liulishuo.filedownloader.model.FileDownloadStatus;
import com.liulishuo.filedownloader.util.FileDownloadHelper;
import com.liulishuo.filedownloader.util.FileDownloadLog;
import com.liulishuo.filedownloader.util.FileDownloadUtils;

import java.util.List;

/**
 * The downloading manager in FileDownloadService, which is used to control all download-inflow.
 * <p/>
 * Handling real {@link #start(String, String, boolean, int, int, int, boolean, FileDownloadHeader,
 * boolean)}.
 *
 * @see FileDownloadThreadPool
 * @see DownloadLaunchRunnable
 * @see DownloadRunnable
 */
class FileDownloadManager implements IThreadPoolMonitor {
    private final FileDownloadDatabase mDatabase;
    private final FileDownloadThreadPool mThreadPool;

    FileDownloadManager() {
        final CustomComponentHolder holder = CustomComponentHolder.getImpl();
        this.mDatabase = holder.getDatabaseInstance();
        this.mThreadPool = new FileDownloadThreadPool(holder.getMaxNetworkThreadCount());
    }

    // synchronize for safe: check downloading, check resume, update data, execute runnable
    public synchronized void start(final String url, final String path,
                                   final boolean pathAsDirectory,
                                   final int callbackProgressTimes,
                                   final int callbackProgressMinIntervalMillis,
                                   final int autoRetryTimes, final boolean forceReDownload,
                                   final FileDownloadHeader header, final boolean isWifiRequired) {
        if (FileDownloadLog.NEED_LOG) {
            FileDownloadLog.d(this, "request start the task with url(%s) path(%s) isDirectory(%B)",
                    url, path, pathAsDirectory);
        }

        final int id = FileDownloadUtils.generateId(url, path, pathAsDirectory);
        FileDownloadModel model = mDatabase.find(id);

        List<ConnectionModel> dirConnectionModelList = null;

        if (!pathAsDirectory && model == null) {
            // try dir data.
            final int dirCaseId = FileDownloadUtils
                    .generateId(url, FileDownloadUtils.getParent(path),
                            true);
            model = mDatabase.find(dirCaseId);
            if (model != null && path.equals(model.getTargetFilePath())) {
                if (FileDownloadLog.NEED_LOG) {
                    FileDownloadLog.d(this, "task[%d] find model by dirCaseId[%d]", id, dirCaseId);
                }

                dirConnectionModelList = mDatabase.findConnectionModel(dirCaseId);
            }
        }

        if (FileDownloadHelper.inspectAndInflowDownloading(id, model, this, true)) {
            if (FileDownloadLog.NEED_LOG) {
                FileDownloadLog.d(this, "has already started download %d", id);
            }
            return;
        }

        final String targetFilePath = model != null ? model.getTargetFilePath()
                : FileDownloadUtils.getTargetFilePath(path, pathAsDirectory, null);
        if (FileDownloadHelper.inspectAndInflowDownloaded(id, targetFilePath, forceReDownload,
                true)) {
            if (FileDownloadLog.NEED_LOG) {
                FileDownloadLog.d(this, "has already completed downloading %d", id);
            }
            return;
        }

        final long sofar = model != null ? model.getSoFar() : 0;
        final String tempFilePath = model != null ? model.getTempFilePath()
                : FileDownloadUtils.getTempPath(targetFilePath);
        if (FileDownloadHelper.inspectAndInflowConflictPath(id, sofar, tempFilePath, targetFilePath,
                this)) {
            if (FileDownloadLog.NEED_LOG) {
                FileDownloadLog
                        .d(this, "there is an another task with the same target-file-path %d %s",
                                id, targetFilePath);
                // because of the file is dirty for this task.
                if (model != null) {
                    mDatabase.remove(id);
                    mDatabase.removeConnections(id);
                }
            }
            return;<commit_msg>fix: fix do not remove the temp duplicate data on the database when there are another running task with the same temp file path closes #953<commit_after>/*
 * Copyright (c) 2015 LingoChamp Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.liulishuo.filedownloader.services;


import android.text.TextUtils;

import com.liulishuo.filedownloader.IThreadPoolMonitor;
import com.liulishuo.filedownloader.database.FileDownloadDatabase;
import com.liulishuo.filedownloader.download.CustomComponentHolder;
import com.liulishuo.filedownloader.download.DownloadLaunchRunnable;
import com.liulishuo.filedownloader.download.DownloadRunnable;
import com.liulishuo.filedownloader.model.ConnectionModel;
import com.liulishuo.filedownloader.model.FileDownloadHeader;
import com.liulishuo.filedownloader.model.FileDownloadModel;
import com.liulishuo.filedownloader.model.FileDownloadStatus;
import com.liulishuo.filedownloader.util.FileDownloadHelper;
import com.liulishuo.filedownloader.util.FileDownloadLog;
import com.liulishuo.filedownloader.util.FileDownloadUtils;

import java.util.List;

/**
 * The downloading manager in FileDownloadService, which is used to control all download-inflow.
 * <p/>
 * Handling real {@link #start(String, String, boolean, int, int, int, boolean, FileDownloadHeader,
 * boolean)}.
 *
 * @see FileDownloadThreadPool
 * @see DownloadLaunchRunnable
 * @see DownloadRunnable
 */
class FileDownloadManager implements IThreadPoolMonitor {
    private final FileDownloadDatabase mDatabase;
    private final FileDownloadThreadPool mThreadPool;

    FileDownloadManager() {
        final CustomComponentHolder holder = CustomComponentHolder.getImpl();
        this.mDatabase = holder.getDatabaseInstance();
        this.mThreadPool = new FileDownloadThreadPool(holder.getMaxNetworkThreadCount());
    }

    // synchronize for safe: check downloading, check resume, update data, execute runnable
    public synchronized void start(final String url, final String path,
                                   final boolean pathAsDirectory,
                                   final int callbackProgressTimes,
                                   final int callbackProgressMinIntervalMillis,
                                   final int autoRetryTimes, final boolean forceReDownload,
                                   final FileDownloadHeader header, final boolean isWifiRequired) {
        if (FileDownloadLog.NEED_LOG) {
            FileDownloadLog.d(this, "request start the task with url(%s) path(%s) isDirectory(%B)",
                    url, path, pathAsDirectory);
        }

        final int id = FileDownloadUtils.generateId(url, path, pathAsDirectory);
        FileDownloadModel model = mDatabase.find(id);

        List<ConnectionModel> dirConnectionModelList = null;

        if (!pathAsDirectory && model == null) {
            // try dir data.
            final int dirCaseId = FileDownloadUtils
                    .generateId(url, FileDownloadUtils.getParent(path),
                            true);
            model = mDatabase.find(dirCaseId);
            if (model != null && path.equals(model.getTargetFilePath())) {
                if (FileDownloadLog.NEED_LOG) {
                    FileDownloadLog.d(this, "task[%d] find model by dirCaseId[%d]", id, dirCaseId);
                }

                dirConnectionModelList = mDatabase.findConnectionModel(dirCaseId);
            }
        }

        if (FileDownloadHelper.inspectAndInflowDownloading(id, model, this, true)) {
            if (FileDownloadLog.NEED_LOG) {
                FileDownloadLog.d(this, "has already started download %d", id);
            }
            return;
        }

        final String targetFilePath = model != null ? model.getTargetFilePath()
                : FileDownloadUtils.getTargetFilePath(path, pathAsDirectory, null);
        if (FileDownloadHelper.inspectAndInflowDownloaded(id, targetFilePath, forceReDownload,
                true)) {
            if (FileDownloadLog.NEED_LOG) {
                FileDownloadLog.d(this, "has already completed downloading %d", id);
            }
            return;
        }

        final long sofar = model != null ? model.getSoFar() : 0;
        final String tempFilePath = model != null ? model.getTempFilePath()
                : FileDownloadUtils.getTempPath(targetFilePath);
        if (FileDownloadHelper.inspectAndInflowConflictPath(id, sofar, tempFilePath, targetFilePath,
                this)) {
            if (FileDownloadLog.NEED_LOG) {
                FileDownloadLog
                        .d(this, "there is an another task with the same target-file-path %d %s",
                                id, targetFilePath);
            }

            // because of the file is dirty for this task.
            if (model != null) {
                mDatabase.remove(id);
                mDatabase.removeConnections(id);
            }
            return;
{'fraction_non_alphanumeric': 0.08048215113583682, 'fraction_numerical': 0.0019471488178025036, 'mean_word_length': 2.5679788289778367, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 140, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4631159', 'n_tokens_mistral': 2811, 'n_tokens_neox': 2684, 'n_words': 738}