added mutex/locker for repositories
This commit is contained in:
parent
d341229f41
commit
5f95fd790a
|
@ -572,10 +572,14 @@ const QJsonObject &Manager::basicRepoInfo() const
|
|||
QMutexLocker locker(&m_basicRepoInfoMutex);
|
||||
if(m_basicRepoInfo.isEmpty()) {
|
||||
// add local data base
|
||||
m_basicRepoInfo.insert(localDataBase()->name(), localDataBase()->basicInfo());
|
||||
{
|
||||
QReadLocker locker(localDataBase()->lock());
|
||||
m_basicRepoInfo.insert(localDataBase()->name(), localDataBase()->basicInfo());
|
||||
}
|
||||
// add sync data bases
|
||||
for(const auto &syncDb : syncDatabases()) {
|
||||
// check if the "sync" database is actually used for syncing
|
||||
QReadLocker locker(syncDb.second->lock());
|
||||
auto usage = syncDb.second->usage();
|
||||
if((usage & ALPM_DB_USAGE_SYNC) || (usage & ALPM_DB_USAGE_INSTALL) || (usage & ALPM_DB_USAGE_UPGRADE)) {
|
||||
m_basicRepoInfo.insert(syncDb.first, syncDb.second->basicInfo());
|
||||
|
@ -585,6 +589,7 @@ const QJsonObject &Manager::basicRepoInfo() const
|
|||
}
|
||||
// add AUR
|
||||
if(userRepository()) {
|
||||
QReadLocker locker(userRepository()->lock());
|
||||
m_basicRepoInfo.insert(userRepository()->name(), userRepository()->basicInfo());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ PackageInfoLookup::PackageInfoLookup(Manager &manager, const QJsonObject &reques
|
|||
}
|
||||
}
|
||||
if(!packagesToBeRequested.isEmpty()) {
|
||||
QReadLocker locker(repo->lock());
|
||||
if(const auto *reply = (m_part & Manager::Details ? repo->requestFullPackageInfo(packagesToBeRequested) : repo->requestPackageInfo(packagesToBeRequested))) {
|
||||
connect(reply, &PackageReply::resultsAvailable, this, &PackageInfoLookup::addResultsFromReply);
|
||||
++m_remainingReplies;
|
||||
|
@ -69,7 +70,7 @@ void PackageInfoLookup::addResultsDirectly(const QStringList &packageNames, cons
|
|||
}
|
||||
bool avail = false;
|
||||
try {
|
||||
if(const auto &pkg = packages.at(packageName)) {
|
||||
if(const auto *pkg = packages.at(packageName)) {
|
||||
avail = true;
|
||||
if(m_part & Manager::Basics) {
|
||||
res.insert(QStringLiteral("basics"), pkg->basicInfo());
|
||||
|
@ -93,22 +94,22 @@ void PackageInfoLookup::addResultsFromReply()
|
|||
auto *reply = static_cast<PackageReply *>(sender());
|
||||
reply->deleteLater();
|
||||
if(reply->error().isEmpty()) {
|
||||
QReadLocker lock(reply->repository()->lock());
|
||||
addResultsDirectly(reply->requestedPackages(), reply->repository());
|
||||
if(!--m_remainingReplies) {
|
||||
emit resultsAvailable(m_what, m_id, m_results);
|
||||
deleteLater();
|
||||
}
|
||||
} else {
|
||||
// TODO: report error
|
||||
/*
|
||||
// TODO: bunch error messages together
|
||||
for(const auto &packageName : packageNames) {
|
||||
QJsonObject res;
|
||||
res.insert(QStringLiteral("name"), packageName);
|
||||
res.insert(QStringLiteral("repo"), repo->name());
|
||||
res.insert(QStringLiteral("error"), reply->error());
|
||||
m_results << res;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if(!--m_remainingReplies) {
|
||||
emit resultsAvailable(m_what, m_id, m_results);
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace RepoIndex
|
||||
|
|
|
@ -78,7 +78,8 @@ Repository::Repository(const QString &name, uint32 index, QObject *parent) :
|
|||
m_index(index),
|
||||
m_name(name),
|
||||
m_usage(static_cast<alpm_db_usage_t>(0)),
|
||||
m_sigLevel(static_cast<alpm_siglevel_t>(ALPM_SIGSTATUS_INVALID))
|
||||
m_sigLevel(static_cast<alpm_siglevel_t>(ALPM_SIGSTATUS_INVALID)),
|
||||
m_lock(QReadWriteLock::Recursive)
|
||||
{}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <QObject>
|
||||
#include <QFuture>
|
||||
#include <QJsonObject>
|
||||
#include <QReadWriteLock>
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
@ -82,6 +83,7 @@ class SuggestionsReply : public Reply
|
|||
Q_OBJECT
|
||||
public:
|
||||
SuggestionsReply(QNetworkReply *networkReply, const QString &term, Repository *repo);
|
||||
const Repository *repository() const;
|
||||
QJsonObject suggestions() const;
|
||||
|
||||
protected:
|
||||
|
@ -95,6 +97,11 @@ inline SuggestionsReply::SuggestionsReply(QNetworkReply *networkReply, const QSt
|
|||
m_repo(repo)
|
||||
{}
|
||||
|
||||
inline const Repository *SuggestionsReply::repository() const
|
||||
{
|
||||
return m_repo;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief The RepositoryType enum specifies the type of a repository object.
|
||||
*/
|
||||
|
@ -198,6 +205,9 @@ public:
|
|||
// parsing src/pkg info
|
||||
QList<Package *> addPackagesFromSrcInfo(const QByteArray &srcInfo);
|
||||
|
||||
// thread synchronization
|
||||
QReadWriteLock *lock() const;
|
||||
|
||||
static const uint32 invalidIndex = static_cast<uint32>(-1);
|
||||
|
||||
protected:
|
||||
|
@ -215,6 +225,9 @@ protected:
|
|||
QList<Repository *> m_upgradeSources;
|
||||
QString m_srcDir;
|
||||
QString m_pkgDir;
|
||||
|
||||
private:
|
||||
QReadWriteLock m_lock;
|
||||
};
|
||||
|
||||
/*!
|
||||
|
@ -401,6 +414,11 @@ inline bool Repository::isCachingUseful() const
|
|||
}
|
||||
}
|
||||
|
||||
inline QReadWriteLock *Repository::lock() const
|
||||
{
|
||||
return const_cast<QReadWriteLock *>(&m_lock);
|
||||
}
|
||||
|
||||
} // namespace PackageManagement
|
||||
|
||||
#endif // PACKAGEMANAGEMENT_PACKAGESOURCE_H
|
||||
|
|
|
@ -154,8 +154,11 @@ QStringList BuildOrderResolver::resolve(const StringVector &packages) const
|
|||
tasks << new TaskInfo(QString::fromLocal8Bit(pkgName.data()));
|
||||
}
|
||||
// find specified packages and their dependencies
|
||||
for(int i = 0, size = tasks.size(); i != size; ++i) {
|
||||
addDeps(tasks, tasks.at(i));
|
||||
//for(int i = 0, size = tasks.size(); i != size; ++i) {
|
||||
// addDeps(tasks, tasks.at(i));
|
||||
//}
|
||||
for(auto *task : tasks) {
|
||||
addDeps(tasks, task);
|
||||
}
|
||||
if(m_manager.config().isVerbose()) {
|
||||
cerr << shchar << "Relevant packages: ";
|
||||
|
|
|
@ -24,13 +24,13 @@ SuggestionsLookup::SuggestionsLookup(Manager &manager, const QJsonObject &reques
|
|||
if(m_errors.isEmpty()) {
|
||||
for(const auto &repoName : repos) {
|
||||
if(auto *repo = manager.repositoryByName(repoName.toString())) {
|
||||
QReadLocker locker(repo->lock());
|
||||
if(const auto *reply = repo->requestSuggestions(searchTerm)) {
|
||||
connect(reply, &SuggestionsReply::resultsAvailable, this, &SuggestionsLookup::addResults);
|
||||
++m_remainingReplies;
|
||||
} else {
|
||||
m_results << repo->suggestions(searchTerm);
|
||||
}
|
||||
|
||||
} else {
|
||||
m_errors << QStringLiteral("The specified repository \"%1\" does not exist.").arg(repoName.toString());
|
||||
}
|
||||
|
@ -44,7 +44,10 @@ void SuggestionsLookup::addResults()
|
|||
{
|
||||
assert(m_remainingReplies);
|
||||
auto *reply = static_cast<SuggestionsReply *>(sender());
|
||||
m_results << reply->suggestions();
|
||||
{
|
||||
QReadLocker locker(reply->repository()->lock());
|
||||
m_results << reply->suggestions();
|
||||
}
|
||||
reply->deleteLater();
|
||||
if(!--m_remainingReplies) {
|
||||
emit resultsAvailable(QStringLiteral("suggestions"), m_id, m_results);
|
||||
|
|
|
@ -42,6 +42,7 @@ QJsonObject UpgradeResult::toJson() const
|
|||
|
||||
/*!
|
||||
* \brief Constructs a new upgrade lookup process. The upgrade lookup process is started immediately.
|
||||
* \remarks \a upgradeLookup and \a upgradeSource musted be locked by caller
|
||||
*/
|
||||
UpgradeLookupProcess::UpgradeLookupProcess(UpgradeLookup *upgradeLookup, Repository *upgradeSource) :
|
||||
QObject(upgradeLookup),
|
||||
|
@ -51,19 +52,21 @@ UpgradeLookupProcess::UpgradeLookupProcess(UpgradeLookup *upgradeLookup, Reposit
|
|||
m_watcher(new QFutureWatcher<void>(this))
|
||||
{
|
||||
connect(this, &UpgradeLookupProcess::finished, upgradeLookup, &UpgradeLookup::processFinished);
|
||||
switch(m_upgradeSource->requestsRequired()) {
|
||||
case PackageDetailAvailability::Request:
|
||||
m_reply = m_upgradeSource->requestPackageInfo(m_toCheck->packageNames());
|
||||
break;
|
||||
case PackageDetailAvailability::FullRequest:
|
||||
m_reply = m_upgradeSource->requestFullPackageInfo(m_toCheck->packageNames());
|
||||
break;
|
||||
case PackageDetailAvailability::Never:
|
||||
m_results.errors << QStringLiteral("Repository \"%1\" does not provide the required information.").arg(m_upgradeSource->name());
|
||||
emit finished();
|
||||
return;
|
||||
case PackageDetailAvailability::Immediately:
|
||||
break;
|
||||
{
|
||||
switch(m_upgradeSource->requestsRequired()) {
|
||||
case PackageDetailAvailability::Request:
|
||||
m_reply = m_upgradeSource->requestPackageInfo(m_toCheck->packageNames());
|
||||
break;
|
||||
case PackageDetailAvailability::FullRequest:
|
||||
m_reply = m_upgradeSource->requestFullPackageInfo(m_toCheck->packageNames());
|
||||
break;
|
||||
case PackageDetailAvailability::Never:
|
||||
m_results.errors << QStringLiteral("Repository \"%1\" does not provide the required information.").arg(m_upgradeSource->name());
|
||||
emit finished();
|
||||
return;
|
||||
case PackageDetailAvailability::Immediately:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(m_reply) {
|
||||
m_reply->setParent(this);
|
||||
|
@ -76,7 +79,7 @@ UpgradeLookupProcess::UpgradeLookupProcess(UpgradeLookup *upgradeLookup, Reposit
|
|||
/*!
|
||||
* \brief Returns the results. Results are available, after the finished() signal has been emitted.
|
||||
*/
|
||||
const UpgradeLookupResults &UpgradeLookupProcess::results() const
|
||||
inline const UpgradeLookupResults &UpgradeLookupProcess::results() const
|
||||
{
|
||||
return m_results;
|
||||
}
|
||||
|
@ -101,6 +104,7 @@ void UpgradeLookupProcess::sourceReady()
|
|||
*/
|
||||
void UpgradeLookupProcess::checkUpgrades()
|
||||
{
|
||||
QReadLocker toCheckLocker(m_toCheck->lock()), srcLocker(m_upgradeSource->lock());
|
||||
m_toCheck->checkForUpgrades(m_results, QList<Repository *>() << m_upgradeSource);
|
||||
}
|
||||
|
||||
|
@ -171,10 +175,12 @@ UpgradeLookupJson::UpgradeLookupJson(Manager &manager, const QJsonObject &reques
|
|||
{
|
||||
const auto toCheckName = request.value(QStringLiteral("db")).toString();
|
||||
if((m_toCheck = manager.repositoryByName(toCheckName))) {
|
||||
QReadLocker toCheckLocker(m_toCheck->lock());
|
||||
// construct upgrade lookup processes
|
||||
const auto syncDbsArray = request.value(QStringLiteral("syncdbs")).toArray();
|
||||
if(syncDbsArray.isEmpty()) {
|
||||
for(auto *src : m_toCheck->upgradeSources()) {
|
||||
QReadLocker srcLocker(src->lock());
|
||||
new UpgradeLookupProcess(this, src);
|
||||
++m_remainingProcesses;
|
||||
}
|
||||
|
@ -182,6 +188,7 @@ UpgradeLookupJson::UpgradeLookupJson(Manager &manager, const QJsonObject &reques
|
|||
for(const auto &syncDbValue : syncDbsArray) {
|
||||
const auto syncDbName = syncDbValue.toString();
|
||||
if(auto *src = manager.repositoryByName(syncDbName)) {
|
||||
QReadLocker srcLocker(src->lock());
|
||||
new UpgradeLookupProcess(this, src);
|
||||
++m_remainingProcesses;
|
||||
} else {
|
||||
|
@ -273,8 +280,10 @@ UpgradeLookupCli::UpgradeLookupCli(Manager &manager, const string &repo, QObject
|
|||
cerr << shchar << "Checking upgrades for \"" << repo << "\" ..." << endl;
|
||||
const auto toCheckName = qstr(repo);
|
||||
if((m_toCheck = manager.repositoryByName(toCheckName))) {
|
||||
QReadLocker toCheckLocker(m_toCheck->lock());
|
||||
// construct upgrade lookup processes
|
||||
for(auto *src : m_toCheck->upgradeSources()) {
|
||||
QReadLocker srcLocker(src->lock());
|
||||
new UpgradeLookupProcess(this, src);
|
||||
++m_remainingProcesses;
|
||||
}
|
||||
|
|
|
@ -49,12 +49,10 @@ void AurPackageReply::processData()
|
|||
auto *reply = m_networkReplies.front();
|
||||
if(reply->error() == QNetworkReply::NoError) {
|
||||
QJsonParseError error;
|
||||
//QByteArray data = m_networkReply->readAll();
|
||||
//cerr << shchar << "AUR reply: " << data.data() << endl;
|
||||
//const QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
||||
const auto doc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
auto &packages = m_repo->packages();
|
||||
if(error.error == QJsonParseError::NoError) {
|
||||
QWriteLocker locker(m_repo->lock());
|
||||
auto &packages = m_repo->packages();
|
||||
for(const auto &result : doc.object().value(QStringLiteral("results")).toArray()) {
|
||||
QJsonObject obj = result.toObject();
|
||||
QString packageName = obj.value(QStringLiteral("Name")).toString();
|
||||
|
@ -68,10 +66,10 @@ void AurPackageReply::processData()
|
|||
}
|
||||
}
|
||||
} else {
|
||||
m_error = QStringLiteral("Error: Unable to parse JSON received from AUR: ") % error.errorString() % QStringLiteral(" at character ") % QString::number(error.offset);
|
||||
m_error = QStringLiteral("Unable to parse JSON received from AUR: ") % error.errorString() % QStringLiteral(" at character ") % QString::number(error.offset);
|
||||
}
|
||||
} else {
|
||||
m_error = QStringLiteral("Error: Unable to request data from AUR via AurJson: ") + reply->errorString();
|
||||
m_error = QStringLiteral("Unable to request data from AUR via AurJson: ") + reply->errorString();
|
||||
}
|
||||
emit resultsAvailable();
|
||||
}
|
||||
|
@ -112,6 +110,7 @@ void AurFullPackageReply::processData()
|
|||
}
|
||||
if(srcInfoEntry && srcInfoEntry->isFile()) {
|
||||
const auto srcInfo = static_cast<const KArchiveFile *>(srcInfoEntry)->data();
|
||||
QWriteLocker locker(m_userRepo->lock());
|
||||
const auto packages = m_userRepo->addPackagesFromSrcInfo(srcInfo);
|
||||
// TODO: error handling
|
||||
for(const auto &entryName : baseDir->entries()) {
|
||||
|
@ -129,13 +128,13 @@ void AurFullPackageReply::processData()
|
|||
}
|
||||
}
|
||||
} else {
|
||||
m_error = QStringLiteral("Error: Aur tarball does not contain \".SRCINFO\".");
|
||||
m_error = QStringLiteral("Aur tarball does not contain \".SRCINFO\".");
|
||||
}
|
||||
} else {
|
||||
m_error = QStringLiteral("Error: Unable to open tarball reply.");
|
||||
m_error = QStringLiteral("Unable to open tarball reply.");
|
||||
}
|
||||
} else {
|
||||
m_error = QStringLiteral("Error: Unable to request tarball from AUR: ") + reply->errorString();
|
||||
m_error = QStringLiteral("Unable to request tarball from AUR: ") + reply->errorString();
|
||||
}
|
||||
if(!m_error.isEmpty()) {
|
||||
qDebug() << m_error;
|
||||
|
@ -157,6 +156,7 @@ void AurSuggestionsReply::processData()
|
|||
//const QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
||||
const auto doc = QJsonDocument::fromJson(reply->readAll(), &error);
|
||||
if(error.error == QJsonParseError::NoError) {
|
||||
QWriteLocker locker(m_repo->lock());
|
||||
auto &packages = m_repo->packages();
|
||||
if(doc.isObject()) {
|
||||
for(const auto &result : doc.object().value(QStringLiteral("results")).toArray()) {
|
||||
|
@ -183,10 +183,10 @@ void AurSuggestionsReply::processData()
|
|||
}
|
||||
}
|
||||
} else {
|
||||
m_error = QStringLiteral("Error: Unable to parse JSON received from AUR: ") % error.errorString() % QStringLiteral(" at character ") % QString::number(error.offset);
|
||||
m_error = QStringLiteral("Unable to parse JSON received from AUR: ") % error.errorString() % QStringLiteral(" at character ") % QString::number(error.offset);
|
||||
}
|
||||
} else {
|
||||
m_error = QStringLiteral("Error: Unable to request data from AUR: ") + reply->errorString();
|
||||
m_error = QStringLiteral("Unable to request data from AUR: ") + reply->errorString();
|
||||
}
|
||||
emit resultsAvailable();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue