blob: 0ff80189c0bffd7a9973501118f029b283901129 [file] [log] [blame] [edit]
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION &
* AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "request_timeout_tracker.hpp"
#include <phosphor-logging/lg2.hpp>
#include <cerrno>
#include <cstddef>
#include <cstdint>
#include <exception>
#include <queue>
#include <string>
#include <system_error>
namespace nsm
{
// Define static member
std::unordered_map<eid_t, std::shared_ptr<DeviceRequestTimeOutTracker>>
DeviceRequestTimeOutTracker::instances;
DeviceRequestTimeOutTracker::DeviceRequestTimeOutTracker(eid_t eid) : eid(eid)
{}
DeviceRequestTimeOutTracker& DeviceRequestTimeOutTracker::getInstance(eid_t eid)
{
if (instances.find(eid) == instances.end())
{
instances[eid] = std::shared_ptr<DeviceRequestTimeOutTracker>(
new DeviceRequestTimeOutTracker(eid));
}
return *instances[eid];
}
void DeviceRequestTimeOutTracker::logFailuresForAllEids()
{
for (const auto& pair : instances)
{
pair.second->logTimeOutFailure();
}
}
bool DeviceRequestTimeOutTracker::isEmpty()
{
return messages.empty();
}
bool DeviceRequestTimeOutTracker::isFull()
{
return messages.size() == MAXSIZE;
}
// push on a full queue, will remove the oldest message
void DeviceRequestTimeOutTracker::push(std::string nsm_request)
{
if (isFull())
{
messages.pop_front();
}
messages.push_back(nsm_request);
}
void DeviceRequestTimeOutTracker::pop()
{
if (isEmpty())
{
return;
}
messages.pop_front();
}
std::string DeviceRequestTimeOutTracker::front()
{
std::string nsm_request;
if (isEmpty())
{
return nsm_request;
}
nsm_request = messages.front();
return nsm_request;
}
void DeviceRequestTimeOutTracker::handleTimeout(std::string nsm_request)
{
if (firstTimeoutMessage.has_value())
{
// skip further timeout messages as first timeout request has been
// recorded
return;
}
firstTimeoutMessage = nsm_request;
}
void DeviceRequestTimeOutTracker::handleNoTimeout(std::string nsm_request)
{
if (firstTimeoutMessage.has_value())
{
// device responded after a timeout, reset tracker params
firstTimeoutMessage = std::nullopt;
emptyQueue();
}
push(nsm_request);
}
void DeviceRequestTimeOutTracker::emptyQueue()
{
messages.clear();
}
void DeviceRequestTimeOutTracker::logTimeOutFailure()
{
lg2::error("******Start logTimeOutFailure: EID={EID}*****", "EID", eid);
if (firstTimeoutMessage.has_value())
{
for (const auto& message : messages)
{
lg2::error(
"logTimeOutFailure: EID={EID}, Last(n) NSM request msg before timeout: {REQ} ",
"EID", eid, "REQ", message);
}
lg2::error(
"logTimeOutFailure: EID={EID}, Timeout for NSM request: {REQ}",
"EID", eid, "REQ", *firstTimeoutMessage);
}
lg2::error("******End logTimeOutFailure: EID={EID}*****", "EID", eid);
}
} // namespace nsm