]> git.proxmox.com Git - proxmox-backup-qemu.git/commitdiff
initial commit
authorDietmar Maurer <dietmar@proxmox.com>
Wed, 11 Sep 2019 08:35:05 +0000 (10:35 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Wed, 11 Sep 2019 08:35:41 +0000 (10:35 +0200)
Cargo.toml [new file with mode: 0644]
Makefile [new file with mode: 0644]
build.rs [new file with mode: 0644]
rust-toolchain [new file with mode: 0644]
src/lib.rs [new file with mode: 0644]

diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..d830048
--- /dev/null
@@ -0,0 +1,24 @@
+[package]
+name = "proxmox-backup-qemu"
+version = "0.1.0"
+authors = [
+    "Dietmar Maurer <dietmar@proxmox.com>",
+    "Wolfgang Bumiller <w.bumiller@proxmox.com>",
+]
+edition = "2018"
+build = "build.rs"
+
+[lib]
+crate-type = ['lib', 'cdylib']
+
+[build-dependencies]
+cbindgen = "0.9.1"
+
+[dependencies]
+libc = "0.2"
+proxmox-backup = { path = "../proxmox-backup" }
+chrono = "0.4" # Date and time library for Rust
+failure = "0.1"
+futures-preview = "0.3.0-alpha"
+tokio = { version = "0.2.0-alpha.4" }
+
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..2a6ed42
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+
+
+ifeq ($(BUILD_MODE), release)
+CARGO_BUILD_ARGS += --release
+endif
+
+all:
+       cargo build $(CARGO_BUILD_ARGS)
diff --git a/build.rs b/build.rs
new file mode 100644 (file)
index 0000000..2b33131
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,15 @@
+// build.rs
+extern crate cbindgen;
+
+use std::env;
+
+fn main() {
+    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
+
+    cbindgen::Builder::new()
+        .with_language(cbindgen::Language::C)
+        .with_crate(&crate_dir)
+        .generate()
+        .unwrap()
+        .write_to_file("proxmox-backup-qemu.h");
+}
diff --git a/rust-toolchain b/rust-toolchain
new file mode 100644 (file)
index 0000000..bf867e0
--- /dev/null
@@ -0,0 +1 @@
+nightly
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644 (file)
index 0000000..9766f91
--- /dev/null
@@ -0,0 +1,163 @@
+use failure::*;
+use std::sync::Arc;
+use std::thread::JoinHandle;
+use tokio::sync::mpsc::{channel, Sender, Receiver};
+
+//use futures::{future, Future, Stream};
+use tokio::runtime::current_thread::{Runtime, RunError};
+
+//#[macro_use]
+use proxmox_backup::client::*;
+
+use chrono::{Utc, TimeZone};
+
+
+struct BackupTask {
+    worker: JoinHandle<Result<(), RunError>>,
+    tx: Sender<BackupMessage>,
+//    runtime: Runtime,
+//    client: Arc<BackupClient>,
+}
+
+enum BackupMessage {
+    End,
+    WriteData {
+        data: *const u8,
+        size: u64,
+        callback: extern "C" fn(*mut libc::c_void),
+        callback_data: *mut libc::c_void,
+    },
+}
+
+unsafe impl std::marker::Send for BackupMessage {} // fixme: ???
+
+impl BackupTask {
+
+    fn new() -> Result<Self, Error> {
+
+        let host = "localhost";
+        let user = "root@pam";
+        let store = "store2";
+        let backup_id = "99";
+        let verbose = false;
+        
+        let backup_time = Utc.timestamp(Utc::now().timestamp(), 0);
+
+        let (tx, rx) = channel(1);
+        
+        let worker = std::thread::spawn(move ||  {
+            backup_worker_task(rx, host)
+        });
+        
+        /*
+        let client = HttpClient::new(host, user)?;
+
+        let client = runtime.block_on(
+            client.start_backup(store, "vm", backup_id, backup_time, verbose))?;
+         */
+        
+        Ok(BackupTask {
+            worker,
+            tx,
+        })
+    }
+
+}
+
+fn backup_worker_task(mut rx: Receiver<BackupMessage>, host: &str) -> Result<(), RunError>  {
+
+    let mut runtime = Runtime::new().unwrap(); // fixme
+
+    runtime.spawn(async move {
+        
+        while let Some(msg) = rx.recv().await {
+
+            match msg {
+                BackupMessage::End => {
+                    break;
+                }
+                BackupMessage::WriteData { data, size, callback, callback_data } => {
+                    println!("write {} bytes", size);
+
+                    // do something async
+                    let res = std::panic::catch_unwind(|| {
+
+                        
+                    });
+  
+                    // fixme: error handling 
+                    callback(callback_data);
+                }
+            }
+        }
+    });
+
+    runtime.run()
+}
+
+// The C interface
+
+#[repr(C)]
+pub struct BackupHandle {
+    task: Box<BackupTask>,
+}
+
+
+#[no_mangle]
+pub unsafe extern "C" fn connect() -> *mut BackupHandle {
+
+    println!("Hello");
+
+    match BackupTask::new() {
+        Ok(task) => {
+            let tmp = Box::new(task);
+            let test = Box::into_raw(tmp);
+            test as * mut BackupHandle
+        }
+        Err(err) => std::ptr::null_mut(),
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn write_data_async(
+    handle: *mut BackupHandle,
+    data: *const u8,
+    size: u64,
+    callback: extern "C" fn(*mut libc::c_void),
+    callback_data: *mut libc::c_void,
+) {
+
+    let msg = BackupMessage::WriteData { data, size , callback, callback_data };
+    
+    let _res = (*handle).task.tx.send(msg); // fixme: log errors
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn disconnect(handle: *mut BackupHandle) {
+
+    println!("diconnect");
+
+    let mut handle = Box::from_raw(handle);
+   
+    let _res = handle.task.tx.send(BackupMessage::End); // fixme: log errors
+    
+    match handle.task.worker.join() {
+        Ok(result) => {
+            match result {
+                Ok(()) => {
+                    println!("worker finished");
+                }
+                Err(err) => {
+                    println!("worker finished with error: {:?}", err);
+                }
+            }
+        }
+        Err(err) => {
+           println!("worker paniced with error: {:?}", err);
+        }
+    }
+    
+    //drop(handle);
+}
+