114fe6698SNan Zhou // Copyright 2021 Google LLC
214fe6698SNan Zhou //
314fe6698SNan Zhou // Licensed under the Apache License, Version 2.0 (the "License");
414fe6698SNan Zhou // you may not use this file except in compliance with the License.
514fe6698SNan Zhou // You may obtain a copy of the License at
614fe6698SNan Zhou //
714fe6698SNan Zhou //      http://www.apache.org/licenses/LICENSE-2.0
814fe6698SNan Zhou //
914fe6698SNan Zhou // Unless required by applicable law or agreed to in writing, software
1014fe6698SNan Zhou // distributed under the License is distributed on an "AS IS" BASIS,
1114fe6698SNan Zhou // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1214fe6698SNan Zhou // See the License for the specific language governing permissions and
1314fe6698SNan Zhou // limitations under the License.
1414fe6698SNan Zhou 
1514fe6698SNan Zhou #include "host_manager.hpp"
1614fe6698SNan Zhou 
1714fe6698SNan Zhou #include <phosphor-logging/log.hpp>
1814fe6698SNan Zhou #include <sdbusplus/bus.hpp>
1914fe6698SNan Zhou #include <sdbusplus/message.hpp>
2014fe6698SNan Zhou 
21*bb53161dSWilly Tu #include <format>
2214fe6698SNan Zhou #include <variant>
2314fe6698SNan Zhou 
2414fe6698SNan Zhou using phosphor::logging::level;
2514fe6698SNan Zhou using phosphor::logging::log;
2614fe6698SNan Zhou 
HostManager()2714fe6698SNan Zhou HostManager::HostManager() :
2814fe6698SNan Zhou     postcodes_(), bus_(sdbusplus::bus::new_default()),
2914fe6698SNan Zhou     signal_(bus_, HostManager::GetMatch().c_str(),
3014fe6698SNan Zhou             [this](auto& m) -> void { this->DbusHandleSignal(m); }),
3114fe6698SNan Zhou     post_poller_enabled_(true)
3214fe6698SNan Zhou {
3314fe6698SNan Zhou     // Spin off thread to listen on bus_
3414fe6698SNan Zhou     auto post_poller_thread = std::mem_fn(&HostManager::PostPollerThread);
3514fe6698SNan Zhou     post_poller_ = std::make_unique<std::thread>(post_poller_thread, this);
3614fe6698SNan Zhou }
3714fe6698SNan Zhou 
DbusHandleSignal(sdbusplus::message_t & msg)3859ac2c2dSPatrick Williams int HostManager::DbusHandleSignal(sdbusplus::message_t& msg)
3914fe6698SNan Zhou {
4014fe6698SNan Zhou     log<level::INFO>("Property Changed!");
4114fe6698SNan Zhou     std::string msgSensor, busName{POSTCODE_BUSNAME};
4214fe6698SNan Zhou     std::map<std::string,
4314fe6698SNan Zhou              std::variant<std::tuple<uint64_t, std::vector<uint8_t>>>>
4414fe6698SNan Zhou         msgData;
4514fe6698SNan Zhou     msg.read(msgSensor, msgData);
4614fe6698SNan Zhou 
4714fe6698SNan Zhou     if (msgSensor == busName)
4814fe6698SNan Zhou     {
4914fe6698SNan Zhou         auto valPropMap = msgData.find("Value");
5014fe6698SNan Zhou         if (valPropMap != msgData.end())
5114fe6698SNan Zhou         {
5214fe6698SNan Zhou             uint64_t rawValue =
5314fe6698SNan Zhou                 std::get<uint64_t>(std::get<0>(valPropMap->second));
5414fe6698SNan Zhou 
5514fe6698SNan Zhou             PushPostcode(rawValue);
5614fe6698SNan Zhou         }
5714fe6698SNan Zhou     }
5814fe6698SNan Zhou 
5914fe6698SNan Zhou     return 0;
6014fe6698SNan Zhou }
6114fe6698SNan Zhou 
PushPostcode(uint64_t postcode)6214fe6698SNan Zhou void HostManager::PushPostcode(uint64_t postcode)
6314fe6698SNan Zhou {
6414fe6698SNan Zhou     // Get lock
6514fe6698SNan Zhou     std::lock_guard<std::mutex> lock(postcodes_lock_);
6614fe6698SNan Zhou     // Add postcode to queue
6714fe6698SNan Zhou     postcodes_.push_back(postcode);
6814fe6698SNan Zhou }
6914fe6698SNan Zhou 
DrainPostcodes()7014fe6698SNan Zhou std::vector<uint64_t> HostManager::DrainPostcodes()
7114fe6698SNan Zhou {
7214fe6698SNan Zhou     // Get lock
7314fe6698SNan Zhou     std::lock_guard<std::mutex> lock(postcodes_lock_);
7414fe6698SNan Zhou 
7514fe6698SNan Zhou     auto count = postcodes_.size();
7614fe6698SNan Zhou     if (count > 0)
7714fe6698SNan Zhou     {
78*bb53161dSWilly Tu         std::string msg = std::format("Draining Postcodes. Count: {}.", count);
7914fe6698SNan Zhou         log<level::ERR>(msg.c_str());
8014fe6698SNan Zhou     }
8114fe6698SNan Zhou 
8214fe6698SNan Zhou     // Drain the queue into a list
8314fe6698SNan Zhou     // TODO: maximum # postcodes?
8414fe6698SNan Zhou     std::vector<uint64_t> result(postcodes_);
8514fe6698SNan Zhou     postcodes_.clear();
8614fe6698SNan Zhou 
8714fe6698SNan Zhou     return result;
8814fe6698SNan Zhou }
8914fe6698SNan Zhou 
GetMatch()9014fe6698SNan Zhou std::string HostManager::GetMatch()
9114fe6698SNan Zhou {
9214fe6698SNan Zhou     std::string obj{POSTCODE_OBJECTPATH};
9314fe6698SNan Zhou     return std::string("type='signal',"
9414fe6698SNan Zhou                        "interface='org.freedesktop.DBus.Properties',"
9514fe6698SNan Zhou                        "member='PropertiesChanged',"
9614fe6698SNan Zhou                        "path='" +
9714fe6698SNan Zhou                        obj + "'");
9814fe6698SNan Zhou }
9914fe6698SNan Zhou 
PostPollerThread()10014fe6698SNan Zhou void HostManager::PostPollerThread()
10114fe6698SNan Zhou {
10214fe6698SNan Zhou     while (post_poller_enabled_)
10314fe6698SNan Zhou     {
10414fe6698SNan Zhou         bus_.process_discard();
10514fe6698SNan Zhou         bus_.wait();
10614fe6698SNan Zhou     }
10714fe6698SNan Zhou }
108