Ejemplo n.º 1
0
void HttpProtocolData::initTask(HttpTask *task)
{
    LOG(0, "enter initTask, task = %p\n", task);

    HttpSession *ses = task->sessions[0];
    TaskInfo *info = task->info;
    CURL *ehandle = ses->handle;

    char logBuffer[64] = {0};

    info->mimeType = getMimeType(ehandle, info->uri);
    snprintf(logBuffer, 63, "mime type: %s", info->mimeType.c_str());
    info->taskLog(info, logBuffer);

    // get file information.
    double length;
    if (info->outputName.length() == 0)
        info->outputName = getFileName(ehandle, info->uri);

    std::string output = info->outputPath;
    output.append(info->outputName);

    if (info->totalSize == 0)
    {
        File::remove(output.c_str());
    }

    task->file.open(output.c_str(), OF_Create | OF_Write);
    if (!task->file.isOpen())
        throw DOWNLOADEXCEPTION(FAIL_OPEN_FILE, "HTTP", strerror(FAIL_OPEN_FILE));
    snprintf(logBuffer, 63, "File path: %s", output.c_str());
    info->taskLog(info, logBuffer);

    if (info->totalSize == 0)
    {
        CURLcode rete = curl_easy_getinfo(ehandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &length);
        CHECK_CURLE(rete);
        if (length > 0)
        {
            info->totalSize = static_cast<size_t>(length);
            info->downloadMap = BitMap(size_t(length), task->conf.bytesPerBlock);
            info->downloadMap.setAll(false);
            info->validMap = BitMap(size_t(length), task->conf.bytesPerBlock);
            info->validMap.setAll(true);
            snprintf(logBuffer, 63, "File length: %lu", info->totalSize);
            info->taskLog(info, logBuffer);

            task->file.resize(info->totalSize);
        }
        else if (length < 0)
            info->totalSize = 0;
        else // length == 0, zero length file
            return;
    }

    info->totalSource = info->validSource = 1;

    if (info->totalSize > 0) // may equal 0 mean unknow length.
    {
        LOG(0, "make download sessions\n");
        // seperate download part in 2 steps:
        // 1 give each non-download part a session;
        // 2 find a biggest part and divide, repeat till enough session.
        unsigned int begin     = ses->pos / info->downloadMap.bytesPerBit();
        unsigned int end       = info->downloadMap.find(true, begin);
        unsigned int nextBegin = info->downloadMap.find(false, end);

        ses->length = (end - begin) * info->downloadMap.bytesPerBit();

        int i = 1;
        begin = nextBegin;

        while ( (i < task->conf.sessionNumber) && (begin < info->downloadMap.size()) )
        {
            end = info->downloadMap.find(true, begin);
            nextBegin = info->downloadMap.find(false, end);

            // make [begin, end) a seesion.
            makeSession(task, begin * info->downloadMap.bytesPerBit(), (end - begin) * info->downloadMap.bytesPerBit());

            ++i;
            begin = nextBegin;
        }

        while (i < task->conf.sessionNumber)
        {
            if (!splitMaxSession(task))
            {
                break;
            }

            ++i;
        }
    }
    task->state = HT_DOWNLOAD;
}