Protect access to image hash dictionaries with lock

Otherwise we step on our own feet when downloading several images,
like after import from divelogs.de with many linked images.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Robert C. Helling 2016-04-29 16:18:06 +02:00 committed by Dirk Hohndel
parent cae99471ad
commit 2e6588dc0e
2 changed files with 21 additions and 1 deletions

View file

@ -77,6 +77,8 @@ void ImageDownloader::saveImage(QNetworkReply *reply)
void loadPicture(struct picture *picture, bool fromHash) void loadPicture(struct picture *picture, bool fromHash)
{ {
if (!picture)
return;
ImageDownloader download(picture); ImageDownloader download(picture);
download.load(fromHash); download.load(fromHash);
} }

View file

@ -996,6 +996,7 @@ QHash <QString, QImage > thumbnailCache;
extern "C" char * hashstring(char * filename) extern "C" char * hashstring(char * filename)
{ {
QMutexLocker locker(&hashOfMutex);
return hashOf[QString(filename)].toHex().data(); return hashOf[QString(filename)].toHex().data();
} }
@ -1012,6 +1013,7 @@ extern "C" char *hashfile_name_string()
void read_hashes() void read_hashes()
{ {
QFile hashfile(hashfile_name()); QFile hashfile(hashfile_name());
QMutexLocker locker(&hashOfMutex);
if (hashfile.open(QIODevice::ReadOnly)) { if (hashfile.open(QIODevice::ReadOnly)) {
QDataStream stream(&hashfile); QDataStream stream(&hashfile);
stream >> localFilenameOf; stream >> localFilenameOf;
@ -1024,6 +1026,8 @@ void read_hashes()
void write_hashes() void write_hashes()
{ {
QSaveFile hashfile(hashfile_name()); QSaveFile hashfile(hashfile_name());
QMutexLocker locker(&hashOfMutex);
if (hashfile.open(QIODevice::WriteOnly)) { if (hashfile.open(QIODevice::WriteOnly)) {
QDataStream stream(&hashfile); QDataStream stream(&hashfile);
stream << localFilenameOf; stream << localFilenameOf;
@ -1064,8 +1068,16 @@ void learnHash(struct picture *picture, QByteArray hash)
picture->hash = strdup(hash.toHex()); picture->hash = strdup(hash.toHex());
} }
bool haveHash(QString &filename)
{
QMutexLocker locker(&hashOfMutex);
return hashOf.contains(filename);
}
QString localFilePath(const QString originalFilename) QString localFilePath(const QString originalFilename)
{ {
QMutexLocker locker(&hashOfMutex);
if (hashOf.contains(originalFilename) && localFilenameOf.contains(hashOf[originalFilename])) if (hashOf.contains(originalFilename) && localFilenameOf.contains(hashOf[originalFilename]))
return localFilenameOf[hashOf[originalFilename]]; return localFilenameOf[hashOf[originalFilename]];
else else
@ -1074,11 +1086,15 @@ QString localFilePath(const QString originalFilename)
QString fileFromHash(char *hash) QString fileFromHash(char *hash)
{ {
QMutexLocker locker(&hashOfMutex);
return localFilenameOf[QByteArray::fromHex(hash)]; return localFilenameOf[QByteArray::fromHex(hash)];
} }
// This needs to operate on a copy of picture as it frees it after finishing! // This needs to operate on a copy of picture as it frees it after finishing!
void updateHash(struct picture *picture) { void updateHash(struct picture *picture) {
if (!picture)
return;
QByteArray hash = hashFile(fileFromHash(picture->hash)); QByteArray hash = hashFile(fileFromHash(picture->hash));
learnHash(picture, hash); learnHash(picture, hash);
picture_free(picture); picture_free(picture);
@ -1087,6 +1103,8 @@ void updateHash(struct picture *picture) {
// This needs to operate on a copy of picture as it frees it after finishing! // This needs to operate on a copy of picture as it frees it after finishing!
void hashPicture(struct picture *picture) void hashPicture(struct picture *picture)
{ {
if (!picture)
return;
char *oldHash = copy_string(picture->hash); char *oldHash = copy_string(picture->hash);
learnHash(picture, hashFile(QString(picture->filename))); learnHash(picture, hashFile(QString(picture->filename)));
if (!same_string(picture->hash, "") && !same_string(picture->hash, oldHash)) if (!same_string(picture->hash, "") && !same_string(picture->hash, oldHash))
@ -1098,7 +1116,7 @@ void hashPicture(struct picture *picture)
extern "C" void cache_picture(struct picture *picture) extern "C" void cache_picture(struct picture *picture)
{ {
QString filename = picture->filename; QString filename = picture->filename;
if (!hashOf.contains(filename)) if (!haveHash(filename))
QtConcurrent::run(hashPicture, clone_picture(picture)); QtConcurrent::run(hashPicture, clone_picture(picture));
} }