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
16 use asset_common::{CallingInfo, Counter, Group, OwnerType, GROUP_SEPARATOR};
17 use asset_db_operator::{
18 database::{get_path, Database},
19 database_file_upgrade::construct_splited_db_name,
20 types::{column, QueryOptions},
21 };
22 use asset_definition::{log_throw_error, ErrCode, Extension, Result};
23 use asset_file_operator::de_operator::create_user_de_dir;
24 use asset_log::{loge, logi};
25 use asset_sdk::{
26 plugin_interface::{ExtDbMap, IAssetPlugin, IAssetPluginCtx, RETURN_LIMIT, RETURN_OFFSET}, Value
27 };
28 use std::{
29 cell::RefCell,
30 sync::{Arc, Mutex},
31 };
32
33 /// The asset_ext plugin.
34 #[derive(Default)]
35 pub struct AssetPlugin {
36 lib: RefCell<Option<libloading::Library>>,
37 }
38
39 static ASSET_OLUGIN_LOCK: Mutex<()> = Mutex::new(());
40
41 unsafe impl Sync for AssetPlugin {}
42
43 impl AssetPlugin {
new() -> Self44 fn new() -> Self {
45 Self { lib: RefCell::new(None) }
46 }
47
48 /// Get the instance of AssetPlugin.
get_instance() -> Arc<AssetPlugin>49 pub fn get_instance() -> Arc<AssetPlugin> {
50 static mut INSTANCE: Option<Arc<AssetPlugin>> = None;
51 let _guard = ASSET_OLUGIN_LOCK.lock().unwrap();
52 unsafe { INSTANCE.get_or_insert_with(|| Arc::new(AssetPlugin::new())).clone() }
53 }
54
55 /// Load the plugin.
load_plugin(&self) -> Result<Box<dyn IAssetPlugin>>56 pub fn load_plugin(&self) -> Result<Box<dyn IAssetPlugin>> {
57 unsafe {
58 let _guard = ASSET_OLUGIN_LOCK.lock().unwrap();
59 if self.lib.borrow().is_none() {
60 logi!("start to load asset_ext plugin.");
61 match libloading::Library::new("libasset_ext_ffi.z.so") {
62 Ok(lib) => *self.lib.borrow_mut() = Some(lib),
63 Err(err) => {
64 loge!("dlopen libasset_ext_ffi.z.so failed, err: {}", err);
65 return log_throw_error!(ErrCode::InvalidArgument, "dlopen failed {}", err);
66 },
67 };
68 }
69
70 let Some(ref lib) = *self.lib.borrow() else {
71 return log_throw_error!(ErrCode::InvalidArgument, "unexpect error");
72 };
73
74 let func = match lib
75 .get::<libloading::Symbol<unsafe extern "C" fn() -> *mut dyn IAssetPlugin>>(b"_create_plugin")
76 {
77 Ok(func) => func,
78 Err(err) => {
79 loge!("dlsym _create_plugin failed, err: {}", err);
80 return log_throw_error!(ErrCode::InvalidArgument, "dlsym failed {}", err);
81 },
82 };
83
84 let plugin_ptr = func();
85 if plugin_ptr.is_null() {
86 loge!("_create_plugin return null.");
87 return log_throw_error!(ErrCode::InvalidArgument, "_create_plugin return null.");
88 }
89
90 logi!("load asset_ext plugin success.");
91 Ok(Box::from_raw(plugin_ptr))
92 }
93 }
94
95 /// Unload plugin.
unload_plugin(&self)96 pub fn unload_plugin(&self) {
97 let _guard = ASSET_OLUGIN_LOCK.lock().unwrap();
98 if self.lib.borrow().is_some() {
99 *self.lib.borrow_mut() = None;
100 }
101 }
102 }
103
104 /// The asset_ext plugin context.
105 #[repr(C)]
106 pub struct AssetContext {
107 /// The asset database's user id.
108 pub user_id: i32,
109 }
110
get_db_name(user_id: i32, attributes: &ExtDbMap, is_ce: bool) -> std::result::Result<String, u32>111 fn get_db_name(user_id: i32, attributes: &ExtDbMap, is_ce: bool) -> std::result::Result<String, u32> {
112 let owner_info = attributes.get_bytes_attr(&column::OWNER).map_err(|e| e.code as u32)?;
113 let owner_type = attributes.get_enum_attr::<OwnerType>(&column::OWNER_TYPE).map_err(|e| e.code as u32)?;
114 let calling_info = match attributes.get_bytes_attr(&column::GROUP_ID).map_err(|e| e.code as u32) {
115 Ok(group) => {
116 let mut parts = group.split(|&byte| byte == GROUP_SEPARATOR as u8);
117 let developer_id: Vec<u8> = parts.next().unwrap().to_vec();
118 let group_id: Vec<u8> = parts.next().unwrap().to_vec();
119 CallingInfo::new(user_id, owner_type, owner_info.to_vec(), Some(Group { developer_id, group_id }))
120 },
121 _ => CallingInfo::new(user_id, owner_type, owner_info.to_vec(), None),
122 };
123 construct_splited_db_name(&calling_info, is_ce).map_err(|e| e.code as u32)
124 }
125
get_query_options(attrs: &ExtDbMap) -> QueryOptions126 fn get_query_options(attrs: &ExtDbMap) -> QueryOptions {
127 QueryOptions {
128 offset: match attrs.get(RETURN_OFFSET) {
129 Some(Value::Number(offset)) => Some(*offset),
130 _ => None,
131 },
132 limit: match attrs.get(RETURN_LIMIT) {
133 Some(Value::Number(limit)) => Some(*limit),
134 _ => None,
135 },
136 order_by: None,
137 order: None,
138 }
139 }
140
141 #[allow(dead_code)]
142 impl IAssetPluginCtx for AssetContext {
143 /// Initializes the plugin before usage.
init(&mut self, user_id: i32) -> std::result::Result<(), u32>144 fn init(&mut self, user_id: i32) -> std::result::Result<(), u32> {
145 create_user_de_dir(user_id).map_err(|e| e.code as u32)?;
146 self.user_id = user_id;
147 Ok(())
148 }
149
150 /// Adds an asset to de db.
add(&mut self, attributes: &ExtDbMap) -> std::result::Result<i32, u32>151 fn add(&mut self, attributes: &ExtDbMap) -> std::result::Result<i32, u32> {
152 let db_name = get_db_name(self.user_id, attributes, false)?;
153 let mut db = Database::build_with_file_name(self.user_id, &db_name, false).map_err(|e| e.code as u32)?;
154 db.insert_datas(attributes).map_err(|e| e.code as u32)
155 }
156
157 /// Adds an asset to ce db.
ce_add(&mut self, attributes: &ExtDbMap) -> std::result::Result<i32, u32>158 fn ce_add(&mut self, attributes: &ExtDbMap) -> std::result::Result<i32, u32> {
159 let db_name = get_db_name(self.user_id, attributes, true)?;
160 let mut db = Database::build_with_file_name(self.user_id, &db_name, true).map_err(|e| e.code as u32)?;
161 db.insert_datas(attributes).map_err(|e| e.code as u32)
162 }
163
164 /// Adds an asset with replace to de db.
replace(&mut self, condition: &ExtDbMap, attributes: &ExtDbMap) -> std::result::Result<(), u32>165 fn replace(&mut self, condition: &ExtDbMap, attributes: &ExtDbMap) -> std::result::Result<(), u32> {
166 let db_name = get_db_name(self.user_id, attributes, false)?;
167 let mut db = Database::build_with_file_name(self.user_id, &db_name, false).map_err(|e| e.code as u32)?;
168 db.replace_datas(condition, false, attributes).map_err(|e| e.code as u32)
169 }
170
171 /// Adds an asset with replace to ce db.
ce_replace(&mut self, condition: &ExtDbMap, attributes: &ExtDbMap) -> std::result::Result<(), u32>172 fn ce_replace(&mut self, condition: &ExtDbMap, attributes: &ExtDbMap) -> std::result::Result<(), u32> {
173 let db_name = get_db_name(self.user_id, attributes, true)?;
174 let mut db = Database::build_with_file_name(self.user_id, &db_name, true).map_err(|e| e.code as u32)?;
175 db.replace_datas(condition, false, attributes).map_err(|e| e.code as u32)
176 }
177
178 /// Queries de db.
query(&mut self, attributes: &ExtDbMap) -> std::result::Result<Vec<ExtDbMap>, u32>179 fn query(&mut self, attributes: &ExtDbMap) -> std::result::Result<Vec<ExtDbMap>, u32> {
180 let de_dbs = asset_file_operator::de_operator::get_de_user_dbs(self.user_id).map_err(|e| e.code as u32)?;
181 let mut query_data = vec![];
182 for db_name in de_dbs {
183 let mut db = Database::build_with_file_name(self.user_id, &db_name, false).map_err(|e| e.code as u32)?;
184 query_data.extend(db.query_datas(&vec![], attributes, None, false).map_err(|e| e.code as u32)?);
185 }
186 Ok(query_data)
187 }
188
189 /// Queries ce db.
ce_query(&mut self, attributes: &ExtDbMap) -> std::result::Result<Vec<ExtDbMap>, u32>190 fn ce_query(&mut self, attributes: &ExtDbMap) -> std::result::Result<Vec<ExtDbMap>, u32> {
191 let ce_dbs = asset_file_operator::ce_operator::get_ce_user_dbs(self.user_id).map_err(|e| e.code as u32)?;
192 let mut query_data = vec![];
193 for db_name in ce_dbs {
194 let mut db = Database::build_with_file_name(self.user_id, &db_name, true).map_err(|e| e.code as u32)?;
195 query_data.extend(db.query_datas(&vec![], attributes, None, false).map_err(|e| e.code as u32)?);
196 }
197 Ok(query_data)
198 }
199
200 /// Query db with attributes to a certain db. Normal, Group, CE.
query_certain_db( &mut self, db_info: &ExtDbMap, attributes: &ExtDbMap, query_options: &ExtDbMap, is_ce: bool) -> std::result::Result<Vec<ExtDbMap>, u32>201 fn query_certain_db(
202 &mut self, db_info: &ExtDbMap, attributes: &ExtDbMap, query_options: &ExtDbMap, is_ce: bool) -> std::result::Result<Vec<ExtDbMap>, u32> {
203 let db_name = get_db_name(self.user_id, db_info, is_ce)?;
204 let mut db = Database::build_with_file_name(self.user_id, &db_name, is_ce).map_err(|e| e.code as u32)?;
205 db.query_datas(&vec![], attributes, Some(&get_query_options(query_options)), true).map_err(|e| e.code as u32)
206 }
207
208 /// Removes an asset from de db.
remove(&mut self, attributes: &ExtDbMap) -> std::result::Result<i32, u32>209 fn remove(&mut self, attributes: &ExtDbMap) -> std::result::Result<i32, u32> {
210 let de_dbs = asset_file_operator::de_operator::get_de_user_dbs(self.user_id).map_err(|e| e.code as u32)?;
211 let mut total_remove_count = 0;
212 for db_name in de_dbs {
213 let mut db = Database::build_with_file_name(self.user_id, &db_name, false).map_err(|e| e.code as u32)?;
214 total_remove_count += db.delete_datas(attributes, None, false).map_err(|e| e.code as u32)?;
215 }
216 Ok(total_remove_count)
217 }
218
219 /// Removes an asset from ce db.
ce_remove(&mut self, attributes: &ExtDbMap) -> std::result::Result<i32, u32>220 fn ce_remove(&mut self, attributes: &ExtDbMap) -> std::result::Result<i32, u32> {
221 let ce_dbs = asset_file_operator::ce_operator::get_ce_user_dbs(self.user_id).map_err(|e| e.code as u32)?;
222 let mut total_remove_count = 0;
223 for db_name in ce_dbs {
224 let mut db = Database::build_with_file_name(self.user_id, &db_name, true).map_err(|e| e.code as u32)?;
225 total_remove_count += db.delete_datas(attributes, None, false).map_err(|e| e.code as u32)?;
226 }
227 Ok(total_remove_count)
228 }
229
230 /// Removes an asset from a certain db. Normal, Group, CE.
remove_certain_db(&mut self, db_info: &ExtDbMap, attributes: &ExtDbMap, is_ce: bool) -> std::result::Result<i32, u32>231 fn remove_certain_db(&mut self, db_info: &ExtDbMap, attributes: &ExtDbMap, is_ce: bool) -> std::result::Result<i32, u32> {
232 let db_name = get_db_name(self.user_id, db_info, is_ce)?;
233 let mut db = Database::build_with_file_name(self.user_id, &db_name, is_ce).map_err(|e| e.code as u32)?;
234 db.delete_datas(attributes, None, false).map_err(|e| e.code as u32)
235 }
236
237 /// Removes assets from de db with sepcific condition.
remove_with_specific_cond( &mut self, specific_cond: &str, condition_value: &[Value], ) -> std::result::Result<i32, u32>238 fn remove_with_specific_cond(
239 &mut self,
240 specific_cond: &str,
241 condition_value: &[Value],
242 ) -> std::result::Result<i32, u32> {
243 let de_dbs = asset_file_operator::de_operator::get_de_user_dbs(self.user_id).map_err(|e| e.code as u32)?;
244 let mut total_remove_count = 0;
245 for db_name in de_dbs {
246 let mut db = Database::build_with_file_name(self.user_id, &db_name, false).map_err(|e| e.code as u32)?;
247 total_remove_count +=
248 db.delete_specific_condition_datas(specific_cond, condition_value).map_err(|e| e.code as u32)?;
249 }
250 Ok(total_remove_count)
251 }
252
253 /// Removes assets from ce db with sepcific condition.
ce_remove_with_specific_cond( &mut self, specific_cond: &str, condition_value: &[Value], ) -> std::result::Result<i32, u32>254 fn ce_remove_with_specific_cond(
255 &mut self,
256 specific_cond: &str,
257 condition_value: &[Value],
258 ) -> std::result::Result<i32, u32> {
259 let ce_dbs = asset_file_operator::ce_operator::get_ce_user_dbs(self.user_id).map_err(|e| e.code as u32)?;
260 let mut total_remove_count = 0;
261 for db_name in ce_dbs {
262 let mut db = Database::build_with_file_name(self.user_id, &db_name, true).map_err(|e| e.code as u32)?;
263 total_remove_count +=
264 db.delete_specific_condition_datas(specific_cond, condition_value).map_err(|e| e.code as u32)?;
265 }
266 Ok(total_remove_count)
267 }
268
269 /// Updates the attributes of an asset in de db.
update(&mut self, attributes: &ExtDbMap, attrs_to_update: &ExtDbMap) -> std::result::Result<i32, u32>270 fn update(&mut self, attributes: &ExtDbMap, attrs_to_update: &ExtDbMap) -> std::result::Result<i32, u32> {
271 let de_dbs = asset_file_operator::de_operator::get_de_user_dbs(self.user_id).map_err(|e| e.code as u32)?;
272 let mut total_update_count = 0;
273 for db_name in de_dbs {
274 let mut db = Database::build_with_file_name(self.user_id, &db_name, false).map_err(|e| e.code as u32)?;
275 total_update_count += db.update_datas(attributes, false, attrs_to_update).map_err(|e| e.code as u32)?;
276 }
277 Ok(total_update_count)
278 }
279
280 /// Updates the attributes of an asset in ce db.
ce_update(&mut self, attributes: &ExtDbMap, attrs_to_update: &ExtDbMap) -> std::result::Result<i32, u32>281 fn ce_update(&mut self, attributes: &ExtDbMap, attrs_to_update: &ExtDbMap) -> std::result::Result<i32, u32> {
282 let ce_dbs = asset_file_operator::ce_operator::get_ce_user_dbs(self.user_id).map_err(|e| e.code as u32)?;
283 let mut total_update_count = 0;
284 for db_name in ce_dbs {
285 let mut db = Database::build_with_file_name(self.user_id, &db_name, true).map_err(|e| e.code as u32)?;
286 total_update_count += db.update_datas(attributes, false, attrs_to_update).map_err(|e| e.code as u32)?;
287 }
288 Ok(total_update_count)
289 }
290
291 /// Returns the storage path for de db.
get_storage_path(&self) -> String292 fn get_storage_path(&self) -> String {
293 get_path()
294 }
295
296 /// Increase count
increase_count(&mut self)297 fn increase_count(&mut self) {
298 let counter = Counter::get_instance();
299 counter.lock().unwrap().increase_count();
300 }
301
302 /// Decrease count
decrease_count(&mut self)303 fn decrease_count(&mut self) {
304 let counter = Counter::get_instance();
305 counter.lock().unwrap().decrease_count();
306 }
307 }
308