• 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::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