1 /* 2 * Copyright (c) 2023 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 crate::service_impl::types::Database; 17 use crate::{ipc_conn, SyncResult}; 18 use std::collections::HashMap; 19 use std::ops::Deref; 20 21 /// Struct of CloudSync 22 pub struct CloudSync { 23 user_id: i32, 24 connect: ipc_conn::Connect, 25 } 26 27 impl std::fmt::Debug for CloudSync { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result28 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 29 write!(f, "CloudSync: user_id = {:?}", self.user_id) 30 } 31 } 32 33 impl CloudSync { 34 /// Get a server instance through IPC, and initialize a CloudSync instance new(user_id: i32) -> SyncResult<Self>35 pub fn new(user_id: i32) -> SyncResult<Self> { 36 Ok(CloudSync { 37 user_id, 38 connect: ipc_conn::Connect::new(user_id)?, 39 }) 40 } 41 42 #[inline] get_cloud_info(&mut self) -> SyncResult<CloudInfo>43 fn get_cloud_info(&mut self) -> SyncResult<CloudInfo> { 44 let user_info_ipc = self.connect.get_service_info(self.user_id)?; 45 Ok(CloudInfo::from(user_info_ipc.deref())) 46 } 47 48 /// Get a cloud server info from the other end through the IPC connection get_service_info(&mut self) -> SyncResult<CloudInfo>49 pub fn get_service_info(&mut self) -> SyncResult<CloudInfo> { 50 let mut cloud_info = self.get_cloud_info()?; 51 cloud_info.user = self.user_id; 52 let app_infos = self.connect.get_app_brief_info(self.user_id)?; 53 for app in &app_infos.0 { 54 let cloud_app_info = AppInfo::from(app.1); 55 cloud_info 56 .apps 57 .insert(cloud_app_info.bundle_name.clone(), cloud_app_info); 58 } 59 Ok(cloud_info) 60 } 61 62 /// Get a application schema by bundle name from the other end through the IPC connection get_app_schema(&mut self, bundle_name: &str) -> SyncResult<SchemaMeta>63 pub fn get_app_schema(&mut self, bundle_name: &str) -> SyncResult<SchemaMeta> { 64 let schema_ipc = self.connect.get_app_schema(self.user_id, bundle_name)?; 65 Ok(SchemaMeta::from(schema_ipc.deref())) 66 } 67 68 /// Passing in relations and a callback function, if possible, send the subscription relation 69 /// to the cloud server and the specific database. subscribe( &mut self, dbs: &HashMap<String, Vec<Database>>, expire: i64, ) -> SyncResult<HashMap<String, RelationSet>>70 pub fn subscribe( 71 &mut self, 72 dbs: &HashMap<String, Vec<Database>>, 73 expire: i64, 74 ) -> SyncResult<HashMap<String, RelationSet>> { 75 let mut result = HashMap::new(); 76 for (bundle_name, dbmetas) in dbs { 77 let mut vec = vec![]; 78 for dbmeta in dbmetas { 79 vec.push(dbmeta.try_into()?) 80 } 81 let dbs_ipc = ipc_conn::Databases(vec); 82 83 let ret = self.connect.subscribe(expire, bundle_name, &dbs_ipc)?; 84 let (ret_expire, map) = ret.0; 85 for (bundle_name_ret, sub_result) in map { 86 let mut r = RelationSet { 87 bundle_name: bundle_name.clone(), 88 expire_time: ret_expire, 89 relations: HashMap::new(), 90 }; 91 for (alias, id) in sub_result.0 { 92 r.relations.insert(alias, id); 93 } 94 result.insert(bundle_name_ret, r); 95 } 96 } 97 Ok(result) 98 } 99 100 /// Passing in relations and a callback function, if possible, send the unsubscription relation 101 /// to the cloud server and the specific database. unsubscribe(&mut self, relations: &HashMap<String, Vec<String>>) -> SyncResult<()>102 pub fn unsubscribe(&mut self, relations: &HashMap<String, Vec<String>>) -> SyncResult<()> { 103 if relations.is_empty() { 104 return Ok(()); 105 } 106 let unsub = ipc_conn::UnsubscriptionInfo(relations.clone()); 107 self.connect.unsubscribe(&unsub)?; 108 Ok(()) 109 } 110 } 111 112 /// Struct of SchemaMeta, containing schema information on a cloud server. 113 pub struct SchemaMeta { 114 version: i32, 115 bundle_name: String, 116 databases: Vec<Database>, 117 } 118 119 impl Default for SchemaMeta { default() -> Self120 fn default() -> Self { 121 SchemaMeta { 122 version: 0, 123 bundle_name: "".to_string(), 124 databases: vec![], 125 } 126 } 127 } 128 129 impl SchemaMeta { 130 /// Get version of SchemaMeta instance. version(&self) -> i32131 pub fn version(&self) -> i32 { 132 self.version 133 } 134 135 /// Get bundle name of SchemaMeta instance. bundle_name(&self) -> &str136 pub fn bundle_name(&self) -> &str { 137 &self.bundle_name 138 } 139 140 /// Get database from a SchemaMeta instance by store id. databases(&self) -> &[Database]141 pub fn databases(&self) -> &[Database] { 142 &self.databases 143 } 144 } 145 146 impl From<&ipc_conn::Schema> for SchemaMeta { from(value: &ipc_conn::Schema) -> Self147 fn from(value: &ipc_conn::Schema) -> Self { 148 let mut dbs = vec![]; 149 for db in &value.databases.0 { 150 dbs.push(Database::from(db)); 151 } 152 SchemaMeta { 153 version: value.version, 154 bundle_name: value.bundle_name.clone(), 155 databases: dbs, 156 } 157 } 158 } 159 160 /// Struct of CloudInfo 161 pub struct CloudInfo { 162 pub(crate) user: i32, 163 pub(crate) id: String, 164 pub(crate) total_space: u64, 165 pub(crate) remain_space: u64, 166 pub(crate) enable_cloud: bool, 167 pub(crate) apps: HashMap<String, AppInfo>, 168 } 169 170 impl From<&ipc_conn::ServiceInfo> for CloudInfo { from(value: &ipc_conn::ServiceInfo) -> Self171 fn from(value: &ipc_conn::ServiceInfo) -> Self { 172 CloudInfo { 173 user: value.user, 174 id: value.account_id.clone(), 175 total_space: value.total_space, 176 remain_space: value.remain_space, 177 enable_cloud: value.enable_cloud, 178 apps: Default::default(), 179 } 180 } 181 } 182 183 impl CloudInfo { 184 /// Get user of CloudInfo instance. get_user(&self) -> i32185 pub fn get_user(&self) -> i32 { 186 self.user 187 } 188 189 /// Get id of CloudInfo instance. get_id(&self) -> &str190 pub fn get_id(&self) -> &str { 191 &self.id 192 } 193 194 /// Get total space of CloudInfo instance. get_total_space(&self) -> u64195 pub fn get_total_space(&self) -> u64 { 196 self.total_space 197 } 198 199 /// Get remain space of CloudInfo instance. get_remain_space(&self) -> u64200 pub fn get_remain_space(&self) -> u64 { 201 self.remain_space 202 } 203 204 /// Check whether the CloudInfo instance enables cloud synchronization. get_enable_cloud(&self) -> bool205 pub fn get_enable_cloud(&self) -> bool { 206 self.enable_cloud 207 } 208 209 /// Get app info from CloudInfo instance. get_app_info(&self) -> &HashMap<String, AppInfo>210 pub fn get_app_info(&self) -> &HashMap<String, AppInfo> { 211 &self.apps 212 } 213 } 214 215 /// Struct of App Info. 216 #[derive(Clone)] 217 pub struct AppInfo { 218 pub(crate) bundle_name: String, 219 pub(crate) app_id: String, 220 pub(crate) instance_id: i32, 221 pub(crate) cloud_switch: bool, 222 } 223 224 impl From<&ipc_conn::AppInfo> for AppInfo { from(value: &ipc_conn::AppInfo) -> Self225 fn from(value: &ipc_conn::AppInfo) -> Self { 226 AppInfo { 227 bundle_name: value.bundle_name.clone(), 228 app_id: value.app_id.clone(), 229 instance_id: value.instance_id, 230 cloud_switch: value.cloud_switch, 231 } 232 } 233 } 234 235 impl AppInfo { 236 /// Get bundle name of AppInfo instance. bundle_name(&self) -> &str237 pub fn bundle_name(&self) -> &str { 238 &self.bundle_name 239 } 240 241 /// Get app id of AppInfo instance. app_id(&self) -> &str242 pub fn app_id(&self) -> &str { 243 &self.app_id 244 } 245 246 /// Check whether the AppInfo instance allows cloud switch. cloud_switch(&self) -> bool247 pub fn cloud_switch(&self) -> bool { 248 self.cloud_switch 249 } 250 251 /// Get instance id of AppInfo instance. instance_id(&self) -> i32252 pub fn instance_id(&self) -> i32 { 253 self.instance_id 254 } 255 } 256 257 /// Struct of Relation to represent subscription relations. 258 #[derive(Default, Clone)] 259 pub struct RelationSet { 260 pub(crate) bundle_name: String, 261 pub(crate) expire_time: i64, 262 // Database alias as key, subscription id generated by the cloud as value 263 pub(crate) relations: HashMap<String, String>, 264 } 265 266 impl RelationSet { 267 /// New a RelationSet. new( bundle_name: String, expire_time: i64, relations: HashMap<String, String>, ) -> RelationSet268 pub fn new( 269 bundle_name: String, 270 expire_time: i64, 271 relations: HashMap<String, String>, 272 ) -> RelationSet { 273 RelationSet { 274 bundle_name, 275 expire_time, 276 relations, 277 } 278 } 279 280 /// Get the relating bundle name of this RelationSet instance. bundle_name(&self) -> &str281 pub fn bundle_name(&self) -> &str { 282 self.bundle_name.as_str() 283 } 284 285 /// Get expire time of this RelationSet instance. expire_time(&self) -> i64286 pub fn expire_time(&self) -> i64 { 287 self.expire_time 288 } 289 290 /// Get the inner hashmap describing relations, with database alias as key, subscription id and 291 /// time as value. relations(&self) -> &HashMap<String, String>292 pub fn relations(&self) -> &HashMap<String, String> { 293 &self.relations 294 } 295 } 296