Check for package upgrades in parallel; Search in packages in parallel;

This commit is contained in:
Nathan Fisher 2023-04-01 02:01:53 -04:00
parent 26be99f408
commit a1843cac33
4 changed files with 75 additions and 39 deletions

View File

@ -2,8 +2,16 @@ use ron::ser::PrettyConfig;
use {
crate::{Package, Repository, Version},
rayon::prelude::*,
serde::{Deserialize, Serialize},
std::{collections::HashMap, error::Error, fmt, fs::{self, File}, path::PathBuf},
std::{
collections::HashMap,
error::Error,
fmt,
fs::{self, File},
path::PathBuf,
sync::Mutex,
},
url::Url,
zstd::{Decoder, Encoder},
};
@ -50,46 +58,48 @@ impl Database {
pub fn get_upgradable(&mut self) -> Result<HashMap<String, Update>, Box<dyn Error>> {
self.update()?;
let mut updates = HashMap::<String, Update>::new();
for local_package in self.packages.values() {
let name = local_package.name.clone();
let updates = Mutex::new(HashMap::<String, Update>::new());
self.packages.par_iter().for_each(|(key, local_package)| {
for repo in self.available.values() {
// Check if the remote has a package by this name
if let Some(remote_package) = repo.packages.get(&name) {
if let Some(remote_package) = repo.packages.get(key) {
// Check if the remote package is an update
if remote_package.is_upgrade(&local_package) {
// Check if we've already pulled in an update from another repo,
// and if so compare versions
if let Some(other_update) = updates.get(&name) {
if remote_package.version > other_update.version
|| (remote_package.version == other_update.version
&& remote_package.release > other_update.release)
{
// The remote version is an update to the already
// pulled in update, so swap it out
if let Ok(mut updates) = updates.lock() {
// Check if we've already pulled in an update from another repo,
// and if so compare versions
if let Some(other_update) = updates.get(key) {
if remote_package.version > other_update.version
|| (remote_package.version == other_update.version
&& remote_package.release > other_update.release)
{
// The remote version is an update to the already
// pulled in update, so swap it out
let update = Update {
name: key.to_string(),
version: remote_package.version.clone(),
release: remote_package.release,
url: repo.base_url.clone(),
};
updates.insert(key.to_string(), update);
}
} else {
// First time we've seen this update, so insert it
// into our hashmap
let update = Update {
name: name.clone(),
name: key.to_string(),
version: remote_package.version.clone(),
release: remote_package.release,
url: repo.base_url.clone(),
};
updates.insert(name.clone(), update);
updates.insert(key.to_string(), update);
}
} else {
// First time we've seen this update, so insert it
// into our hashmap
let update = Update {
name: name.clone(),
version: remote_package.version.clone(),
release: remote_package.release,
url: repo.base_url.clone(),
};
updates.insert(name.clone(), update);
}
}
}
}
}
});
let updates = updates.into_inner()?;
Ok(updates)
}
@ -125,3 +135,20 @@ impl Database {
unimplemented!();
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn update_to_string() {
let up = Update {
name: "hpk".to_string(),
version: Version::Number(42),
release: 1,
url: Url::parse("https://hitchhiker-linux.org/pub/packages/").unwrap(),
}
.to_string();
assert_eq!("hpk-42_1".to_string(), up);
}
}

View File

@ -68,7 +68,6 @@ pub fn get_dbdir(prefix: Option<PathBuf>) -> PathBuf {
path
}
/// Gets the cache directory path. Takes an optional prefix variable for working
/// with an alternate filesystem root.
/// ## Examples
@ -120,4 +119,3 @@ mod test {
assert_eq!(cache, PathBuf::from("/mnt/aarch64/var/cache/hpk"));
}
}

View File

@ -6,8 +6,8 @@ use {
ron::ser::{to_string_pretty, PrettyConfig},
serde::{Deserialize, Serialize},
std::{
fs,
error::Error,
fs,
fs::File,
io::{BufWriter, Write},
path::Path,

View File

@ -1,7 +1,10 @@
use std::sync::PoisonError;
use {
crate::Package,
rayon::prelude::*,
serde::{Deserialize, Serialize},
std::collections::HashMap,
std::{collections::HashMap, sync::Mutex},
url::Url,
};
@ -13,32 +16,40 @@ pub struct Repository {
}
impl Repository {
pub fn search_names(&self, query: &str) -> Vec<&Package> {
pub fn search_names(&self, query: &str) -> Result<Vec<&Package>, PoisonError<Vec<&Package>>> {
let mut results = vec![];
if let Some(p) = self.packages.get(query) {
results.push(p)
}
self.packages.iter().for_each(|(k, v)| {
let results = Mutex::new(results);
self.packages.par_iter().for_each(|(k, v)| {
if k.contains(query) {
results.push(v);
if let Ok(mut r) = results.lock() {
r.push(v);
}
}
});
results
let results = results.into_inner()?;
Ok(results)
}
pub fn search_all(&self, query: &str) -> Vec<&Package> {
pub fn search_all(&self, query: &str) -> Result<Vec<&Package>, PoisonError<Vec<&Package>>> {
let mut results = vec![];
if let Some(p) = self.packages.get(query) {
results.push(p)
}
self.packages.iter().for_each(|(k, v)| {
let results = Mutex::new(results);
self.packages.par_iter().for_each(|(k, v)| {
if k.contains(query)
|| v.description.contains(query)
|| v.long_description.contains(query)
{
results.push(v);
if let Ok(mut r) = results.lock() {
r.push(v);
}
}
});
results
let results = results.into_inner()?;
Ok(results)
}
}