run all commands async with tokio::spawn()

This commit is contained in:
Dietmar Maurer 2019-10-25 11:57:33 +02:00
parent 6abb11b405
commit ca246b4590

View File

@ -103,8 +103,6 @@ fn backup_worker_task(
connect_tx.send(Ok(()))?; connect_tx.send(Ok(()))?;
drop(connect_tx); // no longer needed drop(connect_tx); // no longer needed
let mut client = None;
let (mut abort_tx, mut abort_rx) = tokio::sync::mpsc::channel(1); let (mut abort_tx, mut abort_rx) = tokio::sync::mpsc::channel(1);
let abort_rx = async move { let abort_rx = async move {
match abort_rx.recv().await { match abort_rx.recv().await {
@ -122,25 +120,38 @@ fn backup_worker_task(
let chunk_size = setup.chunk_size; let chunk_size = setup.chunk_size;
let client = Arc::new(Mutex::new(None));
runtime.spawn(async move { runtime.spawn(async move {
let registry = Arc::new(Mutex::new(ImageRegistry::new())); let registry = Arc::new(Mutex::new(ImageRegistry::new()));
loop { loop {
let msg = command_rx.recv().unwrap(); // todo: should be blocking // Note: command_rx.recv() may block one thread, because there are
// still enough threads to do the work
let msg = command_rx.recv();
if let Err(_) = msg {
// sender closed channel, try to abort and then end the loop
let _ = abort_tx.send(()).await;
break;
};
let msg = msg.unwrap();
match msg { match msg {
BackupMessage::Connect { callback_info } => { BackupMessage::Connect { callback_info } => {
client = match setup.connect().await { let client = client.clone();
Ok(client) => { let setup = setup.clone();
callback_info.send_result(Ok(0)); let abort_future = abort.listen();
Some(client) tokio::spawn(async move {
} let command = async move {
Err(err) => { let writer = setup.connect().await?;
callback_info.send_result(Err(err)); let mut guard = client.lock().unwrap();
None *guard = Some(writer);
} Ok(0)
}; };
handle_async_command(command, abort_future, callback_info).await;
});
} }
BackupMessage::Abort => { BackupMessage::Abort => {
println!("worker got abort mesage"); println!("worker got abort mesage");
@ -154,104 +165,137 @@ fn backup_worker_task(
break; break;
} }
BackupMessage::AddConfig { name, data, size, callback_info } => { BackupMessage::AddConfig { name, data, size, callback_info } => {
match client { let client = (*(client.lock().unwrap())).clone();
Some(ref client) => { let abort_future = abort.listen();
handle_async_command( let registry = registry.clone();
add_config( let crypt_config = crypt_config.clone();
client.clone(), tokio::spawn(async move {
crypt_config.clone(), match client {
registry.clone(), Some(client) => {
name, handle_async_command(
data, add_config(
size, client,
), crypt_config,
abort.listen(), registry,
callback_info, name,
).await; data,
size,
),
abort_future,
callback_info,
).await;
}
None => {
callback_info.send_result(Err(format_err!("not connected")));
}
} }
None => { });
callback_info.send_result(Err(format_err!("not connected")));
}
}
} }
BackupMessage::RegisterImage { device_name, size, callback_info} => { BackupMessage::RegisterImage { device_name, size, callback_info} => {
match client { let client = (*(client.lock().unwrap())).clone();
Some(ref client) => { let abort_future = abort.listen();
handle_async_command( let registry = registry.clone();
register_image( let crypt_config = crypt_config.clone();
client.clone(), let known_chunks = known_chunks.clone();
crypt_config.clone(), tokio::spawn(async move {
registry.clone(), match client {
known_chunks.clone(), Some(client) => {
device_name, handle_async_command(
size, register_image(
chunk_size, client,
), crypt_config,
abort.listen(), registry,
callback_info, known_chunks,
).await; device_name,
size,
chunk_size,
),
abort_future,
callback_info,
).await;
}
None => {
callback_info.send_result(Err(format_err!("not connected")));
}
} }
None => { });
callback_info.send_result(Err(format_err!("not connected")));
}
}
} }
BackupMessage::CloseImage { dev_id, callback_info } => { BackupMessage::CloseImage { dev_id, callback_info } => {
match client { let client = (*(client.lock().unwrap())).clone();
Some(ref client) => { let abort_future = abort.listen();
handle_async_command( let registry = registry.clone();
close_image(client.clone(), registry.clone(), dev_id), tokio::spawn(async move {
abort.listen(), match client {
callback_info, Some(client) => {
).await; handle_async_command(
close_image(client, registry, dev_id),
abort_future,
callback_info,
).await;
}
None => {
callback_info.send_result(Err(format_err!("not connected")));
}
} }
None => { });
callback_info.send_result(Err(format_err!("not connected")));
}
}
} }
BackupMessage::WriteData { dev_id, data, offset, size, callback_info } => { BackupMessage::WriteData { dev_id, data, offset, size, callback_info } => {
match client { let client = (*(client.lock().unwrap())).clone();
Some(ref client) => { let abort_future = abort.listen();
written_bytes2.fetch_add(size, Ordering::SeqCst); let registry = registry.clone();
handle_async_command( let crypt_config = crypt_config.clone();
write_data( let known_chunks = known_chunks.clone();
client.clone(), let written_bytes2 = written_bytes2.clone();
crypt_config.clone(), tokio::spawn(async move {
registry.clone(), match client {
known_chunks.clone(), Some(client) => {
dev_id, data, written_bytes2.fetch_add(size, Ordering::SeqCst);
offset, handle_async_command(
size, write_data(
chunk_size, client,
), crypt_config,
abort.listen(), registry,
callback_info, known_chunks,
).await; dev_id, data,
offset,
size,
chunk_size,
),
abort_future,
callback_info,
).await;
}
None => {
callback_info.send_result(Err(format_err!("not connected")));
}
} }
None => { });
callback_info.send_result(Err(format_err!("not connected")));
}
}
} }
BackupMessage::Finish { callback_info } => { BackupMessage::Finish { callback_info } => {
match client { let client = (*(client.lock().unwrap())).clone();
Some(ref client) => { let abort_future = abort.listen();
handle_async_command( let registry = registry.clone();
finish_backup( let crypt_config = crypt_config.clone();
client.clone(), let setup = setup.clone();
crypt_config.clone(), tokio::spawn(async move {
registry.clone(), match client {
setup.clone(), Some(client) => {
), handle_async_command(
abort.listen(), finish_backup(
callback_info, client,
).await; crypt_config,
registry,
setup,
),
abort_future,
callback_info,
).await;
}
None => {
callback_info.send_result(Err(format_err!("not connected")));
}
} }
None => { });
callback_info.send_result(Err(format_err!("not connected")));
}
}
} }
} }
} }