diff --git a/DB/ImageScout.h b/DB/ImageScout.h index bab794ba..8041561c 100644 --- a/DB/ImageScout.h +++ b/DB/ImageScout.h @@ -1,84 +1,84 @@ /* Copyright (C) 2018 Robert Krawitz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef IMAGESCOUT_H #define IMAGESCOUT_H #include "FileName.h" #include #include #include #include namespace DB { typedef QQueue ImageScoutQueue; -typedef void (*PreloadFunc)(const DB::FileName&); +typedef void (*PreloadFunc)(const DB::FileName &); class ImageScoutThread; /** * Scout thread for image loading: preload images from disk to have them in * RAM to mask I/O latency. */ class ImageScout { public: // count is an atomic variable containing the number of images // that have been loaded thus far. Used to prevent the scout from // getting too far ahead, if it's able to run faster than the // loader. Which usually it can't; with hard disks on any halfway // decent system, the loader can run faster than the disk. ImageScout(ImageScoutQueue &, QAtomicInt &count, int threads = 1); ~ImageScout(); // Specify scout buffer size. May not be called after starting the scout. void setBufSize(int); int getBufSize(); // Specify how far we're allowed to run ahead of the loader, in images. // May not be called after starting the scout. void setMaxSeekAhead(int); int getMaxSeekAhead(); // Specify how many bytes we read before moving on. // May not be called after starting the scout. void setReadLimit(int); int getReadLimit(); // Specify an alternate function to preload the file. // This function may perform useful work. Note that this is not // guaranteed to be called, so anything using this must be // prepared to do the work later. void setPreloadFunc(PreloadFunc); PreloadFunc getPreloadFunc(); // Start the scout running void start(); private: QMutex m_mutex; QList m_scoutList; QAtomicInt m_preloadedCount; QAtomicInt m_skippedCount; bool m_isStarted; int m_scoutBufSize; int m_maxSeekAhead; int m_readLimit; PreloadFunc m_preloadFunc; }; } #endif /* IMAGESCOUT_H */ // vi:expandtab:tabstop=4 shiftwidth=4: diff --git a/DB/MD5.cpp b/DB/MD5.cpp index bf2799ce..d6086eb2 100644 --- a/DB/MD5.cpp +++ b/DB/MD5.cpp @@ -1,143 +1,143 @@ /* Copyright (C) 2018 Johannes Zarl-Zierl Copyright (C) 2007-2010 Tuomas Suutari This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "MD5.h" #include "FileName.h" #include #include -#include #include +#include #include static QMutex s_MD5CacheMutex; static QHash s_MD5Cache; DB::MD5::MD5() : m_isNull(true) , m_v0(0) , m_v1(0) { } DB::MD5::MD5(const QString &md5str) : m_isNull(md5str.isEmpty()) , m_v0(md5str.left(16).toULongLong(0, 16)) , m_v1(md5str.mid(16, 16).toULongLong(0, 16)) { } bool DB::MD5::isNull() const { return m_isNull; } DB::MD5 &DB::MD5::operator=(const QString &md5str) { if (md5str.isEmpty()) { m_isNull = true; } else { m_isNull = false; m_v0 = md5str.left(16).toULongLong(0, 16); m_v1 = md5str.mid(16, 16).toULongLong(0, 16); } return *this; } QString DB::MD5::toHexString() const { QString res; static QChar ZERO(QChar::fromLatin1('0')); if (!isNull()) { res += QString::number(m_v0, 16).rightJustified(16, ZERO); res += QString::number(m_v1, 16).rightJustified(16, ZERO); } return res; } bool DB::MD5::operator==(const DB::MD5 &other) const { if (isNull() || other.isNull()) return isNull() == other.isNull(); return (m_v0 == other.m_v0 && m_v1 == other.m_v1); } bool DB::MD5::operator!=(const DB::MD5 &other) const { return !(*this == other); } bool DB::MD5::operator<(const DB::MD5 &other) const { if (isNull() || other.isNull()) return isNull() && !other.isNull(); return (m_v0 < other.m_v0 || (m_v0 == other.m_v0 && (m_v1 < other.m_v1))); } void DB::MD5::resetMD5Cache() { QMutexLocker locker(&s_MD5CacheMutex); s_MD5Cache.clear(); } namespace { // Determined experimentally to yield best results (on Seagate 2TB 2.5" disk, // 5400 RPM). Performance is very similar at 524288. Above that, performance // was significantly worse. Below that, performance also deteriorated. // This assumes use of one image scout thread (see DB/ImageScout.cpp). Without // a scout thread, performance was about 10-15% worse. constexpr int MD5_BUFFER_SIZE = 262144; } DB::MD5 DB::MD5Sum(const DB::FileName &fileName) { QMutexLocker locker(&s_MD5CacheMutex); if (s_MD5Cache.contains(fileName)) { return s_MD5Cache[fileName]; } locker.unlock(); // It's possible that the checksum will be added between now // and when we add it, but as long as the file contents don't change // during that interval, the checksums will match. // Holding the lock while the checksum is being computed will // defeat the whole purpose. DB::MD5 checksum; QFile file(fileName.absolute()); if (file.open(QIODevice::ReadOnly)) { QCryptographicHash md5calculator(QCryptographicHash::Md5); while (!file.atEnd()) { QByteArray md5Buffer(file.read(MD5_BUFFER_SIZE)); md5calculator.addData(md5Buffer); } file.close(); checksum = DB::MD5(QString::fromLatin1(md5calculator.result().toHex())); } locker.relock(); s_MD5Cache[fileName] = checksum; return checksum; } void DB::PreloadMD5Sum(const DB::FileName &fileName) { - (void) MD5Sum(fileName); + (void)MD5Sum(fileName); }