Loading tools/aconfig/aconfig_storage_file/src/lib.rs +80 −49 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ pub mod protos; pub mod test_utils; use anyhow::anyhow; use std::cmp::Ordering; use std::collections::hash_map::DefaultHasher; use std::fs::File; use std::hash::{Hash, Hasher}; Loading Loading @@ -122,6 +123,48 @@ impl TryFrom<u16> for StoredFlagType { } } /// Storage query api error #[non_exhaustive] #[derive(thiserror::Error, Debug)] pub enum AconfigStorageError { #[error("failed to read the file")] FileReadFail(#[source] anyhow::Error), #[error("fail to parse protobuf")] ProtobufParseFail(#[source] anyhow::Error), #[error("storage files not found for this container")] StorageFileNotFound(#[source] anyhow::Error), #[error("fail to map storage file")] MapFileFail(#[source] anyhow::Error), #[error("fail to get mapped file")] ObtainMappedFileFail(#[source] anyhow::Error), #[error("fail to flush mapped storage file")] MapFlushFail(#[source] anyhow::Error), #[error("number of items in hash table exceed limit")] HashTableSizeLimit(#[source] anyhow::Error), #[error("failed to parse bytes into data")] BytesParseFail(#[source] anyhow::Error), #[error("cannot parse storage files with a higher version")] HigherStorageFileVersion(#[source] anyhow::Error), #[error("invalid storage file byte offset")] InvalidStorageFileOffset(#[source] anyhow::Error), #[error("failed to create file")] FileCreationFail(#[source] anyhow::Error), #[error("invalid stored flag type")] InvalidStoredFlagType(#[source] anyhow::Error), } /// Get the right hash table size given number of entries in the table. Use a /// load factor of 0.5 for performance. pub fn get_table_size(entries: u32) -> Result<u32, AconfigStorageError> { Loading Loading @@ -184,47 +227,6 @@ pub(crate) fn read_str_from_bytes( Ok(val) } /// Storage query api error #[non_exhaustive] #[derive(thiserror::Error, Debug)] pub enum AconfigStorageError { #[error("failed to read the file")] FileReadFail(#[source] anyhow::Error), #[error("fail to parse protobuf")] ProtobufParseFail(#[source] anyhow::Error), #[error("storage files not found for this container")] StorageFileNotFound(#[source] anyhow::Error), #[error("fail to map storage file")] MapFileFail(#[source] anyhow::Error), #[error("fail to get mapped file")] ObtainMappedFileFail(#[source] anyhow::Error), #[error("fail to flush mapped storage file")] MapFlushFail(#[source] anyhow::Error), #[error("number of items in hash table exceed limit")] HashTableSizeLimit(#[source] anyhow::Error), #[error("failed to parse bytes into data")] BytesParseFail(#[source] anyhow::Error), #[error("cannot parse storage files with a higher version")] HigherStorageFileVersion(#[source] anyhow::Error), #[error("invalid storage file byte offset")] InvalidStorageFileOffset(#[source] anyhow::Error), #[error("failed to create file")] FileCreationFail(#[source] anyhow::Error), #[error("invalid stored flag type")] InvalidStoredFlagType(#[source] anyhow::Error), } /// Read in storage file as bytes pub fn read_file_to_bytes(file_path: &str) -> Result<Vec<u8>, AconfigStorageError> { let mut file = File::open(file_path).map_err(|errmsg| { Loading @@ -233,7 +235,7 @@ pub fn read_file_to_bytes(file_path: &str) -> Result<Vec<u8>, AconfigStorageErro let mut buffer = Vec::new(); file.read_to_end(&mut buffer).map_err(|errmsg| { AconfigStorageError::FileReadFail(anyhow!( "Failed to read 4 bytes from file {}: {}", "Failed to read bytes from file {}: {}", file_path, errmsg )) Loading @@ -246,7 +248,7 @@ pub fn list_flags( package_map: &str, flag_map: &str, flag_val: &str, ) -> Result<Vec<(String, String, bool)>, AconfigStorageError> { ) -> Result<Vec<(String, String, StoredFlagType, bool)>, AconfigStorageError> { let package_table = PackageTable::from_bytes(&read_file_to_bytes(package_map)?)?; let flag_table = FlagTable::from_bytes(&read_file_to_bytes(flag_map)?)?; let flag_value_list = FlagValueList::from_bytes(&read_file_to_bytes(flag_val)?)?; Loading @@ -261,10 +263,15 @@ pub fn list_flags( let (package_name, package_offset) = package_info[node.package_id as usize]; let flag_offset = package_offset + node.flag_id as u32; let flag_value = flag_value_list.booleans[flag_offset as usize]; flags.push((String::from(package_name), node.flag_name.clone(), flag_value)); flags.push((String::from(package_name), node.flag_name.clone(), node.flag_type, flag_value)); } flags.sort_by(|v1, v2| v1.0.cmp(&v2.0)); flags.sort_by(|v1, v2| { match v1.0.cmp(&v2.0) { Ordering::Equal => v1.1.cmp(&v2.1), other => other, } }); Ok(flags) } Loading Loading @@ -292,30 +299,54 @@ mod tests { let flags = list_flags(&package_table_path, &flag_table_path, &flag_value_list_path).unwrap(); let expected = [ (String::from("com.android.aconfig.storage.test_1"), String::from("enabled_ro"), true), (String::from("com.android.aconfig.storage.test_1"), String::from("enabled_rw"), true), ( String::from("com.android.aconfig.storage.test_1"), String::from("disabled_rw"), StoredFlagType::ReadWriteBoolean, false, ), ( String::from("com.android.aconfig.storage.test_1"), String::from("enabled_ro"), StoredFlagType::ReadOnlyBoolean, true ), ( String::from("com.android.aconfig.storage.test_1"), String::from("enabled_rw"), StoredFlagType::ReadWriteBoolean, true ), ( String::from("com.android.aconfig.storage.test_2"), String::from("disabled_ro"), StoredFlagType::ReadOnlyBoolean, false, ), ( String::from("com.android.aconfig.storage.test_2"), String::from("enabled_fixed_ro"), StoredFlagType::FixedReadOnlyBoolean, true, ), (String::from("com.android.aconfig.storage.test_2"), String::from("enabled_ro"), true), (String::from("com.android.aconfig.storage.test_4"), String::from("enabled_ro"), true), ( String::from("com.android.aconfig.storage.test_2"), String::from("enabled_ro"), StoredFlagType::ReadOnlyBoolean, true ), ( String::from("com.android.aconfig.storage.test_4"), String::from("enabled_fixed_ro"), StoredFlagType::FixedReadOnlyBoolean, true, ), ( String::from("com.android.aconfig.storage.test_4"), String::from("enabled_ro"), StoredFlagType::ReadOnlyBoolean, true ), ]; assert_eq!(flags, expected); } Loading tools/aconfig/aconfig_storage_file/src/main.rs +2 −2 Original line number Diff line number Diff line Loading @@ -88,8 +88,8 @@ fn main() -> Result<(), AconfigStorageError> { let flag_map = sub_matches.get_one::<String>("flag-map").unwrap(); let flag_val = sub_matches.get_one::<String>("flag-val").unwrap(); let flags = list_flags(package_map, flag_map, flag_val)?; for flag in flags.iter() { println!("{}: {}", flag.0, flag.1); for (package_name, flag_name, flag_type, flag_value) in flags.iter() { println!("{} {} {:?} {}", package_name, flag_name, flag_type, flag_value); } } _ => unreachable!(), Loading tools/aconfig/aflags/src/aconfig_storage_source.rs +1 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ impl FlagSource for AconfigStorageSource { let container = file_info.container.ok_or(anyhow!("storage file is missing container"))?; for (package, name, val) in for (package, name, _flag_type, val) in aconfig_storage_file::list_flags(&package_map, &flag_map, &flag_val)? { result.push(Flag { Loading Loading
tools/aconfig/aconfig_storage_file/src/lib.rs +80 −49 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ pub mod protos; pub mod test_utils; use anyhow::anyhow; use std::cmp::Ordering; use std::collections::hash_map::DefaultHasher; use std::fs::File; use std::hash::{Hash, Hasher}; Loading Loading @@ -122,6 +123,48 @@ impl TryFrom<u16> for StoredFlagType { } } /// Storage query api error #[non_exhaustive] #[derive(thiserror::Error, Debug)] pub enum AconfigStorageError { #[error("failed to read the file")] FileReadFail(#[source] anyhow::Error), #[error("fail to parse protobuf")] ProtobufParseFail(#[source] anyhow::Error), #[error("storage files not found for this container")] StorageFileNotFound(#[source] anyhow::Error), #[error("fail to map storage file")] MapFileFail(#[source] anyhow::Error), #[error("fail to get mapped file")] ObtainMappedFileFail(#[source] anyhow::Error), #[error("fail to flush mapped storage file")] MapFlushFail(#[source] anyhow::Error), #[error("number of items in hash table exceed limit")] HashTableSizeLimit(#[source] anyhow::Error), #[error("failed to parse bytes into data")] BytesParseFail(#[source] anyhow::Error), #[error("cannot parse storage files with a higher version")] HigherStorageFileVersion(#[source] anyhow::Error), #[error("invalid storage file byte offset")] InvalidStorageFileOffset(#[source] anyhow::Error), #[error("failed to create file")] FileCreationFail(#[source] anyhow::Error), #[error("invalid stored flag type")] InvalidStoredFlagType(#[source] anyhow::Error), } /// Get the right hash table size given number of entries in the table. Use a /// load factor of 0.5 for performance. pub fn get_table_size(entries: u32) -> Result<u32, AconfigStorageError> { Loading Loading @@ -184,47 +227,6 @@ pub(crate) fn read_str_from_bytes( Ok(val) } /// Storage query api error #[non_exhaustive] #[derive(thiserror::Error, Debug)] pub enum AconfigStorageError { #[error("failed to read the file")] FileReadFail(#[source] anyhow::Error), #[error("fail to parse protobuf")] ProtobufParseFail(#[source] anyhow::Error), #[error("storage files not found for this container")] StorageFileNotFound(#[source] anyhow::Error), #[error("fail to map storage file")] MapFileFail(#[source] anyhow::Error), #[error("fail to get mapped file")] ObtainMappedFileFail(#[source] anyhow::Error), #[error("fail to flush mapped storage file")] MapFlushFail(#[source] anyhow::Error), #[error("number of items in hash table exceed limit")] HashTableSizeLimit(#[source] anyhow::Error), #[error("failed to parse bytes into data")] BytesParseFail(#[source] anyhow::Error), #[error("cannot parse storage files with a higher version")] HigherStorageFileVersion(#[source] anyhow::Error), #[error("invalid storage file byte offset")] InvalidStorageFileOffset(#[source] anyhow::Error), #[error("failed to create file")] FileCreationFail(#[source] anyhow::Error), #[error("invalid stored flag type")] InvalidStoredFlagType(#[source] anyhow::Error), } /// Read in storage file as bytes pub fn read_file_to_bytes(file_path: &str) -> Result<Vec<u8>, AconfigStorageError> { let mut file = File::open(file_path).map_err(|errmsg| { Loading @@ -233,7 +235,7 @@ pub fn read_file_to_bytes(file_path: &str) -> Result<Vec<u8>, AconfigStorageErro let mut buffer = Vec::new(); file.read_to_end(&mut buffer).map_err(|errmsg| { AconfigStorageError::FileReadFail(anyhow!( "Failed to read 4 bytes from file {}: {}", "Failed to read bytes from file {}: {}", file_path, errmsg )) Loading @@ -246,7 +248,7 @@ pub fn list_flags( package_map: &str, flag_map: &str, flag_val: &str, ) -> Result<Vec<(String, String, bool)>, AconfigStorageError> { ) -> Result<Vec<(String, String, StoredFlagType, bool)>, AconfigStorageError> { let package_table = PackageTable::from_bytes(&read_file_to_bytes(package_map)?)?; let flag_table = FlagTable::from_bytes(&read_file_to_bytes(flag_map)?)?; let flag_value_list = FlagValueList::from_bytes(&read_file_to_bytes(flag_val)?)?; Loading @@ -261,10 +263,15 @@ pub fn list_flags( let (package_name, package_offset) = package_info[node.package_id as usize]; let flag_offset = package_offset + node.flag_id as u32; let flag_value = flag_value_list.booleans[flag_offset as usize]; flags.push((String::from(package_name), node.flag_name.clone(), flag_value)); flags.push((String::from(package_name), node.flag_name.clone(), node.flag_type, flag_value)); } flags.sort_by(|v1, v2| v1.0.cmp(&v2.0)); flags.sort_by(|v1, v2| { match v1.0.cmp(&v2.0) { Ordering::Equal => v1.1.cmp(&v2.1), other => other, } }); Ok(flags) } Loading Loading @@ -292,30 +299,54 @@ mod tests { let flags = list_flags(&package_table_path, &flag_table_path, &flag_value_list_path).unwrap(); let expected = [ (String::from("com.android.aconfig.storage.test_1"), String::from("enabled_ro"), true), (String::from("com.android.aconfig.storage.test_1"), String::from("enabled_rw"), true), ( String::from("com.android.aconfig.storage.test_1"), String::from("disabled_rw"), StoredFlagType::ReadWriteBoolean, false, ), ( String::from("com.android.aconfig.storage.test_1"), String::from("enabled_ro"), StoredFlagType::ReadOnlyBoolean, true ), ( String::from("com.android.aconfig.storage.test_1"), String::from("enabled_rw"), StoredFlagType::ReadWriteBoolean, true ), ( String::from("com.android.aconfig.storage.test_2"), String::from("disabled_ro"), StoredFlagType::ReadOnlyBoolean, false, ), ( String::from("com.android.aconfig.storage.test_2"), String::from("enabled_fixed_ro"), StoredFlagType::FixedReadOnlyBoolean, true, ), (String::from("com.android.aconfig.storage.test_2"), String::from("enabled_ro"), true), (String::from("com.android.aconfig.storage.test_4"), String::from("enabled_ro"), true), ( String::from("com.android.aconfig.storage.test_2"), String::from("enabled_ro"), StoredFlagType::ReadOnlyBoolean, true ), ( String::from("com.android.aconfig.storage.test_4"), String::from("enabled_fixed_ro"), StoredFlagType::FixedReadOnlyBoolean, true, ), ( String::from("com.android.aconfig.storage.test_4"), String::from("enabled_ro"), StoredFlagType::ReadOnlyBoolean, true ), ]; assert_eq!(flags, expected); } Loading
tools/aconfig/aconfig_storage_file/src/main.rs +2 −2 Original line number Diff line number Diff line Loading @@ -88,8 +88,8 @@ fn main() -> Result<(), AconfigStorageError> { let flag_map = sub_matches.get_one::<String>("flag-map").unwrap(); let flag_val = sub_matches.get_one::<String>("flag-val").unwrap(); let flags = list_flags(package_map, flag_map, flag_val)?; for flag in flags.iter() { println!("{}: {}", flag.0, flag.1); for (package_name, flag_name, flag_type, flag_value) in flags.iter() { println!("{} {} {:?} {}", package_name, flag_name, flag_type, flag_value); } } _ => unreachable!(), Loading
tools/aconfig/aflags/src/aconfig_storage_source.rs +1 −1 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ impl FlagSource for AconfigStorageSource { let container = file_info.container.ok_or(anyhow!("storage file is missing container"))?; for (package, name, val) in for (package, name, _flag_type, val) in aconfig_storage_file::list_flags(&package_map, &flag_map, &flag_val)? { result.push(Flag { Loading