8000 Parse value final by agrover · Pull Request #387 · stratis-storage/devicemapper-rs · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Parse value final #387

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 52 additions & 110 deletions src/cachedev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use super::dm_options::DmOptions;
use super::lineardev::{LinearDev, LinearDevTargetParams};
use super::result::{DmError, DmResult, ErrorEnum};
use super::shared::{
device_create, device_exists, device_match, parse_device, DmDevice, TargetLine, TargetParams,
TargetTable,
device_create, device_exists, device_match, parse_device, parse_value, DmDevice, TargetLine,
TargetParams, TargetTable,
};
use super::types::{DataBlocks, DevId, DmName, DmUuid, MetaBlocks, Sectors, TargetTypeBuf};

Expand Down Expand Up @@ -83,29 +83,12 @@ impl FromStr for CacheTargetParams {
return Err(DmError::Dm(ErrorEnum::Invalid, err_msg));
}

let metadata_dev = parse_device(vals[1])?;
let cache_dev = parse_device(vals[2])?;
let origin_dev = parse_device(vals[3])?;

let block_size = vals[4].parse::<u64>().map(Sectors).map_err(|_| {
DmError::Dm(
ErrorEnum::Invalid,
format!(
"failed to parse value for data block size from \"{}\"",
vals[4]
),
)
})?;

let num_feature_args = vals[5].parse::<usize>().map_err(|_| {
DmError::Dm(
ErrorEnum::Invalid,
format!(
"failed to parse value for number of feature args from \"{}\"",
vals[5]
),
)
})?;
let metadata_dev = parse_device(vals[1], "metadata sub-device for cache target")?;
let cache_dev = parse_device(vals[2], "cache sub-device for cache target")?;
let origin_dev = parse_device(vals[3], "origin sub-device for cache target")?;

let block_size = Sectors(parse_value(vals[4], "data block size")?);
let num_feature_args: usize = parse_value(vals[5], "number of feature args")?;

let end_feature_args_index = 6 + num_feature_args;
let feature_args: Vec<String> = vals[6..end_feature_args_index]
Expand All @@ -115,17 +98,8 @@ impl FromStr for CacheTargetParams {

let policy = vals[end_feature_args_index].to_owned();

let num_policy_args = vals[end_feature_args_index + 1]
.parse::<usize>()
.map_err(|_| {
DmError::Dm(
ErrorEnum::Invalid,
format!(
"failed to parse value for number of policy args from \"{}\"",
vals[end_feature_args_index + 1]
),
)
})?;
let num_policy_args: usize =
parse_value(vals[end_feature_args_index + 1], "number of policy args")?;

let start_policy_args_index = end_feature_args_index + 2;
let end_policy_args_index = start_policy_args_index + num_policy_args;
Expand Down Expand Up @@ -633,22 +607,20 @@ impl CacheDev {
}

/// Parse pairs of arguments from a slice
/// Use the same policy as status() method in asserting
fn parse_pairs(start_index: usize, vals: &[&str]) -> (usize, Vec<(String, String)>) {
let num_pairs = vals[start_index]
.parse::<usize>()
.expect("number value must be valid format");
fn parse_pairs(start_index: usize, vals: &[&str]) -> DmResult<(usize, Vec<(String, String)>)> {
let num_pairs: usize = parse_value(vals[start_index], "number of pairs")?;
if num_pairs % 2 != 0 {
panic!(format!("Number of args \"{}\" is not even", num_pairs));
let err_msg = format!("Number of args \"{}\" is not even", num_pairs);
return Err(DmError::Dm(ErrorEnum::Invalid, err_msg));
}
let next_start_index = start_index + num_pairs + 1;
(
Ok((
next_start_index,
vals[start_index + 1..next_start_index]
.chunks(2)
.map(|p| (p[0].to_string(), p[1].to_string()))
.collect(),
)
))
}

/// Get the current status of the cache device.
Expand Down Expand Up @@ -680,97 +652,67 @@ impl CacheDev {
let cache_block_size = status_vals[2];
let cache_usage = status_vals[3].split('/').collect::<Vec<_>>();
CacheDevUsage::new(
Sectors(
meta_block_size
.parse::<u64>()
.expect("meta_block_size value must be valid"),
),
MetaBlocks(
meta_usage[0]
.parse::<u64>()
.expect("used_meta value must be valid"),
),
MetaBlocks(
meta_usage[1]
.parse::<u64>()
.expect("total_meta value must be valid"),
),
Sectors(
cache_block_size
.parse::<u64>()
.expect("cache_block_size value must be valid"),
),
DataBlocks(
cache_usage[0]
.parse::<u64>()
.expect("used_cache value must be valid"),
),
DataBlocks(
cache_usage[1]
.parse::<u64>()
.expect("total_cache value must be valid"),
),
Sectors(parse_value(meta_block_size, "meta block size")?),
MetaBlocks(parse_value(meta_usage[0], "used meta")?),
MetaBlocks(parse_value(meta_usage[1], "total meta")?),
Sectors(parse_value(cache_block_size, "cache block size")?),
DataBlocks(parse_value(cache_usage[0], "used cache")?),
DataBlocks(parse_value(cache_usage[1], "total cache")?),
)
};

let performance = CacheDevPerformance::new(
status_vals[4]
.parse::<u64>()
.expect("read hits value must be valid format"),
status_vals[5]
.parse::<u64>()
.expect("read misses value must be valid format"),
status_vals[6]
.parse::<u64>()
.expect("write hits value must be valid format"),
status_vals[7]
.parse::<u64>()
.expect("write misses value must be valid format"),
status_vals[8]
.parse::<u64>()
.expect("demotions value must be valid format"),
status_vals[9]
.parse::<u64>()
.expect("promotions value must be valid format"),
status_vals[10]
.parse::<u64>()
.expect("dirty value must be valid format"),
parse_value(status_vals[4], "read hits")?,
parse_value(status_vals[5], "read misses")?,
parse_value(status_vals[6], "write hits")?,
parse_value(status_vals[7], "write misses")?,
parse_value(status_vals[8], "demotions")?,
parse_value(status_vals[9], "promotions")?,
parse_value(status_vals[10], "dirty")?,
);

let num_feature_args = status_vals[11]
.parse::<usize>()
.expect("number value must be valid format");
let num_feature_args: usize = parse_value(status_vals[11], "number of feature args")?;
let core_args_start_index = 12usize + num_feature_args;
let feature_args: Vec<String> = status_vals[12..core_args_start_index]
.iter()
.map(|x| x.to_string())
.collect();

let (policy_start_index, core_args) =
CacheDev::parse_pairs(core_args_start_index, &status_vals);
CacheDev::parse_pairs(core_args_start_index, &status_vals)?;

let policy = status_vals[policy_start_index].to_string();
let (rest_start_index, policy_args) =
CacheDev::parse_pairs(policy_start_index + 1, &status_vals);
CacheDev::parse_pairs(policy_start_index + 1, &status_vals)?;

let cache_metadata_mode = match status_vals[rest_start_index] {
"rw" => CacheDevMetadataMode::Good,
"ro" => CacheDevMetadataMode::ReadOnly,
val => panic!(format!(
"Kernel returned unexpected {}th value \"{}\" in thin pool status",
rest_start_index + 1,
val
)),
val => {
return Err(DmError::Dm(
ErrorEnum::Invalid,
format!(
"Kernel returned unexpected {}th value \"{}\" in thin pool status",
rest_start_index + 1,
val,
),
))
}
};

let needs_check = match status_vals[rest_start_index + 1] {
"-" => false,
"needs_check" => true,
val => panic!(format!(
"Kernel returned unexpected {}th value \"{}\" in thin pool status",
rest_start_index + 2,
val
)),
val => {
return Err(DmError::Dm(
ErrorEnum::Invalid,
format!(
"Kernel returned unexpected {}th value \"{}\" in thin pool status",
rest_start_index + 1,
val,
),
))
}
};

Ok(CacheDevStatus::Working(Box::new(
Expand Down
58 changes: 9 additions & 49 deletions src/lineardev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use super::dm::DM;
use super::dm_options::DmOptions;
use super::result::{DmError, DmResult, ErrorEnum};
use super::shared::{
device_create, device_exists, device_match, parse_device, DmDevice, TargetLine, TargetParams,
TargetTable,
device_create, device_exists, device_match, parse_device, parse_value, DmDevice, TargetLine,
TargetParams, TargetTable,
};
use super::types::{DevId, DmName, DmUuid, Sectors, TargetTypeBuf};

Expand Down Expand Up @@ -68,17 +68,8 @@ impl FromStr for LinearTargetParams {
return Err(DmError::Dm(ErrorEnum::Invalid, err_msg));
}

let device = parse_device(vals[1])?;

let start = vals[2].parse::<u64>().map(Sectors).map_err(|_| {
DmError::Dm(
ErrorEnum::Invalid,
format!(
"failed to parse value for physical start offset \"{}\"",
vals[2]
),
)
})?;
let device = parse_device(vals[1], "block device for linear target")?;
let start = Sectors(parse_value(vals[2], "physical start offset")?);

Ok(LinearTargetParams::new(device, start))
}
Expand Down Expand Up @@ -199,44 +190,13 @@ impl FromStr for FlakeyTargetParams {
return Err(DmError::Dm(ErrorEnum::Invalid, err_msg));
}

let device = parse_device(vals[1])?;
let device = parse_device(vals[1], "block device for flakey target")?;
let start_offset = Sectors(parse_value(vals[2], "physical start offset")?);

let start_offset = vals[2].parse::<u64>().map(Sectors).map_err(|_| {
DmError::Dm(
ErrorEnum::Invalid,
format!(
"failed to parse value for start_offset from \"{}\"",
vals[2]
),
)
})?;
let up_interval = parse_value(vals[3], "up interval")?;
let down_interval = parse_value(vals[4], "down interval")?;

let up_interval = vals[3].parse::<u32>().map_err(|_| {
DmError::Dm(
ErrorEnum::Invalid,
format!("failed to parse value for up_interval from \"{}\"", vals[3]),
)
})?;

let down_interval = vals[4].parse::<u32>().map_err(|_| {
DmError::Dm(
ErrorEnum::Invalid,
format!(
"failed to parse value for down_interval from \"{}\"",
vals[4]
),
)
})?;

let num_feature_args = vals[5].parse::<usize>().map_err(|_| {
DmError::Dm(
ErrorEnum::Invalid,
format!(
"failed to parse value for number of feature args from \"{}\"",
vals[5]
),
)
})?;
let num_feature_args: usize = parse_value(vals[5], "number of feature args")?;

let feature_args: Vec<String> = vals[6..6 + num_feature_args]
.iter()
Expand Down
20 changes: 18 additions & 2 deletions src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,13 +184,13 @@ pub fn device_exists(dm: &DM, name: &DmName) -> DmResult<bool> {
}

/// Parse a device from either of a path or a maj:min pair
pub fn parse_device(val: &str) -> DmResult<Device> {
pub fn parse_device(val: &str, desc: &str) -> DmResult<Device> {
let device = if val.starts_with('/') {
devnode_to_devno(Path::new(val))?
.ok_or_else(|| {
DmError::Dm(
ErrorEnum::Invalid,
format!("failed to parse device number from \"{}\"", val),
format!("Failed to parse \"{}\" from input \"{}\"", desc, val),
)
})?
.into()
Expand All @@ -199,3 +199,19 @@ pub fn parse_device(val: &str) -> DmResult<Device> {
};
Ok(device)
}

/// Parse a value or return an error.
pub fn parse_value<T>(val: &str, desc: &str) -> DmResult<T>
where
T: FromStr,
{
val.parse::<T>().map_err(|_| {
DmError::Dm(
ErrorEnum::Invalid,
format!(
"Failed to parse value for \"{}\" from input \"{}\"",
desc, val
),
)
})
}
20 changes: 9 additions & 11 deletions src/thindev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use super::dm_flags::{DmCookie, DmFlags};
use super::dm_options::DmOptions;
use super::result::{DmError, DmResult, ErrorEnum};
use super::shared::{
device_create, device_exists, device_match, message, parse_device, DmDevice, TargetLine,
TargetParams, TargetTable,
device_create, device_exists, device_match, message, parse_device, parse_value, DmDevice,
TargetLine, TargetParams, TargetTable,
};
use super::thindevid::ThinDevId;
use super::thinpooldev::ThinPoolDev;
Expand Down Expand Up @@ -72,12 +72,15 @@ impl FromStr for ThinTargetParams {
}

Ok(ThinTargetParams::new(
parse_device(vals[1])?,
parse_device(vals[1], "thinpool device for thin target")?,
vals[2].parse::<ThinDevId>()?,
if len == 3 {
None
} else {
Some(parse_device(vals[3])?)
Some(parse_device(
vals[3],
"external origin device for thin snapshot",
)?)
},
))
}
Expand Down Expand Up @@ -375,17 +378,12 @@ impl ThinDev {
"Kernel must return at least 2 values from thin pool status"
);

let count = status_vals[0]
.parse::<u64>()
.map(Sectors)
.expect("Kernel always returns a parseable u64 for sector count");
let count = Sectors(parse_value(status_vals[0], "sector count")?);

let highest = if count == Sectors(0) {
None
} else {
Some(Sectors(status_vals[1].parse::<u64>().expect(
"Kernel always returns a parseable u64 when count > 0",
)))
Some(Sectors(parse_value(status_vals[1], "highest used sector")?))
};

Ok(ThinStatus::Working(Box::new(ThinDevWorkingStatus::new(
Expand Down
Loading
0