1/*
2 * Copyright (c) 2024 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#include "kv_adapter_manager.h"
16
17#include <mutex>
18#include <unistd.h>
19
20#include "datetime_ex.h"
21#include "string_ex.h"
22
23#include "dm_anonymous.h"
24#include "dm_constants.h"
25#include "dm_log.h"
26
27namespace OHOS {
28namespace DistributedHardware {
29namespace {
30const std::string DM_KV_STORE_PREFIX = "DM2_";
31constexpr int64_t DM_KV_STORE_REFRESH_TIME = 24 * 60 * 60; // one day
32constexpr int64_t MAX_SUPPORTED_EXIST_TIME = 3 * 24 * 60 * 60; // 3days
33}
34
35DM_IMPLEMENT_SINGLE_INSTANCE(KVAdapterManager);
36
37int32_t KVAdapterManager::Init()
38{
39    LOGI("Init Kv-Adapter manager");
40    {
41        std::lock_guard<std::mutex> lock(idCacheMapMtx_);
42        idCacheMap_.clear();
43    }
44    kvAdapter_ = std::make_shared<KVAdapter>();
45    return kvAdapter_->Init();
46}
47
48void KVAdapterManager::UnInit()
49{
50    LOGI("Uninit Kv-Adapter manager");
51    CHECK_NULL_VOID(kvAdapter_);
52    kvAdapter_->UnInit();
53    kvAdapter_ = nullptr;
54}
55
56void KVAdapterManager::ReInit()
57{
58    LOGI("Re init kv adapter");
59    CHECK_NULL_VOID(kvAdapter_);
60    kvAdapter_->ReInit();
61}
62
63int32_t KVAdapterManager::PutByAnoyDeviceId(const std::string &key, const DmKVValue &value)
64{
65    std::string dmKey = DM_KV_STORE_PREFIX + key;
66    std::lock_guard<std::mutex> lock(idCacheMapMtx_);
67    auto idIter = idCacheMap_.find(dmKey);
68    if (idIter != idCacheMap_.end() && !IsTimeOut(idIter->second.lastModifyTime, value.lastModifyTime,
69        DM_KV_STORE_REFRESH_TIME)) {
70        LOGD("Kv value is existed");
71        return DM_OK;
72    }
73    idCacheMap_[dmKey] = value;
74    std::string prefixKey = DM_KV_STORE_PREFIX + value.appID + DB_KEY_DELIMITER + value.udidHash;
75    idCacheMap_[prefixKey] = value;
76    std::string valueStr = "";
77    ConvertDmKVValueToJson(value, valueStr);
78    CHECK_NULL_RETURN(kvAdapter_, ERR_DM_POINT_NULL);
79    if (kvAdapter_->Put(dmKey, valueStr) != DM_OK) {
80        LOGE("Insert value to DB for dmKey failed");
81        return ERR_DM_FAILED;
82    }
83    if (kvAdapter_->Put(prefixKey, valueStr) != DM_OK) {
84        LOGE("Insert value to DB for prefixKey failed");
85        return ERR_DM_FAILED;
86    }
87    return DM_OK;
88}
89
90int32_t KVAdapterManager::Get(const std::string &key, DmKVValue &value)
91{
92    std::string dmKey = DM_KV_STORE_PREFIX + key;
93    std::lock_guard<std::mutex> lock(idCacheMapMtx_);
94    auto idIter = idCacheMap_.find(dmKey);
95    if (idIter != idCacheMap_.end()) {
96        value = idIter->second;
97        return DM_OK;
98    }
99    CHECK_NULL_RETURN(kvAdapter_, ERR_DM_POINT_NULL);
100    std::string valueStr;
101    if (kvAdapter_->Get(dmKey, valueStr) != DM_OK) {
102        LOGE("Get kv value failed, dmKey: %{public}s", GetAnonyString(dmKey).c_str());
103        return ERR_DM_FAILED;
104    }
105    ConvertJsonToDmKVValue(valueStr, value);
106    idCacheMap_[dmKey] = value;
107    std::string prefixKey = DM_KV_STORE_PREFIX + value.appID + DB_KEY_DELIMITER + value.udidHash;
108    idCacheMap_[prefixKey] = value;
109    return DM_OK;
110}
111
112int32_t KVAdapterManager::DeleteAgedEntry()
113{
114    int64_t nowTime = GetSecondsSince1970ToNow();
115    std::lock_guard<std::mutex> lock(idCacheMapMtx_);
116    for (auto it = idCacheMap_.begin(); it != idCacheMap_.end();) {
117        if (IsTimeOut(it->second.lastModifyTime, nowTime, MAX_SUPPORTED_EXIST_TIME)) {
118            it = idCacheMap_.erase(it);
119        } else {
120            ++it;
121        }
122    }
123    return DM_OK;
124}
125
126inline bool KVAdapterManager::IsTimeOut(int64_t sourceTime, int64_t targetTime, int64_t timeOut)
127{
128    return targetTime - sourceTime >= timeOut ? true : false;
129}
130
131int32_t KVAdapterManager::AppUnintall(const std::string &appId)
132{
133    LOGI("appId %{public}s.", GetAnonyString(appId).c_str());
134    std::lock_guard<std::mutex> lock(idCacheMapMtx_);
135    for (auto it = idCacheMap_.begin(); it != idCacheMap_.end();) {
136        if (it->second.appID == appId) {
137            it = idCacheMap_.erase(it);
138        } else {
139            ++it;
140        }
141    }
142    CHECK_NULL_RETURN(kvAdapter_, ERR_DM_POINT_NULL);
143    if (kvAdapter_->DeleteByAppId(appId, DM_KV_STORE_PREFIX) != DM_OK) {
144        LOGE("DeleteByAppId failed");
145        return ERR_DM_FAILED;
146    }
147    return DM_OK;
148}
149} // namespace DistributedHardware
150} // namespace OHOS
151