tuwunel_database/map/open.rs
1use std::sync::Arc;
2
3use rocksdb::ColumnFamily;
4
5use crate::Engine;
6
7/// Acquires a stable column-family handle for a map.
8///
9/// The returned handle erases the engine-borrow lifetime carried by RocksDB.
10/// Its caller must retain the engine until after the handle is dropped, which
11/// `Map` guarantees by field ownership.
12///
13/// # Panics
14///
15/// Panics if the column family was not described before the engine opened.
16pub(super) fn open(engine: &Arc<Engine>, name: &str) -> Arc<ColumnFamily> {
17 let bounded_arc = engine.cf(name);
18 let bounded_ptr = Arc::into_raw(bounded_arc);
19 let cf_ptr = bounded_ptr.cast::<ColumnFamily>();
20
21 // SAFETY: Column family handles out of RocksDB are basic pointers and can
22 // be invalidated: 1. when the database closes. 2. when the column is dropped or
23 // closed. rust_rocksdb wraps this for us by storing handles in their own
24 // `RwLock<BTreeMap>` map and returning an Arc<BoundColumnFamily<'_>>` to
25 // provide expected safety. Similarly in "single-threaded mode" we would
26 // receive `&'_ ColumnFamily`.
27 //
28 // PROBLEM: We need to hold these handles in a field, otherwise we have to take
29 // a lock and get them by name from this map for every query, which is what
30 // conduit was doing, but we're not going to make a query for every query so we
31 // need to be holding it right. The lifetime parameter on these references makes
32 // that complicated. If this can be done without polluting the userspace
33 // with lifetimes on every instance of `Map` then this `unsafe` might not be
34 // necessary.
35 //
36 // SOLUTION: After investigating the underlying types it appears valid to
37 // Arc-swap `BoundColumnFamily<'_>` for `ColumnFamily`. They have the
38 // same inner data, the same Drop behavior, Deref, etc. We're just losing the
39 // lifetime parameter. We should not hold this handle, even in its Arc, after
40 // closing the database (dropping `Engine`). Since `Arc<Engine>` is a sibling
41 // member along with this handle in `Map`, that is prevented.
42 unsafe { Arc::from_raw(cf_ptr) }
43}