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_?.0
if let Some(k_) = cursor.prev() {
k = k_?.0
if 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_?.0
return Err(BlockError::Block { block: p });
if let Some(k_) = cursor.prev() {
k = k_?.0
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<'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 this
max_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> Iterator
for GraphChildren<'txn, 'channel, 'changes, T, P>
impl<'txn, 'changes, T: GraphTxnT, P: ChangeStore + 'changes> Iterator
for GraphChildren<'txn, 'changes, T, P>
impl<'txn, 'channel, 'changes, T: GraphTxnT, P: ChangeStore + 'changes> Iterator
for GraphBasenames<'txn, 'channel, 'changes, T, P>
impl<'txn, 'changes, T: GraphTxnT, P: ChangeStore + 'changes> Iterator
for 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 in
iter_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);
}