1 use crate::change::*;
2 use crate::small_string::*;
3 use crate::{HashMap, HashSet};
4 use parking_lot::{Mutex, RwLock};
5 use std::io::Write;
6 use std::sync::Arc;
7
8 mod change_id;
9 pub use change_id::*;
10 mod vertex;
11 pub use vertex::*;
12 mod edge;
13 pub use edge::*;
14 mod hash;
15 pub use hash::*;
16 mod inode;
17 pub use inode::*;
18 mod inode_metadata;
19 pub use inode_metadata::*;
20 mod path_id;
21 pub use path_id::*;
22 mod merkle;
23 pub use merkle::*;
24
25 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
26 pub struct L64(pub u64);
27
28 impl From<usize> for L64 {
from(u: usize) -> Self29 fn from(u: usize) -> Self {
30 L64((u as u64).to_le())
31 }
32 }
33
34 impl From<u64> for L64 {
from(u: u64) -> Self35 fn from(u: u64) -> Self {
36 L64(u.to_le())
37 }
38 }
39
40 impl From<L64> for u64 {
from(u: L64) -> Self41 fn from(u: L64) -> Self {
42 u64::from_le(u.0)
43 }
44 }
45
46 impl From<L64> for usize {
from(u: L64) -> Self47 fn from(u: L64) -> Self {
48 u64::from_le(u.0) as usize
49 }
50 }
51
52 impl L64 {
as_u64(&self) -> u6453 pub fn as_u64(&self) -> u64 {
54 u64::from_le(self.0)
55 }
as_usize(&self) -> usize56 pub fn as_usize(&self) -> usize {
57 u64::from_le(self.0) as usize
58 }
59 }
60
61 impl std::fmt::Display for L64 {
fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result62 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
63 self.0.fmt(fmt)
64 }
65 }
66
67 impl Ord for L64 {
cmp(&self, x: &Self) -> std::cmp::Ordering68 fn cmp(&self, x: &Self) -> std::cmp::Ordering {
69 u64::from_le(self.0).cmp(&u64::from_le(x.0))
70 }
71 }
72
73 impl PartialOrd for L64 {
partial_cmp(&self, x: &Self) -> Option<std::cmp::Ordering>74 fn partial_cmp(&self, x: &Self) -> Option<std::cmp::Ordering> {
75 Some(u64::from_le(self.0).cmp(&u64::from_le(x.0)))
76 }
77 }
78
79 impl std::ops::Add<L64> for L64 {
80 type Output = Self;
add(self, x: L64) -> L6481 fn add(self, x: L64) -> L64 {
82 L64((u64::from_le(self.0) + u64::from_le(x.0)).to_le())
83 }
84 }
85
86 impl std::ops::Add<usize> for L64 {
87 type Output = Self;
add(self, x: usize) -> L6488 fn add(self, x: usize) -> L64 {
89 L64((u64::from_le(self.0) + x as u64).to_le())
90 }
91 }
92
93 impl std::ops::SubAssign<usize> for L64 {
sub_assign(&mut self, x: usize)94 fn sub_assign(&mut self, x: usize) {
95 self.0 = ((u64::from_le(self.0)) - x as u64).to_le()
96 }
97 }
98
99 impl L64 {
from_slice_le(s: &[u8]) -> Self100 pub fn from_slice_le(s: &[u8]) -> Self {
101 let mut u = 0u64;
102 assert!(s.len() >= 8);
103 unsafe { std::ptr::copy_nonoverlapping(s.as_ptr(), &mut u as *mut u64 as *mut u8, 8) }
104 L64(u)
105 }
to_slice_le(&self, s: &mut [u8])106 pub fn to_slice_le(&self, s: &mut [u8]) {
107 assert!(s.len() >= 8);
108 unsafe {
109 std::ptr::copy_nonoverlapping(&self.0 as *const u64 as *const u8, s.as_mut_ptr(), 8)
110 }
111 }
112 }
113
114 #[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
115 #[repr(C)]
116 pub struct SerializedRemote {
117 remote: L64,
118 rev: L64,
119 states: L64,
120 id_rev: L64,
121 path: SmallStr,
122 }
123
124 #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
125 #[repr(C)]
126 pub struct SerializedChannel {
127 graph: L64,
128 changes: L64,
129 revchanges: L64,
130 states: L64,
131 tags: L64,
132 apply_counter: L64,
133 last_modified: L64,
134 id: RemoteId,
135 }
136
137 #[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
138 #[repr(C)]
139 pub struct Pair<A, B> {
140 pub a: A,
141 pub b: B,
142 }
143
144 pub trait Base32: Sized {
to_base32(&self) -> String145 fn to_base32(&self) -> String;
from_base32(b: &[u8]) -> Option<Self>146 fn from_base32(b: &[u8]) -> Option<Self>;
147 }
148
149 pub mod sanakirja;
150
151 pub type ApplyTimestamp = u64;
152
153 pub struct ChannelRef<T: ChannelTxnT> {
154 pub(crate) r: Arc<RwLock<T::Channel>>,
155 }
156
157 pub struct ArcTxn<T>(pub Arc<RwLock<T>>);
158
159 impl<T> Clone for ArcTxn<T> {
clone(&self) -> Self160 fn clone(&self) -> Self {
161 ArcTxn(self.0.clone())
162 }
163 }
164
165 impl<T: MutTxnT> ArcTxn<T> {
commit(self) -> Result<(), T::GraphError>166 pub fn commit(self) -> Result<(), T::GraphError> {
167 if let Ok(txn) = Arc::try_unwrap(self.0) {
168 txn.into_inner().commit()
169 } else {
170 unreachable!()
171 }
172 }
173 }
174
175 impl<T> std::ops::Deref for ArcTxn<T> {
176 type Target = RwLock<T>;
deref(&self) -> &Self::Target177 fn deref(&self) -> &Self::Target {
178 &self.0
179 }
180 }
181
182 #[derive(Debug, Error)]
183 #[error("Mutex poison error")]
184 pub struct PoisonError {}
185
186 impl<T: ChannelTxnT> ChannelRef<T> {
read(&self) -> parking_lot::RwLockReadGuard<T::Channel>187 pub fn read(&self) -> parking_lot::RwLockReadGuard<T::Channel> {
188 self.r.read()
189 }
write(&self) -> parking_lot::RwLockWriteGuard<T::Channel>190 pub fn write(&self) -> parking_lot::RwLockWriteGuard<T::Channel> {
191 self.r.write()
192 }
193 }
194
195 impl<T: ChannelTxnT> Clone for ChannelRef<T> {
clone(&self) -> Self196 fn clone(&self) -> Self {
197 ChannelRef { r: self.r.clone() }
198 }
199 }
200
201 impl<T: TxnT> RemoteRef<T> {
id(&self) -> &RemoteId202 pub fn id(&self) -> &RemoteId {
203 &self.id
204 }
205
lock(&self) -> parking_lot::MutexGuard<Remote<T>>206 pub fn lock(&self) -> parking_lot::MutexGuard<Remote<T>> {
207 self.db.lock()
208 }
209
id_revision(&self) -> u64210 pub fn id_revision(&self) -> u64 {
211 self.lock().id_rev.into()
212 }
213
set_id_revision(&self, rev: u64) -> ()214 pub fn set_id_revision(&self, rev: u64) -> () {
215 self.lock().id_rev = rev.into()
216 }
217 }
218
219 pub struct Remote<T: TxnT> {
220 pub remote: T::Remote,
221 pub rev: T::Revremote,
222 pub states: T::Remotestates,
223 pub id_rev: L64,
224 pub path: SmallString,
225 }
226
227 pub struct RemoteRef<T: TxnT> {
228 db: Arc<Mutex<Remote<T>>>,
229 id: RemoteId,
230 }
231
232 impl<T: TxnT> Clone for RemoteRef<T> {
clone(&self) -> Self233 fn clone(&self) -> Self {
234 RemoteRef {
235 db: self.db.clone(),
236 id: self.id.clone(),
237 }
238 }
239 }
240
241 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
242 pub struct RemoteId(pub(crate) [u8; 16]);
243
244 impl RemoteId {
nil() -> Self245 pub fn nil() -> Self {
246 RemoteId([0; 16])
247 }
from_bytes(b: &[u8]) -> Option<Self>248 pub fn from_bytes(b: &[u8]) -> Option<Self> {
249 if b.len() < 16 {
250 return None;
251 }
252 let mut x = RemoteId([0; 16]);
253 unsafe {
254 std::ptr::copy_nonoverlapping(b.as_ptr(), x.0.as_mut_ptr(), 16);
255 }
256 Some(x)
257 }
as_bytes(&self) -> &[u8; 16]258 pub fn as_bytes(&self) -> &[u8; 16] {
259 &self.0
260 }
261
from_base32(b: &[u8]) -> Option<Self>262 pub fn from_base32(b: &[u8]) -> Option<Self> {
263 let mut bb = RemoteId([0; 16]);
264 if b.len() != data_encoding::BASE32_NOPAD.encode_len(16) {
265 return None;
266 }
267 if data_encoding::BASE32_NOPAD.decode_mut(b, &mut bb.0).is_ok() {
268 Some(bb)
269 } else {
270 None
271 }
272 }
273 }
274
275 impl std::fmt::Display for RemoteId {
fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result276 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
277 write!(fmt, "{}", data_encoding::BASE32_NOPAD.encode(&self.0))
278 }
279 }
280
281 #[derive(Debug, Error)]
282 pub enum HashPrefixError<T: std::error::Error + 'static> {
283 #[error("Failed to parse hash prefix: {0}")]
284 Parse(String),
285 #[error("Ambiguous hash prefix: {0}")]
286 Ambiguous(String),
287 #[error("Change not found: {0}")]
288 NotFound(String),
289 #[error(transparent)]
290 Txn(T),
291 }
292
293 #[derive(Debug, Error)]
294 pub enum ForkError<T: std::error::Error + 'static> {
295 #[error("Channel name already exists: {0}")]
296 ChannelNameExists(String),
297 #[error(transparent)]
298 Txn(T),
299 }
300
301 #[derive(Debug, Error)]
302 #[error(transparent)]
303 pub struct TxnErr<E: std::error::Error + 'static>(pub E);
304
305 pub trait GraphTxnT: Sized {
306 type GraphError: std::error::Error + Send + Sync + 'static;
307 table!(graph);
308 get!(graph, Vertex<ChangeId>, SerializedEdge, GraphError);
309 /// Returns the external hash of an internal change identifier, if
310 /// the change is known.
get_external( &self, p: &ChangeId, ) -> Result<Option<&SerializedHash>, TxnErr<Self::GraphError>>311 fn get_external(
312 &self,
313 p: &ChangeId,
314 ) -> Result<Option<&SerializedHash>, TxnErr<Self::GraphError>>;
315
316 /// Returns the internal change identifier of change with external
317 /// hash `hash`, if the change is known.
get_internal( &self, p: &SerializedHash, ) -> Result<Option<&ChangeId>, TxnErr<Self::GraphError>>318 fn get_internal(
319 &self,
320 p: &SerializedHash,
321 ) -> Result<Option<&ChangeId>, TxnErr<Self::GraphError>>;
322
323 type Adj;
init_adj( &self, g: &Self::Graph, v: Vertex<ChangeId>, dest: Position<ChangeId>, min: EdgeFlags, max: EdgeFlags, ) -> Result<Self::Adj, TxnErr<Self::GraphError>>324 fn init_adj(
325 &self,
326 g: &Self::Graph,
327 v: Vertex<ChangeId>,
328 dest: Position<ChangeId>,
329 min: EdgeFlags,
330 max: EdgeFlags,
331 ) -> Result<Self::Adj, TxnErr<Self::GraphError>>;
next_adj<'a>( &'a self, g: &Self::Graph, a: &mut Self::Adj, ) -> Option<Result<&'a SerializedEdge, TxnErr<Self::GraphError>>>332 fn next_adj<'a>(
333 &'a self,
334 g: &Self::Graph,
335 a: &mut Self::Adj,
336 ) -> Option<Result<&'a SerializedEdge, TxnErr<Self::GraphError>>>;
337
find_block<'a>( &'a self, graph: &Self::Graph, p: Position<ChangeId>, ) -> Result<&'a Vertex<ChangeId>, BlockError<Self::GraphError>>338 fn find_block<'a>(
339 &'a self,
340 graph: &Self::Graph,
341 p: Position<ChangeId>,
342 ) -> Result<&'a Vertex<ChangeId>, BlockError<Self::GraphError>>;
343
find_block_end<'a>( &'a self, graph: &Self::Graph, p: Position<ChangeId>, ) -> Result<&'a Vertex<ChangeId>, BlockError<Self::GraphError>>344 fn find_block_end<'a>(
345 &'a self,
346 graph: &Self::Graph,
347 p: Position<ChangeId>,
348 ) -> Result<&'a Vertex<ChangeId>, BlockError<Self::GraphError>>;
349 }
350
351 pub trait ChannelTxnT: GraphTxnT {
352 type Channel: Sync + Send;
353
name<'a>(&self, channel: &'a Self::Channel) -> &'a str354 fn name<'a>(&self, channel: &'a Self::Channel) -> &'a str;
id<'a>(&self, c: &'a Self::Channel) -> &'a RemoteId355 fn id<'a>(&self, c: &'a Self::Channel) -> &'a RemoteId;
graph<'a>(&self, channel: &'a Self::Channel) -> &'a Self::Graph356 fn graph<'a>(&self, channel: &'a Self::Channel) -> &'a Self::Graph;
apply_counter(&self, channel: &Self::Channel) -> u64357 fn apply_counter(&self, channel: &Self::Channel) -> u64;
last_modified(&self, channel: &Self::Channel) -> u64358 fn last_modified(&self, channel: &Self::Channel) -> u64;
changes<'a>(&self, channel: &'a Self::Channel) -> &'a Self::Changeset359 fn changes<'a>(&self, channel: &'a Self::Channel) -> &'a Self::Changeset;
rev_changes<'a>(&self, channel: &'a Self::Channel) -> &'a Self::RevChangeset360 fn rev_changes<'a>(&self, channel: &'a Self::Channel) -> &'a Self::RevChangeset;
tags<'a>(&self, channel: &'a Self::Channel) -> &'a Self::Tags361 fn tags<'a>(&self, channel: &'a Self::Channel) -> &'a Self::Tags;
states<'a>(&self, channel: &'a Self::Channel) -> &'a Self::States362 fn states<'a>(&self, channel: &'a Self::Channel) -> &'a Self::States;
363
364 type Changeset;
365 type RevChangeset;
get_changeset( &self, channel: &Self::Changeset, c: &ChangeId, ) -> Result<Option<&L64>, TxnErr<Self::GraphError>>366 fn get_changeset(
367 &self,
368 channel: &Self::Changeset,
369 c: &ChangeId,
370 ) -> Result<Option<&L64>, TxnErr<Self::GraphError>>;
get_revchangeset( &self, channel: &Self::RevChangeset, c: &L64, ) -> Result<Option<&Pair<ChangeId, SerializedMerkle>>, TxnErr<Self::GraphError>>371 fn get_revchangeset(
372 &self,
373 channel: &Self::RevChangeset,
374 c: &L64,
375 ) -> Result<Option<&Pair<ChangeId, SerializedMerkle>>, TxnErr<Self::GraphError>>;
376
377 type ChangesetCursor;
cursor_changeset<'txn>( &'txn self, channel: &Self::Changeset, pos: Option<ChangeId>, ) -> Result< crate::pristine::Cursor<Self, &'txn Self, Self::ChangesetCursor, ChangeId, L64>, TxnErr<Self::GraphError>, >378 fn cursor_changeset<'txn>(
379 &'txn self,
380 channel: &Self::Changeset,
381 pos: Option<ChangeId>,
382 ) -> Result<
383 crate::pristine::Cursor<Self, &'txn Self, Self::ChangesetCursor, ChangeId, L64>,
384 TxnErr<Self::GraphError>,
385 >;
cursor_changeset_next( &self, cursor: &mut Self::ChangesetCursor, ) -> Result<Option<(&ChangeId, &L64)>, TxnErr<Self::GraphError>>386 fn cursor_changeset_next(
387 &self,
388 cursor: &mut Self::ChangesetCursor,
389 ) -> Result<Option<(&ChangeId, &L64)>, TxnErr<Self::GraphError>>;
390
cursor_changeset_prev( &self, cursor: &mut Self::ChangesetCursor, ) -> Result<Option<(&ChangeId, &L64)>, TxnErr<Self::GraphError>>391 fn cursor_changeset_prev(
392 &self,
393 cursor: &mut Self::ChangesetCursor,
394 ) -> Result<Option<(&ChangeId, &L64)>, TxnErr<Self::GraphError>>;
395
396 type RevchangesetCursor;
cursor_revchangeset_ref<RT: std::ops::Deref<Target = Self>>( txn: RT, channel: &Self::RevChangeset, pos: Option<L64>, ) -> Result< Cursor<Self, RT, Self::RevchangesetCursor, L64, Pair<ChangeId, SerializedMerkle>>, TxnErr<Self::GraphError>, >397 fn cursor_revchangeset_ref<RT: std::ops::Deref<Target = Self>>(
398 txn: RT,
399 channel: &Self::RevChangeset,
400 pos: Option<L64>,
401 ) -> Result<
402 Cursor<Self, RT, Self::RevchangesetCursor, L64, Pair<ChangeId, SerializedMerkle>>,
403 TxnErr<Self::GraphError>,
404 >;
rev_cursor_revchangeset<'txn>( &'txn self, channel: &Self::RevChangeset, pos: Option<L64>, ) -> Result< RevCursor< Self, &'txn Self, Self::RevchangesetCursor, L64, Pair<ChangeId, SerializedMerkle>, >, TxnErr<Self::GraphError>, >405 fn rev_cursor_revchangeset<'txn>(
406 &'txn self,
407 channel: &Self::RevChangeset,
408 pos: Option<L64>,
409 ) -> Result<
410 RevCursor<
411 Self,
412 &'txn Self,
413 Self::RevchangesetCursor,
414 L64,
415 Pair<ChangeId, SerializedMerkle>,
416 >,
417 TxnErr<Self::GraphError>,
418 >;
cursor_revchangeset_next( &self, cursor: &mut Self::RevchangesetCursor, ) -> Result<Option<(&L64, &Pair<ChangeId, SerializedMerkle>)>, TxnErr<Self::GraphError>>419 fn cursor_revchangeset_next(
420 &self,
421 cursor: &mut Self::RevchangesetCursor,
422 ) -> Result<Option<(&L64, &Pair<ChangeId, SerializedMerkle>)>, TxnErr<Self::GraphError>>;
423
cursor_revchangeset_prev( &self, cursor: &mut Self::RevchangesetCursor, ) -> Result<Option<(&L64, &Pair<ChangeId, SerializedMerkle>)>, TxnErr<Self::GraphError>>424 fn cursor_revchangeset_prev(
425 &self,
426 cursor: &mut Self::RevchangesetCursor,
427 ) -> Result<Option<(&L64, &Pair<ChangeId, SerializedMerkle>)>, TxnErr<Self::GraphError>>;
428
429 type States;
channel_has_state( &self, channel: &Self::States, hash: &SerializedMerkle, ) -> Result<Option<L64>, TxnErr<Self::GraphError>>430 fn channel_has_state(
431 &self,
432 channel: &Self::States,
433 hash: &SerializedMerkle,
434 ) -> Result<Option<L64>, TxnErr<Self::GraphError>>;
435
436 type Tags;
get_tags( &self, channel: &Self::Tags, c: &L64, ) -> Result<Option<&SerializedHash>, TxnErr<Self::GraphError>>437 fn get_tags(
438 &self,
439 channel: &Self::Tags,
440 c: &L64,
441 ) -> Result<Option<&SerializedHash>, TxnErr<Self::GraphError>>;
442
443 type TagsCursor;
cursor_tags<'txn>( &'txn self, channel: &Self::Tags, pos: Option<L64>, ) -> Result< crate::pristine::Cursor<Self, &'txn Self, Self::TagsCursor, L64, SerializedHash>, TxnErr<Self::GraphError>, >444 fn cursor_tags<'txn>(
445 &'txn self,
446 channel: &Self::Tags,
447 pos: Option<L64>,
448 ) -> Result<
449 crate::pristine::Cursor<Self, &'txn Self, Self::TagsCursor, L64, SerializedHash>,
450 TxnErr<Self::GraphError>,
451 >;
452
cursor_tags_next( &self, cursor: &mut Self::TagsCursor, ) -> Result<Option<(&L64, &SerializedHash)>, TxnErr<Self::GraphError>>453 fn cursor_tags_next(
454 &self,
455 cursor: &mut Self::TagsCursor,
456 ) -> Result<Option<(&L64, &SerializedHash)>, TxnErr<Self::GraphError>>;
457
cursor_tags_prev( &self, cursor: &mut Self::TagsCursor, ) -> Result<Option<(&L64, &SerializedHash)>, TxnErr<Self::GraphError>>458 fn cursor_tags_prev(
459 &self,
460 cursor: &mut Self::TagsCursor,
461 ) -> Result<Option<(&L64, &SerializedHash)>, TxnErr<Self::GraphError>>;
462
iter_tags( &self, channel: &Self::Tags, from: u64, ) -> Result<Cursor<Self, &Self, Self::TagsCursor, L64, SerializedHash>, TxnErr<Self::GraphError>>463 fn iter_tags(
464 &self,
465 channel: &Self::Tags,
466 from: u64,
467 ) -> Result<Cursor<Self, &Self, Self::TagsCursor, L64, SerializedHash>, TxnErr<Self::GraphError>>;
468
rev_iter_tags( &self, channel: &Self::Tags, from: Option<u64>, ) -> Result< RevCursor<Self, &Self, Self::TagsCursor, L64, SerializedHash>, TxnErr<Self::GraphError>, >469 fn rev_iter_tags(
470 &self,
471 channel: &Self::Tags,
472 from: Option<u64>,
473 ) -> Result<
474 RevCursor<Self, &Self, Self::TagsCursor, L64, SerializedHash>,
475 TxnErr<Self::GraphError>,
476 >;
477 }
478
479 pub trait GraphIter: GraphTxnT {
480 type GraphCursor;
graph_cursor( &self, g: &Self::Graph, s: Option<&Vertex<ChangeId>>, ) -> Result<Self::GraphCursor, TxnErr<Self::GraphError>>481 fn graph_cursor(
482 &self,
483 g: &Self::Graph,
484 s: Option<&Vertex<ChangeId>>,
485 ) -> Result<Self::GraphCursor, TxnErr<Self::GraphError>>;
next_graph<'txn>( &'txn self, g: &Self::Graph, a: &mut Self::GraphCursor, ) -> Option<Result<(&'txn Vertex<ChangeId>, &'txn SerializedEdge), TxnErr<Self::GraphError>>>486 fn next_graph<'txn>(
487 &'txn self,
488 g: &Self::Graph,
489 a: &mut Self::GraphCursor,
490 ) -> Option<Result<(&'txn Vertex<ChangeId>, &'txn SerializedEdge), TxnErr<Self::GraphError>>>;
491
iter_graph<'a>( &'a self, g: &'a Self::Graph, s: Option<&Vertex<ChangeId>>, ) -> Result<GraphIterator<'a, Self>, TxnErr<Self::GraphError>>492 fn iter_graph<'a>(
493 &'a self,
494 g: &'a Self::Graph,
495 s: Option<&Vertex<ChangeId>>,
496 ) -> Result<GraphIterator<'a, Self>, TxnErr<Self::GraphError>> {
497 Ok(GraphIterator {
498 cursor: self.graph_cursor(g, s)?,
499 txn: self,
500 g: g,
501 })
502 }
503 }
504
505 pub struct GraphIterator<'a, T: GraphIter> {
506 txn: &'a T,
507 g: &'a T::Graph,
508 cursor: T::GraphCursor,
509 }
510
511 impl<'a, T: GraphIter> Iterator for GraphIterator<'a, T> {
512 type Item = Result<(&'a Vertex<ChangeId>, &'a SerializedEdge), TxnErr<T::GraphError>>;
next(&mut self) -> Option<Self::Item>513 fn next(&mut self) -> Option<Self::Item> {
514 self.txn.next_graph(self.g, &mut self.cursor)
515 }
516 }
517
518 #[derive(Debug, Error)]
519 pub enum BlockError<T: std::error::Error + 'static> {
520 #[error(transparent)]
521 Txn(T),
522 #[error("Block error: {:?}", block)]
523 Block { block: Position<ChangeId> },
524 }
525
526 impl<T: std::error::Error + 'static> std::convert::From<TxnErr<T>> for BlockError<T> {
from(e: TxnErr<T>) -> Self527 fn from(e: TxnErr<T>) -> Self {
528 BlockError::Txn(e.0)
529 }
530 }
531
532 pub trait DepsTxnT: Sized {
533 type DepsError: std::error::Error + Send + Sync + 'static;
534 table!(revdep);
535 table!(dep);
536 table_get!(dep, ChangeId, ChangeId, DepsError);
537 cursor_ref!(dep, ChangeId, ChangeId, DepsError);
538 table_get!(revdep, ChangeId, ChangeId, DepsError);
iter_revdep( &self, p: &ChangeId, ) -> Result<Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId>, TxnErr<Self::DepsError>>539 fn iter_revdep(
540 &self,
541 p: &ChangeId,
542 ) -> Result<Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId>, TxnErr<Self::DepsError>>;
iter_dep( &self, p: &ChangeId, ) -> Result<Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId>, TxnErr<Self::DepsError>>543 fn iter_dep(
544 &self,
545 p: &ChangeId,
546 ) -> Result<Cursor<Self, &Self, Self::DepCursor, ChangeId, ChangeId>, TxnErr<Self::DepsError>>;
iter_dep_ref<RT: std::ops::Deref<Target = Self> + Clone>( txn: RT, p: &ChangeId, ) -> Result<Cursor<Self, RT, Self::DepCursor, ChangeId, ChangeId>, TxnErr<Self::DepsError>>547 fn iter_dep_ref<RT: std::ops::Deref<Target = Self> + Clone>(
548 txn: RT,
549 p: &ChangeId,
550 ) -> Result<Cursor<Self, RT, Self::DepCursor, ChangeId, ChangeId>, TxnErr<Self::DepsError>>;
iter_touched( &self, p: &Position<ChangeId>, ) -> Result< Cursor<Self, &Self, Self::Touched_filesCursor, Position<ChangeId>, ChangeId>, TxnErr<Self::DepsError>, >551 fn iter_touched(
552 &self,
553 p: &Position<ChangeId>,
554 ) -> Result<
555 Cursor<Self, &Self, Self::Touched_filesCursor, Position<ChangeId>, ChangeId>,
556 TxnErr<Self::DepsError>,
557 >;
iter_rev_touched( &self, p: &ChangeId, ) -> Result< Cursor<Self, &Self, Self::Rev_touched_filesCursor, ChangeId, Position<ChangeId>>, TxnErr<Self::DepsError>, >558 fn iter_rev_touched(
559 &self,
560 p: &ChangeId,
561 ) -> Result<
562 Cursor<Self, &Self, Self::Rev_touched_filesCursor, ChangeId, Position<ChangeId>>,
563 TxnErr<Self::DepsError>,
564 >;
565 table!(touched_files);
566 table!(rev_touched_files);
567 table_get!(touched_files, Position<ChangeId>, ChangeId, DepsError);
568 table_get!(rev_touched_files, ChangeId, Position<ChangeId>, DepsError);
569 iter!(touched_files, Position<ChangeId>, ChangeId, DepsError);
570 iter!(rev_touched_files, ChangeId, Position<ChangeId>, DepsError);
571 }
572
573 pub trait TreeTxnT: Sized {
574 type TreeError: std::error::Error + Send + Sync + 'static;
575 table!(tree);
576 table_get!(tree, PathId, Inode, TreeError);
577 iter!(tree, PathId, Inode, TreeError);
578
579 table!(revtree);
580 table_get!(revtree, Inode, PathId, TreeError);
581 iter!(revtree, Inode, PathId, TreeError);
582
583 table!(inodes);
584 table!(revinodes);
585 table_get!(inodes, Inode, Position<ChangeId>, TreeError);
586 table_get!(revinodes, Position<ChangeId>, Inode, TreeError);
587
588 table!(partials);
589 cursor!(partials, SmallStr, Position<ChangeId>, TreeError);
590 cursor!(inodes, Inode, Position<ChangeId>, TreeError);
iter_inodes( &self, ) -> Result< Cursor<Self, &Self, Self::InodesCursor, Inode, Position<ChangeId>>, TxnErr<Self::TreeError>, >591 fn iter_inodes(
592 &self,
593 ) -> Result<
594 Cursor<Self, &Self, Self::InodesCursor, Inode, Position<ChangeId>>,
595 TxnErr<Self::TreeError>,
596 >;
597
598 // #[cfg(debug_assertions)]
599 cursor!(revinodes, Position<ChangeId>, Inode, TreeError);
600 // #[cfg(debug_assertions)]
iter_revinodes( &self, ) -> Result< Cursor<Self, &Self, Self::RevinodesCursor, Position<ChangeId>, Inode>, TxnErr<Self::TreeError>, >601 fn iter_revinodes(
602 &self,
603 ) -> Result<
604 Cursor<Self, &Self, Self::RevinodesCursor, Position<ChangeId>, Inode>,
605 TxnErr<Self::TreeError>,
606 >;
iter_partials<'txn>( &'txn self, channel: &str, ) -> Result< Cursor<Self, &'txn Self, Self::PartialsCursor, SmallStr, Position<ChangeId>>, TxnErr<Self::TreeError>, >607 fn iter_partials<'txn>(
608 &'txn self,
609 channel: &str,
610 ) -> Result<
611 Cursor<Self, &'txn Self, Self::PartialsCursor, SmallStr, Position<ChangeId>>,
612 TxnErr<Self::TreeError>,
613 >;
614 }
615
616 /// The trait of immutable transactions.
617 pub trait TxnT:
618 GraphTxnT
619 + ChannelTxnT
620 + DepsTxnT<DepsError = <Self as GraphTxnT>::GraphError>
621 + TreeTxnT<TreeError = <Self as GraphTxnT>::GraphError>
622 {
623 table!(channels);
624 cursor!(channels, SmallStr, SerializedChannel);
625
hash_from_prefix( &self, prefix: &str, ) -> Result<(Hash, ChangeId), HashPrefixError<Self::GraphError>>626 fn hash_from_prefix(
627 &self,
628 prefix: &str,
629 ) -> Result<(Hash, ChangeId), HashPrefixError<Self::GraphError>>;
hash_from_prefix_remote( &self, remote: &RemoteRef<Self>, prefix: &str, ) -> Result<Hash, HashPrefixError<Self::GraphError>>630 fn hash_from_prefix_remote(
631 &self,
632 remote: &RemoteRef<Self>,
633 prefix: &str,
634 ) -> Result<Hash, HashPrefixError<Self::GraphError>>;
635
load_channel( &self, name: &str, ) -> Result<Option<ChannelRef<Self>>, TxnErr<Self::GraphError>>636 fn load_channel(
637 &self,
638 name: &str,
639 ) -> Result<Option<ChannelRef<Self>>, TxnErr<Self::GraphError>>;
640
load_remote( &self, name: &RemoteId, ) -> Result<Option<RemoteRef<Self>>, TxnErr<Self::GraphError>>641 fn load_remote(
642 &self,
643 name: &RemoteId,
644 ) -> Result<Option<RemoteRef<Self>>, TxnErr<Self::GraphError>>;
645
646 /// Iterate a function over all channels. The loop stops the first
647 /// time `f` returns `false`.
iter_channels<'txn>( &'txn self, start: &str, ) -> Result<ChannelIterator<'txn, Self>, TxnErr<Self::GraphError>>648 fn iter_channels<'txn>(
649 &'txn self,
650 start: &str,
651 ) -> Result<ChannelIterator<'txn, Self>, TxnErr<Self::GraphError>>;
652
iter_remotes<'txn>( &'txn self, start: &RemoteId, ) -> Result<RemotesIterator<'txn, Self>, TxnErr<Self::GraphError>>653 fn iter_remotes<'txn>(
654 &'txn self,
655 start: &RemoteId,
656 ) -> Result<RemotesIterator<'txn, Self>, TxnErr<Self::GraphError>>;
657
658 table!(remotes);
659 cursor!(remotes, RemoteId, SerializedRemote);
660 table!(remote);
661 table!(revremote);
662 table!(remotestates);
663 cursor!(remote, L64, Pair<SerializedHash, SerializedMerkle>);
664 rev_cursor!(remote, L64, Pair<SerializedHash, SerializedMerkle>);
665
iter_remote<'txn>( &'txn self, remote: &Self::Remote, k: u64, ) -> Result< Cursor<Self, &'txn Self, Self::RemoteCursor, L64, Pair<SerializedHash, SerializedMerkle>>, TxnErr<Self::GraphError>, >666 fn iter_remote<'txn>(
667 &'txn self,
668 remote: &Self::Remote,
669 k: u64,
670 ) -> Result<
671 Cursor<Self, &'txn Self, Self::RemoteCursor, L64, Pair<SerializedHash, SerializedMerkle>>,
672 TxnErr<Self::GraphError>,
673 >;
674
iter_rev_remote<'txn>( &'txn self, remote: &Self::Remote, k: Option<L64>, ) -> Result< RevCursor< Self, &'txn Self, Self::RemoteCursor, L64, Pair<SerializedHash, SerializedMerkle>, >, TxnErr<Self::GraphError>, >675 fn iter_rev_remote<'txn>(
676 &'txn self,
677 remote: &Self::Remote,
678 k: Option<L64>,
679 ) -> Result<
680 RevCursor<
681 Self,
682 &'txn Self,
683 Self::RemoteCursor,
684 L64,
685 Pair<SerializedHash, SerializedMerkle>,
686 >,
687 TxnErr<Self::GraphError>,
688 >;
689
get_remote( &mut self, name: RemoteId, ) -> Result<Option<RemoteRef<Self>>, TxnErr<Self::GraphError>>690 fn get_remote(
691 &mut self,
692 name: RemoteId,
693 ) -> Result<Option<RemoteRef<Self>>, TxnErr<Self::GraphError>>;
694
last_remote( &self, remote: &Self::Remote, ) -> Result<Option<(u64, &Pair<SerializedHash, SerializedMerkle>)>, TxnErr<Self::GraphError>>695 fn last_remote(
696 &self,
697 remote: &Self::Remote,
698 ) -> Result<Option<(u64, &Pair<SerializedHash, SerializedMerkle>)>, TxnErr<Self::GraphError>>;
699
get_remote_state( &self, remote: &Self::Remote, n: u64, ) -> Result<Option<(u64, &Pair<SerializedHash, SerializedMerkle>)>, TxnErr<Self::GraphError>>700 fn get_remote_state(
701 &self,
702 remote: &Self::Remote,
703 n: u64,
704 ) -> Result<Option<(u64, &Pair<SerializedHash, SerializedMerkle>)>, TxnErr<Self::GraphError>>;
705
remote_has_change( &self, remote: &RemoteRef<Self>, hash: &SerializedHash, ) -> Result<bool, TxnErr<Self::GraphError>>706 fn remote_has_change(
707 &self,
708 remote: &RemoteRef<Self>,
709 hash: &SerializedHash,
710 ) -> Result<bool, TxnErr<Self::GraphError>>;
remote_has_state( &self, remote: &RemoteRef<Self>, hash: &SerializedMerkle, ) -> Result<bool, TxnErr<Self::GraphError>>711 fn remote_has_state(
712 &self,
713 remote: &RemoteRef<Self>,
714 hash: &SerializedMerkle,
715 ) -> Result<bool, TxnErr<Self::GraphError>>;
716
current_channel(&self) -> Result<&str, Self::GraphError>717 fn current_channel(&self) -> Result<&str, Self::GraphError>;
718 }
719
720 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
721 pub struct SerializedPublicKey {
722 algorithm: crate::key::Algorithm,
723 key: [u8; 32],
724 }
725
726 /// Iterate the graph between `(key, min_flag)` and `(key,
727 /// max_flag)`, where both bounds are included.
iter_adjacent<'txn, T: GraphTxnT>( txn: &'txn T, graph: &'txn T::Graph, key: Vertex<ChangeId>, min_flag: EdgeFlags, max_flag: EdgeFlags, ) -> Result<AdjacentIterator<'txn, T>, TxnErr<T::GraphError>>728 pub(crate) fn iter_adjacent<'txn, T: GraphTxnT>(
729 txn: &'txn T,
730 graph: &'txn T::Graph,
731 key: Vertex<ChangeId>,
732 min_flag: EdgeFlags,
733 max_flag: EdgeFlags,
734 ) -> Result<AdjacentIterator<'txn, T>, TxnErr<T::GraphError>> {
735 Ok(AdjacentIterator {
736 it: txn.init_adj(graph, key, Position::ROOT, min_flag, max_flag)?,
737 graph,
738 txn,
739 })
740 }
741
iter_alive_children<'txn, T: GraphTxnT>( txn: &'txn T, graph: &'txn T::Graph, key: Vertex<ChangeId>, ) -> Result<AdjacentIterator<'txn, T>, TxnErr<T::GraphError>>742 pub(crate) fn iter_alive_children<'txn, T: GraphTxnT>(
743 txn: &'txn T,
744 graph: &'txn T::Graph,
745 key: Vertex<ChangeId>,
746 ) -> Result<AdjacentIterator<'txn, T>, TxnErr<T::GraphError>> {
747 iter_adjacent(
748 txn,
749 graph,
750 key,
751 EdgeFlags::empty(),
752 EdgeFlags::alive_children(),
753 )
754 }
755
iter_deleted_parents<'txn, T: GraphTxnT>( txn: &'txn T, graph: &'txn T::Graph, key: Vertex<ChangeId>, ) -> Result<AdjacentIterator<'txn, T>, TxnErr<T::GraphError>>756 pub(crate) fn iter_deleted_parents<'txn, T: GraphTxnT>(
757 txn: &'txn T,
758 graph: &'txn T::Graph,
759 key: Vertex<ChangeId>,
760 ) -> Result<AdjacentIterator<'txn, T>, TxnErr<T::GraphError>> {
761 iter_adjacent(
762 txn,
763 graph,
764 key,
765 EdgeFlags::DELETED | EdgeFlags::PARENT,
766 EdgeFlags::all(),
767 )
768 }
769
iter_adj_all<'txn, T: GraphTxnT>( txn: &'txn T, graph: &'txn T::Graph, key: Vertex<ChangeId>, ) -> Result<AdjacentIterator<'txn, T>, TxnErr<T::GraphError>>770 pub fn iter_adj_all<'txn, T: GraphTxnT>(
771 txn: &'txn T,
772 graph: &'txn T::Graph,
773 key: Vertex<ChangeId>,
774 ) -> Result<AdjacentIterator<'txn, T>, TxnErr<T::GraphError>> {
775 iter_adjacent(txn, graph, key, EdgeFlags::empty(), EdgeFlags::all())
776 }
777
tree_path<T: TreeTxnT>( txn: &T, v: &Position<ChangeId>, ) -> Result<Option<String>, TxnErr<T::TreeError>>778 pub(crate) fn tree_path<T: TreeTxnT>(
779 txn: &T,
780 v: &Position<ChangeId>,
781 ) -> Result<Option<String>, TxnErr<T::TreeError>> {
782 if let Some(mut inode) = txn.get_revinodes(v, None)? {
783 let mut components = Vec::new();
784 while !inode.is_root() {
785 if let Some(next) = txn.get_revtree(inode, None)? {
786 components.push(next.basename.as_str().to_string());
787 inode = &next.parent_inode;
788 } else {
789 assert!(components.is_empty());
790 return Ok(None);
791 }
792 }
793 if let Some(mut result) = components.pop() {
794 while let Some(c) = components.pop() {
795 result = result + "/" + c.as_str()
796 }
797 return Ok(Some(result));
798 }
799 }
800 Ok(None)
801 }
802
internal<T: GraphTxnT>( txn: &T, h: &Option<Hash>, p: ChangeId, ) -> Result<Option<ChangeId>, TxnErr<T::GraphError>>803 pub(crate) fn internal<T: GraphTxnT>(
804 txn: &T,
805 h: &Option<Hash>,
806 p: ChangeId,
807 ) -> Result<Option<ChangeId>, TxnErr<T::GraphError>> {
808 match *h {
809 Some(Hash::None) => Ok(Some(ChangeId::ROOT)),
810 Some(ref h) => Ok(txn.get_internal(&h.into())?.map(|x| *x)),
811 None => Ok(Some(p)),
812 }
813 }
814
815 #[derive(Error, Debug)]
816 pub enum InconsistentChange<T: std::error::Error + 'static> {
817 #[error("Undeclared dependency")]
818 UndeclaredDep,
819 #[error(transparent)]
820 Txn(T),
821 }
822
823 impl<T: std::error::Error + 'static> std::convert::From<TxnErr<T>> for InconsistentChange<T> {
from(e: TxnErr<T>) -> Self824 fn from(e: TxnErr<T>) -> Self {
825 InconsistentChange::Txn(e.0)
826 }
827 }
828
internal_pos<T: GraphTxnT>( txn: &T, pos: &Position<Option<Hash>>, change_id: ChangeId, ) -> Result<Position<ChangeId>, InconsistentChange<T::GraphError>>829 pub fn internal_pos<T: GraphTxnT>(
830 txn: &T,
831 pos: &Position<Option<Hash>>,
832 change_id: ChangeId,
833 ) -> Result<Position<ChangeId>, InconsistentChange<T::GraphError>> {
834 let change = if let Some(p) = pos.change {
835 if let Some(&p) = txn.get_internal(&p.into())? {
836 p
837 } else {
838 return Err(InconsistentChange::UndeclaredDep);
839 }
840 } else {
841 change_id
842 };
843
844 Ok(Position {
845 change,
846 pos: pos.pos,
847 })
848 }
849
internal_vertex<T: GraphTxnT>( txn: &T, v: &Vertex<Option<Hash>>, change_id: ChangeId, ) -> Result<Vertex<ChangeId>, InconsistentChange<T::GraphError>>850 pub fn internal_vertex<T: GraphTxnT>(
851 txn: &T,
852 v: &Vertex<Option<Hash>>,
853 change_id: ChangeId,
854 ) -> Result<Vertex<ChangeId>, InconsistentChange<T::GraphError>> {
855 let change = if let Some(p) = v.change {
856 if let Some(&p) = txn.get_internal(&p.into())? {
857 p
858 } else {
859 return Err(InconsistentChange::UndeclaredDep);
860 }
861 } else {
862 change_id
863 };
864
865 Ok(Vertex {
866 change,
867 start: v.start,
868 end: v.end,
869 })
870 }
871
changeid_log<'db, 'txn: 'db, T: ChannelTxnT>( txn: &'txn T, channel: &'db T::Channel, from: L64, ) -> Result< Cursor<T, &'txn T, T::RevchangesetCursor, L64, Pair<ChangeId, SerializedMerkle>>, TxnErr<T::GraphError>, >872 pub fn changeid_log<'db, 'txn: 'db, T: ChannelTxnT>(
873 txn: &'txn T,
874 channel: &'db T::Channel,
875 from: L64,
876 ) -> Result<
877 Cursor<T, &'txn T, T::RevchangesetCursor, L64, Pair<ChangeId, SerializedMerkle>>,
878 TxnErr<T::GraphError>,
879 > {
880 T::cursor_revchangeset_ref(txn, txn.rev_changes(&channel), Some(from))
881 }
882
current_state<'db, 'txn: 'db, T: ChannelTxnT>( txn: &'txn T, channel: &'db T::Channel, ) -> Result<Merkle, TxnErr<T::GraphError>>883 pub(crate) fn current_state<'db, 'txn: 'db, T: ChannelTxnT>(
884 txn: &'txn T,
885 channel: &'db T::Channel,
886 ) -> Result<Merkle, TxnErr<T::GraphError>> {
887 if let Some(e) = txn
888 .rev_cursor_revchangeset(txn.rev_changes(&channel), None)?
889 .next()
890 {
891 Ok((&(e?.1).b).into())
892 } else {
893 Ok(Merkle::zero())
894 }
895 }
896
changeid_rev_log<'db, 'txn: 'db, T: ChannelTxnT>( txn: &'txn T, channel: &'db T::Channel, from: Option<L64>, ) -> Result< RevCursor<T, &'txn T, T::RevchangesetCursor, L64, Pair<ChangeId, SerializedMerkle>>, TxnErr<T::GraphError>, >897 pub(crate) fn changeid_rev_log<'db, 'txn: 'db, T: ChannelTxnT>(
898 txn: &'txn T,
899 channel: &'db T::Channel,
900 from: Option<L64>,
901 ) -> Result<
902 RevCursor<T, &'txn T, T::RevchangesetCursor, L64, Pair<ChangeId, SerializedMerkle>>,
903 TxnErr<T::GraphError>,
904 > {
905 Ok(txn.rev_cursor_revchangeset(txn.rev_changes(&channel), from)?)
906 }
907
log_for_path< 'txn, 'channel, T: ChannelTxnT + DepsTxnT<DepsError = <T as GraphTxnT>::GraphError>, >( txn: &'txn T, channel: &'channel T::Channel, key: Position<ChangeId>, from_timestamp: u64, ) -> Result<PathChangeset<'channel, 'txn, T>, TxnErr<T::GraphError>>908 pub(crate) fn log_for_path<
909 'txn,
910 'channel,
911 T: ChannelTxnT + DepsTxnT<DepsError = <T as GraphTxnT>::GraphError>,
912 >(
913 txn: &'txn T,
914 channel: &'channel T::Channel,
915 key: Position<ChangeId>,
916 from_timestamp: u64,
917 ) -> Result<PathChangeset<'channel, 'txn, T>, TxnErr<T::GraphError>> {
918 Ok(PathChangeset {
919 iter: T::cursor_revchangeset_ref(
920 txn,
921 txn.rev_changes(&channel),
922 Some(from_timestamp.into()),
923 )?,
924 txn,
925 channel,
926 key,
927 })
928 }
929
rev_log_for_path< 'txn, 'channel, T: ChannelTxnT + DepsTxnT<DepsError = <T as GraphTxnT>::GraphError>, >( txn: &'txn T, channel: &'channel T::Channel, key: Position<ChangeId>, from_timestamp: u64, ) -> Result<RevPathChangeset<'channel, 'txn, T>, TxnErr<T::GraphError>>930 pub(crate) fn rev_log_for_path<
931 'txn,
932 'channel,
933 T: ChannelTxnT + DepsTxnT<DepsError = <T as GraphTxnT>::GraphError>,
934 >(
935 txn: &'txn T,
936 channel: &'channel T::Channel,
937 key: Position<ChangeId>,
938 from_timestamp: u64,
939 ) -> Result<RevPathChangeset<'channel, 'txn, T>, TxnErr<T::GraphError>> {
940 Ok(RevPathChangeset {
941 iter: txn
942 .rev_cursor_revchangeset(txn.rev_changes(&channel), Some(from_timestamp.into()))?,
943 txn,
944 channel,
945 key,
946 })
947 }
948
949 /// Is there an alive/pseudo edge from `a` to `b`.
test_edge<T: GraphTxnT>( txn: &T, channel: &T::Graph, a: Position<ChangeId>, b: Position<ChangeId>, min: EdgeFlags, max: EdgeFlags, ) -> Result<bool, TxnErr<T::GraphError>>950 pub(crate) fn test_edge<T: GraphTxnT>(
951 txn: &T,
952 channel: &T::Graph,
953 a: Position<ChangeId>,
954 b: Position<ChangeId>,
955 min: EdgeFlags,
956 max: EdgeFlags,
957 ) -> Result<bool, TxnErr<T::GraphError>> {
958 debug!("is_connected {:?} {:?}", a, b);
959 let mut adj = txn.init_adj(channel, a.inode_vertex(), b, min, max)?;
960 match txn.next_adj(channel, &mut adj) {
961 Some(Ok(dest)) => Ok(dest.dest() == b),
962 Some(Err(e)) => Err(e.into()),
963 None => Ok(false),
964 }
965 }
966
967 /// Is there an alive/pseudo edge to `a`.
is_alive<T: GraphTxnT>( txn: &T, channel: &T::Graph, a: &Vertex<ChangeId>, ) -> Result<bool, TxnErr<T::GraphError>>968 pub(crate) fn is_alive<T: GraphTxnT>(
969 txn: &T,
970 channel: &T::Graph,
971 a: &Vertex<ChangeId>,
972 ) -> Result<bool, TxnErr<T::GraphError>> {
973 if a.is_root() {
974 return Ok(true);
975 }
976 for e in iter_adjacent(
977 txn,
978 channel,
979 *a,
980 EdgeFlags::PARENT,
981 EdgeFlags::all() - EdgeFlags::DELETED,
982 )? {
983 let e = e?;
984 if !e.flag().contains(EdgeFlags::PSEUDO)
985 && (e.flag().contains(EdgeFlags::BLOCK) || a.is_empty())
986 {
987 return Ok(true);
988 }
989 }
990 Ok(false)
991 }
992
make_changeid<T: GraphTxnT>( txn: &T, h: &Hash, ) -> Result<ChangeId, TxnErr<T::GraphError>>993 pub(crate) fn make_changeid<T: GraphTxnT>(
994 txn: &T,
995 h: &Hash,
996 ) -> Result<ChangeId, TxnErr<T::GraphError>> {
997 if let Some(h_) = txn.get_internal(&h.into())? {
998 debug!("make_changeid, found = {:?} {:?}", h, h_);
999 return Ok(*h_);
1000 }
1001 use byteorder::{ByteOrder, LittleEndian};
1002 let mut p = match h {
1003 Hash::None => return Ok(ChangeId::ROOT),
1004 Hash::Blake3(ref s) => LittleEndian::read_u64(&s[..]),
1005 };
1006 let mut pp = ChangeId(L64(p));
1007 while let Some(ext) = txn.get_external(&pp)? {
1008 debug!("ext = {:?}", ext);
1009 p = u64::from_le(p) + 1;
1010 pp = ChangeId(L64(p.to_le()));
1011 }
1012 Ok(pp)
1013 }
1014
1015 // #[cfg(debug_assertions)]
debug_tree<P: AsRef<std::path::Path>, T: TreeTxnT>( txn: &T, file: P, ) -> Result<(), std::io::Error>1016 pub fn debug_tree<P: AsRef<std::path::Path>, T: TreeTxnT>(
1017 txn: &T,
1018 file: P,
1019 ) -> Result<(), std::io::Error> {
1020 let root = OwnedPathId {
1021 parent_inode: Inode::ROOT,
1022 basename: SmallString::from_str(""),
1023 };
1024 let mut f = std::fs::File::create(file)?;
1025 for t in txn.iter_tree(&root, None).unwrap() {
1026 writeln!(f, "{:?}", t.unwrap())?
1027 }
1028 Ok(())
1029 }
1030
1031 // #[cfg(debug_assertions)]
debug_tree_print<T: TreeTxnT>(txn: &T)1032 pub fn debug_tree_print<T: TreeTxnT>(txn: &T) {
1033 let root = OwnedPathId {
1034 parent_inode: Inode::ROOT,
1035 basename: SmallString::from_str(""),
1036 };
1037 for t in txn.iter_tree(&root, None).unwrap() {
1038 debug!("{:?}", t.unwrap())
1039 }
1040 }
1041
1042 // #[cfg(debug_assertions)]
debug_remotes<T: TxnT>(txn: &T)1043 pub fn debug_remotes<T: TxnT>(txn: &T) {
1044 for t in txn.iter_remotes(&RemoteId([0; 16])).unwrap() {
1045 let rem = t.unwrap();
1046 debug!("{:?}", rem.id());
1047 for x in txn.iter_remote(&rem.lock().remote, 0).unwrap() {
1048 debug!(" {:?}", x.unwrap());
1049 }
1050 }
1051 }
1052
1053 /// Write the graph of a channel to file `f` in graphviz
1054 /// format. **Warning:** this can be really large on old channels.
1055 // #[cfg(debug_assertions)]
debug_to_file<P: AsRef<std::path::Path>, T: GraphIter + ChannelTxnT>( txn: &T, channel: &ChannelRef<T>, f: P, ) -> Result<bool, std::io::Error>1056 pub fn debug_to_file<P: AsRef<std::path::Path>, T: GraphIter + ChannelTxnT>(
1057 txn: &T,
1058 channel: &ChannelRef<T>,
1059 f: P,
1060 ) -> Result<bool, std::io::Error> {
1061 info!("debug {:?}", f.as_ref());
1062 let mut f = std::fs::File::create(f)?;
1063 let channel = channel.r.read();
1064 let done = debug(txn, txn.graph(&*channel), &mut f)?;
1065 f.flush()?;
1066 info!("done debugging {:?}", done);
1067 Ok(done)
1068 }
1069
1070 // #[cfg(debug_assertions)]
debug_revtree<P: AsRef<std::path::Path>, T: TreeTxnT>( txn: &T, file: P, ) -> Result<(), std::io::Error>1071 pub fn debug_revtree<P: AsRef<std::path::Path>, T: TreeTxnT>(
1072 txn: &T,
1073 file: P,
1074 ) -> Result<(), std::io::Error> {
1075 let mut f = std::fs::File::create(file)?;
1076 for t in txn.iter_revtree(&Inode::ROOT, None).unwrap() {
1077 writeln!(f, "{:?}", t.unwrap())?
1078 }
1079 Ok(())
1080 }
1081
1082 // #[cfg(debug_assertions)]
debug_revtree_print<T: TreeTxnT>(txn: &T)1083 pub fn debug_revtree_print<T: TreeTxnT>(txn: &T) {
1084 for t in txn.iter_revtree(&Inode::ROOT, None).unwrap() {
1085 debug!("{:?}", t.unwrap())
1086 }
1087 }
1088
1089 // #[cfg(debug_assertions)]
debug_inodes<T: TreeTxnT>(txn: &T)1090 pub fn debug_inodes<T: TreeTxnT>(txn: &T) {
1091 debug!("debug_inodes");
1092 for t in txn.iter_inodes().unwrap() {
1093 debug!("debug_inodes = {:?}", t.unwrap())
1094 }
1095 debug!("/debug_inodes");
1096 }
1097
1098 // #[cfg(debug_assertions)]
debug_revinodes<T: TreeTxnT>(txn: &T)1099 pub fn debug_revinodes<T: TreeTxnT>(txn: &T) {
1100 debug!("debug_revinodes");
1101 for t in txn.iter_revinodes().unwrap() {
1102 debug!("debug_revinodes = {:?}", t.unwrap())
1103 }
1104 debug!("/debug_revinodes");
1105 }
1106
1107 /// Write the graph of a channel to write `W` in graphviz
1108 /// format. **Warning:** this can be really large on old channels.
1109 // #[cfg(debug_assertions)]
debug<W: Write, T: GraphIter>( txn: &T, channel: &T::Graph, mut f: W, ) -> Result<bool, std::io::Error>1110 pub fn debug<W: Write, T: GraphIter>(
1111 txn: &T,
1112 channel: &T::Graph,
1113 mut f: W,
1114 ) -> Result<bool, std::io::Error> {
1115 let mut cursor = txn.graph_cursor(&channel, None).unwrap();
1116 writeln!(f, "digraph {{")?;
1117 let mut keys = std::collections::HashSet::new();
1118 let mut at_least_one = false;
1119 while let Some(x) = txn.next_graph(&channel, &mut cursor) {
1120 let (k, v) = x.unwrap();
1121 at_least_one = true;
1122 debug!("debug {:?} {:?}", k, v);
1123 if keys.insert(k) {
1124 debug_vertex(&mut f, *k)?
1125 }
1126 debug_edge(txn, channel, &mut f, *k, *v)?
1127 }
1128 writeln!(f, "}}")?;
1129 Ok(at_least_one)
1130 }
1131
check_alive<T: ChannelTxnT + GraphIter>( txn: &T, channel: &T::Graph, ) -> ( HashMap<Vertex<ChangeId>, Option<Vertex<ChangeId>>>, Vec<(Vertex<ChangeId>, Option<Vertex<ChangeId>>)>, )1132 pub fn check_alive<T: ChannelTxnT + GraphIter>(
1133 txn: &T,
1134 channel: &T::Graph,
1135 ) -> (
1136 HashMap<Vertex<ChangeId>, Option<Vertex<ChangeId>>>,
1137 Vec<(Vertex<ChangeId>, Option<Vertex<ChangeId>>)>,
1138 ) {
1139 // Find the reachable with a DFS.
1140 let mut reachable = HashSet::default();
1141 let mut stack = vec![Vertex::ROOT];
1142 while let Some(v) = stack.pop() {
1143 if !reachable.insert(v) {
1144 continue;
1145 }
1146 for e in iter_adjacent(
1147 txn,
1148 &channel,
1149 v,
1150 EdgeFlags::empty(),
1151 EdgeFlags::all() - EdgeFlags::DELETED - EdgeFlags::PARENT,
1152 )
1153 .unwrap()
1154 {
1155 let e = e.unwrap();
1156 stack.push(*txn.find_block(&channel, e.dest()).unwrap());
1157 }
1158 }
1159 debug!("reachable = {:#?}", reachable);
1160
1161 // Find the alive
1162 let mut alive_unreachable = HashMap::default();
1163 let mut cursor = txn.graph_cursor(&channel, None).unwrap();
1164
1165 let mut visited = HashSet::default();
1166 let mut k0 = Vertex::ROOT;
1167 let mut k0_has_pseudo_parents = false;
1168 let mut k0_has_regular_parents = false;
1169 let mut reachable_pseudo = Vec::new();
1170 while let Some(x) = txn.next_graph(&channel, &mut cursor) {
1171 let (&k, &v) = x.unwrap();
1172 debug!("check_alive, k = {:?}, v = {:?}", k, v);
1173 if k0 != k {
1174 if k0_has_pseudo_parents && !k0_has_regular_parents {
1175 reachable_pseudo.push((
1176 k0,
1177 find_file(txn, &channel, k0, &mut stack, &mut visited).unwrap(),
1178 ))
1179 }
1180 k0 = k;
1181 k0_has_pseudo_parents = false;
1182 k0_has_regular_parents = false;
1183 }
1184 if v.flag().contains(EdgeFlags::PARENT)
1185 && !v.flag().contains(EdgeFlags::FOLDER)
1186 && !v.flag().contains(EdgeFlags::DELETED)
1187 {
1188 if v.flag().contains(EdgeFlags::PSEUDO) {
1189 k0_has_pseudo_parents = true
1190 } else {
1191 k0_has_regular_parents = true
1192 }
1193 }
1194
1195 if v.flag().contains(EdgeFlags::PARENT)
1196 && (v.flag().contains(EdgeFlags::BLOCK) || k.is_empty())
1197 && !v.flag().contains(EdgeFlags::DELETED)
1198 && !reachable.contains(&k)
1199 {
1200 let file = find_file(txn, &channel, k, &mut stack, &mut visited).unwrap();
1201 alive_unreachable.insert(k, file);
1202 }
1203 }
1204 if !k0.is_root() && k0_has_pseudo_parents && !k0_has_regular_parents {
1205 reachable_pseudo.push((
1206 k0,
1207 find_file(txn, &channel, k0, &mut stack, &mut visited).unwrap(),
1208 ));
1209 }
1210
1211 (alive_unreachable, reachable_pseudo)
1212 }
1213
find_file<T: GraphTxnT>( txn: &T, channel: &T::Graph, k: Vertex<ChangeId>, stack: &mut Vec<Vertex<ChangeId>>, visited: &mut HashSet<Vertex<ChangeId>>, ) -> Result<Option<Vertex<ChangeId>>, TxnErr<T::GraphError>>1214 fn find_file<T: GraphTxnT>(
1215 txn: &T,
1216 channel: &T::Graph,
1217 k: Vertex<ChangeId>,
1218 stack: &mut Vec<Vertex<ChangeId>>,
1219 visited: &mut HashSet<Vertex<ChangeId>>,
1220 ) -> Result<Option<Vertex<ChangeId>>, TxnErr<T::GraphError>> {
1221 let mut file = None;
1222 stack.clear();
1223 stack.push(k);
1224 visited.clear();
1225 'outer: while let Some(kk) = stack.pop() {
1226 if !visited.insert(kk) {
1227 continue;
1228 }
1229 for e in iter_adjacent(txn, &channel, kk, EdgeFlags::PARENT, EdgeFlags::all())? {
1230 let e = e?;
1231 if e.flag().contains(EdgeFlags::PARENT) {
1232 if e.flag().contains(EdgeFlags::FOLDER) {
1233 file = Some(kk);
1234 break 'outer;
1235 }
1236 stack.push(*txn.find_block_end(&channel, e.dest()).unwrap());
1237 }
1238 }
1239 }
1240 Ok(file)
1241 }
1242
debug_root<W: Write, T: GraphTxnT>( txn: &T, channel: &T::Graph, root: Vertex<ChangeId>, mut f: W, down: bool, ) -> Result<(), std::io::Error>1243 pub fn debug_root<W: Write, T: GraphTxnT>(
1244 txn: &T,
1245 channel: &T::Graph,
1246 root: Vertex<ChangeId>,
1247 mut f: W,
1248 down: bool,
1249 ) -> Result<(), std::io::Error> {
1250 writeln!(f, "digraph {{")?;
1251 let mut visited = HashSet::default();
1252 let mut stack = vec![root];
1253 while let Some(v) = stack.pop() {
1254 if !visited.insert(v) {
1255 continue;
1256 }
1257 debug_vertex(&mut f, v)?;
1258 for e in iter_adj_all(txn, &channel, v).unwrap() {
1259 let e = e.unwrap();
1260 if e.flag().contains(EdgeFlags::PARENT) ^ down {
1261 debug_edge(txn, &channel, &mut f, v, *e)?;
1262 let v = if e.flag().contains(EdgeFlags::PARENT) {
1263 txn.find_block_end(&channel, e.dest()).unwrap()
1264 } else {
1265 txn.find_block(&channel, e.dest()).unwrap()
1266 };
1267 stack.push(*v);
1268 }
1269 }
1270 }
1271 writeln!(f, "}}")?;
1272 Ok(())
1273 }
1274
debug_vertex<W: std::io::Write>(mut f: W, k: Vertex<ChangeId>) -> Result<(), std::io::Error>1275 fn debug_vertex<W: std::io::Write>(mut f: W, k: Vertex<ChangeId>) -> Result<(), std::io::Error> {
1276 writeln!(
1277 f,
1278 "node_{}_{}_{}[label=\"{} [{};{}[\"];",
1279 k.change.to_base32(),
1280 k.start.0,
1281 k.end.0,
1282 k.change.to_base32(),
1283 k.start.0,
1284 k.end.0,
1285 )
1286 }
1287
debug_edge<T: GraphTxnT, W: std::io::Write>( txn: &T, channel: &T::Graph, mut f: W, k: Vertex<ChangeId>, v: SerializedEdge, ) -> Result<(), std::io::Error>1288 fn debug_edge<T: GraphTxnT, W: std::io::Write>(
1289 txn: &T,
1290 channel: &T::Graph,
1291 mut f: W,
1292 k: Vertex<ChangeId>,
1293 v: SerializedEdge,
1294 ) -> Result<(), std::io::Error> {
1295 let style = if v.flag().contains(EdgeFlags::DELETED) {
1296 ", style=dashed"
1297 } else if v.flag().contains(EdgeFlags::PSEUDO) {
1298 ", style=dotted"
1299 } else {
1300 ""
1301 };
1302 let color = if v.flag().contains(EdgeFlags::PARENT) {
1303 if v.flag().contains(EdgeFlags::FOLDER) {
1304 "orange"
1305 } else {
1306 "red"
1307 }
1308 } else if v.flag().contains(EdgeFlags::FOLDER) {
1309 "royalblue"
1310 } else {
1311 "forestgreen"
1312 };
1313
1314 if v.flag().contains(EdgeFlags::PARENT) {
1315 let dest = if v.dest().change.is_root() {
1316 Vertex::ROOT
1317 } else if let Ok(&dest) = txn.find_block_end(channel, v.dest()) {
1318 dest
1319 } else {
1320 return Ok(());
1321 };
1322 writeln!(
1323 f,
1324 "node_{}_{}_{} -> node_{}_{}_{} [label=\"{}{}{}\", color=\"{}\"{}];",
1325 k.change.to_base32(),
1326 k.start.0,
1327 k.end.0,
1328 dest.change.to_base32(),
1329 dest.start.0,
1330 dest.end.0,
1331 if v.flag().contains(EdgeFlags::BLOCK) {
1332 "["
1333 } else {
1334 ""
1335 },
1336 v.introduced_by().to_base32(),
1337 if v.flag().contains(EdgeFlags::BLOCK) {
1338 "]"
1339 } else {
1340 ""
1341 },
1342 color,
1343 style
1344 )?;
1345 } else if let Ok(dest) = txn.find_block(&channel, v.dest()) {
1346 writeln!(
1347 f,
1348 "node_{}_{}_{} -> node_{}_{}_{} [label=\"{}{}{}\", color=\"{}\"{}];",
1349 k.change.to_base32(),
1350 k.start.0,
1351 k.end.0,
1352 dest.change.to_base32(),
1353 dest.start.0,
1354 dest.end.0,
1355 if v.flag().contains(EdgeFlags::BLOCK) {
1356 "["
1357 } else {
1358 ""
1359 },
1360 v.introduced_by().to_base32(),
1361 if v.flag().contains(EdgeFlags::BLOCK) {
1362 "]"
1363 } else {
1364 ""
1365 },
1366 color,
1367 style
1368 )?;
1369 } else {
1370 writeln!(
1371 f,
1372 "node_{}_{}_{} -> node_{}_{} [label=\"{}{}{}\", color=\"{}\"{}];",
1373 k.change.to_base32(),
1374 k.start.0,
1375 k.end.0,
1376 v.dest().change.to_base32(),
1377 v.dest().pos.0,
1378 if v.flag().contains(EdgeFlags::BLOCK) {
1379 "["
1380 } else {
1381 ""
1382 },
1383 v.introduced_by().to_base32(),
1384 if v.flag().contains(EdgeFlags::BLOCK) {
1385 "]"
1386 } else {
1387 ""
1388 },
1389 color,
1390 style
1391 )?;
1392 }
1393 Ok(())
1394 }
1395
1396 /// A cursor over a table, initialised at a certain value.
1397 pub struct Cursor<T: Sized, RT: std::ops::Deref<Target = T>, Cursor, K: ?Sized, V: ?Sized> {
1398 pub cursor: Cursor,
1399 pub txn: RT,
1400 pub t: std::marker::PhantomData<T>,
1401 pub k: std::marker::PhantomData<K>,
1402 pub v: std::marker::PhantomData<V>,
1403 }
1404
1405 pub struct RevCursor<T: Sized, RT: std::ops::Deref<Target = T>, Cursor, K: ?Sized, V: ?Sized> {
1406 pub cursor: Cursor,
1407 pub txn: RT,
1408 pub t: std::marker::PhantomData<T>,
1409 pub k: std::marker::PhantomData<K>,
1410 pub v: std::marker::PhantomData<V>,
1411 }
1412
1413 initialized_cursor!(changeset, ChangeId, L64, ChannelTxnT, GraphError);
1414 initialized_cursor!(
1415 revchangeset,
1416 L64,
1417 Pair<ChangeId, SerializedMerkle>,
1418 ChannelTxnT,
1419 GraphError
1420 );
1421 initialized_rev_cursor!(
1422 revchangeset,
1423 L64,
1424 Pair<ChangeId, SerializedMerkle>,
1425 ChannelTxnT,
1426 GraphError
1427 );
1428 initialized_cursor!(tree, PathId, Inode, TreeTxnT, TreeError);
1429 initialized_cursor!(revtree, Inode, PathId, TreeTxnT, TreeError);
1430 initialized_cursor!(dep, ChangeId, ChangeId, DepsTxnT, DepsError);
1431 initialized_cursor!(partials, SmallStr, Position<ChangeId>, TreeTxnT, TreeError);
1432 initialized_cursor!(
1433 rev_touched_files,
1434 ChangeId,
1435 Position<ChangeId>,
1436 DepsTxnT,
1437 DepsError
1438 );
1439 initialized_cursor!(
1440 touched_files,
1441 Position<ChangeId>,
1442 ChangeId,
1443 DepsTxnT,
1444 DepsError
1445 );
1446 initialized_cursor!(remote, L64, Pair<SerializedHash, SerializedMerkle>);
1447 initialized_rev_cursor!(remote, L64, Pair<SerializedHash, SerializedMerkle>);
1448 initialized_cursor!(inodes, Inode, Position<ChangeId>, TreeTxnT, TreeError);
1449 initialized_cursor!(revinodes, Position<ChangeId>, Inode, TreeTxnT, TreeError);
1450 initialized_cursor!(tags, L64, SerializedHash, ChannelTxnT, GraphError);
1451 initialized_rev_cursor!(tags, L64, SerializedHash, ChannelTxnT, GraphError);
1452
1453 /// An iterator for nodes adjacent to `key` through an edge with flags smaller than `max_flag`.
1454 pub struct AdjacentIterator<'txn, T: GraphTxnT> {
1455 it: T::Adj,
1456 graph: &'txn T::Graph,
1457 txn: &'txn T,
1458 }
1459
1460 impl<'txn, T: GraphTxnT> Iterator for AdjacentIterator<'txn, T> {
1461 type Item = Result<&'txn SerializedEdge, TxnErr<T::GraphError>>;
next(&mut self) -> Option<Self::Item>1462 fn next(&mut self) -> Option<Self::Item> {
1463 self.txn.next_adj(self.graph, &mut self.it)
1464 }
1465 }
1466
1467 pub struct PathChangeset<'channel, 'txn: 'channel, T: ChannelTxnT + DepsTxnT> {
1468 txn: &'txn T,
1469 channel: &'channel T::Channel,
1470 iter: Cursor<T, &'txn T, T::RevchangesetCursor, L64, Pair<ChangeId, SerializedMerkle>>,
1471 key: Position<ChangeId>,
1472 }
1473
1474 pub struct RevPathChangeset<'channel, 'txn: 'channel, T: ChannelTxnT + DepsTxnT> {
1475 txn: &'txn T,
1476 channel: &'channel T::Channel,
1477 iter: RevCursor<T, &'txn T, T::RevchangesetCursor, L64, Pair<ChangeId, SerializedMerkle>>,
1478 key: Position<ChangeId>,
1479 }
1480
1481 impl<
1482 'channel,
1483 'txn: 'channel,
1484 T: ChannelTxnT + DepsTxnT<DepsError = <T as GraphTxnT>::GraphError>,
1485 > Iterator for PathChangeset<'channel, 'txn, T>
1486 {
1487 type Item = Result<Hash, TxnErr<T::GraphError>>;
next(&mut self) -> Option<Self::Item>1488 fn next(&mut self) -> Option<Self::Item> {
1489 while let Some(x) = self.iter.next() {
1490 let changeid = match x {
1491 Ok(x) => (x.1).a,
1492 Err(e) => return Some(Err(e)),
1493 };
1494 let iter = match self.txn.iter_rev_touched_files(&changeid, None) {
1495 Ok(iter) => iter,
1496 Err(e) => return Some(Err(e)),
1497 };
1498 for x in iter {
1499 let (p, touched) = match x {
1500 Ok(x) => x,
1501 Err(e) => return Some(Err(e)),
1502 };
1503 if *p > changeid {
1504 break;
1505 } else if *p < changeid {
1506 continue;
1507 }
1508 match is_ancestor_of(self.txn, self.txn.graph(&self.channel), self.key, *touched) {
1509 Ok(true) => {
1510 return self
1511 .txn
1512 .get_external(&changeid)
1513 .transpose()
1514 .map(|x| x.map(|x| x.into()))
1515 }
1516 Err(e) => return Some(Err(e)),
1517 Ok(false) => {}
1518 }
1519 }
1520 }
1521 None
1522 }
1523 }
1524
1525 impl<
1526 'channel,
1527 'txn: 'channel,
1528 T: ChannelTxnT + DepsTxnT<DepsError = <T as GraphTxnT>::GraphError>,
1529 > Iterator for RevPathChangeset<'channel, 'txn, T>
1530 {
1531 type Item = Result<Hash, TxnErr<T::GraphError>>;
next(&mut self) -> Option<Self::Item>1532 fn next(&mut self) -> Option<Self::Item> {
1533 loop {
1534 let changeid = match self.iter.next()? {
1535 Err(e) => return Some(Err(e)),
1536 Ok((_, p)) => p.a,
1537 };
1538 let iter = match self.txn.iter_rev_touched_files(&changeid, None) {
1539 Ok(iter) => iter,
1540 Err(e) => return Some(Err(e)),
1541 };
1542 for x in iter {
1543 let (p, touched) = match x {
1544 Ok(x) => x,
1545 Err(e) => return Some(Err(e)),
1546 };
1547 if *p > changeid {
1548 break;
1549 } else if *p < changeid {
1550 continue;
1551 }
1552 match is_ancestor_of(self.txn, self.txn.graph(&self.channel), self.key, *touched) {
1553 Ok(true) => {
1554 return self
1555 .txn
1556 .get_external(&changeid)
1557 .transpose()
1558 .map(|x| x.map(From::from))
1559 }
1560 Err(e) => return Some(Err(e)),
1561 Ok(false) => {}
1562 }
1563 }
1564 }
1565 }
1566 }
1567
is_ancestor_of<T: GraphTxnT>( txn: &T, channel: &T::Graph, a: Position<ChangeId>, b: Position<ChangeId>, ) -> Result<bool, TxnErr<T::GraphError>>1568 fn is_ancestor_of<T: GraphTxnT>(
1569 txn: &T,
1570 channel: &T::Graph,
1571 a: Position<ChangeId>,
1572 b: Position<ChangeId>,
1573 ) -> Result<bool, TxnErr<T::GraphError>> {
1574 let mut stack = vec![b];
1575 let mut visited = std::collections::HashSet::new();
1576 debug!("a = {:?}", a);
1577 while let Some(b) = stack.pop() {
1578 debug!("pop {:?}", b);
1579 if a == b {
1580 return Ok(true);
1581 }
1582 if !visited.insert(b) {
1583 continue;
1584 }
1585 for p in iter_adjacent(
1586 txn,
1587 channel,
1588 b.inode_vertex(),
1589 EdgeFlags::FOLDER | EdgeFlags::PARENT,
1590 EdgeFlags::FOLDER | EdgeFlags::PARENT | EdgeFlags::PSEUDO,
1591 )? {
1592 let p = p?;
1593 // Ok, since `p` is in the channel.
1594 let parent = txn.find_block_end(channel, p.dest()).unwrap();
1595 for pp in iter_adjacent(
1596 txn,
1597 channel,
1598 *parent,
1599 EdgeFlags::FOLDER | EdgeFlags::PARENT,
1600 EdgeFlags::FOLDER | EdgeFlags::PARENT | EdgeFlags::PSEUDO,
1601 )? {
1602 let pp = pp?;
1603 if pp.dest() == a {
1604 return Ok(true);
1605 }
1606 stack.push(pp.dest())
1607 }
1608 }
1609 }
1610 Ok(false)
1611 }
1612
1613 pub struct ChannelIterator<'txn, T: TxnT> {
1614 txn: &'txn T,
1615 cursor: T::ChannelsCursor,
1616 }
1617
1618 impl<'txn, T: TxnT> Iterator for ChannelIterator<'txn, T> {
1619 type Item = Result<(&'txn SmallStr, ChannelRef<T>), TxnErr<T::GraphError>>;
next(&mut self) -> Option<Self::Item>1620 fn next(&mut self) -> Option<Self::Item> {
1621 // Option<(SmallString, (u64, u64, u64, u64, u64, u64))>
1622 match self.txn.cursor_channels_next(&mut self.cursor) {
1623 Err(e) => Some(Err(e)),
1624 Ok(Some((name, _))) => Some(Ok((name, self.txn.load_channel(name.as_str()).unwrap()?))),
1625 Ok(None) => None,
1626 }
1627 }
1628 }
1629
1630 pub struct RemotesIterator<'txn, T: TxnT> {
1631 txn: &'txn T,
1632 cursor: T::RemotesCursor,
1633 }
1634
1635 impl<'txn, T: TxnT> Iterator for RemotesIterator<'txn, T> {
1636 type Item = Result<RemoteRef<T>, TxnErr<T::GraphError>>;
next(&mut self) -> Option<Self::Item>1637 fn next(&mut self) -> Option<Self::Item> {
1638 match self.txn.cursor_remotes_next(&mut self.cursor) {
1639 Ok(Some((name, _))) => self.txn.load_remote(name).transpose(),
1640 Ok(None) => None,
1641 Err(e) => Some(Err(e)),
1642 }
1643 }
1644 }
1645
1646 pub trait GraphMutTxnT: GraphTxnT {
1647 put_del!(internal, SerializedHash, ChangeId, GraphError);
1648 put_del!(external, ChangeId, SerializedHash, GraphError);
1649
1650 /// Insert a key and a value to a graph. Returns `false` if and only if `(k, v)` was already in the graph, in which case no insertion happened.
put_graph( &mut self, channel: &mut Self::Graph, k: &Vertex<ChangeId>, v: &SerializedEdge, ) -> Result<bool, TxnErr<Self::GraphError>>1651 fn put_graph(
1652 &mut self,
1653 channel: &mut Self::Graph,
1654 k: &Vertex<ChangeId>,
1655 v: &SerializedEdge,
1656 ) -> Result<bool, TxnErr<Self::GraphError>>;
1657
1658 /// Delete a key and a value from a graph. Returns `true` if and only if `(k, v)` was in the graph.
del_graph( &mut self, channel: &mut Self::Graph, k: &Vertex<ChangeId>, v: Option<&SerializedEdge>, ) -> Result<bool, TxnErr<Self::GraphError>>1659 fn del_graph(
1660 &mut self,
1661 channel: &mut Self::Graph,
1662 k: &Vertex<ChangeId>,
1663 v: Option<&SerializedEdge>,
1664 ) -> Result<bool, TxnErr<Self::GraphError>>;
1665
debug(&mut self, channel: &mut Self::Graph, extra: &str)1666 fn debug(&mut self, channel: &mut Self::Graph, extra: &str);
1667
1668 /// Split a key `[a, b[` at position `pos`, yielding two keys `[a,
1669 /// pos[` and `[pos, b[` linked by an edge.
split_block( &mut self, graph: &mut Self::Graph, key: &Vertex<ChangeId>, pos: ChangePosition, buf: &mut Vec<SerializedEdge>, ) -> Result<(), TxnErr<Self::GraphError>>1670 fn split_block(
1671 &mut self,
1672 graph: &mut Self::Graph,
1673 key: &Vertex<ChangeId>,
1674 pos: ChangePosition,
1675 buf: &mut Vec<SerializedEdge>,
1676 ) -> Result<(), TxnErr<Self::GraphError>>;
1677 }
1678
1679 pub trait ChannelMutTxnT: ChannelTxnT + GraphMutTxnT {
graph_mut(channel: &mut Self::Channel) -> &mut Self::Graph1680 fn graph_mut(channel: &mut Self::Channel) -> &mut Self::Graph;
touch_channel(&mut self, channel: &mut Self::Channel, t: Option<u64>)1681 fn touch_channel(&mut self, channel: &mut Self::Channel, t: Option<u64>);
1682
1683 /// Add a change and a timestamp to a change table. Returns `None` if and only if `(p, t)` was already in the change table, in which case no insertion happened. Returns the new state else.
put_changes( &mut self, channel: &mut Self::Channel, p: ChangeId, t: ApplyTimestamp, h: &Hash, ) -> Result<Option<Merkle>, TxnErr<Self::GraphError>>1684 fn put_changes(
1685 &mut self,
1686 channel: &mut Self::Channel,
1687 p: ChangeId,
1688 t: ApplyTimestamp,
1689 h: &Hash,
1690 ) -> Result<Option<Merkle>, TxnErr<Self::GraphError>>;
1691
1692 /// Delete a change from a change table. Returns `true` if and only if `(p, t)` was in the change table.
del_changes( &mut self, channel: &mut Self::Channel, p: ChangeId, t: ApplyTimestamp, ) -> Result<bool, TxnErr<Self::GraphError>>1693 fn del_changes(
1694 &mut self,
1695 channel: &mut Self::Channel,
1696 p: ChangeId,
1697 t: ApplyTimestamp,
1698 ) -> Result<bool, TxnErr<Self::GraphError>>;
1699
put_tags( &mut self, channel: &mut Self::Channel, t: ApplyTimestamp, h: &Hash, ) -> Result<(), TxnErr<Self::GraphError>>1700 fn put_tags(
1701 &mut self,
1702 channel: &mut Self::Channel,
1703 t: ApplyTimestamp,
1704 h: &Hash,
1705 ) -> Result<(), TxnErr<Self::GraphError>>;
1706
del_tags( &mut self, channel: &mut Self::Channel, t: ApplyTimestamp, ) -> Result<(), TxnErr<Self::GraphError>>1707 fn del_tags(
1708 &mut self,
1709 channel: &mut Self::Channel,
1710 t: ApplyTimestamp,
1711 ) -> Result<(), TxnErr<Self::GraphError>>;
1712 }
1713
1714 pub trait DepsMutTxnT: DepsTxnT {
1715 put_del!(dep, ChangeId, ChangeId, DepsError);
1716 put_del!(revdep, ChangeId, ChangeId, DepsError);
1717 put_del!(touched_files, Position<ChangeId>, ChangeId, DepsError);
1718 put_del!(rev_touched_files, ChangeId, Position<ChangeId>, DepsError);
1719 }
1720
1721 pub trait TreeMutTxnT: TreeTxnT {
1722 put_del!(inodes, Inode, Position<ChangeId>, TreeError);
1723 put_del!(revinodes, Position<ChangeId>, Inode, TreeError);
1724 put_del!(tree, PathId, Inode, TreeError);
1725 put_del!(revtree, Inode, PathId, TreeError);
put_partials( &mut self, k: &str, e: Position<ChangeId>, ) -> Result<bool, TxnErr<Self::TreeError>>1726 fn put_partials(
1727 &mut self,
1728 k: &str,
1729 e: Position<ChangeId>,
1730 ) -> Result<bool, TxnErr<Self::TreeError>>;
1731
del_partials( &mut self, k: &str, e: Option<Position<ChangeId>>, ) -> Result<bool, TxnErr<Self::TreeError>>1732 fn del_partials(
1733 &mut self,
1734 k: &str,
1735 e: Option<Position<ChangeId>>,
1736 ) -> Result<bool, TxnErr<Self::TreeError>>;
1737 }
1738
1739 /// The trait of immutable transactions.
1740 pub trait MutTxnT:
1741 GraphMutTxnT
1742 + ChannelMutTxnT
1743 + DepsMutTxnT<DepsError = <Self as GraphTxnT>::GraphError>
1744 + TreeMutTxnT<TreeError = <Self as GraphTxnT>::GraphError>
1745 + TxnT
1746 {
1747 /// Open a channel, creating it if it is missing. The return type
1748 /// is a `Rc<RefCell<…>>` in order to avoid:
1749 /// - opening the same channel twice. Since a channel contains pointers, that could potentially lead to double-borrow issues. We absolutely have to check that at runtime (hence the `RefCell`).
1750 /// - writing the channel to disk (if the backend is written on the disk) for every minor operation on the channel.
1751 ///
1752 /// Additionally, the `Rc` is used to:
1753 /// - avoid having to commit channels explicitly (channels are
1754 /// committed automatically upon committing the transaction), and
1755 /// - to return a value that doesn't borrow the transaction, so
1756 /// that the channel can actually be used in a mutable transaction.
open_or_create_channel(&mut self, name: &str) -> Result<ChannelRef<Self>, Self::GraphError>1757 fn open_or_create_channel(&mut self, name: &str) -> Result<ChannelRef<Self>, Self::GraphError>;
1758
fork( &mut self, channel: &ChannelRef<Self>, name: &str, ) -> Result<ChannelRef<Self>, ForkError<Self::GraphError>>1759 fn fork(
1760 &mut self,
1761 channel: &ChannelRef<Self>,
1762 name: &str,
1763 ) -> Result<ChannelRef<Self>, ForkError<Self::GraphError>>;
1764
rename_channel( &mut self, channel: &mut ChannelRef<Self>, name: &str, ) -> Result<(), ForkError<Self::GraphError>>1765 fn rename_channel(
1766 &mut self,
1767 channel: &mut ChannelRef<Self>,
1768 name: &str,
1769 ) -> Result<(), ForkError<Self::GraphError>>;
1770
drop_channel(&mut self, name: &str) -> Result<bool, Self::GraphError>1771 fn drop_channel(&mut self, name: &str) -> Result<bool, Self::GraphError>;
1772
1773 /// Commit this transaction.
commit(self) -> Result<(), Self::GraphError>1774 fn commit(self) -> Result<(), Self::GraphError>;
1775
open_or_create_remote( &mut self, id: RemoteId, path: &str, ) -> Result<RemoteRef<Self>, Self::GraphError>1776 fn open_or_create_remote(
1777 &mut self,
1778 id: RemoteId,
1779 path: &str,
1780 ) -> Result<RemoteRef<Self>, Self::GraphError>;
1781
put_remote( &mut self, remote: &mut RemoteRef<Self>, k: u64, v: (Hash, Merkle), ) -> Result<bool, Self::GraphError>1782 fn put_remote(
1783 &mut self,
1784 remote: &mut RemoteRef<Self>,
1785 k: u64,
1786 v: (Hash, Merkle),
1787 ) -> Result<bool, Self::GraphError>;
1788
del_remote( &mut self, remote: &mut RemoteRef<Self>, k: u64, ) -> Result<bool, Self::GraphError>1789 fn del_remote(
1790 &mut self,
1791 remote: &mut RemoteRef<Self>,
1792 k: u64,
1793 ) -> Result<bool, Self::GraphError>;
1794
drop_remote(&mut self, remote: RemoteRef<Self>) -> Result<bool, Self::GraphError>1795 fn drop_remote(&mut self, remote: RemoteRef<Self>) -> Result<bool, Self::GraphError>;
1796
drop_named_remote(&mut self, id: RemoteId) -> Result<bool, Self::GraphError>1797 fn drop_named_remote(&mut self, id: RemoteId) -> Result<bool, Self::GraphError>;
1798
set_current_channel(&mut self, cur: &str) -> Result<(), Self::GraphError>1799 fn set_current_channel(&mut self, cur: &str) -> Result<(), Self::GraphError>;
1800 }
1801
put_inodes_with_rev<T: TreeMutTxnT>( txn: &mut T, inode: &Inode, position: &Position<ChangeId>, ) -> Result<(), TxnErr<T::TreeError>>1802 pub(crate) fn put_inodes_with_rev<T: TreeMutTxnT>(
1803 txn: &mut T,
1804 inode: &Inode,
1805 position: &Position<ChangeId>,
1806 ) -> Result<(), TxnErr<T::TreeError>> {
1807 txn.put_inodes(inode, position)?;
1808 txn.put_revinodes(position, inode)?;
1809 Ok(())
1810 }
1811
del_inodes_with_rev<T: TreeMutTxnT>( txn: &mut T, inode: &Inode, position: &Position<ChangeId>, ) -> Result<bool, TxnErr<T::TreeError>>1812 pub(crate) fn del_inodes_with_rev<T: TreeMutTxnT>(
1813 txn: &mut T,
1814 inode: &Inode,
1815 position: &Position<ChangeId>,
1816 ) -> Result<bool, TxnErr<T::TreeError>> {
1817 if txn.del_inodes(inode, Some(position))? {
1818 assert!(txn.del_revinodes(position, Some(inode))?);
1819 Ok(true)
1820 } else {
1821 Ok(false)
1822 }
1823 }
1824
put_tree_with_rev<T: TreeMutTxnT>( txn: &mut T, file_id: &PathId, inode: &Inode, ) -> Result<(), TxnErr<T::TreeError>>1825 pub(crate) fn put_tree_with_rev<T: TreeMutTxnT>(
1826 txn: &mut T,
1827 file_id: &PathId,
1828 inode: &Inode,
1829 ) -> Result<(), TxnErr<T::TreeError>> {
1830 if txn.put_tree(file_id, inode)? {
1831 txn.put_revtree(inode, file_id)?;
1832 }
1833 Ok(())
1834 }
1835
del_tree_with_rev<T: TreeMutTxnT>( txn: &mut T, file_id: &PathId, inode: &Inode, ) -> Result<bool, TxnErr<T::TreeError>>1836 pub(crate) fn del_tree_with_rev<T: TreeMutTxnT>(
1837 txn: &mut T,
1838 file_id: &PathId,
1839 inode: &Inode,
1840 ) -> Result<bool, TxnErr<T::TreeError>> {
1841 if txn.del_tree(file_id, Some(inode))? {
1842 if !file_id.basename.is_empty() {
1843 assert!(txn.del_revtree(inode, Some(file_id))?);
1844 }
1845 Ok(true)
1846 } else {
1847 Ok(false)
1848 }
1849 }
1850
del_graph_with_rev<T: GraphMutTxnT>( txn: &mut T, graph: &mut T::Graph, mut flag: EdgeFlags, mut k0: Vertex<ChangeId>, mut k1: Vertex<ChangeId>, introduced_by: ChangeId, ) -> Result<bool, TxnErr<T::GraphError>>1851 pub(crate) fn del_graph_with_rev<T: GraphMutTxnT>(
1852 txn: &mut T,
1853 graph: &mut T::Graph,
1854 mut flag: EdgeFlags,
1855 mut k0: Vertex<ChangeId>,
1856 mut k1: Vertex<ChangeId>,
1857 introduced_by: ChangeId,
1858 ) -> Result<bool, TxnErr<T::GraphError>> {
1859 if flag.contains(EdgeFlags::PARENT) {
1860 std::mem::swap(&mut k0, &mut k1);
1861 flag -= EdgeFlags::PARENT
1862 }
1863 debug!("del_graph_with_rev {:?} {:?} {:?}", flag, k0, k1);
1864 let v0 = SerializedEdge::new(flag, k1.change, k1.start, introduced_by);
1865 let a = txn.del_graph(graph, &k0, Some(&v0))?;
1866 {
1867 if let Some(&ee) = txn.get_graph(graph, &k0, Some(&v0))? {
1868 if ee == v0 {
1869 txn.debug(graph, ".3");
1870 panic!("Not deleted: {:?} {:?}", k0, v0);
1871 }
1872 }
1873 }
1874 let v1 = SerializedEdge::new(flag | EdgeFlags::PARENT, k0.change, k0.end, introduced_by);
1875 let b = txn.del_graph(graph, &k1, Some(&v1))?;
1876 {
1877 if let Some(&ee) = txn.get_graph(graph, &k1, Some(&v1))? {
1878 if ee == v1 {
1879 txn.debug(graph, ".3");
1880 panic!("Not deleted: {:?} {:?}", k1, v1);
1881 }
1882 }
1883 }
1884 if a != b {
1885 txn.debug(graph, ".2");
1886 panic!(
1887 "Failed: {:?} {:?} for {:?} {:?} {:?} {:?}",
1888 a, b, flag, k0, k1, introduced_by
1889 )
1890 }
1891 Ok(a && b)
1892 }
1893
put_graph_with_rev<T: GraphMutTxnT>( txn: &mut T, graph: &mut T::Graph, flag: EdgeFlags, k0: Vertex<ChangeId>, k1: Vertex<ChangeId>, introduced_by: ChangeId, ) -> Result<bool, TxnErr<T::GraphError>>1894 pub(crate) fn put_graph_with_rev<T: GraphMutTxnT>(
1895 txn: &mut T,
1896 graph: &mut T::Graph,
1897 flag: EdgeFlags,
1898 k0: Vertex<ChangeId>,
1899 k1: Vertex<ChangeId>,
1900 introduced_by: ChangeId,
1901 ) -> Result<bool, TxnErr<T::GraphError>> {
1902 debug_assert!(!flag.contains(EdgeFlags::PARENT));
1903 if k0.change == k1.change {
1904 assert_ne!(k0.start_pos(), k1.start_pos());
1905 }
1906 if introduced_by == ChangeId::ROOT {
1907 assert!(flag.contains(EdgeFlags::PSEUDO));
1908 }
1909
1910 let gaeul = ChangeId::from_base32(b"GAEULYDRSLJSC").unwrap();
1911 let has_gaeul1 = {
1912 let v = Vertex {
1913 change: gaeul,
1914 start: ChangePosition(L64(1677892)),
1915 end: ChangePosition(L64(1677893)),
1916 };
1917 let e = SerializedEdge::new(
1918 EdgeFlags::PSEUDO | EdgeFlags::PARENT,
1919 gaeul,
1920 ChangePosition(L64(1677837)),
1921 ChangeId::ROOT,
1922 );
1923 if let Some(&ee) = txn.get_graph(graph, &v, Some(&e))? {
1924 ee == e
1925 } else {
1926 false
1927 }
1928 };
1929
1930 debug!("put_graph_with_rev {:?} {:?} {:?}", k0, k1, flag);
1931 let a = txn.put_graph(
1932 graph,
1933 &k0,
1934 &SerializedEdge::new(flag, k1.change, k1.start, introduced_by),
1935 )?;
1936 let b = txn.put_graph(
1937 graph,
1938 &k1,
1939 &SerializedEdge::new(flag | EdgeFlags::PARENT, k0.change, k0.end, introduced_by),
1940 )?;
1941 assert!((a && b) || (!a && !b));
1942
1943 let has_gaeul1_ = {
1944 let v = Vertex {
1945 change: gaeul,
1946 start: ChangePosition(L64(1677892)),
1947 end: ChangePosition(L64(1677893)),
1948 };
1949 let e = SerializedEdge::new(
1950 EdgeFlags::PSEUDO | EdgeFlags::PARENT,
1951 gaeul,
1952 ChangePosition(L64(1677837)),
1953 ChangeId::ROOT,
1954 );
1955 if let Some(&ee) = txn.get_graph(graph, &v, Some(&e))? {
1956 ee == e
1957 } else {
1958 false
1959 }
1960 };
1961
1962 if has_gaeul1 && !has_gaeul1_ {
1963 txn.debug(graph, ".GAEUL");
1964 panic!("GAEULT");
1965 }
1966
1967 Ok(a && b)
1968 }
1969
register_change< T: GraphMutTxnT + DepsMutTxnT<DepsError = <T as GraphTxnT>::GraphError>, >( txn: &mut T, internal: &ChangeId, hash: &Hash, change: &Change, ) -> Result<(), TxnErr<T::GraphError>>1970 pub(crate) fn register_change<
1971 T: GraphMutTxnT + DepsMutTxnT<DepsError = <T as GraphTxnT>::GraphError>,
1972 >(
1973 txn: &mut T,
1974 internal: &ChangeId,
1975 hash: &Hash,
1976 change: &Change,
1977 ) -> Result<(), TxnErr<T::GraphError>> {
1978 debug!("registering change {:?}", hash);
1979 let shash = hash.into();
1980 txn.put_external(internal, &shash)?;
1981 txn.put_internal(&shash, internal)?;
1982 for dep in change.dependencies.iter() {
1983 debug!("dep = {:?}", dep);
1984 let dep_internal = *txn.get_internal(&dep.into())?.unwrap();
1985 debug!("{:?} depends on {:?}", internal, dep_internal);
1986 txn.put_revdep(&dep_internal, internal)?;
1987 txn.put_dep(internal, &dep_internal)?;
1988 }
1989 for hunk in change.changes.iter().flat_map(|r| r.iter()) {
1990 let (inode, pos) = match *hunk {
1991 Atom::NewVertex(NewVertex {
1992 ref inode,
1993 ref flag,
1994 ref start,
1995 ref end,
1996 ..
1997 }) => {
1998 if flag.contains(EdgeFlags::FOLDER) && start == end {
1999 (inode, Some(*start))
2000 } else {
2001 (inode, None)
2002 }
2003 }
2004 Atom::EdgeMap(EdgeMap { ref inode, .. }) => (inode, None),
2005 };
2006 let change = if let Some(c) = inode.change {
2007 txn.get_internal(&c.into())?.unwrap_or(internal)
2008 } else {
2009 internal
2010 };
2011 let inode = Position {
2012 change: *change,
2013 pos: inode.pos,
2014 };
2015 debug!("touched: {:?} {:?}", inode, internal);
2016 txn.put_touched_files(&inode, internal)?;
2017 txn.put_rev_touched_files(internal, &inode)?;
2018 if let Some(pos) = pos {
2019 let inode = Position {
2020 change: *internal,
2021 pos,
2022 };
2023 txn.put_touched_files(&inode, internal)?;
2024 txn.put_rev_touched_files(internal, &inode)?;
2025 }
2026 }
2027 Ok(())
2028 }
2029
first_state_after<T: ChannelTxnT>( txn: &T, c: &T::Channel, pos: u64, ) -> Result<Option<(u64, SerializedMerkle)>, TxnErr<T::GraphError>>2030 fn first_state_after<T: ChannelTxnT>(
2031 txn: &T,
2032 c: &T::Channel,
2033 pos: u64,
2034 ) -> Result<Option<(u64, SerializedMerkle)>, TxnErr<T::GraphError>> {
2035 for x in T::cursor_revchangeset_ref(txn, txn.rev_changes(&c), Some(pos.into()))? {
2036 let (&n, m) = x?;
2037 let n: u64 = n.into();
2038 if n >= pos {
2039 return Ok(Some((n, m.b.clone())));
2040 }
2041 }
2042 Ok(None)
2043 }
2044
last_state<T: ChannelTxnT>( txn: &T, c: &T::Channel, ) -> Result<Option<(u64, SerializedMerkle)>, TxnErr<T::GraphError>>2045 fn last_state<T: ChannelTxnT>(
2046 txn: &T,
2047 c: &T::Channel,
2048 ) -> Result<Option<(u64, SerializedMerkle)>, TxnErr<T::GraphError>> {
2049 if let Some(e) = txn
2050 .rev_cursor_revchangeset(txn.rev_changes(&c), None)?
2051 .next()
2052 {
2053 let (&b, state) = e?;
2054 let b: u64 = b.into();
2055 Ok(Some((b, state.b.clone())))
2056 } else {
2057 Ok(None)
2058 }
2059 }
2060
2061 /// Find the last state of c1 that is also in c0.
last_common_state<T: ChannelTxnT>( txn: &T, c0: &T::Channel, c1: &T::Channel, ) -> Result<(u64, u64, SerializedMerkle), TxnErr<T::GraphError>>2062 pub fn last_common_state<T: ChannelTxnT>(
2063 txn: &T,
2064 c0: &T::Channel,
2065 c1: &T::Channel,
2066 ) -> Result<(u64, u64, SerializedMerkle), TxnErr<T::GraphError>> {
2067 let mut a = 0;
2068 let (mut b, mut state) = if let Some(x) = last_state(txn, c1)? {
2069 x
2070 } else {
2071 return Ok((0, 0, Merkle::zero().into()));
2072 };
2073 if let Some(aa) = txn.channel_has_state(txn.states(c0), &state)? {
2074 return Ok((aa.into(), b, state));
2075 }
2076 let mut aa = 0;
2077 let mut a_was_found = false;
2078 while a < b {
2079 let mid = (a + b) / 2;
2080 let (_, s) = first_state_after(txn, c1, mid)?.unwrap();
2081 state = s;
2082 if let Some(aa_) = txn.channel_has_state(txn.states(c0), &state)? {
2083 aa = aa_.into();
2084 a_was_found = true;
2085 a = mid
2086 } else {
2087 b = mid
2088 }
2089 }
2090 if a_was_found {
2091 Ok((aa, a, state))
2092 } else {
2093 Ok((0, 0, Merkle::zero().into()))
2094 }
2095 }
2096
2097 /// Check that each inode in the inodes table maps to an alive vertex,
2098 /// and that each inode in the tree table is reachable by only one
2099 /// path.
check_tree_inodes<T: GraphTxnT + TreeTxnT>(txn: &T, channel: &T::Graph)2100 pub fn check_tree_inodes<T: GraphTxnT + TreeTxnT>(txn: &T, channel: &T::Graph) {
2101 // Sanity check
2102 for x in txn.iter_inodes().unwrap() {
2103 let (inode, vertex) = x.unwrap();
2104 let mut inode_ = *inode;
2105 while !inode_.is_root() {
2106 if let Some(next) = txn.get_revtree(&inode_, None).unwrap() {
2107 inode_ = next.parent_inode;
2108 } else {
2109 panic!("inode = {:?}, inode_ = {:?}", inode, inode_);
2110 }
2111 }
2112 if !is_alive(txn, &channel, &vertex.inode_vertex()).unwrap() {
2113 for e in iter_adj_all(txn, channel, vertex.inode_vertex()).unwrap() {
2114 error!("{:?} {:?} {:?}", inode, vertex, e.unwrap())
2115 }
2116 panic!(
2117 "inode {:?}, vertex {:?}, is not alive, {:?}",
2118 inode,
2119 vertex,
2120 tree_path(txn, vertex)
2121 )
2122 }
2123 }
2124 let mut h = HashMap::default();
2125 let id0 = OwnedPathId {
2126 parent_inode: Inode::ROOT,
2127 basename: crate::small_string::SmallString::new(),
2128 };
2129 for x in txn.iter_tree(&id0, None).unwrap() {
2130 let (id, inode) = x.unwrap();
2131 if let Some(inode_) = h.insert(id.to_owned(), inode) {
2132 panic!("id {:?} maps to two inodes: {:?} {:?}", id, inode, inode_);
2133 }
2134 }
2135 }
2136
2137 /// Check that each alive vertex in the graph is reachable, and vice-versa.
check_alive_debug<T: GraphIter + ChannelTxnT, C: crate::changestore::ChangeStore>( changes: &C, txn: &T, channel: &T::Channel, line: u32, ) -> Result<(), std::io::Error>2138 pub fn check_alive_debug<T: GraphIter + ChannelTxnT, C: crate::changestore::ChangeStore>(
2139 changes: &C,
2140 txn: &T,
2141 channel: &T::Channel,
2142 line: u32,
2143 ) -> Result<(), std::io::Error> {
2144 let (alive, reachable) = crate::pristine::check_alive(txn, txn.graph(channel));
2145 let mut h = HashSet::default();
2146 if !alive.is_empty() {
2147 for (k, file) in alive.iter() {
2148 debug!("alive = {:?}, file = {:?}", k, file);
2149 h.insert(file);
2150 }
2151 }
2152 if !reachable.is_empty() {
2153 for (k, file) in reachable.iter() {
2154 debug!("reachable = {:?}, file = {:?}", k, file);
2155 h.insert(file);
2156 }
2157 }
2158 for file in h.iter() {
2159 let file_ = file.unwrap().start_pos();
2160
2161 let (path, _) = crate::fs::find_path(changes, txn, channel, true, file_)
2162 .unwrap()
2163 .unwrap();
2164 let path = path.replace("/", "_");
2165 let name = format!(
2166 "debug_{:?}_{}_{}",
2167 path,
2168 file_.change.to_base32(),
2169 file_.pos.0
2170 );
2171 let mut f = std::fs::File::create(&name)?;
2172 let graph = crate::alive::retrieve::retrieve(txn, txn.graph(channel), file_).unwrap();
2173 graph.debug(changes, txn, txn.graph(channel), false, false, &mut f)?;
2174
2175 let mut f = std::fs::File::create(&format!("{}_all", name))?;
2176 debug_root(txn, txn.graph(channel), file.unwrap(), &mut f, false)?;
2177 }
2178 if !h.is_empty() {
2179 if !alive.is_empty() {
2180 panic!("alive call line {}: {:?}", line, alive);
2181 } else {
2182 panic!("reachable: {:?}", reachable);
2183 }
2184 }
2185 Ok(())
2186 }
2187