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