ctkManagedServiceTracker.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*=============================================================================
  2. Library: CTK
  3. Copyright (c) German Cancer Research Center,
  4. Division of Medical and Biological Informatics
  5. Licensed under the Apache License, Version 2.0 (the "License");
  6. you may not use this file except in compliance with the License.
  7. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. =============================================================================*/
  15. #include "ctkManagedServiceTracker_p.h"
  16. #include <service/cm/ctkConfigurationException.h>
  17. #include <service/log/ctkLogService.h>
  18. #include "ctkConfigurationImpl_p.h"
  19. #include "ctkConfigurationAdminFactory_p.h"
  20. #include <QRunnable>
  21. ctkManagedServiceTracker::ctkManagedServiceTracker(ctkConfigurationAdminFactory* configurationAdminFactory,
  22. ctkConfigurationStore* configurationStore,
  23. ctkPluginContext* context)
  24. : ctkServiceTracker<ctkManagedService*>(context),
  25. context(context),
  26. configurationAdminFactory(configurationAdminFactory),
  27. configurationStoreMutex(QMutex::Recursive),
  28. configurationStore(configurationStore),
  29. queue("ctkManagedService Update Queue")
  30. {
  31. }
  32. ctkManagedService* ctkManagedServiceTracker::addingService(const ctkServiceReference& reference)
  33. {
  34. QString pid = reference.getProperty(ctkPluginConstants::SERVICE_PID).toString();
  35. if (pid.isEmpty())
  36. return 0;
  37. ctkManagedService* service = context->getService<ctkManagedService>(reference);
  38. if (service == 0)
  39. return 0;
  40. {
  41. QMutexLocker lock(&configurationStoreMutex);
  42. addManagedService(reference, pid, service);
  43. }
  44. return service;
  45. }
  46. void ctkManagedServiceTracker::modifiedService(const ctkServiceReference& reference, ctkManagedService* service)
  47. {
  48. QString pid = reference.getProperty(ctkPluginConstants::SERVICE_PID).toString();
  49. {
  50. QMutexLocker lock(&configurationStoreMutex);
  51. if (getManagedService(pid) == service)
  52. return;
  53. QString previousPid = getPidForManagedService(service);
  54. removeManagedService(reference, previousPid);
  55. addingService(reference);
  56. }
  57. }
  58. void ctkManagedServiceTracker::removedService(const ctkServiceReference& reference, ctkManagedService* service)
  59. {
  60. Q_UNUSED(service)
  61. QString pid = reference.getProperty(ctkPluginConstants::SERVICE_PID).toString();
  62. {
  63. QMutexLocker lock(&configurationStoreMutex);
  64. removeManagedService(reference, pid);
  65. }
  66. context->ungetService(reference);
  67. }
  68. void ctkManagedServiceTracker::notifyDeleted(ctkConfigurationImpl* config)
  69. {
  70. config->checkLocked();
  71. QString pid = config->getPid(false);
  72. ctkServiceReference reference = getManagedServiceReference(pid);
  73. if (reference && config->bind(reference.getPlugin()))
  74. asynchUpdated(getManagedService(pid), ctkDictionary());
  75. }
  76. void ctkManagedServiceTracker::notifyUpdated(ctkConfigurationImpl* config) {
  77. config->checkLocked();
  78. QString pid = config->getPid();
  79. ctkServiceReference reference = getManagedServiceReference(pid);
  80. if (reference && config->bind(reference.getPlugin()))
  81. {
  82. ctkDictionary properties = config->getProperties();
  83. configurationAdminFactory->modifyConfiguration(reference, properties);
  84. asynchUpdated(getManagedService(pid), properties);
  85. }
  86. }
  87. void ctkManagedServiceTracker::addManagedService(const ctkServiceReference& reference,
  88. const QString& pid,
  89. ctkManagedService* service)
  90. {
  91. ctkConfigurationImplPtr config = configurationStore->findConfiguration(pid);
  92. if (config.isNull() && trackManagedService(pid, reference, service))
  93. {
  94. asynchUpdated(service, ctkDictionary());
  95. }
  96. else
  97. {
  98. ctkConfigurationImplLocker lock(config.data());
  99. if (trackManagedService(pid, reference, service))
  100. {
  101. if (!config->getFactoryPid().isEmpty())
  102. {
  103. CTK_WARN(configurationAdminFactory->getLogService())
  104. << "Configuration for " << ctkPluginConstants::SERVICE_PID << "="
  105. << pid << " should only be used by a ctkManagedServiceFactory";
  106. }
  107. else if (config->isDeleted())
  108. {
  109. asynchUpdated(service, ctkDictionary());
  110. }
  111. else if (config->bind(reference.getPlugin()))
  112. {
  113. ctkDictionary properties = config->getProperties();
  114. configurationAdminFactory->modifyConfiguration(reference, properties);
  115. asynchUpdated(service, properties);
  116. }
  117. else
  118. {
  119. CTK_WARN(configurationAdminFactory->getLogService())
  120. << "Configuration for " << ctkPluginConstants::SERVICE_PID << "="
  121. << pid << " could not be bound to " << reference.getPlugin()->getLocation();
  122. }
  123. }
  124. }
  125. }
  126. void ctkManagedServiceTracker::removeManagedService(const ctkServiceReference& reference,
  127. const QString& pid)
  128. {
  129. ctkConfigurationImplPtr config = configurationStore->findConfiguration(pid);
  130. if (config.isNull())
  131. {
  132. untrackManagedService(pid, reference);
  133. }
  134. else
  135. {
  136. ctkConfigurationImplLocker lock(config.data());
  137. untrackManagedService(pid, reference);
  138. }
  139. }
  140. bool ctkManagedServiceTracker::trackManagedService(const QString& pid, const ctkServiceReference& reference,
  141. ctkManagedService* service)
  142. {
  143. QMutexLocker lock(&managedServiceMutex);
  144. if (managedServiceReferences.contains(pid))
  145. {
  146. CTK_WARN(configurationAdminFactory->getLogService())
  147. << "ctkManagedService already registered for " << ctkPluginConstants::SERVICE_PID
  148. << "=" << pid;
  149. return false;
  150. }
  151. managedServiceReferences.insert(pid, reference);
  152. managedServices.insert(pid, service);
  153. return true;
  154. }
  155. void ctkManagedServiceTracker::untrackManagedService(const QString& pid, const ctkServiceReference& reference)
  156. {
  157. Q_UNUSED(reference)
  158. QMutexLocker lock(&managedServiceMutex);
  159. managedServiceReferences.remove(pid);
  160. managedServices.remove(pid);
  161. }
  162. ctkManagedService* ctkManagedServiceTracker::getManagedService(const QString& pid) const
  163. {
  164. QMutexLocker lock(&managedServiceMutex);
  165. return managedServices.value(pid);
  166. }
  167. ctkServiceReference ctkManagedServiceTracker::getManagedServiceReference(const QString& pid) const
  168. {
  169. QMutexLocker lock(&managedServiceMutex);
  170. return managedServiceReferences.value(pid);
  171. }
  172. QString ctkManagedServiceTracker::getPidForManagedService(ctkManagedService* service) const
  173. {
  174. QMutexLocker lock(&managedServiceMutex);
  175. QHash<QString, ctkManagedService*>::ConstIterator end = managedServices.end();
  176. QHash<QString, ctkManagedService*>::ConstIterator it;
  177. for (it = managedServices.begin(); it != end; ++it)
  178. {
  179. if (it.value() == service)
  180. return it.key();
  181. }
  182. return QString();
  183. }
  184. class _AsynchUpdateRunnable : public QRunnable
  185. {
  186. public:
  187. _AsynchUpdateRunnable(ctkManagedService* service,
  188. const ctkDictionary& properties,
  189. ctkLogService* log)
  190. : service(service), properties(properties), log(log)
  191. {
  192. }
  193. void run()
  194. {
  195. try
  196. {
  197. service->updated(properties);
  198. }
  199. catch (const ctkConfigurationException* e)
  200. {
  201. // we might consider doing more for ctkConfigurationExceptions
  202. CTK_ERROR_EXC(log, e);
  203. }
  204. catch (const std::exception* e)
  205. {
  206. CTK_ERROR_EXC(log, e);
  207. }
  208. }
  209. private:
  210. ctkManagedService* service;
  211. const ctkDictionary properties;
  212. ctkLogService * const log;
  213. };
  214. void ctkManagedServiceTracker::asynchUpdated(ctkManagedService* service, const ctkDictionary& properties)
  215. {
  216. queue.put(new _AsynchUpdateRunnable(service, properties, configurationAdminFactory->getLogService()));
  217. }