Skip to content

Commit f76bfc6

Browse files
authored
Merge pull request #300 from meilisearch/parametric-send-rotxn
Parametric TLS for read transactions
2 parents b7cb164 + 66af90d commit f76bfc6

File tree

14 files changed

+438
-274
lines changed

14 files changed

+438
-274
lines changed

heed/Cargo.toml

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,6 @@ url = "2.5.4"
4444
default = ["serde", "serde-bincode", "serde-json"]
4545
serde = ["bitflags/serde", "dep:serde"]
4646

47-
# The #MDB_NOTLS flag is automatically set on Env opening,
48-
# RoTxn and RoCursors implements the Send trait. This allows the
49-
# user to move RoTxns and RoCursors between threads as read transactions
50-
# will no more use thread local storage and will tie reader locktable
51-
# slots to #MDB_txn objects instead of to threads.
52-
#
53-
# According to the LMDB documentation, when this feature is not enabled:
54-
# A thread can only use one transaction at a time, plus any child
55-
# transactions. Each transaction belongs to one thread. [...]
56-
# The #MDB_NOTLS flag changes this for read-only transactions.
57-
#
58-
# And a #MDB_BAD_RSLOT error will be thrown when multiple read
59-
# transactions exists on the same thread
60-
read-txn-no-tls = []
61-
6247
# Enable the serde en/decoders for bincode, serde_json, or rmp_serde
6348
serde-bincode = ["heed-types/serde-bincode"]
6449
serde-json = ["heed-types/serde-json"]

heed/src/cookbook.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@
423423
//! }
424424
//!
425425
//! impl<'t> ImmutableMap<'t> {
426-
//! fn from_db(rtxn: &'t RoTxn, db: Database<Str, Str>) -> heed::Result<Self> {
426+
//! fn from_db<T>(rtxn: &'t RoTxn<T>, db: Database<Str, Str>) -> heed::Result<Self> {
427427
//! let mut map = HashMap::new();
428428
//! for result in db.iter(rtxn)? {
429429
//! let (k, v) = result?;

heed/src/cursor.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ use crate::mdb::error::mdb_result;
55
use crate::mdb::ffi;
66
use crate::*;
77

8-
pub struct RoCursor<'txn> {
8+
pub struct RoCursor<'txn, T> {
99
cursor: *mut ffi::MDB_cursor,
10-
_marker: marker::PhantomData<&'txn ()>,
10+
_marker: marker::PhantomData<&'txn T>,
1111
}
1212

13-
impl<'txn> RoCursor<'txn> {
14-
// TODO should I ask for a &mut RoTxn, here?
15-
pub(crate) fn new(txn: &'txn RoTxn, dbi: ffi::MDB_dbi) -> Result<RoCursor<'txn>> {
13+
impl<'txn, T> RoCursor<'txn, T> {
14+
// TODO should I ask for a &mut RoTxn<'_, T>, here?
15+
pub(crate) fn new(txn: &'txn RoTxn<'_, T>, dbi: ffi::MDB_dbi) -> Result<RoCursor<'txn, T>> {
1616
let mut cursor: *mut ffi::MDB_cursor = ptr::null_mut();
1717
let mut txn = txn.txn.unwrap();
1818
unsafe { mdb_result(ffi::mdb_cursor_open(txn.as_mut(), dbi, &mut cursor))? }
@@ -237,14 +237,14 @@ impl<'txn> RoCursor<'txn> {
237237
}
238238
}
239239

240-
impl Drop for RoCursor<'_> {
240+
impl<T> Drop for RoCursor<'_, T> {
241241
fn drop(&mut self) {
242242
unsafe { ffi::mdb_cursor_close(self.cursor) }
243243
}
244244
}
245245

246246
pub struct RwCursor<'txn> {
247-
cursor: RoCursor<'txn>,
247+
cursor: RoCursor<'txn, WithoutTls>,
248248
}
249249

250250
impl<'txn> RwCursor<'txn> {
@@ -404,7 +404,7 @@ impl<'txn> RwCursor<'txn> {
404404
}
405405

406406
impl<'txn> Deref for RwCursor<'txn> {
407-
type Target = RoCursor<'txn>;
407+
type Target = RoCursor<'txn, WithoutTls>;
408408

409409
fn deref(&self) -> &Self::Target {
410410
&self.cursor

heed/src/databases/database.rs

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,16 @@ use crate::*;
5555
/// # Ok(()) }
5656
/// ```
5757
#[derive(Debug)]
58-
pub struct DatabaseOpenOptions<'e, 'n, KC, DC, C = DefaultComparator> {
59-
env: &'e Env,
58+
pub struct DatabaseOpenOptions<'e, 'n, T, KC, DC, C = DefaultComparator> {
59+
env: &'e Env<T>,
6060
types: marker::PhantomData<(KC, DC, C)>,
6161
name: Option<&'n str>,
6262
flags: AllDatabaseFlags,
6363
}
6464

65-
impl<'e> DatabaseOpenOptions<'e, 'static, Unspecified, Unspecified> {
65+
impl<'e, T> DatabaseOpenOptions<'e, 'static, T, Unspecified, Unspecified> {
6666
/// Create an options struct to open/create a database with specific flags.
67-
pub fn new(env: &'e Env) -> Self {
67+
pub fn new(env: &'e Env<T>) -> Self {
6868
DatabaseOpenOptions {
6969
env,
7070
types: Default::default(),
@@ -74,23 +74,24 @@ impl<'e> DatabaseOpenOptions<'e, 'static, Unspecified, Unspecified> {
7474
}
7575
}
7676

77-
impl<'e, 'n, KC, DC, C> DatabaseOpenOptions<'e, 'n, KC, DC, C> {
77+
impl<'e, 'n, T, KC, DC, C> DatabaseOpenOptions<'e, 'n, T, KC, DC, C> {
7878
/// Change the type of the database.
7979
///
8080
/// The default types are [`Unspecified`] and require a call to [`Database::remap_types`]
8181
/// to use the [`Database`].
82-
pub fn types<NKC, NDC>(self) -> DatabaseOpenOptions<'e, 'n, NKC, NDC> {
82+
pub fn types<NKC, NDC>(self) -> DatabaseOpenOptions<'e, 'n, T, NKC, NDC> {
8383
DatabaseOpenOptions {
8484
env: self.env,
8585
types: Default::default(),
8686
name: self.name,
8787
flags: self.flags,
8888
}
8989
}
90+
9091
/// Change the customized key compare function of the database.
9192
///
9293
/// By default no customized compare function will be set when opening a database.
93-
pub fn key_comparator<NC>(self) -> DatabaseOpenOptions<'e, 'n, KC, DC, NC> {
94+
pub fn key_comparator<NC>(self) -> DatabaseOpenOptions<'e, 'n, T, KC, DC, NC> {
9495
DatabaseOpenOptions {
9596
env: self.env,
9697
types: Default::default(),
@@ -131,7 +132,7 @@ impl<'e, 'n, KC, DC, C> DatabaseOpenOptions<'e, 'n, KC, DC, C> {
131132
///
132133
/// If not done, you might raise `Io(Os { code: 22, kind: InvalidInput, message: "Invalid argument" })`
133134
/// known as `EINVAL`.
134-
pub fn open(&self, rtxn: &RoTxn) -> Result<Option<Database<KC, DC, C>>>
135+
pub fn open(&self, rtxn: &RoTxn<T>) -> Result<Option<Database<KC, DC, C>>>
135136
where
136137
KC: 'static,
137138
DC: 'static,
@@ -171,13 +172,13 @@ impl<'e, 'n, KC, DC, C> DatabaseOpenOptions<'e, 'n, KC, DC, C> {
171172
}
172173
}
173174

174-
impl<KC, DC, C> Clone for DatabaseOpenOptions<'_, '_, KC, DC, C> {
175+
impl<T, KC, DC, C> Clone for DatabaseOpenOptions<'_, '_, T, KC, DC, C> {
175176
fn clone(&self) -> Self {
176177
*self
177178
}
178179
}
179180

180-
impl<KC, DC, C> Copy for DatabaseOpenOptions<'_, '_, KC, DC, C> {}
181+
impl<T, KC, DC, C> Copy for DatabaseOpenOptions<'_, '_, T, KC, DC, C> {}
181182

182183
/// A typed database that accepts only the types it was created with.
183184
///
@@ -339,7 +340,11 @@ impl<KC, DC, C> Database<KC, DC, C> {
339340
/// wtxn.commit()?;
340341
/// # Ok(()) }
341342
/// ```
342-
pub fn get<'a, 'txn>(&self, txn: &'txn RoTxn, key: &'a KC::EItem) -> Result<Option<DC::DItem>>
343+
pub fn get<'a, 'txn, T>(
344+
&self,
345+
txn: &'txn RoTxn<T>,
346+
key: &'a KC::EItem,
347+
) -> Result<Option<DC::DItem>>
343348
where
344349
KC: BytesEncode<'a>,
345350
DC: BytesDecode<'txn>,
@@ -423,11 +428,11 @@ impl<KC, DC, C> Database<KC, DC, C> {
423428
/// wtxn.commit()?;
424429
/// # Ok(()) }
425430
/// ```
426-
pub fn get_duplicates<'a, 'txn>(
431+
pub fn get_duplicates<'a, 'txn, T>(
427432
&self,
428-
txn: &'txn RoTxn,
433+
txn: &'txn RoTxn<T>,
429434
key: &'a KC::EItem,
430-
) -> Result<Option<RoIter<'txn, KC, DC, MoveOnCurrentKeyDuplicates>>>
435+
) -> Result<Option<RoIter<'txn, T, KC, DC, MoveOnCurrentKeyDuplicates>>>
431436
where
432437
KC: BytesEncode<'a>,
433438
{
@@ -486,9 +491,9 @@ impl<KC, DC, C> Database<KC, DC, C> {
486491
/// wtxn.commit()?;
487492
/// # Ok(()) }
488493
/// ```
489-
pub fn get_lower_than<'a, 'txn>(
494+
pub fn get_lower_than<'a, 'txn, T>(
490495
&self,
491-
txn: &'txn RoTxn,
496+
txn: &'txn RoTxn<T>,
492497
key: &'a KC::EItem,
493498
) -> Result<Option<(KC::DItem, DC::DItem)>>
494499
where
@@ -555,9 +560,9 @@ impl<KC, DC, C> Database<KC, DC, C> {
555560
/// wtxn.commit()?;
556561
/// # Ok(()) }
557562
/// ```
558-
pub fn get_lower_than_or_equal_to<'a, 'txn>(
563+
pub fn get_lower_than_or_equal_to<'a, 'txn, T>(
559564
&self,
560-
txn: &'txn RoTxn,
565+
txn: &'txn RoTxn<T>,
561566
key: &'a KC::EItem,
562567
) -> Result<Option<(KC::DItem, DC::DItem)>>
563568
where
@@ -628,9 +633,9 @@ impl<KC, DC, C> Database<KC, DC, C> {
628633
/// wtxn.commit()?;
629634
/// # Ok(()) }
630635
/// ```
631-
pub fn get_greater_than<'a, 'txn>(
636+
pub fn get_greater_than<'a, 'txn, T>(
632637
&self,
633-
txn: &'txn RoTxn,
638+
txn: &'txn RoTxn<T>,
634639
key: &'a KC::EItem,
635640
) -> Result<Option<(KC::DItem, DC::DItem)>>
636641
where
@@ -700,9 +705,9 @@ impl<KC, DC, C> Database<KC, DC, C> {
700705
/// wtxn.commit()?;
701706
/// # Ok(()) }
702707
/// ```
703-
pub fn get_greater_than_or_equal_to<'a, 'txn>(
708+
pub fn get_greater_than_or_equal_to<'a, 'txn, T>(
704709
&self,
705-
txn: &'txn RoTxn,
710+
txn: &'txn RoTxn<T>,
706711
key: &'a KC::EItem,
707712
) -> Result<Option<(KC::DItem, DC::DItem)>>
708713
where
@@ -759,7 +764,7 @@ impl<KC, DC, C> Database<KC, DC, C> {
759764
/// wtxn.commit()?;
760765
/// # Ok(()) }
761766
/// ```
762-
pub fn first<'txn>(&self, txn: &'txn RoTxn) -> Result<Option<(KC::DItem, DC::DItem)>>
767+
pub fn first<'txn, T>(&self, txn: &'txn RoTxn<T>) -> Result<Option<(KC::DItem, DC::DItem)>>
763768
where
764769
KC: BytesDecode<'txn>,
765770
DC: BytesDecode<'txn>,
@@ -813,7 +818,7 @@ impl<KC, DC, C> Database<KC, DC, C> {
813818
/// wtxn.commit()?;
814819
/// # Ok(()) }
815820
/// ```
816-
pub fn last<'txn>(&self, txn: &'txn RoTxn) -> Result<Option<(KC::DItem, DC::DItem)>>
821+
pub fn last<'txn, T>(&self, txn: &'txn RoTxn<T>) -> Result<Option<(KC::DItem, DC::DItem)>>
817822
where
818823
KC: BytesDecode<'txn>,
819824
DC: BytesDecode<'txn>,
@@ -870,7 +875,7 @@ impl<KC, DC, C> Database<KC, DC, C> {
870875
/// wtxn.commit()?;
871876
/// # Ok(()) }
872877
/// ```
873-
pub fn len(&self, txn: &RoTxn) -> Result<u64> {
878+
pub fn len<T>(&self, txn: &RoTxn<T>) -> Result<u64> {
874879
self.stat(txn).map(|stat| stat.entries as u64)
875880
}
876881

@@ -913,7 +918,7 @@ impl<KC, DC, C> Database<KC, DC, C> {
913918
/// wtxn.commit()?;
914919
/// # Ok(()) }
915920
/// ```
916-
pub fn is_empty(&self, txn: &RoTxn) -> Result<bool> {
921+
pub fn is_empty<T>(&self, txn: &RoTxn<T>) -> Result<bool> {
917922
self.len(txn).map(|l| l == 0)
918923
}
919924

@@ -955,7 +960,7 @@ impl<KC, DC, C> Database<KC, DC, C> {
955960
/// wtxn.commit()?;
956961
/// # Ok(()) }
957962
/// ```
958-
pub fn stat(&self, txn: &RoTxn) -> Result<DatabaseStat> {
963+
pub fn stat<T>(&self, txn: &RoTxn<T>) -> Result<DatabaseStat> {
959964
assert_eq_env_db_txn!(self, txn);
960965

961966
let mut db_stat = mem::MaybeUninit::uninit();
@@ -1019,7 +1024,7 @@ impl<KC, DC, C> Database<KC, DC, C> {
10191024
/// wtxn.commit()?;
10201025
/// # Ok(()) }
10211026
/// ```
1022-
pub fn iter<'txn>(&self, txn: &'txn RoTxn) -> Result<RoIter<'txn, KC, DC>> {
1027+
pub fn iter<'txn, T>(&self, txn: &'txn RoTxn<T>) -> Result<RoIter<'txn, T, KC, DC>> {
10231028
assert_eq_env_db_txn!(self, txn);
10241029
RoCursor::new(txn, self.dbi).map(|cursor| RoIter::new(cursor))
10251030
}
@@ -1120,7 +1125,7 @@ impl<KC, DC, C> Database<KC, DC, C> {
11201125
/// wtxn.commit()?;
11211126
/// # Ok(()) }
11221127
/// ```
1123-
pub fn rev_iter<'txn>(&self, txn: &'txn RoTxn) -> Result<RoRevIter<'txn, KC, DC>> {
1128+
pub fn rev_iter<'txn, T>(&self, txn: &'txn RoTxn<T>) -> Result<RoRevIter<'txn, T, KC, DC>> {
11241129
assert_eq_env_db_txn!(self, txn);
11251130

11261131
RoCursor::new(txn, self.dbi).map(|cursor| RoRevIter::new(cursor))
@@ -1226,11 +1231,11 @@ impl<KC, DC, C> Database<KC, DC, C> {
12261231
/// wtxn.commit()?;
12271232
/// # Ok(()) }
12281233
/// ```
1229-
pub fn range<'a, 'txn, R>(
1234+
pub fn range<'a, 'txn, R, T>(
12301235
&self,
1231-
txn: &'txn RoTxn,
1236+
txn: &'txn RoTxn<T>,
12321237
range: &'a R,
1233-
) -> Result<RoRange<'txn, KC, DC, C>>
1238+
) -> Result<RoRange<'txn, T, KC, DC, C>>
12341239
where
12351240
KC: BytesEncode<'a>,
12361241
R: RangeBounds<KC::EItem>,
@@ -1398,11 +1403,11 @@ impl<KC, DC, C> Database<KC, DC, C> {
13981403
/// wtxn.commit()?;
13991404
/// # Ok(()) }
14001405
/// ```
1401-
pub fn rev_range<'a, 'txn, R>(
1406+
pub fn rev_range<'a, 'txn, R, T>(
14021407
&self,
1403-
txn: &'txn RoTxn,
1408+
txn: &'txn RoTxn<T>,
14041409
range: &'a R,
1405-
) -> Result<RoRevRange<'txn, KC, DC, C>>
1410+
) -> Result<RoRevRange<'txn, T, KC, DC, C>>
14061411
where
14071412
KC: BytesEncode<'a>,
14081413
R: RangeBounds<KC::EItem>,
@@ -1572,11 +1577,11 @@ impl<KC, DC, C> Database<KC, DC, C> {
15721577
/// wtxn.commit()?;
15731578
/// # Ok(()) }
15741579
/// ```
1575-
pub fn prefix_iter<'a, 'txn>(
1580+
pub fn prefix_iter<'a, 'txn, T>(
15761581
&self,
1577-
txn: &'txn RoTxn,
1582+
txn: &'txn RoTxn<T>,
15781583
prefix: &'a KC::EItem,
1579-
) -> Result<RoPrefix<'txn, KC, DC, C>>
1584+
) -> Result<RoPrefix<'txn, T, KC, DC, C>>
15801585
where
15811586
KC: BytesEncode<'a>,
15821587
C: LexicographicComparator,
@@ -1704,11 +1709,11 @@ impl<KC, DC, C> Database<KC, DC, C> {
17041709
/// wtxn.commit()?;
17051710
/// # Ok(()) }
17061711
/// ```
1707-
pub fn rev_prefix_iter<'a, 'txn>(
1712+
pub fn rev_prefix_iter<'a, 'txn, T>(
17081713
&self,
1709-
txn: &'txn RoTxn,
1714+
txn: &'txn RoTxn<'_, T>,
17101715
prefix: &'a KC::EItem,
1711-
) -> Result<RoRevPrefix<'txn, KC, DC, C>>
1716+
) -> Result<RoRevPrefix<'txn, T, KC, DC, C>>
17121717
where
17131718
KC: BytesEncode<'a>,
17141719
C: LexicographicComparator,

0 commit comments

Comments
 (0)