1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! Embedded, single-file, wide-column store: BigTable's data model with SQLite's deployment
//! model.
//!
//! A Pigeonhole database is a sorted, sparse, versioned map
//! `(table, row, family, qualifier, timestamp) → value` in one file.
//!
//! ```
//! use pigeonhole::{days, Durability, Family, Options, Pigeonhole};
//!
//! # fn main() -> pigeonhole::Result<()> {
//! # let dir = pigeonhole::doc_support::temp_dir();
//! let db = Pigeonhole::open(dir.join("crawl.phdb"), Options::default())?;
//! let pages = db
//! .table("pages")?
//! .family("meta", Family::default().max_versions(1))
//! .family("links", Family::default().bloom_bits(10))
//! .family("body", Family::default().blob_threshold(4096).ttl(days(30)))
//! .family("stats", Family::counter())
//! .create_if_missing()?;
//!
//! // Single-row atomic mutation.
//! pages
//! .mutate(b"com.example/a")
//! .put("meta", b"status", b"200")
//! .put("links", b"com.example/b", b"")
//! .incr("stats", b"hits", 1)
//! .delete_column("meta", b"etag")
//! .commit()?;
//!
//! // Point read: borrows from the cache, no allocation.
//! let status = pages.get(b"com.example/a", "meta", b"status")?;
//! assert_eq!(status.unwrap().value(), b"200");
//!
//! // Row read, projected to families.
//! let row = pages.row(b"com.example/a").families(["meta", "stats"]).latest().read()?;
//! assert_eq!(row.unwrap().get("stats", b"hits").unwrap().as_i64(), Some(1));
//!
//! // Ordered scan with filters pushed into the block decoder.
//! let snap = db.snapshot()?;
//! for row in pages
//! .scan(b"com.example/"..b"com.example0")
//! .family("links")
//! .qualifier_prefix(b"org.")
//! .snapshot(&snap)
//! .iter()?
//! {
//! let row = row?;
//! assert!(row.is_empty() || row.key().starts_with(b"com.example/"));
//! }
//!
//! // Batched multi-row write with one durability point.
//! let mut wb = db.write_batch();
//! wb.put(&pages, b"com.example/c", "meta", b"status", b"404");
//! wb.commit_with(Durability::GroupSync)?;
//! db.close()?;
//! # Ok(())
//! # }
//! ```
//!
//! # Install and status
//!
//! `cargo add pigeonhole`, or `pigeonhole = "0.1"` in `Cargo.toml`. This is an experimental
//! 0.x release: the core engine (Phase 1) is complete and fault-tested in simulation, but the
//! on-disk format and the API may change before 1.0, the wide-column model (Phase 2) and the
//! latency work (Phase 3) are still to come, and it is not recommended for production use yet.
//! See the [status page](https://github.com/CodingAnarchy/pigeonhole/blob/main/docs/status.md)
//! and the [changelog](https://github.com/CodingAnarchy/pigeonhole/blob/main/CHANGELOG.md).
//!
//! # API shape and the future C ABI
//!
//! Every zero-copy type ([`CellRef`], [`RowRef`]) has an owned, cheap, ref-counted
//! equivalent ([`Cell`], [`Row`]), and every iterator has a cursor-style method
//! ([`RowIter::next_ref`]), so a C ABI can wrap this crate later without exposing lifetimes,
//! generics or closures. Errors are a flat, stable [`ErrorCode`] plus a message.
//!
//! # Sync and async
//!
//! Phase 1 ships the blocking API, which needs no async runtime. The async front door
//! (Phase 3) lives behind the `async` feature in the `nonblocking` module.
//!
//! Part of [Pigeonhole](https://github.com/CodingAnarchy/pigeonhole). See the crate README.
/// The user guide's and the READMEs' code samples, compiled and run as doctests.
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ShardStats;
pub use ;
pub use Durability;