File indexing completed on 2025-01-26 05:00:55

0001 /*
0002  *   SPDX-FileCopyrightText: 2011, 2012 Ivan Cukic <ivan.cukic(at)kde.org>
0003  *
0004  *   SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 // Self
0008 #include "ResourceScoreMaintainer.h"
0009 
0010 // Qt
0011 #include <QList>
0012 
0013 // System
0014 #include <unistd.h>
0015 
0016 // Utils
0017 #include <utils/d_ptr_implementation.h>
0018 #include <utils/for_each_assoc.h>
0019 
0020 // Local
0021 #include "ResourceScoreCache.h"
0022 #include "StatsPlugin.h"
0023 
0024 class ResourceScoreMaintainer::Private
0025 {
0026 public:
0027     Private()
0028     {
0029     }
0030 
0031     ~Private();
0032 
0033     typedef QString ApplicationName;
0034     typedef QString ActivityID;
0035     typedef QList<QString> ResourceList;
0036 
0037     typedef QHash<ApplicationName, ResourceList> Applications;
0038     typedef QHash<ActivityID, Applications> ResourceTree;
0039 
0040     ResourceTree scheduledResources;
0041 
0042     void processActivity(const ActivityID &activity, const Applications &applications);
0043 
0044     void processResources();
0045 
0046     QTimer processResourcesTimer;
0047 };
0048 
0049 ResourceScoreMaintainer::Private::~Private()
0050 {
0051 }
0052 
0053 void ResourceScoreMaintainer::Private::processResources()
0054 {
0055     using namespace kamd::utils;
0056 
0057     // initial delay before processing the resources
0058     sleep(1);
0059 
0060     ResourceTree resources;
0061 
0062     std::swap(resources, scheduledResources);
0063 
0064     const auto activity = StatsPlugin::self()->currentActivity();
0065 
0066     // Let us first process the events related to the current
0067     // activity so that the stats are available quicker
0068 
0069     if (resources.contains(activity)) {
0070         processActivity(activity, resources[activity]);
0071         resources.remove(activity);
0072     }
0073 
0074     for_each_assoc(resources, [this](const ActivityID &activity, const Applications &applications) {
0075         processActivity(activity, applications);
0076     });
0077 }
0078 
0079 void ResourceScoreMaintainer::Private::processActivity(const ActivityID &activity, const Applications &applications)
0080 {
0081     using namespace kamd::utils;
0082 
0083     for_each_assoc(applications, [&](const ApplicationName &application, const ResourceList &resources) {
0084         for (const auto &resource : resources) {
0085             ResourceScoreCache(activity, application, resource).update();
0086         }
0087     });
0088 }
0089 
0090 ResourceScoreMaintainer *ResourceScoreMaintainer::self()
0091 {
0092     static ResourceScoreMaintainer instance;
0093     return &instance;
0094 }
0095 
0096 ResourceScoreMaintainer::ResourceScoreMaintainer()
0097 {
0098     d->processResourcesTimer.setInterval(1000);
0099     d->processResourcesTimer.setSingleShot(true);
0100     connect(&d->processResourcesTimer, &QTimer::timeout, this, [this] {
0101         d->processResources();
0102     });
0103 }
0104 
0105 ResourceScoreMaintainer::~ResourceScoreMaintainer()
0106 {
0107 }
0108 
0109 void ResourceScoreMaintainer::processResource(const QString &resource, const QString &application)
0110 {
0111     // Checking whether the item is already scheduled for
0112     // processing
0113 
0114     const auto activity = StatsPlugin::self()->currentActivity();
0115 
0116     Q_ASSERT_X(!application.isEmpty(), "ResourceScoreMaintainer::processResource", "Agent should not be empty");
0117     Q_ASSERT_X(!resource.isEmpty(), "ResourceScoreMaintainer::processResource", "Resource should not be empty");
0118 
0119     if (d->scheduledResources.contains(activity) && d->scheduledResources[activity].contains(application)
0120         && d->scheduledResources[activity][application].contains(resource)) {
0121         // Nothing
0122 
0123     } else {
0124         d->scheduledResources[activity][application] << resource;
0125     }
0126 
0127     d->processResourcesTimer.start();
0128 }