mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Cleanup: Remove hash field from picture-structure
The hash field in the picture-structure was in principle non-operational. It was set on loading, but never actually changed. The authoritative hash comes from the filename->hash map. Therefore, make this explicit by removing the hash field from the picture structure. Instead of filling the picture structure on loading, add the hash directly to the filename->hash map. This is done in the register_hash() function, which does not overwrite old entries. I.e. the local hash has priority over the save-file. This policy might be refined in the future. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
e5dcd9fc16
commit
bdc470a80e
8 changed files with 61 additions and 46 deletions
|
@ -455,7 +455,6 @@ static void copy_pl(struct picture *sp, struct picture *dp)
|
||||||
{
|
{
|
||||||
*dp = *sp;
|
*dp = *sp;
|
||||||
dp->filename = copy_string(sp->filename);
|
dp->filename = copy_string(sp->filename);
|
||||||
dp->hash = copy_string(sp->hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy an element in a list of tags */
|
/* copy an element in a list of tags */
|
||||||
|
@ -3804,7 +3803,6 @@ void picture_free(struct picture *picture)
|
||||||
if (!picture)
|
if (!picture)
|
||||||
return;
|
return;
|
||||||
free(picture->filename);
|
free(picture->filename);
|
||||||
free(picture->hash);
|
|
||||||
free(picture);
|
free(picture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -412,7 +412,6 @@ struct dive_components {
|
||||||
/* picture list and methods related to dive picture handling */
|
/* picture list and methods related to dive picture handling */
|
||||||
struct picture {
|
struct picture {
|
||||||
char *filename;
|
char *filename;
|
||||||
char *hash;
|
|
||||||
offset_t offset;
|
offset_t offset;
|
||||||
degrees_t latitude;
|
degrees_t latitude;
|
||||||
degrees_t longitude;
|
degrees_t longitude;
|
||||||
|
|
|
@ -9,8 +9,9 @@
|
||||||
|
|
||||||
#include <QtConcurrent>
|
#include <QtConcurrent>
|
||||||
|
|
||||||
static QUrl cloudImageURL(const char *hash)
|
static QUrl cloudImageURL(const char *filename)
|
||||||
{
|
{
|
||||||
|
QString hash = hashString(filename);
|
||||||
return QUrl::fromUserInput(QString("https://cloud.subsurface-divelog.org/images/").append(hash));
|
return QUrl::fromUserInput(QString("https://cloud.subsurface-divelog.org/images/").append(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ ImageDownloader::~ImageDownloader()
|
||||||
|
|
||||||
void ImageDownloader::load(bool fromHash)
|
void ImageDownloader::load(bool fromHash)
|
||||||
{
|
{
|
||||||
if (fromHash && loadFromUrl(cloudImageURL(picture->hash)))
|
if (fromHash && loadFromUrl(cloudImageURL(picture->filename)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If loading from hash failed, try to load from filename
|
// If loading from hash failed, try to load from filename
|
||||||
|
@ -107,12 +108,11 @@ SHashedImage::SHashedImage(struct picture *picture) : QImage()
|
||||||
if (isNull()) {
|
if (isNull()) {
|
||||||
// This did not load anything. Let's try to get the image from other sources
|
// This did not load anything. Let's try to get the image from other sources
|
||||||
// Let's try to load it locally via its hash
|
// Let's try to load it locally via its hash
|
||||||
QString filename = fileFromHash(picture->hash);
|
QString filename = localFilePath(picture->filename);
|
||||||
if (filename.isNull())
|
|
||||||
filename = QString(picture->filename);
|
|
||||||
if (filename.isNull()) {
|
if (filename.isNull()) {
|
||||||
// That didn't produce a local filename.
|
// That didn't produce a local filename.
|
||||||
// Try the cloud server
|
// Try the cloud server
|
||||||
|
// TODO: This is dead code at the moment.
|
||||||
QtConcurrent::run(loadPicture, clone_picture(picture), true);
|
QtConcurrent::run(loadPicture, clone_picture(picture), true);
|
||||||
} else {
|
} else {
|
||||||
// Load locally from translated file name
|
// Load locally from translated file name
|
||||||
|
|
|
@ -50,10 +50,13 @@ static void save_picture_from_git(struct picture *picture)
|
||||||
struct picture_entry_list *pic_entry = pel;
|
struct picture_entry_list *pic_entry = pel;
|
||||||
|
|
||||||
while (pic_entry) {
|
while (pic_entry) {
|
||||||
if (same_string(pic_entry->hash, picture->hash)) {
|
char *hash = hashstring(picture->filename);
|
||||||
savePictureLocal(picture, pic_entry->data, pic_entry->len);
|
if (same_string(pic_entry->hash, hash)) {
|
||||||
|
savePictureLocal(picture, hash, pic_entry->data, pic_entry->len);
|
||||||
|
free(hash);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
free(hash);
|
||||||
pic_entry = pic_entry->next;
|
pic_entry = pic_entry->next;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "didn't find picture entry for %s\n", picture->filename);
|
fprintf(stderr, "didn't find picture entry for %s\n", picture->filename);
|
||||||
|
@ -971,7 +974,9 @@ static void parse_picture_hash(char *line, struct membuffer *str, void *_pic)
|
||||||
{
|
{
|
||||||
(void) line;
|
(void) line;
|
||||||
struct picture *pic = _pic;
|
struct picture *pic = _pic;
|
||||||
pic->hash = get_utf8(str);
|
char *hash = get_utf8(str);
|
||||||
|
register_hash(pic->filename, get_utf8(str));
|
||||||
|
free(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These need to be sorted! */
|
/* These need to be sorted! */
|
||||||
|
|
|
@ -1154,6 +1154,7 @@ static void gps_picture_location(char *buffer, struct picture *pic)
|
||||||
/* We're in the top-level dive xml. Try to convert whatever value to a dive value */
|
/* We're in the top-level dive xml. Try to convert whatever value to a dive value */
|
||||||
static void try_to_fill_dive(struct dive *dive, const char *name, char *buf)
|
static void try_to_fill_dive(struct dive *dive, const char *name, char *buf)
|
||||||
{
|
{
|
||||||
|
char *hash;
|
||||||
start_match("dive", name, buf);
|
start_match("dive", name, buf);
|
||||||
|
|
||||||
switch (import_source) {
|
switch (import_source) {
|
||||||
|
@ -1197,8 +1198,11 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf)
|
||||||
return;
|
return;
|
||||||
if (MATCH("gps.picture", gps_picture_location, cur_picture))
|
if (MATCH("gps.picture", gps_picture_location, cur_picture))
|
||||||
return;
|
return;
|
||||||
if (MATCH("hash.picture", utf8_string, &cur_picture->hash))
|
if (MATCH("hash.picture", utf8_string, &hash)) {
|
||||||
|
register_hash(cur_picture->filename, hash);
|
||||||
|
free(hash);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (MATCH("cylinderstartpressure", pressure, &dive->cylinder[0].start))
|
if (MATCH("cylinderstartpressure", pressure, &dive->cylinder[0].start))
|
||||||
return;
|
return;
|
||||||
if (MATCH("cylinderendpressure", pressure, &dive->cylinder[0].end))
|
if (MATCH("cylinderendpressure", pressure, &dive->cylinder[0].end))
|
||||||
|
|
|
@ -1075,10 +1075,20 @@ QMutex hashOfMutex;
|
||||||
QHash<QByteArray, QString> localFilenameOf;
|
QHash<QByteArray, QString> localFilenameOf;
|
||||||
QHash <QString, QImage > thumbnailCache;
|
QHash <QString, QImage > thumbnailCache;
|
||||||
|
|
||||||
extern "C" char * hashstring(const char *filename)
|
static QByteArray getHash(const QString &filename)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&hashOfMutex);
|
QMutexLocker locker(&hashOfMutex);
|
||||||
return strdup(hashOf[QString(filename)].toHex().data());
|
return hashOf[filename];
|
||||||
|
}
|
||||||
|
|
||||||
|
QString hashString(const char *filename)
|
||||||
|
{
|
||||||
|
return getHash(QString(filename)).toHex();
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" char * hashstring(const char *filename)
|
||||||
|
{
|
||||||
|
return strdup(qPrintable(hashString(filename)));
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString hashfile_name()
|
const QString hashfile_name()
|
||||||
|
@ -1136,6 +1146,21 @@ void add_hash(const QString &filename, const QByteArray &hash)
|
||||||
localFilenameOf[hash] = filename;
|
localFilenameOf[hash] = filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add hash if not already known
|
||||||
|
extern "C" void register_hash(const char *filename, const char *hash)
|
||||||
|
{
|
||||||
|
if (empty_string(filename) || empty_string(hash))
|
||||||
|
return;
|
||||||
|
QString filenameString(filename);
|
||||||
|
|
||||||
|
QMutexLocker locker(&hashOfMutex);
|
||||||
|
if (!hashOf.contains(filenameString)) {
|
||||||
|
QByteArray hashBuf = QByteArray::fromHex(hash);
|
||||||
|
hashOf[filename] = hashBuf;
|
||||||
|
localFilenameOf[hashBuf] = filenameString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray hashFile(const QString &filename)
|
QByteArray hashFile(const QString &filename)
|
||||||
{
|
{
|
||||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||||
|
@ -1174,22 +1199,14 @@ QString localFilePath(const QString &originalFilename)
|
||||||
return originalFilename;
|
return originalFilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString fileFromHash(const char *hash)
|
|
||||||
{
|
|
||||||
if (empty_string(hash))
|
|
||||||
return "";
|
|
||||||
QMutexLocker locker(&hashOfMutex);
|
|
||||||
|
|
||||||
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 hashPicture(struct picture *picture)
|
void hashPicture(struct picture *picture)
|
||||||
{
|
{
|
||||||
if (!picture)
|
if (!picture)
|
||||||
return;
|
return;
|
||||||
|
QByteArray oldHash = getHash(QString(picture->filename));
|
||||||
QByteArray hash = hashFile(localFilePath(picture->filename));
|
QByteArray hash = hashFile(localFilePath(picture->filename));
|
||||||
if (!hash.isNull() && !same_string(hash.toHex().data(), picture->hash))
|
if (!hash.isNull() && hash != oldHash)
|
||||||
mark_divelist_changed(true);
|
mark_divelist_changed(true);
|
||||||
picture_free(picture);
|
picture_free(picture);
|
||||||
}
|
}
|
||||||
|
@ -1230,23 +1247,16 @@ void learnImages(const QDir dir, int max_recursions)
|
||||||
|
|
||||||
extern "C" const char *local_file_path(struct picture *picture)
|
extern "C" const char *local_file_path(struct picture *picture)
|
||||||
{
|
{
|
||||||
QString hashString = picture->hash;
|
return strdup(qPrintable(localFilePath(picture->filename)));
|
||||||
if (hashString.isEmpty()) {
|
|
||||||
QByteArray hash = hashFile(picture->filename);
|
|
||||||
free(picture->hash);
|
|
||||||
picture->hash = strdup(hash.toHex().data());
|
|
||||||
}
|
|
||||||
QString localFileName = fileFromHash(picture->hash);
|
|
||||||
if (localFileName.isEmpty())
|
|
||||||
localFileName = picture->filename;
|
|
||||||
return strdup(qPrintable(localFileName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" bool picture_exists(struct picture *picture)
|
extern "C" bool picture_exists(struct picture *picture)
|
||||||
{
|
{
|
||||||
QString localFilename = fileFromHash(picture->hash);
|
QString localPath = localFilePath(picture->filename);
|
||||||
QByteArray hash = hashFile(localFilename);
|
if (localPath.isEmpty())
|
||||||
return same_string(hash.toHex().data(), picture->hash);
|
return false;
|
||||||
|
QByteArray hash = hashFile(localPath);
|
||||||
|
return !hash.isEmpty() && getHash(QString(picture->filename)) == hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString picturedir()
|
const QString picturedir()
|
||||||
|
@ -1262,19 +1272,19 @@ extern "C" char *picturedir_string()
|
||||||
/* when we get a picture from git storage (local or remote) and can't find the picture
|
/* when we get a picture from git storage (local or remote) and can't find the picture
|
||||||
* based on its hash, we create a local copy with the hash as filename and the appropriate
|
* based on its hash, we create a local copy with the hash as filename and the appropriate
|
||||||
* suffix */
|
* suffix */
|
||||||
extern "C" void savePictureLocal(struct picture *picture, const char *data, int len)
|
extern "C" void savePictureLocal(struct picture *picture, const char *hash, const char *data, int len)
|
||||||
{
|
{
|
||||||
QString dirname = picturedir();
|
QString dirname = picturedir();
|
||||||
QDir localPictureDir(dirname);
|
QDir localPictureDir(dirname);
|
||||||
localPictureDir.mkpath(dirname);
|
localPictureDir.mkpath(dirname);
|
||||||
QString suffix(picture->filename);
|
QString suffix(picture->filename);
|
||||||
suffix.replace(QRegularExpression(".*\\."), "");
|
suffix.replace(QRegularExpression(".*\\."), "");
|
||||||
QString filename(dirname + picture->hash + "." + suffix);
|
QString filename(dirname + hash + "." + suffix);
|
||||||
QSaveFile out(filename);
|
QSaveFile out(filename);
|
||||||
if (out.open(QIODevice::WriteOnly)) {
|
if (out.open(QIODevice::WriteOnly)) {
|
||||||
out.write(data, len);
|
out.write(data, len);
|
||||||
out.commit();
|
out.commit();
|
||||||
add_hash(filename, QByteArray::fromHex(picture->hash));
|
add_hash(filename, QByteArray::fromHex(hash));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,12 +34,12 @@ void read_hashes();
|
||||||
void write_hashes();
|
void write_hashes();
|
||||||
void updateHash(struct picture *picture);
|
void updateHash(struct picture *picture);
|
||||||
QByteArray hashFile(const QString &filename);
|
QByteArray hashFile(const QString &filename);
|
||||||
|
QString hashString(const char *filename);
|
||||||
void learnImages(const QDir dir, int max_recursions);
|
void learnImages(const QDir dir, int max_recursions);
|
||||||
void add_hash(const QString &filename, const QByteArray &hash);
|
void add_hash(const QString &filename, const QByteArray &hash);
|
||||||
void hashPicture(struct picture *picture);
|
void hashPicture(struct picture *picture);
|
||||||
extern "C" char *hashstring(const char *filename);
|
extern "C" char *hashstring(const char *filename);
|
||||||
QString localFilePath(const QString &originalFilename);
|
QString localFilePath(const QString &originalFilename);
|
||||||
QString fileFromHash(const char *hash);
|
|
||||||
void learnHash(const QString &originalName, const QString &localName, const QByteArray &hash);
|
void learnHash(const QString &originalName, const QString &localName, const QByteArray &hash);
|
||||||
weight_t string_to_weight(const char *str);
|
weight_t string_to_weight(const char *str);
|
||||||
depth_t string_to_depth(const char *str);
|
depth_t string_to_depth(const char *str);
|
||||||
|
@ -74,10 +74,11 @@ void subsurface_mkdir(const char *dir);
|
||||||
char *get_file_name(const char *fileName);
|
char *get_file_name(const char *fileName);
|
||||||
void copy_image_and_overwrite(const char *cfileName, const char *path, const char *cnewName);
|
void copy_image_and_overwrite(const char *cfileName, const char *path, const char *cnewName);
|
||||||
char *hashstring(const char *filename);
|
char *hashstring(const char *filename);
|
||||||
|
void register_hash(const char *filename, const char *hash);
|
||||||
bool picture_exists(struct picture *picture);
|
bool picture_exists(struct picture *picture);
|
||||||
char *move_away(const char *path);
|
char *move_away(const char *path);
|
||||||
const char *local_file_path(struct picture *picture);
|
const char *local_file_path(struct picture *picture);
|
||||||
void savePictureLocal(struct picture *picture, const char *data, int len);
|
void savePictureLocal(struct picture *picture, const char *hash, const char *data, int len);
|
||||||
void cache_picture(struct picture *picture);
|
void cache_picture(struct picture *picture);
|
||||||
char *cloud_url();
|
char *cloud_url();
|
||||||
char *hashfile_name_string();
|
char *hashfile_name_string();
|
||||||
|
|
|
@ -44,8 +44,6 @@ void TestPicture::addPicture()
|
||||||
QVERIFY(pic1->longitude.udeg == 11334500);
|
QVERIFY(pic1->longitude.udeg == 11334500);
|
||||||
QVERIFY(pic2->offset.seconds == 1321);
|
QVERIFY(pic2->offset.seconds == 1321);
|
||||||
|
|
||||||
QVERIFY(pic1->hash == NULL);
|
|
||||||
QVERIFY(pic2->hash == NULL);
|
|
||||||
QByteArray hash1 = hashFile(localFilePath(pic1->filename));
|
QByteArray hash1 = hashFile(localFilePath(pic1->filename));
|
||||||
QByteArray hash2 = hashFile(localFilePath(pic2->filename));
|
QByteArray hash2 = hashFile(localFilePath(pic2->filename));
|
||||||
learnHash(pic1->filename, PIC1_NAME, hash1);
|
learnHash(pic1->filename, PIC1_NAME, hash1);
|
||||||
|
@ -54,8 +52,8 @@ void TestPicture::addPicture()
|
||||||
QCOMPARE(hashstring(pic2->filename), PIC2_HASH);
|
QCOMPARE(hashstring(pic2->filename), PIC2_HASH);
|
||||||
QCOMPARE(hashstring(PIC1_NAME), PIC1_HASH);
|
QCOMPARE(hashstring(PIC1_NAME), PIC1_HASH);
|
||||||
QCOMPARE(hashstring(PIC2_NAME), PIC2_HASH);
|
QCOMPARE(hashstring(PIC2_NAME), PIC2_HASH);
|
||||||
QCOMPARE(fileFromHash(PIC1_HASH), QString(PIC1_NAME));
|
QCOMPARE(localFilePath(pic1->filename), QString(PIC1_NAME));
|
||||||
QCOMPARE(fileFromHash(PIC2_HASH), QString(PIC2_NAME));
|
QCOMPARE(localFilePath(pic2->filename), QString(PIC2_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue