Skip to main content

pijul_core/pristine/
sanakirja.rs

1use super::*;
2use crate::HashMap;
3use ::sanakirja::*;
4use parking_lot::Mutex;
5use std::collections::hash_map::Entry;
6#[cfg(feature = "mmap")]
7use std::path::Path;
8use std::sync::Arc;
9
10/// A Sanakirja pristine.
11pub struct Pristine {
12    pub env: Arc<::sanakirja::Env>,
13}
14
15pub(crate) type P<K, V> = btree::page::Page<K, V>;
16pub type Db<K, V> = btree::Db<K, V>;
17pub(crate) type UP<K, V> = btree::page_unsized::Page<K, V>;
18pub type UDb<K, V> = btree::Db_<K, V, UP<K, V>>;
19
20#[derive(Debug, Error)]
21pub enum SanakirjaError {
22    #[error(transparent)]
23    Sanakirja(#[from] ::sanakirja::Error),
24    #[error("Pristine locked")]
25    PristineLocked,
26    #[error("Pristine corrupt")]
27    PristineCorrupt,
28    #[error(transparent)]
29    Borrow(#[from] std::cell::BorrowError),
30    #[error("Cannot dropped a borrowed channel: {:?}", c)]
31    ChannelRc { c: String },
32    #[error("Pristine version mismatch. Cloning over the network can fix this.")]
33    Version,
34}
35
36impl std::convert::From<::sanakirja::CRCError> for SanakirjaError {
37    fn from(_: ::sanakirja::CRCError) -> Self {
38        SanakirjaError::PristineCorrupt
39    }
40}
41
42impl std::convert::From<::sanakirja::CRCError> for TxnErr<SanakirjaError> {
43    fn from(_: ::sanakirja::CRCError) -> Self {
44        TxnErr(SanakirjaError::PristineCorrupt)
45    }
46}
47
48impl std::convert::From<::sanakirja::Error> for TxnErr<SanakirjaError> {
49    fn from(e: ::sanakirja::Error) -> Self {
50        TxnErr(e.into())
51    }
52}
53
54impl std::convert::From<::sanakirja::Error> for TreeErr<SanakirjaError> {
55    fn from(e: ::sanakirja::Error) -> Self {
56        TreeErr(e.into())
57    }
58}
59
60impl std::convert::From<TxnErr<::sanakirja::Error>> for TxnErr<SanakirjaError> {
61    fn from(e: TxnErr<::sanakirja::Error>) -> Self {
62        TxnErr(e.0.into())
63    }
64}
65
66impl std::convert::From<TreeErr<::sanakirja::Error>> for TreeErr<SanakirjaError> {
67    fn from(e: TreeErr<::sanakirja::Error>) -> Self {
68        TreeErr(e.0.into())
69    }
70}
71
72impl Pristine {
73    #[cfg(feature = "mmap")]
74    pub fn new<P: AsRef<Path>>(name: P) -> Result<Self, SanakirjaError> {
75        Self::new_with_size(name, 1 << 20)
76    }
77
78    /// # Safety
79    ///
80    /// Multiple processes might be writing to the same memory-mapped
81    /// file, leading to corruption. If you use this, make sure you
82    /// have another locking mechanism in place on the file.
83    #[cfg(feature = "mmap")]
84    pub unsafe fn new_nolock<P: AsRef<Path>>(name: P) -> Result<Self, SanakirjaError> {
85        unsafe { Self::new_with_size_nolock(name, 1 << 20) }
86    }
87
88    #[cfg(feature = "mmap")]
89    pub fn new_with_size<P: AsRef<Path>>(name: P, size: u64) -> Result<Self, SanakirjaError> {
90        let env = ::sanakirja::Env::new(name, size, 2);
91        match env {
92            Ok(env) => Ok(Pristine { env: Arc::new(env) }),
93            Err(::sanakirja::Error::IO(e)) => {
94                if let std::io::ErrorKind::WouldBlock = e.kind() {
95                    Err(SanakirjaError::PristineLocked)
96                } else {
97                    Err(SanakirjaError::Sanakirja(::sanakirja::Error::IO(e)))
98                }
99            }
100            Err(e) => Err(SanakirjaError::Sanakirja(e)),
101        }
102    }
103
104    /// # Safety
105    ///
106    /// Same as new_nolock:
107    ///
108    /// Multiple processes might be writing to the same memory-mapped
109    /// file, leading to corruption. If you use this, make sure you
110    /// have another locking mechanism in place on the file.
111    #[cfg(feature = "mmap")]
112    pub unsafe fn new_with_size_nolock<P: AsRef<Path>>(
113        name: P,
114        size: u64,
115    ) -> Result<Self, SanakirjaError> {
116        unsafe {
117            Ok(Pristine {
118                env: Arc::new(::sanakirja::Env::new_nolock(name, size, 2)?),
119            })
120        }
121    }
122    pub fn new_anon() -> Result<Self, SanakirjaError> {
123        Self::new_anon_with_size(1 << 20)
124    }
125    pub fn new_anon_with_size(size: u64) -> Result<Self, SanakirjaError> {
126        Ok(Pristine {
127            env: Arc::new(::sanakirja::Env::new_anon(size, 2)?),
128        })
129    }
130}
131
132#[derive(Debug, PartialEq, Clone, Copy)]
133#[repr(usize)]
134pub enum Root {
135    Version,
136    Tree,
137    RevTree,
138    Inodes,
139    RevInodes,
140    Internal,
141    External,
142    RevDep,
143    Channels,
144    TouchedFiles,
145    Dep,
146    RevTouchedFiles,
147    Partials,
148    Remotes,
149    Git0,
150    Git1,
151}
152
153const VERSION: u64 = 1u64;
154
155impl Pristine {
156    pub fn txn_begin(&self) -> Result<Txn, SanakirjaError> {
157        let txn = ::sanakirja::Env::txn_begin(self.env.clone())?;
158        if txn.root(Root::Version as usize) != VERSION {
159            return Err(SanakirjaError::Version);
160        }
161        debug!("txn_begin");
162        fn begin(txn: ::sanakirja::Txn<Arc<::sanakirja::Env>>) -> Option<Txn> {
163            Some(Txn {
164                channels: txn.root_db(Root::Channels as usize)?,
165                external: txn.root_db(Root::External as usize)?,
166                internal: txn.root_db(Root::Internal as usize)?,
167                inodes: txn.root_db(Root::Inodes as usize)?,
168                revinodes: txn.root_db(Root::RevInodes as usize)?,
169                tree: txn.root_db(Root::Tree as usize)?,
170                revtree: txn.root_db(Root::RevTree as usize)?,
171                revdep: txn.root_db(Root::RevDep as usize)?,
172                touched_files: txn.root_db(Root::TouchedFiles as usize)?,
173                rev_touched_files: txn.root_db(Root::RevTouchedFiles as usize)?,
174                partials: txn.root_db(Root::Partials as usize)?,
175                dep: txn.root_db(Root::Dep as usize)?,
176                remotes: txn.root_db(Root::Remotes as usize)?,
177                open_channels: Mutex::new(HashMap::default()),
178                open_remotes: Mutex::new(HashMap::default()),
179                txn,
180                counter: 0,
181                cur_channel: None,
182            })
183        }
184        debug!("txn begin done");
185        match begin(txn) {
186            Some(txn) => Ok(txn),
187            _ => Err(SanakirjaError::PristineCorrupt),
188        }
189    }
190
191    pub fn arc_txn_begin(
192        &self,
193    ) -> Result<ArcTxn<MutTxn<::sanakirja::MutTxn<Arc<::sanakirja::Env>>>>, SanakirjaError> {
194        Ok(ArcTxn(Arc::new(RwLock::new(self.mut_txn_begin()?))))
195    }
196
197    pub fn mut_txn_begin(
198        &self,
199    ) -> Result<MutTxn<::sanakirja::MutTxn<Arc<::sanakirja::Env>>>, SanakirjaError> {
200        unsafe {
201            let mut txn = ::sanakirja::Env::mut_txn_begin(self.env.clone()).unwrap();
202            if let Some(version) = txn.root(Root::Version as usize) {
203                if version != VERSION {
204                    return Err(SanakirjaError::Version);
205                }
206            } else {
207                txn.set_root(Root::Version as usize, VERSION);
208            }
209            Ok(MutTxn {
210                channels: if let Some(db) = txn.root_db(Root::Channels as usize) {
211                    db
212                } else {
213                    btree::create_db_(&mut txn)?
214                },
215                external: if let Some(db) = txn.root_db(Root::External as usize) {
216                    db
217                } else {
218                    btree::create_db_(&mut txn)?
219                },
220                internal: if let Some(db) = txn.root_db(Root::Internal as usize) {
221                    db
222                } else {
223                    btree::create_db_(&mut txn)?
224                },
225                inodes: if let Some(db) = txn.root_db(Root::Inodes as usize) {
226                    db
227                } else {
228                    btree::create_db_(&mut txn)?
229                },
230                revinodes: if let Some(db) = txn.root_db(Root::RevInodes as usize) {
231                    db
232                } else {
233                    btree::create_db_(&mut txn)?
234                },
235                tree: if let Some(db) = txn.root_db(Root::Tree as usize) {
236                    db
237                } else {
238                    btree::create_db_(&mut txn)?
239                },
240                revtree: if let Some(db) = txn.root_db(Root::RevTree as usize) {
241                    db
242                } else {
243                    btree::create_db_(&mut txn)?
244                },
245                revdep: if let Some(db) = txn.root_db(Root::RevDep as usize) {
246                    db
247                } else {
248                    btree::create_db_(&mut txn)?
249                },
250                dep: if let Some(db) = txn.root_db(Root::Dep as usize) {
251                    db
252                } else {
253                    btree::create_db_(&mut txn)?
254                },
255                touched_files: if let Some(db) = txn.root_db(Root::TouchedFiles as usize) {
256                    db
257                } else {
258                    btree::create_db_(&mut txn)?
259                },
260                rev_touched_files: if let Some(db) = txn.root_db(Root::RevTouchedFiles as usize) {
261                    db
262                } else {
263                    btree::create_db_(&mut txn)?
264                },
265                partials: if let Some(db) = txn.root_db(Root::Partials as usize) {
266                    db
267                } else {
268                    btree::create_db_(&mut txn)?
269                },
270                remotes: if let Some(db) = txn.root_db(Root::Remotes as usize) {
271                    db
272                } else {
273                    btree::create_db_(&mut txn)?
274                },
275                open_channels: Mutex::new(HashMap::default()),
276                open_remotes: Mutex::new(HashMap::default()),
277                txn,
278                counter: 0,
279                cur_channel: None,
280            })
281        }
282    }
283}
284
285pub type Txn = GenericTxn<::sanakirja::Txn<Arc<::sanakirja::Env>>>;
286pub type MutTxn<T> = GenericTxn<T>;
287pub type MutTxn0 = GenericTxn<::sanakirja::MutTxn<Arc<::sanakirja::Env>>>;
288pub trait RawMutTxnT:
289    ::sanakirja::AllocPage<Error = ::sanakirja::Error>
290    + ::sanakirja::RootPageMut
291    + ::sanakirja::Commit
292    + ::sanakirja::LoadPage<Error = ::sanakirja::Error>
293{
294}
295
296impl<
297    T: ::sanakirja::AllocPage<Error = ::sanakirja::Error>
298        + ::sanakirja::RootPageMut
299        + ::sanakirja::Commit
300        + ::sanakirja::LoadPage<Error = ::sanakirja::Error>,
301> RawMutTxnT for T
302{
303}
304
305/// A transaction, used both for mutable and immutable transactions,
306/// depending on type parameter `T`.
307///
308/// In Sanakirja, both `sanakirja::Txn` and `sanakirja::MutTxn`
309/// implement `sanakirja::Transaction`, explaining our implementation
310/// of `TxnT` for `Txn<T>` for all `T: sanakirja::Transaction`. This
311/// covers both mutable and immutable transactions in a single
312/// implementation.
313pub struct GenericTxn<T: ::sanakirja::LoadPage<Error = ::sanakirja::Error> + ::sanakirja::RootPage>
314{
315    #[doc(hidden)]
316    pub txn: T,
317    #[doc(hidden)]
318    pub internal: UDb<SerializedHash, ChangeId>,
319    #[doc(hidden)]
320    pub external: UDb<ChangeId, SerializedHash>,
321    pub inodes: Db<Inode, Position<ChangeId>>,
322    pub revinodes: Db<Position<ChangeId>, Inode>,
323
324    pub tree: UDb<PathId, Inode>,
325    pub revtree: UDb<Inode, PathId>,
326
327    revdep: Db<ChangeId, ChangeId>,
328    dep: Db<ChangeId, ChangeId>,
329
330    touched_files: Db<Position<ChangeId>, ChangeId>,
331    rev_touched_files: Db<ChangeId, Position<ChangeId>>,
332
333    partials: UDb<SmallStr, Position<ChangeId>>,
334    channels: UDb<SmallStr, SerializedChannel>,
335    remotes: UDb<RemoteId, SerializedRemote>,
336
337    pub(crate) open_channels: Mutex<HashMap<SmallString, ChannelRef<Self>>>,
338    open_remotes: Mutex<HashMap<RemoteId, RemoteRef<Self>>>,
339    counter: usize,
340    cur_channel: Option<String>,
341}
342
343direct_repr!(SerializedPublicKey);
344
345/// This is actually safe because the only non-Send fields are
346/// `open_channels` and `open_remotes`, but we can't do anything with
347/// a `ChannelRef` whose transaction has been moved to another thread.
348unsafe impl<T: ::sanakirja::LoadPage<Error = ::sanakirja::Error> + ::sanakirja::RootPage> Send
349    for GenericTxn<T>
350{
351}
352
353impl Txn {
354    pub fn check_database(&self, refs: &mut std::collections::BTreeMap<u64, usize>) {
355        unsafe {
356            use ::sanakirja::debug::Check;
357            debug!("check: internal 0x{:x}", self.internal.db);
358            self.internal.add_refs(&self.txn, refs).unwrap();
359            debug!("check: external 0x{:x}", self.external.db);
360            self.external.add_refs(&self.txn, refs).unwrap();
361            debug!("check: inodes 0x{:x}", self.inodes.db);
362            self.inodes.add_refs(&self.txn, refs).unwrap();
363            debug!("check: revinodes 0x{:x}", self.revinodes.db);
364            self.revinodes.add_refs(&self.txn, refs).unwrap();
365            debug!("check: tree 0x{:x}", self.tree.db);
366            self.tree.add_refs(&self.txn, refs).unwrap();
367            debug!("check: revtree 0x{:x}", self.revtree.db);
368            self.revtree.add_refs(&self.txn, refs).unwrap();
369            debug!("check: revdep 0x{:x}", self.revdep.db);
370            self.revdep.add_refs(&self.txn, refs).unwrap();
371            debug!("check: dep 0x{:x}", self.dep.db);
372            self.dep.add_refs(&self.txn, refs).unwrap();
373            debug!("check: touched_files 0x{:x}", self.touched_files.db);
374            self.touched_files.add_refs(&self.txn, refs).unwrap();
375            debug!("check: rev_touched_files 0x{:x}", self.rev_touched_files.db);
376            self.rev_touched_files.add_refs(&self.txn, refs).unwrap();
377            debug!("check: partials 0x{:x}", self.partials.db);
378            self.partials.add_refs(&self.txn, refs).unwrap();
379            debug!("check: channels 0x{:x}", self.channels.db);
380            self.channels.add_refs(&self.txn, refs).unwrap();
381            for x in btree::iter(&self.txn, &self.channels, None).unwrap() {
382                let (name, tup) = x.unwrap();
383                debug!("check: channel name: {:?}", name.as_str());
384                let graph: Db<Vertex<ChangeId>, SerializedEdge> = Db::from_page(tup.graph.into());
385                let changes: Db<ChangeId, L64> = Db::from_page(tup.changes.into());
386                let revchanges: UDb<L64, Pair<ChangeId, SerializedMerkle>> =
387                    UDb::from_page(tup.revchanges.into());
388                let states: UDb<SerializedMerkle, L64> = UDb::from_page(tup.states.into());
389                let tags: Db<L64, Pair<SerializedMerkle, SerializedMerkle>> =
390                    Db::from_page(tup.tags.into());
391                debug!("check: graph 0x{:x}", graph.db);
392                graph.add_refs(&self.txn, refs).unwrap();
393                debug!("check: changes 0x{:x}", changes.db);
394                changes.add_refs(&self.txn, refs).unwrap();
395                debug!("check: revchanges 0x{:x}", revchanges.db);
396                revchanges.add_refs(&self.txn, refs).unwrap();
397                debug!("check: states 0x{:x}", states.db);
398                states.add_refs(&self.txn, refs).unwrap();
399                debug!("check: tags 0x{:x}", tags.db);
400                tags.add_refs(&self.txn, refs).unwrap();
401            }
402            debug!("check: remotes 0x{:x}", self.remotes.db);
403            self.remotes.add_refs(&self.txn, refs).unwrap();
404            for x in btree::iter(&self.txn, &self.remotes, None).unwrap() {
405                let (name, tup) = x.unwrap();
406                debug!("check: remote name: {:?}", name);
407                let remote: UDb<L64, Pair<SerializedHash, SerializedMerkle>> =
408                    UDb::from_page(tup.remote.into());
409
410                let rev: UDb<SerializedHash, L64> = UDb::from_page(tup.rev.into());
411                let states: UDb<SerializedMerkle, L64> = UDb::from_page(tup.states.into());
412                let tags: UDb<L64, Pair<SerializedMerkle, SerializedMerkle>> =
413                    UDb::from_page(tup.tags.into());
414                debug!("check: remote 0x{:x}", remote.db);
415                remote.add_refs(&self.txn, refs).unwrap();
416                debug!("check: rev 0x{:x}", rev.db);
417                rev.add_refs(&self.txn, refs).unwrap();
418                debug!("check: states 0x{:x}", states.db);
419                states.add_refs(&self.txn, refs).unwrap();
420                debug!("check: tags 0x{:x}", tags.db);
421                tags.add_refs(&self.txn, refs).unwrap();
422            }
423            ::sanakirja::debug::add_free_refs(&self.txn, refs).unwrap();
424            ::sanakirja::debug::check_free(&self.txn, refs);
425        }
426    }
427}
428
429impl<T: ::sanakirja::LoadPage<Error = ::sanakirja::Error> + ::sanakirja::RootPage> GraphTxnT
430    for GenericTxn<T>
431{
432    type Graph = Channel;
433    type GraphError = SanakirjaError;
434
435    fn get_graph<'txn>(
436        &'txn self,
437        db: &Self::Graph,
438        key: &Vertex<ChangeId>,
439        value: Option<&SerializedEdge>,
440    ) -> Result<Option<&'txn SerializedEdge>, TxnErr<Self::GraphError>> {
441        match ::sanakirja::btree::get(&self.txn, &db.graph, key, value) {
442            Ok(Some((k, v))) if k == key => Ok(Some(v)),
443            Ok(_) => Ok(None),
444            Err(e) => {
445                error!("{:?}", e);
446                Err(TxnErr(SanakirjaError::PristineCorrupt))
447            }
448        }
449    }
450
451    fn get_external(
452        &self,
453        p: &ChangeId,
454    ) -> Result<&SerializedHash, GetExternalError<Self::GraphError>> {
455        debug!("get_external {:?}", p);
456        if p.is_root() {
457            Ok(&HASH_NONE)
458        } else {
459            match btree::get(&self.txn, &self.external, p, None) {
460                Ok(Some((k, v))) if k == p => Ok(v),
461                Ok(_) => Err(GetExternalError::NotFound),
462                Err(e) => {
463                    error!("{:?}", e);
464                    Err(GetExternalError::Txn(SanakirjaError::PristineCorrupt))
465                }
466            }
467        }
468    }
469
470    fn get_internal(
471        &self,
472        p: &SerializedHash,
473    ) -> Result<Option<&ChangeId>, TxnErr<Self::GraphError>> {
474        if p.t == HashAlgorithm::None as u8 {
475            Ok(Some(&ChangeId::ROOT))
476        } else {
477            match btree::get(&self.txn, &self.internal, p, None) {
478                Ok(Some((k, v))) if k == p => Ok(Some(v)),
479                Ok(_) => Ok(None),
480                Err(e) => {
481                    error!("{:?}", e);
482                    Err(TxnErr(SanakirjaError::PristineCorrupt))
483                }
484            }
485        }
486    }
487
488    type Adj = Adj;
489
490    fn init_adj(
491        &self,
492        g: &Self::Graph,
493        key: Vertex<ChangeId>,
494        dest: Position<ChangeId>,
495        min_flag: EdgeFlags,
496        max_flag: EdgeFlags,
497    ) -> Result<Self::Adj, TxnErr<Self::GraphError>> {
498        let edge = SerializedEdge::new(min_flag, dest.change, dest.pos, ChangeId::ROOT);
499        let mut cursor = btree::cursor::Cursor::new(&self.txn, &g.graph).map_err(TxnErr)?;
500        cursor.set(&self.txn, &key, Some(&edge))?;
501        Ok(Adj {
502            cursor,
503            key,
504            min_flag,
505            max_flag,
506        })
507    }
508
509    fn next_adj<'a>(
510        &'a self,
511        _: &Self::Graph,
512        a: &mut Self::Adj,
513    ) -> Option<Result<&'a SerializedEdge, TxnErr<Self::GraphError>>> {
514        next_adj(&self.txn, a).map(|x| x.map_err(|x| TxnErr(x.into())))
515    }
516
517    fn find_block(
518        &self,
519        graph: &Self::Graph,
520        p: Position<ChangeId>,
521    ) -> Result<&Vertex<ChangeId>, BlockError<Self::GraphError>> {
522        Ok(find_block(&self.txn, &graph.graph, p)?)
523    }
524
525    fn find_block_end(
526        &self,
527        graph: &Self::Graph,
528        p: Position<ChangeId>,
529    ) -> Result<&Vertex<ChangeId>, BlockError<Self::GraphError>> {
530        Ok(find_block_end(&self.txn, &graph.graph, p)?)
531    }
532}
533
534impl std::convert::From<BlockError<::sanakirja::Error>> for BlockError<SanakirjaError> {
535    fn from(e: BlockError<::sanakirja::Error>) -> Self {
536        match e {
537            BlockError::Txn(t) => BlockError::Txn(t.into()),
538            BlockError::Block { block } => BlockError::Block { block },
539        }
540    }
541}
542
543#[doc(hidden)]
544pub fn next_adj<'a, T: ::sanakirja::LoadPage>(
545    txn: &'a T,
546    a: &mut Adj,
547) -> Option<Result<&'a SerializedEdge, T::Error>>
548where
549    T::Error: std::error::Error,
550{
551    loop {
552        let x: Result<Option<(&Vertex<ChangeId>, &SerializedEdge)>, _> = a.cursor.next(txn);
553        match x {
554            Ok(Some((v, e))) => {
555                if *v == a.key {
556                    if e.flag() >= a.min_flag {
557                        if e.flag() <= a.max_flag {
558                            return Some(Ok(e));
559                        } else {
560                            return None;
561                        }
562                    }
563                } else if *v > a.key {
564                    return None;
565                }
566            }
567            Err(e) => return Some(Err(e)),
568            Ok(None) => {
569                return None;
570            }
571        }
572    }
573}
574
575#[doc(hidden)]
576pub fn find_block<'a, T: ::sanakirja::LoadPage>(
577    txn: &'a T,
578    graph: &::sanakirja::btree::Db<Vertex<ChangeId>, SerializedEdge>,
579    p: Position<ChangeId>,
580) -> Result<&'a Vertex<ChangeId>, BlockError<T::Error>>
581where
582    T::Error: std::error::Error,
583{
584    if p.change.is_root() {
585        return Ok(&Vertex::ROOT);
586    }
587    let key = Vertex {
588        change: p.change,
589        start: p.pos,
590        end: p.pos,
591    };
592    let mut cursor = btree::cursor::Cursor::new(txn, graph).map_err(BlockError::Txn)?;
593    let mut k = if let Some((k, _)) = cursor.set(txn, &key, None).map_err(BlockError::Txn)? {
594        k
595    } else if let Some((k, _)) = cursor.prev(txn).map_err(BlockError::Txn)? {
596        k
597    } else {
598        debug!("find_block: BLOCK ERROR");
599        return Err(BlockError::Block { block: p });
600    };
601    // The only guarantee here is that k is either the first key >=
602    // `key`. We might need to rewind by one step if key is strictly
603    // larger than the result (i.e. if `p` is in the middle of the
604    // key).
605    while k.change > p.change || (k.change == p.change && k.start > p.pos) {
606        if let Some((k_, _)) = cursor.prev(txn).map_err(BlockError::Txn)? {
607            k = k_
608        } else {
609            break;
610        }
611    }
612    loop {
613        if k.change == p.change && k.start <= p.pos {
614            if k.end > p.pos || (k.start == k.end && k.end == p.pos) {
615                return Ok(k);
616            }
617        } else if k.change > p.change {
618            debug!("find_block: BLOCK ERROR");
619            return Err(BlockError::Block { block: p });
620        }
621        if let Some((k_, _)) = cursor.next(txn).map_err(BlockError::Txn)? {
622            k = k_
623        } else {
624            break;
625        }
626    }
627    debug!("find_block: BLOCK ERROR");
628    Err(BlockError::Block { block: p })
629}
630
631#[doc(hidden)]
632pub fn find_block_end<'a, T: ::sanakirja::LoadPage>(
633    txn: &'a T,
634    graph: &::sanakirja::btree::Db<Vertex<ChangeId>, SerializedEdge>,
635    p: Position<ChangeId>,
636) -> Result<&'a Vertex<ChangeId>, BlockError<T::Error>>
637where
638    T::Error: std::error::Error,
639{
640    if p.change.is_root() {
641        return Ok(&Vertex::ROOT);
642    }
643    let key = Vertex {
644        change: p.change,
645        start: p.pos,
646        end: p.pos,
647    };
648    let mut cursor = btree::cursor::Cursor::new(txn, graph).map_err(BlockError::Txn)?;
649    debug!("key {:?}", key);
650    let (mut k, v) = match cursor.set(txn, &key, None) {
651        Ok(Some((k, v))) => (k, v),
652        Ok(None) => {
653            if let Some((k, v)) = cursor.prev(txn).map_err(BlockError::Txn)? {
654                (k, v)
655            } else {
656                debug!("find_block_end, no prev");
657                return Err(BlockError::Block { block: p });
658            }
659        }
660        Err(e) => {
661            debug!("find_block_end: BLOCK ERROR 0 {:?}", e);
662            return Err(BlockError::Txn(e));
663        }
664    };
665    debug!("cursor {:?} {:?}", k, v);
666    loop {
667        debug!("find_block_end, loop, k = {:?}, p = {:?}", k, p);
668        if k.change < p.change {
669            break;
670        } else if k.change == p.change {
671            // Here we want to create an edge pointing between `p`
672            // and its successor. If k.start == p.pos, the only
673            // case where that's what we want is if k.start ==
674            // k.end.
675            if k.start == p.pos && k.end == p.pos {
676                return Ok(k);
677            } else if k.start < p.pos {
678                break;
679            }
680        }
681        if let Some((k_, _)) = cursor.prev(txn).map_err(BlockError::Txn)? {
682            k = k_
683        } else {
684            break;
685        }
686    }
687    // We also want k.end >= p.pos, so we just call next() until
688    // we have that.
689    debug!("find_block_end, {:?} {:?}", k, p);
690    while k.change < p.change || (k.change == p.change && p.pos > k.end) {
691        if let Some((k_, _)) = cursor.next(txn).map_err(BlockError::Txn)? {
692            k = k_
693        } else {
694            break;
695        }
696    }
697    debug!("find_block_end, {:?} {:?}", k, p);
698    if k.change == p.change
699        && ((k.start < p.pos && p.pos <= k.end) || (k.start == k.end && k.start == p.pos))
700    {
701        Ok(k)
702    } else {
703        debug!("find_block_end: BLOCK ERROR");
704        Err(BlockError::Block { block: p })
705    }
706}
707
708pub struct Adj {
709    pub cursor: ::sanakirja::btree::cursor::Cursor<
710        Vertex<ChangeId>,
711        SerializedEdge,
712        P<Vertex<ChangeId>, SerializedEdge>,
713    >,
714    pub key: Vertex<ChangeId>,
715    pub min_flag: EdgeFlags,
716    pub max_flag: EdgeFlags,
717}
718
719impl<T: ::sanakirja::LoadPage<Error = ::sanakirja::Error> + ::sanakirja::RootPage> GraphIter
720    for GenericTxn<T>
721{
722    type GraphCursor = ::sanakirja::btree::cursor::Cursor<
723        Vertex<ChangeId>,
724        SerializedEdge,
725        P<Vertex<ChangeId>, SerializedEdge>,
726    >;
727
728    fn graph_cursor(
729        &self,
730        g: &Self::Graph,
731        s: Option<&Vertex<ChangeId>>,
732    ) -> Result<Self::GraphCursor, TxnErr<Self::GraphError>> {
733        let mut c = ::sanakirja::btree::cursor::Cursor::new(&self.txn, &g.graph)?;
734        if let Some(s) = s {
735            c.set(&self.txn, s, None)?;
736        }
737        Ok(c)
738    }
739
740    fn next_graph<'txn>(
741        &'txn self,
742        _: &Self::Graph,
743        a: &mut Self::GraphCursor,
744    ) -> Option<Result<(&'txn Vertex<ChangeId>, &'txn SerializedEdge), TxnErr<Self::GraphError>>>
745    {
746        match a.next(&self.txn) {
747            Ok(Some(x)) => Some(Ok(x)),
748            Ok(None) => None,
749            Err(e) => {
750                error!("{:?}", e);
751                Some(Err(TxnErr(SanakirjaError::PristineCorrupt)))
752            }
753        }
754    }
755}
756
757// There is a choice here: the datastructure for `revchanges` is
758// intuitively a list. Moreover, when removing a change, we must
759// recompute the entire merkle tree after the removed change.
760//
761// This seems to indicate that a linked list could be an appropriate
762// structure (a growable array is excluded because amortised
763// complexity is not really acceptable here).
764//
765// However, we want to be able to answers queries such as "when was
766// change X introduced?" without having to read the entire database.
767//
768// Additionally, even though `SerializedMerkle` has only one
769// implementation, and is therefore sized in the current
770// implementation, we can't exclude that other algorithms may be
771// added, which means that the pages inside linked lists won't even be
772// randomly-accessible arrays.
773pub struct Channel {
774    pub graph: Db<Vertex<ChangeId>, SerializedEdge>,
775    pub changes: Db<ChangeId, L64>,
776    pub revchanges: UDb<L64, Pair<ChangeId, SerializedMerkle>>,
777    pub states: UDb<SerializedMerkle, L64>,
778    pub tags: Db<L64, Pair<SerializedMerkle, SerializedMerkle>>,
779    pub apply_counter: ApplyTimestamp,
780    pub name: SmallString,
781    pub last_modified: u64,
782    pub id: RemoteId,
783}
784
785impl<T: ::sanakirja::LoadPage<Error = ::sanakirja::Error> + ::sanakirja::RootPage> ChannelTxnT
786    for GenericTxn<T>
787{
788    type Channel = Channel;
789
790    fn graph<'a>(&self, c: &'a Self::Channel) -> &'a Channel {
791        c
792    }
793    fn name<'a>(&self, c: &'a Self::Channel) -> &'a str {
794        c.name.as_str()
795    }
796    fn id<'a>(&self, c: &'a Self::Channel) -> Option<&'a RemoteId> {
797        Some(&c.id)
798    }
799    fn apply_counter(&self, channel: &Self::Channel) -> u64 {
800        channel.apply_counter
801    }
802    fn last_modified(&self, channel: &Self::Channel) -> u64 {
803        channel.last_modified
804    }
805    fn changes<'a>(&self, channel: &'a Self::Channel) -> &'a Self::Changeset {
806        &channel.changes
807    }
808    fn rev_changes<'a>(&self, channel: &'a Self::Channel) -> &'a Self::RevChangeset {
809        &channel.revchanges
810    }
811    fn tags<'a>(&self, channel: &'a Self::Channel) -> &'a Self::Tags {
812        &channel.tags
813    }
814
815    type Changeset = Db<ChangeId, L64>;
816    type RevChangeset = UDb<L64, Pair<ChangeId, SerializedMerkle>>;
817
818    fn get_changeset(
819        &self,
820        channel: &Self::Changeset,
821        c: &ChangeId,
822    ) -> Result<Option<&L64>, TxnErr<Self::GraphError>> {
823        match btree::get(&self.txn, channel, c, None) {
824            Ok(Some((k, x))) if k == c => Ok(Some(x)),
825            Ok(x) => {
826                debug!("get_changeset = {:?}", x);
827                Ok(None)
828            }
829            Err(e) => {
830                error!("{:?}", e);
831                Err(TxnErr(SanakirjaError::PristineCorrupt))
832            }
833        }
834    }
835    fn get_revchangeset(
836        &self,
837        revchanges: &Self::RevChangeset,
838        c: &L64,
839    ) -> Result<Option<&Pair<ChangeId, SerializedMerkle>>, TxnErr<Self::GraphError>> {
840        match btree::get(&self.txn, revchanges, c, None) {
841            Ok(Some((k, x))) if k == c => Ok(Some(x)),
842            Ok(_) => Ok(None),
843            Err(e) => {
844                error!("{:?}", e);
845                Err(TxnErr(SanakirjaError::PristineCorrupt))
846            }
847        }
848    }
849
850    type ChangesetCursor = ::sanakirja::btree::cursor::Cursor<ChangeId, L64, P<ChangeId, L64>>;
851
852    fn cursor_changeset<'a>(
853        &'a self,
854        channel: &Self::Changeset,
855        pos: Option<ChangeId>,
856    ) -> Result<Cursor<Self, &'a Self, Self::ChangesetCursor, ChangeId, L64>, TxnErr<SanakirjaError>>
857    {
858        let mut cursor = btree::cursor::Cursor::new(&self.txn, channel)?;
859        if let Some(k) = pos {
860            cursor.set(&self.txn, &k, None)?;
861        }
862        Ok(Cursor {
863            cursor,
864            txn: self,
865            k: std::marker::PhantomData,
866            v: std::marker::PhantomData,
867            t: std::marker::PhantomData,
868        })
869    }
870
871    type RevchangesetCursor = ::sanakirja::btree::cursor::Cursor<
872        L64,
873        Pair<ChangeId, SerializedMerkle>,
874        UP<L64, Pair<ChangeId, SerializedMerkle>>,
875    >;
876
877    fn cursor_revchangeset_ref<'a, RT: std::ops::Deref<Target = Self>>(
878        txn: RT,
879        channel: &Self::RevChangeset,
880        pos: Option<L64>,
881    ) -> Result<
882        Cursor<Self, RT, Self::RevchangesetCursor, L64, Pair<ChangeId, SerializedMerkle>>,
883        TxnErr<SanakirjaError>,
884    > {
885        let mut cursor = btree::cursor::Cursor::new(&txn.txn, channel)?;
886        if let Some(k) = pos {
887            cursor.set(&txn.txn, &k, None)?;
888        }
889        Ok(Cursor {
890            cursor,
891            txn,
892            k: std::marker::PhantomData,
893            v: std::marker::PhantomData,
894            t: std::marker::PhantomData,
895        })
896    }
897
898    fn rev_cursor_revchangeset<'a>(
899        &'a self,
900        channel: &Self::RevChangeset,
901        pos: Option<L64>,
902    ) -> Result<
903        RevCursor<Self, &'a Self, Self::RevchangesetCursor, L64, Pair<ChangeId, SerializedMerkle>>,
904        TxnErr<SanakirjaError>,
905    > {
906        let mut cursor = btree::cursor::Cursor::new(&self.txn, channel)?;
907        if let Some(ref pos) = pos {
908            cursor.set(&self.txn, pos, None)?;
909        } else {
910            cursor.set_last(&self.txn)?;
911        };
912        Ok(RevCursor {
913            cursor,
914            txn: self,
915            k: std::marker::PhantomData,
916            v: std::marker::PhantomData,
917            t: std::marker::PhantomData,
918        })
919    }
920
921    fn cursor_revchangeset_next(
922        &self,
923        cursor: &mut Self::RevchangesetCursor,
924    ) -> Result<Option<(&L64, &Pair<ChangeId, SerializedMerkle>)>, TxnErr<SanakirjaError>> {
925        if let Ok(x) = cursor.next(&self.txn) {
926            Ok(x)
927        } else {
928            Err(TxnErr(SanakirjaError::PristineCorrupt))
929        }
930    }
931    fn cursor_revchangeset_prev(
932        &self,
933        cursor: &mut Self::RevchangesetCursor,
934    ) -> Result<Option<(&L64, &Pair<ChangeId, SerializedMerkle>)>, TxnErr<SanakirjaError>> {
935        if let Ok(x) = cursor.prev(&self.txn) {
936            Ok(x)
937        } else {
938            Err(TxnErr(SanakirjaError::PristineCorrupt))
939        }
940    }
941
942    fn cursor_changeset_next(
943        &self,
944        cursor: &mut Self::ChangesetCursor,
945    ) -> Result<Option<(&ChangeId, &L64)>, TxnErr<SanakirjaError>> {
946        if let Ok(x) = cursor.next(&self.txn) {
947            Ok(x)
948        } else {
949            Err(TxnErr(SanakirjaError::PristineCorrupt))
950        }
951    }
952    fn cursor_changeset_prev(
953        &self,
954        cursor: &mut Self::ChangesetCursor,
955    ) -> Result<Option<(&ChangeId, &L64)>, TxnErr<SanakirjaError>> {
956        if let Ok(x) = cursor.prev(&self.txn) {
957            Ok(x)
958        } else {
959            Err(TxnErr(SanakirjaError::PristineCorrupt))
960        }
961    }
962
963    type States = UDb<SerializedMerkle, L64>;
964    fn states<'a>(&self, channel: &'a Self::Channel) -> &'a Self::States {
965        &channel.states
966    }
967    fn channel_has_state(
968        &self,
969        channel: &Self::States,
970        m: &SerializedMerkle,
971    ) -> Result<Option<L64>, TxnErr<Self::GraphError>> {
972        match btree::get(&self.txn, channel, m, None)? {
973            Some((k, v)) if k == m => Ok(Some(*v)),
974            _ => Ok(None),
975        }
976    }
977
978    type Tags = Db<L64, Pair<SerializedMerkle, SerializedMerkle>>;
979
980    fn is_tagged(&self, tags: &Self::Tags, t: u64) -> Result<bool, TxnErr<Self::GraphError>> {
981        let t: L64 = t.into();
982        match btree::get(&self.txn, tags, &t, None)? {
983            Some((k, _)) => Ok(k == &t),
984            _ => Ok(false),
985        }
986    }
987
988    type TagsCursor = ::sanakirja::btree::cursor::Cursor<
989        L64,
990        Pair<SerializedMerkle, SerializedMerkle>,
991        P<L64, Pair<SerializedMerkle, SerializedMerkle>>,
992    >;
993    fn cursor_tags<'txn>(
994        &'txn self,
995        channel: &Self::Tags,
996        k: Option<L64>,
997    ) -> Result<
998        crate::pristine::Cursor<
999            Self,
1000            &'txn Self,
1001            Self::TagsCursor,
1002            L64,
1003            Pair<SerializedMerkle, SerializedMerkle>,
1004        >,
1005        TxnErr<Self::GraphError>,
1006    > {
1007        let mut cursor = btree::cursor::Cursor::new(&self.txn, channel)?;
1008        if let Some(k) = k {
1009            cursor.set(&self.txn, &k, None)?;
1010        }
1011        Ok(Cursor {
1012            cursor,
1013            txn: self,
1014            k: std::marker::PhantomData,
1015            v: std::marker::PhantomData,
1016            t: std::marker::PhantomData,
1017        })
1018    }
1019    fn cursor_tags_next(
1020        &self,
1021        cursor: &mut Self::TagsCursor,
1022    ) -> Result<Option<(&L64, &Pair<SerializedMerkle, SerializedMerkle>)>, TxnErr<Self::GraphError>>
1023    {
1024        if let Ok(x) = cursor.next(&self.txn) {
1025            Ok(x)
1026        } else {
1027            Err(TxnErr(SanakirjaError::PristineCorrupt))
1028        }
1029    }
1030
1031    fn cursor_tags_prev(
1032        &self,
1033        cursor: &mut Self::TagsCursor,
1034    ) -> Result<Option<(&L64, &Pair<SerializedMerkle, SerializedMerkle>)>, TxnErr<Self::GraphError>>
1035    {
1036        if let Ok(x) = cursor.prev(&self.txn) {
1037            Ok(x)
1038        } else {
1039            Err(TxnErr(SanakirjaError::PristineCorrupt))
1040        }
1041    }
1042
1043    fn iter_tags(
1044        &self,
1045        channel: &Self::Tags,
1046        from: u64,
1047    ) -> Result<
1048        super::Cursor<Self, &Self, Self::TagsCursor, L64, Pair<SerializedMerkle, SerializedMerkle>>,
1049        TxnErr<Self::GraphError>,
1050    > {
1051        self.cursor_tags(channel, Some(from.into()))
1052    }
1053
1054    fn rev_iter_tags(
1055        &self,
1056        channel: &Self::Tags,
1057        from: Option<u64>,
1058    ) -> Result<
1059        super::RevCursor<
1060            Self,
1061            &Self,
1062            Self::TagsCursor,
1063            L64,
1064            Pair<SerializedMerkle, SerializedMerkle>,
1065        >,
1066        TxnErr<Self::GraphError>,
1067    > {
1068        let mut cursor = btree::cursor::Cursor::new(&self.txn, channel)?;
1069        if let Some(from) = from {
1070            cursor.set(&self.txn, &from.into(), None)?;
1071        } else {
1072            cursor.set_last(&self.txn)?;
1073        };
1074        Ok(RevCursor {
1075            cursor,
1076            txn: self,
1077            k: std::marker::PhantomData,
1078            v: std::marker::PhantomData,
1079            t: std::marker::PhantomData,
1080        })
1081    }
1082}
1083
1084impl<T: ::sanakirja::LoadPage<Error = ::sanakirja::Error> + ::sanakirja::RootPage> DepsTxnT
1085    for GenericTxn<T>
1086{
1087    type DepsError = SanakirjaError;
1088    type Dep = Db<ChangeId, ChangeId>;
1089    type Revdep = Db<ChangeId, ChangeId>;
1090
1091    sanakirja_table_get!(dep, ChangeId, ChangeId, DepsError);
1092    sanakirja_table_get!(revdep, ChangeId, ChangeId, DepsError);
1093    type DepCursor = ::sanakirja::btree::cursor::Cursor<ChangeId, ChangeId, P<ChangeId, ChangeId>>;
1094    sanakirja_cursor_ref!(dep, ChangeId, ChangeId);
1095    fn iter_dep_ref<RT: std::ops::Deref<Target = Self> + Clone>(
1096        txn: RT,
1097        p: &ChangeId,
1098    ) -> Result<super::Cursor<Self, RT, Self::DepCursor, ChangeId, ChangeId>, TxnErr<Self::DepsError>>
1099    {
1100        Self::cursor_dep_ref(txn.clone(), &txn.dep, Some((p, None)))
1101    }
1102
1103    sanakirja_table_get!(touched_files, Position<ChangeId>, ChangeId, DepsError);
1104    sanakirja_table_get!(rev_touched_files, ChangeId, Position<ChangeId>, DepsError);
1105
1106    type Touched_files = Db<Position<ChangeId>, ChangeId>;
1107
1108    type Rev_touched_files = Db<ChangeId, Position<ChangeId>>;
1109
1110    type Touched_filesCursor = ::sanakirja::btree::cursor::Cursor<
1111        Position<ChangeId>,
1112        ChangeId,
1113        P<Position<ChangeId>, ChangeId>,
1114    >;
1115    sanakirja_iter!(touched_files, Position<ChangeId>, ChangeId);
1116
1117    type Rev_touched_filesCursor = ::sanakirja::btree::cursor::Cursor<
1118        ChangeId,
1119        Position<ChangeId>,
1120        P<ChangeId, Position<ChangeId>>,
1121    >;
1122    sanakirja_iter!(rev_touched_files, ChangeId, Position<ChangeId>);
1123    fn iter_revdep(
1124        &self,
1125        k: &ChangeId,
1126    ) -> Result<
1127        super::Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId>,
1128        TxnErr<Self::DepsError>,
1129    > {
1130        self.cursor_dep(&self.revdep, Some((k, None)))
1131    }
1132
1133    fn iter_dep(
1134        &self,
1135        k: &ChangeId,
1136    ) -> Result<
1137        super::Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId>,
1138        TxnErr<Self::DepsError>,
1139    > {
1140        self.cursor_dep(&self.dep, Some((k, None)))
1141    }
1142
1143    fn iter_touched(
1144        &self,
1145        k: &Position<ChangeId>,
1146    ) -> Result<
1147        super::Cursor<Self, &Self, Self::Touched_filesCursor, Position<ChangeId>, ChangeId>,
1148        TxnErr<Self::DepsError>,
1149    > {
1150        self.cursor_touched_files(&self.touched_files, Some((k, None)))
1151    }
1152
1153    fn iter_rev_touched(
1154        &self,
1155        k: &ChangeId,
1156    ) -> Result<
1157        super::Cursor<Self, &Self, Self::Rev_touched_filesCursor, ChangeId, Position<ChangeId>>,
1158        TxnErr<Self::DepsError>,
1159    > {
1160        self.cursor_rev_touched_files(&self.rev_touched_files, Some((k, None)))
1161    }
1162}
1163
1164impl<T: ::sanakirja::LoadPage<Error = ::sanakirja::Error> + ::sanakirja::RootPage> TreeTxnT
1165    for GenericTxn<T>
1166{
1167    type TreeError = SanakirjaError;
1168    type Inodes = Db<Inode, Position<ChangeId>>;
1169    type Revinodes = Db<Position<ChangeId>, Inode>;
1170    sanakirja_table_get!(inodes, Inode, Position<ChangeId>, TreeError, TreeErr);
1171    sanakirja_table_get!(revinodes, Position<ChangeId>, Inode, TreeError, TreeErr);
1172    sanakirja_cursor!(inodes, Inode, Position<ChangeId>, TreeErr);
1173    // #[cfg(debug_assertions)]
1174    sanakirja_cursor!(revinodes, Position<ChangeId>, Inode, TreeErr);
1175
1176    type Tree = UDb<PathId, Inode>;
1177    sanakirja_table_get!(tree, PathId, Inode, TreeError, TreeErr);
1178    type TreeCursor = ::sanakirja::btree::cursor::Cursor<PathId, Inode, UP<PathId, Inode>>;
1179    sanakirja_iter!(tree, PathId, Inode, TreeErr);
1180    type RevtreeCursor = ::sanakirja::btree::cursor::Cursor<Inode, PathId, UP<Inode, PathId>>;
1181    sanakirja_iter!(revtree, Inode, PathId, TreeErr);
1182
1183    type Revtree = UDb<Inode, PathId>;
1184    sanakirja_table_get!(revtree, Inode, PathId, TreeError, TreeErr);
1185
1186    type Partials = UDb<SmallStr, Position<ChangeId>>;
1187    type PartialsCursor = ::sanakirja::btree::cursor::Cursor<
1188        SmallStr,
1189        Position<ChangeId>,
1190        UP<SmallStr, Position<ChangeId>>,
1191    >;
1192    sanakirja_cursor!(partials, SmallStr, Position<ChangeId>, TreeErr);
1193    type InodesCursor =
1194        ::sanakirja::btree::cursor::Cursor<Inode, Position<ChangeId>, P<Inode, Position<ChangeId>>>;
1195    fn iter_inodes(
1196        &self,
1197    ) -> Result<
1198        super::Cursor<Self, &Self, Self::InodesCursor, Inode, Position<ChangeId>>,
1199        TreeErr<Self::TreeError>,
1200    > {
1201        self.cursor_inodes(&self.inodes, None)
1202    }
1203
1204    // #[cfg(debug_assertions)]
1205    type RevinodesCursor =
1206        ::sanakirja::btree::cursor::Cursor<Position<ChangeId>, Inode, P<Position<ChangeId>, Inode>>;
1207    // #[cfg(debug_assertions)]
1208    fn iter_revinodes(
1209        &self,
1210    ) -> Result<
1211        super::Cursor<Self, &Self, Self::RevinodesCursor, Position<ChangeId>, Inode>,
1212        TreeErr<SanakirjaError>,
1213    > {
1214        self.cursor_revinodes(&self.revinodes, None)
1215    }
1216
1217    fn iter_partials<'txn>(
1218        &'txn self,
1219        k0: &crate::small_string::SmallStr,
1220    ) -> Result<
1221        super::Cursor<Self, &'txn Self, Self::PartialsCursor, SmallStr, Position<ChangeId>>,
1222        TreeErr<SanakirjaError>,
1223    > {
1224        self.cursor_partials(&self.partials, Some((k0, None)))
1225    }
1226}
1227
1228impl<T: ::sanakirja::LoadPage<Error = ::sanakirja::Error> + ::sanakirja::RootPage> GenericTxn<T> {
1229    #[doc(hidden)]
1230    pub unsafe fn unsafe_load_channel(
1231        &self,
1232        name: SmallString,
1233    ) -> Result<Option<Channel>, TxnErr<SanakirjaError>> {
1234        unsafe {
1235            debug!("unsafe load channel");
1236            match btree::get(&self.txn, &self.channels, &name, None)? {
1237                Some((name_, tup)) if name_ == name.as_ref() => {
1238                    debug!("load_channel: {:?} {:?}", name, tup);
1239                    Ok(Some(Channel {
1240                        graph: Db::from_page(tup.graph.into()),
1241                        changes: Db::from_page(tup.changes.into()),
1242                        revchanges: UDb::from_page(tup.revchanges.into()),
1243                        states: UDb::from_page(tup.states.into()),
1244                        tags: Db::from_page(tup.tags.into()),
1245                        apply_counter: tup.apply_counter.into(),
1246                        last_modified: tup.last_modified.into(),
1247                        id: tup.id,
1248                        name,
1249                    }))
1250                }
1251                _ => {
1252                    debug!("unsafe_load_channel: not found");
1253                    Ok(None)
1254                }
1255            }
1256        }
1257    }
1258}
1259
1260impl<T: ::sanakirja::LoadPage<Error = ::sanakirja::Error> + ::sanakirja::RootPage> TxnT
1261    for GenericTxn<T>
1262{
1263    fn hash_from_prefix(
1264        &self,
1265        s: &str,
1266    ) -> Result<(Hash, ChangeId), super::HashPrefixError<Self::GraphError>> {
1267        let mut result = None;
1268        for h in prefix_guesses(s) {
1269            let h: SerializedHash = (&h).into();
1270            debug!("h = {:?}", h);
1271            for x in btree::iter(&self.txn, &self.internal, Some((&h, None)))
1272                .map_err(|e| super::HashPrefixError::Txn(e.into()))?
1273            {
1274                let (e, i) = x.map_err(|e| super::HashPrefixError::Txn(e.into()))?;
1275                debug!("{:?}", e);
1276                if e < &h {
1277                    continue;
1278                } else {
1279                    let e: Hash = e.into();
1280                    let b32 = e.to_base32();
1281                    debug!("{:?}", b32);
1282                    let (b32, _) = b32.split_at(s.len().min(b32.len()));
1283                    if b32 != s {
1284                        break;
1285                    } else if result.is_none() {
1286                        result = Some((e, *i))
1287                    } else {
1288                        return Err(super::HashPrefixError::Ambiguous(s.to_string()));
1289                    }
1290                }
1291            }
1292        }
1293        if let Some(result) = result {
1294            return Ok(result);
1295        }
1296        Err(super::HashPrefixError::NotFound(s.to_string()))
1297    }
1298
1299    fn state_from_prefix(
1300        &self,
1301        channel: &Self::States,
1302        s: &str,
1303    ) -> Result<(Merkle, L64), super::HashPrefixError<Self::GraphError>> {
1304        let h: SerializedMerkle = if let Some(ref h) = Merkle::from_prefix(s) {
1305            h.into()
1306        } else {
1307            return Err(super::HashPrefixError::Parse(s.to_string()));
1308        };
1309        let mut result = None;
1310        debug!("h = {:?}", h);
1311        for x in btree::iter(&self.txn, channel, Some((&h, None)))
1312            .map_err(|e| super::HashPrefixError::Txn(e.into()))?
1313        {
1314            let (e, i) = x.map_err(|e| super::HashPrefixError::Txn(e.into()))?;
1315            debug!("{:?} {:?}", e, i);
1316            if e < &h {
1317                continue;
1318            } else {
1319                let e: Merkle = e.into();
1320                let b32 = e.to_base32();
1321                debug!("{:?}", b32);
1322                let (b32, _) = b32.split_at(s.len().min(b32.len()));
1323                if b32 != s {
1324                    break;
1325                } else if result.is_none() {
1326                    result = Some((e, *i))
1327                } else {
1328                    return Err(super::HashPrefixError::Ambiguous(s.to_string()));
1329                }
1330            }
1331        }
1332        if let Some(result) = result {
1333            Ok(result)
1334        } else {
1335            Err(super::HashPrefixError::NotFound(s.to_string()))
1336        }
1337    }
1338
1339    fn hash_from_prefix_remote(
1340        &self,
1341        remote: &RemoteRef<Self>,
1342        s: &str,
1343    ) -> Result<Hash, super::HashPrefixError<Self::GraphError>> {
1344        let remote = remote.db.lock();
1345
1346        let mut result = None;
1347
1348        for h in prefix_guesses(s) {
1349            let h: SerializedHash = (&h).into();
1350            debug!("h = {:?}", h);
1351            for x in btree::iter(&self.txn, &remote.rev, Some((&h, None)))
1352                .map_err(|e| super::HashPrefixError::Txn(e.into()))?
1353            {
1354                let (e, _) = x.map_err(|e| super::HashPrefixError::Txn(e.into()))?;
1355                debug!("{:?}", e);
1356                if e < &h {
1357                    continue;
1358                } else {
1359                    let e: Hash = e.into();
1360                    let b32 = e.to_base32();
1361                    debug!("{:?}", b32);
1362                    let (b32, _) = b32.split_at(s.len().min(b32.len()));
1363                    if b32 != s {
1364                        break;
1365                    } else if result.is_none() {
1366                        result = Some(e)
1367                    } else {
1368                        return Err(super::HashPrefixError::Ambiguous(s.to_string()));
1369                    }
1370                }
1371            }
1372        }
1373        if let Some(result) = result {
1374            return Ok(result);
1375        }
1376        Err(super::HashPrefixError::NotFound(s.to_string()))
1377    }
1378
1379    fn load_channel(
1380        &self,
1381        name: SmallString,
1382    ) -> Result<Option<ChannelRef<Self>>, TxnErr<Self::GraphError>> {
1383        match self.open_channels.lock().entry(name.clone()) {
1384            Entry::Vacant(v) => {
1385                if let Some(c) = unsafe { self.unsafe_load_channel(name)? } {
1386                    Ok(Some(
1387                        v.insert(ChannelRef {
1388                            r: Arc::new(RwLock::new(c)),
1389                        })
1390                        .clone(),
1391                    ))
1392                } else {
1393                    Ok(None)
1394                }
1395            }
1396            Entry::Occupied(occ) => Ok(Some(occ.get().clone())),
1397        }
1398    }
1399
1400    fn load_remote(
1401        &self,
1402        name: &RemoteId,
1403    ) -> Result<Option<RemoteRef<Self>>, TxnErr<Self::GraphError>> {
1404        unsafe {
1405            let name = name.to_owned();
1406            match self.open_remotes.lock().entry(name) {
1407                Entry::Vacant(v) => match btree::get(&self.txn, &self.remotes, &name, None)? {
1408                    Some((name_, remote)) if name == *name_ => {
1409                        debug!("load_remote: {:?} {:?}", name_, remote);
1410                        let r = Remote {
1411                            remote: UDb::from_page(remote.remote.into()),
1412                            rev: UDb::from_page(remote.rev.into()),
1413                            states: UDb::from_page(remote.states.into()),
1414                            id_rev: remote.id_rev,
1415                            tags: Db::from_page(remote.tags.into()),
1416                            path: remote.path.to_owned(),
1417                        };
1418                        for x in btree::iter(&self.txn, &r.remote, None).unwrap() {
1419                            debug!("remote -> {:?}", x);
1420                        }
1421                        for x in btree::iter(&self.txn, &r.rev, None).unwrap() {
1422                            debug!("rev -> {:?}", x);
1423                        }
1424                        for x in btree::iter(&self.txn, &r.states, None).unwrap() {
1425                            debug!("states -> {:?}", x);
1426                        }
1427
1428                        for x in self.iter_remote(&r.remote, 0).unwrap() {
1429                            debug!("ITER {:?}", x);
1430                        }
1431
1432                        let r = RemoteRef {
1433                            db: Arc::new(Mutex::new(r)),
1434                            id: name,
1435                        };
1436                        Ok(Some(v.insert(r).clone()))
1437                    }
1438                    _ => Ok(None),
1439                },
1440                Entry::Occupied(occ) => Ok(Some(occ.get().clone())),
1441            }
1442        }
1443    }
1444
1445    type Channels = UDb<SmallStr, SerializedChannel>;
1446    type ChannelsCursor = ::sanakirja::btree::cursor::Cursor<
1447        SmallStr,
1448        SerializedChannel,
1449        UP<SmallStr, SerializedChannel>,
1450    >;
1451    sanakirja_cursor!(channels, SmallStr, SerializedChannel);
1452    fn channels(
1453        &self,
1454        start: &SmallStr,
1455    ) -> Result<Vec<ChannelRef<Self>>, TxnErr<Self::GraphError>> {
1456        let name = start;
1457        let mut cursor = btree::cursor::Cursor::new(&self.txn, &self.channels)?;
1458        cursor.set(&self.txn, name, None)?;
1459        while let Ok(Some((name, _))) = self.cursor_channels_next(&mut cursor) {
1460            self.load_channel(name.to_owned())?;
1461        }
1462        Ok(self.open_channels.lock().values().cloned().collect())
1463    }
1464
1465    type Remotes = UDb<RemoteId, SerializedRemote>;
1466    type RemotesCursor = ::sanakirja::btree::cursor::Cursor<
1467        RemoteId,
1468        SerializedRemote,
1469        UP<RemoteId, SerializedRemote>,
1470    >;
1471    sanakirja_cursor!(remotes, RemoteId, SerializedRemote);
1472    fn iter_remotes<'txn>(
1473        &'txn self,
1474        start: &RemoteId,
1475    ) -> Result<RemotesIterator<'txn, Self>, TxnErr<Self::GraphError>> {
1476        let mut cursor = btree::cursor::Cursor::new(&self.txn, &self.remotes)?;
1477        cursor.set(&self.txn, start, None)?;
1478        Ok(RemotesIterator { cursor, txn: self })
1479    }
1480
1481    type Remote = UDb<L64, Pair<SerializedHash, SerializedMerkle>>;
1482    type Revremote = UDb<SerializedHash, L64>;
1483    type Remotestates = UDb<SerializedMerkle, L64>;
1484    type Remotetags = UDb<L64, Pair<SerializedMerkle, SerializedMerkle>>;
1485    type RemoteCursor = ::sanakirja::btree::cursor::Cursor<
1486        L64,
1487        Pair<SerializedHash, SerializedMerkle>,
1488        UP<L64, Pair<SerializedHash, SerializedMerkle>>,
1489    >;
1490    sanakirja_cursor!(remote, L64, Pair<SerializedHash, SerializedMerkle>);
1491    sanakirja_rev_cursor!(remote, L64, Pair<SerializedHash, SerializedMerkle>);
1492
1493    fn iter_remote<'txn>(
1494        &'txn self,
1495        remote: &Self::Remote,
1496        k: u64,
1497    ) -> Result<
1498        super::Cursor<
1499            Self,
1500            &'txn Self,
1501            Self::RemoteCursor,
1502            L64,
1503            Pair<SerializedHash, SerializedMerkle>,
1504        >,
1505        TxnErr<Self::GraphError>,
1506    > {
1507        self.cursor_remote(remote, Some((&k.into(), None)))
1508    }
1509
1510    fn iter_rev_remote<'txn>(
1511        &'txn self,
1512        remote: &Self::Remote,
1513        k: Option<L64>,
1514    ) -> Result<
1515        super::RevCursor<
1516            Self,
1517            &'txn Self,
1518            Self::RemoteCursor,
1519            L64,
1520            Pair<SerializedHash, SerializedMerkle>,
1521        >,
1522        TxnErr<Self::GraphError>,
1523    > {
1524        self.rev_cursor_remote(remote, k.as_ref().map(|k| (k, None)))
1525    }
1526
1527    fn get_remote(
1528        &mut self,
1529        name: RemoteId,
1530    ) -> Result<Option<RemoteRef<Self>>, TxnErr<Self::GraphError>> {
1531        unsafe {
1532            let name = name.to_owned();
1533            match self.open_remotes.lock().entry(name) {
1534                Entry::Vacant(v) => match btree::get(&self.txn, &self.remotes, &name, None)? {
1535                    Some((name_, remote)) if *name_ == name => {
1536                        let r = RemoteRef {
1537                            db: Arc::new(Mutex::new(Remote {
1538                                remote: UDb::from_page(remote.remote.into()),
1539                                rev: UDb::from_page(remote.rev.into()),
1540                                states: UDb::from_page(remote.states.into()),
1541                                id_rev: remote.id_rev,
1542                                tags: Db::from_page(remote.tags.into()),
1543                                path: remote.path.to_owned(),
1544                            })),
1545                            id: name,
1546                        };
1547                        v.insert(r);
1548                    }
1549                    _ => return Ok(None),
1550                },
1551                Entry::Occupied(_) => {}
1552            }
1553            Ok(self.open_remotes.lock().get(&name).cloned())
1554        }
1555    }
1556
1557    fn last_remote(
1558        &self,
1559        remote: &Self::Remote,
1560    ) -> Result<Option<(u64, &Pair<SerializedHash, SerializedMerkle>)>, TxnErr<Self::GraphError>>
1561    {
1562        debug!("last_remote: {:?}", remote);
1563        if let Some(x) = btree::rev_iter(&self.txn, remote, None)?.next() {
1564            let (&k, v) = x?;
1565            Ok(Some((k.into(), v)))
1566        } else {
1567            Ok(None)
1568        }
1569    }
1570
1571    fn last_remote_tag(
1572        &self,
1573        remote: &Self::Tags,
1574    ) -> Result<Option<(u64, &SerializedMerkle, &SerializedMerkle)>, TxnErr<Self::GraphError>> {
1575        if let Some(x) = btree::rev_iter(&self.txn, remote, None)?.next() {
1576            let (&k, v) = x?;
1577            Ok(Some((k.into(), &v.a, &v.b)))
1578        } else {
1579            Ok(None)
1580        }
1581    }
1582
1583    fn get_remote_state(
1584        &self,
1585        remote: &Self::Remote,
1586        n: u64,
1587    ) -> Result<Option<(u64, &Pair<SerializedHash, SerializedMerkle>)>, TxnErr<Self::GraphError>>
1588    {
1589        let n = n.into();
1590        for x in btree::iter(&self.txn, remote, Some((&n, None)))? {
1591            let (&k, m) = x?;
1592            if k >= n {
1593                return Ok(Some((k.into(), m)));
1594            }
1595        }
1596        Ok(None)
1597    }
1598
1599    fn get_remote_tag(
1600        &self,
1601        remote: &Self::Tags,
1602        n: u64,
1603    ) -> Result<Option<(u64, &Pair<SerializedMerkle, SerializedMerkle>)>, TxnErr<Self::GraphError>>
1604    {
1605        let n = n.into();
1606        if let Some(x) = btree::rev_iter(&self.txn, remote, Some((&n, None)))?.next() {
1607            let (&k, m) = x?;
1608            Ok(Some((k.into(), m)))
1609        } else {
1610            Ok(None)
1611        }
1612    }
1613
1614    fn remote_has_change(
1615        &self,
1616        remote: &RemoteRef<Self>,
1617        hash: &SerializedHash,
1618    ) -> Result<bool, TxnErr<Self::GraphError>> {
1619        match btree::get(&self.txn, &remote.db.lock().rev, hash, None)? {
1620            Some((k, _)) if k == hash => Ok(true),
1621            _ => Ok(false),
1622        }
1623    }
1624    fn remote_has_state(
1625        &self,
1626        remote: &RemoteRef<Self>,
1627        m: &SerializedMerkle,
1628    ) -> Result<Option<u64>, TxnErr<Self::GraphError>> {
1629        match btree::get(&self.txn, &remote.db.lock().states, m, None)? {
1630            Some((k, v)) if k == m => Ok(Some((*v).into())),
1631            _ => Ok(None),
1632        }
1633    }
1634    fn current_channel(&self) -> Result<&str, Self::GraphError> {
1635        if let Some(ref c) = self.cur_channel {
1636            Ok(c)
1637        } else {
1638            unsafe {
1639                let b = self.txn.root_page();
1640                let len = b[4096 - 256] as usize;
1641                if len == 0 {
1642                    Ok("main")
1643                } else {
1644                    let s = std::slice::from_raw_parts(b.as_ptr().add(4096 - 255), len);
1645                    Ok(std::str::from_utf8(s).unwrap_or("main"))
1646                }
1647            }
1648        }
1649    }
1650}
1651
1652impl<
1653    T: sanakirja::AllocPage<Error = ::sanakirja::Error>
1654        + sanakirja::RootPage
1655        + sanakirja::LoadPage<Error = ::sanakirja::Error>,
1656> GraphMutTxnT for MutTxn<T>
1657{
1658    fn put_graph(
1659        &mut self,
1660        graph: &mut Self::Graph,
1661        k: &Vertex<ChangeId>,
1662        e: &SerializedEdge,
1663    ) -> Result<bool, TxnErr<Self::GraphError>> {
1664        Ok(btree::put(&mut self.txn, &mut graph.graph, k, e)?)
1665    }
1666
1667    fn del_graph(
1668        &mut self,
1669        graph: &mut Self::Graph,
1670        k: &Vertex<ChangeId>,
1671        e: Option<&SerializedEdge>,
1672    ) -> Result<bool, TxnErr<Self::GraphError>> {
1673        Ok(btree::del(&mut self.txn, &mut graph.graph, k, e)?)
1674    }
1675
1676    fn debug(&mut self, graph: &mut Self::Graph, extra: &str) {
1677        ::sanakirja::debug::debug(
1678            &self.txn,
1679            &[&graph.graph],
1680            format!("debug{}{}", self.counter, extra),
1681            true,
1682        );
1683    }
1684
1685    sanakirja_put_del!(internal, SerializedHash, ChangeId, GraphError);
1686    sanakirja_put_del!(external, ChangeId, SerializedHash, GraphError);
1687
1688    fn split_block(
1689        &mut self,
1690        graph: &mut Self::Graph,
1691        key: &Vertex<ChangeId>,
1692        pos: ChangePosition,
1693        buf: &mut Vec<SerializedEdge>,
1694    ) -> Result<(), TxnErr<Self::GraphError>> {
1695        assert!(pos > key.start);
1696        assert!(pos < key.end);
1697        let mut cursor = btree::cursor::Cursor::new(&self.txn, &graph.graph)?;
1698        cursor.set(&self.txn, key, None)?;
1699        loop {
1700            match cursor.next(&self.txn) {
1701                Ok(Some((k, v))) => {
1702                    if k > key {
1703                        break;
1704                    } else if k < key {
1705                        continue;
1706                    }
1707                    buf.push(*v)
1708                }
1709                Ok(None) => break,
1710                Err(e) => {
1711                    error!("{:?}", e);
1712                    return Err(TxnErr(SanakirjaError::PristineCorrupt));
1713                }
1714            }
1715        }
1716        for chi in buf.drain(..) {
1717            assert!(
1718                chi.introduced_by() != ChangeId::ROOT || chi.flag().contains(EdgeFlags::PSEUDO)
1719            );
1720            if chi.flag().contains(EdgeFlags::PARENT | EdgeFlags::BLOCK) {
1721                put_graph_with_rev(
1722                    self,
1723                    graph,
1724                    chi.flag() - EdgeFlags::PARENT,
1725                    Vertex {
1726                        change: key.change,
1727                        start: key.start,
1728                        end: pos,
1729                    },
1730                    Vertex {
1731                        change: key.change,
1732                        start: pos,
1733                        end: key.end,
1734                    },
1735                    chi.introduced_by(),
1736                )?;
1737            }
1738
1739            self.del_graph(graph, key, Some(&chi))?;
1740            self.put_graph(
1741                graph,
1742                &if chi.flag().contains(EdgeFlags::PARENT) {
1743                    Vertex {
1744                        change: key.change,
1745                        start: key.start,
1746                        end: pos,
1747                    }
1748                } else {
1749                    Vertex {
1750                        change: key.change,
1751                        start: pos,
1752                        end: key.end,
1753                    }
1754                },
1755                &chi,
1756            )?;
1757        }
1758        Ok(())
1759    }
1760}
1761
1762impl<
1763    T: sanakirja::AllocPage<Error = ::sanakirja::Error>
1764        + sanakirja::RootPage
1765        + sanakirja::LoadPage<Error = ::sanakirja::Error>,
1766> ChannelMutTxnT for MutTxn<T>
1767{
1768    fn graph_mut(c: &mut Self::Channel) -> &mut Self::Graph {
1769        c
1770    }
1771    fn touch_channel(&mut self, channel: &mut Self::Channel, t: Option<u64>) {
1772        use std::time::SystemTime;
1773        debug!("touch_channel: {:?}", t);
1774        if let Some(t) = t {
1775            channel.last_modified = t
1776        } else if let Ok(duration) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
1777            debug!("touch {:?}", duration.as_secs() * 1000);
1778            channel.last_modified = duration.as_secs() * 1000
1779        }
1780    }
1781
1782    fn put_changes(
1783        &mut self,
1784        channel: &mut Self::Channel,
1785        p: ChangeId,
1786        t: ApplyTimestamp,
1787        h: &Hash,
1788    ) -> Result<Option<Merkle>, TxnErr<Self::GraphError>> {
1789        debug!("put_changes {:?} {:?}", p, h);
1790        if let Some(m) = self.get_changeset(&channel.changes, &p)? {
1791            debug!("found m = {:?}, p = {:?}", m, p);
1792            Ok(None)
1793        } else {
1794            channel.apply_counter += 1;
1795            debug!("put_changes {:?} {:?}", t, p);
1796            let m = if let Some(x) = btree::rev_iter(&self.txn, &channel.revchanges, None)?.next() {
1797                let (a, b) = x?;
1798                let a: u64 = (*a).into();
1799                assert!(a < t);
1800                (&b.b).into()
1801            } else {
1802                Merkle::zero()
1803            };
1804            let m = m.next(h);
1805            assert!(
1806                self.get_revchangeset(&channel.revchanges, &t.into())?
1807                    .is_none()
1808            );
1809            assert!(btree::put(
1810                &mut self.txn,
1811                &mut channel.changes,
1812                &p,
1813                &t.into()
1814            )?);
1815            assert!(btree::put(
1816                &mut self.txn,
1817                &mut channel.revchanges,
1818                &t.into(),
1819                &Pair { a: p, b: m.into() }
1820            )?);
1821            assert!(btree::put(
1822                &mut self.txn,
1823                &mut channel.states,
1824                &m.into(),
1825                &t.into(),
1826            )?);
1827            Ok(Some(m))
1828        }
1829    }
1830
1831    fn del_changes(
1832        &mut self,
1833        channel: &mut Self::Channel,
1834        p: ChangeId,
1835        t: ApplyTimestamp,
1836    ) -> Result<bool, TxnErr<Self::GraphError>> {
1837        let mut repl = Vec::new();
1838        let tl = t.into();
1839        for x in btree::iter(&self.txn, &channel.revchanges, Some((&tl, None)))? {
1840            let (t_, p) = x?;
1841            if *t_ >= tl {
1842                repl.push((*t_, p.a, p.b))
1843            }
1844        }
1845        let mut m = Merkle::zero();
1846        for x in btree::rev_iter(&self.txn, &channel.revchanges, Some((&tl, None)))? {
1847            let (t_, mm) = x?;
1848            if t_ < &tl {
1849                m = (&mm.b).into();
1850                break;
1851            }
1852        }
1853        for (t_, p, m0) in repl.iter() {
1854            debug!("del_changes {:?} {:?}", t_, p);
1855            btree::del(&mut self.txn, &mut channel.revchanges, t_, None)?;
1856            btree::del(&mut self.txn, &mut channel.states, m0, None)?;
1857            if *t_ > tl {
1858                m = m.next(self.get_external(p).optional()?.unwrap());
1859                btree::put(
1860                    &mut self.txn,
1861                    &mut channel.revchanges,
1862                    t_,
1863                    &Pair { a: *p, b: m.into() },
1864                )?;
1865                btree::put(&mut self.txn, &mut channel.states, &m.into(), t_)?;
1866            }
1867        }
1868        btree::del(&mut self.txn, &mut channel.tags, &t.into(), None)?;
1869        Ok(btree::del(
1870            &mut self.txn,
1871            &mut channel.changes,
1872            &p,
1873            Some(&t.into()),
1874        )?)
1875    }
1876
1877    fn tags_mut<'a>(&mut self, channel: &'a mut Self::Channel) -> &'a mut Self::Tags {
1878        &mut channel.tags
1879    }
1880
1881    fn put_tags(
1882        &mut self,
1883        channel: &mut Self::Tags,
1884        n: u64,
1885        m: &Merkle,
1886    ) -> Result<(), TxnErr<Self::GraphError>> {
1887        debug!("put_tags {:?}", m);
1888        let mm: SerializedMerkle = m.into();
1889        if btree::get(&self.txn, channel, &n.into(), None)?.is_some() {
1890            debug!("already tagged");
1891            Ok(())
1892        } else {
1893            let tl = n.into();
1894            let mut repl = vec![(tl, mm)];
1895            replay_tags(self, channel, tl, &mut repl)?;
1896            Ok(())
1897        }
1898    }
1899
1900    fn del_tags(
1901        &mut self,
1902        channel: &mut Self::Tags,
1903        t: u64,
1904    ) -> Result<(), TxnErr<Self::GraphError>> {
1905        replay_tags(self, channel, t.into(), &mut Vec::new())?;
1906        Ok(())
1907    }
1908
1909    fn move_change(
1910        &mut self,
1911        channel: &mut Self::Channel,
1912        change_id: ChangeId,
1913        old_pos: ApplyTimestamp,
1914        new_pos: ApplyTimestamp,
1915    ) -> Result<(), TxnErr<Self::GraphError>> {
1916        if old_pos == new_pos {
1917            return Ok(());
1918        }
1919        let new_l64 = L64::from(new_pos);
1920        let old_l64 = L64::from(old_pos);
1921        // Collect all entries in [new_pos, old_pos] — the range being reordered.
1922        let mut entries: Vec<(L64, ChangeId)> = Vec::new();
1923        for x in btree::iter(&self.txn, &channel.revchanges, Some((&new_l64, None)))? {
1924            let (t, p) = x?;
1925            let t_u64: u64 = (*t).into();
1926            if t_u64 > old_pos {
1927                break;
1928            }
1929            entries.push((*t, p.a));
1930        }
1931        // Remove them all from revchanges, states, and changes.
1932        let mut merkles: Vec<SerializedMerkle> = Vec::with_capacity(entries.len());
1933        for (t, _) in entries.iter() {
1934            let m = self.get_revchangeset(&channel.revchanges, t)?.unwrap().b;
1935            merkles.push(m);
1936        }
1937        for ((t, p), m) in entries.iter().zip(merkles.iter()) {
1938            btree::del(&mut self.txn, &mut channel.revchanges, t, None)?;
1939            btree::del(&mut self.txn, &mut channel.states, m, None)?;
1940            btree::del(&mut self.txn, &mut channel.changes, p, Some(t))?;
1941        }
1942        // Starting Merkle is the value just before new_pos.
1943        let mut m: Merkle = {
1944            let mut it = btree::rev_iter(&self.txn, &channel.revchanges, Some((&new_l64, None)))?;
1945            match it.next() {
1946                Some(x) => {
1947                    let (t_, mm) = x?;
1948                    if *t_ < new_l64 {
1949                        (&mm.b).into()
1950                    } else {
1951                        Merkle::zero()
1952                    }
1953                }
1954                None => Merkle::zero(),
1955            }
1956        };
1957        // New order: change_id first (it was at old_pos), then entries[0..last] in original order.
1958        let last = entries.len() - 1;
1959        let new_order: Vec<ChangeId> = std::iter::once(change_id)
1960            .chain(entries[..last].iter().map(|(_, p)| *p))
1961            .collect();
1962        for (i, p) in new_order.iter().enumerate() {
1963            let pos = L64::from(new_pos + i as u64);
1964            m = m.next(self.get_external(p).optional()?.unwrap());
1965            btree::put(
1966                &mut self.txn,
1967                &mut channel.revchanges,
1968                &pos,
1969                &Pair { a: *p, b: m.into() },
1970            )?;
1971            btree::put(&mut self.txn, &mut channel.states, &m.into(), &pos)?;
1972            btree::put(&mut self.txn, &mut channel.changes, p, &pos)?;
1973        }
1974        let _ = old_l64;
1975        Ok(())
1976    }
1977}
1978
1979fn replay_tags<
1980    T: sanakirja::AllocPage<Error = ::sanakirja::Error>
1981        + sanakirja::RootPage
1982        + sanakirja::LoadPage<Error = ::sanakirja::Error>,
1983>(
1984    txn: &mut MutTxn<T>,
1985    channel: &mut Db<L64, Pair<SerializedMerkle, SerializedMerkle>>,
1986    tl: L64,
1987    repl: &mut Vec<(L64, SerializedMerkle)>,
1988) -> Result<(), TxnErr<SanakirjaError>> {
1989    let del = repl.is_empty();
1990    for x in btree::iter(&txn.txn, channel, Some((&tl, None)))? {
1991        let (t_, p) = x?;
1992        if *t_ >= tl {
1993            repl.push((*t_, p.a))
1994        }
1995    }
1996    let mut m = Merkle::zero();
1997    for x in btree::rev_iter(&txn.txn, channel, Some((&tl, None)))? {
1998        let (t_, mm) = x?;
1999        if t_ < &tl {
2000            m = (&mm.b).into();
2001            break;
2002        }
2003    }
2004    for (t_, p) in repl.iter() {
2005        debug!("del_tags {:?} {:?}", t_, p);
2006        btree::del(&mut txn.txn, channel, t_, None)?;
2007        if *t_ > tl || !del {
2008            m = m.next(p);
2009            btree::put(&mut txn.txn, channel, t_, &Pair { a: *p, b: m.into() })?;
2010        }
2011    }
2012    Ok(())
2013}
2014
2015impl<
2016    T: sanakirja::AllocPage<Error = ::sanakirja::Error>
2017        + sanakirja::RootPage
2018        + sanakirja::LoadPage<Error = ::sanakirja::Error>,
2019> DepsMutTxnT for MutTxn<T>
2020{
2021    sanakirja_put_del!(dep, ChangeId, ChangeId, DepsError);
2022    sanakirja_put_del!(revdep, ChangeId, ChangeId, DepsError);
2023    sanakirja_put_del!(touched_files, Position<ChangeId>, ChangeId, DepsError);
2024    sanakirja_put_del!(rev_touched_files, ChangeId, Position<ChangeId>, DepsError);
2025}
2026
2027impl<
2028    T: sanakirja::AllocPage<Error = ::sanakirja::Error>
2029        + sanakirja::RootPageMut
2030        + sanakirja::LoadPage<Error = ::sanakirja::Error>,
2031> TreeMutTxnT for MutTxn<T>
2032{
2033    sanakirja_put_del!(inodes, Inode, Position<ChangeId>, TreeError, TreeErr);
2034    sanakirja_put_del!(revinodes, Position<ChangeId>, Inode, TreeError, TreeErr);
2035
2036    sanakirja_put_del!(tree, PathId, Inode, TreeError, TreeErr);
2037    sanakirja_put_del!(revtree, Inode, PathId, TreeError, TreeErr);
2038
2039    fn put_partials(
2040        &mut self,
2041        k: &SmallStr,
2042        e: Position<ChangeId>,
2043    ) -> Result<bool, TreeErr<Self::TreeError>> {
2044        btree::put(&mut self.txn, &mut self.partials, k, &e).map_err(|e| TreeErr(e.into()))
2045    }
2046
2047    fn del_partials(
2048        &mut self,
2049        k: &SmallStr,
2050        e: Option<Position<ChangeId>>,
2051    ) -> Result<bool, TreeErr<Self::TreeError>> {
2052        btree::del(&mut self.txn, &mut self.partials, k, e.as_ref()).map_err(|e| TreeErr(e.into()))
2053    }
2054}
2055
2056impl<T: RawMutTxnT> MutTxnT for MutTxn<T> {
2057    fn put_remote(
2058        &mut self,
2059        remote: &mut RemoteRef<Self>,
2060        k: u64,
2061        v: (Hash, Merkle),
2062    ) -> Result<bool, TxnErr<Self::GraphError>> {
2063        let mut remote = remote.db.lock();
2064        let h = (&v.0).into();
2065        let m: SerializedMerkle = (&v.1).into();
2066        btree::put(
2067            &mut self.txn,
2068            &mut remote.remote,
2069            &k.into(),
2070            &Pair { a: h, b: m },
2071        )?;
2072        debug!("remote.remote after put: {:?}", remote.remote);
2073        btree::put(&mut self.txn, &mut remote.states, &m, &k.into())?;
2074        // if v.2 {
2075        //     self.put_tags(&mut remote.tags, k, &v.1)?;
2076        // }
2077        Ok(btree::put(&mut self.txn, &mut remote.rev, &h, &k.into())?)
2078    }
2079
2080    fn del_remote(
2081        &mut self,
2082        remote: &mut RemoteRef<Self>,
2083        k: u64,
2084    ) -> Result<bool, TxnErr<Self::GraphError>> {
2085        let mut remote = remote.db.lock();
2086        let k = k.into();
2087        match btree::get(&self.txn, &remote.remote, &k, None)? {
2088            Some((k0, p)) if k0 == &k => {
2089                debug!("del_remote {:?} {:?}", k0, p);
2090                let p = *p;
2091                btree::del(&mut self.txn, &mut remote.rev, &p.a, None)?;
2092                btree::del(&mut self.txn, &mut remote.states, &p.b, None)?;
2093                Ok(btree::del(&mut self.txn, &mut remote.remote, &k, None)?)
2094            }
2095            x => {
2096                debug!("not found, {:?}", x);
2097                Ok(false)
2098            }
2099        }
2100    }
2101
2102    fn open_or_create_channel(
2103        &mut self,
2104        name: &SmallStr,
2105    ) -> Result<ChannelRef<Self>, Self::GraphError> {
2106        unsafe {
2107            let mut commit = None;
2108            let result = match self.open_channels.lock().entry(name.to_owned()) {
2109                Entry::Vacant(v) => {
2110                    let r = match btree::get(&self.txn, &self.channels, name, None)? {
2111                        Some((name_, b)) if name_ == name => ChannelRef {
2112                            r: Arc::new(RwLock::new(Channel {
2113                                graph: Db::from_page(b.graph.into()),
2114                                changes: Db::from_page(b.changes.into()),
2115                                revchanges: UDb::from_page(b.revchanges.into()),
2116                                states: UDb::from_page(b.states.into()),
2117                                tags: Db::from_page(b.tags.into()),
2118                                apply_counter: b.apply_counter.into(),
2119                                last_modified: b.last_modified.into(),
2120                                id: b.id,
2121                                name: name.to_owned(),
2122                            })),
2123                        },
2124                        _ => {
2125                            let br = ChannelRef {
2126                                r: Arc::new(RwLock::new(Channel {
2127                                    graph: btree::create_db_(&mut self.txn)?,
2128                                    changes: btree::create_db_(&mut self.txn)?,
2129                                    revchanges: btree::create_db_(&mut self.txn)?,
2130                                    states: btree::create_db_(&mut self.txn)?,
2131                                    tags: btree::create_db_(&mut self.txn)?,
2132                                    id: {
2133                                        let mut rng = rand::rng();
2134                                        use rand::RngExt;
2135                                        let mut x = RemoteId([0; 16]);
2136                                        for x in x.0.iter_mut() {
2137                                            *x = rng.random()
2138                                        }
2139                                        x
2140                                    },
2141                                    apply_counter: 0,
2142                                    last_modified: 0,
2143                                    name: name.to_owned(),
2144                                })),
2145                            };
2146                            commit = Some(br.clone());
2147                            br
2148                        }
2149                    };
2150                    v.insert(r).clone()
2151                }
2152                Entry::Occupied(occ) => occ.get().clone(),
2153            };
2154            if let Some(commit) = commit {
2155                self.put_channel(commit)?;
2156            }
2157            Ok(result)
2158        }
2159    }
2160
2161    fn fork(
2162        &mut self,
2163        channel: &ChannelRef<Self>,
2164        name: &SmallStr,
2165    ) -> Result<ChannelRef<Self>, ForkError<Self::GraphError>> {
2166        let channel = channel.r.read();
2167        match btree::get(&self.txn, &self.channels, name, None)
2168            .map_err(|e| ForkError::Txn(e.into()))?
2169        {
2170            Some((name_, _)) if name_ == name => {
2171                Err(super::ForkError::ChannelNameExists(name.to_string()))
2172            }
2173            _ => {
2174                let br = ChannelRef {
2175                    r: Arc::new(RwLock::new(Channel {
2176                        graph: btree::fork_db(&mut self.txn, &channel.graph)
2177                            .map_err(|e| ForkError::Txn(e.into()))?,
2178                        changes: btree::fork_db(&mut self.txn, &channel.changes)
2179                            .map_err(|e| ForkError::Txn(e.into()))?,
2180                        revchanges: btree::fork_db(&mut self.txn, &channel.revchanges)
2181                            .map_err(|e| ForkError::Txn(e.into()))?,
2182                        states: btree::fork_db(&mut self.txn, &channel.states)
2183                            .map_err(|e| ForkError::Txn(e.into()))?,
2184                        tags: btree::fork_db(&mut self.txn, &channel.tags)
2185                            .map_err(|e| ForkError::Txn(e.into()))?,
2186                        name: name.to_owned(),
2187                        apply_counter: channel.apply_counter,
2188                        last_modified: channel.last_modified,
2189                        id: {
2190                            let mut rng = rand::rng();
2191                            use rand::RngExt;
2192                            let mut x = RemoteId([0; 16]);
2193                            for x in x.0.iter_mut() {
2194                                *x = rng.random()
2195                            }
2196                            x
2197                        },
2198                    })),
2199                };
2200                self.open_channels
2201                    .lock()
2202                    .insert(name.to_owned(), br.clone());
2203                Ok(br)
2204            }
2205        }
2206    }
2207
2208    fn rename_channel(
2209        &mut self,
2210        channel: &mut ChannelRef<Self>,
2211        name: &SmallStr,
2212    ) -> Result<(), ForkError<Self::GraphError>> {
2213        match btree::get(&self.txn, &self.channels, name, None)
2214            .map_err(|e| ForkError::Txn(e.into()))?
2215        {
2216            Some((name_, _)) if name_ == name => {
2217                Err(super::ForkError::ChannelNameExists(name.to_string()))
2218            }
2219            _ => {
2220                btree::del(
2221                    &mut self.txn,
2222                    &mut self.channels,
2223                    &channel.r.read().name,
2224                    None,
2225                )
2226                .map_err(|e| ForkError::Txn(e.into()))?;
2227                std::mem::drop(
2228                    self.open_channels
2229                        .lock()
2230                        .remove(&channel.r.read().name)
2231                        .unwrap(),
2232                );
2233                channel.r.write().name = name.to_owned();
2234                self.open_channels
2235                    .lock()
2236                    .insert(name.to_owned(), channel.clone());
2237                Ok(())
2238            }
2239        }
2240    }
2241
2242    fn drop_channel(&mut self, name: &SmallStr) -> Result<bool, Self::GraphError> {
2243        unsafe {
2244            let name = name.to_owned();
2245            debug!(target: "drop_channel", "drop channel {:?}", name);
2246            let channel = if let Some(channel) = self.open_channels.lock().remove(&name) {
2247                let channel = Arc::try_unwrap(channel.r)
2248                    .map_err(|_| SanakirjaError::ChannelRc {
2249                        c: name.to_string(),
2250                    })?
2251                    .into_inner();
2252                Some((
2253                    channel.graph,
2254                    channel.changes,
2255                    channel.revchanges,
2256                    channel.states,
2257                    channel.tags,
2258                ))
2259            } else if let Some((name_, chan)) = btree::get(&self.txn, &self.channels, &name, None)?
2260            {
2261                if name_ == name.as_ref() {
2262                    Some((
2263                        Db::from_page(chan.graph.into()),
2264                        Db::from_page(chan.changes.into()),
2265                        UDb::from_page(chan.revchanges.into()),
2266                        UDb::from_page(chan.states.into()),
2267                        Db::from_page(chan.tags.into()),
2268                    ))
2269                } else {
2270                    None
2271                }
2272            } else {
2273                None
2274            };
2275            btree::del(&mut self.txn, &mut self.channels, &name, None)?;
2276            if let Some((a, b, c, d, e)) = channel {
2277                let mut unused_changes = Vec::new();
2278                'outer: for x in btree::rev_iter(&self.txn, &c, None)? {
2279                    let (_, p) = x?;
2280                    debug!(target: "drop_channel", "testing unused change: {:?}", p);
2281                    let empty = SmallString::new();
2282                    for chan in self.channels(&empty).map_err(|e| e.0)? {
2283                        debug!(target: "drop_channel", "channel: {:?}", name);
2284                        let chan = chan.read();
2285                        assert_ne!(chan.name, name);
2286                        if self
2287                            .channel_has_state(&chan.states, &p.b)
2288                            .map_err(|e| e.0)?
2289                            .is_some()
2290                        {
2291                            // This other channel is in the same state as
2292                            // our dropped channel is, so all subsequent
2293                            // patches are in use.
2294                            break 'outer;
2295                        }
2296                        if self
2297                            .get_changeset(&chan.changes, &p.a)
2298                            .map_err(|e| e.0)?
2299                            .is_some()
2300                        {
2301                            // This channel has a patch, move on.
2302                            continue 'outer;
2303                        }
2304                    }
2305
2306                    debug!(target: "drop_channel", "actually unused: {:?}", p);
2307                    unused_changes.push(p.a);
2308                }
2309                let mut deps = Vec::new();
2310                for ch in unused_changes.iter() {
2311                    for x in btree::iter(&self.txn, &self.dep, Some((ch, None)))? {
2312                        let (k, v) = x?;
2313                        if k > ch {
2314                            break;
2315                        }
2316                        deps.push((*k, *v));
2317                    }
2318                    for (k, v) in deps.drain(..) {
2319                        debug!(target: "drop_channel", "deleting from revdep: {:?} {:?}", k, v);
2320                        btree::del(&mut self.txn, &mut self.dep, &k, Some(&v))?;
2321                        btree::del(&mut self.txn, &mut self.revdep, &v, Some(&k))?;
2322                    }
2323                }
2324                btree::drop(&mut self.txn, a)?;
2325                btree::drop(&mut self.txn, b)?;
2326                btree::drop(&mut self.txn, c)?;
2327                btree::drop(&mut self.txn, d)?;
2328                btree::drop(&mut self.txn, e)?;
2329                Ok(true)
2330            } else {
2331                Ok(false)
2332            }
2333        }
2334    }
2335
2336    fn open_or_create_remote(
2337        &mut self,
2338        id: RemoteId,
2339        path: &SmallStr,
2340    ) -> Result<RemoteRef<Self>, Self::GraphError> {
2341        unsafe {
2342            let mut commit = None;
2343            match self.open_remotes.lock().entry(id) {
2344                Entry::Vacant(v) => {
2345                    let r = match btree::get(&self.txn, &self.remotes, &id, None)? {
2346                        Some((name_, remote)) if *name_ == id => RemoteRef {
2347                            db: Arc::new(Mutex::new(Remote {
2348                                remote: UDb::from_page(remote.remote.into()),
2349                                rev: UDb::from_page(remote.rev.into()),
2350                                states: UDb::from_page(remote.states.into()),
2351                                id_rev: remote.id_rev,
2352                                tags: Db::from_page(remote.tags.into()),
2353                                path: path.to_owned(),
2354                            })),
2355                            id,
2356                        },
2357                        _ => {
2358                            let br = RemoteRef {
2359                                db: Arc::new(Mutex::new(Remote {
2360                                    remote: btree::create_db_(&mut self.txn)?,
2361                                    rev: btree::create_db_(&mut self.txn)?,
2362                                    states: btree::create_db_(&mut self.txn)?,
2363                                    id_rev: 0u64.into(),
2364                                    tags: btree::create_db(&mut self.txn)?,
2365                                    path: path.to_owned(),
2366                                })),
2367                                id,
2368                            };
2369                            commit = Some(br.clone());
2370                            br
2371                        }
2372                    };
2373                    v.insert(r);
2374                }
2375                Entry::Occupied(_) => {}
2376            }
2377            if let Some(commit) = commit {
2378                self.put_remotes(commit)?;
2379            }
2380            Ok(self.open_remotes.lock().get(&id).unwrap().clone())
2381        }
2382    }
2383
2384    fn drop_remote(&mut self, remote: RemoteRef<Self>) -> Result<bool, Self::GraphError> {
2385        let r = self.open_remotes.lock().remove(&remote.id).unwrap();
2386        std::mem::drop(remote);
2387        assert_eq!(Arc::strong_count(&r.db), 1);
2388        Ok(btree::del(&mut self.txn, &mut self.remotes, &r.id, None)?)
2389    }
2390
2391    fn drop_named_remote(&mut self, id: RemoteId) -> Result<bool, Self::GraphError> {
2392        if let Some(r) = self.open_remotes.lock().remove(&id) {
2393            assert_eq!(Arc::strong_count(&r.db), 1);
2394        }
2395        Ok(btree::del(&mut self.txn, &mut self.remotes, &id, None)?)
2396    }
2397
2398    fn commit(mut self) -> Result<(), Self::GraphError> {
2399        use std::ops::DerefMut;
2400        {
2401            let open_channels = std::mem::take(self.open_channels.lock().deref_mut());
2402            for (name, channel) in open_channels {
2403                debug!("commit_channel {:?}", name);
2404                self.commit_channel(channel)?
2405            }
2406        }
2407        {
2408            let open_remotes = std::mem::take(self.open_remotes.lock().deref_mut());
2409            for (name, remote) in open_remotes {
2410                debug!("commit remote {:?}", name);
2411                self.commit_remote(remote)?
2412            }
2413        }
2414        if let Some(ref cur) = self.cur_channel {
2415            unsafe {
2416                assert!(cur.len() < 256);
2417                let b = self.txn.root_page_mut();
2418                b[4096 - 256] = cur.len() as u8;
2419                std::ptr::copy(cur.as_ptr(), b.as_mut_ptr().add(4096 - 255), cur.len())
2420            }
2421        }
2422        // No need to set `Root::Version`, it is set at init.
2423        debug!(
2424            "{:x} {:x} {:x} {:x} {:x} {:x} {:x} {:x} {:x} {:x} {:x} {:x} {:x}",
2425            self.tree.db,
2426            self.revtree.db,
2427            self.inodes.db,
2428            self.revinodes.db,
2429            self.internal.db,
2430            self.external.db,
2431            self.revdep.db,
2432            self.channels.db,
2433            self.remotes.db,
2434            self.touched_files.db,
2435            self.dep.db,
2436            self.rev_touched_files.db,
2437            self.partials.db,
2438        );
2439        self.txn
2440            .set_root(Root::Tree as usize, u64::from(self.tree.db));
2441        self.txn
2442            .set_root(Root::RevTree as usize, u64::from(self.revtree.db));
2443        self.txn
2444            .set_root(Root::Inodes as usize, u64::from(self.inodes.db));
2445        self.txn
2446            .set_root(Root::RevInodes as usize, self.revinodes.db.into());
2447        self.txn
2448            .set_root(Root::Internal as usize, self.internal.db.into());
2449        self.txn
2450            .set_root(Root::External as usize, self.external.db.into());
2451        self.txn
2452            .set_root(Root::RevDep as usize, self.revdep.db.into());
2453        self.txn
2454            .set_root(Root::Channels as usize, self.channels.db.into());
2455        self.txn
2456            .set_root(Root::Remotes as usize, self.remotes.db.into());
2457        self.txn
2458            .set_root(Root::TouchedFiles as usize, self.touched_files.db.into());
2459        self.txn.set_root(Root::Dep as usize, self.dep.db.into());
2460        self.txn.set_root(
2461            Root::RevTouchedFiles as usize,
2462            self.rev_touched_files.db.into(),
2463        );
2464        self.txn
2465            .set_root(Root::Partials as usize, self.partials.db.into());
2466        self.txn.commit()?;
2467        Ok(())
2468    }
2469
2470    fn set_current_channel(&mut self, cur: &str) -> Result<(), Self::GraphError> {
2471        self.cur_channel = Some(cur.to_string());
2472        Ok(())
2473    }
2474}
2475
2476impl Txn {
2477    pub fn load_const_channel(&self, name: &SmallStr) -> Result<Option<Channel>, SanakirjaError> {
2478        unsafe {
2479            let name = name.to_owned();
2480            match btree::get(&self.txn, &self.channels, &name, None)? {
2481                Some((name_, c)) if name.as_ref() == name_ => {
2482                    debug!("load_const_channel = {:?} {:?}", name_, c);
2483                    Ok(Some(Channel {
2484                        graph: Db::from_page(c.graph.into()),
2485                        changes: Db::from_page(c.changes.into()),
2486                        revchanges: UDb::from_page(c.revchanges.into()),
2487                        states: UDb::from_page(c.states.into()),
2488                        tags: Db::from_page(c.tags.into()),
2489                        apply_counter: c.apply_counter.into(),
2490                        last_modified: c.last_modified.into(),
2491                        id: c.id,
2492                        name,
2493                    }))
2494                }
2495                _ => Ok(None),
2496            }
2497        }
2498    }
2499}
2500
2501impl<
2502    T: sanakirja::AllocPage<Error = ::sanakirja::Error>
2503        + sanakirja::RootPage
2504        + sanakirja::LoadPage<Error = ::sanakirja::Error>,
2505> MutTxn<T>
2506{
2507    fn put_channel(&mut self, channel: ChannelRef<Self>) -> Result<(), SanakirjaError> {
2508        debug!("Commit_channel.");
2509        let channel = channel.r.read();
2510        debug!("Commit_channel, dbs_channels = {:?}", self.channels);
2511        btree::del(&mut self.txn, &mut self.channels, &channel.name, None)?;
2512        debug!(
2513            "channels: {:x} {:x} {:x} {:x} {:x}",
2514            channel.graph.db,
2515            channel.changes.db,
2516            channel.revchanges.db,
2517            channel.states.db,
2518            channel.tags.db,
2519        );
2520        let sc = SerializedChannel {
2521            graph: u64::from(channel.graph.db).into(),
2522            changes: u64::from(channel.changes.db).into(),
2523            revchanges: u64::from(channel.revchanges.db).into(),
2524            states: u64::from(channel.states.db).into(),
2525            tags: u64::from(channel.tags.db).into(),
2526            apply_counter: channel.apply_counter.into(),
2527            last_modified: channel.last_modified.into(),
2528            id: channel.id,
2529        };
2530        btree::put(&mut self.txn, &mut self.channels, &channel.name, &sc)?;
2531        debug!("Commit_channel, self.channels = {:?}", self.channels);
2532        Ok(())
2533    }
2534
2535    fn commit_channel(&mut self, channel: ChannelRef<Self>) -> Result<(), SanakirjaError> {
2536        std::mem::drop(self.open_channels.lock().remove(&channel.r.read().name));
2537        self.put_channel(channel)
2538    }
2539
2540    fn put_remotes(&mut self, remote: RemoteRef<Self>) -> Result<(), SanakirjaError> {
2541        btree::del(&mut self.txn, &mut self.remotes, &remote.id, None)?;
2542        debug!("Commit_remote, dbs_remotes = {:?}", self.remotes);
2543        let r = remote.db.lock();
2544        let rr = OwnedSerializedRemote {
2545            _remote: u64::from(r.remote.db).into(),
2546            _rev: u64::from(r.rev.db).into(),
2547            _states: u64::from(r.states.db).into(),
2548            _id_rev: r.id_rev,
2549            _tags: u64::from(r.tags.db).into(),
2550            _path: r.path.clone(),
2551        };
2552        debug!("put {:?}", rr);
2553        btree::put(&mut self.txn, &mut self.remotes, &remote.id, &rr)?;
2554        debug!("Commit_remote, self.dbs.remotes = {:?}", self.remotes);
2555        Ok(())
2556    }
2557
2558    fn commit_remote(&mut self, remote: RemoteRef<Self>) -> Result<(), SanakirjaError> {
2559        std::mem::drop(self.open_remotes.lock().remove(&remote.id));
2560        // assert_eq!(Rc::strong_count(&remote.db), 1);
2561        self.put_remotes(remote)
2562    }
2563}
2564
2565direct_repr!(ChangeId);
2566impl ::sanakirja::debug::Check for ChangeId {}
2567
2568direct_repr!(Vertex<ChangeId>);
2569impl ::sanakirja::debug::Check for Vertex<ChangeId> {}
2570
2571direct_repr!(Position<ChangeId>);
2572impl ::sanakirja::debug::Check for Position<ChangeId> {}
2573
2574direct_repr!(SerializedEdge);
2575impl ::sanakirja::debug::Check for SerializedEdge {}
2576
2577impl ::sanakirja::debug::Check for PathId {}
2578impl Storable for PathId {
2579    fn compare<T>(&self, _: &T, x: &Self) -> std::cmp::Ordering {
2580        self.cmp(x)
2581    }
2582    type PageReferences = std::iter::Empty<u64>;
2583    fn page_references(&self) -> Self::PageReferences {
2584        std::iter::empty()
2585    }
2586}
2587impl UnsizedStorable for PathId {
2588    const ALIGN: usize = 8;
2589    fn size(&self) -> usize {
2590        9 + self.basename.len()
2591    }
2592    unsafe fn onpage_size(p: *const u8) -> usize {
2593        unsafe {
2594            let len = *(p.add(8)) as usize;
2595            9 + len
2596        }
2597    }
2598    unsafe fn from_raw_ptr<'a, T>(_: &T, p: *const u8) -> &'a Self {
2599        unsafe { path_id_from_raw_ptr(p) }
2600    }
2601    unsafe fn write_to_page(&self, p: *mut u8) {
2602        unsafe {
2603            *(p as *mut u64) = (self.parent_inode.0).0;
2604            self.basename.write_to_page(p.add(8))
2605        }
2606    }
2607}
2608
2609unsafe fn path_id_from_raw_ptr<'a>(p: *const u8) -> &'a PathId {
2610    unsafe {
2611        let len = *(p.add(8)) as usize;
2612        std::mem::transmute(std::slice::from_raw_parts(p, 1 + len))
2613    }
2614}
2615
2616#[test]
2617fn pathid_repr() {
2618    let o = OwnedPathId {
2619        parent_inode: Inode::ROOT,
2620        basename: SmallString::from_str("blablabla"),
2621    };
2622    let mut x = vec![0u8; 200];
2623
2624    unsafe {
2625        o.write_to_page(x.as_mut_ptr());
2626        let p = path_id_from_raw_ptr(x.as_ptr());
2627        assert_eq!(p.basename.as_str(), "blablabla");
2628        assert_eq!(p.parent_inode, Inode::ROOT);
2629    }
2630}
2631
2632direct_repr!(Inode);
2633impl ::sanakirja::debug::Check for Inode {}
2634direct_repr!(SerializedMerkle);
2635impl ::sanakirja::debug::Check for SerializedMerkle {}
2636direct_repr!(SerializedHash);
2637impl ::sanakirja::debug::Check for SerializedHash {}
2638
2639impl<A: ::sanakirja::debug::Check, B: ::sanakirja::debug::Check> ::sanakirja::debug::Check
2640    for Pair<A, B>
2641{
2642    fn add_refs<T: LoadPage>(
2643        &self,
2644        txn: &T,
2645        pages: &mut std::collections::BTreeMap<u64, usize>,
2646    ) -> Result<(), T::Error>
2647    where
2648        T::Error: std::fmt::Debug,
2649    {
2650        self.a.add_refs(txn, pages)?;
2651        self.b.add_refs(txn, pages)
2652    }
2653}
2654impl<A: Storable, B: Storable> Storable for Pair<A, B> {
2655    type PageReferences = core::iter::Chain<A::PageReferences, B::PageReferences>;
2656    fn page_references(&self) -> Self::PageReferences {
2657        self.a.page_references().chain(self.b.page_references())
2658    }
2659    fn compare<T: LoadPage>(&self, t: &T, b: &Self) -> core::cmp::Ordering {
2660        match self.a.compare(t, &b.a) {
2661            core::cmp::Ordering::Equal => self.b.compare(t, &b.b),
2662            ord => ord,
2663        }
2664    }
2665}
2666
2667impl<A: Ord + UnsizedStorable, B: Ord + UnsizedStorable> UnsizedStorable for Pair<A, B> {
2668    const ALIGN: usize = std::mem::align_of::<(A, B)>();
2669
2670    fn size(&self) -> usize {
2671        let a = self.a.size();
2672        let b_off = (a + (B::ALIGN - 1)) & !(B::ALIGN - 1);
2673        (b_off + self.b.size() + (Self::ALIGN - 1)) & !(Self::ALIGN - 1)
2674    }
2675    unsafe fn onpage_size(p: *const u8) -> usize {
2676        unsafe {
2677            let a = A::onpage_size(p);
2678            let b_off = (a + (B::ALIGN - 1)) & !(B::ALIGN - 1);
2679            let b_size = B::onpage_size(p.add(b_off));
2680            (b_off + b_size + (Self::ALIGN - 1)) & !(Self::ALIGN - 1)
2681        }
2682    }
2683    unsafe fn from_raw_ptr<'a, T>(_: &T, p: *const u8) -> &'a Self {
2684        unsafe { &*(p as *const Self) }
2685    }
2686    unsafe fn write_to_page_alloc<T: sanakirja::AllocPage>(&self, t: &mut T, p: *mut u8) {
2687        unsafe {
2688            self.a.write_to_page_alloc(t, p);
2689            let off = (self.a.size() + (B::ALIGN - 1)) & !(B::ALIGN - 1);
2690            self.b.write_to_page_alloc(t, p.add(off));
2691        }
2692    }
2693}
2694
2695impl ::sanakirja::debug::Check for SerializedRemote {}
2696impl Storable for SerializedRemote {
2697    type PageReferences = std::iter::Empty<u64>;
2698    fn page_references(&self) -> Self::PageReferences {
2699        std::iter::empty()
2700    }
2701    fn compare<T: LoadPage>(&self, _t: &T, b: &Self) -> core::cmp::Ordering {
2702        self.cmp(b)
2703    }
2704}
2705
2706const REMOTE_LEN: usize = 40;
2707
2708impl UnsizedStorable for SerializedRemote {
2709    const ALIGN: usize = 8;
2710
2711    fn size(&self) -> usize {
2712        REMOTE_LEN + 1 + self.path.len()
2713    }
2714    unsafe fn onpage_size(p: *const u8) -> usize {
2715        unsafe { REMOTE_LEN + 1 + (*p.add(REMOTE_LEN)) as usize }
2716    }
2717    unsafe fn from_raw_ptr<'a, T>(_: &T, p: *const u8) -> &'a Self {
2718        unsafe {
2719            let len = *p.add(REMOTE_LEN) as usize;
2720            let m: &SerializedRemote = std::mem::transmute(std::slice::from_raw_parts(p, 1 + len));
2721            m
2722        }
2723    }
2724    unsafe fn write_to_page_alloc<T: sanakirja::AllocPage>(&self, _: &mut T, p: *mut u8) {
2725        unsafe {
2726            std::ptr::copy(
2727                &self.remote as *const L64 as *const u8,
2728                p,
2729                REMOTE_LEN + 1 + self.path.len(),
2730            );
2731            debug!(
2732                "write_to_page: {:?}",
2733                std::slice::from_raw_parts(p, REMOTE_LEN + 1 + self.path.len())
2734            );
2735        }
2736    }
2737}
2738
2739#[derive(Debug)]
2740#[repr(C)]
2741struct OwnedSerializedRemote {
2742    _remote: L64,
2743    _rev: L64,
2744    _states: L64,
2745    _id_rev: L64,
2746    _tags: L64,
2747    _path: SmallString,
2748}
2749
2750impl std::ops::Deref for OwnedSerializedRemote {
2751    type Target = SerializedRemote;
2752    fn deref(&self) -> &Self::Target {
2753        let len = REMOTE_LEN + 1 + self._path.len();
2754        unsafe {
2755            std::mem::transmute(std::slice::from_raw_parts(
2756                self as *const Self as *const u8,
2757                len,
2758            ))
2759        }
2760    }
2761}
2762
2763direct_repr!(SerializedChannel);
2764impl ::sanakirja::debug::Check for SerializedChannel {}
2765
2766direct_repr!(RemoteId);
2767impl ::sanakirja::debug::Check for RemoteId {}