]> Some of my projects - aniplayer-old.git/commitdiff
- New (broken) hashing infrastructure
authoraptx <aptx@rhea.(none)>
Fri, 21 Aug 2009 11:12:51 +0000 (13:12 +0200)
committeraptx <aptx@rhea.(none)>
Fri, 21 Aug 2009 11:12:51 +0000 (13:12 +0200)
lib/anidbudpclient/circularbuffer.h [new file with mode: 0644]
lib/anidbudpclient/hash.cpp [new file with mode: 0644]
lib/anidbudpclient/hash.h [new file with mode: 0644]
lib/anidbudpclient/hashconsumer.cpp [new file with mode: 0644]
lib/anidbudpclient/hashconsumer.h [new file with mode: 0644]
lib/anidbudpclient/hashproducer.cpp [new file with mode: 0644]
lib/anidbudpclient/hashproducer.h [new file with mode: 0644]
lib/anidbudpclient/include/AniDBUdpClient/Hash [new file with mode: 0644]

diff --git a/lib/anidbudpclient/circularbuffer.h b/lib/anidbudpclient/circularbuffer.h
new file mode 100644 (file)
index 0000000..dd9a9da
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef CIRCULARBUFFER_H
+#define CIRCULARBUFFER_H
+
+#include <QSemaphore>
+
+namespace AniDBUdpClient {
+namespace HashPrivate {
+
+template<typename T, int SIZE> 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<QByteArray, 2> Buffer;
+
+} // namespace HashPrivate
+} // namesapce AniDBUdpClient
+
+#endif // CIRCULARBUFFER_H
diff --git a/lib/anidbudpclient/hash.cpp b/lib/anidbudpclient/hash.cpp
new file mode 100644 (file)
index 0000000..bd5dc0b
--- /dev/null
@@ -0,0 +1,85 @@
+#include "hash.h"
+
+#include <QDebug>
+
+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 (file)
index 0000000..38eaf32
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef HASH_H
+#define HASH_H
+
+#include "anidbudpclient_global.h"
+#include <QObject>
+#include <QQueue>
+#include <QMap>
+#include <QFileInfo>
+
+#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<QFileInfo> fileQueue;
+       QMap<QFileInfo, QByteArray> hashedFiles;
+
+       bool hashing;
+};
+
+} // namesapce AniDBUdpClient
+
+#endif // HASH_H
diff --git a/lib/anidbudpclient/hashconsumer.cpp b/lib/anidbudpclient/hashconsumer.cpp
new file mode 100644 (file)
index 0000000..f5dc40f
--- /dev/null
@@ -0,0 +1,63 @@
+#include "hashconsumer.h"
+
+#include <QDebug>
+
+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 (file)
index 0000000..69c6c0f
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef HASHCONSUMER_H
+#define HASHCONSUMER_H
+
+#include "anidbudpclient_global.h"
+#include <QThread>
+#include <QCryptographicHash>
+#include <QFile>
+#include <QFileInfo>
+
+#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 (file)
index 0000000..d4c4358
--- /dev/null
@@ -0,0 +1,59 @@
+#include "hashproducer.h"
+
+#include <QDebug>
+
+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 (file)
index 0000000..0bde203
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef HASHPRODUCER_H
+#define HASHPRODUCER_H
+
+#include "anidbudpclient_global.h"
+#include <QThread>
+#include <QFile>
+#include <QFileInfo>
+
+#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 (file)
index 0000000..4ae187b
--- /dev/null
@@ -0,0 +1 @@
+#include "../../hash.h"