File indexing completed on 2024-06-02 05:20:39
0001 /* 0002 SPDX-FileCopyrightText: 2013 Christian Mollekopf <mollekopf@kolabsys.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "gidmigrationjob.h" 0008 #include <Akonadi/CollectionFetchJob> 0009 #include <Akonadi/CollectionFetchScope> 0010 #include <Akonadi/ItemFetchJob> 0011 #include <Akonadi/ItemFetchScope> 0012 #include <Akonadi/ItemModifyJob> 0013 0014 using namespace Akonadi; 0015 0016 UpdateJob::UpdateJob(const Collection &col, QObject *parent) 0017 : Job(parent) 0018 , mCollection(col) 0019 , mModJobRunning(false) 0020 { 0021 } 0022 0023 UpdateJob::~UpdateJob() = default; 0024 0025 void UpdateJob::doStart() 0026 { 0027 auto fetchJob = new ItemFetchJob(mCollection, this); 0028 fetchJob->fetchScope().setCacheOnly(true); 0029 fetchJob->fetchScope().setIgnoreRetrievalErrors(true); 0030 fetchJob->fetchScope().setFetchModificationTime(false); 0031 fetchJob->fetchScope().setFetchRemoteIdentification(false); 0032 fetchJob->fetchScope().fetchFullPayload(true); 0033 // Limit scope to envelope only for mail 0034 connect(fetchJob, &ItemFetchJob::itemsReceived, this, &UpdateJob::itemsReceived); 0035 } 0036 0037 void UpdateJob::itemsReceived(const Akonadi::Item::List &items) 0038 { 0039 // We're queuing items rather than creating ItemModifyJobs directly due to memory concerns 0040 // I'm not sure if that would indeed be a problem (a ModifyJob shouldn't be much larger than the item) but we'd have to compare memory usage first when 0041 // creating large amounts of ItemModifyJobs. 0042 for (const Akonadi::Item &item : items) { 0043 mItemQueue.enqueue(item); 0044 } 0045 processNext(); 0046 } 0047 0048 void UpdateJob::slotResult(KJob *job) 0049 { 0050 // This slot is automatically called for all subjobs by KCompositeJob 0051 // FIXME the fetch job emits result before itemsReceived, because itemsReceived is triggered using the result signal (which is wrong IMO). See 0052 // ItemFetchJob::timeout If result was emitted at the end we could avoid having to call processNext in itemsReceived and locking it. 0053 auto const fetchJob = qobject_cast<ItemFetchJob *>(job); 0054 const bool fetchReturnedNoItems = fetchJob && fetchJob->items().isEmpty(); 0055 Job::slotResult(job); 0056 if (fetchReturnedNoItems) { 0057 emitResult(); 0058 } else if (!fetchJob) { 0059 mModJobRunning = false; 0060 if (!hasSubjobs()) { 0061 if (!processNext()) { 0062 emitResult(); 0063 } 0064 } 0065 } 0066 } 0067 0068 bool UpdateJob::processNext() 0069 { 0070 if (mModJobRunning || mItemQueue.isEmpty()) { 0071 return false; 0072 } 0073 const Akonadi::Item &item = mItemQueue.dequeue(); 0074 // Only the single item modifyjob updates the gid 0075 auto modJob = new ItemModifyJob(item, this); 0076 modJob->setUpdateGid(true); 0077 modJob->setIgnorePayload(true); 0078 mModJobRunning = true; 0079 return true; 0080 } 0081 0082 GidMigrationJob::GidMigrationJob(const QStringList &mimeTypeFilter, QObject *parent) 0083 : Job(parent) 0084 , mMimeTypeFilter(mimeTypeFilter) 0085 { 0086 } 0087 0088 GidMigrationJob::~GidMigrationJob() = default; 0089 0090 void GidMigrationJob::doStart() 0091 { 0092 auto fetchJob = new CollectionFetchJob(Collection::root(), CollectionFetchJob::Recursive, this); 0093 fetchJob->fetchScope().setContentMimeTypes(mMimeTypeFilter); 0094 connect(fetchJob, &CollectionFetchJob::collectionsReceived, this, &GidMigrationJob::collectionsReceived); 0095 connect(fetchJob, &CollectionFetchJob::result, this, &GidMigrationJob::collectionsFetched); 0096 } 0097 0098 void GidMigrationJob::collectionsReceived(const Collection::List &collections) 0099 { 0100 mCollections << collections; 0101 } 0102 0103 void GidMigrationJob::collectionsFetched(KJob *job) 0104 { 0105 // Errors are propagated by KCompositeJob 0106 if (!job->error()) { 0107 processCollection(); 0108 } 0109 } 0110 0111 void GidMigrationJob::processCollection() 0112 { 0113 if (mCollections.isEmpty()) { 0114 emitResult(); 0115 return; 0116 } 0117 const Collection col = mCollections.takeLast(); 0118 auto updateJob = new UpdateJob(col, this); 0119 connect(updateJob, &UpdateJob::result, this, &GidMigrationJob::itemsUpdated); 0120 } 0121 0122 void GidMigrationJob::itemsUpdated(KJob *job) 0123 { 0124 // Errors are propagated by KCompositeJob 0125 if (!job->error()) { 0126 processCollection(); 0127 } 0128 } 0129 0130 #include "moc_gidmigrationjob.cpp"