149aefb31SBrad Bishop /**
249aefb31SBrad Bishop  * Copyright © 2016 IBM Corporation
349aefb31SBrad Bishop  *
449aefb31SBrad Bishop  * Licensed under the Apache License, Version 2.0 (the "License");
549aefb31SBrad Bishop  * you may not use this file except in compliance with the License.
649aefb31SBrad Bishop  * You may obtain a copy of the License at
749aefb31SBrad Bishop  *
849aefb31SBrad Bishop  *     http://www.apache.org/licenses/LICENSE-2.0
949aefb31SBrad Bishop  *
1049aefb31SBrad Bishop  * Unless required by applicable law or agreed to in writing, software
1149aefb31SBrad Bishop  * distributed under the License is distributed on an "AS IS" BASIS,
1249aefb31SBrad Bishop  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1349aefb31SBrad Bishop  * See the License for the specific language governing permissions and
1449aefb31SBrad Bishop  * limitations under the License.
1549aefb31SBrad Bishop  */
1649aefb31SBrad Bishop #include "manager.hpp"
17a680d1efSPatrick Venture 
1879ccaf77SBrad Bishop #include "errors.hpp"
1949aefb31SBrad Bishop 
20a83db30eSBrad Bishop #include <phosphor-logging/log.hpp>
21a83db30eSBrad Bishop 
22a680d1efSPatrick Venture #include <algorithm>
23a680d1efSPatrick Venture #include <chrono>
24a680d1efSPatrick Venture #include <exception>
25e6b21c74SKun Yi #include <filesystem>
26a680d1efSPatrick Venture #include <iostream>
27a680d1efSPatrick Venture 
2824424983SBrad Bishop using namespace std::literals::chrono_literals;
2924424983SBrad Bishop 
3049aefb31SBrad Bishop namespace phosphor
3149aefb31SBrad Bishop {
3249aefb31SBrad Bishop namespace inventory
3349aefb31SBrad Bishop {
3449aefb31SBrad Bishop namespace manager
3549aefb31SBrad Bishop {
3649aefb31SBrad Bishop /** @brief Fowrarding signal callback.
3749aefb31SBrad Bishop  *
3849aefb31SBrad Bishop  *  Extracts per-signal specific context and forwards the call to the manager
3949aefb31SBrad Bishop  *  instance.
4049aefb31SBrad Bishop  */
4149aefb31SBrad Bishop auto _signal(sd_bus_message* m, void* data, sd_bus_error* e) noexcept
4249aefb31SBrad Bishop {
437b33777bSBrad Bishop     try
447b33777bSBrad Bishop     {
4549aefb31SBrad Bishop         auto msg = sdbusplus::message::message(m);
4649aefb31SBrad Bishop         auto& args = *static_cast<Manager::SigArg*>(data);
4749aefb31SBrad Bishop         sd_bus_message_ref(m);
4849aefb31SBrad Bishop         auto& mgr = *std::get<0>(args);
49615b2a8fSBrad Bishop         mgr.handleEvent(msg, static_cast<const DbusSignal&>(*std::get<1>(args)),
5068c80839SBrad Bishop                         *std::get<2>(args));
5149aefb31SBrad Bishop     }
527b33777bSBrad Bishop     catch (const std::exception& e)
537b33777bSBrad Bishop     {
5449aefb31SBrad Bishop         std::cerr << e.what() << std::endl;
5549aefb31SBrad Bishop     }
5649aefb31SBrad Bishop 
5749aefb31SBrad Bishop     return 0;
5849aefb31SBrad Bishop }
5949aefb31SBrad Bishop 
6020c9435cSBrad Bishop Manager::Manager(sdbusplus::bus::bus&& bus, const char* root) :
614627a9ccSBrad Bishop     ServerObject<ManagerIface>(bus, root), _root(root), _bus(std::move(bus)),
624627a9ccSBrad Bishop     _manager(_bus, root),
63852db67bSMatt Spinler #ifdef CREATE_ASSOCIATIONS
644627a9ccSBrad Bishop     _associations(_bus),
65852db67bSMatt Spinler #endif
664627a9ccSBrad Bishop     _status(ManagerStatus::STARTING)
6749aefb31SBrad Bishop {
6868c80839SBrad Bishop     for (auto& group : _events)
6968c80839SBrad Bishop     {
70615b2a8fSBrad Bishop         for (auto pEvent : std::get<std::vector<EventBasePtr>>(group))
7168c80839SBrad Bishop         {
72615b2a8fSBrad Bishop             if (pEvent->type != Event::Type::DBUS_SIGNAL)
737b33777bSBrad Bishop             {
744f20a3e3SBrad Bishop                 continue;
757b33777bSBrad Bishop             }
764f20a3e3SBrad Bishop 
7768c80839SBrad Bishop             // Create a callback context for this event group.
78615b2a8fSBrad Bishop             auto dbusEvent = static_cast<DbusSignal*>(pEvent.get());
7968c80839SBrad Bishop 
8068c80839SBrad Bishop             // Go ahead and store an iterator pointing at
8168c80839SBrad Bishop             // the event data to avoid lookups later since
8268c80839SBrad Bishop             // additional signal callbacks aren't added
8368c80839SBrad Bishop             // after the manager is constructed.
8449aefb31SBrad Bishop             _sigargs.emplace_back(
85615b2a8fSBrad Bishop                 std::make_unique<SigArg>(this, dbusEvent, &group));
8668c80839SBrad Bishop 
8749aefb31SBrad Bishop             // Register our callback and the context for
8868c80839SBrad Bishop             // each signal event.
89615b2a8fSBrad Bishop             _matches.emplace_back(_bus, dbusEvent->signature, _signal,
901ab880a1SBrad Bishop                                   _sigargs.back().get());
9149aefb31SBrad Bishop         }
9268c80839SBrad Bishop     }
9349aefb31SBrad Bishop 
94b28990f3SDeepak Kodihalli     // Restore any persistent inventory
95b28990f3SDeepak Kodihalli     restore();
9649aefb31SBrad Bishop }
9749aefb31SBrad Bishop 
9849aefb31SBrad Bishop void Manager::shutdown() noexcept
9949aefb31SBrad Bishop {
1004627a9ccSBrad Bishop     _status = ManagerStatus::STOPPING;
10149aefb31SBrad Bishop }
10249aefb31SBrad Bishop 
10320c9435cSBrad Bishop void Manager::run(const char* busname)
10449aefb31SBrad Bishop {
1053e4a19a3SBrad Bishop     sdbusplus::message::message unusedMsg{nullptr};
1063e4a19a3SBrad Bishop 
1073e4a19a3SBrad Bishop     // Run startup events.
1083e4a19a3SBrad Bishop     for (auto& group : _events)
1093e4a19a3SBrad Bishop     {
110615b2a8fSBrad Bishop         for (auto pEvent : std::get<std::vector<EventBasePtr>>(group))
1113e4a19a3SBrad Bishop         {
112615b2a8fSBrad Bishop             if (pEvent->type == Event::Type::STARTUP)
1133e4a19a3SBrad Bishop             {
1143e4a19a3SBrad Bishop                 handleEvent(unusedMsg, *pEvent, group);
1153e4a19a3SBrad Bishop             }
1163e4a19a3SBrad Bishop         }
1173e4a19a3SBrad Bishop     }
1183e4a19a3SBrad Bishop 
1194627a9ccSBrad Bishop     _status = ManagerStatus::RUNNING;
12020c9435cSBrad Bishop     _bus.request_name(busname);
1214627a9ccSBrad Bishop 
1224627a9ccSBrad Bishop     while (_status != ManagerStatus::STOPPING)
1237b33777bSBrad Bishop     {
1247b33777bSBrad Bishop         try
1257b33777bSBrad Bishop         {
12649aefb31SBrad Bishop             _bus.process_discard();
12724424983SBrad Bishop             _bus.wait((5000000us).count());
12849aefb31SBrad Bishop         }
1297b33777bSBrad Bishop         catch (const std::exception& e)
1307b33777bSBrad Bishop         {
13149aefb31SBrad Bishop             std::cerr << e.what() << std::endl;
13249aefb31SBrad Bishop         }
13349aefb31SBrad Bishop     }
13449aefb31SBrad Bishop }
13549aefb31SBrad Bishop 
136615b2a8fSBrad Bishop void Manager::updateInterfaces(const sdbusplus::message::object_path& path,
13779ccaf77SBrad Bishop                                const Object& interfaces,
138615b2a8fSBrad Bishop                                ObjectReferences::iterator pos, bool newObject,
139b28990f3SDeepak Kodihalli                                bool restoreFromCache)
14079ccaf77SBrad Bishop {
14179ccaf77SBrad Bishop     auto& refaces = pos->second;
14279ccaf77SBrad Bishop     auto ifaceit = interfaces.cbegin();
14379ccaf77SBrad Bishop     auto opsit = _makers.cbegin();
14479ccaf77SBrad Bishop     auto refaceit = refaces.begin();
14579ccaf77SBrad Bishop     std::vector<std::string> signals;
14679ccaf77SBrad Bishop 
14779ccaf77SBrad Bishop     while (ifaceit != interfaces.cend())
14879ccaf77SBrad Bishop     {
14979ccaf77SBrad Bishop         try
15079ccaf77SBrad Bishop         {
15179ccaf77SBrad Bishop             // Find the binding ops for this interface.
152615b2a8fSBrad Bishop             opsit = std::lower_bound(opsit, _makers.cend(), ifaceit->first,
15379ccaf77SBrad Bishop                                      compareFirst(_makers.key_comp()));
15479ccaf77SBrad Bishop 
15579ccaf77SBrad Bishop             if (opsit == _makers.cend() || opsit->first != ifaceit->first)
15679ccaf77SBrad Bishop             {
15779ccaf77SBrad Bishop                 // This interface is not supported.
158615b2a8fSBrad Bishop                 throw InterfaceError("Encountered unsupported interface.",
15979ccaf77SBrad Bishop                                      ifaceit->first);
16079ccaf77SBrad Bishop             }
16179ccaf77SBrad Bishop 
16279ccaf77SBrad Bishop             // Find the binding insertion point or the binding to update.
163615b2a8fSBrad Bishop             refaceit = std::lower_bound(refaceit, refaces.end(), ifaceit->first,
16479ccaf77SBrad Bishop                                         compareFirst(refaces.key_comp()));
16579ccaf77SBrad Bishop 
16679ccaf77SBrad Bishop             if (refaceit == refaces.end() || refaceit->first != ifaceit->first)
16779ccaf77SBrad Bishop             {
16879ccaf77SBrad Bishop                 // Add the new interface.
16902763c68SBrad Bishop                 auto& ctor = std::get<MakeInterfaceType>(opsit->second);
17023a8d935SBrad Bishop                 // skipSignal = true here to avoid getting PropertiesChanged
17123a8d935SBrad Bishop                 // signals while the interface is constructed.  We'll emit an
17223a8d935SBrad Bishop                 // ObjectManager signal for this interface below.
17379ccaf77SBrad Bishop                 refaceit = refaces.insert(
174e96f2aa7SBrad Bishop                     refaceit, std::make_pair(ifaceit->first,
175e96f2aa7SBrad Bishop                                              ctor(_bus, path.str.c_str(),
17623a8d935SBrad Bishop                                                   ifaceit->second, true)));
17779ccaf77SBrad Bishop                 signals.push_back(ifaceit->first);
17879ccaf77SBrad Bishop             }
17979ccaf77SBrad Bishop             else
18079ccaf77SBrad Bishop             {
18179ccaf77SBrad Bishop                 // Set the new property values.
18202763c68SBrad Bishop                 auto& assign = std::get<AssignInterfaceType>(opsit->second);
18323a8d935SBrad Bishop                 assign(ifaceit->second, refaceit->second,
18423a8d935SBrad Bishop                        _status != ManagerStatus::RUNNING);
18579ccaf77SBrad Bishop             }
186b28990f3SDeepak Kodihalli             if (!restoreFromCache)
187b28990f3SDeepak Kodihalli             {
18802763c68SBrad Bishop                 auto& serialize =
18902763c68SBrad Bishop                     std::get<SerializeInterfaceType<SerialOps>>(opsit->second);
1906620e98dSDeepak Kodihalli                 serialize(path, ifaceit->first, refaceit->second);
19179ccaf77SBrad Bishop             }
192b28990f3SDeepak Kodihalli             else
193b28990f3SDeepak Kodihalli             {
19402763c68SBrad Bishop                 auto& deserialize =
19502763c68SBrad Bishop                     std::get<DeserializeInterfaceType<SerialOps>>(
19602763c68SBrad Bishop                         opsit->second);
197b28990f3SDeepak Kodihalli                 deserialize(path, ifaceit->first, refaceit->second);
198b28990f3SDeepak Kodihalli             }
199b28990f3SDeepak Kodihalli         }
20079ccaf77SBrad Bishop         catch (const InterfaceError& e)
20179ccaf77SBrad Bishop         {
20279ccaf77SBrad Bishop             // Reset the binding ops iterator since we are
20379ccaf77SBrad Bishop             // at the end.
20479ccaf77SBrad Bishop             opsit = _makers.cbegin();
20579ccaf77SBrad Bishop             e.log();
20679ccaf77SBrad Bishop         }
20779ccaf77SBrad Bishop 
20879ccaf77SBrad Bishop         ++ifaceit;
20979ccaf77SBrad Bishop     }
21079ccaf77SBrad Bishop 
21123a8d935SBrad Bishop     if (_status == ManagerStatus::RUNNING)
21223a8d935SBrad Bishop     {
21379ccaf77SBrad Bishop         if (newObject)
21479ccaf77SBrad Bishop         {
21579ccaf77SBrad Bishop             _bus.emit_object_added(path.str.c_str());
21679ccaf77SBrad Bishop         }
21779ccaf77SBrad Bishop         else if (!signals.empty())
21879ccaf77SBrad Bishop         {
219a8ff8154SGunnar Mills             _bus.emit_interfaces_added(path.str.c_str(), signals);
22079ccaf77SBrad Bishop         }
22179ccaf77SBrad Bishop     }
22223a8d935SBrad Bishop }
22379ccaf77SBrad Bishop 
22479ccaf77SBrad Bishop void Manager::updateObjects(
225b28990f3SDeepak Kodihalli     const std::map<sdbusplus::message::object_path, Object>& objs,
226b28990f3SDeepak Kodihalli     bool restoreFromCache)
22779ccaf77SBrad Bishop {
22879ccaf77SBrad Bishop     auto objit = objs.cbegin();
22979ccaf77SBrad Bishop     auto refit = _refs.begin();
23079ccaf77SBrad Bishop     std::string absPath;
23179ccaf77SBrad Bishop     bool newObj;
23279ccaf77SBrad Bishop 
23379ccaf77SBrad Bishop     while (objit != objs.cend())
23479ccaf77SBrad Bishop     {
23579ccaf77SBrad Bishop         // Find the insertion point or the object to update.
236615b2a8fSBrad Bishop         refit = std::lower_bound(refit, _refs.end(), objit->first,
23779ccaf77SBrad Bishop                                  compareFirst(RelPathCompare(_root)));
23879ccaf77SBrad Bishop 
23979ccaf77SBrad Bishop         absPath.assign(_root);
24079ccaf77SBrad Bishop         absPath.append(objit->first);
24179ccaf77SBrad Bishop 
24279ccaf77SBrad Bishop         newObj = false;
24379ccaf77SBrad Bishop         if (refit == _refs.end() || refit->first != absPath)
24479ccaf77SBrad Bishop         {
24579ccaf77SBrad Bishop             refit = _refs.insert(
246615b2a8fSBrad Bishop                 refit, std::make_pair(absPath, decltype(_refs)::mapped_type()));
24779ccaf77SBrad Bishop             newObj = true;
24879ccaf77SBrad Bishop         }
24979ccaf77SBrad Bishop 
250b28990f3SDeepak Kodihalli         updateInterfaces(absPath, objit->second, refit, newObj,
251b28990f3SDeepak Kodihalli                          restoreFromCache);
252852db67bSMatt Spinler #ifdef CREATE_ASSOCIATIONS
253*59521e87SMatt Spinler         if (!_associations.pendingCondition() && newObj)
254852db67bSMatt Spinler         {
25523a8d935SBrad Bishop             _associations.createAssociations(absPath,
256ee294d68SBrad Bishop                                              _status != ManagerStatus::RUNNING);
257852db67bSMatt Spinler         }
258*59521e87SMatt Spinler         else if (!restoreFromCache &&
259*59521e87SMatt Spinler                  _associations.conditionMatch(objit->first, objit->second))
260*59521e87SMatt Spinler         {
261*59521e87SMatt Spinler             // The objit path/interface/property matched a pending condition.
262*59521e87SMatt Spinler             // Now the associations are valid so attempt to create them against
263*59521e87SMatt Spinler             // all existing objects.  If this was the restoreFromCache path,
264*59521e87SMatt Spinler             // objit doesn't contain property values so don't bother checking.
265*59521e87SMatt Spinler             std::for_each(_refs.begin(), _refs.end(), [this](const auto& ref) {
266*59521e87SMatt Spinler                 _associations.createAssociations(
267*59521e87SMatt Spinler                     ref.first, _status != ManagerStatus::RUNNING);
268*59521e87SMatt Spinler             });
269*59521e87SMatt Spinler         }
270852db67bSMatt Spinler #endif
27179ccaf77SBrad Bishop         ++objit;
27279ccaf77SBrad Bishop     }
27379ccaf77SBrad Bishop }
27479ccaf77SBrad Bishop 
27503f4cd95SBrad Bishop void Manager::notify(std::map<sdbusplus::message::object_path, Object> objs)
27649aefb31SBrad Bishop {
277cda036f7SBrad Bishop     updateObjects(objs);
27849aefb31SBrad Bishop }
27949aefb31SBrad Bishop 
280615b2a8fSBrad Bishop void Manager::handleEvent(sdbusplus::message::message& msg, const Event& event,
28168c80839SBrad Bishop                           const EventInfo& info)
28249aefb31SBrad Bishop {
28368c80839SBrad Bishop     auto& actions = std::get<1>(info);
2843d57f507SBrad Bishop 
28548547a85SBrad Bishop     for (auto& f : event)
2867b33777bSBrad Bishop     {
28707934a64SBrad Bishop         if (!f(_bus, msg, *this))
288064c94a6SBrad Bishop         {
289064c94a6SBrad Bishop             return;
290064c94a6SBrad Bishop         }
291064c94a6SBrad Bishop     }
2929007432aSBrad Bishop     for (auto& action : actions)
2937b33777bSBrad Bishop     {
29407934a64SBrad Bishop         action(_bus, *this);
2953d57f507SBrad Bishop     }
29649aefb31SBrad Bishop }
29749aefb31SBrad Bishop 
298615b2a8fSBrad Bishop void Manager::destroyObjects(const std::vector<const char*>& paths)
2997b7e712cSBrad Bishop {
300a5cc34c2SBrad Bishop     std::string p;
301a5cc34c2SBrad Bishop 
3027b7e712cSBrad Bishop     for (const auto& path : paths)
303656a7d00SBrad Bishop     {
304a5cc34c2SBrad Bishop         p.assign(_root);
305a5cc34c2SBrad Bishop         p.append(path);
306a5cc34c2SBrad Bishop         _bus.emit_object_removed(p.c_str());
307a5cc34c2SBrad Bishop         _refs.erase(p);
308656a7d00SBrad Bishop     }
3097b7e712cSBrad Bishop }
310656a7d00SBrad Bishop 
311eb68a687SBrad Bishop void Manager::createObjects(
312eb68a687SBrad Bishop     const std::map<sdbusplus::message::object_path, Object>& objs)
313eb68a687SBrad Bishop {
314cda036f7SBrad Bishop     updateObjects(objs);
315eb68a687SBrad Bishop }
316eb68a687SBrad Bishop 
31725d54b51SBrad Bishop std::any& Manager::getInterfaceHolder(const char* path, const char* interface)
318b83a21eaSBrad Bishop {
31925d54b51SBrad Bishop     return const_cast<std::any&>(
320615b2a8fSBrad Bishop         const_cast<const Manager*>(this)->getInterfaceHolder(path, interface));
321b83a21eaSBrad Bishop }
322b83a21eaSBrad Bishop 
32325d54b51SBrad Bishop const std::any& Manager::getInterfaceHolder(const char* path,
324615b2a8fSBrad Bishop                                             const char* interface) const
325b83a21eaSBrad Bishop {
326b83a21eaSBrad Bishop     std::string p{path};
327b83a21eaSBrad Bishop     auto oit = _refs.find(_root + p);
328b83a21eaSBrad Bishop     if (oit == _refs.end())
329615b2a8fSBrad Bishop         throw std::runtime_error(_root + p + " was not found");
330b83a21eaSBrad Bishop 
331b83a21eaSBrad Bishop     auto& obj = oit->second;
332b83a21eaSBrad Bishop     auto iit = obj.find(interface);
333b83a21eaSBrad Bishop     if (iit == obj.end())
334615b2a8fSBrad Bishop         throw std::runtime_error("interface was not found");
335b83a21eaSBrad Bishop 
336150147aeSBrad Bishop     return iit->second;
337b83a21eaSBrad Bishop }
338b83a21eaSBrad Bishop 
339b28990f3SDeepak Kodihalli void Manager::restore()
340b28990f3SDeepak Kodihalli {
341e6b21c74SKun Yi     namespace fs = std::filesystem;
342b28990f3SDeepak Kodihalli 
343b28990f3SDeepak Kodihalli     if (!fs::exists(fs::path(PIM_PERSIST_PATH)))
344b28990f3SDeepak Kodihalli     {
345b28990f3SDeepak Kodihalli         return;
346b28990f3SDeepak Kodihalli     }
347b28990f3SDeepak Kodihalli 
348b28990f3SDeepak Kodihalli     static const std::string remove =
349b28990f3SDeepak Kodihalli         std::string(PIM_PERSIST_PATH) + INVENTORY_ROOT;
350b28990f3SDeepak Kodihalli 
351b28990f3SDeepak Kodihalli     std::map<sdbusplus::message::object_path, Object> objects;
352b28990f3SDeepak Kodihalli     for (const auto& dirent :
353b28990f3SDeepak Kodihalli          fs::recursive_directory_iterator(PIM_PERSIST_PATH))
354b28990f3SDeepak Kodihalli     {
355b28990f3SDeepak Kodihalli         const auto& path = dirent.path();
356b28990f3SDeepak Kodihalli         if (fs::is_regular_file(path))
357b28990f3SDeepak Kodihalli         {
358b28990f3SDeepak Kodihalli             auto ifaceName = path.filename().string();
359b28990f3SDeepak Kodihalli             auto objPath = path.parent_path().string();
360b28990f3SDeepak Kodihalli             objPath.erase(0, remove.length());
361b28990f3SDeepak Kodihalli             auto objit = objects.find(objPath);
362b28990f3SDeepak Kodihalli             Interface propertyMap{};
363b28990f3SDeepak Kodihalli             if (objects.end() != objit)
364b28990f3SDeepak Kodihalli             {
365b28990f3SDeepak Kodihalli                 auto& object = objit->second;
366b28990f3SDeepak Kodihalli                 object.emplace(std::move(ifaceName), std::move(propertyMap));
367b28990f3SDeepak Kodihalli             }
368b28990f3SDeepak Kodihalli             else
369b28990f3SDeepak Kodihalli             {
370b28990f3SDeepak Kodihalli                 Object object;
371b28990f3SDeepak Kodihalli                 object.emplace(std::move(ifaceName), std::move(propertyMap));
372b28990f3SDeepak Kodihalli                 objects.emplace(std::move(objPath), std::move(object));
373b28990f3SDeepak Kodihalli             }
374b28990f3SDeepak Kodihalli         }
375b28990f3SDeepak Kodihalli     }
376b28990f3SDeepak Kodihalli     if (!objects.empty())
377b28990f3SDeepak Kodihalli     {
378b28990f3SDeepak Kodihalli         auto restoreFromCache = true;
379b28990f3SDeepak Kodihalli         updateObjects(objects, restoreFromCache);
380*59521e87SMatt Spinler 
381*59521e87SMatt Spinler #ifdef CREATE_ASSOCIATIONS
382*59521e87SMatt Spinler         // There may be conditional associations waiting to be loaded
383*59521e87SMatt Spinler         // based on certain path/interface/property values.  Now that
384*59521e87SMatt Spinler         // _refs contains all objects with their property values, check
385*59521e87SMatt Spinler         // which property values the conditions need and set them in the
386*59521e87SMatt Spinler         // condition structure entries, using the actualValue field.  Then
387*59521e87SMatt Spinler         // the associations manager can check if the conditions are met.
388*59521e87SMatt Spinler         if (_associations.pendingCondition())
389*59521e87SMatt Spinler         {
390*59521e87SMatt Spinler             ObjectReferences::iterator refIt;
391*59521e87SMatt Spinler             InterfaceComposite::iterator ifaceIt;
392*59521e87SMatt Spinler 
393*59521e87SMatt Spinler             auto& conditions = _associations.getConditions();
394*59521e87SMatt Spinler             for (auto& condition : conditions)
395*59521e87SMatt Spinler             {
396*59521e87SMatt Spinler                 refIt = _refs.find(_root + condition.path);
397*59521e87SMatt Spinler                 if (refIt != _refs.end())
398*59521e87SMatt Spinler                 {
399*59521e87SMatt Spinler                     ifaceIt = refIt->second.find(condition.interface);
400*59521e87SMatt Spinler                 }
401*59521e87SMatt Spinler 
402*59521e87SMatt Spinler                 if ((refIt != _refs.end()) && (ifaceIt != refIt->second.end()))
403*59521e87SMatt Spinler                 {
404*59521e87SMatt Spinler                     const auto& maker = _makers.find(condition.interface);
405*59521e87SMatt Spinler                     if (maker != _makers.end())
406*59521e87SMatt Spinler                     {
407*59521e87SMatt Spinler                         auto& getProperty =
408*59521e87SMatt Spinler                             std::get<GetPropertyValueType>(maker->second);
409*59521e87SMatt Spinler 
410*59521e87SMatt Spinler                         condition.actualValue =
411*59521e87SMatt Spinler                             getProperty(condition.property, ifaceIt->second);
412*59521e87SMatt Spinler                     }
413*59521e87SMatt Spinler                 }
414*59521e87SMatt Spinler             }
415*59521e87SMatt Spinler 
416*59521e87SMatt Spinler             // Check if a property value in a condition matches an
417*59521e87SMatt Spinler             // actual property value just saved.  If one did, now the
418*59521e87SMatt Spinler             // associations file is valid so create its associations.
419*59521e87SMatt Spinler             if (_associations.conditionMatch())
420*59521e87SMatt Spinler             {
421*59521e87SMatt Spinler                 std::for_each(
422*59521e87SMatt Spinler                     _refs.begin(), _refs.end(), [this](const auto& ref) {
423*59521e87SMatt Spinler                         _associations.createAssociations(
424*59521e87SMatt Spinler                             ref.first, _status != ManagerStatus::RUNNING);
425*59521e87SMatt Spinler                     });
426*59521e87SMatt Spinler             }
427*59521e87SMatt Spinler         }
428*59521e87SMatt Spinler #endif
429b28990f3SDeepak Kodihalli     }
430b28990f3SDeepak Kodihalli }
431b28990f3SDeepak Kodihalli 
43249aefb31SBrad Bishop } // namespace manager
43349aefb31SBrad Bishop } // namespace inventory
43449aefb31SBrad Bishop } // namespace phosphor
43549aefb31SBrad Bishop 
43649aefb31SBrad Bishop // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
437