• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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