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 pub use crate::ipc_conn::{AssetStatus, CloudAsset}; 17 use crate::service_impl::error::SyncError; 18 use crate::service_impl::types::{Database, Table}; 19 use crate::{ipc_conn, SyncResult}; 20 use std::collections::HashMap; 21 22 /// Cloud Asset loader struct. 23 pub struct CloudAssetLoader<'a> { 24 asset_loader: ipc_conn::AssetLoader, 25 tables: &'a HashMap<String, Table>, 26 // Keep the following fields below for future extension. 27 #[allow(unused)] 28 bundle_name: String, 29 } 30 31 impl<'a> CloudAssetLoader<'a> { 32 /// Initialize a CloudAssetLoader instance from user id, bundle name, and database. 33 /// Database can be obtained from CloudInfo and CloudSync. new(user_id: i32, bundle_name: &str, db: &'a Database) -> SyncResult<Self>34 pub fn new(user_id: i32, bundle_name: &str, db: &'a Database) -> SyncResult<Self> { 35 let asset_loader = ipc_conn::AssetLoader::new(user_id)?; 36 Ok(CloudAssetLoader { 37 asset_loader, 38 tables: &db.tables, 39 bundle_name: bundle_name.to_string(), 40 }) 41 } 42 43 /// Take in table name, gid, prefix, and assets, send upload request to the other side of IPC 44 /// connection. Necessary information will be updated in the parameter assets. The cloud storage 45 /// will ask for files from source paths, and this function only returns result and relating infos. upload( &self, table_name: &str, gid: &str, prefix: &str, assets: &[CloudAsset], ) -> SyncResult<Vec<Result<CloudAsset, SyncError>>>46 pub fn upload( 47 &self, 48 table_name: &str, 49 gid: &str, 50 prefix: &str, 51 assets: &[CloudAsset], 52 ) -> SyncResult<Vec<Result<CloudAsset, SyncError>>> { 53 self.upload_download_inner( 54 table_name, 55 gid, 56 prefix, 57 assets, 58 ipc_conn::AssetLoader::upload, 59 ) 60 } 61 62 /// Take in table name, gid, prefix, and assets, send download request to the other side of IPC 63 /// connection. Necessary information will be updated in the parameter assets. The cloud storage 64 /// will send files to target paths, and this function only returns result and relating infos. download( &self, table_name: &str, gid: &str, prefix: &str, assets: &[CloudAsset], ) -> SyncResult<Vec<Result<CloudAsset, SyncError>>>65 pub fn download( 66 &self, 67 table_name: &str, 68 gid: &str, 69 prefix: &str, 70 assets: &[CloudAsset], 71 ) -> SyncResult<Vec<Result<CloudAsset, SyncError>>> { 72 self.upload_download_inner( 73 table_name, 74 gid, 75 prefix, 76 assets, 77 ipc_conn::AssetLoader::download, 78 ) 79 } 80 81 /// Remove local file according to the path in the asset passed in. remove_local_assets(asset: &CloudAsset) -> SyncResult<()>82 pub fn remove_local_assets(asset: &CloudAsset) -> SyncResult<()> { 83 std::fs::remove_file(asset.local_path())?; 84 Ok(()) 85 } 86 upload_download_inner<F>( &self, table_name: &str, gid: &str, prefix: &str, assets: &[CloudAsset], mut f: F, ) -> SyncResult<Vec<Result<CloudAsset, SyncError>>> where F: FnMut( &ipc_conn::AssetLoader, &str, &str, &str, &ipc_conn::CloudAssets, ) -> Result<Vec<Result<CloudAsset, ipc_conn::Error>>, ipc_conn::Error>,87 fn upload_download_inner<F>( 88 &self, 89 table_name: &str, 90 gid: &str, 91 prefix: &str, 92 assets: &[CloudAsset], 93 mut f: F, 94 ) -> SyncResult<Vec<Result<CloudAsset, SyncError>>> 95 where 96 F: FnMut( 97 &ipc_conn::AssetLoader, 98 &str, 99 &str, 100 &str, 101 &ipc_conn::CloudAssets, 102 ) -> Result<Vec<Result<CloudAsset, ipc_conn::Error>>, ipc_conn::Error>, 103 { 104 let mut assets_ipc = ipc_conn::CloudAssets::default(); 105 for asset in assets.iter() { 106 if asset.status == AssetStatus::Delete { 107 CloudAssetLoader::remove_local_assets(asset)?; 108 } 109 110 assets_ipc.0.push(asset.clone()); 111 } 112 let alias = self.get_table_alias(table_name); 113 let ret = f(&self.asset_loader, alias, gid, prefix, &assets_ipc)?; 114 let mut ret_map = vec![]; 115 for single_result in ret { 116 ret_map.push(single_result.map_err(|e| e.into())); 117 } 118 Ok(ret_map) 119 } 120 get_table_alias(&self, table_name: &str) -> &str121 fn get_table_alias(&self, table_name: &str) -> &str { 122 match self.tables.get(table_name) { 123 None => "", 124 Some(t) => t.alias.as_str(), 125 } 126 } 127 } 128