From: aptx Date: Fri, 21 Aug 2009 11:12:51 +0000 (+0200) Subject: - New (broken) hashing infrastructure X-Git-Url: https://gitweb.tyo.aptx.org/?a=commitdiff_plain;h=cb6f8b5953a71cb1b0fd7b2ad789220abbcbbf7b;p=aniplayer-old.git - New (broken) hashing infrastructure --- diff --git a/lib/anidbudpclient/circularbuffer.h b/lib/anidbudpclient/circularbuffer.h new file mode 100644 index 0000000..dd9a9da --- /dev/null +++ b/lib/anidbudpclient/circularbuffer.h @@ -0,0 +1,72 @@ +#ifndef CIRCULARBUFFER_H +#define CIRCULARBUFFER_H + +#include + +namespace AniDBUdpClient { +namespace HashPrivate { + +template class CircularBuffer +{ +public: + CircularBuffer() + { + // Set N to SIZE + free.release(SIZE); + r = w = 0; + m_end = false; + } + + void put(T data, bool last = false) + { + if (m_end) return; + + free.acquire(); + buffer[w] = data; + m_end = last; + used.release(); + w++; + w %= SIZE; + } + + T get() + { + used.acquire(); + T data = buffer[r]; + free.release(); + r++; + r %= SIZE; + return data; + } + + bool end() const + { + return m_end && r == w; + } + + bool reset() + { + if (!end()) + return false; + + m_end = false; + r = w = 0; + return true; + } + +private: + T buffer[SIZE]; + QSemaphore free; + QSemaphore used; + + int r; + int w; + bool m_end; +}; + +typedef CircularBuffer Buffer; + +} // namespace HashPrivate +} // namesapce AniDBUdpClient + +#endif // CIRCULARBUFFER_H diff --git a/lib/anidbudpclient/hash.cpp b/lib/anidbudpclient/hash.cpp new file mode 100644 index 0000000..bd5dc0b --- /dev/null +++ b/lib/anidbudpclient/hash.cpp @@ -0,0 +1,85 @@ +#include "hash.h" + +#include + +namespace AniDBUdpClient { + +Hash::Hash(QObject *parent) : QObject(parent) +{ + producer = 0; + consumer = 0; + buffer = 0; + hashing = false; + setUp(); +} + +Hash::~Hash() +{ + tearDown(); +} + +void Hash::hashFile(const QFileInfo &file) +{ +qDebug() << "Hash::hashFile"; + fileQueue.enqueue(file); + + if (hashing) + return; + + emit startHashing(fileQueue.first().absoluteFilePath()); +} + +void Hash::endHashing(const QByteArray &hash) +{ +qDebug() << "Hash::endHashing"; + QFileInfo f = fileQueue.dequeue(); + + if (!fileQueue.isEmpty()) + { + emit startHashing(fileQueue.first().absoluteFilePath()); + } + else + { + hashing = false; + } + emit fileHashed(f, hash); +qDebug() << "FILE" << f.fileName() << "HASH" << hash; +} + + +void Hash::setUp() +{ + if (producer || consumer || buffer) + return; + + buffer = new HashPrivate::Buffer; + producer = new HashPrivate::HashProducer(buffer, this); + consumer = new HashPrivate::HashConsumer(buffer, this); + connect(this, SIGNAL(startHashing(QString)), consumer, SLOT(hashFile(QString)), Qt::QueuedConnection); + connect(this, SIGNAL(startHashing(QString)), producer, SLOT(readFile(QString)), Qt::QueuedConnection); + connect(consumer, SIGNAL(finishedHashing(QByteArray)), this, SLOT(endHashing(QByteArray)), Qt::QueuedConnection); + + producer->start(); + consumer->start(); +} + +void Hash::tearDown() +{ + if (!producer || !consumer || !buffer) + return; + + producer->stop(); + consumer->stop(); + producer->wait(); + consumer->wait(); + + delete producer; + delete consumer; + delete buffer; + + producer = 0; + consumer = 0; + buffer = 0; +} + +} // namesapce AniDBUdpClient diff --git a/lib/anidbudpclient/hash.h b/lib/anidbudpclient/hash.h new file mode 100644 index 0000000..38eaf32 --- /dev/null +++ b/lib/anidbudpclient/hash.h @@ -0,0 +1,49 @@ +#ifndef HASH_H +#define HASH_H + +#include "anidbudpclient_global.h" +#include +#include +#include +#include + +#include "hashproducer.h" +#include "hashconsumer.h" + +namespace AniDBUdpClient { + +class ANIDBUDPCLIENTSHARED_EXPORT Hash : public QObject +{ + + Q_OBJECT + +public: + Hash(QObject *parent = 0); + ~Hash(); + + void hashFile(const QFileInfo &file); + +signals: + void startHashing(const QString &file); + void fileHashed(const QFileInfo &file, const QByteArray &hash); + +private slots: + void endHashing(const QByteArray &hash); + +private: + void setUp(); + void tearDown(); + + HashPrivate::Buffer *buffer; + HashPrivate::HashProducer *producer; + HashPrivate::HashConsumer *consumer; + + QQueue fileQueue; + QMap hashedFiles; + + bool hashing; +}; + +} // namesapce AniDBUdpClient + +#endif // HASH_H diff --git a/lib/anidbudpclient/hashconsumer.cpp b/lib/anidbudpclient/hashconsumer.cpp new file mode 100644 index 0000000..f5dc40f --- /dev/null +++ b/lib/anidbudpclient/hashconsumer.cpp @@ -0,0 +1,63 @@ +#include "hashconsumer.h" + +#include + +namespace AniDBUdpClient { +namespace HashPrivate { + +HashConsumer::HashConsumer(Buffer *buffer, QObject *parent) : QThread(parent) +{ + this->buffer = buffer; + hash = new QCryptographicHash(QCryptographicHash::Md4); + connect(this, SIGNAL(startHashing()), this, SLOT(doHash())); +} + +HashConsumer::~HashConsumer() +{ + delete hash; +} + +void HashConsumer::hashFile(const QString &file) +{ +qDebug() << "hashFile()"; + fileSize = QFileInfo(file).size(); + + emit startHashing(); +} + +void HashConsumer::stop() +{ + m_stop = true; + quit(); +} + +void HashConsumer::run() +{ + exec(); +} + +void HashConsumer::doHash() +{ + while (!buffer->end()) + { +qDebug() << "doHash()->while(" << buffer->end() << ")"; + hashSome(); + } + buffer->reset(); + hash->reset(); +} + +void HashConsumer::hashSome() +{ + QByteArray data = buffer->get(); + + hash->addData(QCryptographicHash::hash(data, QCryptographicHash::Md4)); + + if (buffer->end()) + emit finishedHashing(hash->result()); + +qDebug() << "hashSome()"; +} + +} // namespace HashPrivate +} // namesapce AniDBUdpClient diff --git a/lib/anidbudpclient/hashconsumer.h b/lib/anidbudpclient/hashconsumer.h new file mode 100644 index 0000000..69c6c0f --- /dev/null +++ b/lib/anidbudpclient/hashconsumer.h @@ -0,0 +1,50 @@ +#ifndef HASHCONSUMER_H +#define HASHCONSUMER_H + +#include "anidbudpclient_global.h" +#include +#include +#include +#include + +#include "circularbuffer.h" + +namespace AniDBUdpClient { +namespace HashPrivate { + +class HashConsumer : public QThread +{ + Q_OBJECT +public: + HashConsumer(Buffer *buffer, QObject *parent = 0); + ~HashConsumer(); + +public slots: + void hashFile(const QString &file); + + void stop(); + +protected: + void run(); + +signals: + void startHashing(); + void finishedHashing(QByteArray hash); + +private slots: + void doHash(); + +private: + void hashSome(); + + Buffer *buffer; + QCryptographicHash *hash; + qint64 fileSize; + + bool m_stop; +}; + +} // namespace HashPrivate +} // namesapce AniDBUdpClient + +#endif // HASHCONSUMER_H diff --git a/lib/anidbudpclient/hashproducer.cpp b/lib/anidbudpclient/hashproducer.cpp new file mode 100644 index 0000000..d4c4358 --- /dev/null +++ b/lib/anidbudpclient/hashproducer.cpp @@ -0,0 +1,59 @@ +#include "hashproducer.h" + +#include + +namespace AniDBUdpClient { +namespace HashPrivate { + +HashProducer::HashProducer(Buffer *buffer, QObject *parent) : QThread(parent) +{ + this->buffer = buffer; + connect(this, SIGNAL(startReading()), this, SLOT(doRead())); +} + +void HashProducer::readFile(const QString &file) +{ +qDebug() << "readFile"; + this->file.setFileName(file); + + fileSize = file.size(); + + if (!this->file.open(QIODevice::ReadOnly)) + { +qDebug() << "Failed toopen file" << this->file.fileName(); + return; + } + + emit startReading(); +} + +void HashProducer::stop() +{ + m_stop = true; + quit(); +} + +void HashProducer::run() +{ + exec(); +} + +void HashProducer::doRead() +{ + while (!this->file.atEnd()) + { +qDebug() << "doRead->while(" << (!this->file.atEnd()) << ")"; + readSome(); + } + this->file.close(); +} + +void HashProducer::readSome() +{ + QByteArray data = file.read(ED2K_PART_SIZE); +qDebug() << "readSome"; + buffer->put(data, file.atEnd()); +} + +} // namespace HashPrivate +} // namesapce AniDBUdpClient diff --git a/lib/anidbudpclient/hashproducer.h b/lib/anidbudpclient/hashproducer.h new file mode 100644 index 0000000..0bde203 --- /dev/null +++ b/lib/anidbudpclient/hashproducer.h @@ -0,0 +1,48 @@ +#ifndef HASHPRODUCER_H +#define HASHPRODUCER_H + +#include "anidbudpclient_global.h" +#include +#include +#include + +#include "circularbuffer.h" + +namespace AniDBUdpClient { +namespace HashPrivate { + +class HashProducer : public QThread +{ + Q_OBJECT + +public: + HashProducer(Buffer *buffer, QObject *parent = 0); + +public slots: + void readFile(const QString &file); + + void stop(); +protected: + void run(); + +signals: + void startReading(); + void finishedReading(); + +private slots: + void doRead(); + +private: + void readSome(); + + Buffer *buffer; + QFile file; + qint64 fileSize; + + bool m_stop; +}; + +} // namespace HashPrivate +} // namesapce AniDBUdpClient + +#endif // HASHPRODUCER_H diff --git a/lib/anidbudpclient/include/AniDBUdpClient/Hash b/lib/anidbudpclient/include/AniDBUdpClient/Hash new file mode 100644 index 0000000..4ae187b --- /dev/null +++ b/lib/anidbudpclient/include/AniDBUdpClient/Hash @@ -0,0 +1 @@ +#include "../../hash.h"