GHO6DWPILBBTL6CVZKERJBTFL3EY6ZT4YM4E5R4S6YPGVFKFHCVAC 3M7WBE24JTPTHWQOU5PO2ZJYKPKEH2F6R4M6RWIRFG334PQEA55QC CCLLB7OIFNFYJZTG3UCI7536TOCWSCSXR67VELSB466R24WLJSDAC SXEYMYF7P4RZMZ46WPL4IZUTSQ2ATBWYZX7QNVMS3SGOYXYOHAGQC 5DVRL6MFXQOCPOZMYSKBERMRRVUTYRL2SRGRTU2MH4IEOFCDKM3QC I52XSRUH5RVHQBFWVMAQPTUSPAJ4KNVID2RMI3UGCVKFLYUO6WZAC MU5GSJAW65PEG3BRYUKZ7O37BPHW3MOX3S5E2RFOXKGUOJEEDQ5AC 76PCXGML77EZWTRI5E6KHLVRAFTJ2AB5YRN5EKOYNAPKTWY2KCGAC FMKKWCFVK5CPPP55T4VMCHSFPZ47EBK6V7D4MJ5BH55TP4UBOZXAC Q4SVMHAEZQQCBFGPJMWS5H4VXB2HFQREZ3AWGOHFWHLFARUQVPBAC L4JXJHWXYNCL4QGJXNKKTOKKTAXKKXBJUUY7HFZGEUZ5A2V5H34QC VO5OQW4W2656DIYYRNZ3PO7TQ4JOKQ3GVWE5ALUTYVMX3WMXJOYQC WZVCLZKY34KQBQU6YBGJLQCDADBQ67LQVDNRVCMQVY3O3C3EIWSQC KQTD46KVVWMJ3W6O55BEJLCVTNTDLUH6QT46AEFT7OU2SELXG4IAC 6YMDOZIB5LVYLFIDGN2WNT5JTHEAMS4TFPVDEZ3OWXWOKJOC5QDAC Q45QHPO4HDTEZF2W4UDZSYYQ46BPEIWSW4GJILZR5HTJNLKXJABQC ERV3644QELKOHAVNMZGRWYCPPN3XELTAH4PPFR6QKGWW73XBOOKQC DNQHXWRZF6EWII3RGQ6HPGFD47BOOFH4FCQHSCACBS3RLQO3DNIQC PJ7T2VFLV5PYG3CV23GC2GIQETXKGC6CO74JBGREV3JC3LG5OXUAC BD5PC25AB5MKVIYDFSDGRZ4YGX4PKW4SMZ3YAYAPNA5HLDVJUR3QC 5BRU2RRWOQBMS2V3RQM7PRFR5UILYZ73GISHAKJA6KIZGC5M2MFAC BXD3IQYNMKMI5BTANCF6NZHZP4CKPWADGJMBT2R3WTMKVKONT5QAC HMMMKONLCRAXVT7SO2ITTFDOJIQKKVSRIZPXYVPDC34RCBHWMHVAC XL6Y64UPFLIVRV3YVJMTTMZU7VL6SUXVE6BKL6K7DYRKVJ4X727AC UNZXTNSJI4YRY3EQ3M4HMBKQDNYDTY6B7IZRBNYGDJXTA2UKYWRAC 7PM25EXLNQ6JUUIZNTAOQYNNIZNG6TJREEBUSAIC3FIOE7FHETSAC KDF6FJRVF72L274BEUJCTUKRFMNL6BDZMTVKDPEYGFX4TC3YOVSQC GVQ7YSEDDCYYYWDJ5JUVFSBWA5EZVOZJI63KK6E46N6Y2B6LP72AC ZWPPIJXFKEL3RP2MEYGB3BPTE73GYRW6FSRZDQKFBJFOK4JBNQ4AC 23LVKATNTT74YKHG7KJM6SBO2IVZEV24TQ46ZJIHQ2IXONWNVXJAC UFCZKKLXVYQYQBYENCAFHY3ZPPSDAJJAIREZSYNQM4QNXV6G6RXAC crate::apply::clean_obsolete_pseudo_edges(txn, &mut channel.graph, &mut ws.apply, change_id)?;crate::apply::repair_cyclic_paths(txn, &mut channel.graph, &mut ws.apply)?;channel.last_modified = 0;
crate::apply::clean_obsolete_pseudo_edges(txn,T::graph_mut(channel),&mut ws.apply,change_id,)?;crate::apply::repair_cyclic_paths(txn, T::graph_mut(channel), &mut ws.apply)?;T::touch_channel(channel, Some(0));
debug_to_file(&txn, &channel_alice, "debug_alice").unwrap();debug_to_file(&txn, &channel_bob, "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice.borrow(), "debug_alice").unwrap();debug_to_file(&txn, &channel_bob.borrow(), "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice, "debug_alice").unwrap();debug_to_file(&txn, &channel_bob, "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice.borrow(), "debug_alice").unwrap();debug_to_file(&txn, &channel_bob.borrow(), "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice, "debug_alice").unwrap();debug_to_file(&txn, &channel_bob, "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice.borrow(), "debug_alice").unwrap();debug_to_file(&txn, &channel_bob.borrow(), "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice, "debug_alice").unwrap();debug_to_file(&txn, &channel_bob, "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice.borrow(), "debug_alice").unwrap();debug_to_file(&txn, &channel_bob.borrow(), "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice, "debug_alice").unwrap();debug_to_file(&txn, &channel_bob, "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice.borrow(), "debug_alice").unwrap();debug_to_file(&txn, &channel_bob.borrow(), "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice, "debug_alice").unwrap();debug_to_file(&txn, &channel_bob, "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice.borrow(), "debug_alice").unwrap();debug_to_file(&txn, &channel_bob.borrow(), "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice, "debug_alice").unwrap();debug_to_file(&txn, &channel_bob, "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice.borrow(), "debug_alice").unwrap();debug_to_file(&txn, &channel_bob.borrow(), "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice, "debug_alice").unwrap();debug_to_file(&txn, &channel_bob, "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice.borrow(), "debug_alice").unwrap();debug_to_file(&txn, &channel_bob.borrow(), "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice, "debug_alice").unwrap();debug_to_file(&txn, &channel_bob, "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice.borrow(), "debug_alice").unwrap();debug_to_file(&txn, &channel_bob.borrow(), "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice, "debug_alice").unwrap();debug_to_file(&txn, &channel_bob, "debug_bob").unwrap();
debug_to_file(&txn, &channel_alice.borrow(), "debug_alice").unwrap();debug_to_file(&txn, &channel_bob.borrow(), "debug_bob").unwrap();
}}use super::*;/// Find the key where a position is.txn: &'txn T,p: Position<ChangeId>,if p.change.is_root() {return Ok(Vertex::ROOT);}let key = Vertex {change: p.change,start: p.pos,end: p.pos,};debug!(target: "libpijul::find_block", "find_block {:?}", key);} else {};debug!("k = {:?}", k);// The only guarantee here is that k is either the first key// >= `key`, or the key just before that. We might need to// rewind by one step if key is strictly larger than the// result (i.e. if `p` is in the middle of the key).while k.change > p.change || (k.change == p.change && k.start > p.pos) {debug!(target: "libpijul::find_block", "find_block while {:?}", k);} else {break;}}loop {debug!(target: "libpijul::find_block", "find_block loop {:?}", k);if k.change == p.change && k.start <= p.pos {if k.end > p.pos || (k.start == k.end && k.end == p.pos) {return Ok(k);}} else if k.change > p.change {}} else {break;}}debug!(target: "libpijul::find_block", "find_block None, {:?}", k);}/// Find the key ending at a position.txn: &'txn T,p: Position<ChangeId>,if p.change.is_root() {return Ok(Vertex::ROOT);}let key = Vertex {change: p.change,start: p.pos,end: p.pos,};debug!(target: "libpijul::find_block_end", "find_block_end {:?}, p.change.0 = {:?}", key, p.change.0);} else {};// The only guarantee here is that k is either the first key// before `key`, or the key just before that.loop {debug!(target: "libpijul::find_block_end", "find_block_end loop {:?} k.change.0 = {:?}", k, k.change.0);if k.change < p.change {break;} else if k.change == p.change {// Here we want to create an edge pointing between `p`// and its successor. If k.start == p.pos, the only// case where that's what we want is if k.start ==// k.end.break;}}} else {break;}}// We also want k.end >= p.pos, so we just call next() until// we have that.debug!(target: "libpijul::find_block_end", "find_block_end k(0) = {:?} k.change.0 = {:?}", k, k.change.0);while k.change < p.change || (k.change == p.change && p.pos > k.end) {} else {break;}}debug!(target: "libpijul::find_block_end", "find_block_end k(1) = {:?}, k.change.0 = {:?}", k, k.change.0);if k.change == p.change && k.start <= p.pos && p.pos <= k.end {Ok(k)} else {Err(BlockError::Block { block: p })if let Some(k_) = cursor.next() {k = k_?.0if let Some(k_) = cursor.prev() {k = k_?.0if k.start == p.pos && k.end == p.pos || k.start < p.pos {return Err(BlockError::Block { block: p });let mut cursor = txn.cursor_graph(graph, Some((key, None)))?;let mut k = if let Some(k) = cursor.next() {k?.0) -> Result<Vertex<ChangeId>, BlockError<T::GraphError>> {graph: &'db T::Graph,pub(crate) fn find_block_end<'db, 'txn: 'db, T: GraphTxnT>(Err(BlockError::Block { block: p })if let Some(k_) = cursor.next() {k = k_?.0return Err(BlockError::Block { block: p });if let Some(k_) = cursor.prev() {k = k_?.0return Err(BlockError::Block { block: p });let mut cursor = txn.cursor_graph(graph, Some((key, None)))?;let mut k = if let Some(k) = cursor.next() {k?.0) -> Result<Vertex<ChangeId>, BlockError<T::GraphError>> {graph: &'db T::Graph,pub(crate) fn find_block<'db, 'txn: 'db, T: GraphTxnT>(#[derive(Debug, Error)]}pub enum BlockError<T: std::error::Error + 'static> {#[error(transparent)]Txn(T),#[error("Block error: {:?}", block)]Block { block: Position<ChangeId> },}impl<T: std::error::Error + 'static> std::convert::From<TxnErr<T>> for BlockError<T> {fn from(e: TxnErr<T>) -> Self {BlockError::Txn(e.0)}
} else {Err(TxnErr(SanakirjaError::PristineCorrupt))}}type Adj = Adj;fn init_adj(&self,g: &Self::Graph,key: Vertex<ChangeId>,dest: Position<ChangeId>,min_flag: EdgeFlags,max_flag: EdgeFlags,) -> Result<Self::Adj, TxnErr<Self::GraphError>> {let edge = Edge {flag: min_flag,dest,introduced_by: ChangeId::ROOT,};if let Ok((cursor, _)) = self.txn.set_cursors(g, Some((key, Some(edge)))) {Ok(Adj {cursor,key,min_flag,max_flag,})} else {Err(TxnErr(SanakirjaError::PristineCorrupt))}}fn next_adj(&self,_: &Self::Graph,a: &mut Self::Adj,) -> Option<Result<Edge, TxnErr<Self::GraphError>>> {next_adj(&self.txn, a)}fn find_block(&self,graph: &Self::Graph,p: Position<ChangeId>,) -> Result<Vertex<ChangeId>, BlockError<Self::GraphError>> {find_block(&self.txn, graph, p)}fn find_block_end(&self,graph: &Self::Graph,p: Position<ChangeId>,) -> Result<Vertex<ChangeId>, BlockError<Self::GraphError>> {find_block_end(&self.txn, graph, p)}}unsafe fn next_graph<T: ::sanakirja::Transaction>(txn: &T,cursor: &mut ::sanakirja::Cursor,) -> Result<Option<(Vertex<ChangeId>, Edge)>, BlockError<SanakirjaError>> {match ::sanakirja::next::<_, Vertex<ChangeId>, Edge>(txn, cursor) {Ok(x) => Ok(x),Err(::sanakirja::CRCError {}) => Err(BlockError::Txn(SanakirjaError::PristineCorrupt)),}}unsafe fn prev_graph<T: ::sanakirja::Transaction>(txn: &T,cursor: &mut ::sanakirja::Cursor,) -> Result<Option<(Vertex<ChangeId>, Edge)>, BlockError<SanakirjaError>> {match ::sanakirja::prev::<_, Vertex<ChangeId>, Edge>(txn, cursor) {Ok(x) => Ok(x),Err(::sanakirja::CRCError {}) => Err(BlockError::Txn(SanakirjaError::PristineCorrupt)),}}#[doc(hidden)]pub fn next_adj<T: ::sanakirja::Transaction>(txn: &T,a: &mut Adj,) -> Option<Result<Edge, TxnErr<SanakirjaError>>> {loop {let x: Result<Option<(Vertex<ChangeId>, Edge)>, _> =unsafe { ::sanakirja::next(txn, &mut a.cursor) };match x {Ok(Some((v, e))) => {debug!("adjacent iterator: {:?} {:?}", v, e);if v == a.key {if e.flag >= a.min_flag {if e.flag <= a.max_flag {return Some(Ok(e));} else {return None;}}} else if v > a.key {return None;}}Err(e) => return Some(Err(TxnErr(e.into()))),Ok(None) => {debug!("adjacent iterator: over");return None;}}}}#[doc(hidden)]pub fn find_block<T: ::sanakirja::Transaction>(txn: &T,graph: &::sanakirja::Db<Vertex<ChangeId>, Edge>,p: Position<ChangeId>,) -> Result<Vertex<ChangeId>, BlockError<SanakirjaError>> {if p.change.is_root() {return Ok(Vertex::ROOT);}let key = Vertex {change: p.change,start: p.pos,end: p.pos,};debug!(target: "libpijul::find_block", "find_block {:?}", key);let mut cursor = if let Ok((cursor, _)) = txn.set_cursors(&graph, Some((key, None))) {cursor} else {return Err(BlockError::Txn(SanakirjaError::PristineCorrupt));};let mut k = if let Some((k, _)) = unsafe { next_graph(txn, &mut cursor)? } {k} else {return Err(BlockError::Block { block: p });};debug!("k = {:?}", k);// The only guarantee here is that k is either the first key// >= `key`, or the key just before that. We might need to// rewind by one step if key is strictly larger than the// result (i.e. if `p` is in the middle of the key).while k.change > p.change || (k.change == p.change && k.start > p.pos) {debug!(target: "libpijul::find_block", "find_block while {:?}", k);if let Some((k_, _)) = unsafe { prev_graph(txn, &mut cursor)? } {k = k_} else {break;}}loop {debug!(target: "libpijul::find_block", "find_block loop {:?}", k);if k.change == p.change && k.start <= p.pos {if k.end > p.pos || (k.start == k.end && k.end == p.pos) {return Ok(k);}} else if k.change > p.change {return Err(BlockError::Block { block: p });}if let Some((k_, _)) = unsafe { next_graph(txn, &mut cursor)? } {k = k_} else {break;}}debug!(target: "libpijul::find_block", "find_block None, {:?}", k);Err(BlockError::Block { block: p })}#[doc(hidden)]pub fn find_block_end<T: ::sanakirja::Transaction>(txn: &T,graph: &::sanakirja::Db<Vertex<ChangeId>, Edge>,p: Position<ChangeId>,) -> Result<Vertex<ChangeId>, BlockError<SanakirjaError>> {if p.change.is_root() {return Ok(Vertex::ROOT);}let key = Vertex {change: p.change,start: p.pos,end: p.pos,};debug!(target: "libpijul::find_block_end", "find_block_end {:?}, p.change.0 = {:?}", key, p.change.0);let mut cursor = if let Ok((cursor, _)) = txn.set_cursors(&graph, Some((key, None))) {cursor} else {return Err(BlockError::Txn(SanakirjaError::PristineCorrupt));};let mut k = if let Some((k, _)) = unsafe { next_graph(txn, &mut cursor)? } {k} else {return Err(BlockError::Block { block: p });};// The only guarantee here is that k is either the first key// before `key`, or the key just before that.loop {debug!(target: "libpijul::find_block_end", "find_block_end loop {:?} k.change.0 = {:?}", k, k.change.0);if k.change < p.change {break;} else if k.change == p.change {// Here we want to create an edge pointing between `p`// and its successor. If k.start == p.pos, the only// case where that's what we want is if k.start ==// k.end.if k.start == p.pos && k.end == p.pos {return Ok(k);} else if k.start < p.pos {break;}}if let Some((k_, _)) = unsafe { prev_graph(txn, &mut cursor)? } {k = k_} else {break;}}// We also want k.end >= p.pos, so we just call next() until// we have that.debug!(target: "libpijul::find_block_end", "find_block_end k(0) = {:?} k.change.0 = {:?}", k, k.change.0);while k.change < p.change || (k.change == p.change && p.pos > k.end) {if let Some((k_, _)) = unsafe { next_graph(txn, &mut cursor)? } {k = k_
break;}}debug!(target: "libpijul::find_block_end", "find_block_end k(1) = {:?}, k.change.0 = {:?}", k, k.change.0);if k.change == p.change&& ((k.start < p.pos && p.pos <= k.end) || (k.start == k.end && k.start == p.pos)){debug!("ok");Ok(k)} else {Err(BlockError::Block { block: p })}}pub struct Adj {pub cursor: ::sanakirja::Cursor,pub key: Vertex<ChangeId>,pub min_flag: EdgeFlags,pub max_flag: EdgeFlags,}impl<T: ::sanakirja::Transaction> GraphIter for GenericTxn<T> {type GraphCursor = ::sanakirja::Cursor;fn iter_graph(&self, g: &Self::Graph) -> Result<Self::GraphCursor, TxnErr<Self::GraphError>> {if let Ok((cursor, _)) = self.txn.set_cursors(&g, None) {Ok(cursor)} else {
}}fn next_graph(&self,_: &Self::Graph,a: &mut Self::GraphCursor,) -> Option<Result<(Vertex<ChangeId>, Edge), TxnErr<Self::GraphError>>> {match unsafe { ::sanakirja::next(&self.txn, a) } {Ok(Some(x)) => Some(Ok(x)),Ok(None) => None,Err(::sanakirja::CRCError {}) => Some(Err(TxnErr(SanakirjaError::PristineCorrupt))),
type Revchangeset = Db<u64, (ChangeId, Merkle)>;
fn graph(c: &Channel) -> &Db<Vertex<ChangeId>, Edge> {&c.graph}fn name(c: &Channel) -> &str {c.name.as_str()}fn apply_counter(channel: &Self::Channel) -> u64 {channel.apply_counter}fn last_modified(channel: &Self::Channel) -> u64 {channel.last_modified}fn changes(channel: &Self::Channel) -> &Self::Changeset {&channel.changes}fn rev_changes(channel: &Self::Channel) -> &Self::RevChangeset {&channel.revchanges}type Changeset = ::sanakirja::Db<ChangeId, u64>;type RevChangeset = ::sanakirja::Db<u64, (ChangeId, Merkle)>;
type Channelstates = Db<Merkle, u64>;sanakirja_get!(changeset, ChangeId, u64, GraphError);sanakirja_get!(revchangeset, u64, (ChangeId, Merkle), GraphError);sanakirja_cursor!(changeset, ChangeId, u64);sanakirja_cursor_ref!(revchangeset, u64, (ChangeId, Merkle));sanakirja_rev_cursor!(revchangeset, u64, (ChangeId, Merkle));
fn get_changeset(&self,channel: &Self::Changeset,c: ChangeId,) -> Result<Option<u64>, TxnErr<Self::GraphError>> {if let Ok(x) = self.txn.get(channel, c, None) {Ok(x)} else {Err(TxnErr(SanakirjaError::PristineCorrupt))}}fn get_revchangeset(&self,revchanges: &Self::RevChangeset,c: u64,) -> Result<Option<(ChangeId, Merkle)>, TxnErr<Self::GraphError>> {if let Ok(x) = self.txn.get(revchanges, c, None) {Ok(x)} else {Err(TxnErr(SanakirjaError::PristineCorrupt))}}type ChangesetCursor = ::sanakirja::Cursor;fn cursor_changeset<'a>(&'a self,channel: &Self::Changeset,pos: Option<ChangeId>,) -> Result<Cursor<Self, &'a Self, Self::ChangesetCursor, ChangeId, u64>, TxnErr<SanakirjaError>>{if let Ok((cursor, _)) = self.txn.set_cursors(&channel, pos.map(|x| (x, None))) {Ok(Cursor {cursor,txn: self,marker: std::marker::PhantomData,})} else {Err(TxnErr(SanakirjaError::PristineCorrupt))}}type RevchangesetCursor = ::sanakirja::Cursor;fn cursor_revchangeset_ref<'a, RT: std::ops::Deref<Target = Self>>(txn: RT,channel: &Self::RevChangeset,pos: Option<u64>,) -> Result<Cursor<Self, RT, Self::RevchangesetCursor, u64, (ChangeId, Merkle)>,TxnErr<SanakirjaError>,> {if let Ok((cursor, _)) = txn.txn.set_cursors(channel, pos.map(|x| (x, None))) {Ok(Cursor {cursor,txn,marker: std::marker::PhantomData,})} else {Err(TxnErr(SanakirjaError::PristineCorrupt))}}fn rev_cursor_revchangeset<'a>(&'a self,channel: &Self::RevChangeset,pos: Option<u64>,) -> Result<RevCursor<Self, &'a Self, Self::RevchangesetCursor, u64, (ChangeId, Merkle)>,TxnErr<SanakirjaError>,> {let cursor = if let Some(pos) = pos {if let Ok((x, _)) = self.txn.set_cursors(channel, Some((pos, None))) {x} else {return Err(TxnErr(SanakirjaError::PristineCorrupt));}} else if let Ok(x) = self.txn.set_cursors_last(channel) {x} else {return Err(TxnErr(SanakirjaError::PristineCorrupt));};Ok(RevCursor {cursor,txn: self,marker: std::marker::PhantomData,})}fn cursor_revchangeset_next(&self,cursor: &mut Self::RevchangesetCursor,) -> Result<Option<(u64, (ChangeId, Merkle))>, TxnErr<SanakirjaError>> {if let Ok(x) = unsafe { ::sanakirja::next(&self.txn, cursor) } {Ok(x)} else {Err(TxnErr(SanakirjaError::PristineCorrupt))}}fn cursor_revchangeset_prev(&self,cursor: &mut Self::RevchangesetCursor,) -> Result<Option<(u64, (ChangeId, Merkle))>, TxnErr<SanakirjaError>> {if let Ok(x) = unsafe { ::sanakirja::prev(&self.txn, cursor) } {Ok(x)} else {Err(TxnErr(SanakirjaError::PristineCorrupt))}}fn cursor_changeset_next(&self,cursor: &mut Self::ChangesetCursor,) -> Result<Option<(ChangeId, u64)>, TxnErr<SanakirjaError>> {if let Ok(x) = unsafe { ::sanakirja::next(&self.txn, cursor) } {Ok(x)} else {Err(TxnErr(SanakirjaError::PristineCorrupt))}}fn cursor_changeset_prev(&self,cursor: &mut Self::ChangesetCursor,) -> Result<Option<(ChangeId, u64)>, TxnErr<SanakirjaError>> {if let Ok(x) = unsafe { ::sanakirja::prev(&self.txn, cursor) } {Ok(x)} else {Err(TxnErr(SanakirjaError::PristineCorrupt))}}
}}impl<T: ::sanakirja::Transaction> GenericTxn<T> {#[doc(hidden)]pub unsafe fn unsafe_load_channel(&self,name: SmallString,) -> Result<Option<Channel>, TxnErr<SanakirjaError>> {if let Some((channel, changes, revchanges, states, counter, last_modified)) = self.txn.get(&self.channels,UnsafeSmallStr::from_small_str(name.as_small_str()),None,)? {debug!("unsafe_load_channel: found {:?} {:?}", changes, revchanges);Ok(Some(Channel {graph: channel,changes,revchanges,apply_counter: counter,states,name: name.clone(),last_modified,}))} else {debug!("unsafe_load_channel: not found");Ok(None)}
if let Some((channel, changes, revchanges, states, counter, last_modified)) =self.txn.get(&self.channels,UnsafeSmallStr::from_small_str(name.as_small_str()),None,)?{let r = ChannelRef {r: Rc::new(RefCell::new(Channel {graph: channel,changes,revchanges,apply_counter: counter,states,name: name.clone(),last_modified,})),};v.insert(r);
if let Some(c) = unsafe { self.unsafe_load_channel(name)? } {Ok(Some(v.insert(ChannelRef {r: Rc::new(RefCell::new(c)),}).clone(),))
fn split_block(&mut self,graph: &mut Self::Graph,key: Vertex<ChangeId>,pos: ChangePosition,buf: &mut Vec<Edge>,) -> Result<(), TxnErr<Self::GraphError>> {let (mut cursor, _) = self.txn.set_cursors(graph, Some((key, None)))?;loop {match unsafe { ::sanakirja::next::<_, Vertex<ChangeId>, Edge>(&self.txn, &mut cursor) }{Ok(Some((k, v))) => {if k > key {break;} else if k < key {continue;}buf.push(v)}Ok(None) => break,Err(::sanakirja::CRCError {}) => {return Err(TxnErr(SanakirjaError::PristineCorrupt))}}}for chi in buf.drain(..) {assert!(chi.introduced_by != ChangeId::ROOT || chi.flag.contains(EdgeFlags::PSEUDO));if chi.flag.contains(EdgeFlags::PARENT | EdgeFlags::BLOCK) {put_graph_with_rev(self,graph,chi.flag - EdgeFlags::PARENT,Vertex {change: key.change,start: key.start,end: pos,},Vertex {change: key.change,start: pos,end: key.end,},chi.introduced_by,)?;}self.del_graph(graph, key, Some(chi))?;self.put_graph(graph,if chi.flag.contains(EdgeFlags::PARENT) {Vertex {change: key.change,start: key.start,end: pos,}} else {Vertex {change: key.change,start: pos,end: key.end,}},chi,)?;}Ok(())}
fn graph_mut(c: &mut Self::Channel) -> &mut Self::Graph {&mut c.graph}fn touch_channel(channel: &mut Self::Channel, t: Option<u64>) {use std::time::SystemTime;if let Some(t) = t {channel.last_modified = t} else if let Ok(duration) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {channel.last_modified = duration.as_secs()}}
/// A channel, i.e. a pristine graph plus a set of changes.pub struct Channel<T: ChannelTxnT> {pub graph: T::Graph,pub changes: T::Changeset,pub revchanges: T::Revchangeset,pub states: T::Channelstates,pub apply_counter: ApplyTimestamp,pub(crate) name: SmallString,pub last_modified: u64,}
}}impl<T: ChannelTxnT> Channel<T> {pub fn name(&self) -> &str {self.name.as_str()}}impl<T: ChannelTxnT> Channel<T> {pub(crate) fn touch(&mut self) {use std::time::SystemTime;if let Ok(duration) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {self.last_modified = duration.as_secs();}
type Adj;fn init_adj(&self,g: &Self::Graph,v: Vertex<ChangeId>,dest: Position<ChangeId>,min: EdgeFlags,max: EdgeFlags,) -> Result<Self::Adj, TxnErr<Self::GraphError>>;fn next_adj(&self,g: &Self::Graph,a: &mut Self::Adj,) -> Option<Result<Edge, TxnErr<Self::GraphError>>>;fn find_block(&self,graph: &Self::Graph,p: Position<ChangeId>,) -> Result<Vertex<ChangeId>, BlockError<Self::GraphError>>;fn find_block_end(&self,graph: &Self::Graph,p: Position<ChangeId>,) -> Result<Vertex<ChangeId>, BlockError<Self::GraphError>>;
table!(changeset);get!(changeset, ChangeId, u64, GraphError);cursor!(changeset, ChangeId, u64, GraphError);
type Channel;fn name(channel: &Self::Channel) -> &str;fn graph(channel: &Self::Channel) -> &Self::Graph;fn apply_counter(channel: &Self::Channel) -> u64;fn last_modified(channel: &Self::Channel) -> u64;fn changes(channel: &Self::Channel) -> &Self::Changeset;fn rev_changes(channel: &Self::Channel) -> &Self::RevChangeset;type Changeset;type RevChangeset;fn get_changeset(&self,channel: &Self::Changeset,c: ChangeId,) -> Result<Option<u64>, TxnErr<Self::GraphError>>;fn get_revchangeset(&self,channel: &Self::RevChangeset,c: u64,) -> Result<Option<(ChangeId, Merkle)>, TxnErr<Self::GraphError>>;type ChangesetCursor;fn cursor_changeset<'txn>(&'txn self,channel: &Self::Changeset,pos: Option<ChangeId>,) -> Result<crate::pristine::Cursor<Self, &'txn Self, Self::ChangesetCursor, ChangeId, u64>,TxnErr<Self::GraphError>,>;fn cursor_changeset_next(&self,cursor: &mut Self::ChangesetCursor,) -> Result<Option<(ChangeId, u64)>, TxnErr<Self::GraphError>>;
table!(revchangeset);get!(revchangeset, u64, (ChangeId, Merkle), GraphError);cursor_ref!(revchangeset, u64, (ChangeId, Merkle), GraphError);rev_cursor!(revchangeset, u64, (ChangeId, Merkle), GraphError);
fn cursor_changeset_prev(&self,cursor: &mut Self::ChangesetCursor,) -> Result<Option<(ChangeId, u64)>, TxnErr<Self::GraphError>>;
table!(channelstates);
type RevchangesetCursor;fn cursor_revchangeset_ref<RT: std::ops::Deref<Target = Self>>(txn: RT,channel: &Self::RevChangeset,pos: Option<u64>,) -> Result<Cursor<Self, RT, Self::RevchangesetCursor, u64, (ChangeId, Merkle)>,TxnErr<Self::GraphError>,>;fn rev_cursor_revchangeset<'txn>(&'txn self,channel: &Self::RevChangeset,pos: Option<u64>,) -> Result<RevCursor<Self, &'txn Self, Self::RevchangesetCursor, u64, (ChangeId, Merkle)>,TxnErr<Self::GraphError>,>;fn cursor_revchangeset_next(&self,cursor: &mut Self::RevchangesetCursor,) -> Result<Option<(u64, (ChangeId, Merkle))>, TxnErr<Self::GraphError>>;fn cursor_revchangeset_prev(&self,cursor: &mut Self::RevchangesetCursor,) -> Result<Option<(u64, (ChangeId, Merkle))>, TxnErr<Self::GraphError>>;}pub trait GraphIter: GraphTxnT {type GraphCursor;fn iter_graph(&self, g: &Self::Graph) -> Result<Self::GraphCursor, TxnErr<Self::GraphError>>;fn next_graph(&self,g: &Self::Graph,a: &mut Self::GraphCursor,) -> Option<Result<(Vertex<ChangeId>, Edge), TxnErr<Self::GraphError>>>;}#[derive(Debug, Error)]pub enum BlockError<T: std::error::Error + 'static> {#[error(transparent)]Txn(T),#[error("Block error: {:?}", block)]Block { block: Position<ChangeId> },}impl<T: std::error::Error + 'static> std::convert::From<TxnErr<T>> for BlockError<T> {fn from(e: TxnErr<T>) -> Self {BlockError::Txn(e.0)}
/// Returns a handle to the channel with name `name`, if it/// exists. In order to prevent memory leaks, channels have to be/// committed after use.////// See the note about the return type of/// [`MutTxnT::open_or_create_channel`](trait.MutTxnT.html#tymethod.open_or_create_channel)./// Since a mutable transaction type could implement both this/// trait and [`MutTxnT`](trait.MutTxnT.html), the return type of/// this function must use the same logic as the return type of/// [`MutTxnT::open_or_create_channel`](trait.MutTxnT.html#tymethod.open_or_create_channel).
}pub(crate) fn iter_graph<'txn, T: GraphTxnT>(txn: &'txn T,graph: &T::Graph,k: Vertex<ChangeId>,v: Option<Edge>,) -> Result<Cursor<T, &'txn T, T::GraphCursor, Vertex<ChangeId>, Edge>, TxnErr<T::GraphError>> {txn.cursor_graph(graph, Some((k, v)))
pub(crate) fn iter_graph_ref<T: GraphTxnT, RT: std::ops::Deref<Target = T>>(txn: RT,graph: &T::Graph,k: Vertex<ChangeId>,v: Option<Edge>,) -> Result<Cursor<T, RT, T::GraphCursor, Vertex<ChangeId>, Edge>, TxnErr<T::GraphError>> {T::cursor_graph_ref(txn, graph, Some((k, v)))}
let key = Vertex {change: a.change,start: a.pos,end: a.pos,};let edge = Edge {flag: min,dest: b,introduced_by: ChangeId::ROOT,};let mut cursor = txn.cursor_graph(&channel, Some((key, Some(edge))))?;let (a_, b_) = cursor.next().unwrap()?;Ok(a_.change == a.change&& a_.start <= a.pos&& a_.end >= a.pos&& b_.flag >= min&& b_.flag <= max&& b_.dest == b)
let mut adj = txn.init_adj(channel, a.inode_vertex(), b, min, max)?;match txn.next_adj(channel, &mut adj) {Some(Ok(dest)) => Ok(dest.dest == b),Some(Err(e)) => Err(e.into()),None => Ok(false),}
it: Cursor<T, &'txn T, T::GraphCursor, Vertex<ChangeId>, Edge>,key: Vertex<ChangeId>,min_flag: EdgeFlags,/// iter as long as the flag is smaller than thismax_flag: EdgeFlags,
it: T::Adj,graph: &'txn T::Graph,txn: &'txn T,
loop {match self.it.next() {Some(Ok((v, e))) => {debug!("adjacent iterator: {:?} {:?}", v, e);if v == self.key {if e.flag >= self.min_flag {if e.flag <= self.max_flag {return Some(Ok(e));} else {return None;}}} else if v > self.key {return None;}}Some(Err(e)) => return Some(Err(e)),None => {debug!("adjacent iterator: over");return None;}}}
self.txn.next_adj(self.graph, &mut self.it)
/// Split a key `[a, b[` at position `pos`, yielding two keys `[a,/// pos[` and `[pos, b[` linked by an edge.fn split_block(&mut self,graph: &mut Self::Graph,key: Vertex<ChangeId>,pos: ChangePosition,buf: &mut Vec<Edge>,) -> Result<(), TxnErr<Self::GraphError>>;
/// Split a key `[a, b[` at position `pos`, yielding two keys `[a,/// pos[` and `[pos, b[` linked by an edge.pub(crate) fn split_block<T: GraphMutTxnT>(txn: &mut T,graph: &mut T::Graph,key: Vertex<ChangeId>,pos: ChangePosition,buf: &mut Vec<Edge>,) -> Result<(), TxnErr<T::GraphError>> {for x in txn.cursor_graph(graph, Some((key, None)))? {let (k, v) = x?;if k > key {break;} else if k < key {continue;}buf.push(v)}for chi in buf.drain(..) {assert!(chi.introduced_by != ChangeId::ROOT || chi.flag.contains(EdgeFlags::PSEUDO));if chi.flag.contains(EdgeFlags::PARENT | EdgeFlags::BLOCK) {put_graph_with_rev(txn,graph,chi.flag - EdgeFlags::PARENT,Vertex {change: key.change,start: key.start,end: pos,},Vertex {change: key.change,start: pos,end: key.end,},chi.introduced_by,)?;}txn.del_graph(graph, key, Some(chi))?;txn.put_graph(graph,if chi.flag.contains(EdgeFlags::PARENT) {Vertex {change: key.change,start: key.start,end: pos,}} else {Vertex {change: key.change,start: pos,end: key.end,}},chi,)?;}Ok(())}
let graph = crate::alive::retrieve::retrieve(txn, &channel.graph, file_).unwrap();graph.debug(changes, txn, &channel.graph, false, false, &mut f)?;
let graph = crate::alive::retrieve::retrieve(txn, T::graph(channel), file_).unwrap();graph.debug(changes, txn, T::graph(channel), false, false, &mut f)?;
graph: match iter_graph_ref(self.txn.clone(),&self.channel.graph,Vertex::ROOT,None,) {Ok(x) => x,
cursor: match self.txn.iter_graph(T::graph(&self.channel)) {Ok(c) => c,
let source = find_block_end(txn, &channel, internal_pos(txn, &e.from, change_id)?)?;let target = find_block(txn,&channel,internal_pos(txn, &e.to.start_pos(), change_id)?,)?;
let source = txn.find_block_end(&channel, internal_pos(txn, &e.from, change_id)?)?;let target = txn.find_block(&channel, internal_pos(txn, &e.to.start_pos(), change_id)?)?;
Base32, ChangeId, Channel, ChannelRef, ChannelTxnT, DepsTxnT, EdgeFlags, GraphTxnT, Hash,Inode, Merkle, MutTxnT, OwnedPathId, RemoteRef, TreeTxnT, TxnT, Vertex,
Base32, ChangeId, ChannelRef, ChannelTxnT, DepsTxnT, EdgeFlags, GraphTxnT, Hash, Inode, Merkle,MutTxnT, OwnedPathId, RemoteRef, TreeTxnT, TxnT, Vertex,
impl<'txn, 'channel, 'changes, T: GraphTxnT, P: ChangeStore + 'changes> Iteratorfor GraphChildren<'txn, 'channel, 'changes, T, P>
impl<'txn, 'changes, T: GraphTxnT, P: ChangeStore + 'changes> Iteratorfor GraphChildren<'txn, 'changes, T, P>
impl<'txn, 'channel, 'changes, T: GraphTxnT, P: ChangeStore + 'changes> Iteratorfor GraphBasenames<'txn, 'channel, 'changes, T, P>
impl<'txn, 'changes, T: GraphTxnT, P: ChangeStore + 'changes> Iteratorfor GraphBasenames<'txn, 'changes, T, P>
for x in iter_graph(txn, &graph, cur_key.inode_vertex(), Some(e)).map_err(|e| e.0)? {let (k, parent) = x.map_err(|e| e.0)?;if k != cur_key.inode_vertex() {break;} else if !parent.flag.contains(EdgeFlags::FOLDER | EdgeFlags::PARENT) {continue;
let f = EdgeFlags::parent_folder();for parent in iter_adjacent(txn,&graph,cur_key.inode_vertex(),f,f | EdgeFlags::PSEUDO,)? {let parent_dest = txn.find_block_end(&graph, parent?.dest).unwrap();for grandparent initer_adjacent(txn, &graph, parent_dest, f, f | EdgeFlags::PSEUDO)?{stack.push((grandparent?.dest, false))
let parent_dest = find_block_end(txn, &graph, parent.dest).unwrap();for x in iter_graph(txn, &graph, parent_dest, Some(e)).map_err(|e| e.0)? {let (k, grandparent) = x.map_err(|e| e.0)?;if k != parent_dest {break;}if grandparent.flag.contains(EdgeFlags::FOLDER | EdgeFlags::PARENT){stack.push((grandparent.dest, false))}}
add_zombie_deps_from(txn, &channel.graph, &mut zombie_deps, e.from)?;add_zombie_deps_to(txn, &channel.graph, &mut zombie_deps, e.to)?
add_zombie_deps_from(txn, T::graph(channel), &mut zombie_deps, e.from)?;add_zombie_deps_to(txn, T::graph(channel), &mut zombie_deps, e.to)?
repair_missing_contexts(txn, &mut channel.graph, ws, change_id, change)?;repair_cyclic_paths(txn, &mut channel.graph, ws)?;
repair_missing_contexts(txn, T::graph_mut(channel), ws, change_id, change)?;repair_cyclic_paths(txn, T::graph_mut(channel), ws)?;
let p = find_block(txn, channel, e.dest)?;apply.children.insert(p);
let p = txn.find_block(channel, e.dest)?;if !e.flag.contains(EdgeFlags::PSEUDO) || is_alive(txn, channel, p).unwrap() {apply.children.insert(p);}