No longer refcount rodeo to avoid redundant serialization
This commit is contained in:
parent
f0fa985f8a
commit
2f2fdf9056
2 changed files with 47 additions and 54 deletions
|
@ -84,7 +84,7 @@ impl Manager {
|
||||||
let index_manager = self.clone();
|
let index_manager = self.clone();
|
||||||
move || {
|
move || {
|
||||||
let index = index_manager.index.read().unwrap();
|
let index = index_manager.index.read().unwrap();
|
||||||
index.browser.browse(virtual_path)
|
index.browser.browse(&index.strings, virtual_path)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -96,7 +96,7 @@ impl Manager {
|
||||||
let index_manager = self.clone();
|
let index_manager = self.clone();
|
||||||
move || {
|
move || {
|
||||||
let index = index_manager.index.read().unwrap();
|
let index = index_manager.index.read().unwrap();
|
||||||
index.browser.flatten(virtual_path)
|
index.browser.flatten(&index.strings, virtual_path)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -180,48 +180,43 @@ impl Manager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Default, Serialize, Deserialize)]
|
||||||
pub struct Index {
|
pub struct Index {
|
||||||
|
pub strings: ThreadedRodeo,
|
||||||
pub browser: browser::Browser,
|
pub browser: browser::Browser,
|
||||||
pub collection: collection::Collection,
|
pub collection: collection::Collection,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Index {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
browser: browser::Browser::new(Arc::default()),
|
|
||||||
collection: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Builder {
|
pub struct Builder {
|
||||||
|
strings: ThreadedRodeo,
|
||||||
browser_builder: browser::Builder,
|
browser_builder: browser::Builder,
|
||||||
collection_builder: collection::Builder,
|
collection_builder: collection::Builder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let strings = Arc::new(ThreadedRodeo::new());
|
|
||||||
Self {
|
Self {
|
||||||
browser_builder: browser::Builder::new(strings),
|
strings: ThreadedRodeo::new(),
|
||||||
|
browser_builder: browser::Builder::default(),
|
||||||
collection_builder: collection::Builder::default(),
|
collection_builder: collection::Builder::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_directory(&mut self, directory: scanner::Directory) {
|
pub fn add_directory(&mut self, directory: scanner::Directory) {
|
||||||
self.browser_builder.add_directory(directory);
|
self.browser_builder
|
||||||
|
.add_directory(&mut self.strings, directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_song(&mut self, song: scanner::Song) {
|
pub fn add_song(&mut self, song: scanner::Song) {
|
||||||
self.browser_builder.add_song(&song);
|
self.browser_builder.add_song(&mut self.strings, &song);
|
||||||
self.collection_builder.add_song(song);
|
self.collection_builder.add_song(song);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Index {
|
pub fn build(mut self) -> Index {
|
||||||
Index {
|
Index {
|
||||||
browser: self.browser_builder.build(),
|
browser: self.browser_builder.build(&mut self.strings),
|
||||||
collection: self.collection_builder.build(),
|
collection: self.collection_builder.build(),
|
||||||
|
strings: self.strings,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -236,12 +231,12 @@ impl Default for Builder {
|
||||||
pub(self) struct PathID(lasso2::Spur);
|
pub(self) struct PathID(lasso2::Spur);
|
||||||
|
|
||||||
pub(self) trait InternPath {
|
pub(self) trait InternPath {
|
||||||
fn get_or_intern(self, strings: &mut Arc<ThreadedRodeo>) -> Option<PathID>;
|
fn get_or_intern(self, strings: &mut ThreadedRodeo) -> Option<PathID>;
|
||||||
fn get(self, strings: &Arc<ThreadedRodeo>) -> Option<PathID>;
|
fn get(self, strings: &ThreadedRodeo) -> Option<PathID>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: AsRef<Path>> InternPath for P {
|
impl<P: AsRef<Path>> InternPath for P {
|
||||||
fn get_or_intern(self, strings: &mut Arc<ThreadedRodeo>) -> Option<PathID> {
|
fn get_or_intern(self, strings: &mut ThreadedRodeo) -> Option<PathID> {
|
||||||
let id = self
|
let id = self
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.as_os_str()
|
.as_os_str()
|
||||||
|
@ -254,7 +249,7 @@ impl<P: AsRef<Path>> InternPath for P {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(self, strings: &Arc<ThreadedRodeo>) -> Option<PathID> {
|
fn get(self, strings: &ThreadedRodeo) -> Option<PathID> {
|
||||||
let id = self
|
let id = self
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.as_os_str()
|
.as_os_str()
|
||||||
|
|
|
@ -3,7 +3,6 @@ use std::{
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use lasso2::ThreadedRodeo;
|
use lasso2::ThreadedRodeo;
|
||||||
|
@ -21,24 +20,28 @@ pub enum File {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct Browser {
|
pub struct Browser {
|
||||||
strings: Arc<ThreadedRodeo>,
|
|
||||||
directories: HashMap<PathID, Vec<storage::File>>,
|
directories: HashMap<PathID, Vec<storage::File>>,
|
||||||
flattened: Trie<lasso2::Spur>,
|
flattened: Trie<lasso2::Spur>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Browser {
|
impl Default for Browser {
|
||||||
pub fn new(strings: Arc<ThreadedRodeo>) -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
strings,
|
directories: HashMap::default(),
|
||||||
directories: HashMap::new(),
|
|
||||||
flattened: TrieBuilder::new().build(),
|
flattened: TrieBuilder::new().build(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn browse<P: AsRef<Path>>(&self, virtual_path: P) -> Result<Vec<File>, Error> {
|
impl Browser {
|
||||||
|
pub fn browse<P: AsRef<Path>>(
|
||||||
|
&self,
|
||||||
|
strings: &ThreadedRodeo,
|
||||||
|
virtual_path: P,
|
||||||
|
) -> Result<Vec<File>, Error> {
|
||||||
let path_id = virtual_path
|
let path_id = virtual_path
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.get(&self.strings)
|
.get(strings)
|
||||||
.ok_or_else(|| Error::DirectoryNotFound(virtual_path.as_ref().to_owned()))?;
|
.ok_or_else(|| Error::DirectoryNotFound(virtual_path.as_ref().to_owned()))?;
|
||||||
|
|
||||||
let Some(files) = self.directories.get(&path_id) else {
|
let Some(files) = self.directories.get(&path_id) else {
|
||||||
|
@ -52,7 +55,7 @@ impl Browser {
|
||||||
storage::File::Directory(p) => p,
|
storage::File::Directory(p) => p,
|
||||||
storage::File::Song(p) => p,
|
storage::File::Song(p) => p,
|
||||||
};
|
};
|
||||||
let path = Path::new(OsStr::new(self.strings.resolve(&path_id.0))).to_owned();
|
let path = Path::new(OsStr::new(strings.resolve(&path_id.0))).to_owned();
|
||||||
match f {
|
match f {
|
||||||
storage::File::Directory(_) => File::Directory(path),
|
storage::File::Directory(_) => File::Directory(path),
|
||||||
storage::File::Song(_) => File::Song(path),
|
storage::File::Song(_) => File::Song(path),
|
||||||
|
@ -61,12 +64,16 @@ impl Browser {
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flatten<P: AsRef<Path>>(&self, virtual_path: P) -> Result<Vec<PathBuf>, Error> {
|
pub fn flatten<P: AsRef<Path>>(
|
||||||
|
&self,
|
||||||
|
strings: &ThreadedRodeo,
|
||||||
|
virtual_path: P,
|
||||||
|
) -> Result<Vec<PathBuf>, Error> {
|
||||||
let path_components = virtual_path
|
let path_components = virtual_path
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.components()
|
.components()
|
||||||
.map(|c| c.as_os_str().to_str().unwrap_or_default())
|
.map(|c| c.as_os_str().to_str().unwrap_or_default())
|
||||||
.filter_map(|c| self.strings.get(c))
|
.filter_map(|c| strings.get(c))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if !self.flattened.is_prefix(&path_components) {
|
if !self.flattened.is_prefix(&path_components) {
|
||||||
|
@ -78,7 +85,7 @@ impl Browser {
|
||||||
.predictive_search(path_components)
|
.predictive_search(path_components)
|
||||||
.map(|c: Vec<_>| -> PathBuf {
|
.map(|c: Vec<_>| -> PathBuf {
|
||||||
c.into_iter()
|
c.into_iter()
|
||||||
.map(|s| self.strings.resolve(&s))
|
.map(|s| strings.resolve(&s))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(std::path::MAIN_SEPARATOR_STR)
|
.join(std::path::MAIN_SEPARATOR_STR)
|
||||||
.into()
|
.into()
|
||||||
|
@ -87,29 +94,21 @@ impl Browser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct Builder {
|
pub struct Builder {
|
||||||
strings: Arc<ThreadedRodeo>,
|
|
||||||
directories: HashMap<PathID, Vec<storage::File>>,
|
directories: HashMap<PathID, Vec<storage::File>>,
|
||||||
flattened: TrieBuilder<lasso2::Spur>,
|
flattened: TrieBuilder<lasso2::Spur>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Builder {
|
impl Builder {
|
||||||
pub fn new(strings: Arc<ThreadedRodeo>) -> Self {
|
pub fn add_directory(&mut self, strings: &mut ThreadedRodeo, directory: scanner::Directory) {
|
||||||
Self {
|
let Some(path_id) = directory.virtual_path.get_or_intern(strings) else {
|
||||||
strings,
|
|
||||||
directories: HashMap::default(),
|
|
||||||
flattened: TrieBuilder::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_directory(&mut self, directory: scanner::Directory) {
|
|
||||||
let Some(path_id) = directory.virtual_path.get_or_intern(&mut self.strings) else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(parent_id) = directory
|
let Some(parent_id) = directory
|
||||||
.virtual_parent
|
.virtual_parent
|
||||||
.and_then(|p| p.get_or_intern(&mut self.strings))
|
.and_then(|p| p.get_or_intern(strings))
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -122,12 +121,12 @@ impl Builder {
|
||||||
.push(storage::File::Directory(path_id));
|
.push(storage::File::Directory(path_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_song(&mut self, song: &scanner::Song) {
|
pub fn add_song(&mut self, strings: &mut ThreadedRodeo, song: &scanner::Song) {
|
||||||
let Some(path_id) = (&song.virtual_path).get_or_intern(&mut self.strings) else {
|
let Some(path_id) = (&song.virtual_path).get_or_intern(strings) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(parent_id) = (&song.virtual_parent).get_or_intern(&mut self.strings) else {
|
let Some(parent_id) = (&song.virtual_parent).get_or_intern(strings) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -139,20 +138,19 @@ impl Builder {
|
||||||
self.flattened.push(
|
self.flattened.push(
|
||||||
song.virtual_path
|
song.virtual_path
|
||||||
.components()
|
.components()
|
||||||
.map(|c| self.strings.get_or_intern(c.as_os_str().to_str().unwrap()))
|
.map(|c| strings.get_or_intern(c.as_os_str().to_str().unwrap()))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(mut self) -> Browser {
|
pub fn build(mut self, strings: &mut ThreadedRodeo) -> Browser {
|
||||||
for directory in self.directories.values_mut() {
|
for directory in self.directories.values_mut() {
|
||||||
directory.sort_by_key(|f| match f {
|
directory.sort_by_key(|f| match f {
|
||||||
storage::File::Directory(p) => self.strings.resolve(&p.0),
|
storage::File::Directory(p) => strings.resolve(&p.0),
|
||||||
storage::File::Song(p) => self.strings.resolve(&p.0),
|
storage::File::Song(p) => strings.resolve(&p.0),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Browser {
|
Browser {
|
||||||
strings: self.strings,
|
|
||||||
directories: self.directories,
|
directories: self.directories,
|
||||||
flattened: self.flattened.build(),
|
flattened: self.flattened.build(),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue