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 
20a680d1efSPatrick Venture #include <algorithm>
21a680d1efSPatrick Venture #include <chrono>
22a680d1efSPatrick Venture #include <exception>
23e6b21c74SKun Yi #include <filesystem>
24a680d1efSPatrick Venture #include <iostream>
25a680d1efSPatrick Venture 
2624424983SBrad Bishop using namespace std::literals::chrono_literals;
2724424983SBrad Bishop 
2849aefb31SBrad Bishop namespace phosphor
2949aefb31SBrad Bishop {
3049aefb31SBrad Bishop namespace inventory
3149aefb31SBrad Bishop {
3249aefb31SBrad Bishop namespace manager
3349aefb31SBrad Bishop {
3449aefb31SBrad Bishop /** @brief Fowrarding signal callback.
3549aefb31SBrad Bishop  *
3649aefb31SBrad Bishop  *  Extracts per-signal specific context and forwards the call to the manager
3749aefb31SBrad Bishop  *  instance.
3849aefb31SBrad Bishop  */
_signal(sd_bus_message * m,void * data,sd_bus_error *)3923314a5cSGeorge Liu auto _signal(sd_bus_message* m, void* data, sd_bus_error* /* e */) noexcept
4049aefb31SBrad Bishop {
417b33777bSBrad Bishop     try
427b33777bSBrad Bishop     {
43563306f6SPatrick Williams         auto msg = sdbusplus::message_t(m);
4449aefb31SBrad Bishop         auto& args = *static_cast<Manager::SigArg*>(data);
4549aefb31SBrad Bishop         sd_bus_message_ref(m);
4649aefb31SBrad Bishop         auto& mgr = *std::get<0>(args);
47615b2a8fSBrad Bishop         mgr.handleEvent(msg, static_cast<const DbusSignal&>(*std::get<1>(args)),
4868c80839SBrad Bishop                         *std::get<2>(args));
4949aefb31SBrad Bishop     }
507b33777bSBrad Bishop     catch (const std::exception& e)
517b33777bSBrad Bishop     {
5249aefb31SBrad Bishop         std::cerr << e.what() << std::endl;
5349aefb31SBrad Bishop     }
5449aefb31SBrad Bishop 
5549aefb31SBrad Bishop     return 0;
5649aefb31SBrad Bishop }
5749aefb31SBrad Bishop 
Manager(sdbusplus::bus_t && bus,const char * root)58563306f6SPatrick Williams Manager::Manager(sdbusplus::bus_t&& bus, const char* root) :
594627a9ccSBrad Bishop     ServerObject<ManagerIface>(bus, root), _root(root), _bus(std::move(bus)),
604627a9ccSBrad Bishop     _manager(_bus, root),
61852db67bSMatt Spinler #ifdef CREATE_ASSOCIATIONS
624627a9ccSBrad Bishop     _associations(_bus),
63852db67bSMatt Spinler #endif
644627a9ccSBrad Bishop     _status(ManagerStatus::STARTING)
6549aefb31SBrad Bishop {
6668c80839SBrad Bishop     for (auto& group : _events)
6768c80839SBrad Bishop     {
68615b2a8fSBrad Bishop         for (auto pEvent : std::get<std::vector<EventBasePtr>>(group))
6968c80839SBrad Bishop         {
70615b2a8fSBrad Bishop             if (pEvent->type != Event::Type::DBUS_SIGNAL)
717b33777bSBrad Bishop             {
724f20a3e3SBrad Bishop                 continue;
737b33777bSBrad Bishop             }
744f20a3e3SBrad Bishop 
7568c80839SBrad Bishop             // Create a callback context for this event group.
76615b2a8fSBrad Bishop             auto dbusEvent = static_cast<DbusSignal*>(pEvent.get());
7768c80839SBrad Bishop 
7868c80839SBrad Bishop             // Go ahead and store an iterator pointing at
7968c80839SBrad Bishop             // the event data to avoid lookups later since
8068c80839SBrad Bishop             // additional signal callbacks aren't added
8168c80839SBrad Bishop             // after the manager is constructed.
8249aefb31SBrad Bishop             _sigargs.emplace_back(
83615b2a8fSBrad Bishop                 std::make_unique<SigArg>(this, dbusEvent, &group));
8468c80839SBrad Bishop 
8549aefb31SBrad Bishop             // Register our callback and the context for
8668c80839SBrad Bishop             // each signal event.
87615b2a8fSBrad Bishop             _matches.emplace_back(_bus, dbusEvent->signature, _signal,
881ab880a1SBrad Bishop                                   _sigargs.back().get());
8949aefb31SBrad Bishop         }
9068c80839SBrad Bishop     }
9149aefb31SBrad Bishop 
92b28990f3SDeepak Kodihalli     // Restore any persistent inventory
93b28990f3SDeepak Kodihalli     restore();
9449aefb31SBrad Bishop }
9549aefb31SBrad Bishop 
shutdown()9649aefb31SBrad Bishop void Manager::shutdown() noexcept
9749aefb31SBrad Bishop {
984627a9ccSBrad Bishop     _status = ManagerStatus::STOPPING;
9949aefb31SBrad Bishop }
10049aefb31SBrad Bishop 
run(const char * busname)10120c9435cSBrad Bishop void Manager::run(const char* busname)
10249aefb31SBrad Bishop {
103563306f6SPatrick Williams     sdbusplus::message_t unusedMsg{nullptr};
1043e4a19a3SBrad Bishop 
1053e4a19a3SBrad Bishop     // Run startup events.
1063e4a19a3SBrad Bishop     for (auto& group : _events)
1073e4a19a3SBrad Bishop     {
108615b2a8fSBrad Bishop         for (auto pEvent : std::get<std::vector<EventBasePtr>>(group))
1093e4a19a3SBrad Bishop         {
110615b2a8fSBrad Bishop             if (pEvent->type == Event::Type::STARTUP)
1113e4a19a3SBrad Bishop             {
1123e4a19a3SBrad Bishop                 handleEvent(unusedMsg, *pEvent, group);
1133e4a19a3SBrad Bishop             }
1143e4a19a3SBrad Bishop         }
1153e4a19a3SBrad Bishop     }
1163e4a19a3SBrad Bishop 
1174627a9ccSBrad Bishop     _status = ManagerStatus::RUNNING;
11820c9435cSBrad Bishop     _bus.request_name(busname);
1194627a9ccSBrad Bishop 
1204627a9ccSBrad Bishop     while (_status != ManagerStatus::STOPPING)
1217b33777bSBrad Bishop     {
1227b33777bSBrad Bishop         try
1237b33777bSBrad Bishop         {
12449aefb31SBrad Bishop             _bus.process_discard();
12524424983SBrad Bishop             _bus.wait((5000000us).count());
12649aefb31SBrad Bishop         }
1277b33777bSBrad Bishop         catch (const std::exception& e)
1287b33777bSBrad Bishop         {
12949aefb31SBrad Bishop             std::cerr << e.what() << std::endl;
13049aefb31SBrad Bishop         }
13149aefb31SBrad Bishop     }
13249aefb31SBrad Bishop }
13349aefb31SBrad Bishop 
updateInterfaces(const sdbusplus::message::object_path & path,const Object & interfaces,ObjectReferences::iterator pos,bool newObject,bool restoreFromCache)134615b2a8fSBrad Bishop void Manager::updateInterfaces(const sdbusplus::message::object_path& path,
13579ccaf77SBrad Bishop                                const Object& interfaces,
136615b2a8fSBrad Bishop                                ObjectReferences::iterator pos, bool newObject,
137b28990f3SDeepak Kodihalli                                bool restoreFromCache)
13879ccaf77SBrad Bishop {
13979ccaf77SBrad Bishop     auto& refaces = pos->second;
14079ccaf77SBrad Bishop     auto ifaceit = interfaces.cbegin();
14179ccaf77SBrad Bishop     auto opsit = _makers.cbegin();
14279ccaf77SBrad Bishop     auto refaceit = refaces.begin();
14379ccaf77SBrad Bishop     std::vector<std::string> signals;
14479ccaf77SBrad Bishop 
14579ccaf77SBrad Bishop     while (ifaceit != interfaces.cend())
14679ccaf77SBrad Bishop     {
14779ccaf77SBrad Bishop         try
14879ccaf77SBrad Bishop         {
14979ccaf77SBrad Bishop             // Find the binding ops for this interface.
150615b2a8fSBrad Bishop             opsit = std::lower_bound(opsit, _makers.cend(), ifaceit->first,
15179ccaf77SBrad Bishop                                      compareFirst(_makers.key_comp()));
15279ccaf77SBrad Bishop 
15379ccaf77SBrad Bishop             if (opsit == _makers.cend() || opsit->first != ifaceit->first)
15479ccaf77SBrad Bishop             {
15579ccaf77SBrad Bishop                 // This interface is not supported.
156615b2a8fSBrad Bishop                 throw InterfaceError("Encountered unsupported interface.",
15779ccaf77SBrad Bishop                                      ifaceit->first);
15879ccaf77SBrad Bishop             }
15979ccaf77SBrad Bishop 
16079ccaf77SBrad Bishop             // Find the binding insertion point or the binding to update.
161615b2a8fSBrad Bishop             refaceit = std::lower_bound(refaceit, refaces.end(), ifaceit->first,
16279ccaf77SBrad Bishop                                         compareFirst(refaces.key_comp()));
16379ccaf77SBrad Bishop 
16479ccaf77SBrad Bishop             if (refaceit == refaces.end() || refaceit->first != ifaceit->first)
16579ccaf77SBrad Bishop             {
16679ccaf77SBrad Bishop                 // Add the new interface.
16702763c68SBrad Bishop                 auto& ctor = std::get<MakeInterfaceType>(opsit->second);
16823a8d935SBrad Bishop                 // skipSignal = true here to avoid getting PropertiesChanged
16923a8d935SBrad Bishop                 // signals while the interface is constructed.  We'll emit an
17023a8d935SBrad Bishop                 // ObjectManager signal for this interface below.
17179ccaf77SBrad Bishop                 refaceit = refaces.insert(
172e96f2aa7SBrad Bishop                     refaceit, std::make_pair(ifaceit->first,
173e96f2aa7SBrad Bishop                                              ctor(_bus, path.str.c_str(),
17423a8d935SBrad Bishop                                                   ifaceit->second, true)));
17579ccaf77SBrad Bishop                 signals.push_back(ifaceit->first);
17679ccaf77SBrad Bishop             }
17779ccaf77SBrad Bishop             else
17879ccaf77SBrad Bishop             {
17979ccaf77SBrad Bishop                 // Set the new property values.
18002763c68SBrad Bishop                 auto& assign = std::get<AssignInterfaceType>(opsit->second);
18123a8d935SBrad Bishop                 assign(ifaceit->second, refaceit->second,
18223a8d935SBrad Bishop                        _status != ManagerStatus::RUNNING);
18379ccaf77SBrad Bishop             }
184b28990f3SDeepak Kodihalli             if (!restoreFromCache)
185b28990f3SDeepak Kodihalli             {
18602763c68SBrad Bishop                 auto& serialize =
18702763c68SBrad Bishop                     std::get<SerializeInterfaceType<SerialOps>>(opsit->second);
1886620e98dSDeepak Kodihalli                 serialize(path, ifaceit->first, refaceit->second);
18979ccaf77SBrad Bishop             }
190b28990f3SDeepak Kodihalli             else
191b28990f3SDeepak Kodihalli             {
19202763c68SBrad Bishop                 auto& deserialize =
19302763c68SBrad Bishop                     std::get<DeserializeInterfaceType<SerialOps>>(
19402763c68SBrad Bishop                         opsit->second);
195b28990f3SDeepak Kodihalli                 deserialize(path, ifaceit->first, refaceit->second);
196b28990f3SDeepak Kodihalli             }
197b28990f3SDeepak Kodihalli         }
19879ccaf77SBrad Bishop         catch (const InterfaceError& e)
19979ccaf77SBrad Bishop         {
20079ccaf77SBrad Bishop             // Reset the binding ops iterator since we are
20179ccaf77SBrad Bishop             // at the end.
20279ccaf77SBrad Bishop             opsit = _makers.cbegin();
20379ccaf77SBrad Bishop             e.log();
20479ccaf77SBrad Bishop         }
20579ccaf77SBrad Bishop 
20679ccaf77SBrad Bishop         ++ifaceit;
20779ccaf77SBrad Bishop     }
20879ccaf77SBrad Bishop 
20923a8d935SBrad Bishop     if (_status == ManagerStatus::RUNNING)
21023a8d935SBrad Bishop     {
21179ccaf77SBrad Bishop         if (newObject)
21279ccaf77SBrad Bishop         {
21379ccaf77SBrad Bishop             _bus.emit_object_added(path.str.c_str());
21479ccaf77SBrad Bishop         }
21579ccaf77SBrad Bishop         else if (!signals.empty())
21679ccaf77SBrad Bishop         {
217a8ff8154SGunnar Mills             _bus.emit_interfaces_added(path.str.c_str(), signals);
21879ccaf77SBrad Bishop         }
21979ccaf77SBrad Bishop     }
22023a8d935SBrad Bishop }
22179ccaf77SBrad Bishop 
updateObjects(const std::map<sdbusplus::message::object_path,Object> & objs,bool restoreFromCache)22279ccaf77SBrad Bishop void Manager::updateObjects(
223b28990f3SDeepak Kodihalli     const std::map<sdbusplus::message::object_path, Object>& objs,
224b28990f3SDeepak Kodihalli     bool restoreFromCache)
22579ccaf77SBrad Bishop {
22679ccaf77SBrad Bishop     auto objit = objs.cbegin();
22779ccaf77SBrad Bishop     auto refit = _refs.begin();
22879ccaf77SBrad Bishop     std::string absPath;
22979ccaf77SBrad Bishop     bool newObj;
23079ccaf77SBrad Bishop 
23179ccaf77SBrad Bishop     while (objit != objs.cend())
23279ccaf77SBrad Bishop     {
23379ccaf77SBrad Bishop         // Find the insertion point or the object to update.
234615b2a8fSBrad Bishop         refit = std::lower_bound(refit, _refs.end(), objit->first,
23579ccaf77SBrad Bishop                                  compareFirst(RelPathCompare(_root)));
23679ccaf77SBrad Bishop 
23779ccaf77SBrad Bishop         absPath.assign(_root);
23879ccaf77SBrad Bishop         absPath.append(objit->first);
23979ccaf77SBrad Bishop 
24079ccaf77SBrad Bishop         newObj = false;
24179ccaf77SBrad Bishop         if (refit == _refs.end() || refit->first != absPath)
24279ccaf77SBrad Bishop         {
24379ccaf77SBrad Bishop             refit = _refs.insert(
244615b2a8fSBrad Bishop                 refit, std::make_pair(absPath, decltype(_refs)::mapped_type()));
24579ccaf77SBrad Bishop             newObj = true;
24679ccaf77SBrad Bishop         }
24779ccaf77SBrad Bishop 
248b28990f3SDeepak Kodihalli         updateInterfaces(absPath, objit->second, refit, newObj,
249b28990f3SDeepak Kodihalli                          restoreFromCache);
250852db67bSMatt Spinler #ifdef CREATE_ASSOCIATIONS
25159521e87SMatt Spinler         if (!_associations.pendingCondition() && newObj)
252852db67bSMatt Spinler         {
25323a8d935SBrad Bishop             _associations.createAssociations(absPath,
254ee294d68SBrad Bishop                                              _status != ManagerStatus::RUNNING);
255852db67bSMatt Spinler         }
25659521e87SMatt Spinler         else if (!restoreFromCache &&
25759521e87SMatt Spinler                  _associations.conditionMatch(objit->first, objit->second))
25859521e87SMatt Spinler         {
25959521e87SMatt Spinler             // The objit path/interface/property matched a pending condition.
26059521e87SMatt Spinler             // Now the associations are valid so attempt to create them against
26159521e87SMatt Spinler             // all existing objects.  If this was the restoreFromCache path,
26259521e87SMatt Spinler             // objit doesn't contain property values so don't bother checking.
26359521e87SMatt Spinler             std::for_each(_refs.begin(), _refs.end(), [this](const auto& ref) {
26459521e87SMatt Spinler                 _associations.createAssociations(
26559521e87SMatt Spinler                     ref.first, _status != ManagerStatus::RUNNING);
26659521e87SMatt Spinler             });
26759521e87SMatt Spinler         }
268852db67bSMatt Spinler #endif
26979ccaf77SBrad Bishop         ++objit;
27079ccaf77SBrad Bishop     }
27179ccaf77SBrad Bishop }
27279ccaf77SBrad Bishop 
notify(std::map<sdbusplus::message::object_path,Object> objs)27303f4cd95SBrad Bishop void Manager::notify(std::map<sdbusplus::message::object_path, Object> objs)
27449aefb31SBrad Bishop {
275cda036f7SBrad Bishop     updateObjects(objs);
27649aefb31SBrad Bishop }
27749aefb31SBrad Bishop 
handleEvent(sdbusplus::message_t & msg,const Event & event,const EventInfo & info)278563306f6SPatrick Williams void Manager::handleEvent(sdbusplus::message_t& msg, const Event& event,
27968c80839SBrad Bishop                           const EventInfo& info)
28049aefb31SBrad Bishop {
28168c80839SBrad Bishop     auto& actions = std::get<1>(info);
2823d57f507SBrad Bishop 
28348547a85SBrad Bishop     for (auto& f : event)
2847b33777bSBrad Bishop     {
28507934a64SBrad Bishop         if (!f(_bus, msg, *this))
286064c94a6SBrad Bishop         {
287064c94a6SBrad Bishop             return;
288064c94a6SBrad Bishop         }
289064c94a6SBrad Bishop     }
2909007432aSBrad Bishop     for (auto& action : actions)
2917b33777bSBrad Bishop     {
29207934a64SBrad Bishop         action(_bus, *this);
2933d57f507SBrad Bishop     }
29449aefb31SBrad Bishop }
29549aefb31SBrad Bishop 
destroyObjects(const std::vector<const char * > & paths)296615b2a8fSBrad Bishop void Manager::destroyObjects(const std::vector<const char*>& paths)
2977b7e712cSBrad Bishop {
298a5cc34c2SBrad Bishop     std::string p;
299a5cc34c2SBrad Bishop 
3007b7e712cSBrad Bishop     for (const auto& path : paths)
301656a7d00SBrad Bishop     {
302a5cc34c2SBrad Bishop         p.assign(_root);
303a5cc34c2SBrad Bishop         p.append(path);
304a5cc34c2SBrad Bishop         _bus.emit_object_removed(p.c_str());
305a5cc34c2SBrad Bishop         _refs.erase(p);
306656a7d00SBrad Bishop     }
3077b7e712cSBrad Bishop }
308656a7d00SBrad Bishop 
createObjects(const std::map<sdbusplus::message::object_path,Object> & objs)309eb68a687SBrad Bishop void Manager::createObjects(
310eb68a687SBrad Bishop     const std::map<sdbusplus::message::object_path, Object>& objs)
311eb68a687SBrad Bishop {
312cda036f7SBrad Bishop     updateObjects(objs);
313eb68a687SBrad Bishop }
314eb68a687SBrad Bishop 
getInterfaceHolder(const char * path,const char * interface)31525d54b51SBrad Bishop std::any& Manager::getInterfaceHolder(const char* path, const char* interface)
316b83a21eaSBrad Bishop {
31725d54b51SBrad Bishop     return const_cast<std::any&>(
318615b2a8fSBrad Bishop         const_cast<const Manager*>(this)->getInterfaceHolder(path, interface));
319b83a21eaSBrad Bishop }
320b83a21eaSBrad Bishop 
getInterfaceHolder(const char * path,const char * interface) const32125d54b51SBrad Bishop const std::any& Manager::getInterfaceHolder(const char* path,
322615b2a8fSBrad Bishop                                             const char* interface) const
323b83a21eaSBrad Bishop {
324b83a21eaSBrad Bishop     std::string p{path};
325b83a21eaSBrad Bishop     auto oit = _refs.find(_root + p);
326b83a21eaSBrad Bishop     if (oit == _refs.end())
327615b2a8fSBrad Bishop         throw std::runtime_error(_root + p + " was not found");
328b83a21eaSBrad Bishop 
329b83a21eaSBrad Bishop     auto& obj = oit->second;
330b83a21eaSBrad Bishop     auto iit = obj.find(interface);
331b83a21eaSBrad Bishop     if (iit == obj.end())
332615b2a8fSBrad Bishop         throw std::runtime_error("interface was not found");
333b83a21eaSBrad Bishop 
334150147aeSBrad Bishop     return iit->second;
335b83a21eaSBrad Bishop }
336b83a21eaSBrad Bishop 
restore()337b28990f3SDeepak Kodihalli void Manager::restore()
338b28990f3SDeepak Kodihalli {
339e6b21c74SKun Yi     namespace fs = std::filesystem;
340b28990f3SDeepak Kodihalli 
341b28990f3SDeepak Kodihalli     if (!fs::exists(fs::path(PIM_PERSIST_PATH)))
342b28990f3SDeepak Kodihalli     {
343b28990f3SDeepak Kodihalli         return;
344b28990f3SDeepak Kodihalli     }
345b28990f3SDeepak Kodihalli 
346*7edafe06SPatrick Williams     static const std::string remove = std::string(PIM_PERSIST_PATH) +
347*7edafe06SPatrick Williams                                       INVENTORY_ROOT;
348b28990f3SDeepak Kodihalli 
349b28990f3SDeepak Kodihalli     std::map<sdbusplus::message::object_path, Object> objects;
350b28990f3SDeepak Kodihalli     for (const auto& dirent :
351b28990f3SDeepak Kodihalli          fs::recursive_directory_iterator(PIM_PERSIST_PATH))
352b28990f3SDeepak Kodihalli     {
353b28990f3SDeepak Kodihalli         const auto& path = dirent.path();
354b28990f3SDeepak Kodihalli         if (fs::is_regular_file(path))
355b28990f3SDeepak Kodihalli         {
356b28990f3SDeepak Kodihalli             auto ifaceName = path.filename().string();
357b28990f3SDeepak Kodihalli             auto objPath = path.parent_path().string();
358b28990f3SDeepak Kodihalli             objPath.erase(0, remove.length());
359b28990f3SDeepak Kodihalli             auto objit = objects.find(objPath);
360b28990f3SDeepak Kodihalli             Interface propertyMap{};
361b28990f3SDeepak Kodihalli             if (objects.end() != objit)
362b28990f3SDeepak Kodihalli             {
363b28990f3SDeepak Kodihalli                 auto& object = objit->second;
364b28990f3SDeepak Kodihalli                 object.emplace(std::move(ifaceName), std::move(propertyMap));
365b28990f3SDeepak Kodihalli             }
366b28990f3SDeepak Kodihalli             else
367b28990f3SDeepak Kodihalli             {
368b28990f3SDeepak Kodihalli                 Object object;
369b28990f3SDeepak Kodihalli                 object.emplace(std::move(ifaceName), std::move(propertyMap));
370b28990f3SDeepak Kodihalli                 objects.emplace(std::move(objPath), std::move(object));
371b28990f3SDeepak Kodihalli             }
372b28990f3SDeepak Kodihalli         }
373b28990f3SDeepak Kodihalli     }
374b28990f3SDeepak Kodihalli     if (!objects.empty())
375b28990f3SDeepak Kodihalli     {
376b28990f3SDeepak Kodihalli         auto restoreFromCache = true;
377b28990f3SDeepak Kodihalli         updateObjects(objects, restoreFromCache);
37859521e87SMatt Spinler 
37959521e87SMatt Spinler #ifdef CREATE_ASSOCIATIONS
38059521e87SMatt Spinler         // There may be conditional associations waiting to be loaded
38159521e87SMatt Spinler         // based on certain path/interface/property values.  Now that
38259521e87SMatt Spinler         // _refs contains all objects with their property values, check
38359521e87SMatt Spinler         // which property values the conditions need and set them in the
38459521e87SMatt Spinler         // condition structure entries, using the actualValue field.  Then
38559521e87SMatt Spinler         // the associations manager can check if the conditions are met.
38659521e87SMatt Spinler         if (_associations.pendingCondition())
38759521e87SMatt Spinler         {
38859521e87SMatt Spinler             ObjectReferences::iterator refIt;
38959521e87SMatt Spinler             InterfaceComposite::iterator ifaceIt;
39059521e87SMatt Spinler 
39159521e87SMatt Spinler             auto& conditions = _associations.getConditions();
39259521e87SMatt Spinler             for (auto& condition : conditions)
39359521e87SMatt Spinler             {
39459521e87SMatt Spinler                 refIt = _refs.find(_root + condition.path);
39559521e87SMatt Spinler                 if (refIt != _refs.end())
39659521e87SMatt Spinler                 {
39759521e87SMatt Spinler                     ifaceIt = refIt->second.find(condition.interface);
39859521e87SMatt Spinler                 }
39959521e87SMatt Spinler 
40059521e87SMatt Spinler                 if ((refIt != _refs.end()) && (ifaceIt != refIt->second.end()))
40159521e87SMatt Spinler                 {
40259521e87SMatt Spinler                     const auto& maker = _makers.find(condition.interface);
40359521e87SMatt Spinler                     if (maker != _makers.end())
40459521e87SMatt Spinler                     {
40559521e87SMatt Spinler                         auto& getProperty =
40659521e87SMatt Spinler                             std::get<GetPropertyValueType>(maker->second);
40759521e87SMatt Spinler 
408*7edafe06SPatrick Williams                         condition.actualValue = getProperty(condition.property,
409*7edafe06SPatrick Williams                                                             ifaceIt->second);
41059521e87SMatt Spinler                     }
41159521e87SMatt Spinler                 }
41259521e87SMatt Spinler             }
41359521e87SMatt Spinler 
41459521e87SMatt Spinler             // Check if a property value in a condition matches an
41559521e87SMatt Spinler             // actual property value just saved.  If one did, now the
41659521e87SMatt Spinler             // associations file is valid so create its associations.
41759521e87SMatt Spinler             if (_associations.conditionMatch())
41859521e87SMatt Spinler             {
419*7edafe06SPatrick Williams                 std::for_each(_refs.begin(), _refs.end(),
420*7edafe06SPatrick Williams                               [this](const auto& ref) {
42159521e87SMatt Spinler                     _associations.createAssociations(
42259521e87SMatt Spinler                         ref.first, _status != ManagerStatus::RUNNING);
42359521e87SMatt Spinler                 });
42459521e87SMatt Spinler             }
42559521e87SMatt Spinler         }
42659521e87SMatt Spinler #endif
427b28990f3SDeepak Kodihalli     }
428b28990f3SDeepak Kodihalli }
429b28990f3SDeepak Kodihalli 
43049aefb31SBrad Bishop } // namespace manager
43149aefb31SBrad Bishop } // namespace inventory
43249aefb31SBrad Bishop } // namespace phosphor
43349aefb31SBrad Bishop 
43449aefb31SBrad Bishop // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
435