Initial prototype

This prototype has basic IPC working, with starting actions and waiting for actions or just getting information
This commit is contained in:
OMGeeky
2024-01-31 15:38:52 +01:00
commit 1f8105943c
21 changed files with 1873 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
[package]
name = "gdriver-backend"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
fuser={ version = "0.14", default_features = true, features = ["serializable"] }
tracing.workspace = true
tokio.workspace = true
serde.workspace = true
tarpc.workspace = true
futures.workspace = true
chrono.workspace = true
[dependencies.gdriver-common]
path = "../gdriver-common/"

View File

@@ -0,0 +1,29 @@
use std::collections::HashMap;
use chrono::{DateTime, Utc};
use gdriver_common::{drive_structure::drive_id::DriveId, prelude::CONFIGURATION};
use crate::prelude::*;
pub struct Drive {
tracked_files: HashMap<DriveId, DateTime<Utc>>,
}
impl Drive {
pub fn new() -> Self {
Self {
tracked_files: HashMap::new(),
}
}
pub fn get_file_tracking_state(&self, id: &DriveId) -> TrackingState {
let file = self.tracked_files.get(id);
match file {
Some(date) => TrackingState::Tracked(*date),
None => TrackingState::Untracked,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TrackingState {
Untracked,
Tracked(DateTime<Utc>),
}

View File

@@ -0,0 +1,23 @@
use futures::{future, prelude::*};
use std::net::SocketAddr;
use tarpc::{
context,
server::{self, incoming::Incoming, Channel},
tokio_serde::formats::Json,
};
mod prelude;
use crate::prelude::*;
pub(crate) use gdriver_common::prelude::*;
mod drive;
mod sample;
mod service;
pub(crate) async fn spawn(fut: impl Future<Output = ()> + Send + 'static) {
tokio::spawn(fut);
}
#[tokio::main]
async fn main() -> Result<()> {
// sample::main().await?;
service::start().await?;
Ok(())
}

View File

@@ -0,0 +1,2 @@
pub(crate) type Result<T> = StdResult<T, Box<dyn Error>>;
use std::{error::Error, result::Result as StdResult};

View File

@@ -0,0 +1,38 @@
use super::*;
use gdriver_common::ipc::sample::World;
#[derive(Clone)]
struct HelloServer(SocketAddr);
impl World for HelloServer {
async fn hello(self, _: context::Context, name: String) -> String {
println!("Got Hello request with name: {name}");
format!("Hello {}", name)
}
}
pub(super) async fn main() -> Result<()> {
println!("Hello, world!");
let config = &CONFIGURATION;
let server_addr = (config.ip, config.port);
let mut listener = tarpc::serde_transport::tcp::listen(&server_addr, Json::default).await?;
println!("Listening");
listener.config_mut().max_frame_length(usize::MAX);
listener
// Ignore accept errors.
.filter_map(|r| future::ready(r.ok()))
.map(server::BaseChannel::with_defaults)
// Limit channels to 1 per IP.
.max_channels_per_key(1, |t| t.transport().peer_addr().unwrap().ip())
// serve is generated by the service attribute. It takes as input any type implementing
// the generated World trait.
.map(|channel| {
let server = HelloServer(channel.transport().peer_addr().unwrap());
channel.execute(server.serve()).for_each(spawn)
})
// Max 10 channels.
.buffer_unordered(10)
.for_each(|_| async {})
.await;
Ok(())
}

View File

@@ -0,0 +1,100 @@
use std::{sync::Arc, thread};
use chrono::Duration;
use gdriver_common::{
drive_structure::drive_id::ROOT_ID,
ipc::gdriver_service::{BackendActionError, BackendActionRequest, GDriverService},
};
use tokio::sync::Mutex;
use crate::drive::Drive;
use super::*;
#[derive(Clone)]
struct GdriverServer {
socket_address: SocketAddr,
drive: Arc<Mutex<Drive>>,
}
impl GDriverService for GdriverServer {
async fn do_something2(
self,
_: ::tarpc::context::Context,
req: BackendActionRequest,
) -> std::result::Result<String, BackendActionError> {
println!("You are connected from {}", self.socket_address);
match req {
BackendActionRequest::ShutdownGracefully => {
println!("Shutdown request received, but I dont want to.");
Err(BackendActionError::CouldNotComplete)
//Ok(String::from("OK. Shutting down"))
}
BackendActionRequest::UpdateChanges => {
println!("UpdateChanges request received");
let drive = &self.drive;
print_sample_tracking_state(drive).await;
Ok(String::from("OK"))
}
BackendActionRequest::Ping => {
println!("Ping request received");
Ok(String::from("Pong"))
}
BackendActionRequest::RunLong => {
println!("RunLong request received");
long_running_task(&self.drive).await;
Ok(String::from("OK"))
}
BackendActionRequest::StartLong => {
println!("StartLong request received");
tokio::spawn(async move { long_running_task(&self.drive).await });
Ok(String::from("OK"))
}
}
}
}
async fn long_running_task(drive: &Arc<Mutex<Drive>>) {
thread::sleep(Duration::seconds(10).to_std().unwrap());
print_sample_tracking_state(drive).await;
}
async fn print_sample_tracking_state(drive: &Arc<Mutex<Drive>>) {
let lock = drive.lock();
let drive = lock.await;
let state = drive.get_file_tracking_state(&ROOT_ID);
dbg!(state);
}
pub async fn start() -> Result<()> {
println!("Hello, world!");
let config = &CONFIGURATION;
println!("Config: {:?}", **config);
let drive = Drive::new();
let m = Arc::new(Mutex::new(drive));
let server_addr = (config.ip, config.port);
let mut listener = tarpc::serde_transport::tcp::listen(&server_addr, Json::default).await?;
listener.config_mut().max_frame_length(usize::MAX);
println!("Listening");
listener
// Ignore accept errors.
.filter_map(|r| future::ready(r.ok()))
.map(server::BaseChannel::with_defaults)
// // Limit channels to 1 per IP.
.max_channels_per_key(1, |t| t.transport().peer_addr().unwrap().ip())
// serve is generated by the service attribute. It takes as input any type implementing
// the generated World trait.
.map(|channel| {
let c = channel.transport().peer_addr().unwrap();
let server = GdriverServer {
socket_address: c,
drive: m.clone(),
};
channel.execute(server.serve()).for_each(spawn)
})
// Max 10 channels.
.buffer_unordered(10)
.for_each(|_| async {})
.await;
Ok(())
}