156 lines
5.1 KiB
Rust
156 lines
5.1 KiB
Rust
extern crate a03;
|
|
extern crate serde;
|
|
extern crate serde_json;
|
|
#[macro_use]
|
|
extern crate serde_derive;
|
|
|
|
use a03::*;
|
|
use std::net::{TcpStream, Shutdown};
|
|
use std::io::{Write, Read};
|
|
use std::fs::File;
|
|
use std::fs;
|
|
|
|
fn main() {
|
|
let args = get_cli_args();
|
|
let mut stream = TcpStream::connect(&args.endpoint).unwrap();
|
|
let packet_type;
|
|
let json;
|
|
if args.is_copy_to_dfs {
|
|
packet_type = PacketType::RequestWrite;
|
|
let file = fs::read(&args.filename).unwrap();
|
|
let size = file.len();
|
|
println!("Requesting Write of {}", args.filepath);
|
|
json = Some(serde_json::to_string(
|
|
&AddFile { name: args.filepath.clone(), size: size as u32 }).unwrap())
|
|
} else {
|
|
packet_type = PacketType::RequestRead;
|
|
println!("Requesting Read of {}", args.filepath);
|
|
json = Some(serde_json::to_string::<String>(&args.filepath).unwrap())
|
|
}
|
|
serde_json::to_writer(&mut stream, &Packet { p_type: packet_type, json, data: None })
|
|
.unwrap();
|
|
stream.flush().unwrap();
|
|
stream.shutdown(Shutdown::Write).unwrap();
|
|
|
|
let mut nodes: Option<Vec<AvailableNodes>> = None;
|
|
match serde_json::from_reader(&mut stream) {
|
|
Ok(Packet { p_type: PacketType::Success, json, .. }) =>
|
|
nodes = Some(serde_json::from_str::<Vec<AvailableNodes>>(&json.unwrap())
|
|
.unwrap()),
|
|
Ok(Packet { p_type: PacketType::Error, json, .. }) => {
|
|
eprintln!("Meta Data Server Error: {}", &json.unwrap());
|
|
}
|
|
Ok(_) => {}
|
|
Err(e) => eprintln!("Error parsing json {}", e.to_string()),
|
|
};
|
|
let filename = &args.filepath;
|
|
let destination = &args.filename;
|
|
if args.is_copy_to_dfs {
|
|
let file = fs::read(&args.filename).unwrap();
|
|
nodes.map(|ns| send_file_to_data_nodes(&filename, &ns, &file));
|
|
} else {
|
|
nodes.map(|ns| get_file_from_data_nodes(&destination, &filename, &ns));
|
|
}
|
|
}
|
|
|
|
fn send_file_to_data_nodes(
|
|
filename: &String,
|
|
nodes: &Vec<AvailableNodes>,
|
|
file: &Vec<u8>)
|
|
{
|
|
let endpoint = format!("{}:{}", nodes[0].ip, nodes[0].port);
|
|
let mut stream = TcpStream::connect(endpoint).unwrap();
|
|
println!("Going to send a file! Bytes {}", file.len());
|
|
let chunk = Chunk {
|
|
index: nodes[0].chunk_index,
|
|
filename: filename.clone(),
|
|
};
|
|
let packet = serde_json::to_writer(
|
|
&mut stream,
|
|
&Packet {
|
|
p_type: PacketType::PutFile,
|
|
json: Some(serde_json::to_string(&chunk).unwrap()),
|
|
data: Some(file.clone()),
|
|
}).unwrap();
|
|
stream.flush().unwrap();
|
|
stream.shutdown(Shutdown::Write).unwrap();
|
|
}
|
|
|
|
fn get_file_from_data_nodes(
|
|
destination_path: &String,
|
|
filename: &String,
|
|
nodes: &Vec<AvailableNodes>)
|
|
{
|
|
let chunk = Chunk {
|
|
index: nodes[0].chunk_index,
|
|
filename: filename.clone(),
|
|
};
|
|
let endpoint = format!("{}:{}", nodes[0].ip, nodes[0].port);
|
|
let mut stream = TcpStream::connect(endpoint).unwrap();
|
|
let packet = serde_json::to_writer(
|
|
&stream,
|
|
&Packet {
|
|
p_type: PacketType::GetFile,
|
|
json: Some(serde_json::to_string(&chunk).unwrap()),
|
|
data: None,
|
|
}).unwrap();
|
|
stream.flush().unwrap();
|
|
stream.shutdown(Shutdown::Write).unwrap();
|
|
match serde_json::from_reader(stream) {
|
|
Ok(Packet { p_type: PacketType::GetFile, json, data }) => {
|
|
let data = data.unwrap();
|
|
let chunk: Chunk = serde_json::from_str(&json.unwrap()).unwrap();
|
|
// TODO: Here we have to rebuild the chunks
|
|
let mut copy = File::create(destination_path).unwrap();
|
|
copy.write_all(&data[..]).unwrap();
|
|
}
|
|
Ok(Packet { p_type: PacketType::Error, json, .. }) => {
|
|
eprintln!("Data Node Server Error: {}", &json.unwrap());
|
|
}
|
|
Ok(_) => {}
|
|
Err(e) => eprintln!("Error parsing json {}", e.to_string()),
|
|
};
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct CliArgs {
|
|
pub endpoint: String,
|
|
pub filepath: String,
|
|
pub filename: String,
|
|
pub is_copy_to_dfs: bool,
|
|
}
|
|
|
|
pub fn get_cli_args() -> CliArgs {
|
|
let mut args: Vec<String> = std::env::args().skip(1).collect();
|
|
if args.len() < 2 {
|
|
panic!("Requires 2 arguments; IP:PORT:FILEPATH and a Local filename/filepath")
|
|
}
|
|
let mut endpoint_arg: String = args.get(0).unwrap().clone();
|
|
|
|
let endpoint;
|
|
let filepath;
|
|
let filename;
|
|
let splits: Vec<&str>;
|
|
|
|
let is_copy_to_dfs = !endpoint_arg.contains(":");
|
|
if is_copy_to_dfs {
|
|
endpoint_arg = args.get(1).unwrap().clone();
|
|
splits = endpoint_arg.split(':').collect();
|
|
if splits.len() < 3 {
|
|
panic!("Incorrect endpoint argument format! Please provide IP:PORT:FILE");
|
|
}
|
|
filename = args.get(0).unwrap().clone();
|
|
} else {
|
|
splits = endpoint_arg.split(':').collect();
|
|
if splits.len() < 3 {
|
|
panic!("Incorrect endpoint argument format! Please provide IP:PORT:FILE");
|
|
}
|
|
filename = args.get(1).unwrap().clone();
|
|
}
|
|
endpoint = format!("{}:{}", splits[0], splits[1]);
|
|
filepath = String::from(splits[2]);
|
|
|
|
CliArgs { endpoint, filepath, filename, is_copy_to_dfs }
|
|
}
|
|
|