Commit 9ba77fdb authored by Gilles Caulier's avatar Gilles Caulier 🗼
Browse files

Maintenance Tool : Add Multi-core support for Metadata Synchronizer tool.

Now, metadata synchronization between database and files (and vis-versa) is multi-threaded and use multi-core CPU.
This do not freeze GUI as previous in previous versions and speed to process files is drasticaly increased.
CCBUGS: 289204
parent 14570c10
......@@ -1259,6 +1259,8 @@ IF(DIGIKAM_CAN_BE_COMPILED)
SET(libmaintenance_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/utilities/maintenance/imageinfojob.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/maintenance/imageinfoalbumsjob.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/maintenance/metadatatask.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/maintenance/metadatathread.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/maintenance/metadatasynchronizer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/maintenance/duplicatesfinder.cpp
${CMAKE_CURRENT_SOURCE_DIR}/utilities/maintenance/newitemsfinder.cpp
......
......@@ -38,9 +38,8 @@
// Local includes
#include "albummanager.h"
#include "collectionscanner.h"
#include "imageinfojob.h"
#include "metadatahub.h"
#include "metadatathread.h"
namespace Digikam
{
......@@ -51,22 +50,20 @@ class MetadataSynchronizer::Private
public:
Private() :
imageInfoIndex(0),
imageInfoJob(0),
thread(0),
direction(MetadataSynchronizer::WriteFromDatabaseToFile)
{
}
int imageInfoIndex;
AlbumList palbumList;
AlbumList::Iterator albumsIt;
ImageInfoJob* imageInfoJob;
ImageInfoList imageInfoList;
CollectionScanner scanner;
MetadataThread* thread;
MetadataSynchronizer::SyncDirection direction;
};
......@@ -80,7 +77,7 @@ MetadataSynchronizer::MetadataSynchronizer(const AlbumList& list, SyncDirection
else
d->palbumList = list;
d->direction = direction;
init(direction);
}
MetadataSynchronizer::MetadataSynchronizer(const ImageInfoList& list, SyncDirection direction, ProgressItem* const parent)
......@@ -88,11 +85,23 @@ MetadataSynchronizer::MetadataSynchronizer(const ImageInfoList& list, SyncDirect
d(new Private)
{
d->imageInfoList = list;
d->direction = direction;
init(direction);
}
// Common methods ----------------------------------------------------------------------------
void MetadataSynchronizer::init(SyncDirection direction)
{
d->direction = direction;
d->thread = new MetadataThread(this);
connect(d->thread, SIGNAL(signalCompleted()),
this, SLOT(slotDone()));
connect(d->thread, SIGNAL(signalAdvance()),
this, SLOT(slotAdvance()));
}
void MetadataSynchronizer::slotStart()
{
MaintenanceTool::slotStart();
......@@ -122,6 +131,7 @@ MetadataSynchronizer::~MetadataSynchronizer()
void MetadataSynchronizer::slotCancel()
{
d->imageInfoJob->stop();
d->thread->cancel();
MaintenanceTool::slotCancel();
}
......@@ -180,36 +190,14 @@ void MetadataSynchronizer::parseList()
setTotalItems(d->imageInfoList.count());
while (d->imageInfoIndex != d->imageInfoList.size() && !canceled())
{
parsePicture();
kapp->processEvents();
}
MaintenanceTool::slotDone();
d->thread->setUseMultiCore(true);
d->thread->processItems(d->imageInfoList, d->direction);
d->thread->start();
}
// TODO : use multithreading to process this method.
void MetadataSynchronizer::parsePicture()
void MetadataSynchronizer::slotAdvance()
{
ImageInfo info = d->imageInfoList.at(d->imageInfoIndex);
MetadataHub fileHub;
if (d->direction == WriteFromDatabaseToFile)
{
// read in from database
fileHub.load(info);
// write out to file DMetadata
fileHub.write(info.filePath());
}
else
{
d->scanner.scanFile(info, CollectionScanner::Rescan);
}
advance(1);
d->imageInfoIndex++;
}
} // namespace Digikam
......@@ -64,11 +64,13 @@ private Q_SLOTS:
void slotStart();
void slotParseAlbums();
void slotAlbumParsed(const ImageInfoList&);
void slotAdvance();
void slotOneAlbumIsComplete();
void slotCancel();
private:
void init(SyncDirection direction);
void parseList();
void parsePicture();
void processOneAlbum();
......
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2013-08-09
* Description : Thread actions task for metadata synchronizer.
*
* Copyright (C) 2013 by Gilles Caulier <caulier dot gilles at gmail dot com>
*
* 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, 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.
*
* ============================================================ */
#include "metadatatask.moc"
// KDE includes
#include <kdebug.h>
#include <threadweaver/ThreadWeaver.h>
// Local includes
#include "collectionscanner.h"
#include "metadatahub.h"
#include "imageinfo.h"
namespace Digikam
{
class MetadataTask::Private
{
public:
Private()
{
cancel = false;
direction = MetadataSynchronizer::WriteFromDatabaseToFile;
}
bool cancel;
ImageInfo item;
MetadataSynchronizer::SyncDirection direction;
};
// -------------------------------------------------------
MetadataTask::MetadataTask()
: Job(0), d(new Private)
{
}
MetadataTask::~MetadataTask()
{
slotCancel();
delete d;
}
void MetadataTask::setItem(const ImageInfo& item, MetadataSynchronizer::SyncDirection dir)
{
d->item = item;
d->direction = dir;
}
void MetadataTask::slotCancel()
{
d->cancel = true;
}
void MetadataTask::run()
{
if(d->cancel)
{
return;
}
if (d->direction == MetadataSynchronizer::WriteFromDatabaseToFile)
{
MetadataHub fileHub;
// read in from database
fileHub.load(d->item);
// write out to file DMetadata
fileHub.write(d->item.filePath());
}
else // MetadataSynchronizer::ReadFromFileToDatabase
{
CollectionScanner scanner;
scanner.scanFile(d->item, CollectionScanner::Rescan);
}
emit signalFinished();
}
} // namespace Digikam
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2013-08-09
* Description : Thread actions task for metadata synchronizer.
*
* Copyright (C) 2013 by Gilles Caulier <caulier dot gilles at gmail dot com>
*
* 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, 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.
*
* ============================================================ */
#ifndef METADATA_TASK_H
#define METADATA_TASK_H
// Qt includes
#include <QThread>
// KDE includes
#include <threadweaver/Job.h>
// Local includes
#include "imageinfo.h"
#include "metadatasynchronizer.h"
using namespace ThreadWeaver;
namespace Digikam
{
class MetadataTask : public Job
{
Q_OBJECT
public:
MetadataTask();
~MetadataTask();
void setItem(const ImageInfo& item, MetadataSynchronizer::SyncDirection dir);
Q_SIGNALS:
void signalFinished();
public Q_SLOTS:
void slotCancel();
protected:
void run();
private:
class Private;
Private* const d;
};
} // namespace Digikam
#endif /* METADATA_TASK_H */
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2013-08-09
* Description : Thread actions manager for metadata synchronizer.
*
* Copyright (C) 2013 by Gilles Caulier <caulier dot gilles at gmail dot com>
*
* 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, 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.
*
* ============================================================ */
#include "metadatathread.moc"
// KDE includes
#include <kdebug.h>
#include <threadweaver/JobCollection.h>
#include <solid/device.h>
// Local includes
#include "config-digikam.h"
#include "metadatatask.h"
using namespace Solid;
namespace Digikam
{
class MetadataThread::Private
{
public:
Private()
{
}
};
// --------------------------------------------------------------------------------------
MetadataThread::MetadataThread(QObject* const parent)
: RActionThreadBase(parent), d(new Private)
{
connect(this, SIGNAL(finished()),
this, SLOT(slotThreadFinished()));
}
MetadataThread::~MetadataThread()
{
cancel();
wait();
delete d;
}
void MetadataThread::setUseMultiCore(const bool b)
{
if (!b)
{
setMaximumNumberOfThreads(1);
}
else
{
setMaximumNumberOfThreads(qMax(Device::listFromType(DeviceInterface::Processor).count(), 1));
}
}
void MetadataThread::processItems(const ImageInfoList& items, MetadataSynchronizer::SyncDirection dir)
{
JobCollection* const collection = new JobCollection();
for(int i=0; i < items.size(); i++)
{
MetadataTask* const t = new MetadataTask();
t->setItem(items.at(i), dir);
connect(t, SIGNAL(signalFinished()),
this, SIGNAL(signalAdvance()));
connect(this, SIGNAL(signalCanceled()),
t, SLOT(slotCancel()), Qt::QueuedConnection);
collection->addJob(t);
}
appendJob(collection);
}
void MetadataThread::cancel()
{
if (isRunning())
emit signalCanceled();
RActionThreadBase::cancel();
}
void MetadataThread::slotThreadFinished()
{
if (isEmpty())
{
kDebug() << "List of Pending Jobs is empty";
emit signalCompleted();
}
}
} // namespace Digikam
/* ============================================================
*
* This file is a part of digiKam project
* http://www.digikam.org
*
* Date : 2013-08-09
* Description : Thread actions manager for metadata synchronizer.
*
* Copyright (C) 2013 by Gilles Caulier <caulier dot gilles at gmail dot com>
*
* 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, 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.
*
* ============================================================ */
#ifndef METADATA_THREAD_H
#define METADATA_THREAD_H
// Libkdcraw includes
#include <libkdcraw/ractionthreadbase.h>
// Local includes
#include "metadatasynchronizer.h"
#include "imageinfo.h"
using namespace KDcrawIface;
namespace Digikam
{
class MetadataThread : public RActionThreadBase
{
Q_OBJECT
public:
explicit MetadataThread(QObject* const parent);
~MetadataThread();
void setUseMultiCore(const bool b);
void processItems(const ImageInfoList& items, MetadataSynchronizer::SyncDirection dir);
void cancel();
Q_SIGNALS:
/** Emit when an item have been processed.
*/
void signalAdvance();
/** Emit when a items list have been fully processed.
*/
void signalCompleted();
/** Signal to emit to sub-tasks to cancel processing.
*/
void signalCanceled();
private Q_SLOTS:
void slotThreadFinished();
private:
class Private;
Private* const d;
};
} // namespace Digikam
#endif /* METADATA_THREAD_H */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment