@@ -5,8 +5,8 @@ use parking_lot::Mutex;
5
5
6
6
use re_chunk:: { Chunk , ChunkResult , RowId , TimeInt } ;
7
7
use re_chunk_store:: {
8
- ChunkStore , ChunkStoreChunkStats , ChunkStoreConfig , ChunkStoreEvent , ChunkStoreSubscriber ,
9
- GarbageCollectionOptions , GarbageCollectionTarget ,
8
+ ChunkStore , ChunkStoreChunkStats , ChunkStoreConfig , ChunkStoreEvent , ChunkStoreHandle ,
9
+ ChunkStoreSubscriber , GarbageCollectionOptions , GarbageCollectionTarget ,
10
10
} ;
11
11
use re_log_types:: {
12
12
ApplicationId , EntityPath , EntityPathHash , LogMsg , ResolvedTimeRange , ResolvedTimeRangeF ,
@@ -62,7 +62,7 @@ pub struct EntityDb {
62
62
tree : crate :: EntityTree ,
63
63
64
64
/// Stores all components for all entities for all timelines.
65
- data_store : ChunkStore ,
65
+ data_store : ChunkStoreHandle ,
66
66
67
67
/// Query caches for the data in [`Self::data_store`].
68
68
query_caches : re_query:: QueryCache ,
@@ -76,8 +76,8 @@ impl EntityDb {
76
76
}
77
77
78
78
pub fn with_store_config ( store_id : StoreId , store_config : ChunkStoreConfig ) -> Self {
79
- let data_store = ChunkStore :: new ( store_id. clone ( ) , store_config) ;
80
- let query_caches = re_query:: QueryCache :: new ( & data_store) ;
79
+ let data_store = ChunkStoreHandle :: new ( ChunkStore :: new ( store_id. clone ( ) , store_config) ) ;
80
+ let query_caches = re_query:: QueryCache :: new ( data_store. clone ( ) ) ;
81
81
82
82
Self {
83
83
data_source : None ,
@@ -99,11 +99,6 @@ impl EntityDb {
99
99
& self . tree
100
100
}
101
101
102
- #[ inline]
103
- pub fn data_store ( & self ) -> & ChunkStore {
104
- & self . data_store
105
- }
106
-
107
102
pub fn store_info_msg ( & self ) -> Option < & SetStoreInfo > {
108
103
self . set_store_info . as_ref ( )
109
104
}
@@ -123,7 +118,7 @@ impl EntityDb {
123
118
124
119
pub fn query_engine ( & self ) -> re_dataframe:: QueryEngine < ' _ > {
125
120
re_dataframe:: QueryEngine {
126
- store : self . store ( ) ,
121
+ store : self . store ( ) . clone ( ) ,
127
122
cache : self . query_caches ( ) ,
128
123
}
129
124
}
@@ -141,7 +136,7 @@ impl EntityDb {
141
136
component_names : impl IntoIterator < Item = re_types_core:: ComponentName > ,
142
137
) -> re_query:: LatestAtResults {
143
138
self . query_caches ( )
144
- . latest_at ( self . store ( ) , query, entity_path, component_names)
139
+ . latest_at ( query, entity_path, component_names)
145
140
}
146
141
147
142
/// Get the latest index and value for a given dense [`re_types_core::Component`].
@@ -160,7 +155,7 @@ impl EntityDb {
160
155
) -> Option < ( ( TimeInt , RowId ) , C ) > {
161
156
let results = self
162
157
. query_caches ( )
163
- . latest_at ( self . store ( ) , query, entity_path, [ C :: name ( ) ] ) ;
158
+ . latest_at ( query, entity_path, [ C :: name ( ) ] ) ;
164
159
results
165
160
. component_mono ( )
166
161
. map ( |value| ( results. index ( ) , value) )
@@ -182,7 +177,7 @@ impl EntityDb {
182
177
) -> Option < ( ( TimeInt , RowId ) , C ) > {
183
178
let results = self
184
179
. query_caches ( )
185
- . latest_at ( self . store ( ) , query, entity_path, [ C :: name ( ) ] ) ;
180
+ . latest_at ( query, entity_path, [ C :: name ( ) ] ) ;
186
181
results
187
182
. component_mono_quiet ( )
188
183
. map ( |value| ( results. index ( ) , value) )
@@ -208,7 +203,7 @@ impl EntityDb {
208
203
}
209
204
210
205
#[ inline]
211
- pub fn store ( & self ) -> & ChunkStore {
206
+ pub fn store ( & self ) -> & ChunkStoreHandle {
212
207
& self . data_store
213
208
}
214
209
@@ -218,8 +213,8 @@ impl EntityDb {
218
213
}
219
214
220
215
#[ inline]
221
- pub fn store_id ( & self ) -> & StoreId {
222
- self . data_store . id ( )
216
+ pub fn store_id ( & self ) -> StoreId {
217
+ self . data_store . read ( ) . id ( )
223
218
}
224
219
225
220
/// If this entity db is the result of a clone, which store was it cloned from?
@@ -264,14 +259,14 @@ impl EntityDb {
264
259
265
260
#[ inline]
266
261
pub fn num_rows ( & self ) -> u64 {
267
- self . data_store . stats ( ) . total ( ) . num_rows
262
+ self . data_store . read ( ) . stats ( ) . total ( ) . num_rows
268
263
}
269
264
270
265
/// Return the current `ChunkStoreGeneration`. This can be used to determine whether the
271
266
/// database has been modified since the last time it was queried.
272
267
#[ inline]
273
268
pub fn generation ( & self ) -> re_chunk_store:: ChunkStoreGeneration {
274
- self . data_store . generation ( )
269
+ self . data_store . read ( ) . generation ( )
275
270
}
276
271
277
272
#[ inline]
@@ -324,7 +319,7 @@ impl EntityDb {
324
319
pub fn add ( & mut self , msg : & LogMsg ) -> Result < Vec < ChunkStoreEvent > , Error > {
325
320
re_tracing:: profile_function!( ) ;
326
321
327
- debug_assert_eq ! ( msg. store_id( ) , self . store_id( ) ) ;
322
+ debug_assert_eq ! ( * msg. store_id( ) , self . store_id( ) ) ;
328
323
329
324
let store_events = match & msg {
330
325
LogMsg :: SetStoreInfo ( msg) => {
@@ -350,7 +345,10 @@ impl EntityDb {
350
345
}
351
346
352
347
pub fn add_chunk ( & mut self , chunk : & Arc < Chunk > ) -> Result < Vec < ChunkStoreEvent > , Error > {
353
- let store_events = self . data_store . insert_chunk ( chunk) ?;
348
+ // NOTE: using `write_arc` so the borrow checker can make sense of the partial borrow of `self`.
349
+ let mut store = self . data_store . write_arc ( ) ;
350
+
351
+ let store_events = store. insert_chunk ( chunk) ?;
354
352
355
353
self . register_entity_path ( chunk. entity_path ( ) ) ;
356
354
@@ -367,8 +365,7 @@ impl EntityDb {
367
365
368
366
// It is possible for writes to trigger deletions: specifically in the case of
369
367
// overwritten static data leading to dangling chunks.
370
- self . tree
371
- . on_store_deletions ( & self . data_store , & store_events) ;
368
+ self . tree . on_store_deletions ( & store, & store_events) ;
372
369
373
370
// We inform the stats last, since it measures e2e latency.
374
371
self . stats . on_events ( & store_events) ;
@@ -433,15 +430,18 @@ impl EntityDb {
433
430
fn gc ( & mut self , gc_options : & GarbageCollectionOptions ) -> Vec < ChunkStoreEvent > {
434
431
re_tracing:: profile_function!( ) ;
435
432
436
- let ( store_events, stats_diff) = self . data_store . gc ( gc_options) ;
433
+ // NOTE: using `write_arc` so the borrow checker can make sense of the partial borrow of `self`.
434
+ let mut store = self . data_store . write_arc ( ) ;
435
+
436
+ let ( store_events, stats_diff) = store. gc ( gc_options) ;
437
437
438
438
re_log:: trace!(
439
439
num_row_ids_dropped = store_events. len( ) ,
440
440
size_bytes_dropped = re_format:: format_bytes( stats_diff. total( ) . total_size_bytes as _) ,
441
441
"purged datastore"
442
442
) ;
443
443
444
- self . on_store_deletions ( & store_events) ;
444
+ self . on_store_deletions ( & store , & store_events) ;
445
445
446
446
store_events
447
447
}
@@ -454,8 +454,11 @@ impl EntityDb {
454
454
timeline : & Timeline ,
455
455
drop_range : ResolvedTimeRange ,
456
456
) -> Vec < ChunkStoreEvent > {
457
- let store_events = self . data_store . drop_time_range ( timeline, drop_range) ;
458
- self . on_store_deletions ( & store_events) ;
457
+ // NOTE: using `write_arc` so the borrow checker can make sense of the partial borrow of `self`.
458
+ let mut store = self . data_store . write_arc ( ) ;
459
+
460
+ let store_events = store. drop_time_range ( timeline, drop_range) ;
461
+ self . on_store_deletions ( & store, & store_events) ;
459
462
store_events
460
463
}
461
464
@@ -467,9 +470,12 @@ impl EntityDb {
467
470
pub fn drop_entity_path ( & mut self , entity_path : & EntityPath ) {
468
471
re_tracing:: profile_function!( ) ;
469
472
470
- let store_events = self . data_store . drop_entity_path ( entity_path) ;
473
+ // NOTE: using `write_arc` so the borrow checker can make sense of the partial borrow of `self`.
474
+ let mut store = self . data_store . write_arc ( ) ;
475
+
476
+ let store_events = store. drop_entity_path ( entity_path) ;
471
477
472
- self . on_store_deletions ( & store_events) ;
478
+ self . on_store_deletions ( & store , & store_events) ;
473
479
}
474
480
475
481
/// Unconditionally drops all the data for a given [`EntityPath`] and all its children.
@@ -489,13 +495,13 @@ impl EntityDb {
489
495
}
490
496
}
491
497
492
- fn on_store_deletions ( & mut self , store_events : & [ ChunkStoreEvent ] ) {
498
+ fn on_store_deletions ( & mut self , store : & ChunkStore , store_events : & [ ChunkStoreEvent ] ) {
493
499
re_tracing:: profile_function!( ) ;
494
500
495
501
self . times_per_timeline . on_events ( store_events) ;
496
502
self . query_caches . on_events ( store_events) ;
497
503
self . time_histogram_per_timeline . on_events ( store_events) ;
498
- self . tree . on_store_deletions ( & self . data_store , store_events) ;
504
+ self . tree . on_store_deletions ( store , store_events) ;
499
505
}
500
506
501
507
/// Key used for sorting recordings in the UI.
@@ -514,6 +520,8 @@ impl EntityDb {
514
520
) -> impl Iterator < Item = ChunkResult < LogMsg > > + ' _ {
515
521
re_tracing:: profile_function!( ) ;
516
522
523
+ let store = self . data_store . read ( ) ;
524
+
517
525
let set_store_info_msg = self
518
526
. store_info_msg ( )
519
527
. map ( |msg| Ok ( LogMsg :: SetStoreInfo ( msg. clone ( ) ) ) ) ;
@@ -526,8 +534,7 @@ impl EntityDb {
526
534
)
527
535
} ) ;
528
536
529
- let mut chunks: Vec < & Arc < Chunk > > = self
530
- . store ( )
537
+ let mut chunks: Vec < Arc < Chunk > > = store
531
538
. iter_chunks ( )
532
539
. filter ( move |chunk| {
533
540
let Some ( ( timeline, time_range) ) = time_filter else {
@@ -543,6 +550,7 @@ impl EntityDb {
543
550
|| time_range. contains ( time_column. time_range ( ) . max ( ) )
544
551
} )
545
552
} )
553
+ . cloned ( ) // refcount
546
554
. collect ( ) ;
547
555
548
556
// Try to roughly preserve the order of the chunks
@@ -606,7 +614,8 @@ impl EntityDb {
606
614
} ) ;
607
615
}
608
616
609
- for chunk in self . store ( ) . iter_chunks ( ) {
617
+ let store = self . data_store . read ( ) ;
618
+ for chunk in store. iter_chunks ( ) {
610
619
new_db. add_chunk ( & Arc :: clone ( chunk) ) ?;
611
620
}
612
621
@@ -627,8 +636,9 @@ impl EntityDb {
627
636
} ;
628
637
629
638
let mut stats = ChunkStoreChunkStats :: default ( ) ;
639
+ let store = self . data_store . read ( ) ;
630
640
subtree. visit_children_recursively ( |path| {
631
- stats += self . store ( ) . entity_stats_static ( path) ;
641
+ stats += store. entity_stats_static ( path) ;
632
642
} ) ;
633
643
634
644
stats
@@ -649,8 +659,9 @@ impl EntityDb {
649
659
} ;
650
660
651
661
let mut stats = ChunkStoreChunkStats :: default ( ) ;
662
+ let store = self . data_store . read ( ) ;
652
663
subtree. visit_children_recursively ( |path| {
653
- stats += self . store ( ) . entity_stats_on_timeline ( path, timeline) ;
664
+ stats += store. entity_stats_on_timeline ( path, timeline) ;
654
665
} ) ;
655
666
656
667
stats
@@ -670,10 +681,9 @@ impl EntityDb {
670
681
return false ;
671
682
} ;
672
683
684
+ let store = self . data_store . read ( ) ;
673
685
subtree
674
- . find_first_child_recursive ( |path| {
675
- self . store ( ) . entity_has_data_on_timeline ( timeline, path)
676
- } )
686
+ . find_first_child_recursive ( |path| store. entity_has_data_on_timeline ( timeline, path) )
677
687
. is_some ( )
678
688
}
679
689
@@ -691,10 +701,10 @@ impl EntityDb {
691
701
return false ;
692
702
} ;
693
703
704
+ let store = self . data_store . read ( ) ;
694
705
subtree
695
706
. find_first_child_recursive ( |path| {
696
- self . store ( )
697
- . entity_has_temporal_data_on_timeline ( timeline, path)
707
+ store. entity_has_temporal_data_on_timeline ( timeline, path)
698
708
} )
699
709
. is_some ( )
700
710
}
@@ -704,7 +714,7 @@ impl re_types_core::SizeBytes for EntityDb {
704
714
#[ inline]
705
715
fn heap_size_bytes ( & self ) -> u64 {
706
716
// TODO(emilk): size of entire EntityDb, including secondary indices etc
707
- self . data_store ( ) . stats ( ) . total ( ) . total_size_bytes
717
+ self . data_store . read ( ) . stats ( ) . total ( ) . total_size_bytes
708
718
}
709
719
}
710
720
0 commit comments