From 6226af8fe1db626417c6202fc1b997c4aeff54b9 Mon Sep 17 00:00:00 2001 From: Zhanglong Xia Date: Tue, 10 Dec 2024 09:38:10 +0800 Subject: [PATCH] [spinel] save the radio spinel metrics to temporary settings The otRadioSpinelMetrics includes metrics that record the count of the RCP timeout and the count of RCP reboot and so on. After these events happen, the Thread stack will exits and the system will re-start the Thread stack again. In this case, metrics of the otRadioSpinelMetrics will be cleared and metrics values are awalys 0. This commit adds a temporary settings to store the radio spinel metrics. The temporary settings will clear all settings after the system reboots. --- src/lib/spinel/radio_spinel.cpp | 78 +++++++++++- src/lib/spinel/radio_spinel.hpp | 66 +++++++++- src/posix/platform/CMakeLists.txt | 1 + src/posix/platform/openthread-posix-config.h | 10 ++ src/posix/platform/radio.cpp | 20 ++- src/posix/platform/radio.hpp | 32 +++++ src/posix/platform/temp_settings.cpp | 127 +++++++++++++++++++ src/posix/platform/temp_settings.hpp | 93 ++++++++++++++ 8 files changed, 419 insertions(+), 8 deletions(-) create mode 100644 src/posix/platform/temp_settings.cpp create mode 100644 src/posix/platform/temp_settings.hpp diff --git a/src/lib/spinel/radio_spinel.cpp b/src/lib/spinel/radio_spinel.cpp index f467c1f2849..7be1e4985a0 100644 --- a/src/lib/spinel/radio_spinel.cpp +++ b/src/lib/spinel/radio_spinel.cpp @@ -108,6 +108,7 @@ RadioSpinel::RadioSpinel(void) , mTxRadioEndUs(UINT64_MAX) , mRadioTimeRecalcStart(UINT64_MAX) , mRadioTimeOffset(UINT64_MAX) + , mRadioSpinelMetrics(mCallbacks) #if OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE , mVendorRestorePropertiesCallback(nullptr) , mVendorRestorePropertiesContext(nullptr) @@ -120,7 +121,6 @@ RadioSpinel::RadioSpinel(void) , mTimeSyncOn(false) , mSpinelDriver(nullptr) { - memset(&mRadioSpinelMetrics, 0, sizeof(mRadioSpinelMetrics)); memset(&mCallbacks, 0, sizeof(mCallbacks)); } @@ -170,6 +170,8 @@ void RadioSpinel::Init(bool aSkipRcpVersionCheck, mTxRadioFrame.mPsdu = mTxPsdu; mAckRadioFrame.mPsdu = mAckPsdu; + mRadioSpinelMetrics.Init(); + exit: SuccessOrDie(error); } @@ -2005,7 +2007,7 @@ void RadioSpinel::HandleRcpUnexpectedReset(spinel_status_t aStatus) { OT_UNUSED_VARIABLE(aStatus); - mRadioSpinelMetrics.mRcpUnexpectedResetCount++; + mRadioSpinelMetrics.IncreaseRcpUnexpectedResetCount(); LogCrit("Unexpected RCP reset: %s", spinel_status_to_cstr(aStatus)); #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 @@ -2019,7 +2021,7 @@ void RadioSpinel::HandleRcpUnexpectedReset(spinel_status_t aStatus) void RadioSpinel::HandleRcpTimeout(void) { - mRadioSpinelMetrics.mRcpTimeoutCount++; + mRadioSpinelMetrics.IncreaseRcpTimeoutCount(); #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 mRcpFailure = kRcpFailureTimeout; @@ -2055,7 +2057,7 @@ void RadioSpinel::RecoverFromRcpFailure(void) LogWarn("RCP failure detected"); - ++mRadioSpinelMetrics.mRcpRestorationCount; + mRadioSpinelMetrics.IncreaseRcpRestorationCount(); ++mRcpFailureCount; if (mRcpFailureCount > kMaxFailureCount) { @@ -2457,5 +2459,73 @@ void RadioSpinel::HandleCompatibilityError(void) DieNow(OT_EXIT_RADIO_SPINEL_INCOMPATIBLE); } +void RadioSpinel::Metrics::Init() { ReadMetrics(*reinterpret_cast(this)); } + +const otRadioSpinelMetrics *RadioSpinel::Metrics::GetMetrics(void) const +{ + return reinterpret_cast(this); +} + +bool RadioSpinel::Metrics::IsReadWriteCallbackValid(void) +{ + return (mCallbacks.mWriteRadioSpinelMetrics != nullptr) && (mCallbacks.mReadRadioSpinelMetrics != nullptr); +} + +void RadioSpinel::Metrics::ReadMetrics(otRadioSpinelMetrics &aMetrics) +{ + VerifyOrExit(IsReadWriteCallbackValid()); + + if (mCallbacks.mReadRadioSpinelMetrics(aMetrics, mCallbacks.mRadioSpinelMetricsContext) != OT_ERROR_NONE) + { + memset(&aMetrics, 0, sizeof(aMetrics)); + mCallbacks.mWriteRadioSpinelMetrics(aMetrics, mCallbacks.mRadioSpinelMetricsContext); + } + +exit: + return; +} + +void RadioSpinel::Metrics::WriteMetrics(otRadioSpinelMetrics &aMetrics) +{ + VerifyOrExit(IsReadWriteCallbackValid()); + mCallbacks.mWriteRadioSpinelMetrics(aMetrics, mCallbacks.mRadioSpinelMetricsContext); + +exit: + return; +} + +void RadioSpinel::Metrics::IncreaseCount(MetricType aType) +{ + otRadioSpinelMetrics *metrics = reinterpret_cast(this); + + ReadMetrics(*metrics); + + IncreaseMetricCount(*metrics, aType); + + WriteMetrics(*metrics); +} + +void RadioSpinel::Metrics::IncreaseMetricCount(otRadioSpinelMetrics &aMetrics, MetricType aType) +{ + switch (aType) + { + case kTypeTimeoutCount: + aMetrics.mRcpTimeoutCount++; + break; + case kTypeUnexpectResetCount: + aMetrics.mRcpUnexpectedResetCount++; + break; + case kTypeRestorationCount: + aMetrics.mRcpRestorationCount++; + break; + case kTypeSpinelParseErrorCount: + aMetrics.mSpinelParseErrorCount++; + break; + default: + OT_ASSERT(false); + break; + } +} + } // namespace Spinel } // namespace ot diff --git a/src/lib/spinel/radio_spinel.hpp b/src/lib/spinel/radio_spinel.hpp index 90de94ce7e2..888407ebb5e 100644 --- a/src/lib/spinel/radio_spinel.hpp +++ b/src/lib/spinel/radio_spinel.hpp @@ -134,6 +134,28 @@ struct RadioSpinelCallbacks */ void (*mDiagTransmitDone)(otInstance *aInstance, otRadioFrame *aFrame, Error aError); #endif // OPENTHREAD_CONFIG_DIAG_ENABLE + + /** + * This method writes the radio spinel metrics to the temporarily storage. + * + * @param[in] aMetrics A reference to the radio spinel metrics. + * @param[in] aContext A pointer to application-specific context. + */ + void (*mWriteRadioSpinelMetrics)(const otRadioSpinelMetrics &aMetrics, void *aContext); + + /** + * This method reads the radio spinel metrics from the temporarily storage. + * + * @param[out] aMetrics A reference to the radio spinel metrics. + * @param[in] aContext A pointer to application-specific context. + */ + otError (*mReadRadioSpinelMetrics)(otRadioSpinelMetrics &aMetrics, void *aContext); + + /** + * The pointer to application-specific context for methods `mWriteRadioSpinelMetrics` and + * `mReadRadioSpinelMetrics`. + */ + void *mRadioSpinelMetricsContext; }; /** @@ -958,7 +980,7 @@ class RadioSpinel : private Logger * * @returns The radio Spinel metrics. */ - const otRadioSpinelMetrics *GetRadioSpinelMetrics(void) const { return &mRadioSpinelMetrics; } + const otRadioSpinelMetrics *GetRadioSpinelMetrics(void) const { return mRadioSpinelMetrics.GetMetrics(); } #if OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE /** @@ -1198,7 +1220,10 @@ class RadioSpinel : private Logger void UpdateParseErrorCount(otError aError) { - mRadioSpinelMetrics.mSpinelParseErrorCount += (aError == OT_ERROR_PARSE) ? 1 : 0; + if (aError == OT_ERROR_PARSE) + { + mRadioSpinelMetrics.IncreaseSpinelParseErrorCount(); + } } otError SetMacKey(uint8_t aKeyIdMode, @@ -1216,6 +1241,41 @@ class RadioSpinel : private Logger void HandleCompatibilityError(void); + class Metrics : public otRadioSpinelMetrics + { + public: + Metrics(RadioSpinelCallbacks &aCallbacks) + : mCallbacks(aCallbacks) + { + memset(reinterpret_cast(this), 0, sizeof(otRadioSpinelMetrics)); + } + + void Init(); + const otRadioSpinelMetrics *GetMetrics(void) const; + + void IncreaseRcpTimeoutCount(void) { IncreaseCount(kTypeTimeoutCount); } + void IncreaseRcpUnexpectedResetCount(void) { IncreaseCount(kTypeUnexpectResetCount); } + void IncreaseRcpRestorationCount(void) { IncreaseCount(kTypeRestorationCount); } + void IncreaseSpinelParseErrorCount(void) { IncreaseCount(kTypeSpinelParseErrorCount); } + + private: + enum MetricType : uint8_t + { + kTypeTimeoutCount, + kTypeUnexpectResetCount, + kTypeRestorationCount, + kTypeSpinelParseErrorCount, + }; + + bool IsReadWriteCallbackValid(void); + void ReadMetrics(otRadioSpinelMetrics &aMetrics); + void WriteMetrics(otRadioSpinelMetrics &aMetrics); + void IncreaseCount(MetricType aType); + void IncreaseMetricCount(otRadioSpinelMetrics &aMetrics, MetricType aType); + + RadioSpinelCallbacks &mCallbacks; + }; + otInstance *mInstance; RadioSpinelCallbacks mCallbacks; ///< Callbacks for notifications of higher layer. @@ -1317,7 +1377,7 @@ class RadioSpinel : private Logger MaxPowerTable mMaxPowerTable; - otRadioSpinelMetrics mRadioSpinelMetrics; + Metrics mRadioSpinelMetrics; #if OPENTHREAD_SPINEL_CONFIG_VENDOR_HOOK_ENABLE otRadioSpinelVendorRestorePropertiesCallback mVendorRestorePropertiesCallback; diff --git a/src/posix/platform/CMakeLists.txt b/src/posix/platform/CMakeLists.txt index 4b94da29374..d572316a2ec 100644 --- a/src/posix/platform/CMakeLists.txt +++ b/src/posix/platform/CMakeLists.txt @@ -150,6 +150,7 @@ add_library(openthread-posix spinel_manager.cpp spi_interface.cpp system.cpp + temp_settings.cpp trel.cpp udp.cpp utils.cpp diff --git a/src/posix/platform/openthread-posix-config.h b/src/posix/platform/openthread-posix-config.h index a9849485c93..9aba6024ea5 100644 --- a/src/posix/platform/openthread-posix-config.h +++ b/src/posix/platform/openthread-posix-config.h @@ -425,4 +425,14 @@ #define OPENTHREAD_POSIX_CONFIG_TREL_SELECT_INFRA_IF 0 #endif +/** + * @def OPENTHREAD_POSIX_CONFIG_TEMP_SETTINGS_ENABLE + * + * Define as 1 to enable the temporary settings. The key-value pairs stored in the temporary settings will be erased + * after the system is rebooted. + */ +#ifndef OPENTHREAD_POSIX_CONFIG_TEMP_SETTINGS_ENABLE +#define OPENTHREAD_POSIX_CONFIG_TEMP_SETTINGS_ENABLE 1 +#endif + #endif // OPENTHREAD_PLATFORM_POSIX_CONFIG_H_ diff --git a/src/posix/platform/radio.cpp b/src/posix/platform/radio.cpp index 823af6784f7..d6dbd3bc388 100644 --- a/src/posix/platform/radio.cpp +++ b/src/posix/platform/radio.cpp @@ -67,6 +67,9 @@ Radio::Radio(void) #if OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE , mRcpCapsDiag(mRadioSpinel) #endif +#if OPENTHREAD_POSIX_CONFIG_TEMP_SETTINGS_ENABLE + , mTempSettings() +#endif { } @@ -94,6 +97,12 @@ void Radio::Init(const char *aUrl) callbacks.mReceiveDone = otPlatRadioReceiveDone; callbacks.mTransmitDone = otPlatRadioTxDone; callbacks.mTxStarted = otPlatRadioTxStarted; +#if OPENTHREAD_POSIX_CONFIG_TEMP_SETTINGS_ENABLE + callbacks.mWriteRadioSpinelMetrics = WriteRadioSpinelMetrics; + callbacks.mReadRadioSpinelMetrics = ReadRadioSpinelMetrics; + callbacks.mRadioSpinelMetricsContext = reinterpret_cast(this); + mTempSettings.Init(); +#endif resetRadio = !mRadioUrl.HasParam("no-reset"); skipCompatibilityCheck = mRadioUrl.HasParam("skip-rcp-compatibility-check"); @@ -105,6 +114,15 @@ void Radio::Init(const char *aUrl) ProcessRadioUrl(mRadioUrl); } +void Radio::Deinit(void) +{ + mRadioSpinel.Deinit(); + +#if OPENTHREAD_POSIX_CONFIG_TEMP_SETTINGS_ENABLE + mTempSettings.Deinit(); +#endif +} + void Radio::ProcessRadioUrl(const RadioUrl &aRadioUrl) { const char *region; @@ -215,7 +233,7 @@ ot::Spinel::RadioSpinel &GetRadioSpinel(void) { return sRadio.GetRadioSpinel(); ot::Posix::RcpCapsDiag &GetRcpCapsDiag(void) { return sRadio.GetRcpCapsDiag(); } #endif -void platformRadioDeinit(void) { GetRadioSpinel().Deinit(); } +void platformRadioDeinit(void) { sRadio.Deinit(); } void platformRadioHandleStateChange(otInstance *aInstance, otChangedFlags aFlags) { diff --git a/src/posix/platform/radio.hpp b/src/posix/platform/radio.hpp index b1b700fb7e7..7c9ea550bd2 100644 --- a/src/posix/platform/radio.hpp +++ b/src/posix/platform/radio.hpp @@ -35,6 +35,7 @@ #include "rcp_caps_diag.hpp" #include "spi_interface.hpp" #include "spinel_manager.hpp" +#include "temp_settings.hpp" #include "vendor_interface.hpp" #include "common/code_utils.hpp" #include "lib/spinel/radio_spinel.hpp" @@ -68,6 +69,11 @@ class Radio : public Logger */ void Init(const char *aUrl); + /** + * De-initializes the Thread radio. + */ + void Deinit(void); + /** * Acts as an accessor to the spinel interface instance used by the radio. * @@ -95,6 +101,28 @@ class Radio : public Logger void ProcessRadioUrl(const RadioUrl &aRadioUrl); void ProcessMaxPowerTable(const RadioUrl &aRadioUrl); +#if OPENTHREAD_POSIX_CONFIG_TEMP_SETTINGS_ENABLE + static void WriteRadioSpinelMetrics(const otRadioSpinelMetrics &aMetrics, void *aContext) + { + reinterpret_cast(aContext)->WriteRadioSpinelMetrics(aMetrics); + } + + void WriteRadioSpinelMetrics(const otRadioSpinelMetrics &aMetrics) + { + mTempSettings.WriteRadioSpinelMetrics(aMetrics); + } + + static otError ReadRadioSpinelMetrics(otRadioSpinelMetrics &aMetrics, void *aContext) + { + return reinterpret_cast(aContext)->ReadRadioSpinelMetrics(aMetrics); + } + + otError ReadRadioSpinelMetrics(otRadioSpinelMetrics &aMetrics) + { + return mTempSettings.ReadRadioSpinelMetrics(aMetrics); + } +#endif + #if OPENTHREAD_POSIX_CONFIG_SPINEL_HDLC_INTERFACE_ENABLE && OPENTHREAD_POSIX_CONFIG_SPINEL_SPI_INTERFACE_ENABLE static constexpr size_t kSpinelInterfaceRawSize = sizeof(ot::Posix::SpiInterface) > sizeof(ot::Posix::HdlcInterface) ? sizeof(ot::Posix::SpiInterface) @@ -125,6 +153,10 @@ class Radio : public Logger #if OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE RcpCapsDiag mRcpCapsDiag; #endif + +#if OPENTHREAD_POSIX_CONFIG_TEMP_SETTINGS_ENABLE + TempSettings mTempSettings; +#endif }; } // namespace Posix diff --git a/src/posix/platform/temp_settings.cpp b/src/posix/platform/temp_settings.cpp new file mode 100644 index 00000000000..310d4e5bbb5 --- /dev/null +++ b/src/posix/platform/temp_settings.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2024, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements the temporary settings module for getting, setting and deleting the temporarily settings. + * All temporary settings will be deleted after the system reboots. + */ + +#include "openthread-posix-config.h" +#include "platform-posix.h" + +#include +#include +#include +#include + +#include "temp_settings.hpp" +#include "common/code_utils.hpp" +#include "common/debug.hpp" +#include "common/encoding.hpp" + +#if OPENTHREAD_POSIX_CONFIG_TEMP_SETTINGS_ENABLE +namespace ot { +namespace Posix { + +void TempSettings::Init(void) +{ + otError error = OT_ERROR_NONE; + time_t storedBootTime; + time_t currentBootTime; + uint16_t valueLength = sizeof(time_t); + + VerifyOrDie(SettingsFileInit(), OT_EXIT_FAILURE); + + currentBootTime = GetBootTime(); + + error = mSettingsFile.Get(kKeyBootTime, 0, reinterpret_cast(&storedBootTime), &valueLength); + + // If failed to get the boot time or the current boot time doesn't match the stored boot time, it means + // the system has been rebooted. + if ((error != OT_ERROR_NONE) || (valueLength != sizeof(time_t)) || !BootTimeMatch(storedBootTime, currentBootTime)) + { + mSettingsFile.Wipe(); + mSettingsFile.Set(kKeyBootTime, reinterpret_cast(¤tBootTime), + static_cast(sizeof(currentBootTime))); + } +} + +void TempSettings::Deinit(void) { mSettingsFile.Deinit(); } + +void TempSettings::WriteRadioSpinelMetrics(const otRadioSpinelMetrics &aMetrics) +{ + mSettingsFile.Set(kKeyRadioSpinelMetrics, reinterpret_cast(&aMetrics), + static_cast(sizeof(aMetrics))); +} + +otError TempSettings::ReadRadioSpinelMetrics(otRadioSpinelMetrics &aMetrics) +{ + uint16_t valueLength = sizeof(aMetrics); + + return mSettingsFile.Get(kKeyRadioSpinelMetrics, 0, reinterpret_cast(&aMetrics), &valueLength); +} + +otError TempSettings::SettingsFileInit(void) +{ + static constexpr size_t kMaxFileBaseNameSize = 32; + char fileBaseName[kMaxFileBaseNameSize]; + const char *offset = getenv("PORT_OFFSET"); + uint64_t nodeId; + + otPlatRadioGetIeeeEui64(gInstance, reinterpret_cast(&nodeId)); + nodeId = ot::BigEndian::HostSwap64(nodeId); + + snprintf(fileBaseName, sizeof(fileBaseName), "%s_%lx-temp", ((offset == nullptr) ? "0" : offset), nodeId); + VerifyOrDie(strlen(fileBaseName) < kMaxFileBaseNameSize, OT_EXIT_FAILURE); + + return mSettingsFile.Init(fileBaseName); +} + +time_t TempSettings::GetBootTime(void) +{ + struct sysinfo info; + time_t curTime; + + VerifyOrDie(sysinfo(&info) == 0, OT_EXIT_ERROR_ERRNO); + VerifyOrDie(time(&curTime) != -1, OT_EXIT_ERROR_ERRNO); + + return (curTime > info.uptime) ? (curTime - info.uptime) : (info.uptime - curTime); +} + +bool TempSettings::BootTimeMatch(time_t aBootTimeA, time_t aBootTimeB) +{ + time_t diff = (aBootTimeA > aBootTimeB) ? (aBootTimeA - aBootTimeB) : (aBootTimeB - aBootTimeA); + + // The unit of the boot time is 1 second. The boot time has 1 second of jitter. + return diff < 2; +} + +} // namespace Posix +} // namespace ot +#endif // OPENTHREAD_POSIX_CONFIG_TEMP_SETTINGS_ENABLE diff --git a/src/posix/platform/temp_settings.hpp b/src/posix/platform/temp_settings.hpp new file mode 100644 index 00000000000..c5dd9cb29af --- /dev/null +++ b/src/posix/platform/temp_settings.hpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OT_POSIX_PLATFORM_STEMP_ETTINGS_HPP_ +#define OT_POSIX_PLATFORM_STEMP_ETTINGS_HPP_ + +#include "openthread-posix-config.h" +#include "platform-posix.h" + +#include "settings_file.hpp" + +#if OPENTHREAD_POSIX_CONFIG_TEMP_SETTINGS_ENABLE +namespace ot { +namespace Posix { + +class TempSettings +{ +public: + TempSettings(void) + : mSettingsFile() + { + } + + /** + * Performs the initialization for the temporary settings file. + */ + void Init(void); + + /** + * Performs the de-initialization for the temporary settings file. + */ + void Deinit(void); + + /** + * Writes the radio spinel metrics to the temporary settings file. + * + * @param[in] aMetrics A reference to the radio spinel metrics. + */ + void WriteRadioSpinelMetrics(const otRadioSpinelMetrics &aMetrics); + + /** + * Reads the radio spinel metrics from the temporary settings file. + * + * @param[out] aMetrics A reference to the radio spinel metrics. + * + * @retval OT_ERROR_NONE The radio spinel metrics was found and fetched successfully. + * @retval OT_ERROR_NOT_FOUND The radio spinel metrics was not found in the setting store. + */ + otError ReadRadioSpinelMetrics(otRadioSpinelMetrics &aMetrics); + +private: + enum + { + kKeyBootTime = 1, + kKeyRadioSpinelMetrics = 2, + }; + + otError SettingsFileInit(void); + time_t GetBootTime(void); + bool BootTimeMatch(time_t aBootTimeA, time_t aBootTimeB); + + SettingsFile mSettingsFile; +}; + +} // namespace Posix +} // namespace ot +#endif // OPENTHREAD_POSIX_CONFIG_TEMP_SETTINGS_ENABLE +#endif // OT_POSIX_PLATFORM_STEMP_ETTINGS_HPP_