mirror of
https://gitee.com/openharmony/startup_init
synced 2024-12-19 17:08:41 +00:00
44bbc364e1
Signed-off-by: Mupceet <laiguizhong@huawei.com> Change-Id: Ie512784d4cd22bf371632c614505f289f2b29c97
245 lines
8.9 KiB
C
245 lines
8.9 KiB
C
/*
|
||
* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
|
||
* 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 "param_persist.h"
|
||
|
||
#include <time.h>
|
||
|
||
#include "init_param.h"
|
||
#include "init_utils.h"
|
||
#include "param_manager.h"
|
||
#include "param_trie.h"
|
||
#include "param_osadp.h"
|
||
#include "securec.h"
|
||
|
||
static ParamPersistWorkSpace g_persistWorkSpace = {0, 0, NULL, 0, {}};
|
||
static int IsNeedToSave(const char *name)
|
||
{
|
||
#if defined(__LITEOS_M__) || defined(__LITEOS_A__)
|
||
return IS_READY_ONLY(name) ? 0 : 1;
|
||
#else
|
||
return (strncmp(name, PARAM_PERSIST_PREFIX, strlen(PARAM_PERSIST_PREFIX)) == 0) ? 1 : 0;
|
||
#endif
|
||
}
|
||
|
||
static long long GetPersistCommitId(void)
|
||
{
|
||
ParamWorkSpace *paramSpace = GetParamWorkSpace();
|
||
PARAM_CHECK(paramSpace != NULL, return 0, "Invalid paramSpace");
|
||
PARAM_WORKSPACE_CHECK(paramSpace, return 0, "Invalid space");
|
||
WorkSpace *space = GetWorkSpace(WORKSPACE_NAME_DAC);
|
||
if (space == NULL || space->area == NULL) {
|
||
return 0;
|
||
}
|
||
PARAMSPACE_AREA_RD_LOCK(space);
|
||
long long globalCommitId = ATOMIC_LOAD_EXPLICIT(&space->area->commitPersistId, memory_order_acquire);
|
||
PARAMSPACE_AREA_RW_UNLOCK(space);
|
||
return globalCommitId;
|
||
}
|
||
|
||
static void UpdatePersistCommitId(void)
|
||
{
|
||
ParamWorkSpace *paramSpace = GetParamWorkSpace();
|
||
PARAM_CHECK(paramSpace != NULL, return, "Invalid paramSpace");
|
||
PARAM_WORKSPACE_CHECK(paramSpace, return, "Invalid space");
|
||
WorkSpace *space = GetWorkSpace(WORKSPACE_NAME_DAC);
|
||
if (space == NULL || space->area == NULL) {
|
||
return;
|
||
}
|
||
PARAMSPACE_AREA_RW_LOCK(space);
|
||
long long globalCommitId = ATOMIC_LOAD_EXPLICIT(&space->area->commitPersistId, memory_order_relaxed);
|
||
ATOMIC_STORE_EXPLICIT(&space->area->commitPersistId, ++globalCommitId, memory_order_release);
|
||
PARAMSPACE_AREA_RW_UNLOCK(space);
|
||
}
|
||
|
||
static int SavePersistParam(const WorkSpace *workSpace, const ParamTrieNode *node, const void *cookie)
|
||
{
|
||
ParamTrieNode *current = (ParamTrieNode *)node;
|
||
if (current == NULL || current->dataIndex == 0) {
|
||
return 0;
|
||
}
|
||
ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex);
|
||
if (entry == NULL) {
|
||
return 0;
|
||
}
|
||
|
||
if (!IsNeedToSave(entry->data)) {
|
||
return 0;
|
||
}
|
||
static char name[PARAM_NAME_LEN_MAX] = {0};
|
||
int ret = memcpy_s(name, PARAM_NAME_LEN_MAX - 1, entry->data, entry->keyLength);
|
||
PARAM_CHECK(ret == EOK, return -1, "Failed to read param name %s", entry->data);
|
||
name[entry->keyLength] = '\0';
|
||
ret = g_persistWorkSpace.persistParamOps.batchSave(
|
||
(PERSIST_SAVE_HANDLE)cookie, name, entry->data + entry->keyLength + 1);
|
||
PARAM_CHECK(ret == 0, return -1, "Failed to write param %s", current->key);
|
||
return ret;
|
||
}
|
||
|
||
static int BatchSavePersistParam()
|
||
{
|
||
PARAM_LOGV("BatchSavePersistParam");
|
||
if (g_persistWorkSpace.persistParamOps.batchSaveBegin == NULL ||
|
||
g_persistWorkSpace.persistParamOps.batchSave == NULL ||
|
||
g_persistWorkSpace.persistParamOps.batchSaveEnd == NULL) {
|
||
return 0;
|
||
}
|
||
|
||
PERSIST_SAVE_HANDLE handle;
|
||
int ret = g_persistWorkSpace.persistParamOps.batchSaveBegin(&handle);
|
||
PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Failed to save persist");
|
||
#if defined(__LITEOS_M__) || defined(__LITEOS_A__)
|
||
const char *prefix = "";
|
||
#else
|
||
const char *prefix = PARAM_PERSIST_PREFIX;
|
||
#endif
|
||
// walk and save persist param
|
||
WorkSpace *workSpace = GetFirstWorkSpace();
|
||
while (workSpace != NULL) {
|
||
WorkSpace *next = GetNextWorkSpace(workSpace);
|
||
ParamTrieNode *root = FindTrieNode(workSpace, prefix, strlen(prefix), NULL);
|
||
PARAMSPACE_AREA_RD_LOCK(workSpace);
|
||
TraversalTrieNode(workSpace, root, SavePersistParam, (void *)handle);
|
||
PARAMSPACE_AREA_RW_UNLOCK(workSpace);
|
||
workSpace = next;
|
||
}
|
||
g_persistWorkSpace.persistParamOps.batchSaveEnd(handle);
|
||
PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Save persist param fail");
|
||
|
||
PARAM_CLEAR_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE);
|
||
(void)time(&g_persistWorkSpace.lastSaveTimer);
|
||
return ret;
|
||
}
|
||
|
||
INIT_LOCAL_API int InitPersistParamWorkSpace()
|
||
{
|
||
if (PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_INIT)) {
|
||
return 0;
|
||
}
|
||
(void)time(&g_persistWorkSpace.lastSaveTimer);
|
||
RegisterPersistParamOps(&g_persistWorkSpace.persistParamOps);
|
||
PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_INIT);
|
||
return 0;
|
||
}
|
||
|
||
INIT_LOCAL_API void ClosePersistParamWorkSpace(void)
|
||
{
|
||
if (g_persistWorkSpace.saveTimer != NULL) {
|
||
ParamTimerClose(g_persistWorkSpace.saveTimer);
|
||
}
|
||
g_persistWorkSpace.flags = 0;
|
||
}
|
||
|
||
void CheckAndSavePersistParam(void)
|
||
{
|
||
// check commit
|
||
long long commit = GetPersistCommitId();
|
||
PARAM_LOGV("CheckAndSavePersistParam commit %lld %lld", commit, g_persistWorkSpace.commitId);
|
||
if (g_persistWorkSpace.commitId == commit) {
|
||
return;
|
||
}
|
||
g_persistWorkSpace.commitId = commit;
|
||
(void)BatchSavePersistParam();
|
||
}
|
||
|
||
PARAM_STATIC void TimerCallbackForSave(const ParamTaskPtr timer, void *context)
|
||
{
|
||
UNUSED(context);
|
||
UNUSED(timer);
|
||
PARAM_LOGV("TimerCallbackForSave ");
|
||
// for liteos-a,we must cycle check
|
||
#if (!defined(PARAM_SUPPORT_CYCLE_CHECK) || defined(PARAM_SUPPORT_REAL_CHECK))
|
||
ParamTimerClose(g_persistWorkSpace.saveTimer);
|
||
g_persistWorkSpace.saveTimer = NULL;
|
||
if (!PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE)) {
|
||
return;
|
||
}
|
||
#endif
|
||
CheckAndSavePersistParam();
|
||
}
|
||
|
||
INIT_LOCAL_API int WritePersistParam(const char *name, const char *value)
|
||
{
|
||
PARAM_CHECK(value != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param");
|
||
if (!IsNeedToSave(name)) {
|
||
return 0;
|
||
}
|
||
PARAM_LOGV("WritePersistParam name %s ", name);
|
||
if (g_persistWorkSpace.persistParamOps.save != NULL) {
|
||
g_persistWorkSpace.persistParamOps.save(name, value);
|
||
}
|
||
// update commit for check
|
||
UpdatePersistCommitId();
|
||
// for liteos-m, start task to check and save parameter
|
||
// for linux, start timer after set persist parameter
|
||
// for liteos-a, start timer in init to check and save parameter
|
||
#ifdef PARAM_SUPPORT_REAL_CHECK
|
||
PARAM_LOGI("WritePersistParam start check ");
|
||
if (!PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED)) {
|
||
PARAM_LOGE("Can not save persist param before load %s ", name);
|
||
return 0;
|
||
}
|
||
if (g_persistWorkSpace.persistParamOps.batchSave == NULL) {
|
||
return 0;
|
||
}
|
||
|
||
// check timer for save all
|
||
time_t currTimer;
|
||
(void)time(&currTimer);
|
||
uint32_t diff = Difftime(currTimer, g_persistWorkSpace.lastSaveTimer);
|
||
if (diff > PARAM_MUST_SAVE_PARAM_DIFF) {
|
||
if (g_persistWorkSpace.saveTimer != NULL) {
|
||
ParamTimerClose(g_persistWorkSpace.saveTimer);
|
||
g_persistWorkSpace.saveTimer = NULL;
|
||
}
|
||
return BatchSavePersistParam();
|
||
}
|
||
|
||
PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE);
|
||
if (g_persistWorkSpace.saveTimer == NULL) {
|
||
ParamTimerCreate(&g_persistWorkSpace.saveTimer, TimerCallbackForSave, NULL);
|
||
ParamTimerStart(g_persistWorkSpace.saveTimer, PARAM_MUST_SAVE_PARAM_DIFF * MS_UNIT, MS_UNIT);
|
||
}
|
||
#endif
|
||
return 0;
|
||
}
|
||
|
||
int LoadPersistParams(void)
|
||
{
|
||
// get persist parameter
|
||
int ret = InitPersistParamWorkSpace();
|
||
PARAM_CHECK(ret == 0, return ret, "Failed to init persist param");
|
||
#ifndef STARTUP_INIT_TEST
|
||
if (PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED)) {
|
||
PARAM_LOGE("Persist param has been loaded");
|
||
return 0;
|
||
}
|
||
#endif
|
||
if (g_persistWorkSpace.persistParamOps.load != NULL) {
|
||
ret = g_persistWorkSpace.persistParamOps.load();
|
||
PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED);
|
||
}
|
||
// save new persist param
|
||
ret = BatchSavePersistParam();
|
||
PARAM_CHECK(ret == 0, return ret, "Failed to load persist param");
|
||
// for liteos-a, start time to check in init
|
||
#ifdef PARAM_SUPPORT_CYCLE_CHECK
|
||
PARAM_LOGV("LoadPersistParams start check time ");
|
||
if (g_persistWorkSpace.saveTimer == NULL) {
|
||
ParamTimerCreate(&g_persistWorkSpace.saveTimer, TimerCallbackForSave, NULL);
|
||
ParamTimerStart(g_persistWorkSpace.saveTimer, PARAM_MUST_SAVE_PARAM_DIFF * MS_UNIT, MS_UNIT);
|
||
}
|
||
#endif
|
||
return 0;
|
||
} |