1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "updater/hwfault_retry.h"
17#include <unistd.h>
18#include "init_reboot.h"
19#include "log/log.h"
20#include "misc_info/misc_info.h"
21#include "updater/updater.h"
22#include "updater/updater_const.h"
23#include "utils.h"
24#include "securec.h"
25
26namespace Updater {
27HwFaultRetry &HwFaultRetry::GetInstance()
28{
29    static HwFaultRetry instance;
30    return instance;
31}
32
33HwFaultRetry::HwFaultRetry()
34{
35    RetryFunc rebootFunc = [this]() {
36                                return this->RebootRetry();
37                            };
38    RegisterFunc(VERIFY_FAILED_REBOOT, rebootFunc);
39    RegisterFunc(IO_FAILED_REBOOT, rebootFunc);
40}
41
42void HwFaultRetry::RegisterFunc(const std::string &faultInfo, RetryFunc func)
43{
44    if (!retryMap_.emplace(faultInfo, func).second) {
45        LOG(ERROR) << "emplace: " << faultInfo.c_str() << " fail";
46    }
47}
48
49void HwFaultRetry::DoRetryAction()
50{
51    auto it = retryMap_.find(faultInfo_);
52    if (it == retryMap_.end() || it->second == nullptr) {
53        LOG(ERROR) << "GetRepair func for: " << faultInfo_.c_str() << " fail";
54        return;
55    }
56    return (it->second)();
57}
58
59void HwFaultRetry::SetFaultInfo(const std::string &faultInfo)
60{
61    faultInfo_ = faultInfo;
62}
63
64void HwFaultRetry::SetRetryCount(const uint32_t count)
65{
66    retryCount_ = count;
67}
68
69void HwFaultRetry::RebootRetry()
70{
71    if (retryCount_ >= MAX_RETRY_COUNT) {
72        LOG(INFO) << "retry more than 3 times, no need retry";
73        return;
74    }
75
76    Utils::AddUpdateInfoToMisc("retry_count", retryCount_ + 1);
77    Utils::SetFaultInfoToMisc(faultInfo_);
78
79    PostUpdater(false);
80    sync();
81#ifndef UPDATER_UT
82    DoReboot("updater:Updater fault retry");
83    while (true) {
84        pause();
85    }
86#endif
87}
88} // Updater
89