Simplification of missing context repairs
Dependencies
- [2]
3KHT2M5ZFixing alive vertex detection in down contexts too - [3]
L7S3MNQ4When repairing down contexts, do not follow deleted edges if there is an block+alive outgoing edge - [4]
L4EZSH6BFixing zombie conflicts: known was computed on the wrong thing - [5]
XNY6VDZSFixing a bug in context repairs - [6]
PNJL5TPZVersion bump - [7]
X6EUOQ5OAdding more debugging checks in `pijul debug` - [8]
T7YIRFWDRaising an error on corrupt patches rather than panicking - [9]
PNKAJTFZFixing a caching mistake in find_alive - [10]
X7OHUPL5Fixing a bug in unrecord, and fixing the tests - [11]
YTQS4ES3Fixing a parsing problem (related to permissions), and the associated permissions - [12]
QQZNSB26Permission update (after #X243) - [13]
ATZ3BWSEFixing the double-deletion of repairs for folder edges - [14]
SFQBWL6PImproving unrecord performance (8 times faster on my tests) - [15]
AD6M434Ofind_alive performance (matters a lot for unrecord) - [16]
I52XSRUHMassive cleanup, and simplification - [17]
NMX52UOGFixing the "invalid change" errors - [18]
XGH2A4BOFormatting/Cleanup - [19]
RSFUX6MLCorrect find_alive cache system - [20]
YN63NUZOSanakirja 1.0 - [21]
ZJWCPRMHFixing known patches in deleted contexts - [22]
5FI6SBEZRe-implement change printing and parsing - [23]
3CFU4DQNFixing a bug in unrecord, where a patch creating an undeletion conflict would not be properly unrecorded - [24]
FAOGX7G3Outputting the repo after the last Git import - [25]
TNN56XYKlibpijul alpha.43 - [26]
CD6XDYOHFixing unrecord - [27]
IACED7RWtext_encoding module - [28]
7NSTS6PKAdding a cache in find_alive to improve performance in some cases - [29]
2BKYJ2JMFixing a bug introduced by the recent refactoring - [30]
HMMMKONLFixing alive vertices - [31]
CCLLB7OIUpgrading to Sanakirja 0.15 + version bump - [32]
HDGRZISMVersion updates - [33]
EEBKW7VTKeys and identities - [34]
UEWNF7X3Detecting "self-solving" zombie folder (or file) conflicts - [35]
JQR4Q2NKFixing a cache miss/unwrap in find_alive for vertices that have been split during insertion - [36]
QL6K2ZM3Tags - [37]
ZCPGCKKYFixing a bug where zombie files could be deleted by unrecord, but not their contents - [38]
MQ6ERQ43Bug fixes when unrecording a patch that introduced zombie files - [39]
3I4PAA2AMaking a few types and methods public - [40]
GHO6DWPIRefactoring iterators - [41]
SXEYMYF7Fixing the bad changes in history (unfortunately, by rebooting). - [42]
VO5OQW4WRemoving anyhow in libpijul - [43]
X243Z3Y5Recording only the required metadata (can even be changed later!) - [44]
I24UEJQLVarious post-fire fixes - [45]
T7CAACFBFixing zombie conflicts (some vertices were wrongly detected alive) - [46]
KDF6FJRVbigger clippy refactors - [47]
N3X5YP7PAdding tag/txn.rs, now that the parser allows it - [48]
WUNYO4QBForgot to add EdgeFlags::df() - [49]
WZVCLZKYaddress clippy lints - [50]
FABI77LLCleaning up the cache in missing_context and find_alive - [51]
RRCSHAYZFormatting - [52]
WBTE6H6VSolving a conflict - [53]
6YMDOZIBRefactoring apply - [54]
JACZYXK4Fixing a bug in unrecord - [55]
ZDK3GNDBTag transactions (including a massive refactoring of errors)
Change contents
- file deletion: find_alive.rs find_alive.rs[10.198146]→[10.1295:1310](∅→∅),[10.1310]→[10.763306:763306](∅→∅),[10.198146]→[10.763290:763305](∅→∅),[10.763305]→[10.763306:763306](∅→∅)
use crate::pristine::*;use crate::{HashMap, HashSet};// use std::collections::hash_map::Entry;/// The following is an unrolled DFS, where each alive vertex is/// inserted into each "alive set" along the current path (which is/// recognised by looking at the visited vertices on the stack).pub(crate) fn find_alive_down<'a, T: GraphTxnT>(txn: &T,channel: &T::Graph,vertex0: Vertex<ChangeId>,cache: &'a mut HashMap<Vertex<ChangeId>, Option<HashSet<Vertex<ChangeId>>>>,) -> Result<&'a Option<HashSet<Vertex<ChangeId>>>, BlockError<T::GraphError>> {let mut stack: Vec<(_, Option<HashSet<Vertex<ChangeId>>>)> = vec![(SerializedEdge::empty(vertex0.start_pos(), ChangeId::ROOT),None,)];let mut visited = HashSet::default();while let Some((elt, alive)) = stack.pop() {if let Some(alive) = alive {// We've gone through all the descendants, put this in the// cache.let vertex = txn.find_block(&channel, elt.dest())?;if stack.is_empty() {// Done!cache.insert(*vertex, Some(alive.clone()));assert_eq!(vertex0.start_pos(), vertex.start_pos());return Ok(cache.get(&vertex).unwrap());}continue;}let vertex = txn.find_block(&channel, elt.dest())?;if let Some(c) = cache.get(vertex) {for st in stack.iter_mut() {if let Some(ref mut st) = st.1 {if let Some(c) = c {st.extend(c.iter().cloned());} else {st.insert(*vertex);}}}continue;}// A `None` in the cache means that the vertex// itself (the cache key) is alive.debug!("elt = {:?}, vertex = {:?}", elt, vertex);let elt_index = stack.len();for v in iter_adj_all(txn, &channel, *vertex)? {let v = v?;if v.flag().contains(EdgeFlags::FOLDER) {continue;}debug!("v = {:?}", v);if v.flag().contains(EdgeFlags::PARENT) {if (v.flag().contains(EdgeFlags::BLOCK) || vertex.is_empty())&& !v.flag().contains(EdgeFlags::DELETED)&& !v.flag().contains(EdgeFlags::PSEUDO){if *vertex == vertex0 {// vertex0 is alive.stack.truncate(elt_index);let (_, alive) = stack.pop().unwrap();let alive = alive.unwrap();assert!(alive.is_empty());cache.insert(vertex0, None);return Ok(cache.get(&vertex0).unwrap());} else {// vertex is alive, insert it into all the// alive sets on the current DFS path// (including `vertex`).for st in stack.iter_mut() {if let Some(ref mut st) = st.1 {st.insert(*vertex);}}stack.truncate(elt_index);break;}}} else if v.flag().contains(EdgeFlags::DELETED) {if !has_alive_blocks {stack.push((*v, None))}}}}unreachable!()}pub fn find_alive_up<'a, T: GraphTxnT>(txn: &T,channel: &T::Graph,files: &mut HashSet<Vertex<ChangeId>>,vertex0: Vertex<ChangeId>,change: ChangeId,cache: &'a mut HashMap<Vertex<ChangeId>,(Option<HashSet<Vertex<ChangeId>>>, HashSet<Vertex<ChangeId>>),>,) -> Result<&'a Option<HashSet<Vertex<ChangeId>>>, BlockError<T::GraphError>> {debug!("find alive up: {:?}", vertex0);let mut stack: Vec<(_,Option<(HashSet<Vertex<ChangeId>>, HashSet<Vertex<ChangeId>>)>,)> = vec![(SerializedEdge::empty(vertex0.end_pos(), ChangeId::ROOT),None,)];let mut visited = HashSet::default();while let Some((elt, alive)) = stack.pop() {debug!("pop {:?} {:?}", elt, alive);if elt.dest().is_root() {continue;}if let Some((alive, files_)) = alive {let vertex = *txn.find_block_end(&channel, elt.dest())?;if stack.is_empty() {// Done!cache.insert(vertex, (Some(alive), files_));assert_eq!(vertex.end_pos(), vertex0.end_pos());return Ok(&cache.get(&vertex).unwrap().0);}continue;}let vertex = *txn.find_block_end(&channel, elt.dest())?;debug!("vertex = {:?}", vertex);if let Some((c, d)) = cache.get(&vertex) {debug!("Cached: {:?} {:?}", c, d);for st in stack.iter_mut() {if let Some((ref mut al, ref mut f)) = st.1 {if let Some(c) = c {al.extend(c.iter().cloned());} else {al.insert(vertex);}f.extend(d.iter().cloned());files.extend(d.iter().cloned());}}continue;}stack.push((elt, Some((HashSet::new(), HashSet::new()))));continue;}if !visited.insert(elt.dest()) {}if visited.insert(elt.dest()) {stack.push((elt, Some((HashSet::new(), HashSet::new()))));debug!("find_alive_up: elt = {:?}, vertex = {:?}", elt, vertex);let elt_index = stack.len();let mut is_file = false; // Is this the "inode" vertex of a file?let mut it = iter_adj_all(txn, &channel, vertex)?;while let Some(v) = it.next() {let v = v?;debug!("find_alive_up: v = {:?} change = {:?}", v, change);if v.flag() & EdgeFlags::pseudof() == EdgeFlags::PSEUDO {continue;}if !v.flag().is_parent() {is_file |= !v.flag().is_folder();continue;}if !v.flag().is_deleted() {if v.flag().is_folder() {for e in it {let e = e?;is_file |= !e.flag().intersects(EdgeFlags::parent_folder())}if is_file {debug!("is alive + is file {:?}", vertex);for st in stack.iter_mut() {if let Some((ref mut al, ref mut fi)) = st.1 {al.insert(vertex);fi.insert(vertex);}}files.insert(vertex);}break;} else if v.flag().is_block() || vertex.is_empty() {debug!("is alive {:?}", vertex);for st in stack.iter_mut() {if let Some((ref mut st, _)) = st.1 {st.insert(vertex);}}stack.truncate(elt_index);break;}}if v.flag().is_folder() {if is_file {debug!("is pseudo-alive folder {:?}", vertex);for st in stack.iter_mut() {if let Some((ref mut al, ref mut fi)) = st.1 {al.insert(vertex);fi.insert(vertex);}}files.insert(vertex);}break;} else {stack.push((*v, None))}}}unreachable!()}debug!("is_file = {:?}", is_file);debug!("just push");for e in it {let e = e?;is_file |= !e.flag().intersects(EdgeFlags::parent_folder())}debug!("{:?} is a file ? {:?}", vertex, is_file);if v.flag().is_block() && vertex == vertex0 {// vertex0 is alive.stack.truncate(elt_index);let (_, alive) = stack.pop().unwrap();let (alive, _) = alive.unwrap();assert!(alive.is_empty());cache.insert(vertex0, (None, HashSet::new()));return Ok(&cache.get(&vertex0).unwrap().0);}debug!("is_file {:?} {:?}", is_file, !v.flag().is_folder());debug!("stack = {:?}", stack);// Each element of the stack is a pair of (1) an edge pointing to// the position we want to visit next and (2) optionally, a set of// alive vertices found until now.// Every time we find an alive vertex, we add it to the sets of// each element on the path to that vertex.} else {stack.push((*v, None));} else if v.flag().contains(EdgeFlags::BLOCK) {has_alive_blocks = true;stack.push((*v, None));let mut has_alive_blocks = false;} else {if !visited.insert(elt.dest()) {continue;}stack.push((elt, Some(HashSet::new()))); - edit in libpijul/src/unrecord/mod.rs at line 4
use crate::missing_context::*; - replacement in libpijul/src/unrecord/mod.rs at line 206
repair_newvertex_contexts::<T, C>(txn, T::graph_mut(channel), &mut ws, change_id)?; - edit in libpijul/src/unrecord/mod.rs at line 213[10.189]→[10.2074:2154](∅→∅),[10.2308]→[10.2074:2154](∅→∅),[10.9861]→[10.2074:2154](∅→∅),[10.24492]→[10.2074:2154](∅→∅),[10.2074]→[10.2074:2154](∅→∅),[10.2154]→[10.2309:2348](∅→∅),[10.2348]→[10.2179:2287](∅→∅),[10.24529]→[10.2179:2287](∅→∅),[10.2179]→[10.2179:2287](∅→∅)
repair_edges_context(changes,txn,T::graph_mut(channel),&mut ws.apply.missing_context,change_id,n,)? - edit in libpijul/src/unrecord/mod.rs at line 260
crate::apply::repair_zombies(txn, channel, inode)?; - edit in libpijul/src/unrecord/mod.rs at line 359[10.238934]→[10.11603:11677](∅→∅),[10.10183]→[10.238976:238993](∅→∅),[10.11677]→[10.238976:238993](∅→∅),[10.25244]→[10.238976:238993](∅→∅),[10.238976]→[10.238976:238993](∅→∅),[10.238993]→[10.25245:25273](∅→∅),[10.25273]→[10.239023:239047](∅→∅),[10.239023]→[10.239023:239047](∅→∅),[10.239047]→[10.1483:1508](∅→∅),[10.1508]→[10.11678:11724](∅→∅),[10.10237]→[10.239080:239152](∅→∅),[10.11724]→[10.239080:239152](∅→∅),[10.25332]→[10.239080:239152](∅→∅),[10.239080]→[10.239080:239152](∅→∅),[10.239152]→[10.17659:17702](∅→∅),[10.17702]→[10.42:64](∅→∅),[10.42]→[10.42:64](∅→∅),[10.64]→[10.239430:239440](∅→∅),[10.239430]→[10.239430:239440](∅→∅),[10.239440]→[10.65:272](∅→∅),[10.272]→[10.239440:239446](∅→∅),[10.239440]→[10.239440:239446](∅→∅)
fn repair_newvertex_contexts<T: GraphMutTxnT + TreeTxnT, C: ChangeStore>(txn: &mut T,channel: &mut T::Graph,ws: &mut Workspace,change_id: ChangeId,) -> Result<(), UnrecordError<C::Error, T>> {debug!("up = {:#?}", ws.up);for (up, inode) in ws.up.drain() {if !is_alive(txn, channel, &up)? {continue;}crate::missing_context::repair_missing_down_context(txn,channel,&mut ws.apply.missing_context,inode,up,&[up],)?} - edit in libpijul/src/unrecord/mod.rs at line 360[10.239447]→[10.239447:239484](∅→∅),[10.239484]→[10.1509:1552](∅→∅),[10.1552]→[10.17703:17748](∅→∅),[10.17748]→[10.317:349](∅→∅),[10.317]→[10.317:349](∅→∅),[10.349]→[10.8261:8315](∅→∅),[10.1552]→[10.8261:8315](∅→∅),[10.239578]→[10.8261:8315](∅→∅),[10.8315]→[10.239619:239740](∅→∅),[10.239619]→[10.239619:239740](∅→∅),[10.239740]→[10.25375:25422](∅→∅),[10.25422]→[10.17749:17819](∅→∅),[10.3007]→[10.25423:25473](∅→∅),[10.17819]→[10.25423:25473](∅→∅),[10.8385]→[10.25423:25473](∅→∅),[10.25473]→[10.17820:17864](∅→∅),[10.1596]→[10.239908:239932](∅→∅),[10.17864]→[10.239908:239932](∅→∅),[10.239908]→[10.239908:239932](∅→∅),[10.239932]→[10.1597:1681](∅→∅),[10.1681]→[10.240010:240166](∅→∅),[10.240010]→[10.240010:240166](∅→∅),[10.240166]→[10.1682:1709](∅→∅),[10.1709]→[10.240166:240234](∅→∅),[10.240166]→[10.240166:240234](∅→∅),[10.240261]→[10.240261:240305](∅→∅),[10.240305]→[10.10238:10239](∅→∅)
debug!("down = {:#?}", ws.down);for (down, inode) in ws.down.drain() {if !is_alive(txn, channel, &down)? {continue;}for parent in iter_adjacent(txn,channel,down,EdgeFlags::PARENT,EdgeFlags::all() - EdgeFlags::DELETED,)? {let parent = parent?;let parent = txn.find_block_end(channel, parent.dest())?;if !is_alive(txn, channel, parent)? {ws.parents.insert(*parent);}}debug!("parents {:#?}", ws.parents);for up in ws.parents.drain() {crate::missing_context::repair_missing_up_context(txn,channel,&mut ws.apply.missing_context,change_id,inode,up,&[down],)?}}Ok(())} - edit in libpijul/src/unrecord/mod.rs at line 699[10.3885]→[10.3885:3886](∅→∅),[10.3886]→[10.12172:12241](∅→∅),[10.12241]→[10.246914:246948](∅→∅),[10.27114]→[10.246914:246948](∅→∅),[10.246914]→[10.246914:246948](∅→∅),[10.246948]→[10.27115:27143](∅→∅),[10.27143]→[10.246978:247082](∅→∅),[10.246978]→[10.246978:247082](∅→∅),[10.247082]→[10.12242:12288](∅→∅),[10.12288]→[10.461:497](∅→∅),[10.27202]→[10.461:497](∅→∅),[10.497]→[10.19248:19323](∅→∅),[10.27202]→[10.19248:19323](∅→∅),[10.19323]→[10.247175:247205](∅→∅),[10.27263]→[10.247175:247205](∅→∅),[10.247175]→[10.247175:247205](∅→∅),[10.247205]→[10.191:240](∅→∅),[10.240]→[10.247205:247259](∅→∅),[10.247205]→[10.247205:247259](∅→∅),[10.247259]→[10.27264:27338](∅→∅),[10.4024]→[10.247259:247312](∅→∅),[10.247259]→[10.247259:247312](∅→∅),[10.247675]→[10.247675:247825](∅→∅),[10.247825]→[10.356:418](∅→∅),[10.418]→[10.4025:4072](∅→∅),[10.247885]→[10.4025:4072](∅→∅),[10.4072]→[10.247905:247937](∅→∅),[10.247905]→[10.247905:247937](∅→∅),[10.248081]→[10.10099:10170](∅→∅),[10.10170]→[10.3314:3365](∅→∅),[10.3365]→[10.498:535](∅→∅),[10.535]→[10.27339:27385](∅→∅),[10.3365]→[10.27339:27385](∅→∅),[10.10222]→[10.27339:27385](∅→∅),[10.27385]→[10.536:573](∅→∅),[10.573]→[10.248246:248439](∅→∅),[10.10267]→[10.248246:248439](∅→∅),[10.27385]→[10.248246:248439](∅→∅),[10.248246]→[10.248246:248439](∅→∅),[10.62]→[10.4073:4120](∅→∅),[10.248499]→[10.4073:4120](∅→∅),[10.4120]→[10.248739:248783](∅→∅),[10.248739]→[10.248739:248783](∅→∅)
fn repair_edges_context<T: GraphMutTxnT + TreeTxnT, P: ChangeStore>(changes: &P,txn: &mut T,channel: &mut T::Graph,ws: &mut crate::missing_context::Workspace,change_id: ChangeId,n: &EdgeMap<Option<Hash>>,) -> Result<(), UnrecordError<P::Error, T>> {debug!("repair_edges_context");let change_hash: Hash = txn.get_external(&change_id)?.unwrap().into();for e in n.edges.iter() {debug!("repair_edges_context: {:?}", e);assert!(!e.flag.contains(EdgeFlags::PARENT));let intro = internal(txn, &e.introduced_by, change_id)?.unwrap();if e.previous.contains(EdgeFlags::DELETED) {repair_context_deleted(txn,channel,ws,n.inode,intro,|h| changes.knows(&change_hash, &h).unwrap(),&e.reverse(Some(change_hash)),)?} else {let to = internal_pos(txn, &e.to.start_pos(), change_id)?;let to = txn.find_block(channel, to)?;debug!("to = {:?}", to);if !is_alive(txn, channel, to)? {debug!("not alive");continue;}repair_context_nondeleted(txn,channel,ws,n.inode,intro,&e.reverse(Some(change_hash)),)?}}Ok(())} - edit in libpijul/src/pristine/mod.rs at line 1338
let stack_len = stack.len(); - edit in libpijul/src/pristine/mod.rs at line 1353
(&mut stack[stack_len..]).reverse() - edit in libpijul/src/pristine/edge.rs at line 25
pub(crate) fn db() -> Self {Self::DELETED | Self::BLOCK}#[inline] - edit in libpijul/src/missing_context.rs at line 3
use crate::find_alive::*; - edit in libpijul/src/missing_context.rs at line 56[10.697932]→[10.697932:697950](∅→∅),[10.697950]→[10.26444:26445](∅→∅),[10.26445]→[10.698005:698054](∅→∅),[10.698005]→[10.698005:698054](∅→∅),[10.698054]→[10.89079:89100](∅→∅),[10.89100]→[10.698070:698140](∅→∅),[10.698070]→[10.698070:698140](∅→∅),[10.698140]→[10.89101:89129](∅→∅),[10.89129]→[10.698170:698194](∅→∅),[10.698170]→[10.698170:698194](∅→∅),[10.698194]→[10.9450:9475](∅→∅),[10.9475]→[10.698194:698264](∅→∅),[10.698194]→[10.698194:698264](∅→∅),[10.698264]→[10.89130:89177](∅→∅),[10.26488]→[10.698320:698361](∅→∅),[10.89177]→[10.698320:698361](∅→∅),[10.698320]→[10.698320:698361](∅→∅),[10.698361]→[10.43:197](∅→∅),[10.197]→[10.0:226](∅→∅),[10.226]→[10.698527:698528](∅→∅),[10.698527]→[10.698527:698528](∅→∅),[10.698528]→[10.227:700](∅→∅),[10.700]→[10.698931:698941](∅→∅),[10.698931]→[10.698931:698941](∅→∅),[10.698941]→[10.701:777](∅→∅),[10.146]→[10.699912:699918](∅→∅),[10.379]→[10.699912:699918](∅→∅),[10.777]→[10.699912:699918](∅→∅),[10.9719]→[10.699912:699918](∅→∅),[10.89250]→[10.699912:699918](∅→∅),[10.699912]→[10.699912:699918](∅→∅),[10.48]→[10.699962:699976](∅→∅),[10.699962]→[10.699962:699976](∅→∅),[10.699976]→[10.89251:89290](∅→∅),[10.9754]→[10.700008:700025](∅→∅),[10.89290]→[10.700008:700025](∅→∅),[10.700008]→[10.700008:700025](∅→∅),[10.700025]→[10.89291:89319](∅→∅),[10.89319]→[10.9755:9840](∅→∅),[10.700055]→[10.9755:9840](∅→∅),[10.9840]→[10.89320:89361](∅→∅),[10.89361]→[10.9868:9904](∅→∅),[10.9868]→[10.9868:9904](∅→∅),[10.9904]→[10.380:444](∅→∅),[10.444]→[10.9968:10155](∅→∅),[10.9968]→[10.9968:10155](∅→∅),[10.10215]→[10.10215:10293](∅→∅),[10.105]→[10.700569:700588](∅→∅),[10.10293]→[10.700569:700588](∅→∅),[10.26694]→[10.700569:700588](∅→∅),[10.700569]→[10.700569:700588](∅→∅),[10.700588]→[10.26695:26696](∅→∅),[10.26696]→[10.700643:700694](∅→∅),[10.700643]→[10.700643:700694](∅→∅),[10.700694]→[10.89362:89383](∅→∅),[10.89383]→[10.700710:700780](∅→∅),[10.700710]→[10.700710:700780](∅→∅),[10.700780]→[10.89384:89412](∅→∅),[10.89412]→[10.700810:700904](∅→∅),[10.700810]→[10.700810:700904](∅→∅),[10.700904]→[10.89413:89460](∅→∅),[10.89460]→[10.445:496](∅→∅),[10.496]→[10.700937:700978](∅→∅),[10.26739]→[10.700937:700978](∅→∅),[10.89460]→[10.700937:700978](∅→∅),[10.700937]→[10.700937:700978](∅→∅),[10.700978]→[10.497:574](∅→∅),[10.574]→[10.778:1145](∅→∅)
}}}pub(crate) fn repair_missing_up_context<'a,T: GraphMutTxnT,I: IntoIterator<Item = &'a Vertex<ChangeId>>,>(txn: &mut T,channel: &mut T::Graph,ws: &mut Workspace,change_id: ChangeId,inode: Position<Option<Hash>>,c: Vertex<ChangeId>,d: I,) -> Result<(), MissingError<T::GraphError>> {let now = std::time::Instant::now();let alive = find_alive_up(txn,channel,&mut ws.files,c,change_id,&mut ws.alive_up_cache,)?;if let Some(alive) = alive {let mut alive = alive.clone();debug!("files = {:?}", ws.files);crate::TIMERS.lock().unwrap().find_alive += now.elapsed();ws.load_graph(txn, channel, inode)?;debug!("repair_missing_up_context, alive = {:?}", alive);for &d in d {if let Some((graph, vids)) = ws.graphs.0.get(&inode) {crate::alive::remove_redundant_parents(graph,vids,&mut alive,&mut ws.covered_parents,d,);}repair_regular_up(txn, channel, &alive, d, EdgeFlags::PSEUDO)?;}} else {debug!("repair_missing_up_context: {:?} is alive", c);}Ok(())}fn repair_regular_up<T: GraphMutTxnT>(txn: &mut T,channel: &mut T::Graph,alive: &HashSet<Vertex<ChangeId>>,d: Vertex<ChangeId>,flag: EdgeFlags,) -> Result<(), TxnErr<T::GraphError>> {for &ancestor in alive.iter() {debug!("repair_regular_up {:?} → {:?}", ancestor, d);if ancestor == d {info!("repair_missing_up_context, alive: {:?} == {:?}",ancestor, d);continue;}put_graph_with_rev(txn, channel, flag, ancestor, d, ChangeId::ROOT)?;}Ok(())}pub(crate) fn repair_missing_down_context<'a,T: GraphMutTxnT,I: IntoIterator<Item = &'a Vertex<ChangeId>>,>(txn: &mut T,channel: &mut T::Graph,ws: &mut Workspace,inode: Position<Option<Hash>>,c: Vertex<ChangeId>,d: I,) -> Result<(), MissingError<T::GraphError>> {debug!("repair_missing_down_context {:?}", c);let now = std::time::Instant::now();let alive = find_alive_down(txn, channel, c, &mut ws.alive_down_cache)?;if let Some(alive) = alive {let mut alive = alive.clone();debug!("alive = {:?}", alive);crate::TIMERS.lock().unwrap().find_alive += now.elapsed();ws.load_graph(txn, channel, inode)?;if let Some((graph, vids)) = ws.graphs.0.get(&inode) {crate::alive::remove_redundant_children(graph, vids, &mut alive, c); - edit in libpijul/src/missing_context.rs at line 57[10.1155]→[10.701277:701278](∅→∅),[10.701277]→[10.701277:701278](∅→∅),[10.701278]→[10.1156:1269](∅→∅),[10.1269]→[10.701379:701380](∅→∅),[10.701379]→[10.701379:701380](∅→∅),[10.701380]→[10.1270:1660](∅→∅),[10.1660]→[10.701647:701661](∅→∅),[10.701647]→[10.701647:701661](∅→∅),[10.10699]→[10.701825:701835](∅→∅),[10.26796]→[10.701825:701835](∅→∅),[10.57387]→[10.701825:701835](∅→∅),[10.89552]→[10.701825:701835](∅→∅),[10.701825]→[10.701825:701835](∅→∅),[10.701835]→[10.1661:1731](∅→∅)
if !alive.is_empty() {debug!("repair_missing_down_context alive = {:#?}", alive);}for &d in d {for &desc in alive.iter() {if d == desc {info!("repair_missing_down_context, alive: {:?} == {:?}", d, desc);continue;}debug!("repair_missing_down {:?} {:?}", d, desc);put_graph_with_rev(txn, channel, EdgeFlags::PSEUDO, d, desc, ChangeId::ROOT)?;}}} else {debug!("repair_missing_down: {:?} is alive", c); - edit in libpijul/src/missing_context.rs at line 58
Ok(()) - replacement in libpijul/src/missing_context.rs at line 60[10.26798]→[10.978:1036](∅→∅),[10.1036]→[10.701965:701982](∅→∅),[10.89614]→[10.701965:701982](∅→∅),[10.701965]→[10.701965:701982](∅→∅),[10.701982]→[10.89615:89643](∅→∅),[10.89643]→[10.702012:702071](∅→∅),[10.702012]→[10.702012:702071](∅→∅)
pub(crate) fn repair_context_nondeleted<T: GraphMutTxnT>(txn: &mut T,channel: &mut T::Graph,ws: &mut Workspace,inode: Position<Option<Hash>>,pub(crate) fn has_missing_context_nondeleted<T: GraphMutTxnT>(txn: &T,channel: &T::Graph, - replacement in libpijul/src/missing_context.rs at line 65
) -> Result<(), MissingError<T::GraphError>> {) -> Result<bool, MissingError<T::GraphError>> { - replacement in libpijul/src/missing_context.rs at line 67
return Ok(());return Ok(false); - replacement in libpijul/src/missing_context.rs at line 75[5.113]→[10.1085:1172](∅→∅),[10.123202]→[10.1085:1172](∅→∅),[10.1172]→[10.11149:11219](∅→∅),[10.11149]→[10.11149:11219](∅→∅),[10.11219]→[10.482:525](∅→∅),[10.525]→[5.114:260](∅→∅)
repair_missing_up_context(txn, channel, ws, change_id, inode, source, &[target])?;reconnect_target_up(txn, channel, ws, inode, target, change_id)?;if e.flag.contains(EdgeFlags::BLOCK) {let mut missing_down = std::mem::replace(&mut ws.missing_down, Vec::new());missing_down.clear();for e in iter_adjacent(if is_alive(txn, channel, &source)? && e.flag.contains(EdgeFlags::BLOCK) {Ok(iter_adjacent( - replacement in libpijul/src/missing_context.rs at line 82[5.400]→[5.400:644](∅→∅),[5.644]→[10.123203:123252](∅→∅),[10.607]→[10.123203:123252](∅→∅),[10.123252]→[10.655:754](∅→∅),[10.655]→[10.655:754](∅→∅),[10.754]→[10.11301:11303](∅→∅),[10.11301]→[10.11301:11303](∅→∅),[10.11303]→[10.704008:704009](∅→∅),[10.704008]→[10.704008:704009](∅→∅),[10.704009]→[10.89765:89806](∅→∅),[10.89806]→[10.11340:11357](∅→∅),[10.11340]→[10.11340:11357](∅→∅),[10.11357]→[10.89807:89835](∅→∅),[10.89835]→[10.11387:11501](∅→∅),[10.11387]→[10.11387:11501](∅→∅),[10.11501]→[10.89836:89883](∅→∅),[10.89883]→[10.83424:83466](∅→∅),[10.83466]→[10.89884:89963](∅→∅),[10.704213]→[10.89884:89963](∅→∅),[10.89963]→[10.123253:123323](∅→∅),[10.11668]→[10.704390:704422](∅→∅),[10.123323]→[10.704390:704422](∅→∅),[10.704390]→[10.704390:704422](∅→∅),[10.704422]→[10.123324:123368](∅→∅),[10.123368]→[10.11711:11759](∅→∅),[10.11711]→[10.11711:11759](∅→∅),[10.11759]→[10.704542:704620](∅→∅),[10.704542]→[10.704542:704620](∅→∅),[10.704620]→[10.11760:11822](∅→∅),[10.11822]→[10.123369:123434](∅→∅),[10.57866]→[10.704732:704770](∅→∅),[10.59136]→[10.704732:704770](∅→∅),[10.123434]→[10.704732:704770](∅→∅),[10.704732]→[10.704732:704770](∅→∅),[10.704770]→[10.11823:11910](∅→∅)
)? {let e = e?;ws.missing_down.push(*txn.find_block(&channel, e.dest())?)}repair_missing_down_context(txn, channel, ws, inode, target, &missing_down)?;ws.missing_down = missing_down;} else if is_alive(txn, channel, &source)? {repair_missing_down_context(txn, channel, ws, inode, target, &[source])?;}Ok(())}fn reconnect_target_up<T: GraphMutTxnT>(txn: &mut T,channel: &mut T::Graph,ws: &mut Workspace,inode: Position<Option<Hash>>,target: Vertex<ChangeId>,change_id: ChangeId,) -> Result<(), MissingError<T::GraphError>> {let mut unknown = HashSet::default();for v in iter_deleted_parents(txn, channel, target)? {let v = v?;if v.dest().change.is_root() || v.introduced_by().is_root() {continue;}if v.introduced_by() == change_id {unknown.clear();break;}// Else change ~v.introduced_by~ is a change we don't know,// since no change can create a conflict with itself.unknown.insert(*txn.find_block_end(channel, v.dest())?);}for up in unknown.drain() {repair_missing_up_context(txn, channel, ws, change_id, inode, up, &[target])?;)?.next().is_some())} else {Ok(true) - edit in libpijul/src/missing_context.rs at line 88
Ok(()) - replacement in libpijul/src/missing_context.rs at line 90[10.705750]→[10.90568:90626](∅→∅),[10.90626]→[10.705858:705875](∅→∅),[10.705858]→[10.705858:705875](∅→∅),[10.705875]→[10.90627:90655](∅→∅),[10.90655]→[10.705905:705964](∅→∅),[10.705905]→[10.705905:705964](∅→∅)
pub(crate) fn repair_context_deleted<T: GraphMutTxnT, K>(txn: &mut T,channel: &mut T::Graph,ws: &mut Workspace,inode: Position<Option<Hash>>,pub(crate) fn has_missing_context_deleted<T: GraphMutTxnT, K>(txn: &T,channel: &T::Graph, - replacement in libpijul/src/missing_context.rs at line 96
) -> Result<(), MissingError<T::GraphError>>) -> Result<bool, MissingError<T::GraphError>> - replacement in libpijul/src/missing_context.rs at line 101
return Ok(());return Ok(false); - replacement in libpijul/src/missing_context.rs at line 107
repair_children_of_deleted(txn, channel, ws, inode, &mut known, change_id, dest_vertex)?;if has_unknown_children(txn, channel, dest_vertex, change_id, &mut known)? {return Ok(true);} - replacement in libpijul/src/missing_context.rs at line 118
Ok(())Ok(false) - replacement in libpijul/src/missing_context.rs at line 218
debug!("detect folder conflict resolution, deleting {:?} → {:?} {:?}", v, e, p);debug!("detect folder conflict resolution, deleting {:?} → {:?} {:?}",v, e, p); - replacement in libpijul/src/missing_context.rs at line 316
fn collect_unknown_children<T: GraphTxnT, K>(fn has_unknown_children<T: GraphTxnT, K>( - edit in libpijul/src/missing_context.rs at line 319
ws: &mut Workspace, - replacement in libpijul/src/missing_context.rs at line 322
) -> Result<(), TxnErr<T::GraphError>>) -> Result<bool, TxnErr<T::GraphError>> - edit in libpijul/src/missing_context.rs at line 336
ws.pseudo.push((dest_vertex, *v)); - replacement in libpijul/src/missing_context.rs at line 355[10.709260]→[10.124107:124144](∅→∅),[10.124144]→[10.709296:709326](∅→∅),[10.709296]→[10.709296:709326](∅→∅),[10.709326]→[10.91352:91363](∅→∅),[10.91363]→[10.709326:709329](∅→∅),[10.709326]→[10.709326:709329](∅→∅),[10.709329]→[10.91364:91415](∅→∅),[10.91415]→[10.709375:709392](∅→∅),[10.709375]→[10.709375:709392](∅→∅),[10.709392]→[10.91416:91444](∅→∅),[10.91444]→[10.709422:709559](∅→∅),[10.709422]→[10.709422:709559](∅→∅),[10.709559]→[10.91445:91490](∅→∅),[10.26923]→[10.709590:709626](∅→∅),[10.91490]→[10.709590:709626](∅→∅),[10.709590]→[10.709590:709626](∅→∅),[10.709685]→[10.709685:709745](∅→∅),[10.709745]→[10.91491:91576](∅→∅),[10.91576]→[10.709829:709899](∅→∅),[10.709829]→[10.709829:709899](∅→∅),[10.709899]→[10.14431:14503](∅→∅),[10.14503]→[10.710052:710088](∅→∅),[10.710052]→[10.710052:710088](∅→∅),[10.710088]→[10.124145:124260](∅→∅),[10.124260]→[10.14561:14621](∅→∅),[10.14561]→[10.14561:14621](∅→∅),[10.14621]→[10.91577:91664](∅→∅),[10.91664]→[10.14707:14730](∅→∅),[10.26980]→[10.14707:14730](∅→∅),[10.14730]→[10.124261:124327](∅→∅),[10.59321]→[10.14796:14894](∅→∅),[10.124327]→[10.14796:14894](∅→∅),[10.14796]→[10.14796:14894](∅→∅),[10.14894]→[10.91665:91750](∅→∅),[10.91750]→[10.14978:15044](∅→∅),[10.27053]→[10.14978:15044](∅→∅)
ws.unknown.push(*v);}}}Ok(())}fn repair_children_of_deleted<T: GraphMutTxnT, K>(txn: &mut T,channel: &mut T::Graph,ws: &mut Workspace,inode: Position<Option<Hash>>,mut known: K,change_id: ChangeId,dest_vertex: Vertex<ChangeId>,) -> Result<(), MissingError<T::GraphError>>whereK: FnMut(Hash) -> bool,{trace!("repair_children_of_deleted {:?}", dest_vertex);collect_unknown_children(txn, channel, ws, dest_vertex, change_id, &mut known)?;let mut unknown = std::mem::replace(&mut ws.unknown, Vec::new());debug!("dest_vertex = {:?}, unknown = {:?}", dest_vertex, unknown);for edge in unknown.drain(..) {let p = *txn.find_block(channel, edge.dest())?;assert!(!edge.flag().contains(EdgeFlags::FOLDER));debug!("dest_vertex {:?}, p {:?}", dest_vertex, p);put_graph_with_rev(txn, channel, EdgeFlags::db(), dest_vertex, p, change_id)?;let mut u = p;while let Ok(&v) = txn.find_block(channel, u.end_pos()) {if u != v {debug!("repair_children_of_deleted: {:?} -> {:?}", u, v);put_graph_with_rev(txn, channel, EdgeFlags::db(), u, v, change_id)?;u = v} else {break;return Ok(true); - edit in libpijul/src/missing_context.rs at line 358[10.711106]→[10.124328:124369](∅→∅),[10.91791]→[10.15084:15179](∅→∅),[10.124369]→[10.15084:15179](∅→∅),[10.15084]→[10.15084:15179](∅→∅),[10.15179]→[10.711414:711431](∅→∅),[10.711414]→[10.711414:711431](∅→∅),[10.711431]→[10.1936:2029](∅→∅),[10.2029]→[10.1091:1275](∅→∅),[10.1091]→[10.1091:1275](∅→∅),[10.1275]→[10.2030:2083](∅→∅),[10.2083]→[10.1309:1325](∅→∅),[10.1309]→[10.1309:1325](∅→∅),[10.1325]→[10.711583:711593](∅→∅),[10.15277]→[10.711583:711593](∅→∅),[10.711583]→[10.711583:711593](∅→∅)
if is_alive(txn, channel, &p)? {repair_missing_up_context(txn, channel, ws, change_id, inode, dest_vertex, &[p])?;} else {let alive = find_alive_down(txn, channel, p, &mut ws.alive_down_cache)?.clone();repair_missing_up_context(txn,channel,ws,change_id,inode,dest_vertex,alive.iter().flat_map(|t| t.iter()),)?;} - replacement in libpijul/src/missing_context.rs at line 359
ws.unknown = unknown;Ok(())Ok(false) - edit in libpijul/src/missing_context.rs at line 361[10.711638]→[10.58890:58891](∅→∅),[10.58891]→[10.91792:91844](∅→∅),[10.91844]→[10.711740:711757](∅→∅),[10.711740]→[10.711740:711757](∅→∅),[10.711757]→[10.91845:91873](∅→∅),[10.91873]→[10.711787:711811](∅→∅),[10.711787]→[10.711787:711811](∅→∅),[10.711811]→[10.91874:91921](∅→∅),[10.27096]→[10.711844:711914](∅→∅),[10.91921]→[10.711844:711914](∅→∅),[10.711844]→[10.711844:711914](∅→∅),[10.711914]→[10.15278:15332](∅→∅),[10.15332]→[10.711964:712042](∅→∅),[10.711964]→[10.711964:712042](∅→∅),[10.712042]→[10.124370:124630](∅→∅),[10.92062]→[10.59054:59118](∅→∅),[10.124630]→[10.59054:59118](∅→∅),[10.59054]→[10.59054:59118](∅→∅),[10.59118]→[10.124631:124775](∅→∅),[10.15530]→[10.712510:712549](∅→∅),[10.27169]→[10.712510:712549](∅→∅),[10.92159]→[10.712510:712549](∅→∅),[10.124775]→[10.712510:712549](∅→∅),[10.712510]→[10.712510:712549](∅→∅),[10.712549]→[10.124776:124887](∅→∅),[10.92209]→[10.59295:59363](∅→∅),[10.124887]→[10.59295:59363](∅→∅),[10.59295]→[10.59295:59363](∅→∅),[10.59363]→[10.124888:124988](∅→∅),[10.125429]→[10.714122:714140](∅→∅),[10.714122]→[10.714122:714140](∅→∅),[10.715906]→[10.715906:715930](∅→∅),[10.716708]→[10.716708:716728](∅→∅),[10.716728]→[10.92810:92868](∅→∅),[10.92868]→[10.716781:716798](∅→∅),[10.716781]→[10.716781:716798](∅→∅),[10.716798]→[10.92869:92897](∅→∅),[10.92897]→[10.716828:716852](∅→∅),[10.716828]→[10.716828:716852](∅→∅),[10.716852]→[10.92898:92945](∅→∅),[10.27635]→[10.716885:717371](∅→∅),[10.92945]→[10.716885:717371](∅→∅),[10.716885]→[10.716885:717371](∅→∅)
pub(crate) fn delete_pseudo_edges<T: GraphMutTxnT>(txn: &mut T,channel: &mut T::Graph,ws: &mut Workspace,) -> Result<(), MissingError<T::GraphError>> {if ws.pseudo.is_empty() {debug!("no pseudo edges")}for (dest_vertex, mut e) in ws.pseudo.drain(..) {debug!("repair_context_deleted, deleting {:?} {:?}", dest_vertex, e);if !is_alive(txn, channel, &dest_vertex)? && !ws.repaired.contains(&dest_vertex) {if e.flag().contains(EdgeFlags::PARENT) {let p = *txn.find_block_end(channel, e.dest())?;if !is_alive(txn, channel, &p)? {debug!("delete {:?} {:?}", p, dest_vertex);e -= EdgeFlags::PARENT;del_graph_with_rev(txn, channel, e.flag(), p, dest_vertex, e.introduced_by())?;}} else {let p = *txn.find_block(channel, e.dest())?;if !is_alive(txn, channel, &p)? {debug!("delete (2) {:?} {:?}", dest_vertex, p);del_graph_with_rev(txn, channel, e.flag(), dest_vertex, p, e.introduced_by())?;}}}}Ok(())}pub(crate) fn repair_parents_of_deleted<T: GraphMutTxnT>(txn: &mut T,channel: &mut T::Graph,ws: &mut Workspace,) -> Result<(), MissingError<T::GraphError>> {debug!("repair_parents_of_deleted");let mut unknown = std::mem::replace(&mut ws.unknown_parents, Vec::new());for (dest_vertex, p, inode, flag) in unknown.drain(..) {if flag.contains(EdgeFlags::FOLDER) {repair_missing_down_context(txn, channel, ws, inode, dest_vertex, &[dest_vertex])?} else {repair_missing_down_context(txn, channel, ws, inode, dest_vertex, &[p])?}}ws.unknown_parents = unknown;Ok(())} - edit in libpijul/src/lib.rs at line 22
pub mod find_alive; - replacement in libpijul/src/apply.rs at line 51
MakeChange(#[from]crate::change::MakeChangeError<T>),MakeChange(#[from] crate::change::MakeChangeError<T>), - replacement in libpijul/src/apply.rs at line 340
Atom::NewVertex(ref n) => {put_newvertex(txn,T::graph_mut(channel),changes,change,ws,change_id,n,)?},Atom::NewVertex(ref n) => put_newvertex(txn,T::graph_mut(channel),changes,change,ws,change_id,n,)?, - edit in libpijul/src/apply.rs at line 385
{let file = Vertex {change: ChangeId(L64(5867590239053715538)),start: ChangePosition(204370u64.into()),end: ChangePosition(204370u64.into()),};let still_here: Vec<_> = iter_adjacent(txn,T::graph_mut(channel),file,EdgeFlags::empty(),EdgeFlags::all(),)?.collect();debug!("still here! {:?}", still_here);} - edit in libpijul/src/apply.rs at line 387
- replacement in libpijul/src/apply.rs at line 391
clean_obsolete_pseudo_edges(txn, T::graph_mut(channel), ws, change_id)?;let mut inodes = clean_obsolete_pseudo_edges(txn, T::graph_mut(channel), ws, change_id)?;collect_missing_contexts(txn, txn.graph(channel), ws, &change, change_id, &mut inodes)?;for i in inodes {repair_zombies(txn, T::graph_mut(channel), i)?;} - edit in libpijul/src/apply.rs at line 397
info!("repairing missing contexts");repair_missing_contexts(txn, T::graph_mut(channel), ws, change_id, change)?; - edit in libpijul/src/apply.rs at line 562
pub(crate) fn repair_zombies<T: GraphMutTxnT + TreeTxnT>(txn: &mut T,channel: &mut T::Graph,root: Position<ChangeId>,) -> Result<(), LocalApplyError<T>> {let mut stack = vec![(root.inode_vertex(), true, false)];let mut visited = HashSet::new(); - replacement in libpijul/src/apply.rs at line 572
pub(crate) fn clean_obsolete_pseudo_edges<T: GraphMutTxnT + TreeTxnT>(while let Some((current, alive, on_path)) = stack.pop() {stack.push((current, alive, true));let is_first_visit = visited.insert(current);let len = stack.len();if !on_path {// If this is the first visit, find the children, starting// with in flag order (alive first), since we don't want// to reconnect vertices multiple times.for e in iter_adjacent(txn, channel, current, EdgeFlags::empty(), EdgeFlags::all())? {let e = e?;if e.flag().contains(EdgeFlags::PARENT) {if e.flag() & (EdgeFlags::BLOCK | EdgeFlags::DELETED) == EdgeFlags::BLOCK {// This vertex is alive!stack[len - 1].1 = true;}continue;}if is_first_visit {let child = txn.find_block(channel, e.dest())?;stack.push((*child, false, false));}}}if len >= 2 && stack[len - 1].1 {if let Some(last_on_path) = (&stack[..len - 1]).iter().rev().position(|x| x.2) {let last_on_path = len - 2 - last_on_path;// If the last vertex on the path to `current` is not// alive, a reconnect is needed.if !stack[last_on_path].1 {if let Some(last_alive_on_path) =(&stack[..last_on_path]).iter().rev().position(|x| x.1){let last_alive_on_path = last_on_path - 1 - last_alive_on_path;debug!("repair zombies {:?} {:?}", last_alive_on_path, len - 1);// We need to reconnect, and we can do it now// since we won't have a chance to visit that// edge (because non-PARENT edge we are// inserting now starts from a vertex that is// on the path, which means we've already// pushed all its children onto the stack.).put_graph_with_rev(txn,channel,EdgeFlags::PSEUDO,stack[last_alive_on_path].0,stack[len - 1].0,ChangeId::ROOT,)?;}}}}// If no children, pop.if stack.len() == len {stack.pop();}}Ok(())}pub fn clean_obsolete_pseudo_edges<T: GraphMutTxnT + TreeTxnT>( - replacement in libpijul/src/apply.rs at line 644
) -> Result<(), LocalApplyError<T>> {) -> Result<HashSet<Position<ChangeId>>, LocalApplyError<T>> {info!("clean_obsolete_pseudo_edges, ws.pseudo.len() = {}",ws.pseudo.len()); - edit in libpijul/src/apply.rs at line 651
let mut inodes = HashSet::new(); - replacement in libpijul/src/apply.rs at line 655
debug!("clean_obsolete_pseudo_edges {:?} {:?} {:?}", next_vertex, p, inode);debug!("clean_obsolete_pseudo_edges {:?} {:?} {:?}",next_vertex, p, inode); - replacement in libpijul/src/apply.rs at line 667
)?.collect();debug!("pseudo edge still here ? {:?} {:?}", next_vertex.change.0.0, still_here))?.collect();debug!("pseudo edge still here ? {:?} {:?}",next_vertex.change.0 .0, still_here) - edit in libpijul/src/apply.rs at line 744[10.21227]→[10.972853:972877](∅→∅),[10.132503]→[10.972853:972877](∅→∅),[10.972853]→[10.972853:972877](∅→∅),[10.972877]→[10.284:319](∅→∅),[10.319]→[10.21228:21333](∅→∅),[10.972877]→[10.21228:21333](∅→∅),[10.21333]→[10.71094:71140](∅→∅),[10.71094]→[10.71094:71140](∅→∅),[10.71140]→[10.21334:21398](∅→∅),[10.21398]→[10.71203:71222](∅→∅),[10.71203]→[10.71203:71222](∅→∅),[10.71222]→[10.21399:21421](∅→∅),[10.21421]→[10.99202:99216](∅→∅),[10.71255]→[10.99202:99216](∅→∅),[10.99216]→[10.21422:21475](∅→∅),[10.21475]→[10.147383:147439](∅→∅),[10.147439]→[10.374:407](∅→∅),[10.374]→[10.374:407](∅→∅)
if a_is_alive {debug!("repair down");debug_assert!(!b_is_alive);crate::missing_context::repair_missing_down_context(txn,channel,&mut ws.missing_context,inode,b,&[a],).map_err(LocalApplyError::from_missing)?} else if b_is_alive && !p.flag().is_folder() {debug!("repair up"); - replacement in libpijul/src/apply.rs at line 745[10.1982]→[10.1982:2142](∅→∅),[10.407]→[10.21515:21578](∅→∅),[10.2142]→[10.21515:21578](∅→∅),[10.21515]→[10.21515:21578](∅→∅),[10.21578]→[10.71305:71351](∅→∅),[10.71305]→[10.71305:71351](∅→∅),[10.71351]→[10.21579:21670](∅→∅),[10.21670]→[10.71395:71414](∅→∅),[10.71395]→[10.71395:71414](∅→∅),[10.71414]→[10.21671:21693](∅→∅),[10.21693]→[10.99351:99365](∅→∅),[10.71466]→[10.99351:99365](∅→∅),[10.99365]→[10.21694:21747](∅→∅)
// Note: if this is a folder edge,// repair_missing_up_context will stop immediately, so we// don't even need to call it.crate::missing_context::repair_missing_up_context(txn,channel,&mut ws.missing_context,change_id,inode,a,&[b],).map_err(LocalApplyError::from_missing)?if a_is_alive || (b_is_alive && !p.flag().is_folder()) {// A context repair is needed.inodes.insert(internal_pos(txn, &inode, change_id)?); - edit in libpijul/src/apply.rs at line 750
- replacement in libpijul/src/apply.rs at line 753
Ok(())Ok(inodes) - replacement in libpijul/src/apply.rs at line 807[10.3809]→[10.42354:42410](∅→∅),[10.1060]→[10.42354:42410](∅→∅),[10.42410]→[10.974346:974363](∅→∅),[10.132549]→[10.974346:974363](∅→∅),[10.974346]→[10.974346:974363](∅→∅),[10.974363]→[10.132550:132578](∅→∅)
fn repair_missing_contexts<T: GraphMutTxnT + TreeTxnT>(txn: &mut T,channel: &mut T::Graph,fn collect_missing_contexts<T: GraphMutTxnT + TreeTxnT>(txn: &T,channel: &T::Graph, - edit in libpijul/src/apply.rs at line 811
change: &Change, - replacement in libpijul/src/apply.rs at line 813
change: &Change,inodes: &mut HashSet<Position<ChangeId>>, - replacement in libpijul/src/apply.rs at line 815[10.42449]→[10.974496:974537](∅→∅),[10.99456]→[10.974496:974537](∅→∅),[10.132629]→[10.974496:974537](∅→∅),[10.974496]→[10.974496:974537](∅→∅),[10.974537]→[10.99457:99600](∅→∅)
let now = std::time::Instant::now();crate::missing_context::repair_parents_of_deleted(txn, channel, &mut ws.missing_context).map_err(LocalApplyError::from_missing)?;inodes.extend(ws.missing_context.unknown_parents.drain(..).map(|x| internal_pos(txn, &x.2, change_id).unwrap()),); - replacement in libpijul/src/apply.rs at line 824[10.21811]→[10.974756:974920](∅→∅),[10.974756]→[10.974756:974920](∅→∅),[10.974920]→[10.21812:21988](∅→∅)
let vertex = Vertex {change: change_id,start: n.start,end: n.end,};repair_new_vertex_context_up(txn, channel, ws, change_id, n, vertex)?;repair_new_vertex_context_down(txn, channel, ws, change_id, n, vertex)?;let inode = internal_pos(txn, &n.inode, change_id)?;if !inodes.contains(&inode) {for up in n.up_context.iter() {let up =*txn.find_block_end(channel, internal_pos(txn, &up, change_id)?)?;if !is_alive(txn, channel, &up)? {inodes.insert(inode);break;}}for down in n.down_context.iter() {let down =*txn.find_block(channel, internal_pos(txn, &down, change_id)?)?;let mut down_has_other_parents = false;for e in iter_adjacent(txn,channel,down,EdgeFlags::PARENT,EdgeFlags::all() - EdgeFlags::DELETED,)? {let e = e?;if e.introduced_by() != change_id {down_has_other_parents = true;break;}}if !down_has_other_parents {inodes.insert(inode);break;}}} - replacement in libpijul/src/apply.rs at line 860[10.976997]→[10.22027:22105](∅→∅),[10.22105]→[10.977637:977667](∅→∅),[10.977637]→[10.977637:977667](∅→∅),[10.978406]→[10.99969:100106](∅→∅),[10.100106]→[10.978495:978575](∅→∅),[10.978495]→[10.978495:978575](∅→∅),[10.978575]→[10.1061:1062](∅→∅),[10.1062]→[10.42450:42511](∅→∅),[10.42511]→[10.22151:22168](∅→∅),[10.132680]→[10.22151:22168](∅→∅),[10.22151]→[10.22151:22168](∅→∅),[10.22168]→[10.132681:132709](∅→∅),[10.132709]→[10.22198:22310](∅→∅),[10.22198]→[10.22198:22310](∅→∅),[10.22310]→[10.42512:42550](∅→∅),[10.42550]→[10.22355:22391](∅→∅),[10.132760]→[10.22355:22391](∅→∅),[10.22355]→[10.22355:22391](∅→∅),[10.22391]→[10.147440:147567](∅→∅),[10.132803]→[10.22516:22912](∅→∅),[10.147567]→[10.22516:22912](∅→∅),[10.22516]→[10.22516:22912](∅→∅),[10.22912]→[10.42551:42614](∅→∅),[10.42614]→[10.22959:22976](∅→∅),[10.132856]→[10.22959:22976](∅→∅),[10.22959]→[10.22959:22976](∅→∅),[10.22976]→[10.132857:132885](∅→∅),[10.132885]→[10.23006:23118](∅→∅),[10.23006]→[10.23006:23118](∅→∅),[10.23118]→[10.42615:42653](∅→∅),[10.42653]→[10.23163:23294](∅→∅),[10.132936]→[10.23163:23294](∅→∅),[10.23163]→[10.23163:23294](∅→∅),[10.23294]→[10.132937:132985](∅→∅),[10.132985]→[10.147568:147652](∅→∅),[10.66872]→[10.132986:133018](∅→∅),[10.147652]→[10.132986:133018](∅→∅),[10.23418]→[10.132986:133018](∅→∅),[10.133018]→[10.23444:23582](∅→∅),[10.23444]→[10.23444:23582](∅→∅),[10.23582]→[10.133019:133056](∅→∅),[10.133056]→[10.147653:147701](∅→∅),[10.147701]→[10.133102:133135](∅→∅),[10.133102]→[10.133102:133135](∅→∅)
repair_edge_context(txn, channel, ws, change_id, change, n)?;}}}crate::missing_context::delete_pseudo_edges(txn, channel, &mut ws.missing_context).map_err(LocalApplyError::from_missing)?;crate::TIMERS.lock().unwrap().repair_context += now.elapsed();Ok(())}fn repair_new_vertex_context_up<T: GraphMutTxnT + TreeTxnT>(txn: &mut T,channel: &mut T::Graph,ws: &mut Workspace,change_id: ChangeId,n: &NewVertex<Option<Hash>>,vertex: Vertex<ChangeId>,) -> Result<(), LocalApplyError<T>> {for up in n.up_context.iter() {let up = *txn.find_block_end(channel, internal_pos(txn, &up, change_id)?)?;if !is_alive(txn, channel, &up)? {debug!("repairing missing up context {:?} {:?}", up, vertex);repair_missing_up_context(txn,channel,&mut ws.missing_context,change_id,n.inode,up,&[vertex],).map_err(LocalApplyError::from_missing)?}}Ok(())}fn repair_new_vertex_context_down<T: GraphMutTxnT + TreeTxnT>(txn: &mut T,channel: &mut T::Graph,ws: &mut Workspace,change_id: ChangeId,n: &NewVertex<Option<Hash>>,vertex: Vertex<ChangeId>,) -> Result<(), LocalApplyError<T>> {debug!("repairing missing context for {:?}", vertex);if n.flag.contains(EdgeFlags::FOLDER) {return Ok(());}'outer: for down in n.down_context.iter() {let down = *txn.find_block(channel, internal_pos(txn, &down, change_id)?)?;for e in iter_adjacent(txn,channel,down,EdgeFlags::PARENT,EdgeFlags::all() - EdgeFlags::DELETED,)? {let e = e?;if e.introduced_by() != change_id {continue 'outer;has_missing_edge_context(txn, channel, change_id, change, n, inodes)?; - edit in libpijul/src/apply.rs at line 863
debug!("repairing missing down context {:?} {:?}", down, vertex);repair_missing_down_context(txn,channel,&mut ws.missing_context,n.inode,down,&[vertex],).map_err(LocalApplyError::from_missing)? - replacement in libpijul/src/apply.rs at line 867[10.24008]→[10.42654:42706](∅→∅),[10.24044]→[10.978666:978683](∅→∅),[10.42706]→[10.978666:978683](∅→∅),[10.133191]→[10.978666:978683](∅→∅),[10.978666]→[10.978666:978683](∅→∅),[10.978683]→[10.133192:133220](∅→∅),[10.133220]→[10.978713:978737](∅→∅),[10.978713]→[10.978713:978737](∅→∅)
fn repair_edge_context<T: GraphMutTxnT + TreeTxnT>(txn: &mut T,channel: &mut T::Graph,ws: &mut Workspace,fn has_missing_edge_context<T: GraphMutTxnT + TreeTxnT>(txn: &T,channel: &T::Graph, - edit in libpijul/src/apply.rs at line 873
inodes: &mut HashSet<Position<ChangeId>>, - replacement in libpijul/src/apply.rs at line 875[10.42745]→[10.24121:24687](∅→∅),[10.133271]→[10.24121:24687](∅→∅),[10.24121]→[10.24121:24687](∅→∅),[10.24687]→[10.1227:1327](∅→∅)
for e in n.edges.iter() {assert!(!e.flag.contains(EdgeFlags::PARENT));if e.flag.contains(EdgeFlags::DELETED) {trace!("repairing context deleted {:?}", e);repair_context_deleted(txn,channel,&mut ws.missing_context,n.inode,change_id,|h| change.knows(&h),e,).map_err(LocalApplyError::from_missing)?} else {trace!("repairing context nondeleted {:?}", e);repair_context_nondeleted(txn, channel, &mut ws.missing_context, n.inode, change_id, e)let inode = internal_pos(txn, &n.inode, change_id)?;if !inodes.contains(&inode) {for e in n.edges.iter() {assert!(!e.flag.contains(EdgeFlags::PARENT));if e.flag.contains(EdgeFlags::DELETED) {trace!("repairing context deleted {:?}", e);if has_missing_context_deleted(txn, channel, change_id, |h| change.knows(&h), e).map_err(LocalApplyError::from_missing)?{inodes.insert(inode);break;}} else {trace!("repairing context nondeleted {:?}", e);if has_missing_context_nondeleted(txn,channel,change_id,e,) - edit in libpijul/src/apply.rs at line 896
{inodes.insert(inode);break;}}