1 /*
2 * Copyright (c) 2025 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 #define LOG_TAG "KnowledgeSchemaHelper"
16 #include "knowledge_schema_helper.h"
17
18 #ifndef CROSS_PLATFORM
19 #include <dlfcn.h>
20 #endif
21 #include <fstream>
22 #include <sstream>
23 #include "logger.h"
24 #include "rdb_errno.h"
25 #include "rdb_fault_hiview_reporter.h"
26 #include "sqlite_utils.h"
27 #include "task_executor.h"
28
29 namespace OHOS::NativeRdb {
30 using namespace OHOS::Rdb;
31
32 static constexpr int AIP_MODULE_ID = 13;
33 constexpr ErrCode AIP_ERR_OFFSET = ErrCodeOffset(SUBSYS_DISTRIBUTEDDATAMNG, AIP_MODULE_ID);
34 constexpr int32_t KNOWLEDGE_BASE_ERROR_CODE_OFFSET{ 20000 };
35 constexpr ErrCode KNOWLEDGE_BASE_FAIL = AIP_ERR_OFFSET + KNOWLEDGE_BASE_ERROR_CODE_OFFSET;
36 constexpr ErrCode KNOWLEDGE_SCHEMA_NOT_VALID = KNOWLEDGE_BASE_FAIL + 1;
37
~KnowledgeSchemaHelper()38 KnowledgeSchemaHelper::~KnowledgeSchemaHelper()
39 {
40 std::unique_lock<std::shared_mutex> writeLock(libMutex_);
41 if (schemaManager_ != nullptr) {
42 schemaManager_->StopTask(dbName_);
43 delete schemaManager_;
44 schemaManager_ = nullptr;
45 }
46 #ifndef CROSS_PLATFORM
47 if (dlHandle_ != nullptr) {
48 dlclose(dlHandle_);
49 dlHandle_ = nullptr;
50 }
51 #endif
52 }
53
Init(const RdbStoreConfig & config,const DistributedRdb::RdbKnowledgeSchema & schema)54 void KnowledgeSchemaHelper::Init(const RdbStoreConfig &config, const DistributedRdb::RdbKnowledgeSchema &schema)
55 {
56 LoadKnowledgeLib();
57 if (!IsLoadLib()) {
58 LOG_WARN("skip init by miss lib");
59 return;
60 }
61 std::unique_lock<std::shared_mutex> writeLock(libMutex_);
62 if (schemaManager_ == nullptr) {
63 LOG_WARN("skip init by miss manager");
64 return;
65 }
66 schemaManager_->Init(config, schema);
67 bundleName_ = config.GetBundleName();
68 dbName_ = config.GetName();
69 inited_ = true;
70 }
71
GetRdbKnowledgeSchema(const std::string & dbName)72 std::pair<int, DistributedRdb::RdbKnowledgeSchema> KnowledgeSchemaHelper::GetRdbKnowledgeSchema(
73 const std::string &dbName)
74 {
75 std::pair<int, DistributedRdb::RdbKnowledgeSchema> res;
76 auto &[errCode, schema] = res;
77 LoadKnowledgeLib();
78 if (!IsLoadLib()) {
79 LOG_WARN("skip get donate data by miss lib");
80 errCode = E_ERROR;
81 return res;
82 }
83 std::shared_lock<std::shared_mutex> readLock(libMutex_);
84 if (schemaManager_ == nullptr) {
85 LOG_WARN("skip get donate data by miss manager");
86 errCode = E_ERROR;
87 return res;
88 }
89 errCode = E_OK;
90 auto kSchema = schemaManager_->GetRdbKnowledgeSchema(dbName);
91 if (kSchema == nullptr) {
92 LOG_WARN("unable to get knowledge schema.");
93 RdbFaultHiViewReporter::ReportRAGFault("Parse knowledge schema failed", "ParseRdbKnowledgeSchema", bundleName_,
94 KNOWLEDGE_BASE_FAIL, KNOWLEDGE_SCHEMA_NOT_VALID);
95 errCode = E_ERROR;
96 return res;
97 }
98 schema = *kSchema;
99 return res;
100 }
101
DonateKnowledgeData()102 void KnowledgeSchemaHelper::DonateKnowledgeData()
103 {
104 if (!inited_) {
105 LOG_WARN("knowledge schema helper not init.");
106 return;
107 }
108 LoadKnowledgeLib();
109 if (!IsLoadLib()) {
110 LOG_WARN("skip donate data by miss lib");
111 return;
112 }
113 auto executor = TaskExecutor::GetInstance().GetExecutor();
114 if (executor == nullptr) {
115 LOG_WARN("skip donate data by miss pool");
116 return;
117 }
118 std::shared_lock<std::shared_mutex> readLock(libMutex_);
119 if (schemaManager_ == nullptr) {
120 LOG_WARN("skip donate data by miss manager");
121 return;
122 }
123 std::weak_ptr<KnowledgeSchemaHelper> helper = shared_from_this();
124 executor->Execute([helper]() {
125 auto realHelper = helper.lock();
126 if (realHelper == nullptr) {
127 LOG_WARN("knowledge helper is null");
128 return;
129 }
130 realHelper->StartTask();
131 });
132 }
133
LoadKnowledgeLib()134 void KnowledgeSchemaHelper::LoadKnowledgeLib()
135 {
136 #ifndef CROSS_PLATFORM
137 std::unique_lock<std::shared_mutex> writeLock(libMutex_);
138 if (dlHandle_ != nullptr) {
139 return;
140 }
141 auto handle = dlopen("libaip_knowledge_process.z.so", RTLD_LAZY);
142 if (handle != nullptr) {
143 LoadKnowledgeSchemaManager(handle);
144 dlHandle_ = handle;
145 } else {
146 LOG_WARN("unable to load lib, errno: %{public}d, %{public}s", errno, dlerror());
147 }
148 #endif
149 }
150
LoadKnowledgeSchemaManager(void * handle)151 void KnowledgeSchemaHelper::LoadKnowledgeSchemaManager(void *handle)
152 {
153 #ifndef CROSS_PLATFORM
154 typedef DistributedRdb::IKnowledgeSchemaManager* (*CreateKnowledgeSchemaManager)();
155 auto creator = (CreateKnowledgeSchemaManager)(dlsym(handle, "CreateKnowledgeSchemaManager"));
156 if (creator == nullptr) {
157 LOG_WARN("unable to load creator, errno: %{public}d, %{public}s", errno, dlerror());
158 return;
159 }
160 schemaManager_ = creator();
161 if (schemaManager_ != nullptr) {
162 LOG_INFO("load creator success");
163 } else {
164 LOG_WARN("load creator failed with oom");
165 }
166 #endif
167 }
168
IsLoadLib() const169 bool KnowledgeSchemaHelper::IsLoadLib() const
170 {
171 #ifndef CROSS_PLATFORM
172 std::shared_lock<std::shared_mutex> readLock(libMutex_);
173 return dlHandle_ != nullptr;
174 #else
175 return false;
176 #endif
177 }
178
StartTask()179 void KnowledgeSchemaHelper::StartTask()
180 {
181 DistributedRdb::IKnowledgeSchemaManager *manager = nullptr;
182 {
183 std::shared_lock<std::shared_mutex> readLock(libMutex_);
184 if (schemaManager_ == nullptr) {
185 LOG_WARN("skip execute donate data by miss manager");
186 return;
187 }
188 manager = schemaManager_;
189 }
190 manager->StartTask(dbName_);
191 }
192
Close()193 void KnowledgeSchemaHelper::Close()
194 {
195 std::unique_lock<std::shared_mutex> writeLock(libMutex_);
196 if (schemaManager_ != nullptr) {
197 schemaManager_->StopTask(dbName_);
198 }
199 }
200 }