startup_init/services/param/manager/param_persist.c
Mupceet 44bbc364e1 headerfile
Signed-off-by: Mupceet <laiguizhong@huawei.com>
Change-Id: Ie512784d4cd22bf371632c614505f289f2b29c97
2022-07-27 10:01:09 +08:00

245 lines
8.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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-awe 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;
}