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::Counter; 17 use asset_db_operator::database::{get_path, Database}; 18 use asset_definition::{log_throw_error, ErrCode, Result}; 19 use asset_log::{loge, logi}; 20 use asset_sdk::{plugin_interface::{ExtDbMap, IAssetPlugin, IAssetPluginCtx}, Value}; 21 use std::{ 22 cell::RefCell, 23 sync::{Arc, Mutex}, 24 }; 25 26 /// The asset_ext plugin. 27 #[derive(Default)] 28 pub struct AssetPlugin { 29 lib: RefCell<Option<libloading::Library>>, 30 } 31 32 static ASSET_OLUGIN_LOCK: Mutex<()> = Mutex::new(()); 33 34 unsafe impl Sync for AssetPlugin {} 35 36 impl AssetPlugin { new() -> Self37 fn new() -> Self { 38 Self { lib: RefCell::new(None) } 39 } 40 41 /// Get the instance of AssetPlugin. get_instance() -> Arc<AssetPlugin>42 pub fn get_instance() -> Arc<AssetPlugin> { 43 static mut INSTANCE: Option<Arc<AssetPlugin>> = None; 44 let _guard = ASSET_OLUGIN_LOCK.lock().unwrap(); 45 unsafe { INSTANCE.get_or_insert_with(|| Arc::new(AssetPlugin::new())).clone() } 46 } 47 48 /// Load the plugin. load_plugin(&self) -> Result<Box<dyn IAssetPlugin>>49 pub fn load_plugin(&self) -> Result<Box<dyn IAssetPlugin>> { 50 unsafe { 51 let _guard = ASSET_OLUGIN_LOCK.lock().unwrap(); 52 if self.lib.borrow().is_none() { 53 logi!("start to load asset_ext plugin."); 54 match libloading::Library::new("libasset_ext_ffi.z.so") { 55 Ok(lib) => *self.lib.borrow_mut() = Some(lib), 56 Err(err) => { 57 loge!("dlopen libasset_ext_ffi.z.so failed, err: {}", err); 58 return log_throw_error!(ErrCode::InvalidArgument, "dlopen failed {}", err); 59 }, 60 }; 61 } 62 63 let Some(ref lib) = *self.lib.borrow() else { 64 return log_throw_error!(ErrCode::InvalidArgument, "unexpect error"); 65 }; 66 67 let func = match lib 68 .get::<libloading::Symbol<unsafe extern "C" fn() -> *mut dyn IAssetPlugin>>(b"_create_plugin") 69 { 70 Ok(func) => func, 71 Err(err) => { 72 loge!("dlsym _create_plugin failed, err: {}", err); 73 return log_throw_error!(ErrCode::InvalidArgument, "dlsym failed {}", err); 74 }, 75 }; 76 77 let plugin_ptr = func(); 78 if plugin_ptr.is_null() { 79 loge!("_create_plugin return null."); 80 return log_throw_error!(ErrCode::InvalidArgument, "_create_plugin return null."); 81 } 82 83 logi!("load asset_ext plugin success."); 84 Ok(Box::from_raw(plugin_ptr)) 85 } 86 } 87 88 /// Unload plugin. unload_plugin(&self)89 pub fn unload_plugin(&self) { 90 let _guard = ASSET_OLUGIN_LOCK.lock().unwrap(); 91 if self.lib.borrow().is_some() { 92 *self.lib.borrow_mut() = None; 93 } 94 } 95 } 96 97 /// The asset_ext plugin context. 98 #[repr(C)] 99 pub struct AssetContext { 100 /// The asset database instance. 101 pub data_base: Option<Database>, 102 } 103 104 #[allow(dead_code)] 105 impl IAssetPluginCtx for AssetContext { 106 /// Initializes the plugin before usage. init(&mut self, user_id: i32) -> std::result::Result<(), u32>107 fn init(&mut self, user_id: i32) -> std::result::Result<(), u32> { 108 // Create database directory if not exists. 109 asset_file_operator::create_user_db_dir(user_id).map_err(|e| e.code as u32)?; 110 111 let db = Database::build(user_id).map_err(|e| e.code as u32)?; 112 self.data_base = Some(db); 113 Ok(()) 114 } 115 116 /// Adds an asset to the database. add(&mut self, attributes: &ExtDbMap) -> std::result::Result<i32, u32>117 fn add(&mut self, attributes: &ExtDbMap) -> std::result::Result<i32, u32> { 118 self.data_base 119 .as_mut() 120 .ok_or(ErrCode::InvalidArgument as u32)? 121 .insert_datas(attributes) 122 .map_err(|e| e.code as u32) 123 } 124 replace(&mut self, condition: &ExtDbMap, attributes: &ExtDbMap) -> std::result::Result<(), u32>125 fn replace(&mut self, condition: &ExtDbMap, attributes: &ExtDbMap) -> std::result::Result<(), u32> { 126 self.data_base 127 .as_mut() 128 .ok_or(ErrCode::InvalidArgument as u32)? 129 .replace_datas(condition, false, attributes) 130 .map_err(|e| e.code as u32) 131 } 132 133 /// Queries the asset database. query(&mut self, attributes: &ExtDbMap) -> std::result::Result<Vec<ExtDbMap>, u32>134 fn query(&mut self, attributes: &ExtDbMap) -> std::result::Result<Vec<ExtDbMap>, u32> { 135 self.data_base 136 .as_mut() 137 .ok_or(ErrCode::InvalidArgument as u32)? 138 .query_datas(&vec![], attributes, None, false) 139 .map_err(|e| e.code as u32) 140 } 141 142 /// Removes an asset from the database. remove(&mut self, attributes: &ExtDbMap) -> std::result::Result<i32, u32>143 fn remove(&mut self, attributes: &ExtDbMap) -> std::result::Result<i32, u32> { 144 self.data_base 145 .as_mut() 146 .ok_or(ErrCode::InvalidArgument as u32)? 147 .delete_datas(attributes, None, false) 148 .map_err(|e| e.code as u32) 149 } 150 151 /// Remove assets from the database with sepcific condition. remove_with_specific_cond( &mut self, specific_cond: &str, condition_value: &[Value] ) -> std::result::Result<i32, u32>152 fn remove_with_specific_cond( 153 &mut self, specific_cond: &str, 154 condition_value: &[Value] 155 ) -> std::result::Result<i32, u32> { 156 self.data_base 157 .as_mut() 158 .ok_or(ErrCode::InvalidArgument as u32)? 159 .delete_specific_condition_datas(specific_cond, condition_value) 160 .map_err(|e| e.code as u32) 161 } 162 163 /// Updates the attributes of an asset in the database. update(&mut self, attributes: &ExtDbMap, attrs_to_update: &ExtDbMap) -> std::result::Result<i32, u32>164 fn update(&mut self, attributes: &ExtDbMap, attrs_to_update: &ExtDbMap) -> std::result::Result<i32, u32> { 165 self.data_base 166 .as_mut() 167 .ok_or(ErrCode::InvalidArgument as u32)? 168 .update_datas(attributes, false, attrs_to_update) 169 .map_err(|e| e.code as u32) 170 } 171 172 /// Begins a transaction for the asset database. begin_transaction(&mut self) -> std::result::Result<(), u32>173 fn begin_transaction(&mut self) -> std::result::Result<(), u32> { 174 self.data_base 175 .as_mut() 176 .ok_or(ErrCode::InvalidArgument as u32)? 177 .exec("begin immediate") 178 .map_err(|e| e.code as u32) 179 } 180 181 /// Commits a transaction for the asset database. commit_transaction(&mut self) -> std::result::Result<(), u32>182 fn commit_transaction(&mut self) -> std::result::Result<(), u32> { 183 self.data_base.as_mut().ok_or(ErrCode::InvalidArgument as u32)?.exec("commit").map_err(|e| e.code as u32) 184 } 185 186 /// Rolls back a transaction for the asset database. rollback_transaction(&mut self) -> std::result::Result<(), u32>187 fn rollback_transaction(&mut self) -> std::result::Result<(), u32> { 188 self.data_base.as_mut().ok_or(ErrCode::InvalidArgument as u32)?.exec("rollback").map_err(|e| e.code as u32) 189 } 190 191 /// Returns the storage path for the asset database. get_storage_path(&self) -> String192 fn get_storage_path(&self) -> String { 193 get_path() 194 } 195 196 /// Increase count increase_count(&mut self)197 fn increase_count(&mut self) { 198 let counter = Counter::get_instance(); 199 counter.lock().unwrap().increase_count(); 200 } 201 202 /// Decrease count decrease_count(&mut self)203 fn decrease_count(&mut self) { 204 let counter = Counter::get_instance(); 205 counter.lock().unwrap().decrease_count(); 206 } 207 } 208