mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-07 22:03:14 +00:00
feat(grpc): walk_dir http
fix(ecstore): rebalance loop
This commit is contained in:
@@ -124,7 +124,7 @@ pub enum DiskError {
|
||||
#[error("erasure read quorum")]
|
||||
ErasureReadQuorum,
|
||||
|
||||
#[error("io error")]
|
||||
#[error("io error {0}")]
|
||||
Io(io::Error),
|
||||
}
|
||||
|
||||
|
||||
@@ -773,7 +773,7 @@ impl LocalDisk {
|
||||
Ok(res) => res,
|
||||
Err(e) => {
|
||||
if e != DiskError::VolumeNotFound && e != Error::FileNotFound {
|
||||
info!("scan list_dir {}, err {:?}", ¤t, &e);
|
||||
warn!("scan list_dir {}, err {:?}", ¤t, &e);
|
||||
}
|
||||
|
||||
if opts.report_notfound && e == Error::FileNotFound && current == &opts.base_dir {
|
||||
@@ -785,6 +785,7 @@ impl LocalDisk {
|
||||
};
|
||||
|
||||
if entries.is_empty() {
|
||||
warn!("scan list_dir {}, entries is empty", ¤t);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -800,6 +801,7 @@ impl LocalDisk {
|
||||
let entry = item.clone();
|
||||
// check limit
|
||||
if opts.limit > 0 && *objs_returned >= opts.limit {
|
||||
warn!("scan list_dir {}, limit reached", ¤t);
|
||||
return Ok(());
|
||||
}
|
||||
// check prefix
|
||||
@@ -843,13 +845,14 @@ impl LocalDisk {
|
||||
let name = decode_dir_object(format!("{}/{}", ¤t, &name).as_str());
|
||||
|
||||
out.write_obj(&MetaCacheEntry {
|
||||
name,
|
||||
name: name.clone(),
|
||||
metadata,
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
*objs_returned += 1;
|
||||
|
||||
// warn!("scan list_dir {}, write_obj done, name: {:?}", ¤t, &name);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@@ -870,6 +873,7 @@ impl LocalDisk {
|
||||
|
||||
for entry in entries.iter() {
|
||||
if opts.limit > 0 && *objs_returned >= opts.limit {
|
||||
// warn!("scan list_dir {}, limit reached 2", ¤t);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -945,6 +949,7 @@ impl LocalDisk {
|
||||
|
||||
while let Some(dir) = dir_stack.pop() {
|
||||
if opts.limit > 0 && *objs_returned >= opts.limit {
|
||||
// warn!("scan list_dir {}, limit reached 3", ¤t);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -965,6 +970,7 @@ impl LocalDisk {
|
||||
}
|
||||
}
|
||||
|
||||
// warn!("scan list_dir {}, done", ¤t);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1568,6 +1574,11 @@ impl DiskAPI for LocalDisk {
|
||||
let mut current = opts.base_dir.clone();
|
||||
self.scan_dir(&mut current, &opts, &mut out, &mut objs_returned).await?;
|
||||
|
||||
warn!(
|
||||
"walk_dir: done, volume_dir: {:?}, base_dir: {}",
|
||||
volume_dir.to_string_lossy(),
|
||||
opts.base_dir
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
+76
-46
@@ -2,20 +2,20 @@ use std::path::PathBuf;
|
||||
|
||||
use bytes::Bytes;
|
||||
use futures::lock::Mutex;
|
||||
use http::{HeaderMap, Method};
|
||||
use http::{HeaderMap, HeaderValue, Method, header::CONTENT_TYPE};
|
||||
use protos::{
|
||||
node_service_time_out_client,
|
||||
proto_gen::node_service::{
|
||||
CheckPartsRequest, DeletePathsRequest, DeleteRequest, DeleteVersionRequest, DeleteVersionsRequest, DeleteVolumeRequest,
|
||||
DiskInfoRequest, ListDirRequest, ListVolumesRequest, MakeVolumeRequest, MakeVolumesRequest, NsScannerRequest,
|
||||
ReadAllRequest, ReadMultipleRequest, ReadVersionRequest, ReadXlRequest, RenameDataRequest, RenameFileRequest,
|
||||
StatVolumeRequest, UpdateMetadataRequest, VerifyFileRequest, WalkDirRequest, WriteAllRequest, WriteMetadataRequest,
|
||||
StatVolumeRequest, UpdateMetadataRequest, VerifyFileRequest, WriteAllRequest, WriteMetadataRequest,
|
||||
},
|
||||
};
|
||||
use rmp_serde::Serializer;
|
||||
use rustfs_filemeta::{FileInfo, MetaCacheEntry, MetacacheWriter, RawFileInfo};
|
||||
|
||||
use rustfs_filemeta::{FileInfo, RawFileInfo};
|
||||
use rustfs_rio::{HttpReader, HttpWriter};
|
||||
use serde::Serialize;
|
||||
|
||||
use tokio::{
|
||||
io::AsyncWrite,
|
||||
sync::mpsc::{self, Sender},
|
||||
@@ -256,47 +256,55 @@ impl DiskAPI for RemoteDisk {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// FIXME: TODO: use writer
|
||||
#[tracing::instrument(skip(self, wr))]
|
||||
async fn walk_dir<W: AsyncWrite + Unpin + Send>(&self, opts: WalkDirOptions, wr: &mut W) -> Result<()> {
|
||||
let now = std::time::SystemTime::now();
|
||||
info!("walk_dir {}/{}/{:?}", self.endpoint.to_string(), opts.bucket, opts.filter_prefix);
|
||||
let mut wr = wr;
|
||||
let mut out = MetacacheWriter::new(&mut wr);
|
||||
let mut buf = Vec::new();
|
||||
opts.serialize(&mut Serializer::new(&mut buf))?;
|
||||
let mut client = node_service_time_out_client(&self.addr)
|
||||
.await
|
||||
.map_err(|err| Error::other(format!("can not get client, err: {}", err)))?;
|
||||
let request = Request::new(WalkDirRequest {
|
||||
disk: self.endpoint.to_string(),
|
||||
walk_dir_options: buf.into(),
|
||||
});
|
||||
let mut response = client.walk_dir(request).await?.into_inner();
|
||||
// // FIXME: TODO: use writer
|
||||
// #[tracing::instrument(skip(self, wr))]
|
||||
// async fn walk_dir<W: AsyncWrite + Unpin + Send>(&self, opts: WalkDirOptions, wr: &mut W) -> Result<()> {
|
||||
// let now = std::time::SystemTime::now();
|
||||
// info!("walk_dir {}/{}/{:?}", self.endpoint.to_string(), opts.bucket, opts.filter_prefix);
|
||||
// let mut wr = wr;
|
||||
// let mut out = MetacacheWriter::new(&mut wr);
|
||||
// let mut buf = Vec::new();
|
||||
// opts.serialize(&mut Serializer::new(&mut buf))?;
|
||||
// let mut client = node_service_time_out_client(&self.addr)
|
||||
// .await
|
||||
// .map_err(|err| Error::other(format!("can not get client, err: {}", err)))?;
|
||||
// let request = Request::new(WalkDirRequest {
|
||||
// disk: self.endpoint.to_string(),
|
||||
// walk_dir_options: buf.into(),
|
||||
// });
|
||||
// let mut response = client.walk_dir(request).await?.into_inner();
|
||||
|
||||
loop {
|
||||
match response.next().await {
|
||||
Some(Ok(resp)) => {
|
||||
if !resp.success {
|
||||
return Err(Error::other(resp.error_info.unwrap_or_default()));
|
||||
}
|
||||
let entry = serde_json::from_str::<MetaCacheEntry>(&resp.meta_cache_entry)
|
||||
.map_err(|_| Error::other(format!("Unexpected response: {:?}", response)))?;
|
||||
out.write_obj(&entry).await?;
|
||||
}
|
||||
None => break,
|
||||
_ => return Err(Error::other(format!("Unexpected response: {:?}", response))),
|
||||
}
|
||||
}
|
||||
// loop {
|
||||
// match response.next().await {
|
||||
// Some(Ok(resp)) => {
|
||||
// if !resp.success {
|
||||
// if let Some(err) = resp.error_info {
|
||||
// if err == "Unexpected EOF" {
|
||||
// return Err(Error::Io(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, err)));
|
||||
// } else {
|
||||
// return Err(Error::other(err));
|
||||
// }
|
||||
// }
|
||||
|
||||
info!(
|
||||
"walk_dir {}/{:?} done {:?}",
|
||||
opts.bucket,
|
||||
opts.filter_prefix,
|
||||
now.elapsed().unwrap_or_default()
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
// return Err(Error::other("unknown error"));
|
||||
// }
|
||||
// let entry = serde_json::from_str::<MetaCacheEntry>(&resp.meta_cache_entry)
|
||||
// .map_err(|_| Error::other(format!("Unexpected response: {:?}", response)))?;
|
||||
// out.write_obj(&entry).await?;
|
||||
// }
|
||||
// None => break,
|
||||
// _ => return Err(Error::other(format!("Unexpected response: {:?}", response))),
|
||||
// }
|
||||
// }
|
||||
|
||||
// info!(
|
||||
// "walk_dir {}/{:?} done {:?}",
|
||||
// opts.bucket,
|
||||
// opts.filter_prefix,
|
||||
// now.elapsed().unwrap_or_default()
|
||||
// );
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
async fn delete_version(
|
||||
@@ -559,6 +567,28 @@ impl DiskAPI for RemoteDisk {
|
||||
Ok(response.volumes)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self, wr))]
|
||||
async fn walk_dir<W: AsyncWrite + Unpin + Send>(&self, opts: WalkDirOptions, wr: &mut W) -> Result<()> {
|
||||
info!("walk_dir {}", self.endpoint.to_string());
|
||||
|
||||
let url = format!(
|
||||
"{}/rustfs/rpc/walk_dir?disk={}",
|
||||
self.endpoint.grid_host(),
|
||||
urlencoding::encode(self.endpoint.to_string().as_str()),
|
||||
);
|
||||
|
||||
let opts = serde_json::to_vec(&opts)?;
|
||||
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
|
||||
|
||||
let mut reader = HttpReader::new(url, Method::GET, headers, Some(opts)).await?;
|
||||
|
||||
tokio::io::copy(&mut reader, wr).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
async fn read_file(&self, volume: &str, path: &str) -> Result<FileReader> {
|
||||
info!("read_file {}/{}", volume, path);
|
||||
@@ -573,7 +603,7 @@ impl DiskAPI for RemoteDisk {
|
||||
0
|
||||
);
|
||||
|
||||
Ok(Box::new(HttpReader::new(url, Method::GET, HeaderMap::new()).await?))
|
||||
Ok(Box::new(HttpReader::new(url, Method::GET, HeaderMap::new(), None).await?))
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
@@ -589,7 +619,7 @@ impl DiskAPI for RemoteDisk {
|
||||
length
|
||||
);
|
||||
|
||||
Ok(Box::new(HttpReader::new(url, Method::GET, HeaderMap::new()).await?))
|
||||
Ok(Box::new(HttpReader::new(url, Method::GET, HeaderMap::new(), None).await?))
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
|
||||
Reference in New Issue
Block a user