⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filemanager.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
字号:
/******************************************************************************** Copyright (C) 2004-2006 Trolltech ASA. All rights reserved.**** This file is part of the example classes of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "filemanager.h"#include "metainfo.h"#include <QByteArray>#include <QDir>#include <QFile>#include <QTimer>#include <QTimerEvent>extern "C" {#include "3rdparty/sha1.h"}FileManager::FileManager(QObject *parent)    : QThread(parent){    quit = false;    totalLength = 0;    readId = 0;    startVerification = false;    wokeUp = false;    newFile = false;    numPieces = 0;    verifiedPieces.fill(false);}FileManager::~FileManager(){    quit = true;    cond.wakeOne();    wait();    foreach (QFile *file, files) {        file->close();        delete file;    }}int FileManager::read(int pieceIndex, int offset, int length){    ReadRequest request;    request.pieceIndex = pieceIndex;    request.offset = offset;    request.length = length;    QMutexLocker locker(&mutex);    request.id = readId++;    readRequests << request;    if (!wokeUp) {        wokeUp = true;        QMetaObject::invokeMethod(this, "wakeUp", Qt::QueuedConnection);    }    return request.id;}void FileManager::write(int pieceIndex, int offset, const QByteArray &data){    WriteRequest request;    request.pieceIndex = pieceIndex;    request.offset = offset;    request.data = data;    QMutexLocker locker(&mutex);    writeRequests << request;    if (!wokeUp) {        wokeUp = true;        QMetaObject::invokeMethod(this, "wakeUp", Qt::QueuedConnection);    }}void FileManager::verifyPiece(int pieceIndex){    QMutexLocker locker(&mutex);    pendingVerificationRequests << pieceIndex;    startVerification = true;    if (!wokeUp) {        wokeUp = true;        QMetaObject::invokeMethod(this, "wakeUp", Qt::QueuedConnection);    }}int FileManager::pieceLengthAt(int pieceIndex) const{    QMutexLocker locker(&mutex);    return (sha1s.size() == pieceIndex + 1)        ? (totalLength % pieceLength) : pieceLength;}QBitArray FileManager::completedPieces() const{    QMutexLocker locker(&mutex);    return verifiedPieces;}void FileManager::setCompletedPieces(const QBitArray &pieces){    QMutexLocker locker(&mutex);    verifiedPieces = pieces;}QString FileManager::errorString() const{    return errString;}void FileManager::run(){    if (!generateFiles())        return;    do {        {            // Go to sleep if there's nothing to do.            QMutexLocker locker(&mutex);            if (!quit && readRequests.isEmpty() && writeRequests.isEmpty() && !startVerification)                cond.wait(&mutex);        }        // Read pending read requests        mutex.lock();        QList<ReadRequest> newReadRequests = readRequests;        readRequests.clear();        mutex.unlock();        while (!newReadRequests.isEmpty()) {            ReadRequest request = newReadRequests.takeFirst();            QByteArray block = readBlock(request.pieceIndex, request.offset, request.length);            emit dataRead(request.id, request.pieceIndex, request.offset, block);        }        // Write pending write requests        mutex.lock();        QList<WriteRequest> newWriteRequests = writeRequests;        writeRequests.clear();        while (!quit && !newWriteRequests.isEmpty()) {            WriteRequest request = newWriteRequests.takeFirst();            writeBlock(request.pieceIndex, request.offset, request.data);        }        // Process pending verification requests        if (startVerification) {            newPendingVerificationRequests = pendingVerificationRequests;            pendingVerificationRequests.clear();            verifyFileContents();            startVerification = false;        }        mutex.unlock();        newPendingVerificationRequests.clear();    } while (!quit);    // Write pending write requests    mutex.lock();    QList<WriteRequest> newWriteRequests = writeRequests;    writeRequests.clear();    mutex.unlock();    while (!newWriteRequests.isEmpty()) {        WriteRequest request = newWriteRequests.takeFirst();        writeBlock(request.pieceIndex, request.offset, request.data);    }}void FileManager::startDataVerification(){    QMutexLocker locker(&mutex);    startVerification = true;    cond.wakeOne();}bool FileManager::generateFiles(){    numPieces = -1;    // Set up the thread local data    if (metaInfo.fileForm() == MetaInfo::SingleFileForm) {        QMutexLocker locker(&mutex);        MetaInfoSingleFile singleFile = metaInfo.singleFile();        QString prefix;        if (!destinationPath.isEmpty()) {            prefix = destinationPath;            if (!prefix.endsWith("/"))                prefix += "/";            QDir dir;            if (!dir.mkpath(prefix)) {                errString = tr("Failed to create directory %1").arg(prefix);                emit error();                return false;            }        }        QFile *file = new QFile(prefix + singleFile.name);        if (!file->open(QFile::ReadWrite)) {            errString = tr("Failed to open/create file %1: %2")                        .arg(file->fileName()).arg(file->errorString());            emit error();            return false;        }        if (file->size() != singleFile.length) {            newFile = true;            if (!file->resize(singleFile.length)) {                errString = tr("Failed to resize file %1: %2")                            .arg(file->fileName()).arg(file->errorString());                emit error();                return false;            }        }        fileSizes << file->size();        files << file;        file->close();        pieceLength = singleFile.pieceLength;        totalLength = singleFile.length;        sha1s = singleFile.sha1Sums;    } else {        QMutexLocker locker(&mutex);        QDir dir;        QString prefix;        if (!destinationPath.isEmpty()) {            prefix = destinationPath;            if (!prefix.endsWith("/"))                prefix += "/";        }        if (!metaInfo.name().isEmpty()) {            prefix += metaInfo.name();            if (!prefix.endsWith("/"))                prefix += "/";        }        if (!dir.mkpath(prefix)) {            errString = tr("Failed to create directory %1").arg(prefix);            emit error();            return false;        }        foreach (const MetaInfoMultiFile &entry, metaInfo.multiFiles()) {            QString filePath = QFileInfo(prefix + entry.path).path();            if (!QFile::exists(filePath)) {                if (!dir.mkpath(filePath)) {                    errString = tr("Failed to create directory %1").arg(filePath);                    emit error();                    return false;                }            }            QFile *file = new QFile(prefix + entry.path);            if (!file->open(QFile::ReadWrite)) {                errString = tr("Failed to open/create file %1: %2")                            .arg(file->fileName()).arg(file->errorString());                emit error();                return false;            }            if (file->size() != entry.length) {                newFile = true;                if (!file->resize(entry.length)) {                    errString = tr("Failed to resize file %1: %2")                                .arg(file->fileName()).arg(file->errorString());                    emit error();                    return false;                }            }            fileSizes << file->size();            files << file;            file->close();            totalLength += entry.length;        }        sha1s = metaInfo.sha1Sums();        pieceLength = metaInfo.pieceLength();    }    numPieces = sha1s.size();    return true;}QByteArray FileManager::readBlock(int pieceIndex, int offset, int length){    QByteArray block;    qint64 startReadIndex = (quint64(pieceIndex) * pieceLength) + offset;    qint64 currentIndex = 0;    for (int i = 0; !quit && i < files.size() && length > 0; ++i) {        QFile *file = files[i];        qint64 currentFileSize = fileSizes.at(i);        if ((currentIndex + currentFileSize) > startReadIndex) {            if (!file->isOpen()) {                if (!file->open(QFile::ReadWrite)) {                    errString = tr("Failed to read from file %1: %2")                        .arg(file->fileName()).arg(file->errorString());                    emit error();                    break;                }            }            file->seek(startReadIndex - currentIndex);            QByteArray chunk = file->read(qMin<qint64>(length, currentFileSize - file->pos()));            file->close();            block += chunk;            length -= chunk.size();            startReadIndex += chunk.size();            if (length < 0) {                errString = tr("Failed to read from file %1 (read %3 bytes): %2")                            .arg(file->fileName()).arg(file->errorString()).arg(length);                emit error();                break;            }        }        currentIndex += currentFileSize;    }    return block;}bool FileManager::writeBlock(int pieceIndex, int offset, const QByteArray &data){    qint64 startWriteIndex = (qint64(pieceIndex) * pieceLength) + offset;    qint64 currentIndex = 0;    int bytesToWrite = data.size();    int written = 0;    for (int i = 0; !quit && i < files.size(); ++i) {        QFile *file = files[i];        qint64 currentFileSize = fileSizes.at(i);        if ((currentIndex + currentFileSize) > startWriteIndex) {            if (!file->isOpen()) {                if (!file->open(QFile::ReadWrite)) {                    errString = tr("Failed to write to file %1: %2")                        .arg(file->fileName()).arg(file->errorString());                    emit error();                    break;                }            }            file->seek(startWriteIndex - currentIndex);            qint64 bytesWritten = file->write(data.constData() + written,                                              qMin<qint64>(bytesToWrite, currentFileSize - file->pos()));            file->close();            if (bytesWritten <= 0) {                errString = tr("Failed to write to file %1: %2")                            .arg(file->fileName()).arg(file->errorString());                emit error();                return false;            }            written += bytesWritten;            startWriteIndex += bytesWritten;            bytesToWrite -= bytesWritten;            if (bytesToWrite == 0)                break;        }        currentIndex += currentFileSize;    }    return true;}void FileManager::verifyFileContents(){    // Verify all pieces the first time    if (newPendingVerificationRequests.isEmpty()) {        if (verifiedPieces.count(true) == 0) {            verifiedPieces.resize(sha1s.size());            int oldPercent = 0;            if (!newFile) {                int numPieces = sha1s.size();                for (int index = 0; index < numPieces; ++index) {                    verifySinglePiece(index);                    int percent = ((index + 1) * 100) / numPieces;                    if (oldPercent != percent) {                        emit verificationProgress(percent);                        oldPercent = percent;                    }                }            }        }        emit verificationDone();        return;    }    // Verify all pending pieces    foreach (int index, newPendingVerificationRequests)        emit pieceVerified(index, verifySinglePiece(index));}bool FileManager::verifySinglePiece(int pieceIndex){    QByteArray block = readBlock(pieceIndex, 0, pieceLength);    SHA1Context sha;    SHA1Reset(&sha);    SHA1Input(&sha, (const unsigned char *)block.constData(), block.size());    SHA1Result(&sha);    QByteArray sha1Sum(20, ' ');    unsigned char *digest = (unsigned char *)sha.Message_Digest;    for (int i = 0; i < 5; ++i) {#if Q_BYTE_ORDER == Q_BIG_ENDIAN        sha1Sum[i * 4 + 3] = digest[i * 4 + 3];        sha1Sum[i * 4 + 2] = digest[i * 4 + 2];        sha1Sum[i * 4 + 1] = digest[i * 4 + 1];        sha1Sum[i * 4 + 0] = digest[i * 4 + 0];#else        sha1Sum[i * 4 + 0] = digest[i * 4 + 3];        sha1Sum[i * 4 + 1] = digest[i * 4 + 2];        sha1Sum[i * 4 + 2] = digest[i * 4 + 1];        sha1Sum[i * 4 + 3] = digest[i * 4 + 0];#endif    }    if (sha1Sum != sha1s.at(pieceIndex))        return false;    verifiedPieces.setBit(pieceIndex);    return true;}void FileManager::wakeUp(){    QMutexLocker locker(&mutex);    wokeUp = false;    cond.wakeOne();}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -