From b9280ab62d24d952b081de669dee59693af49ae5 Mon Sep 17 00:00:00 2001 From: weisd Date: Wed, 21 Aug 2024 17:14:46 +0800 Subject: [PATCH 01/10] stash delete_object --- ecstore/src/sets.rs | 24 ++++++++++ ecstore/src/store.rs | 97 ++++++++++++++++++++++++++++++++++++++++ ecstore/src/store_api.rs | 15 ++++--- 3 files changed, 130 insertions(+), 6 deletions(-) diff --git a/ecstore/src/sets.rs b/ecstore/src/sets.rs index b9adb1f9..a21b1714 100644 --- a/ecstore/src/sets.rs +++ b/ecstore/src/sets.rs @@ -1,3 +1,4 @@ +use futures::future::join_all; use http::HeaderMap; use uuid::Uuid; @@ -110,6 +111,22 @@ impl Sets { // ) -> Vec> { // unimplemented!() // } + + async fn delete_prefix(&self, bucket: &str, object: &str) -> Result<()> { + let mut futures = Vec::new(); + let opt = ObjectOptions { + delete_prefix: true, + ..Default::default() + }; + + for set in self.disk_set.iter() { + futures.push(set.delete_object(bucket, object, opt.clone())); + } + + let _results = join_all(futures).await; + + Ok(()) + } } // #[derive(Debug)] @@ -134,7 +151,14 @@ impl StorageAPI for Sets { async fn get_bucket_info(&self, _bucket: &str, _opts: &BucketOptions) -> Result { unimplemented!() } + async fn delete_object(&self, bucket: &str, object: &str, opts: ObjectOptions) -> Result { + if opts.delete_prefix { + self.delete_prefix(bucket, object).await?; + return Ok(ObjectInfo::default()); + } + self.get_disks_by_key(object).delete_object(bucket, object, opts).await + } async fn list_objects_v2( &self, _bucket: &str, diff --git a/ecstore/src/store.rs b/ecstore/src/store.rs index bbcc49fa..44a43223 100644 --- a/ecstore/src/store.rs +++ b/ecstore/src/store.rs @@ -16,6 +16,7 @@ use futures::future::join_all; use http::HeaderMap; use s3s::{dto::StreamingBlob, Body}; use std::collections::{HashMap, HashSet}; +use time::OffsetDateTime; use tracing::{debug, warn}; use uuid::Uuid; @@ -227,6 +228,77 @@ impl ECStore { Ok(()) } + async fn delete_prefix(&self, _bucket: &str, _object: &str) -> Result<()> { + unimplemented!() + } + + async fn get_pool_info_existing_with_opts( + &self, + bucket: &str, + object: &str, + opts: &ObjectOptions, + ) -> Result<(PoolObjInfo, Vec)> { + let mut futures = Vec::new(); + + for pool in self.pools.iter() { + futures.push(pool.get_object_info(bucket, object, opts)); + } + + let results = join_all(futures).await; + + let mut ress = Vec::new(); + + let mut i = 0; + + // join_all结果跟输入顺序一致 + for res in results { + let index = i; + + match res { + Ok(r) => { + ress.push(PoolObjInfo { + index, + object_info: r, + err: None, + }); + } + Err(e) => { + ress.push(PoolObjInfo { + index, + err: Some(e), + ..Default::default() + }); + } + } + i += 1; + } + + ress.sort_by(|a, b| { + let at = a.object_info.mod_time.unwrap_or(OffsetDateTime::UNIX_EPOCH); + let bt = b.object_info.mod_time.unwrap_or(OffsetDateTime::UNIX_EPOCH); + + at.cmp(&bt) + }); + + for res in ress { + // check + if res.err.is_none() { + // TODO: let errs = self.poolsWithObject() + return Ok((res, Vec::new())); + } + } + + let ret = PoolObjInfo::default(); + + Ok((ret, Vec::new())) + } +} + +#[derive(Debug, Default)] +pub struct PoolObjInfo { + pub index: usize, + pub object_info: ObjectInfo, + pub err: Option, } #[derive(Debug, Default)] @@ -302,6 +374,31 @@ impl StorageAPI for ECStore { Ok(info) } + async fn delete_object(&self, bucket: &str, object: &str, opts: ObjectOptions) -> Result { + if opts.delete_prefix { + self.delete_prefix(bucket, &object).await?; + return Ok(ObjectInfo::default()); + } + + let object = utils::path::encode_dir_object(object); + let object = object.as_str(); + + // 查询在哪个pool + let (mut pinfo, errs) = self.get_pool_info_existing_with_opts(bucket, object, &opts).await?; + if pinfo.object_info.delete_marker && opts.version_id.is_empty() { + pinfo.object_info.name = utils::path::decode_dir_object(object); + return Ok(pinfo.object_info); + } + + if !errs.is_empty() { + // TODO: deleteObjectFromAllPools + } + + let mut obj = self.pools[pinfo.index].delete_object(bucket, object, opts.clone()).await?; + obj.name = utils::path::decode_dir_object(object); + + Ok(obj) + } async fn list_objects_v2( &self, bucket: &str, diff --git a/ecstore/src/store_api.rs b/ecstore/src/store_api.rs index 3aa50f56..0228338f 100644 --- a/ecstore/src/store_api.rs +++ b/ecstore/src/store_api.rs @@ -86,7 +86,7 @@ impl FileInfo { parity_blocks: self.erasure.parity_blocks, data_blocks: self.erasure.data_blocks, version_id: self.version_id, - deleted: self.deleted, + delete_marker: self.deleted, mod_time: self.mod_time, size: self.size, parts: self.parts.clone(), @@ -358,12 +358,15 @@ impl HTTPRangeSpec { } } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct ObjectOptions { // Use the maximum parity (N/2), used when saving server configuration files pub max_parity: bool, pub mod_time: Option, pub part_number: usize, + + pub delete_prefix: bool, + pub version_id: String, } // impl Default for ObjectOptions { @@ -413,13 +416,13 @@ impl From for CompletePart { pub struct ObjectInfo { pub bucket: String, pub name: String, + pub mod_time: Option, + pub size: usize, pub is_dir: bool, pub parity_blocks: usize, pub data_blocks: usize, pub version_id: Uuid, - pub deleted: bool, - pub mod_time: Option, - pub size: usize, + pub delete_marker: bool, pub parts: Vec, pub is_latest: bool, } @@ -474,7 +477,7 @@ pub trait StorageAPI { async fn delete_bucket(&self, bucket: &str) -> Result<()>; async fn list_bucket(&self, opts: &BucketOptions) -> Result>; async fn get_bucket_info(&self, bucket: &str, opts: &BucketOptions) -> Result; - + async fn delete_object(&self, bucket: &str, object: &str, opts: ObjectOptions) -> Result; async fn list_objects_v2( &self, bucket: &str, From 0080383c401f8868e39373cbbd55ea5917491c46 Mon Sep 17 00:00:00 2001 From: weisd Date: Thu, 22 Aug 2024 17:18:40 +0800 Subject: [PATCH 02/10] stash delete_object --- ecstore/src/sets.rs | 15 ++++- ecstore/src/store.rs | 122 ++++++++++++++++++++++++++++++++++++++- ecstore/src/store_api.rs | 22 +++++++ 3 files changed, 154 insertions(+), 5 deletions(-) diff --git a/ecstore/src/sets.rs b/ecstore/src/sets.rs index a21b1714..53851cb1 100644 --- a/ecstore/src/sets.rs +++ b/ecstore/src/sets.rs @@ -8,11 +8,11 @@ use crate::{ DiskStore, }, endpoints::PoolEndpoints, - error::Result, + error::{Error, Result}, set_disk::SetDisks, store_api::{ - BucketInfo, BucketOptions, CompletePart, GetObjectReader, HTTPRangeSpec, ListObjectsV2Info, MakeBucketOptions, - MultipartUploadResult, ObjectInfo, ObjectOptions, PartInfo, PutObjReader, StorageAPI, + BucketInfo, BucketOptions, CompletePart, DeletedObject, GetObjectReader, HTTPRangeSpec, ListObjectsV2Info, + MakeBucketOptions, MultipartUploadResult, ObjectInfo, ObjectOptions, ObjectToDelete, PartInfo, PutObjReader, StorageAPI, }, utils::hash, }; @@ -151,6 +151,15 @@ impl StorageAPI for Sets { async fn get_bucket_info(&self, _bucket: &str, _opts: &BucketOptions) -> Result { unimplemented!() } + async fn delete_objects( + &self, + _bucket: &str, + _objects: Vec, + _opts: ObjectOptions, + ) -> Result<(Vec, Vec>)> { + // FIXME: + unimplemented!() + } async fn delete_object(&self, bucket: &str, object: &str, opts: ObjectOptions) -> Result { if opts.delete_prefix { self.delete_prefix(bucket, object).await?; diff --git a/ecstore/src/store.rs b/ecstore/src/store.rs index 44a43223..315b6986 100644 --- a/ecstore/src/store.rs +++ b/ecstore/src/store.rs @@ -7,8 +7,9 @@ use crate::{ peer::{PeerS3Client, S3PeerSys}, sets::Sets, store_api::{ - BucketInfo, BucketOptions, CompletePart, GetObjectReader, HTTPRangeSpec, ListObjectsInfo, ListObjectsV2Info, - MakeBucketOptions, MultipartUploadResult, ObjectInfo, ObjectOptions, PartInfo, PutObjReader, StorageAPI, + BucketInfo, BucketOptions, CompletePart, DeletedObject, GetObjectReader, HTTPRangeSpec, ListObjectsInfo, + ListObjectsV2Info, MakeBucketOptions, MultipartUploadResult, ObjectInfo, ObjectOptions, ObjectToDelete, PartInfo, + PutObjReader, StorageAPI, }, store_init, utils, }; @@ -373,7 +374,124 @@ impl StorageAPI for ECStore { Ok(info) } + async fn delete_objects( + &self, + bucket: &str, + objects: Vec, + opts: ObjectOptions, + ) -> Result<(Vec, Vec>)> { + // encode object name + let objects: Vec = objects + .iter() + .map(|v| { + let mut v = v.clone(); + v.object_name = utils::path::encode_dir_object(v.object_name.as_str()); + v + }) + .collect(); + // 默认返回值 + let mut del_objects = vec![DeletedObject::default(); objects.len()]; + + let mut del_errs = Vec::with_capacity(objects.len()); + for _ in 0..objects.len() { + del_errs.push(None) + } + + // TODO: limte 限制并发数量 + let opt = ObjectOptions::default(); + // 取所有poolObjInfo + let mut futures = Vec::new(); + for obj in objects.iter() { + futures.push(self.get_pool_info_existing_with_opts(bucket, &obj.object_name, &opt)); + } + + let results = join_all(futures).await; + + // 记录pool Index 对应的objects pool_idx -> objects idx + let mut pool_index_objects = HashMap::new(); + + let mut i = 0; + for res in results { + match res { + Ok((pinfo, _)) => { + if pinfo.object_info.delete_marker && opts.version_id.is_empty() { + del_objects[i] = DeletedObject { + delete_marker: pinfo.object_info.delete_marker, + delete_marker_version_id: pinfo.object_info.version_id.to_string(), + object_name: utils::path::decode_dir_object(&pinfo.object_info.name), + delete_marker_mtime: pinfo.object_info.mod_time, + ..Default::default() + }; + } + + if !pool_index_objects.contains_key(&pinfo.index) { + pool_index_objects.insert(pinfo.index, vec![i]); + } else { + // let mut vals = pool_index_objects. + if let Some(val) = pool_index_objects.get_mut(&pinfo.index) { + val.push(i); + } + } + } + Err(e) => { + //TODO: check not found + + del_errs[i] = Some(e) + } + } + + i += 1; + } + + if !pool_index_objects.is_empty() { + for sets in self.pools.iter() { + // 取pool idx 对应的 objects index + let vals = pool_index_objects.get(&sets.pool_idx); + if vals.is_none() { + continue; + } + + let obj_idxs = vals.unwrap(); + // 取对应obj,理论上不会none + let objs: Vec = obj_idxs + .iter() + .filter_map(|&idx| { + if let Some(obj) = objects.get(idx) { + Some(obj.clone()) + } else { + None + } + }) + .collect(); + + if objs.is_empty() { + continue; + } + + let (pdel_objs, perrs) = sets.delete_objects(bucket, objs, opts.clone()).await?; + + // perrs的顺序理论上跟obj_idxs顺序一致 + let mut i = 0; + for err in perrs { + let obj_idx = obj_idxs[i]; + + if err.is_some() { + del_errs[obj_idx] = err; + } + + let mut dobj = pdel_objs.get(i).unwrap().clone(); + dobj.object_name = utils::path::decode_dir_object(&dobj.object_name); + + del_objects[obj_idx] = dobj; + + i += 1; + } + } + } + + Ok((del_objects, del_errs)) + } async fn delete_object(&self, bucket: &str, object: &str, opts: ObjectOptions) -> Result { if opts.delete_prefix { self.delete_prefix(bucket, &object).await?; diff --git a/ecstore/src/store_api.rs b/ecstore/src/store_api.rs index 0228338f..39f9a523 100644 --- a/ecstore/src/store_api.rs +++ b/ecstore/src/store_api.rs @@ -471,6 +471,22 @@ pub struct ListObjectsV2Info { pub prefixes: Vec, } +#[derive(Debug, Default, Clone)] +pub struct ObjectToDelete { + pub object_name: String, +} +#[derive(Debug, Default, Clone)] +pub struct DeletedObject { + pub delete_marker: bool, + pub delete_marker_version_id: String, + pub object_name: String, + pub version_id: String, + // MTime of DeleteMarker on source that needs to be propagated to replica + pub delete_marker_mtime: Option, + // to support delete marker replication + // pub replication_state: ReplicationState, +} + #[async_trait::async_trait] pub trait StorageAPI { async fn make_bucket(&self, bucket: &str, opts: &MakeBucketOptions) -> Result<()>; @@ -478,6 +494,12 @@ pub trait StorageAPI { async fn list_bucket(&self, opts: &BucketOptions) -> Result>; async fn get_bucket_info(&self, bucket: &str, opts: &BucketOptions) -> Result; async fn delete_object(&self, bucket: &str, object: &str, opts: ObjectOptions) -> Result; + async fn delete_objects( + &self, + bucket: &str, + objects: Vec, + opts: ObjectOptions, + ) -> Result<(Vec, Vec>)>; async fn list_objects_v2( &self, bucket: &str, From 7f8854d7f5018ebfdc2bf507d4505a2d1bea4186 Mon Sep 17 00:00:00 2001 From: weisd Date: Thu, 22 Aug 2024 17:48:35 +0800 Subject: [PATCH 03/10] stash delete_object --- ecstore/src/sets.rs | 72 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/ecstore/src/sets.rs b/ecstore/src/sets.rs index 53851cb1..63815089 100644 --- a/ecstore/src/sets.rs +++ b/ecstore/src/sets.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use futures::future::join_all; use http::HeaderMap; use uuid::Uuid; @@ -139,6 +141,12 @@ impl Sets { // pub default_parity_count: usize, // } +struct DelObj { + // set_idx: usize, + orig_idx: usize, + obj: ObjectToDelete, +} + #[async_trait::async_trait] impl StorageAPI for Sets { async fn list_bucket(&self, _opts: &BucketOptions) -> Result> { @@ -153,12 +161,66 @@ impl StorageAPI for Sets { } async fn delete_objects( &self, - _bucket: &str, - _objects: Vec, - _opts: ObjectOptions, + bucket: &str, + objects: Vec, + opts: ObjectOptions, ) -> Result<(Vec, Vec>)> { - // FIXME: - unimplemented!() + // 默认返回值 + let mut del_objects = vec![DeletedObject::default(); objects.len()]; + + let mut del_errs = Vec::with_capacity(objects.len()); + for _ in 0..objects.len() { + del_errs.push(None) + } + + let mut set_obj_map = HashMap::new(); + + // hash key + let mut i = 0; + for obj in objects.iter() { + let idx = self.get_hashed_set_index(obj.object_name.as_str()); + + if !set_obj_map.contains_key(&idx) { + set_obj_map.insert( + idx, + vec![DelObj { + // set_idx: idx, + orig_idx: i, + obj: obj.clone(), + }], + ); + } else { + if let Some(val) = set_obj_map.get_mut(&idx) { + val.push(DelObj { + // set_idx: idx, + orig_idx: i, + obj: obj.clone(), + }); + } + } + + i += 1; + } + + // TODO: 并发 + for (k, v) in set_obj_map { + let disks = self.get_disks(k); + let objs: Vec = v.iter().map(|v| v.obj.clone()).collect(); + let (dobjects, errs) = disks.delete_objects(bucket, objs, opts.clone()).await?; + + let mut i = 0; + for err in errs { + let obj = v.get(i).unwrap(); + + del_errs[obj.orig_idx] = err; + + del_objects[obj.orig_idx] = dobjects.get(i).unwrap().clone(); + + i += 1; + } + } + + Ok((del_objects, del_errs)) } async fn delete_object(&self, bucket: &str, object: &str, opts: ObjectOptions) -> Result { if opts.delete_prefix { From 2058f765b0349b3e1b33a842801b8237a498d36f Mon Sep 17 00:00:00 2001 From: weisd Date: Fri, 23 Aug 2024 17:48:29 +0800 Subject: [PATCH 04/10] stash delete_object --- ecstore/src/disk/local.rs | 119 +++++++++++++++++++++++++++++-------- ecstore/src/disk/mod.rs | 24 +++++++- ecstore/src/store_api.rs | 122 +++++++++++++++++++------------------- 3 files changed, 176 insertions(+), 89 deletions(-) diff --git a/ecstore/src/disk/local.rs b/ecstore/src/disk/local.rs index 9de369ac..407c779e 100644 --- a/ecstore/src/disk/local.rs +++ b/ecstore/src/disk/local.rs @@ -1,7 +1,7 @@ use super::{endpoint::Endpoint, error::DiskError, format::FormatV3}; use super::{ - DeleteOptions, DiskAPI, FileReader, FileWriter, MetaCacheEntry, ReadMultipleReq, ReadMultipleResp, ReadOptions, - RenameDataResp, VolumeInfo, WalkDirOptions, + DeleteOptions, DiskAPI, FileInfoVersions, FileReader, FileWriter, MetaCacheEntry, ReadMultipleReq, ReadMultipleResp, + ReadOptions, RenameDataResp, VolumeInfo, WalkDirOptions, }; use crate::disk::STORAGE_FORMAT_FILE; use crate::{ @@ -138,8 +138,34 @@ impl LocalDisk { Ok(()) } + pub async fn move_to_trash(&self, delete_path: &PathBuf, _recursive: bool, _immediate_purge: bool) -> Result<()> { + let trash_path = self.get_object_path(super::RUSTFS_META_TMP_DELETED_BUCKET, Uuid::new_v4().to_string().as_str())?; + // TODO: 清空回收站 + if let Err(err) = fs::rename(&delete_path, &trash_path).await { + match err.kind() { + ErrorKind::NotFound => (), + _ => { + warn!("delete_file rename {:?} err {:?}", &delete_path, &err); + return Err(Error::from(err)); + } + } + } + + // FIXME: 先清空回收站吧,有时间再添加判断逻辑 + let _ = fs::remove_dir_all(&trash_path).await; + + // TODO: immediate + Ok(()) + } + // #[tracing::instrument(skip(self))] - pub async fn delete_file(&self, base_path: &PathBuf, delete_path: &PathBuf, recursive: bool, _immediate: bool) -> Result<()> { + pub async fn delete_file( + &self, + base_path: &PathBuf, + delete_path: &PathBuf, + recursive: bool, + immediate_purge: bool, + ) -> Result<()> { debug!("delete_file {:?}\n base_path:{:?}", &delete_path, &base_path); if is_root_path(base_path) || is_root_path(delete_path) { @@ -153,29 +179,7 @@ impl LocalDisk { } if recursive { - let trash_path = self.get_object_path(super::RUSTFS_META_TMP_DELETED_BUCKET, Uuid::new_v4().to_string().as_str())?; - - if let Some(dir_path) = trash_path.parent() { - fs::create_dir_all(dir_path).await?; - } - - debug!("delete_file ranme to trash {:?} to {:?}", &delete_path, &trash_path); - - // TODO: 清空回收站 - if let Err(err) = fs::rename(&delete_path, &trash_path).await { - match err.kind() { - ErrorKind::NotFound => (), - _ => { - warn!("delete_file rename {:?} err {:?}", &delete_path, &err); - return Err(Error::from(err)); - } - } - } - - // FIXME: 先清空回收站吧,有时间再添加判断逻辑 - let _ = fs::remove_dir_all(&trash_path).await; - - // TODO: immediate + self.move_to_trash(delete_path, recursive, immediate_purge).await?; } else { if delete_path.is_dir() { if let Err(err) = fs::remove_dir(&delete_path).await { @@ -253,6 +257,51 @@ impl LocalDisk { Ok((data, modtime)) } + + async fn delete_versions_internal(&self, volume: &str, path: &str, fis: &Vec) -> Result<()> { + let volume_dir = self.get_bucket_path(volume)?; + let xlpath = self.get_object_path(volume, format!("{}/{}", path, super::STORAGE_FORMAT_FILE).as_str())?; + + let (data, _) = match self.read_all_data(volume, volume_dir.as_path(), &xlpath).await { + Ok(res) => res, + Err(_err) => { + // TODO: check if not found return err + + (Vec::new(), OffsetDateTime::UNIX_EPOCH) + } + }; + + if data.is_empty() { + return Err(Error::new(DiskError::FileNotFound)); + } + + let mut fm = FileMeta::default(); + + fm.unmarshal_msg(&data)?; + + for fi in fis { + let data_dir = fm.delete_version(fi)?; + + if data_dir.is_some() { + let dir_path = self.get_object_path(volume, format!("{}/{}", path, data_dir.unwrap().to_string()).as_str())?; + + self.move_to_trash(&dir_path, true, false).await?; + } + } + + // 没有版本了,删除xl.meta + if fm.versions.is_empty() { + self.delete_file(&volume_dir, &xlpath, true, false).await?; + } + + // 更新xl.meta + let buf = fm.marshal_msg()?; + + self.write_all(volume, format!("{}/{}", path, super::STORAGE_FORMAT_FILE).as_str(), buf) + .await?; + + Ok(()) + } } fn is_root_path(path: impl AsRef) -> bool { @@ -815,6 +864,24 @@ impl DiskAPI for LocalDisk { Ok(RawFileInfo { buf }) } + async fn delete_versions( + &self, + volume: &str, + versions: Vec, + _opts: DeleteOptions, + ) -> Result>> { + let mut errs = Vec::with_capacity(versions.len()); + + for (i, ver) in versions.iter().enumerate() { + if let Err(e) = self.delete_versions_internal(volume, ver.name.as_str(), &ver.versions).await { + errs[i] = Some(e); + } else { + errs[i] = None; + } + } + + Ok(errs) + } async fn read_multiple(&self, req: ReadMultipleReq) -> Result> { let mut results = Vec::new(); let mut found = 0; diff --git a/ecstore/src/disk/mod.rs b/ecstore/src/disk/mod.rs index b694f99b..71701467 100644 --- a/ecstore/src/disk/mod.rs +++ b/ecstore/src/disk/mod.rs @@ -13,7 +13,7 @@ const STORAGE_FORMAT_FILE: &str = "xl.meta"; use crate::{ erasure::ReadAt, - error::Result, + error::{Error, Result}, file_meta::FileMeta, store_api::{FileInfo, RawFileInfo}, }; @@ -79,9 +79,31 @@ pub trait DiskAPI: Debug + Send + Sync + 'static { opts: &ReadOptions, ) -> Result; async fn read_xl(&self, volume: &str, path: &str, read_data: bool) -> Result; + async fn delete_versions( + &self, + volume: &str, + versions: Vec, + opts: DeleteOptions, + ) -> Result>>; async fn read_multiple(&self, req: ReadMultipleReq) -> Result>; } +#[derive(Debug, Default, Clone)] +pub struct FileInfoVersions { + // Name of the volume. + pub volume: String, + + // Name of the file. + pub name: String, + + // Represents the latest mod time of the + // latest version. + pub latest_mod_time: Option, + + pub versions: Vec, + pub free_versions: Vec, +} + #[derive(Debug, Default, Clone)] pub struct WalkDirOptions { // Bucket to scanner diff --git a/ecstore/src/store_api.rs b/ecstore/src/store_api.rs index 39f9a523..328d3f8f 100644 --- a/ecstore/src/store_api.rs +++ b/ecstore/src/store_api.rs @@ -27,7 +27,66 @@ pub struct FileInfo { pub is_latest: bool, } +impl Default for FileInfo { + fn default() -> Self { + Self { + version_id: Uuid::nil(), + erasure: Default::default(), + deleted: Default::default(), + data_dir: Uuid::nil(), + mod_time: None, + size: Default::default(), + data: Default::default(), + fresh: Default::default(), + name: Default::default(), + volume: Default::default(), + parts: Default::default(), + is_latest: Default::default(), + } + } +} + impl FileInfo { + pub fn new(object: &str, data_blocks: usize, parity_blocks: usize) -> Self { + let indexs = { + let cardinality = data_blocks + parity_blocks; + let mut nums = vec![0; cardinality]; + let key_crc = crc32fast::hash(object.as_bytes()); + + let start = key_crc as usize % cardinality; + for i in 1..=cardinality { + nums[i - 1] = 1 + ((start + i) % cardinality); + } + + nums + }; + Self { + erasure: ErasureInfo { + algorithm: String::from(ERASURE_ALGORITHM), + data_blocks, + parity_blocks, + block_size: BLOCK_SIZE_V2, + distribution: indexs, + ..Default::default() + }, + ..Default::default() + } + } + + pub fn is_valid(&self) -> bool { + if self.deleted { + return true; + } + + let data_blocks = self.erasure.data_blocks; + let parity_blocks = self.erasure.parity_blocks; + + (data_blocks >= parity_blocks) + && (data_blocks > 0) + && (self.erasure.index > 0 + && self.erasure.index <= data_blocks + parity_blocks + && self.erasure.distribution.len() == (data_blocks + parity_blocks)) + } pub fn is_remote(&self) -> bool { // TODO: when lifecycle false @@ -113,68 +172,6 @@ impl FileInfo { } } -impl Default for FileInfo { - fn default() -> Self { - Self { - version_id: Uuid::nil(), - erasure: Default::default(), - deleted: Default::default(), - data_dir: Uuid::nil(), - mod_time: None, - size: Default::default(), - data: Default::default(), - fresh: Default::default(), - name: Default::default(), - volume: Default::default(), - parts: Default::default(), - is_latest: Default::default(), - } - } -} - -impl FileInfo { - pub fn new(object: &str, data_blocks: usize, parity_blocks: usize) -> Self { - let indexs = { - let cardinality = data_blocks + parity_blocks; - let mut nums = vec![0; cardinality]; - let key_crc = crc32fast::hash(object.as_bytes()); - - let start = key_crc as usize % cardinality; - for i in 1..=cardinality { - nums[i - 1] = 1 + ((start + i) % cardinality); - } - - nums - }; - Self { - erasure: ErasureInfo { - algorithm: String::from(ERASURE_ALGORITHM), - data_blocks, - parity_blocks, - block_size: BLOCK_SIZE_V2, - distribution: indexs, - ..Default::default() - }, - ..Default::default() - } - } - - pub fn is_valid(&self) -> bool { - if self.deleted { - return true; - } - - let data_blocks = self.erasure.data_blocks; - let parity_blocks = self.erasure.parity_blocks; - - (data_blocks >= parity_blocks) - && (data_blocks > 0) - && (self.erasure.index > 0 - && self.erasure.index <= data_blocks + parity_blocks - && self.erasure.distribution.len() == (data_blocks + parity_blocks)) - } -} - #[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Default)] pub struct ObjectPartInfo { // pub etag: Option, @@ -474,6 +471,7 @@ pub struct ListObjectsV2Info { #[derive(Debug, Default, Clone)] pub struct ObjectToDelete { pub object_name: String, + pub version_id: Option, } #[derive(Debug, Default, Clone)] pub struct DeletedObject { From 939d37822d7aef385ceafd508118949f94fbd8d7 Mon Sep 17 00:00:00 2001 From: loverustfs Date: Mon, 26 Aug 2024 14:44:50 +0800 Subject: [PATCH 05/10] fix license --- Cargo.toml | 2 +- rustfs-inner.zip | Bin 0 -> 116269 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 rustfs-inner.zip diff --git a/Cargo.toml b/Cargo.toml index 9420e9b3..92b3b1c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ members = ["rustfs", "ecstore"] [workspace.package] edition = "2021" -license = "MIT OR Apache-2.0" +license = "Apache-2.0" repository = "https://github.com/rustfs/rustfs" rust-version = "1.75" diff --git a/rustfs-inner.zip b/rustfs-inner.zip new file mode 100644 index 0000000000000000000000000000000000000000..f5aad0ed9712e4fb3394ae9d99d56e92e6513d1f GIT binary patch literal 116269 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°8`HY327?j@_*IoCt7cK%R>w~- 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 TZUEpC^j|y&002rtgZ}k@p6$^% literal 0 HcmV?d00001 From cfd6e2b32fbdefe473852a60911b6ab854f9e547 Mon Sep 17 00:00:00 2001 From: weisd Date: Tue, 27 Aug 2024 14:12:15 +0800 Subject: [PATCH 06/10] add: delete_versions --- Cargo.lock | 1 + ecstore/src/disk/local.rs | 4 ++++ rustfs/Cargo.toml | 2 +- rustfs/src/storage/ecfs.rs | 29 ++++++++++++++++++++++++++++- 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dd42ff16..8773cca8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1168,6 +1168,7 @@ dependencies = [ "tracing-error", "tracing-subscriber", "transform-stream", + "uuid", ] [[package]] diff --git a/ecstore/src/disk/local.rs b/ecstore/src/disk/local.rs index 407c779e..3daf2637 100644 --- a/ecstore/src/disk/local.rs +++ b/ecstore/src/disk/local.rs @@ -292,6 +292,7 @@ impl LocalDisk { // 没有版本了,删除xl.meta if fm.versions.is_empty() { self.delete_file(&volume_dir, &xlpath, true, false).await?; + return Ok(()); } // 更新xl.meta @@ -871,6 +872,9 @@ impl DiskAPI for LocalDisk { _opts: DeleteOptions, ) -> Result>> { let mut errs = Vec::with_capacity(versions.len()); + for _ in 0..versions.len() { + errs.push(None); + } for (i, ver) in versions.iter().enumerate() { if let Err(e) = self.delete_versions_internal(volume, ver.name.as_str(), &ver.versions).await { diff --git a/rustfs/Cargo.toml b/rustfs/Cargo.toml index 5e5414f0..f08b977e 100644 --- a/rustfs/Cargo.toml +++ b/rustfs/Cargo.toml @@ -23,7 +23,7 @@ http.workspace = true bytes.workspace = true futures.workspace = true futures-util.workspace = true - +uuid = { version = "1.8.0", features = ["v4", "fast-rng", "serde"] } ecstore = { path = "../ecstore" } s3s = "0.10.0" clap = { version = "4.5.7", features = ["derive"] } diff --git a/rustfs/src/storage/ecfs.rs b/rustfs/src/storage/ecfs.rs index 8e8f53db..822488aa 100644 --- a/rustfs/src/storage/ecfs.rs +++ b/rustfs/src/storage/ecfs.rs @@ -6,6 +6,7 @@ use ecstore::store_api::HTTPRangeSpec; use ecstore::store_api::MakeBucketOptions; use ecstore::store_api::MultipartUploadResult; use ecstore::store_api::ObjectOptions; +use ecstore::store_api::ObjectToDelete; use ecstore::store_api::PutObjReader; use ecstore::store_api::StorageAPI; use futures::pin_mut; @@ -20,7 +21,9 @@ use s3s::S3; use s3s::{S3Request, S3Response}; use std::fmt::Debug; use std::str::FromStr; +use tracing::info; use transform_stream::AsyncTryStream; +use uuid::Uuid; use ecstore::error::Result; use ecstore::store::ECStore; @@ -99,7 +102,31 @@ impl S3 for FS { #[tracing::instrument(level = "debug", skip(self, req))] async fn delete_objects(&self, req: S3Request) -> S3Result> { - let _input = req.input; + info!("delete_objects args {:?}", req.input); + + let DeleteObjectsInput { bucket, delete, .. } = req.input; + + let objects: Vec = delete + .objects + .iter() + .map(|v| { + let version_id = v + .version_id + .as_ref() + .map(|v| match Uuid::parse_str(v) { + Ok(id) => Some(id), + Err(_) => None, + }) + .unwrap_or_default(); + ObjectToDelete { + object_name: v.key.clone(), + version_id: version_id, + } + }) + .collect(); + + let (dobjs, errs) = try_!(self.store.delete_objects(&bucket, objects, ObjectOptions::default()).await); + info!("delete_objects res {:?} {:?}", &dobjs, errs); let output = DeleteObjectsOutput { ..Default::default() }; Ok(S3Response::new(output)) From 9370cdc88b5946a34ed19c28c34f46a1f4ae7ee0 Mon Sep 17 00:00:00 2001 From: weisd Date: Tue, 27 Aug 2024 15:10:58 +0800 Subject: [PATCH 07/10] add: delete_versions Option --- ecstore/src/disk/local.rs | 9 ++++--- ecstore/src/store.rs | 2 +- ecstore/src/store_api.rs | 48 +++++++++++++++++++------------------- rustfs/src/storage/ecfs.rs | 28 +++++++++++++++++++--- 4 files changed, 54 insertions(+), 33 deletions(-) diff --git a/ecstore/src/disk/local.rs b/ecstore/src/disk/local.rs index 3daf2637..3e8524aa 100644 --- a/ecstore/src/disk/local.rs +++ b/ecstore/src/disk/local.rs @@ -650,7 +650,7 @@ impl DiskAPI for LocalDisk { let (src_data_path, dst_data_path) = { let mut data_dir = String::new(); if !fi.is_remote() { - data_dir = utils::path::retain_slash(fi.data_dir.to_string().as_str()); + data_dir = utils::path::retain_slash(fi.data_dir.unwrap_or(Uuid::nil()).to_string().as_str()); } if !data_dir.is_empty() { @@ -689,10 +689,9 @@ impl DiskAPI for LocalDisk { let old_data_dir = meta .find_version(fi.version_id) .map(|(_, version)| { - version.get_data_dir().filter(|data_dir| { - warn!("get data dir {}", &data_dir); - meta.shard_data_dir_count(&fi.version_id, data_dir) == 0 - }) + version + .get_data_dir() + .filter(|data_dir| meta.shard_data_dir_count(&fi.version_id, &Some(data_dir.clone())) == 0) }) .unwrap_or_default(); diff --git a/ecstore/src/store.rs b/ecstore/src/store.rs index 315b6986..8fdcc2fb 100644 --- a/ecstore/src/store.rs +++ b/ecstore/src/store.rs @@ -418,7 +418,7 @@ impl StorageAPI for ECStore { if pinfo.object_info.delete_marker && opts.version_id.is_empty() { del_objects[i] = DeletedObject { delete_marker: pinfo.object_info.delete_marker, - delete_marker_version_id: pinfo.object_info.version_id.to_string(), + delete_marker_version_id: pinfo.object_info.version_id.map(|v| v.to_string()), object_name: utils::path::decode_dir_object(&pinfo.object_info.name), delete_marker_mtime: pinfo.object_info.mod_time, ..Default::default() diff --git a/ecstore/src/store_api.rs b/ecstore/src/store_api.rs index 328d3f8f..a330f3e3 100644 --- a/ecstore/src/store_api.rs +++ b/ecstore/src/store_api.rs @@ -10,15 +10,15 @@ pub const ERASURE_ALGORITHM: &str = "rs-vandermonde"; pub const BLOCK_SIZE_V2: usize = 1048576; // 1M // #[derive(Debug, Clone)] -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] +#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Default)] pub struct FileInfo { pub name: String, pub volume: String, - pub version_id: Uuid, + pub version_id: Option, pub erasure: ErasureInfo, pub deleted: bool, // DataDir of the file - pub data_dir: Uuid, + pub data_dir: Option, pub mod_time: Option, pub size: usize, pub data: Option>, @@ -27,24 +27,24 @@ pub struct FileInfo { pub is_latest: bool, } -impl Default for FileInfo { - fn default() -> Self { - Self { - version_id: Uuid::nil(), - erasure: Default::default(), - deleted: Default::default(), - data_dir: Uuid::nil(), - mod_time: None, - size: Default::default(), - data: Default::default(), - fresh: Default::default(), - name: Default::default(), - volume: Default::default(), - parts: Default::default(), - is_latest: Default::default(), - } - } -} +// impl Default for FileInfo { +// fn default() -> Self { +// Self { +// version_id: Default::default(), +// erasure: Default::default(), +// deleted: Default::default(), +// data_dir: Default::default(), +// mod_time: None, +// size: Default::default(), +// data: Default::default(), +// fresh: Default::default(), +// name: Default::default(), +// volume: Default::default(), +// parts: Default::default(), +// is_latest: Default::default(), +// } +// } +// } impl FileInfo { pub fn new(object: &str, data_blocks: usize, parity_blocks: usize) -> Self { @@ -418,7 +418,7 @@ pub struct ObjectInfo { pub is_dir: bool, pub parity_blocks: usize, pub data_blocks: usize, - pub version_id: Uuid, + pub version_id: Option, pub delete_marker: bool, pub parts: Vec, pub is_latest: bool, @@ -476,9 +476,9 @@ pub struct ObjectToDelete { #[derive(Debug, Default, Clone)] pub struct DeletedObject { pub delete_marker: bool, - pub delete_marker_version_id: String, + pub delete_marker_version_id: Option, pub object_name: String, - pub version_id: String, + pub version_id: Option, // MTime of DeleteMarker on source that needs to be propagated to replica pub delete_marker_mtime: Option, // to support delete marker replication diff --git a/rustfs/src/storage/ecfs.rs b/rustfs/src/storage/ecfs.rs index 822488aa..ded92dd7 100644 --- a/rustfs/src/storage/ecfs.rs +++ b/rustfs/src/storage/ecfs.rs @@ -102,7 +102,7 @@ impl S3 for FS { #[tracing::instrument(level = "debug", skip(self, req))] async fn delete_objects(&self, req: S3Request) -> S3Result> { - info!("delete_objects args {:?}", req.input); + // info!("delete_objects args {:?}", req.input); let DeleteObjectsInput { bucket, delete, .. } = req.input; @@ -126,9 +126,31 @@ impl S3 for FS { .collect(); let (dobjs, errs) = try_!(self.store.delete_objects(&bucket, objects, ObjectOptions::default()).await); - info!("delete_objects res {:?} {:?}", &dobjs, errs); + // info!("delete_objects res {:?} {:?}", &dobjs, errs); - let output = DeleteObjectsOutput { ..Default::default() }; + let deleted = dobjs + .iter() + .map(|v| DeletedObject { + delete_marker: { + if v.delete_marker { + Some(true) + } else { + None + } + }, + delete_marker_version_id: v.delete_marker_version_id.clone(), + key: Some(v.object_name.clone()), + version_id: v.version_id.clone(), + }) + .collect(); + + // TODO: let errors; + + let output = DeleteObjectsOutput { + deleted: Some(deleted), + // errors, + ..Default::default() + }; Ok(S3Response::new(output)) } From d93bc39d8d7453d03aa413c0f65207c366e288e5 Mon Sep 17 00:00:00 2001 From: weisd Date: Tue, 27 Aug 2024 15:13:59 +0800 Subject: [PATCH 08/10] update:todo.md --- TODO.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index b15b6097..f020ad93 100644 --- a/TODO.md +++ b/TODO.md @@ -29,7 +29,7 @@ - [x] 提交完成 CompleteMultipartUpload - [x] 取消上传 AbortMultipartUpload - [x] 下载 GetObject - - [ ] 删除 DeleteObjects + - [x] 删除 DeleteObjects - [ ] 版本控制 - [ ] 对象锁 - [ ] 复制 CopyObject From 84b7b86ed53e83d2966f7574d9561e3ec903b64d Mon Sep 17 00:00:00 2001 From: weisd Date: Tue, 27 Aug 2024 15:42:09 +0800 Subject: [PATCH 09/10] update:delete_object --- rustfs/src/storage/ecfs.rs | 55 +++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/rustfs/src/storage/ecfs.rs b/rustfs/src/storage/ecfs.rs index ded92dd7..0117cd83 100644 --- a/rustfs/src/storage/ecfs.rs +++ b/rustfs/src/storage/ecfs.rs @@ -21,7 +21,6 @@ use s3s::S3; use s3s::{S3Request, S3Response}; use std::fmt::Debug; use std::str::FromStr; -use tracing::info; use transform_stream::AsyncTryStream; use uuid::Uuid; @@ -94,9 +93,57 @@ impl S3 for FS { #[tracing::instrument(level = "debug", skip(self, req))] async fn delete_object(&self, req: S3Request) -> S3Result> { - let _input = req.input; + let DeleteObjectInput { + bucket, key, version_id, .. + } = req.input; - let output = DeleteObjectOutput::default(); + let version_id = version_id + .as_ref() + .map(|v| match Uuid::parse_str(v) { + Ok(id) => Some(id), + Err(_) => None, + }) + .unwrap_or_default(); + let dobj = ObjectToDelete { + object_name: key, + version_id, + }; + + let objects: Vec = vec![dobj]; + + let (dobjs, _errs) = try_!(self.store.delete_objects(&bucket, objects, ObjectOptions::default()).await); + + // TODO: let errors; + + let (delete_marker, version_id) = { + if let Some((a, b)) = dobjs + .iter() + .map(|v| { + let delete_marker = { + if v.delete_marker { + Some(true) + } else { + None + } + }; + + let version_id = v.version_id.clone(); + + (delete_marker, version_id) + }) + .next() + { + (a, b) + } else { + (None, None) + } + }; + + let output = DeleteObjectOutput { + delete_marker, + version_id, + ..Default::default() + }; Ok(S3Response::new(output)) } @@ -125,7 +172,7 @@ impl S3 for FS { }) .collect(); - let (dobjs, errs) = try_!(self.store.delete_objects(&bucket, objects, ObjectOptions::default()).await); + let (dobjs, _errs) = try_!(self.store.delete_objects(&bucket, objects, ObjectOptions::default()).await); // info!("delete_objects res {:?} {:?}", &dobjs, errs); let deleted = dobjs From 72b754881e34a1851f2b2b7b0ed44be9148138bc Mon Sep 17 00:00:00 2001 From: loverustfs Date: Sun, 8 Sep 2024 21:52:51 +0800 Subject: [PATCH 10/10] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rustfs/src/main.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/rustfs/src/main.rs b/rustfs/src/main.rs index d43b4ab5..54aeccac 100644 --- a/rustfs/src/main.rs +++ b/rustfs/src/main.rs @@ -31,10 +31,13 @@ fn setup_tracing() { } fn main() -> Result<()> { + //解析获得到的参数 let opt = config::Opt::parse(); + //设置trace setup_tracing(); + //运行参数 run(opt) } @@ -42,7 +45,9 @@ fn main() -> Result<()> { async fn run(opt: config::Opt) -> Result<()> { debug!("opt: {:?}", &opt); + //监听地址,端口从参数中获取 let listener = TcpListener::bind(opt.address.clone()).await?; + //获取监听地址 let local_addr: SocketAddr = listener.local_addr()?; // let mut domain_name = { @@ -62,9 +67,11 @@ async fn run(opt: config::Opt) -> Result<()> { // }; // Setup S3 service + // 本项目使用s3s库来实现s3服务 let service = { let mut b = S3ServiceBuilder::new(storage::ecfs::FS::new(opt.address.clone(), opt.volumes.clone()).await?); - + //设置AK和SK + //其中部份内容从config配置文件中读取 let mut access_key = String::from_str(config::DEFAULT_ACCESS_KEY).unwrap(); let mut secret_key = String::from_str(config::DEFAULT_SECRET_KEY).unwrap(); @@ -73,7 +80,7 @@ async fn run(opt: config::Opt) -> Result<()> { access_key = ak; secret_key = sk; } - + //显示info信息 info!("authentication is enabled {}, {}", &access_key, &secret_key); b.set_auth(SimpleAuth::from_single(access_key, secret_key));