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 <fmt/format.h>
1814fe6698SNan Zhou 
1914fe6698SNan Zhou #include <phosphor-logging/log.hpp>
2014fe6698SNan Zhou #include <sdbusplus/bus.hpp>
2114fe6698SNan Zhou #include <sdbusplus/message.hpp>
2214fe6698SNan Zhou 
2314fe6698SNan Zhou #include <functional>
2414fe6698SNan Zhou #include <iostream>
2514fe6698SNan Zhou #include <variant>
2614fe6698SNan Zhou 
2714fe6698SNan Zhou using fmt::format;
2814fe6698SNan Zhou using phosphor::logging::level;
2914fe6698SNan Zhou using phosphor::logging::log;
3014fe6698SNan Zhou 
3114fe6698SNan Zhou HostManager::HostManager() :
3214fe6698SNan Zhou     postcodes_(), bus_(sdbusplus::bus::new_default()),
3314fe6698SNan Zhou     signal_(bus_, HostManager::GetMatch().c_str(),
3414fe6698SNan Zhou             [this](auto& m) -> void { this->DbusHandleSignal(m); }),
3514fe6698SNan Zhou     post_poller_enabled_(true)
3614fe6698SNan Zhou {
3714fe6698SNan Zhou     // Spin off thread to listen on bus_
3814fe6698SNan Zhou     auto post_poller_thread = std::mem_fn(&HostManager::PostPollerThread);
3914fe6698SNan Zhou     post_poller_ = std::make_unique<std::thread>(post_poller_thread, this);
4014fe6698SNan Zhou }
4114fe6698SNan Zhou 
42*59ac2c2dSPatrick Williams int HostManager::DbusHandleSignal(sdbusplus::message_t& msg)
4314fe6698SNan Zhou {
4414fe6698SNan Zhou     log<level::INFO>("Property Changed!");
4514fe6698SNan Zhou     std::string msgSensor, busName{POSTCODE_BUSNAME};
4614fe6698SNan Zhou     std::map<std::string,
4714fe6698SNan Zhou              std::variant<std::tuple<uint64_t, std::vector<uint8_t>>>>
4814fe6698SNan Zhou         msgData;
4914fe6698SNan Zhou     msg.read(msgSensor, msgData);
5014fe6698SNan Zhou 
5114fe6698SNan Zhou     if (msgSensor == busName)
5214fe6698SNan Zhou     {
5314fe6698SNan Zhou         auto valPropMap = msgData.find("Value");
5414fe6698SNan Zhou         if (valPropMap != msgData.end())
5514fe6698SNan Zhou         {
5614fe6698SNan Zhou             uint64_t rawValue =
5714fe6698SNan Zhou                 std::get<uint64_t>(std::get<0>(valPropMap->second));
5814fe6698SNan Zhou 
5914fe6698SNan Zhou             PushPostcode(rawValue);
6014fe6698SNan Zhou         }
6114fe6698SNan Zhou     }
6214fe6698SNan Zhou 
6314fe6698SNan Zhou     return 0;
6414fe6698SNan Zhou }
6514fe6698SNan Zhou 
6614fe6698SNan Zhou void HostManager::PushPostcode(uint64_t postcode)
6714fe6698SNan Zhou {
6814fe6698SNan Zhou     // Get lock
6914fe6698SNan Zhou     std::lock_guard<std::mutex> lock(postcodes_lock_);
7014fe6698SNan Zhou     // Add postcode to queue
7114fe6698SNan Zhou     postcodes_.push_back(postcode);
7214fe6698SNan Zhou }
7314fe6698SNan Zhou 
7414fe6698SNan Zhou std::vector<uint64_t> HostManager::DrainPostcodes()
7514fe6698SNan Zhou {
7614fe6698SNan Zhou     // Get lock
7714fe6698SNan Zhou     std::lock_guard<std::mutex> lock(postcodes_lock_);
7814fe6698SNan Zhou 
7914fe6698SNan Zhou     auto count = postcodes_.size();
8014fe6698SNan Zhou     if (count > 0)
8114fe6698SNan Zhou     {
8214fe6698SNan Zhou         std::string msg = format("Draining Postcodes. Count: {}.", count);
8314fe6698SNan Zhou         log<level::ERR>(msg.c_str());
8414fe6698SNan Zhou     }
8514fe6698SNan Zhou 
8614fe6698SNan Zhou     // Drain the queue into a list
8714fe6698SNan Zhou     // TODO: maximum # postcodes?
8814fe6698SNan Zhou     std::vector<uint64_t> result(postcodes_);
8914fe6698SNan Zhou     postcodes_.clear();
9014fe6698SNan Zhou 
9114fe6698SNan Zhou     return result;
9214fe6698SNan Zhou }
9314fe6698SNan Zhou 
9414fe6698SNan Zhou std::string HostManager::GetMatch()
9514fe6698SNan Zhou {
9614fe6698SNan Zhou     std::string obj{POSTCODE_OBJECTPATH};
9714fe6698SNan Zhou     return std::string("type='signal',"
9814fe6698SNan Zhou                        "interface='org.freedesktop.DBus.Properties',"
9914fe6698SNan Zhou                        "member='PropertiesChanged',"
10014fe6698SNan Zhou                        "path='" +
10114fe6698SNan Zhou                        obj + "'");
10214fe6698SNan Zhou }
10314fe6698SNan Zhou 
10414fe6698SNan Zhou void HostManager::PostPollerThread()
10514fe6698SNan Zhou {
10614fe6698SNan Zhou     while (post_poller_enabled_)
10714fe6698SNan Zhou     {
10814fe6698SNan Zhou         bus_.process_discard();
10914fe6698SNan Zhou         bus_.wait();
11014fe6698SNan Zhou     }
11114fe6698SNan Zhou }
112