Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <opc/common/addons_core/addon.h>
00012 #include <opc/common/addons_core/addon_manager.h>
00013 #include <opc/common/addons_core/errors.h>
00014 #include <opc/common/exception.h>
00015
00016 #include <iostream>
00017 #include <map>
00018
00019 namespace
00020 {
00021 struct AddonData
00022 {
00023 Common::AddonId Id;
00024 Common::AddonFactory::SharedPtr Factory;
00025 std::vector<Common::AddonId> Dependencies;
00026 Common::AddonParameters Parameters;
00027 Common::Addon::SharedPtr Addon;
00028
00029 AddonData(const Common::AddonInformation& configuration)
00030 : Id(configuration.Id)
00031 , Factory(configuration.Factory)
00032 , Dependencies(configuration.Dependencies)
00033 , Parameters(configuration.Parameters)
00034 {
00035 }
00036 };
00037
00038 bool IsAddonNotStarted(const std::pair<Common::AddonId, AddonData>& addonData)
00039 {
00040 return addonData.second.Addon == Common::Addon::SharedPtr();
00041 }
00042
00043 class AddonsManagerImpl : public Common::AddonsManager
00044 {
00045 typedef std::map<Common::AddonId, AddonData> AddonList;
00046
00047 public:
00048 AddonsManagerImpl()
00049 : ManagerStarted(false)
00050 {
00051 }
00052
00053 virtual ~AddonsManagerImpl()
00054 {
00055 try
00056 {
00057 if (ManagerStarted)
00058 {
00059 Stop();
00060 }
00061 }
00062 catch(const Common::Error& err)
00063 {
00064 std::cerr << err.GetFullMessage() << std::endl;
00065 }
00066 catch (...)
00067 {
00068 std::cerr << "unknown exception" << std::endl;
00069 throw;
00070 }
00071 }
00072
00073 virtual void Register(const Common::AddonInformation& addonConfiguration)
00074 {
00075
00076 if (ManagerStarted && !addonConfiguration.Dependencies.empty())
00077 {
00078 THROW_ERROR1(UnableToRegisterAddonWhenStarted, addonConfiguration.Id);
00079 }
00080
00081 EnsureAddonNotRegistered(addonConfiguration.Id);
00082 Addons.insert(std::make_pair(addonConfiguration.Id, AddonData(addonConfiguration)));
00083 if (ManagerStarted)
00084 {
00085 DoStart();
00086 }
00087 }
00088
00089 virtual void Unregister(const Common::AddonId& id)
00090 {
00091
00092 EnsureAddonRegistered(id);
00093 AddonData& addonData = Addons.find(id)->second;
00094 if (addonData.Addon)
00095 {
00096 addonData.Addon->Stop();
00097 }
00098 Addons.erase(id);
00099 }
00100
00101 virtual Common::Addon::SharedPtr GetAddon(const Common::AddonId& id) const
00102 {
00103
00104 EnsureAddonRegistered(id);
00105 EnsureAddonInitialized(id);
00106 return Addons.find(id)->second.Addon;
00107 }
00108
00109 virtual void Start()
00110 {
00111 if (ManagerStarted)
00112 {
00113 THROW_ERROR(AddonsManagerAlreadyStarted);
00114 }
00115
00116 if (!DoStart())
00117 {
00118 StopAddons();
00119 THROW_ERROR(FailedToStartAddons);
00120 }
00121 ManagerStarted = true;
00122 }
00123
00124 virtual void Stop()
00125 {
00126 if (!ManagerStarted)
00127 {
00128 THROW_ERROR(AddonsManagerAlreadyStopped);
00129 }
00130
00131 StopAddons();
00132 ManagerStarted = false;
00133 }
00134 private:
00135 void StopAddons()
00136 {
00137 if (Addons.empty())
00138 return;
00139
00140 while (AddonData* addonData = GetNextAddonDataForStop())
00141 {
00142 try
00143 {
00144
00145 addonData->Addon->Stop();
00146 addonData->Addon.reset();
00147
00148 }
00149 catch (const std::exception& exc)
00150 {
00151 std::cerr << "Failed to initialize addon '" << addonData->Id << "': "<< exc.what() << std::endl;
00152 }
00153 }
00154 Addons.clear();
00155 }
00156
00157 bool DoStart()
00158 {
00159 while (AddonData* addonData = GetNextAddonDataForStart())
00160 {
00161
00162 Common::Addon::SharedPtr addon = addonData->Factory->CreateAddon();
00163
00164 try
00165 {
00166 addon->Initialize(*this, addonData->Parameters);
00167
00168 }
00169 catch (const std::exception& exc)
00170 {
00171 std::cerr << "Failed to initialize addon '" << addonData->Id << "': "<< exc.what() << std::endl;
00172 return false;
00173 }
00174 addonData->Addon = addon;
00175 }
00176 EnsureAllAddonsStarted();
00177 return true;
00178 }
00179
00180 AddonData* GetNextAddonDataForStart()
00181 {
00182 for (AddonList::iterator it = Addons.begin(); it != Addons.end(); ++it)
00183 {
00184 if (!IsAddonStarted(it->second) && IsAllAddonsStarted(it->second.Dependencies))
00185 {
00186 return &it->second;
00187 }
00188 }
00189 return 0;
00190 }
00191
00192
00193 AddonData* GetNextAddonDataForStop()
00194 {
00195 for (AddonList::iterator it = Addons.begin(); it != Addons.end(); ++it)
00196 {
00197 if (IsAddonStarted(it->second) && IsAllDependentAddonsStopped(it->first))
00198 {
00199 return &it->second;
00200 }
00201 }
00202 return 0;
00203 }
00204
00205 bool IsAddonStarted(const AddonData& addonData) const
00206 {
00207 return static_cast<bool>(addonData.Addon);
00208 }
00209
00210 bool IsAllAddonsStarted(const std::vector<Common::AddonId>& ids) const
00211 {
00212 for (std::vector<Common::AddonId>::const_iterator it = ids.begin(); it != ids.end(); ++it)
00213 {
00214 const AddonList::const_iterator addonIt = Addons.find(*it);
00215 if (addonIt == Addons.end())
00216 {
00217 THROW_ERROR1(AddonNotFound, *it);
00218 }
00219
00220 if (!IsAddonStarted(addonIt->second))
00221 {
00222 return false;
00223 }
00224 }
00225 return true;
00226 }
00227
00228 bool IsAllDependentAddonsStopped(const Common::AddonId& id) const
00229 {
00230 for (const AddonList::value_type& addonIt : Addons)
00231 {
00232
00233 if (!IsAddonStarted(addonIt.second))
00234 {
00235 continue;
00236 }
00237
00238 const std::vector<Common::AddonId>& deps = addonIt.second.Dependencies;
00239 if (std::find(deps.begin(), deps.end(), id) != deps.end())
00240 {
00241 return false;
00242 }
00243 }
00244 return true;
00245 }
00246
00247 void EnsureAddonInitialized(Common::AddonId id) const
00248 {
00249 if (!Addons.find(id)->second.Addon)
00250 {
00251 THROW_ERROR1(AddonNotInitializedYet, id);
00252 }
00253 }
00254
00255 void EnsureAddonRegistered(Common::AddonId id) const
00256 {
00257 if (!IsAddonRegistered(id))
00258 {
00259 THROW_ERROR1(AddonNotRegistered, id);
00260 }
00261 }
00262
00263 void EnsureAddonNotRegistered(Common::AddonId id) const
00264 {
00265 if (IsAddonRegistered(id))
00266 {
00267 THROW_ERROR1(AddonRegisteredButShouldnt, id);
00268 }
00269 }
00270
00271 bool IsAddonRegistered(Common::AddonId id) const
00272 {
00273 return Addons.find(id) != Addons.end();
00274 }
00275
00276 void EnsureAllAddonsStarted() const
00277 {
00278 AddonList::const_iterator addonIt = std::find_if(Addons.begin(), Addons.end(), IsAddonNotStarted);
00279 if (!Addons.empty() && addonIt != Addons.end())
00280 {
00281 THROW_ERROR1(AddonIsNotStarted, addonIt->first);
00282 }
00283 }
00284
00285 private:
00286 AddonList Addons;
00287 bool ManagerStarted;
00288 };
00289 }
00290
00291 Common::AddonsManager::UniquePtr Common::CreateAddonsManager()
00292 {
00293 return AddonsManager::UniquePtr(new AddonsManagerImpl());
00294 }
00295