[DB] Added detection for duplicated audio files (mbid or checksum)

This commit is contained in:
emeric
2016-02-01 20:48:58 +01:00
parent e912b1bad7
commit b9a7707849
6 changed files with 65 additions and 1 deletions
+31 -1
View File
@@ -23,6 +23,7 @@
#include <boost/asio/placeholders.hpp>
#include "logger/Logger.hpp"
#include "utils/Utils.hpp"
#include "database/Types.hpp"
@@ -244,7 +245,9 @@ Updater::process(boost::system::error_code err)
LMS_LOG(DBUPDATER, INFO) << "Processing root directory '" << rootDirectory.path << "' DONE";
}
LMS_LOG(DBUPDATER, INFO) << "Scan complete. Changes = " << stats.nbChanges() << ", Errors = " << stats.nbScanErrors;
checkDuplicatedAudioFiles(stats);
LMS_LOG(DBUPDATER, INFO) << "Scan complete. Changes = " << stats.nbChanges() << "(added = " << stats.nbAdded << ", nbRemoved = " << stats.nbRemoved << ", nbModified = " << stats.nbModified << "), Errors = " << stats.nbScanErrors;
// Update database stats
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
@@ -394,6 +397,9 @@ Updater::processAudioFile( const boost::filesystem::path& file, Stats& stats)
if (!_metadataParser.parse(file, items))
return;
std::vector<unsigned char> checksum ;
computeCrc(file, checksum);
Wt::Dbo::Transaction transaction(_db.getSession());
Wt::Dbo::ptr<Track> track = Track::getByPath(_db.getSession(), file);
@@ -502,6 +508,7 @@ Updater::processAudioFile( const boost::filesystem::path& file, Stats& stats)
assert(track);
track.modify()->setChecksum(checksum);
track.modify()->setArtist(artist);
track.modify()->setRelease(release);
track.modify()->setLastWriteTime(lastWriteTime);
@@ -719,6 +726,29 @@ Updater::checkAudioFiles( Stats& stats )
LMS_LOG(DBUPDATER, INFO) << "Check audio files done!";
}
void
Updater::checkDuplicatedAudioFiles(Stats& stats)
{
LMS_LOG(DBUPDATER, INFO) << "Checking duplicated audio files";
Wt::Dbo::Transaction transaction(_db.getSession());
std::vector<Track::pointer> tracks = Database::Track::getMBIDDuplicates(_db.getSession());
for (Track::pointer track : tracks)
{
LMS_LOG(DBUPDATER, INFO) << "Found duplicated MBID [" << track->getMBID() << "], file: " << track->getPath() << " - " << track->getArtist()->getName() << " - " << track->getName();
}
tracks = Database::Track::getChecksumDuplicates(_db.getSession());
for (Track::pointer track : tracks)
{
LMS_LOG(DBUPDATER, INFO) << "Found duplicated checksum [" << bufferToString(track->getChecksum()) << "], file: " << track->getPath() << " - " << track->getArtist()->getName() << " - " << track->getName();
}
LMS_LOG(DBUPDATER, INFO) << "Checking duplicated audio files done!";
}
void
Updater::checkVideoFiles( Stats& stats )
{
+1
View File
@@ -84,6 +84,7 @@ class Updater
// Audio
void checkAudioFiles( Stats& stats );
void checkDuplicatedAudioFiles( Stats& stats );
void processAudioFile( const boost::filesystem::path& file, Stats& stats);
// Video
+15
View File
@@ -87,6 +87,20 @@ Track::getAllPaths(Wt::Dbo::Session& session)
return std::vector<boost::filesystem::path>(res.begin(), res.end());
}
std::vector<Track::pointer>
Track::getMBIDDuplicates(Wt::Dbo::Session& session)
{
Wt::Dbo::collection<pointer> res = session.query<pointer>( "SELECT track FROM track WHERE mbid in (SELECT mbid FROM track WHERE mbid <> '' GROUP BY mbid HAVING COUNT (*) > 1)").orderBy("track.mbid");
return std::vector<pointer>(res.begin(), res.end());
}
std::vector<Track::pointer>
Track::getChecksumDuplicates(Wt::Dbo::Session& session)
{
Wt::Dbo::collection<pointer> res = session.query<pointer>( "SELECT track FROM track WHERE checksum in (SELECT checksum FROM track WHERE Length(checksum) > 0 GROUP BY checksum HAVING COUNT(*) > 1)").orderBy("track.checksum");
return std::vector<pointer>(res.begin(), res.end());
}
std::vector< Genre::pointer >
Track::getGenres(void) const
{
@@ -167,6 +181,7 @@ Track::updateUIQueryModel(Wt::Dbo::Session& session, Wt::Dbo::QueryModel< UIQuer
}
Genre::Genre()
{
}
+3
View File
@@ -53,6 +53,7 @@ class Genre
static pointer getNone(Wt::Dbo::Session& session);
static std::vector<pointer> getByFilter(Wt::Dbo::Session& session, SearchFilter filter, int offset = -1, int size = -1);
static Wt::Dbo::collection<Genre::pointer> getAll(Wt::Dbo::Session& session);
// MVC models for the user interface
// Genre ID, name, track count
typedef boost::tuple<id_type, std::string, int> UIQueryResult;
@@ -106,6 +107,8 @@ class Track
static std::vector<pointer> getByFilter(Wt::Dbo::Session& session, SearchFilter filter, int offset = -1, int size = -1);
static Wt::Dbo::collection< pointer > getAll(Wt::Dbo::Session& session);
static std::vector<boost::filesystem::path> getAllPaths(Wt::Dbo::Session& session);
static std::vector<pointer> getMBIDDuplicates(Wt::Dbo::Session& session);
static std::vector<pointer> getChecksumDuplicates(Wt::Dbo::Session& session);
// Utility fonctions
// MVC models for the user interface
+12
View File
@@ -118,4 +118,16 @@ stringToUTF8(const std::string& str)
return boost::locale::conv::to_utf<char>(str, "UTF-8");
}
std::string
bufferToString(const std::vector<unsigned char>& data)
{
std::ostringstream oss;
for (unsigned char c : data)
{
oss << std::setw(2) << std::setfill('0') << std::hex << (int)c;
}
return oss.str();
}
+3
View File
@@ -44,6 +44,9 @@ stringTrim(const std::string& str, const std::string& whitespace = " \t");
std::string
stringToUTF8(const std::string& str);
std::string
bufferToString(const std::vector<unsigned char>& data);
template<typename T>
static inline bool readAs(const std::string& str, T& data)
{