tape: avoid executor blocking in drive API

By using tokio::task::spawn_blocking().
This commit is contained in:
Dietmar Maurer 2020-12-12 09:20:04 +01:00
parent 2d87f2fb73
commit 66dbe5639e

View File

@ -70,7 +70,7 @@ use crate::{
}, },
)] )]
/// Load media via changer from slot /// Load media via changer from slot
pub fn load_slot( pub async fn load_slot(
drive: String, drive: String,
slot: u64, slot: u64,
_param: Value, _param: Value,
@ -85,9 +85,10 @@ pub fn load_slot(
None => bail!("drive '{}' has no associated changer", drive), None => bail!("drive '{}' has no associated changer", drive),
}; };
let drivenum = drive_config.changer_drive_id.unwrap_or(0); tokio::task::spawn_blocking(move || {
let drivenum = drive_config.changer_drive_id.unwrap_or(0);
mtx_load(&changer.path, slot, drivenum) mtx_load(&changer.path, slot, drivenum)
}).await?
} }
#[api( #[api(
@ -105,15 +106,14 @@ pub fn load_slot(
/// Load media with specified label /// Load media with specified label
/// ///
/// Issue a media load request to the associated changer device. /// Issue a media load request to the associated changer device.
pub fn load_media(drive: String, changer_id: String) -> Result<(), Error> { pub async fn load_media(drive: String, changer_id: String) -> Result<(), Error> {
let (config, _digest) = config::drive::config()?; let (config, _digest) = config::drive::config()?;
let (mut changer, _) = media_changer(&config, &drive, false)?; tokio::task::spawn_blocking(move || {
let (mut changer, _) = media_changer(&config, &drive, false)?;
changer.load_media(&changer_id)?; changer.load_media(&changer_id)
}).await?
Ok(())
} }
#[api( #[api(
@ -131,7 +131,7 @@ pub fn load_media(drive: String, changer_id: String) -> Result<(), Error> {
}, },
)] )]
/// Unload media via changer /// Unload media via changer
pub fn unload( pub async fn unload(
drive: String, drive: String,
slot: Option<u64>, slot: Option<u64>,
_param: Value, _param: Value,
@ -146,13 +146,15 @@ pub fn unload(
None => bail!("drive '{}' has no associated changer", drive), None => bail!("drive '{}' has no associated changer", drive),
}; };
let drivenum: u64 = 0; let drivenum = drive_config.changer_drive_id.unwrap_or(0);
if let Some(slot) = slot { tokio::task::spawn_blocking(move || {
mtx_unload(&changer.path, slot, drivenum) if let Some(slot) = slot {
} else { mtx_unload(&changer.path, slot, drivenum)
drive_config.unload_media() } else {
} drive_config.unload_media()
}
}).await?
} }
#[api( #[api(
@ -270,20 +272,20 @@ pub fn rewind(
}, },
)] )]
/// Eject/Unload drive media /// Eject/Unload drive media
pub fn eject_media(drive: String) -> Result<(), Error> { pub async fn eject_media(drive: String) -> Result<(), Error> {
let (config, _digest) = config::drive::config()?; let (config, _digest) = config::drive::config()?;
let (mut changer, _) = media_changer(&config, &drive, false)?; tokio::task::spawn_blocking(move || {
let (mut changer, _) = media_changer(&config, &drive, false)?;
if !changer.eject_on_unload() { if !changer.eject_on_unload() {
let mut drive = open_drive(&config, &drive)?; let mut drive = open_drive(&config, &drive)?;
drive.eject_media()?; drive.eject_media()?;
} }
changer.unload_media()?; changer.unload_media()
}).await?
Ok(())
} }
#[api( #[api(
@ -439,39 +441,41 @@ fn write_media_label(
}, },
)] )]
/// Read media label /// Read media label
pub fn read_label(drive: String) -> Result<MediaLabelInfoFlat, Error> { pub async fn read_label(drive: String) -> Result<MediaLabelInfoFlat, Error> {
let (config, _digest) = config::drive::config()?; let (config, _digest) = config::drive::config()?;
let mut drive = open_drive(&config, &drive)?; tokio::task::spawn_blocking(move || {
let mut drive = open_drive(&config, &drive)?;
let info = drive.read_label()?; let info = drive.read_label()?;
let info = match info { let info = match info {
Some(info) => { Some(info) => {
let mut flat = MediaLabelInfoFlat { let mut flat = MediaLabelInfoFlat {
uuid: info.label.uuid.to_string(), uuid: info.label.uuid.to_string(),
changer_id: info.label.changer_id.clone(), changer_id: info.label.changer_id.clone(),
ctime: info.label.ctime, ctime: info.label.ctime,
media_set_ctime: None, media_set_ctime: None,
media_set_uuid: None, media_set_uuid: None,
pool: None, pool: None,
seq_nr: None, seq_nr: None,
}; };
if let Some((set, _)) = info.media_set_label { if let Some((set, _)) = info.media_set_label {
flat.pool = Some(set.pool.clone()); flat.pool = Some(set.pool.clone());
flat.seq_nr = Some(set.seq_nr); flat.seq_nr = Some(set.seq_nr);
flat.media_set_uuid = Some(set.uuid.to_string()); flat.media_set_uuid = Some(set.uuid.to_string());
flat.media_set_ctime = Some(set.ctime); flat.media_set_ctime = Some(set.ctime);
}
flat
} }
flat None => {
} bail!("Media is empty (no label).");
None => { }
bail!("Media is empty (no label)."); };
}
};
Ok(info) Ok(info)
}).await?
} }
#[api( #[api(
@ -497,41 +501,49 @@ pub fn read_label(drive: String) -> Result<MediaLabelInfoFlat, Error> {
/// This method queries the changer to get a list of media labels. /// This method queries the changer to get a list of media labels.
/// ///
/// Note: This updates the media online status. /// Note: This updates the media online status.
pub fn inventory( pub async fn inventory(
drive: String, drive: String,
) -> Result<Vec<LabelUuidMap>, Error> { ) -> Result<Vec<LabelUuidMap>, Error> {
let (config, _digest) = config::drive::config()?; let (config, _digest) = config::drive::config()?;
let (changer, changer_name) = media_changer(&config, &drive, false)?; tokio::task::spawn_blocking(move || {
let (changer, changer_name) = media_changer(&config, &drive, false)?;
let changer_id_list = changer.list_media_changer_ids()?; let changer_id_list = changer.list_media_changer_ids()?;
let state_path = Path::new(TAPE_STATUS_DIR); let state_path = Path::new(TAPE_STATUS_DIR);
let mut inventory = Inventory::load(state_path)?; let mut inventory = Inventory::load(state_path)?;
let mut state_db = MediaStateDatabase::load(state_path)?; let mut state_db = MediaStateDatabase::load(state_path)?;
update_changer_online_status(&config, &mut inventory, &mut state_db, &changer_name, &changer_id_list)?; update_changer_online_status(
&config,
&mut inventory,
&mut state_db,
&changer_name,
&changer_id_list,
)?;
let mut list = Vec::new(); let mut list = Vec::new();
for changer_id in changer_id_list.iter() { for changer_id in changer_id_list.iter() {
if changer_id.starts_with("CLN") { if changer_id.starts_with("CLN") {
// skip cleaning unit // skip cleaning unit
continue; continue;
}
let changer_id = changer_id.to_string();
if let Some(media_id) = inventory.find_media_by_changer_id(&changer_id) {
list.push(LabelUuidMap { changer_id, uuid: Some(media_id.label.uuid.to_string()) });
} else {
list.push(LabelUuidMap { changer_id, uuid: None });
}
} }
let changer_id = changer_id.to_string(); Ok(list)
}).await?
if let Some(media_id) = inventory.find_media_by_changer_id(&changer_id) {
list.push(LabelUuidMap { changer_id, uuid: Some(media_id.label.uuid.to_string()) });
} else {
list.push(LabelUuidMap { changer_id, uuid: None });
}
}
Ok(list)
} }
#[api( #[api(