blob: 289f91e74175a99f6434455a85dc32bb28c26ee7 [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 requester
{
DeviceRequestTimeOutTracker::DeviceRequestTimeOutTracker(eid_t eid) : eid(eid)
{}
DeviceRequestTimeOutTracker& DeviceRequestTimeOutTracker::instance(eid_t eid)
{
if (instances.find(eid) == instances.end())
{
instances[eid] = std::shared_ptr<DeviceRequestTimeOutTracker>(
new DeviceRequestTimeOutTracker(eid));
}
return *instances[eid];
}
void DeviceRequestTimeOutTracker::logFailures()
{
for (const auto& pair : instances)
{
pair.second->logTimeOutFailure();
}
}
// push on a full queue, will remove the oldest message
void DeviceRequestTimeOutTracker::push(const RequestBase& request)
{
if (size() == MAXSIZE)
{
pop_front();
}
push_back(request);
}
void DeviceRequestTimeOutTracker::pushWithTimeout(const RequestBase& request)
{
auto& tracker = instance(request.eid);
if (tracker.timeoutMessage.has_value())
{
// skip further timeout messages as first timeout request has been
// recorded
return;
}
tracker.timeoutMessage = request;
}
void DeviceRequestTimeOutTracker::pushWithoutTimeout(const RequestBase& request)
{
auto& tracker = instance(request.eid);
if (tracker.timeoutMessage.has_value())
{
// device responded after a timeout, reset tracker params
tracker.timeoutMessage = std::nullopt;
tracker.clear();
}
tracker.push(request);
}
void DeviceRequestTimeOutTracker::logTimeOutFailure() const
{
lg2::error("******Start logTimeOutFailure: EID={EID}*****", "EID", eid);
if (timeoutMessage.has_value())
{
for (const auto& message : *this)
{
lg2::error(
"logTimeOutFailure: EID={EID}, Last(n) NSM request msg before timeout: {REQ} ",
"EID", eid, "REQ",
utils::convertMsgToString(true, message.requestMsg, message.tag,
message.eid));
}
lg2::error(
"logTimeOutFailure: EID={EID}, Timeout for NSM request: {REQ}",
"EID", eid, "REQ",
utils::convertMsgToString(true, timeoutMessage->requestMsg,
timeoutMessage->tag,
timeoutMessage->eid));
}
lg2::error("******End logTimeOutFailure: EID={EID}*****", "EID", eid);
}
} // namespace requester