Unified · Split
| @@ -1,4 +1,7 @@ | |||
| 1 | use crate::{data::output, find, FindExt}; | 1 | use crate::{ |
| 2 | data::{output, output::ChunkId}, | ||
| 3 | find, FindExt, | ||
| 4 | }; | ||
| 2 | use dashmap::DashSet; | 5 | use dashmap::DashSet; |
| 3 | use git_features::{parallel, progress::Progress}; | 6 | use git_features::{parallel, progress::Progress}; |
| 4 | use git_hash::{oid, ObjectId}; | 7 | use git_hash::{oid, ObjectId}; |
| @@ -29,7 +32,7 @@ pub fn from_objects_iter<Find, Iter, Oid, Cache>( · 24 unmodified lines | |||
| 29 | input_object_expansion, | 32 | input_object_expansion, |
| 30 | chunk_size, | 33 | chunk_size, |
| 31 | }: Options, | 34 | }: Options, |
| 32 | ) -> impl Iterator<Item = Result<Vec<output::Count>, Error<find::existing::Error<Find::Error>>>> | 35 | ) -> impl Iterator<Item = Result<(ChunkId, Vec<output::Count>), Error<find::existing::Error<Find::Error>>>> |
| 33 | + parallel::reduce::Finalize<Reduce = reduce::Statistics<Error<find::existing::Error<Find::Error>>>> | 36 | + parallel::reduce::Finalize<Reduce = reduce::Statistics<Error<find::existing::Error<Find::Error>>>> |
| 34 | where | 37 | where |
| 35 | Find: crate::Find + Clone + Send + Sync + 'static, | 38 | Find: crate::Find + Clone + Send + Sync + 'static, |
| @@ -48,7 +51,8 @@ where · 12 unmodified lines | |||
| 48 | let chunks = util::Chunks { | 51 | let chunks = util::Chunks { |
| 49 | iter: objects, | 52 | iter: objects, |
| 50 | size: chunk_size, | 53 | size: chunk_size, |
| 51 | }; | 54 | } |
| 55 | .enumerate(); | ||
| 52 | let seen_objs = Arc::new(dashmap::DashSet::<ObjectId>::new()); | 56 | let seen_objs = Arc::new(dashmap::DashSet::<ObjectId>::new()); |
| 53 | let progress = Arc::new(parking_lot::Mutex::new(progress)); | 57 | let progress = Arc::new(parking_lot::Mutex::new(progress)); |
| 54 | 58 | ||
| @@ -72,7 +76,7 @@ where · 17 unmodified lines | |||
| 72 | }, | 76 | }, |
| 73 | { | 77 | { |
| 74 | let seen_objs = Arc::clone(&seen_objs); | 78 | let seen_objs = Arc::clone(&seen_objs); |
| 75 | move |oids: Vec<Oid>, (buf1, buf2, cache, progress)| { | 79 | move |(chunk_id, oids): (ChunkId, Vec<Oid>), (buf1, buf2, cache, progress)| { |
| 76 | use ObjectExpansion::*; | 80 | use ObjectExpansion::*; |
| 77 | let mut out = Vec::new(); | 81 | let mut out = Vec::new(); |
| 78 | let mut tree_traversal_state = git_traverse::tree::breadthfirst::State::default(); | 82 | let mut tree_traversal_state = git_traverse::tree::breadthfirst::State::default(); |
| @@ -243,7 +247,7 @@ where · 164 unmodified lines | |||
| 243 | AsIs => push_obj_count_unique(&mut out, seen_objs, id, &obj, progress, stats, false), | 247 | AsIs => push_obj_count_unique(&mut out, seen_objs, id, &obj, progress, stats, false), |
| 244 | } | 248 | } |
| 245 | } | 249 | } |
| 246 | Ok((out, outcome)) | 250 | Ok((chunk_id, out, outcome)) |
| 247 | } | 251 | } |
| 248 | }, | 252 | }, |
| 249 | reduce::Statistics::default(), | 253 | reduce::Statistics::default(), |
| @@ -525,7 +529,7 @@ pub use types::{Error, ObjectExpansion, Options, Outcome}; · 275 unmodified lines | |||
| 525 | 529 | ||
| 526 | mod reduce { | 530 | mod reduce { |
| 527 | use super::Outcome; | 531 | use super::Outcome; |
| 528 | use crate::data::output; | 532 | use crate::data::{output, output::ChunkId}; |
| 529 | use git_features::parallel; | 533 | use git_features::parallel; |
| 530 | use std::marker::PhantomData; | 534 | use std::marker::PhantomData; |
| 531 | 535 | ||
| @@ -544,16 +548,16 @@ mod reduce { · 12 unmodified lines | |||
| 544 | } | 548 | } |
| 545 | 549 | ||
| 546 | impl<Error> parallel::Reduce for Statistics<Error> { | 550 | impl<Error> parallel::Reduce for Statistics<Error> { |
| 547 | type Input = Result<(Vec<output::Count>, Outcome), Error>; | 551 | type Input = Result<(ChunkId, Vec<output::Count>, Outcome), Error>; |
| 548 | type FeedProduce = Vec<output::Count>; | 552 | type FeedProduce = (ChunkId, Vec<output::Count>); |
| 549 | type Output = Outcome; | 553 | type Output = Outcome; |
| 550 | type Error = Error; | 554 | type Error = Error; |
| 551 | 555 | ||
| 552 | fn feed(&mut self, item: Self::Input) -> Result<Self::FeedProduce, Self::Error> { | 556 | fn feed(&mut self, item: Self::Input) -> Result<Self::FeedProduce, Self::Error> { |
| 553 | item.map(|(counts, mut stats)| { | 557 | item.map(|(chunk_id, counts, mut stats)| { |
| 554 | stats.total_objects = counts.len(); | 558 | stats.total_objects = counts.len(); |
| 555 | self.total.aggregate(stats); | 559 | self.total.aggregate(stats); |
| 556 | counts | 560 | (chunk_id, counts) |
| 557 | }) | 561 | }) |
| 558 | } | 562 | } |
| 559 | 563 | ||
| @@ -1,4 +1,7 @@ | |||
| 1 | use crate::{data::output, find, FindExt}; | 1 | use crate::{ |
| 2 | data::{output, output::ChunkId}, | ||
| 3 | find, FindExt, | ||
| 4 | }; | ||
| 2 | use git_features::{parallel, progress::Progress}; | 5 | use git_features::{parallel, progress::Progress}; |
| 3 | use std::sync::Arc; | 6 | use std::sync::Arc; |
| 4 | 7 | ||
| @@ -185,9 +188,6 @@ mod reduce { · 180 unmodified lines | |||
| 185 | mod types { | 188 | mod types { |
| 186 | use crate::data::output::entry; | 189 | use crate::data::output::entry; |
| 187 | 190 | ||
| 188 | /// A counter for chunks to be able to put them back into original order later. | ||
| 189 | pub type ChunkId = usize; | ||
| 190 | |||
| 191 | /// Information gathered during the run of [`from_counts_iter()`][super::from_counts_iter()]. | 191 | /// Information gathered during the run of [`from_counts_iter()`][super::from_counts_iter()]. |
| 192 | #[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] | 192 | #[derive(Default, PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] |
| 193 | #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] | 193 | #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] |
| @@ -248,4 +248,4 @@ mod types { · 54 unmodified lines | |||
| 248 | NewEntry(#[from] entry::Error), | 248 | NewEntry(#[from] entry::Error), |
| 249 | } | 249 | } |
| 250 | } | 250 | } |
| 251 | pub use types::{ChunkId, Error, Options, Outcome}; | 251 | pub use types::{Error, Options, Outcome}; |
| @@ -1,5 +1,7 @@ | |||
| 1 | use std::cmp::Ordering; | 1 | use std::{cmp::Ordering, collections::BTreeMap}; |
| 2 | use std::collections::BTreeMap; | 2 | |
| 3 | /// A counter for chunks to be able to put them back into original order later. | ||
| 4 | pub type ChunkId = usize; | ||
| 3 | 5 | ||
| 4 | /// An iterator which olds iterated items with a **sequential** ID starting at 0 long enough to dispense them in order. | 6 | /// An iterator which olds iterated items with a **sequential** ID starting at 0 long enough to dispense them in order. |
| 5 | /// | 7 | /// |
| @@ -8,14 +10,14 @@ use std::collections::BTreeMap; · 2 unmodified lines | |||
| 8 | pub struct InOrderIter<T, I> { | 10 | pub struct InOrderIter<T, I> { |
| 9 | /// The iterator yielding the out-of-order elements we are to yield in order. | 11 | /// The iterator yielding the out-of-order elements we are to yield in order. |
| 10 | pub inner: I, | 12 | pub inner: I, |
| 11 | store: BTreeMap<usize, T>, | 13 | store: BTreeMap<ChunkId, T>, |
| 12 | next_chunk: usize, | 14 | next_chunk: ChunkId, |
| 13 | is_done: bool, | 15 | is_done: bool, |
| 14 | } | 16 | } |
| 15 | 17 | ||
| 16 | impl<T, E, I> From<I> for InOrderIter<T, I> | 18 | impl<T, E, I> From<I> for InOrderIter<T, I> |
| 17 | where | 19 | where |
| 18 | I: Iterator<Item = Result<(usize, T), E>>, | 20 | I: Iterator<Item = Result<(ChunkId, T), E>>, |
| 19 | { | 21 | { |
| 20 | fn from(iter: I) -> Self { | 22 | fn from(iter: I) -> Self { |
| 21 | InOrderIter { | 23 | InOrderIter { |
| @@ -29,7 +31,7 @@ where · 7 unmodified lines | |||
| 29 | 31 | ||
| 30 | impl<T, E, I> Iterator for InOrderIter<T, I> | 32 | impl<T, E, I> Iterator for InOrderIter<T, I> |
| 31 | where | 33 | where |
| 32 | I: Iterator<Item = Result<(usize, T), E>>, | 34 | I: Iterator<Item = Result<(ChunkId, T), E>>, |
| 33 | { | 35 | { |
| 34 | type Item = Result<T, E>; | 36 | type Item = Result<T, E>; |
| 35 | 37 | ||
| @@ -12,4 +12,4 @@ pub use entry::Entry; · 11 unmodified lines | |||
| 12 | pub mod bytes; | 12 | pub mod bytes; |
| 13 | 13 | ||
| 14 | mod in_order; | 14 | mod in_order; |
| 15 | pub use in_order::InOrderIter; | 15 | pub use in_order::{ChunkId, InOrderIter}; |
| @@ -50,6 +50,7 @@ mod count_and_entries { · 49 unmodified lines | |||
| 50 | data::output::{db, DbKind}, | 50 | data::output::{db, DbKind}, |
| 51 | hex_to_id, | 51 | hex_to_id, |
| 52 | }; | 52 | }; |
| 53 | use git_odb::data::output::InOrderIter; | ||
| 53 | 54 | ||
| 54 | #[test] | 55 | #[test] |
| 55 | fn traversals() -> crate::Result { | 56 | fn traversals() -> crate::Result { |
| @@ -153,8 +154,7 @@ mod count_and_entries { · 97 unmodified lines | |||
| 153 | ..Default::default() | 154 | ..Default::default() |
| 154 | }, | 155 | }, |
| 155 | ); | 156 | ); |
| 156 | let counts: Vec<_> = counts_iter | 157 | let counts: Vec<_> = InOrderIter::from(counts_iter.by_ref()) |
| 157 | .by_ref() | ||
| 158 | .collect::<Result<Vec<_>, _>>()? | 158 | .collect::<Result<Vec<_>, _>>()? |
| 159 | .into_iter() | 159 | .into_iter() |
| 160 | .flatten() | 160 | .flatten() |
| @@ -1,5 +1,6 @@ | |||
| 1 | use crate::OutputFormat; | 1 | use crate::OutputFormat; |
| 2 | use anyhow::bail; | 2 | use anyhow::bail; |
| 3 | use git_repository::odb::data::output::InOrderIter; | ||
| 3 | use git_repository::{ | 4 | use git_repository::{ |
| 4 | hash, | 5 | hash, |
| 5 | hash::ObjectId, | 6 | hash::ObjectId, |
| @@ -117,7 +118,7 @@ where · 111 unmodified lines | |||
| 117 | let counts = { | 118 | let counts = { |
| 118 | let mut progress = progress.add_child("counting"); | 119 | let mut progress = progress.add_child("counting"); |
| 119 | progress.init(None, progress::count("objects")); | 120 | progress.init(None, progress::count("objects")); |
| 120 | let mut counts_iter = pack::data::output::count::from_objects_iter( | 121 | let mut in_order_counts_iter = InOrderIter::from(pack::data::output::count::from_objects_iter( |
| 121 | Arc::clone(&db), | 122 | Arc::clone(&db), |
| 122 | pack::cache::lru::StaticLinkedList::<64>::default, | 123 | pack::cache::lru::StaticLinkedList::<64>::default, |
| 123 | input, | 124 | input, |
| @@ -127,9 +128,9 @@ where · 3 unmodified lines | |||
| 127 | chunk_size, | 128 | chunk_size, |
| 128 | input_object_expansion: expansion.into(), | 129 | input_object_expansion: expansion.into(), |
| 129 | }, | 130 | }, |
| 130 | ); | 131 | )); |
| 131 | let mut counts = Vec::new(); | 132 | let mut counts = Vec::new(); |
| 132 | for c in counts_iter.by_ref() { | 133 | for c in in_order_counts_iter.by_ref() { |
| 133 | if interrupt::is_triggered() { | 134 | if interrupt::is_triggered() { |
| 134 | bail!("Cancelled by user") | 135 | bail!("Cancelled by user") |
| 135 | } | 136 | } |
| @@ -137,7 +138,7 @@ where · 1 unmodified line | |||
| 137 | progress.inc_by(c.len()); | 138 | progress.inc_by(c.len()); |
| 138 | counts.extend(c.into_iter()); | 139 | counts.extend(c.into_iter()); |
| 139 | } | 140 | } |
| 140 | stats.counts = counts_iter.finalize()?; | 141 | stats.counts = in_order_counts_iter.inner.finalize()?; |
| 141 | progress.show_throughput(start); | 142 | progress.show_throughput(start); |
| 142 | counts.shrink_to_fit(); | 143 | counts.shrink_to_fit(); |
| 143 | counts | 144 | counts |