|
4 | 4 | //! `next` pointer (page id, 0 = end of chain) followed by raw data bytes. |
5 | 5 | //! |
6 | 6 | //! - Root page (`PageKind::OverflowRoot`): `refcount[4] || next[8] || data_len[4] || data`. |
7 | | -//! The `refcount: u32` enables shared chains — `increment_ref` CoW-copies the |
8 | | -//! root with `refcount + 1`; `release` CoW-copies it with `refcount - 1` and, |
9 | | -//! when it reaches 0, frees the entire chain. |
| 7 | +//! `release` CoW-copies the root with `refcount - 1` and, when it reaches 0, |
| 8 | +//! frees the entire chain. Snapshot lifetime does not rely on the count: |
| 9 | +//! copy-on-write leaves that still name a chain are protected because commit |
| 10 | +//! tags every freed page and reclamation waits until no retained root or live |
| 11 | +//! reader can reach it. Nothing in this crate raises a count above 1, so the |
| 12 | +//! decrement branch only fires for a root written by some other producer. |
10 | 13 | //! - Chain page (`PageKind::Overflow`): `next[8] || data_len[4] || data`. |
11 | 14 | //! |
12 | 15 | //! The two layouts differ only in the root's 4-byte `refcount` prefix, so the |
@@ -218,37 +221,11 @@ pub async fn write_chain<V: Vfs>( |
218 | 221 | Ok(page_ids[0]) |
219 | 222 | } |
220 | 223 |
|
221 | | -/// Increment the reference count of an overflow root page. Writes a new `CoW` |
222 | | -/// copy of the root at `new_page_id` with `refcount + 1`. The caller is |
223 | | -/// responsible for allocating `new_page_id` and freeing the old root page when |
224 | | -/// appropriate. |
225 | | -/// |
226 | | -/// Returns the new root page id (`new_page_id`). |
227 | | -pub async fn increment_ref<V: Vfs>( |
228 | | - pager: &Pager<V>, |
229 | | - realm_id: RealmId, |
230 | | - root_page_id: u64, |
231 | | - new_page_id: u64, |
232 | | -) -> Result<u64> { |
233 | | - let page_size = pager.page_size(); |
234 | | - let info = read_root_page(pager, realm_id, root_page_id).await?; |
235 | | - let new_refcount = info |
236 | | - .refcount |
237 | | - .checked_add(1) |
238 | | - .ok_or_else(|| PagedbError::Io(std::io::Error::other("overflow refcount overflow")))?; |
239 | | - let mut body = vec![0u8; page_size - ENVELOPE_OVERHEAD]; |
240 | | - encode_overflow_root(&mut body, new_refcount, info.next, &info.root_data)?; |
241 | | - pager |
242 | | - .write_main_page(new_page_id, realm_id, PageKind::OverflowRoot, &body) |
243 | | - .await?; |
244 | | - Ok(new_page_id) |
245 | | -} |
246 | | - |
247 | 224 | /// The result of a `release` call. |
248 | 225 | pub enum ReleaseResult { |
249 | | - /// Refcount decremented; new root page written at `new_root_page_id`. |
250 | | - /// The caller must free `old_root_page_id`. |
251 | | - Decremented { new_root_page_id: u64 }, |
| 226 | + /// Refcount decremented; the decremented root was written to the caller's |
| 227 | + /// `new_page_id`. The caller must free the old root page. |
| 228 | + Decremented, |
252 | 229 | /// Refcount reached 0; all chain pages are listed in `freed_pages` |
253 | 230 | /// (including the original root). The caller must free them all. |
254 | 231 | Freed { freed_pages: Vec<u64> }, |
@@ -297,9 +274,7 @@ pub async fn release<V: Vfs>( |
297 | 274 | pager |
298 | 275 | .write_main_page(new_page_id, realm_id, PageKind::OverflowRoot, &body) |
299 | 276 | .await?; |
300 | | - Ok(ReleaseResult::Decremented { |
301 | | - new_root_page_id: new_page_id, |
302 | | - }) |
| 277 | + Ok(ReleaseResult::Decremented) |
303 | 278 | } |
304 | 279 |
|
305 | 280 | /// Read a value's overflow chain via the Pager. Follows `next` pointers until 0. |
|
0 commit comments