From 724e881236388655807d5267b6cb138a3037540e Mon Sep 17 00:00:00 2001 From: shenjack <3695888@qq.com> Date: Sat, 27 Jan 2024 00:33:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E4=B8=80=E6=B3=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 1 + src/cluster.rs | 44 +++++++++++++++++++++++++++++++------------- src/utils.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2229011..4f54470 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ tokio = { version = "1.35.1", features = ["full"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" toml = "0.8.8" +apache-avro = "0.16.0" md-5 = "0.10.6" sha1 = "0.10.6" diff --git a/src/cluster.rs b/src/cluster.rs index a126634..3b1372f 100644 --- a/src/cluster.rs +++ b/src/cluster.rs @@ -1,7 +1,22 @@ +use crate::utils::avro_data_to_file_list; use crate::config::{ClusterByoc, Config}; use crate::PROTOCOL_VERSION; use reqwest::{Client, StatusCode}; +use serde::Deserialize; +use zstd::stream::decode_all; + +#[derive(Deserialize, Debug, Clone)] +pub struct SyncFile { + pub path: String, + pub hash: String, + pub size: i64, +} + +#[derive(Deserialize, Debug, Clone)] +pub struct SyncFileList { + pub files: Vec, +} pub struct Cluster { pub config: Config, @@ -40,7 +55,7 @@ impl Cluster { /// files: FileListSchema.fromBuffer(Buffer.from(decompressed)), /// } /// } - pub async fn get_file_list(&self) { + pub async fn get_file_list(&self) -> Vec { // server: https://openbmclapi.bangbang93.com // path: /openbmclapi/files let url = format!( @@ -57,22 +72,26 @@ impl Cluster { .basic_auth(username, Some(password)) .timeout(std::time::Duration::from_secs(60)) .send() - .await - .unwrap(); + .await; + if res.is_err() { + panic!("get file list error: {:?}", res.err()); + } + let res = res.unwrap(); match res.status() { StatusCode::OK => { let body = res.bytes().await.unwrap(); - println!("get file list body! len: {}", body.len()); let cur = std::io::Cursor::new(body); - let data = zstd::decode_all(cur); - match data { - Ok(data) => { - println!("file list decompressed! len: {}", data.len()); - } - Err(e) => { - panic!("file list decompress faild e:{:?}", e) - } + let raw_data = decode_all(cur); + if raw_data.is_err() { + panic!("decompress file list error: {:?}", raw_data.err()); } + let raw_data = raw_data.unwrap(); + let file_list = avro_data_to_file_list(raw_data); + if file_list.is_err() { + panic!("parse file list error: {:?}", file_list.err()); + } + let file_list = file_list.unwrap(); + file_list } _ => { panic!("error status: {:?}", res.status()); @@ -85,7 +104,6 @@ impl Cluster { mod tests { use super::*; - use serde::Deserialize; #[derive(Deserialize)] struct TestConfig { pub cluster_port: u32, diff --git a/src/utils.rs b/src/utils.rs index b8bcedb..9e25df0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,12 @@ +use crate::cluster::{SyncFile, SyncFileList}; + +use std::io::Cursor; + use md5::{Digest, Md5}; use sha1::Sha1; use std::path::PathBuf; +use apache_avro::{from_value, from_avro_datum}; + /// import {join} from 'path' /// @@ -46,6 +52,40 @@ pub fn validate_file(buffer: &[u8], check_sum: &str) -> bool { } } + +/// BYD avro 格式的文件列表 +pub const SYNC_FILE_LIST_SCHEMA: &str = r#" +{ + "type": "array", + "items": { + "type": "record", + "name": "fileinfo", + "fields": [ + {"name": "path", "type": "string"}, + {"name": "hash", "type": "string"}, + {"name": "size", "type": "long"} + ] + } +} +"#; + +/// 用来将 BYD avro 格式的数据转换成文件列表 +pub fn avro_data_to_file_list(data: Vec) -> apache_avro::AvroResult> { + let chema = apache_avro::Schema::parse_str(SYNC_FILE_LIST_SCHEMA).unwrap(); + let mut cur = Cursor::new(data); + let reader = from_avro_datum(&chema, &mut cur, Some(&chema)); + if reader.is_err() { + return Err(reader.err().unwrap()); + } + let files = from_value::(&reader.unwrap()); + if files.is_err() { + // return Err(files.err().unwrap()); + panic!("parse file list error: {:?}", files.err()); + } + let files = files.unwrap(); + Ok(files.files) +} + #[test] fn test_hash_to_filename() { assert_eq!(