[app] Store book's MD-5 hash as xattr if the filesystem allows it
This significantly speeds up the process of scanning downloads for new books. The attribute name is "user.harbour-books.md5-hash"
This commit is contained in:
parent
b108c25f25
commit
481d42d616
1 changed files with 28 additions and 4 deletions
|
@ -35,12 +35,20 @@
|
||||||
#include "BooksStorage.h"
|
#include "BooksStorage.h"
|
||||||
#include "BooksTask.h"
|
#include "BooksTask.h"
|
||||||
#include "BooksUtil.h"
|
#include "BooksUtil.h"
|
||||||
|
#include "BooksDefs.h"
|
||||||
|
|
||||||
#include "HarbourDebug.h"
|
#include "HarbourDebug.h"
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
|
#include <attr/xattr.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define DIGEST_XATTR "user." BOOKS_APP_NAME ".md5-hash"
|
||||||
|
#define DIGEST_TYPE (QCryptographicHash::Md5)
|
||||||
|
#define DIGEST_SIZE (16)
|
||||||
|
|
||||||
enum BooksImportRole {
|
enum BooksImportRole {
|
||||||
BooksImportRoleTitle = Qt::UserRole,
|
BooksImportRoleTitle = Qt::UserRole,
|
||||||
BooksImportRoleBook,
|
BooksImportRoleBook,
|
||||||
|
@ -124,7 +132,7 @@ QByteArray BooksImportModel::Task::calculateFileHash(QString aPath)
|
||||||
QFile file(aPath);
|
QFile file(aPath);
|
||||||
if (file.open(QIODevice::ReadOnly)) {
|
if (file.open(QIODevice::ReadOnly)) {
|
||||||
qint64 len = 0;
|
qint64 len = 0;
|
||||||
QCryptographicHash hash(QCryptographicHash::Md5);
|
QCryptographicHash hash(DIGEST_TYPE);
|
||||||
hash.reset();
|
hash.reset();
|
||||||
if (!iBuf) iBuf = new char[iBufSize];
|
if (!iBuf) iBuf = new char[iBufSize];
|
||||||
while (!isCanceled() && (len = file.read(iBuf, iBufSize)) > 0) {
|
while (!isCanceled() && (len = file.read(iBuf, iBufSize)) > 0) {
|
||||||
|
@ -133,6 +141,7 @@ QByteArray BooksImportModel::Task::calculateFileHash(QString aPath)
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
if (!isCanceled()) {
|
if (!isCanceled()) {
|
||||||
result = hash.result();
|
result = hash.result();
|
||||||
|
HASSERT(result.size() == DIGEST_SIZE);
|
||||||
HDEBUG(qPrintable(aPath) << QString(result.toHex()));
|
HDEBUG(qPrintable(aPath) << QString(result.toHex()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,9 +157,24 @@ QByteArray BooksImportModel::Task::getFileHash(QString aPath)
|
||||||
if (iFileHash.contains(aPath)) {
|
if (iFileHash.contains(aPath)) {
|
||||||
return iFileHash.value(aPath);
|
return iFileHash.value(aPath);
|
||||||
} else {
|
} else {
|
||||||
QByteArray hash = calculateFileHash(aPath);
|
QByteArray hash;
|
||||||
|
char attr[DIGEST_SIZE];
|
||||||
|
QByteArray fname = aPath.toLocal8Bit();
|
||||||
|
if (getxattr(fname, DIGEST_XATTR, attr, sizeof(attr)) == DIGEST_SIZE) {
|
||||||
|
hash = QByteArray(attr, sizeof(attr));
|
||||||
|
HDEBUG(qPrintable(aPath) << QString(hash.toHex()));
|
||||||
|
} else {
|
||||||
|
hash = calculateFileHash(aPath);
|
||||||
|
if (hash.size() == DIGEST_SIZE &&
|
||||||
|
setxattr(fname, DIGEST_XATTR, hash, hash.size(), 0)) {
|
||||||
|
HDEBUG("Failed to set " DIGEST_XATTR " xattr on" <<
|
||||||
|
fname.constData() << ":" << strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hash.size() == DIGEST_SIZE) {
|
||||||
iFileHash.insert(aPath, hash);
|
iFileHash.insert(aPath, hash);
|
||||||
iHashFile.insert(hash, aPath);
|
iHashFile.insert(hash, aPath);
|
||||||
|
}
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue