Changeset View
Changeset View
Standalone View
Standalone View
src/akonadicontrol/agentmanager.cpp
Show First 20 Lines • Show All 98 Lines • ▼ Show 20 Line(s) | |||||
99 | 99 | | |||
100 | AgentManager::AgentManager(bool verbose, QObject *parent) | 100 | AgentManager::AgentManager(bool verbose, QObject *parent) | ||
101 | : QObject(parent) | 101 | : QObject(parent) | ||
102 | , mAgentServer(nullptr) | 102 | , mAgentServer(nullptr) | ||
103 | , mVerbose(verbose) | 103 | , mVerbose(verbose) | ||
104 | { | 104 | { | ||
105 | new AgentManagerAdaptor(this); | 105 | new AgentManagerAdaptor(this); | ||
106 | new AgentManagerInternalAdaptor(this); | 106 | new AgentManagerInternalAdaptor(this); | ||
107 | QDBusConnection::sessionBus().registerObject(QStringLiteral("/AgentManager"), this); | | |||
108 | 107 | | |||
109 | connect(QDBusConnection::sessionBus().interface(), &QDBusConnectionInterface::serviceOwnerChanged, | 108 | auto bus = QDBusConnection::sessionBus(); | ||
110 | this, &AgentManager::serviceOwnerChanged); | 109 | bus.registerObject(QStringLiteral("/AgentManager"), this); | ||
111 | 110 | | |||
112 | if (QDBusConnection::sessionBus().interface()->isServiceRegistered(Akonadi::DBus::serviceName(Akonadi::DBus::Server))) { | 111 | mWatcher.setConnection(bus); | ||
112 | mWatcher.setWatchMode(QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration); | ||||
113 | mWatcher.addWatchedService(QStringLiteral("org.freedesktop.Akonadi*")); | ||||
114 | connect(&mWatcher, &QDBusServiceWatcher::serviceRegistered, | ||||
115 | this, [this](const QString &name) { | ||||
116 | qCDebug(AKONADICONTROL_LOG) << "Service" << name<< "registered"; | ||||
117 | if (checkServerIsOperational(name)) { | ||||
118 | continueStartup(); // Server is operational, start agents | ||||
119 | return; | ||||
120 | } | ||||
121 | | ||||
122 | const auto service = Akonadi::DBus::parseAgentServiceName(name); | ||||
123 | if (service.has_value()) { | ||||
124 | switch (service->agentType) { | ||||
125 | case Akonadi::DBus::Agent: | ||||
126 | registerAgentService(*service); | ||||
127 | break; | ||||
128 | case Akonadi::DBus::Resource: | ||||
129 | registerResourceService(*service); | ||||
130 | break; | ||||
131 | case Akonadi::DBus::Preprocessor: | ||||
132 | registerPreprocessorService(*service); | ||||
133 | break; | ||||
134 | case Akonadi::DBus::Unknown: | ||||
135 | break; | ||||
136 | } | ||||
137 | } | ||||
138 | }); | ||||
139 | connect(&mWatcher, &QDBusServiceWatcher::serviceUnregistered, | ||||
140 | this, [this](const QString &name) { | ||||
141 | qCDebug(AKONADICONTROL_LOG) << "Service" << name << "unregistered from bus"; | ||||
142 | const auto service = Akonadi::DBus::parseAgentServiceName(name); | ||||
143 | if (service.has_value()) { | ||||
144 | switch (service->agentType) { | ||||
145 | case Akonadi::DBus::Agent: | ||||
146 | case Akonadi::DBus::Resource: | ||||
147 | case Akonadi::DBus::Unknown: | ||||
148 | // We don't care those got lost | ||||
149 | break; | ||||
150 | case Akonadi::DBus::Preprocessor: | ||||
151 | unregisterPreprocessorService(*service); | ||||
152 | break; | ||||
153 | } | ||||
154 | } | ||||
155 | }); | ||||
156 | | ||||
157 | if (bus.interface()->isServiceRegistered(Akonadi::DBus::serviceName(Akonadi::DBus::Server))) { | ||||
113 | qFatal("akonadiserver already running!"); | 158 | qFatal("akonadiserver already running!"); | ||
114 | } | 159 | } | ||
115 | 160 | | |||
116 | const QSettings settings(Akonadi::StandardDirs::agentsConfigFile(Akonadi::StandardDirs::ReadOnly), QSettings::IniFormat); | 161 | const QSettings settings(Akonadi::StandardDirs::agentsConfigFile(Akonadi::StandardDirs::ReadOnly), QSettings::IniFormat); | ||
117 | mAgentServerEnabled = settings.value(QStringLiteral("AgentServer/Enabled"), enableAgentServerDefault).toBool(); | 162 | mAgentServerEnabled = settings.value(QStringLiteral("AgentServer/Enabled"), enableAgentServerDefault).toBool(); | ||
118 | 163 | | |||
119 | QStringList serviceArgs; | 164 | QStringList serviceArgs; | ||
120 | if (Akonadi::Instance::hasIdentifier()) { | 165 | if (Akonadi::Instance::hasIdentifier()) { | ||
▲ Show 20 Lines • Show All 511 Lines • ▼ Show 20 Line(s) | 676 | for (const AgentInstance::Ptr &instance : qAsConst(mAgentInstances)) { | |||
632 | file.beginGroup(instance->identifier()); | 677 | file.beginGroup(instance->identifier()); | ||
633 | file.setValue(QStringLiteral("AgentType"), instance->agentType()); | 678 | file.setValue(QStringLiteral("AgentType"), instance->agentType()); | ||
634 | file.endGroup(); | 679 | file.endGroup(); | ||
635 | } | 680 | } | ||
636 | 681 | | |||
637 | file.endGroup(); | 682 | file.endGroup(); | ||
638 | } | 683 | } | ||
639 | 684 | | |||
640 | void AgentManager::serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner) | 685 | void AgentManager::registerAgentService(const Akonadi::DBus::AgentService &service) | ||
641 | { | 686 | { | ||
642 | Q_UNUSED(oldOwner); | 687 | if (!mAgentInstances.contains(service.identifier)) { | ||
643 | // This is called by the D-Bus server when a service comes up, goes down or changes ownership for some reason | | |||
644 | // and this is where we "hook up" our different Agent interfaces. | | |||
645 | | ||||
646 | qCDebug(AKONADICONTROL_LOG) << "Service" << name << "owner changed from" << oldOwner << "to" << newOwner; | | |||
647 | | ||||
648 | if ((name == Akonadi::DBus::serviceName(Akonadi::DBus::Server) || name == Akonadi::DBus::serviceName(Akonadi::DBus::AgentServer)) && !newOwner.isEmpty()) { | | |||
649 | if (QDBusConnection::sessionBus().interface()->isServiceRegistered(Akonadi::DBus::serviceName(Akonadi::DBus::Server)) | | |||
650 | && (!mAgentServer || QDBusConnection::sessionBus().interface()->isServiceRegistered(Akonadi::DBus::serviceName(Akonadi::DBus::AgentServer)))) { | | |||
651 | // server is operational, start agents | | |||
652 | continueStartup(); | | |||
653 | } | | |||
654 | } | | |||
655 | | ||||
656 | const auto service = Akonadi::DBus::parseAgentServiceName(name); | | |||
657 | if (!service.has_value()) { | | |||
658 | return; | | |||
659 | } | | |||
660 | switch (service->agentType) { | | |||
661 | case Akonadi::DBus::Agent: { | | |||
662 | // An agent service went up or down | | |||
663 | if (newOwner.isEmpty()) { | | |||
664 | return; // It went down: we don't care here. | | |||
665 | } | | |||
666 | | ||||
667 | if (!mAgentInstances.contains(service->identifier)) { | | |||
668 | return; | 688 | return; | ||
669 | } | 689 | } | ||
670 | 690 | | |||
671 | const AgentInstance::Ptr instance = mAgentInstances.value(service->identifier); | 691 | const AgentInstance::Ptr instance = mAgentInstances.value(service.identifier); | ||
672 | const bool restarting = instance->hasAgentInterface(); | 692 | const bool restarting = instance->hasAgentInterface(); | ||
673 | if (!instance->obtainAgentInterface()) { | 693 | if (!instance->obtainAgentInterface()) { | ||
674 | return; | 694 | return; | ||
675 | } | 695 | } | ||
676 | 696 | | |||
677 | Q_ASSERT(mAgents.contains(instance->agentType())); | 697 | Q_ASSERT(mAgents.contains(instance->agentType())); | ||
678 | const bool isResource = mAgents.value(instance->agentType()).capabilities.contains(AgentType::CapabilityResource); | 698 | const bool isResource = mAgents.value(instance->agentType()).capabilities.contains(AgentType::CapabilityResource); | ||
679 | 699 | | |||
680 | if (!restarting && (!isResource || instance->hasResourceInterface())) { | 700 | if (!restarting && (!isResource || instance->hasResourceInterface())) { | ||
681 | Q_EMIT agentInstanceAdded(service->identifier); | 701 | Q_EMIT agentInstanceAdded(service.identifier); | ||
682 | } | 702 | } | ||
683 | | ||||
684 | break; | | |||
685 | } | | |||
686 | case Akonadi::DBus::Resource: { | | |||
687 | // A resource service went up or down | | |||
688 | if (newOwner.isEmpty()) { | | |||
689 | return; // It went down: we don't care here. | | |||
690 | } | 703 | } | ||
691 | 704 | | |||
692 | if (!mAgentInstances.contains(service->identifier)) { | 705 | void AgentManager::registerResourceService(const Akonadi::DBus::AgentService &service) | ||
706 | { | ||||
707 | if (!mAgentInstances.contains(service.identifier)) { | ||||
693 | return; | 708 | return; | ||
694 | } | 709 | } | ||
695 | 710 | | |||
696 | const AgentInstance::Ptr instance = mAgentInstances.value(service->identifier); | 711 | const AgentInstance::Ptr instance = mAgentInstances.value(service.identifier); | ||
697 | const bool restarting = instance->hasResourceInterface(); | 712 | const bool restarting = instance->hasResourceInterface(); | ||
698 | if (!instance->obtainResourceInterface()) { | 713 | if (!instance->obtainResourceInterface()) { | ||
699 | return; | 714 | return; | ||
700 | } | 715 | } | ||
701 | 716 | | |||
702 | if (!restarting && instance->hasAgentInterface()) { | 717 | if (!restarting && instance->hasAgentInterface()) { | ||
703 | Q_EMIT agentInstanceAdded(service->identifier); | 718 | Q_EMIT agentInstanceAdded(service.identifier); | ||
704 | } | 719 | } | ||
705 | | ||||
706 | break; | | |||
707 | } | 720 | } | ||
708 | case Akonadi::DBus::Preprocessor: { | | |||
709 | // A preprocessor service went up or down | | |||
710 | 721 | | |||
722 | void AgentManager::registerPreprocessorService(const Akonadi::DBus::AgentService &service) | ||||
723 | { | ||||
711 | // If the preprocessor is going up then the org.freedesktop.Akonadi.Agent.* interface | 724 | // If the preprocessor is going up then the org.freedesktop.Akonadi.Agent.* interface | ||
712 | // should be already up (as it's registered before the preprocessor one). | 725 | // should be already up (as it's registered before the preprocessor one). | ||
713 | // So if we don't know about the preprocessor as agent instance | 726 | // So if we don't know about the preprocessor as agent instance | ||
714 | // then it's not our preprocessor. | 727 | // then it's not our preprocessor. | ||
715 | 728 | | |||
716 | // If the preprocessor is going down then either the agent interface already | 729 | qCDebug(AKONADICONTROL_LOG) << "Preprocessor " << service.identifier << " is going up or down..."; | ||
717 | // went down (and it has been already unregistered on the manager side) | | |||
718 | // or it's still registered as agent and WE have to unregister it. | | |||
719 | // The order of interface deletions depends on Qt but we handle both cases. | | |||
720 | 730 | | |||
721 | // Check if we "know" about it. | 731 | // Check if we "know" about it. | ||
722 | qCDebug(AKONADICONTROL_LOG) << "Preprocessor " << service->identifier << " is going up or down..."; | 732 | if (!mAgentInstances.contains(service.identifier)) { | ||
723 | | ||||
724 | if (!mAgentInstances.contains(service->identifier)) { | | |||
725 | qCDebug(AKONADICONTROL_LOG) << "But it isn't registered as agent... not mine (anymore?)"; | 733 | qCDebug(AKONADICONTROL_LOG) << "But it isn't registered as agent... not mine (anymore?)"; | ||
726 | return; // not our agent (?) | 734 | return; // not our agent (?) | ||
727 | } | 735 | } | ||
728 | 736 | | |||
729 | org::freedesktop::Akonadi::PreprocessorManager preProcessorManager( | 737 | org::freedesktop::Akonadi::PreprocessorManager preProcessorManager( | ||
730 | Akonadi::DBus::serviceName(Akonadi::DBus::Server), | 738 | Akonadi::DBus::serviceName(Akonadi::DBus::Server), | ||
731 | QStringLiteral("/PreprocessorManager"), | 739 | QStringLiteral("/PreprocessorManager"), | ||
732 | QDBusConnection::sessionBus(), | 740 | QDBusConnection::sessionBus(), | ||
733 | this); | 741 | this); | ||
734 | 742 | | |||
735 | if (!preProcessorManager.isValid()) { | 743 | if (!preProcessorManager.isValid()) { | ||
736 | qCWarning(AKONADICONTROL_LOG) << "Could not connect to PreprocessorManager via D-Bus:" << preProcessorManager.lastError().message(); | 744 | qCWarning(AKONADICONTROL_LOG) << "Could not connect to PreprocessorManager via D-Bus:" << preProcessorManager.lastError().message(); | ||
737 | } else { | 745 | return; | ||
738 | if (newOwner.isEmpty()) { | 746 | } | ||
739 | // The preprocessor went down. Unregister it on server side. | | |||
740 | | ||||
741 | preProcessorManager.unregisterInstance(service->identifier); | | |||
742 | | ||||
743 | } else { | | |||
744 | | ||||
745 | // The preprocessor went up. Register it on server side. | | |||
746 | 747 | | |||
747 | if (!mAgentInstances.value(service->identifier)->obtainPreprocessorInterface()) { | 748 | if (!mAgentInstances.value(service.identifier)->obtainPreprocessorInterface()) { | ||
748 | // Hm.. couldn't hook up its preprocessor interface.. | 749 | // Hm.. couldn't hook up its preprocessor interface.. | ||
749 | // Make sure we don't have it in the preprocessor chain | 750 | // Make sure we don't have it in the preprocessor chain | ||
750 | qCWarning(AKONADICONTROL_LOG) << "Couldn't obtain preprocessor interface for instance" << service->identifier; | 751 | qCWarning(AKONADICONTROL_LOG) << "Couldn't obtain preprocessor interface for instance" << service.identifier; | ||
751 | 752 | preProcessorManager.unregisterInstance(service.identifier); | |||
752 | preProcessorManager.unregisterInstance(service->identifier); | | |||
753 | return; | 753 | return; | ||
754 | } | 754 | } | ||
755 | 755 | | |||
756 | qCDebug(AKONADICONTROL_LOG) << "Registering preprocessor instance" << service->identifier; | 756 | qCDebug(AKONADICONTROL_LOG) << "Registering preprocessor instance" << service.identifier; | ||
757 | 757 | | |||
758 | // Add to the preprocessor chain | 758 | // Add to the preprocessor chain | ||
759 | preProcessorManager.registerInstance(service->identifier); | 759 | preProcessorManager.registerInstance(service.identifier); | ||
760 | } | 760 | } | ||
761 | | ||||
762 | void AgentManager::unregisterPreprocessorService(const Akonadi::DBus::AgentService &service) | ||||
763 | { | ||||
764 | // If the preprocessor is going down then either the agent interface already | ||||
765 | // went down (and it has been already unregistered on the manager side) | ||||
766 | // or it's still registered as agent and WE have to unregister it. | ||||
767 | // The order of interface deletions depends on Qt but we handle both cases. | ||||
768 | | ||||
769 | org::freedesktop::Akonadi::PreprocessorManager preProcessorManager( | ||||
770 | Akonadi::DBus::serviceName(Akonadi::DBus::Server), | ||||
771 | QStringLiteral("/PreprocessorManager"), | ||||
772 | QDBusConnection::sessionBus(), | ||||
773 | this); | ||||
774 | | ||||
775 | if (!preProcessorManager.isValid()) { | ||||
776 | qCWarning(AKONADICONTROL_LOG) << "Could not connect to PreprocessorManager via D-Bus:" << preProcessorManager.lastError().message(); | ||||
777 | return; | ||||
778 | } | ||||
779 | // The preprocessor went down. Unregister it on server side. | ||||
780 | preProcessorManager.unregisterInstance(service.identifier); | ||||
761 | } | 781 | } | ||
762 | 782 | | |||
763 | break; | 783 | bool AgentManager::checkServerIsOperational(const QString &service) const | ||
784 | { | ||||
785 | const auto dbusInterface = QDBusConnection::sessionBus().interface(); | ||||
786 | const auto serverService = Akonadi::DBus::serviceName(Akonadi::DBus::Server); | ||||
787 | const auto agentServerService = Akonadi::DBus::serviceName(Akonadi::DBus::AgentServer); | ||||
788 | if (service == serverService || service == agentServerService) { | ||||
789 | if (dbusInterface->isServiceRegistered(serverService) && (!mAgentServer || dbusInterface->isServiceRegistered(agentServerService))) { | ||||
790 | return true; | ||||
764 | } | 791 | } | ||
765 | default: | | |||
766 | break; | | |||
767 | } | 792 | } | ||
793 | | ||||
794 | return false; | ||||
768 | } | 795 | } | ||
769 | 796 | | |||
770 | bool AgentManager::checkInstance(const QString &identifier) const | 797 | bool AgentManager::checkInstance(const QString &identifier) const | ||
771 | { | 798 | { | ||
772 | if (!mAgentInstances.contains(identifier)) { | 799 | if (!mAgentInstances.contains(identifier)) { | ||
773 | qCWarning(AKONADICONTROL_LOG) << "Agent instance with identifier " << identifier << " does not exist"; | 800 | qCWarning(AKONADICONTROL_LOG) << "Agent instance with identifier " << identifier << " does not exist"; | ||
774 | return false; | 801 | return false; | ||
775 | } | 802 | } | ||
▲ Show 20 Lines • Show All 121 Lines • Show Last 20 Lines |