1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License. 5d9f0492fSopenharmony_ci * You may obtain a copy of the License at 6d9f0492fSopenharmony_ci * 7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d9f0492fSopenharmony_ci * 9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and 13d9f0492fSopenharmony_ci * limitations under the License. 14d9f0492fSopenharmony_ci */ 15d9f0492fSopenharmony_ci#include "param_persist.h" 16d9f0492fSopenharmony_ci 17d9f0492fSopenharmony_ci#include <time.h> 18d9f0492fSopenharmony_ci 19d9f0492fSopenharmony_ci#include "init_param.h" 20d9f0492fSopenharmony_ci#include "init_utils.h" 21d9f0492fSopenharmony_ci#include "param_manager.h" 22d9f0492fSopenharmony_ci#include "param_trie.h" 23d9f0492fSopenharmony_ci#include "param_osadp.h" 24d9f0492fSopenharmony_ci#include "securec.h" 25d9f0492fSopenharmony_ci 26d9f0492fSopenharmony_cistatic ParamPersistWorkSpace g_persistWorkSpace = {0, 0, NULL, {0}, {0}}; 27d9f0492fSopenharmony_cistatic int IsNeedToSave(const char *name) 28d9f0492fSopenharmony_ci{ 29d9f0492fSopenharmony_ci#if defined(__LITEOS_M__) || defined(__LITEOS_A__) 30d9f0492fSopenharmony_ci return IS_READY_ONLY(name) ? 0 : 1; 31d9f0492fSopenharmony_ci#else 32d9f0492fSopenharmony_ci return (strncmp(name, PARAM_PERSIST_PREFIX, strlen(PARAM_PERSIST_PREFIX)) == 0) ? 1 : 0; 33d9f0492fSopenharmony_ci#endif 34d9f0492fSopenharmony_ci} 35d9f0492fSopenharmony_ci 36d9f0492fSopenharmony_cistatic long long GetPersistCommitId(void) 37d9f0492fSopenharmony_ci{ 38d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 39d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return 0, "Invalid paramSpace"); 40d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(paramSpace, return 0, "Invalid space"); 41d9f0492fSopenharmony_ci WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); 42d9f0492fSopenharmony_ci if (space == NULL) { 43d9f0492fSopenharmony_ci return 0; 44d9f0492fSopenharmony_ci } 45d9f0492fSopenharmony_ci PARAMSPACE_AREA_RD_LOCK(space); 46d9f0492fSopenharmony_ci long long globalCommitId = ATOMIC_UINT64_LOAD_EXPLICIT(&space->area->commitPersistId, MEMORY_ORDER_ACQUIRE); 47d9f0492fSopenharmony_ci PARAMSPACE_AREA_RW_UNLOCK(space); 48d9f0492fSopenharmony_ci return globalCommitId; 49d9f0492fSopenharmony_ci} 50d9f0492fSopenharmony_ci 51d9f0492fSopenharmony_cistatic void UpdatePersistCommitId(void) 52d9f0492fSopenharmony_ci{ 53d9f0492fSopenharmony_ci ParamWorkSpace *paramSpace = GetParamWorkSpace(); 54d9f0492fSopenharmony_ci PARAM_CHECK(paramSpace != NULL, return, "Invalid paramSpace"); 55d9f0492fSopenharmony_ci PARAM_WORKSPACE_CHECK(paramSpace, return, "Invalid space"); 56d9f0492fSopenharmony_ci WorkSpace *space = GetWorkSpace(WORKSPACE_INDEX_DAC); 57d9f0492fSopenharmony_ci if (space == NULL) { 58d9f0492fSopenharmony_ci return; 59d9f0492fSopenharmony_ci } 60d9f0492fSopenharmony_ci PARAMSPACE_AREA_RW_LOCK(space); 61d9f0492fSopenharmony_ci ATOMIC_SYNC_ADD_AND_FETCH(&space->area->commitPersistId, 1, MEMORY_ORDER_RELEASE); 62d9f0492fSopenharmony_ci PARAMSPACE_AREA_RW_UNLOCK(space); 63d9f0492fSopenharmony_ci} 64d9f0492fSopenharmony_ci 65d9f0492fSopenharmony_cistatic int SavePersistParam(const WorkSpace *workSpace, const ParamTrieNode *node, const void *cookie) 66d9f0492fSopenharmony_ci{ 67d9f0492fSopenharmony_ci ParamTrieNode *current = (ParamTrieNode *)node; 68d9f0492fSopenharmony_ci if (current == NULL || current->dataIndex == 0) { 69d9f0492fSopenharmony_ci return 0; 70d9f0492fSopenharmony_ci } 71d9f0492fSopenharmony_ci ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex); 72d9f0492fSopenharmony_ci if (entry == NULL) { 73d9f0492fSopenharmony_ci return 0; 74d9f0492fSopenharmony_ci } 75d9f0492fSopenharmony_ci 76d9f0492fSopenharmony_ci if (!IsNeedToSave(entry->data)) { 77d9f0492fSopenharmony_ci return 0; 78d9f0492fSopenharmony_ci } 79d9f0492fSopenharmony_ci 80d9f0492fSopenharmony_ci if ((entry->commitId & PARAM_FLAGS_PERSIST) == 0) { 81d9f0492fSopenharmony_ci return 0; 82d9f0492fSopenharmony_ci } 83d9f0492fSopenharmony_ci static char name[PARAM_NAME_LEN_MAX] = {0}; 84d9f0492fSopenharmony_ci int ret = memcpy_s(name, PARAM_NAME_LEN_MAX - 1, entry->data, entry->keyLength); 85d9f0492fSopenharmony_ci PARAM_CHECK(ret == EOK, return -1, "Failed to read param name %s", entry->data); 86d9f0492fSopenharmony_ci name[entry->keyLength] = '\0'; 87d9f0492fSopenharmony_ci ret = g_persistWorkSpace.persistParamOps.batchSave( 88d9f0492fSopenharmony_ci (PERSIST_SAVE_HANDLE)cookie, name, entry->data + entry->keyLength + 1); 89d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return -1, "Failed to write param %s", current->key); 90d9f0492fSopenharmony_ci return ret; 91d9f0492fSopenharmony_ci} 92d9f0492fSopenharmony_ci 93d9f0492fSopenharmony_cistatic int BatchSavePersistParam(void) 94d9f0492fSopenharmony_ci{ 95d9f0492fSopenharmony_ci PARAM_LOGV("BatchSavePersistParam"); 96d9f0492fSopenharmony_ci if (g_persistWorkSpace.persistParamOps.batchSaveBegin == NULL || 97d9f0492fSopenharmony_ci g_persistWorkSpace.persistParamOps.batchSave == NULL || 98d9f0492fSopenharmony_ci g_persistWorkSpace.persistParamOps.batchSaveEnd == NULL) { 99d9f0492fSopenharmony_ci return 0; 100d9f0492fSopenharmony_ci } 101d9f0492fSopenharmony_ci#if defined(__LITEOS_M__) || defined(__LITEOS_A__) || defined(__LINUX__) 102d9f0492fSopenharmony_ci PERSIST_SAVE_HANDLE handle; 103d9f0492fSopenharmony_ci int ret = g_persistWorkSpace.persistParamOps.batchSaveBegin(&handle); 104d9f0492fSopenharmony_ci#if defined(__LITEOS_M__) || defined(__LITEOS_A__) 105d9f0492fSopenharmony_ci const char *prefix = ""; 106d9f0492fSopenharmony_ci#else 107d9f0492fSopenharmony_ci const char *prefix = PARAM_PERSIST_PREFIX; 108d9f0492fSopenharmony_ci#endif 109d9f0492fSopenharmony_ci#else 110d9f0492fSopenharmony_ci PERSIST_SAVE_HANDLE handle[PERSIST_HANDLE_MAX] = { NULL, NULL }; 111d9f0492fSopenharmony_ci int ret = g_persistWorkSpace.persistParamOps.batchSaveBegin(handle); 112d9f0492fSopenharmony_ci const char *prefix = PARAM_PERSIST_PREFIX; 113d9f0492fSopenharmony_ci#endif 114d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Failed to save persist"); 115d9f0492fSopenharmony_ci // walk and save persist param 116d9f0492fSopenharmony_ci WorkSpace *workSpace = GetNextWorkSpace(NULL); 117d9f0492fSopenharmony_ci while (workSpace != NULL) { 118d9f0492fSopenharmony_ci WorkSpace *next = GetNextWorkSpace(workSpace); 119d9f0492fSopenharmony_ci ParamTrieNode *root = FindTrieNode(workSpace, prefix, strlen(prefix), NULL); 120d9f0492fSopenharmony_ci PARAMSPACE_AREA_RD_LOCK(workSpace); 121d9f0492fSopenharmony_ci TraversalTrieNode(workSpace, root, SavePersistParam, (void *)handle); 122d9f0492fSopenharmony_ci PARAMSPACE_AREA_RW_UNLOCK(workSpace); 123d9f0492fSopenharmony_ci workSpace = next; 124d9f0492fSopenharmony_ci } 125d9f0492fSopenharmony_ci g_persistWorkSpace.persistParamOps.batchSaveEnd(handle); 126d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Save persist param fail"); 127d9f0492fSopenharmony_ci 128d9f0492fSopenharmony_ci PARAM_CLEAR_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE); 129d9f0492fSopenharmony_ci (void)clock_gettime(CLOCK_MONOTONIC, &g_persistWorkSpace.lastSaveTimer); 130d9f0492fSopenharmony_ci return ret; 131d9f0492fSopenharmony_ci} 132d9f0492fSopenharmony_ci 133d9f0492fSopenharmony_ciINIT_LOCAL_API int InitPersistParamWorkSpace(void) 134d9f0492fSopenharmony_ci{ 135d9f0492fSopenharmony_ci if (PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_INIT)) { 136d9f0492fSopenharmony_ci return 0; 137d9f0492fSopenharmony_ci } 138d9f0492fSopenharmony_ci (void)clock_gettime(CLOCK_MONOTONIC, &g_persistWorkSpace.lastSaveTimer); 139d9f0492fSopenharmony_ci RegisterPersistParamOps(&g_persistWorkSpace.persistParamOps); 140d9f0492fSopenharmony_ci PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_INIT); 141d9f0492fSopenharmony_ci return 0; 142d9f0492fSopenharmony_ci} 143d9f0492fSopenharmony_ci 144d9f0492fSopenharmony_ciINIT_LOCAL_API void ClosePersistParamWorkSpace(void) 145d9f0492fSopenharmony_ci{ 146d9f0492fSopenharmony_ci if (g_persistWorkSpace.saveTimer != NULL) { 147d9f0492fSopenharmony_ci ParamTimerClose(g_persistWorkSpace.saveTimer); 148d9f0492fSopenharmony_ci } 149d9f0492fSopenharmony_ci g_persistWorkSpace.flags = 0; 150d9f0492fSopenharmony_ci} 151d9f0492fSopenharmony_ci 152d9f0492fSopenharmony_civoid CheckAndSavePersistParam(void) 153d9f0492fSopenharmony_ci{ 154d9f0492fSopenharmony_ci // check commit 155d9f0492fSopenharmony_ci long long commit = GetPersistCommitId(); 156d9f0492fSopenharmony_ci PARAM_LOGV("CheckAndSavePersistParam commit %lld %lld", commit, g_persistWorkSpace.commitId); 157d9f0492fSopenharmony_ci if (g_persistWorkSpace.commitId == commit) { 158d9f0492fSopenharmony_ci return; 159d9f0492fSopenharmony_ci } 160d9f0492fSopenharmony_ci g_persistWorkSpace.commitId = commit; 161d9f0492fSopenharmony_ci (void)BatchSavePersistParam(); 162d9f0492fSopenharmony_ci} 163d9f0492fSopenharmony_ci 164d9f0492fSopenharmony_ciPARAM_STATIC void TimerCallbackForSave(const ParamTaskPtr timer, void *context) 165d9f0492fSopenharmony_ci{ 166d9f0492fSopenharmony_ci UNUSED(context); 167d9f0492fSopenharmony_ci UNUSED(timer); 168d9f0492fSopenharmony_ci PARAM_LOGV("TimerCallbackForSave "); 169d9f0492fSopenharmony_ci // for liteos-a must cycle check 170d9f0492fSopenharmony_ci#if (!defined(PARAM_SUPPORT_CYCLE_CHECK) || defined(PARAM_SUPPORT_REAL_CHECK)) 171d9f0492fSopenharmony_ci ParamTimerClose(g_persistWorkSpace.saveTimer); 172d9f0492fSopenharmony_ci g_persistWorkSpace.saveTimer = NULL; 173d9f0492fSopenharmony_ci if (!PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE)) { 174d9f0492fSopenharmony_ci return; 175d9f0492fSopenharmony_ci } 176d9f0492fSopenharmony_ci#endif 177d9f0492fSopenharmony_ci CheckAndSavePersistParam(); 178d9f0492fSopenharmony_ci} 179d9f0492fSopenharmony_ci 180d9f0492fSopenharmony_ciINIT_LOCAL_API int WritePersistParam(const char *name, const char *value) 181d9f0492fSopenharmony_ci{ 182d9f0492fSopenharmony_ci PARAM_CHECK(value != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param"); 183d9f0492fSopenharmony_ci if (!IsNeedToSave(name)) { 184d9f0492fSopenharmony_ci return 0; 185d9f0492fSopenharmony_ci } 186d9f0492fSopenharmony_ci PARAM_LOGV("WritePersistParam name %s ", name); 187d9f0492fSopenharmony_ci if (g_persistWorkSpace.persistParamOps.save != NULL) { 188d9f0492fSopenharmony_ci g_persistWorkSpace.persistParamOps.save(name, value); 189d9f0492fSopenharmony_ci } 190d9f0492fSopenharmony_ci // update commit for check 191d9f0492fSopenharmony_ci UpdatePersistCommitId(); 192d9f0492fSopenharmony_ci // for liteos-m, start task to check and save parameter 193d9f0492fSopenharmony_ci // for linux, start timer after set persist parameter 194d9f0492fSopenharmony_ci // for liteos-a, start timer in init to check and save parameter 195d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_REAL_CHECK 196d9f0492fSopenharmony_ci if (!PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED)) { 197d9f0492fSopenharmony_ci PARAM_LOGE("Can not save persist param before load %s ", name); 198d9f0492fSopenharmony_ci return 0; 199d9f0492fSopenharmony_ci } 200d9f0492fSopenharmony_ci if (g_persistWorkSpace.persistParamOps.batchSave == NULL) { 201d9f0492fSopenharmony_ci return 0; 202d9f0492fSopenharmony_ci } 203d9f0492fSopenharmony_ci 204d9f0492fSopenharmony_ci // check timer for save all 205d9f0492fSopenharmony_ci struct timespec currTimer = {0}; 206d9f0492fSopenharmony_ci (void)clock_gettime(CLOCK_MONOTONIC, &currTimer); 207d9f0492fSopenharmony_ci uint32_t diff = IntervalTime(&g_persistWorkSpace.lastSaveTimer, &currTimer); 208d9f0492fSopenharmony_ci if (diff > PARAM_MUST_SAVE_PARAM_DIFF) { 209d9f0492fSopenharmony_ci if (g_persistWorkSpace.saveTimer != NULL) { 210d9f0492fSopenharmony_ci ParamTimerClose(g_persistWorkSpace.saveTimer); 211d9f0492fSopenharmony_ci g_persistWorkSpace.saveTimer = NULL; 212d9f0492fSopenharmony_ci } 213d9f0492fSopenharmony_ci return BatchSavePersistParam(); 214d9f0492fSopenharmony_ci } 215d9f0492fSopenharmony_ci 216d9f0492fSopenharmony_ci PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE); 217d9f0492fSopenharmony_ci if (g_persistWorkSpace.saveTimer == NULL) { 218d9f0492fSopenharmony_ci ParamTimerCreate(&g_persistWorkSpace.saveTimer, TimerCallbackForSave, NULL); 219d9f0492fSopenharmony_ci ParamTimerStart(g_persistWorkSpace.saveTimer, PARAM_MUST_SAVE_PARAM_DIFF * MS_UNIT, MS_UNIT); 220d9f0492fSopenharmony_ci } 221d9f0492fSopenharmony_ci#endif 222d9f0492fSopenharmony_ci return 0; 223d9f0492fSopenharmony_ci} 224d9f0492fSopenharmony_ci 225d9f0492fSopenharmony_ciint LoadPersistParams(void) 226d9f0492fSopenharmony_ci{ 227d9f0492fSopenharmony_ci // get persist parameter 228d9f0492fSopenharmony_ci int ret = InitPersistParamWorkSpace(); 229d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Failed to init persist param"); 230d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 231d9f0492fSopenharmony_ci if (PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED)) { 232d9f0492fSopenharmony_ci PARAM_LOGE("Persist param has been loaded"); 233d9f0492fSopenharmony_ci return 0; 234d9f0492fSopenharmony_ci } 235d9f0492fSopenharmony_ci#endif 236d9f0492fSopenharmony_ci#if defined(__LITEOS_M__) || defined(__LITEOS_A__) || defined(__LINUX__) 237d9f0492fSopenharmony_ci if (g_persistWorkSpace.persistParamOps.load != NULL) { 238d9f0492fSopenharmony_ci (void)g_persistWorkSpace.persistParamOps.load(); 239d9f0492fSopenharmony_ci PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED); 240d9f0492fSopenharmony_ci } 241d9f0492fSopenharmony_ci // save new persist param 242d9f0492fSopenharmony_ci ret = BatchSavePersistParam(); 243d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Failed to load persist param"); 244d9f0492fSopenharmony_ci // for liteos-a, start time to check in init 245d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_CYCLE_CHECK 246d9f0492fSopenharmony_ci PARAM_LOGV("LoadPersistParams start check time "); 247d9f0492fSopenharmony_ci if (g_persistWorkSpace.saveTimer == NULL) { 248d9f0492fSopenharmony_ci ParamTimerCreate(&g_persistWorkSpace.saveTimer, TimerCallbackForSave, NULL); 249d9f0492fSopenharmony_ci ParamTimerStart(g_persistWorkSpace.saveTimer, PARAM_MUST_SAVE_PARAM_DIFF * MS_UNIT, MS_UNIT); 250d9f0492fSopenharmony_ci } 251d9f0492fSopenharmony_ci#endif 252d9f0492fSopenharmony_ci#else 253d9f0492fSopenharmony_ci if (g_persistWorkSpace.persistParamOps.load != NULL) { 254d9f0492fSopenharmony_ci (void)g_persistWorkSpace.persistParamOps.load(PUBLIC_PERSIST_FILE); 255d9f0492fSopenharmony_ci } 256d9f0492fSopenharmony_ci#endif 257d9f0492fSopenharmony_ci return 0; 258d9f0492fSopenharmony_ci} 259d9f0492fSopenharmony_ci 260d9f0492fSopenharmony_ciint LoadPrivatePersistParams(void) 261d9f0492fSopenharmony_ci{ 262d9f0492fSopenharmony_ci#if !(defined(__LITEOS_M__) || defined(__LITEOS_A__) || defined(__LINUX__)) 263d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 264d9f0492fSopenharmony_ci if (PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED)) { 265d9f0492fSopenharmony_ci PARAM_LOGE("Persist param has been loaded"); 266d9f0492fSopenharmony_ci return 0; 267d9f0492fSopenharmony_ci } 268d9f0492fSopenharmony_ci#endif 269d9f0492fSopenharmony_ci if (g_persistWorkSpace.persistParamOps.load != NULL) { 270d9f0492fSopenharmony_ci (void)g_persistWorkSpace.persistParamOps.load(PRIVATE_PERSIST_FILE); 271d9f0492fSopenharmony_ci PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED); 272d9f0492fSopenharmony_ci } 273d9f0492fSopenharmony_ci // save new persist param 274d9f0492fSopenharmony_ci int ret = BatchSavePersistParam(); 275d9f0492fSopenharmony_ci PARAM_CHECK(ret == 0, return ret, "Failed to load persist param"); 276d9f0492fSopenharmony_ci // for liteos-a, start time to check in init 277d9f0492fSopenharmony_ci#ifdef PARAM_SUPPORT_CYCLE_CHECK 278d9f0492fSopenharmony_ci PARAM_LOGV("LoadPersistParams start check time "); 279d9f0492fSopenharmony_ci if (g_persistWorkSpace.saveTimer == NULL) { 280d9f0492fSopenharmony_ci ParamTimerCreate(&g_persistWorkSpace.saveTimer, TimerCallbackForSave, NULL); 281d9f0492fSopenharmony_ci ParamTimerStart(g_persistWorkSpace.saveTimer, PARAM_MUST_SAVE_PARAM_DIFF * MS_UNIT, MS_UNIT); 282d9f0492fSopenharmony_ci } 283d9f0492fSopenharmony_ci#endif 284d9f0492fSopenharmony_ci#endif 285d9f0492fSopenharmony_ci return 0; 286d9f0492fSopenharmony_ci}