mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-18 10:43:15 +00:00
7cb91a0190
Replace every bare `#[allow(dead_code)]` in ecstore with either a deletion or a per-item allow carrying a `reason`. Blanket allows at module, struct, and impl level silence the lint for future members too, so each is narrowed to the members that are actually dead. Delete the dead cluster in `config/heal.rs` (`Config`, its three methods, `RUSTFS_BITROT_CYCLE_IN_MONTHS`, `parse_bitrot_config`) rather than annotate it: it has no callers and is unreachable outside the crate, and `parse_bitrot_config` would panic on its disabled path via `Duration::from_secs_f64(-1.0)`. `DEFAULT_KVS` stays, since the config registry uses it. Correct two `reason` strings on `Checksum::new` and `PutObjReader::md5_current_hex_string`, which are methods but carried a field-only rationale. Refs backlog#1823 Co-authored-by: houseme <housemecn@gmail.com>
289 lines
9.0 KiB
Rust
289 lines
9.0 KiB
Rust
// Copyright 2024 RustFS Team
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
#![allow(clippy::map_entry)]
|
|
#![allow(unused_imports)]
|
|
#![allow(unused_variables)]
|
|
#![allow(unused_mut)]
|
|
#![allow(unused_assignments)]
|
|
#![allow(unused_must_use)]
|
|
#![allow(clippy::all)]
|
|
|
|
use futures_util::ready;
|
|
use http::HeaderMap;
|
|
use std::io::{Cursor, Error as IoError, ErrorKind as IoErrorKind, Read};
|
|
use std::pin::Pin;
|
|
use std::task::{Context, Poll};
|
|
use tokio::io::BufReader;
|
|
use tokio_util::io::StreamReader;
|
|
|
|
use crate::client::{
|
|
api_error_response::err_invalid_argument,
|
|
api_get_options::GetObjectOptions,
|
|
transition_api::{ObjectInfo, ReadCloser, ReaderImpl, RequestMetadata, TransitionClient, to_object_info_for_provider},
|
|
};
|
|
use futures_util::StreamExt;
|
|
use http_body_util::BodyExt;
|
|
use hyper::body::Body;
|
|
use hyper::body::Bytes;
|
|
use rustfs_utils::hash::EMPTY_STRING_SHA256_HASH;
|
|
use tokio_util::io::ReaderStream;
|
|
|
|
impl TransitionClient {
|
|
pub fn get_object(&self, bucket_name: &str, object_name: &str, opts: &GetObjectOptions) -> Result<Object, std::io::Error> {
|
|
let _ = opts;
|
|
Err(std::io::Error::new(
|
|
IoErrorKind::Unsupported,
|
|
format!("get_object is not implemented for {bucket_name}/{object_name}"),
|
|
))
|
|
}
|
|
|
|
pub async fn get_object_inner(
|
|
&self,
|
|
bucket_name: &str,
|
|
object_name: &str,
|
|
opts: &GetObjectOptions,
|
|
) -> Result<(ObjectInfo, HeaderMap, ReadCloser), std::io::Error> {
|
|
let resp = self
|
|
.execute_method(
|
|
http::Method::GET,
|
|
&mut RequestMetadata {
|
|
bucket_name: bucket_name.to_string(),
|
|
object_name: object_name.to_string(),
|
|
query_values: opts.to_query_values(),
|
|
custom_header: opts.header(),
|
|
content_sha256_hex: EMPTY_STRING_SHA256_HASH.to_string(),
|
|
content_body: ReaderImpl::Body(Bytes::new()),
|
|
content_length: 0,
|
|
content_md5_base64: "".to_string(),
|
|
stream_sha256: false,
|
|
trailer: HeaderMap::new(),
|
|
pre_sign_url: Default::default(),
|
|
add_crc: Default::default(),
|
|
extra_pre_sign_header: Default::default(),
|
|
bucket_location: Default::default(),
|
|
expires: Default::default(),
|
|
},
|
|
)
|
|
.await?;
|
|
|
|
let object_stat =
|
|
to_object_info_for_provider(bucket_name, object_name, resp.headers(), self.provider_version_capabilities())?;
|
|
|
|
let h = resp.headers().clone();
|
|
|
|
let mut body_vec = Vec::new();
|
|
let mut body = resp.into_body();
|
|
while let Some(frame) = body.frame().await {
|
|
let frame = frame.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
|
|
if let Some(data) = frame.data_ref() {
|
|
body_vec.extend_from_slice(data);
|
|
}
|
|
}
|
|
Ok((object_stat, h, BufReader::new(Cursor::new(body_vec))))
|
|
}
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct GetRequest {
|
|
pub buffer: Vec<u8>,
|
|
pub offset: i64,
|
|
pub did_offset_change: bool,
|
|
pub been_read: bool,
|
|
pub is_read_at: bool,
|
|
pub is_read_op: bool,
|
|
pub is_first_req: bool,
|
|
pub setting_object_info: bool,
|
|
}
|
|
|
|
pub struct GetResponse {
|
|
pub size: i64,
|
|
//pub error: error,
|
|
#[allow(dead_code, reason = "written but never read back (backlog#1823)")]
|
|
pub did_read: bool,
|
|
#[allow(dead_code, reason = "written but never read back (backlog#1823)")]
|
|
pub object_info: ObjectInfo,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct Object {
|
|
//pub reqch: chan<- getRequest,
|
|
//pub resch: <-chan getResponse,
|
|
//pub cancel: context.CancelFunc,
|
|
pub curr_offset: i64,
|
|
pub object_info: ObjectInfo,
|
|
pub seek_data: bool,
|
|
pub is_closed: bool,
|
|
pub is_started: bool,
|
|
//pub prev_err: error,
|
|
pub been_read: bool,
|
|
pub object_info_set: bool,
|
|
}
|
|
|
|
impl Object {
|
|
pub fn new() -> Object {
|
|
Self { ..Default::default() }
|
|
}
|
|
|
|
#[allow(
|
|
dead_code,
|
|
reason = "MinIO-parity reader surface with no caller in this port (backlog#1823)"
|
|
)]
|
|
fn do_get_request(&self, request: &GetRequest) -> Result<GetResponse, std::io::Error> {
|
|
let _ = request.did_offset_change;
|
|
let _ = request.offset;
|
|
let _ = request.is_first_req;
|
|
let _ = request.is_read_at;
|
|
let _ = request.setting_object_info;
|
|
let _ = request.is_read_op;
|
|
let _ = request.been_read;
|
|
let _ = request.buffer.len();
|
|
Err(std::io::Error::new(
|
|
IoErrorKind::Unsupported,
|
|
"read-path for Object in api_get_object is not implemented",
|
|
))
|
|
}
|
|
|
|
#[allow(
|
|
dead_code,
|
|
reason = "MinIO-parity Object reader method with no caller in this port (backlog#1823)"
|
|
)]
|
|
fn set_offset(&mut self, bytes_read: i64) -> Result<(), std::io::Error> {
|
|
self.curr_offset += bytes_read;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[allow(
|
|
dead_code,
|
|
reason = "MinIO-parity Object reader method with no caller in this port (backlog#1823)"
|
|
)]
|
|
fn read(&mut self, b: &[u8]) -> Result<i64, std::io::Error> {
|
|
let mut read_req = GetRequest {
|
|
is_read_op: true,
|
|
been_read: self.been_read,
|
|
buffer: b.to_vec(),
|
|
..Default::default()
|
|
};
|
|
|
|
if !self.is_started {
|
|
read_req.is_first_req = true;
|
|
}
|
|
|
|
read_req.did_offset_change = self.seek_data;
|
|
read_req.offset = self.curr_offset;
|
|
|
|
let response = self.do_get_request(&read_req)?;
|
|
|
|
let bytes_read = response.size;
|
|
|
|
let oerr = self.set_offset(bytes_read);
|
|
|
|
Ok(response.size)
|
|
}
|
|
|
|
#[allow(
|
|
dead_code,
|
|
reason = "MinIO-parity Object reader method with no caller in this port (backlog#1823)"
|
|
)]
|
|
fn stat(&self) -> Result<ObjectInfo, std::io::Error> {
|
|
if !self.is_started || !self.object_info_set {
|
|
let _ = self.do_get_request(&GetRequest {
|
|
is_first_req: !self.is_started,
|
|
setting_object_info: !self.object_info_set,
|
|
..Default::default()
|
|
})?;
|
|
}
|
|
|
|
Ok(self.object_info.clone())
|
|
}
|
|
|
|
#[allow(
|
|
dead_code,
|
|
reason = "MinIO-parity Object reader method with no caller in this port (backlog#1823)"
|
|
)]
|
|
fn read_at(&mut self, b: &[u8], offset: i64) -> Result<i64, std::io::Error> {
|
|
self.curr_offset = offset;
|
|
|
|
let mut read_at_req = GetRequest {
|
|
is_read_op: true,
|
|
is_read_at: true,
|
|
did_offset_change: true,
|
|
been_read: self.been_read,
|
|
offset,
|
|
buffer: b.to_vec(),
|
|
..Default::default()
|
|
};
|
|
|
|
if !self.is_started {
|
|
read_at_req.is_first_req = true;
|
|
}
|
|
|
|
let response = self.do_get_request(&read_at_req)?;
|
|
let bytes_read = response.size;
|
|
if !self.object_info_set {
|
|
self.curr_offset += bytes_read;
|
|
} else {
|
|
let oerr = self.set_offset(bytes_read);
|
|
}
|
|
Ok(response.size)
|
|
}
|
|
|
|
#[allow(
|
|
dead_code,
|
|
reason = "MinIO-parity Object reader method with no caller in this port (backlog#1823)"
|
|
)]
|
|
fn seek(&mut self, offset: i64, whence: i64) -> Result<i64, std::io::Error> {
|
|
if !self.is_started || !self.object_info_set {
|
|
let seek_req = GetRequest {
|
|
is_read_op: false,
|
|
offset,
|
|
is_first_req: true,
|
|
..Default::default()
|
|
};
|
|
let _ = self.do_get_request(&seek_req);
|
|
}
|
|
|
|
let mut new_offset = self.curr_offset;
|
|
|
|
match whence {
|
|
0 => {
|
|
new_offset = offset;
|
|
}
|
|
1 => {
|
|
new_offset += offset;
|
|
}
|
|
2 => {
|
|
new_offset = self.object_info.size as i64 + offset as i64;
|
|
}
|
|
_ => {
|
|
return Err(std::io::Error::other(err_invalid_argument(&format!("Invalid whence {}", whence))));
|
|
}
|
|
}
|
|
|
|
self.seek_data = (new_offset != self.curr_offset) || self.seek_data;
|
|
self.curr_offset = new_offset;
|
|
|
|
Ok(self.curr_offset)
|
|
}
|
|
|
|
#[allow(
|
|
dead_code,
|
|
reason = "MinIO-parity Object reader method with no caller in this port (backlog#1823)"
|
|
)]
|
|
fn close(&mut self) -> Result<(), std::io::Error> {
|
|
self.is_closed = true;
|
|
Ok(())
|
|
}
|
|
}
|