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
10pub 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 #[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 #[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
305pub 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
345unsafe 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 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 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 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
757pub 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 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 type RevinodesCursor =
1206 ::sanakirja::btree::cursor::Cursor<Position<ChangeId>, Inode, P<Position<ChangeId>, Inode>>;
1207 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 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 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 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 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 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 break 'outer;
2295 }
2296 if self
2297 .get_changeset(&chan.changes, &p.a)
2298 .map_err(|e| e.0)?
2299 .is_some()
2300 {
2301 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 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 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 {}