Adding the block module

[?]
Nov 25, 2020, 6:43 PM
ERV3644QELKOHAVNMZGRWYCPPN3XELTAH4PPFR6QKGWW73XBOOKQC

Dependencies

  • [2] SXEYMYF7 Fixing the bad changes in history (unfortunately, by rebooting).

Change contents

  • file addition: block.rs (-xw-x--x--)
    [2.525229]
    use super::*;
    /// Find the key where a position is.
    pub(crate) fn find_block<'db, 'txn: 'db, T: TxnT>(
    txn: &'txn T,
    channel: &'db Channel<T>,
    p: Position<ChangeId>,
    ) -> Result<Vertex<ChangeId>, crate::Error> {
    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 = txn.cursor_graph(&channel.graph, Some((key, None)));
    let mut k = if let Some((k, _)) = cursor.next() {
    k
    } else {
    return Err(crate::Error::WrongBlock { 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_, _)) = cursor.prev() {
    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(crate::Error::WrongBlock { block: p });
    }
    if let Some((k_, _)) = cursor.next() {
    k = k_
    } else {
    break;
    }
    }
    debug!(target: "libpijul::find_block", "find_block None, {:?}", k);
    Err(crate::Error::WrongBlock { block: p })
    }
    /// Find the key ending at a position.
    pub(crate) fn find_block_end<'db, 'txn: 'db, T: TxnT>(
    txn: &'txn T,
    channel: &'db Channel<T>,
    p: Position<ChangeId>,
    ) -> Result<Vertex<ChangeId>, crate::Error> {
    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 = txn.cursor_graph(&channel.graph, Some((key, None)));
    let mut k = if let Some((k, _)) = cursor.next() {
    k
    } else {
    return Err(crate::Error::WrongBlock { 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 {
    break;
    } else if k.start < p.pos {
    break;
    }
    }
    if let Some((k_, _)) = cursor.prev() {
    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_, _)) = cursor.next() {
    k = k_
    } 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(crate::Error::WrongBlock { block: p })
    }
    }