@@ -98,9 +98,9 @@ use tables::{ReadOnlyTables, ReadableTables, Tables};
9898
9999use self :: { tables:: DeleteSet , test_support:: EntryData , util:: PeekableFlumeReceiver } ;
100100use super :: {
101- bao_file:: { BaoFileConfig , BaoFileHandle , BaoFileHandleWeak , CreateCb } ,
102- temp_name, BaoBatchWriter , BaoBlobSize , ConsistencyCheckProgress , EntryStatus , ExportMode ,
103- ExportProgressCb , ImportMode , ImportProgress , Map , ReadableStore , TempCounterMap ,
101+ bao_file:: { read_current_size , BaoFileConfig , BaoFileHandle , BaoFileHandleWeak , CreateCb } ,
102+ temp_name, BaoBatchWriter , BaoBlobSize , ConsistencyCheckProgress , EntryPathOrData , EntryStatus ,
103+ ExportMode , ExportProgressCb , ImportMode , ImportProgress , Map , ReadableStore , TempCounterMap ,
104104} ;
105105use crate :: {
106106 store:: {
@@ -532,6 +532,10 @@ pub(crate) enum ActorMessage {
532532 hash : Hash ,
533533 tx : oneshot:: Sender < ActorResult < EntryStatus > > ,
534534 } ,
535+ EntryPathOrData {
536+ hash : Hash ,
537+ tx : oneshot:: Sender < ActorResult < Option < EntryPathOrData > > > ,
538+ } ,
535539 #[ cfg( test) ]
536540 /// Query method: get the full entry state for a hash, both in memory and in redb.
537541 /// This is everything we got about the entry, including the actual inline outboard and data.
@@ -664,6 +668,7 @@ impl ActorMessage {
664668 | Self :: Tags { .. }
665669 | Self :: GcStart { .. }
666670 | Self :: GetFullEntryState { .. }
671+ | Self :: EntryPathOrData { .. }
667672 | Self :: Dump => MessageCategory :: ReadOnly ,
668673 Self :: Import { .. }
669674 | Self :: Export { .. }
@@ -870,6 +875,14 @@ impl StoreInner {
870875 Ok ( tags)
871876 }
872877
878+ async fn entry_path_or_data ( & self , hash : Hash ) -> OuterResult < Option < EntryPathOrData > > {
879+ let ( tx, rx) = oneshot:: channel ( ) ;
880+ self . tx
881+ . send ( ActorMessage :: EntryPathOrData { hash, tx } )
882+ . await ?;
883+ Ok ( rx. await ??)
884+ }
885+
873886 async fn set_tag ( & self , tag : Tag , value : Option < HashAndFormat > ) -> OuterResult < ( ) > {
874887 let ( tx, rx) = oneshot:: channel ( ) ;
875888 self . tx
@@ -1371,6 +1384,10 @@ impl super::Store for Store {
13711384 . await ??)
13721385 }
13731386
1387+ async fn entry_path_or_data ( & self , hash : Hash ) -> io:: Result < Option < EntryPathOrData > > {
1388+ Ok ( self . 0 . entry_path_or_data ( hash) . await ?)
1389+ }
1390+
13741391 async fn set_tag ( & self , name : Tag , hash : Option < HashAndFormat > ) -> io:: Result < ( ) > {
13751392 Ok ( self . 0 . set_tag ( name, hash) . await ?)
13761393 }
@@ -2266,6 +2283,65 @@ impl ActorState {
22662283 Ok ( ( ) )
22672284 }
22682285
2286+ fn entry_path_or_data (
2287+ & mut self ,
2288+ tables : & impl ReadableTables ,
2289+ hash : Hash ,
2290+ ) -> ActorResult < Option < EntryPathOrData > > {
2291+ let data_path = || self . options . path . owned_data_path ( & hash) ;
2292+ let outboard_path = || self . options . path . owned_outboard_path ( & hash) ;
2293+ let sizes_path = || self . options . path . owned_sizes_path ( & hash) ;
2294+ Ok ( match tables. blobs ( ) . get ( hash) ? {
2295+ Some ( guard) => match guard. value ( ) {
2296+ EntryState :: Complete {
2297+ data_location,
2298+ outboard_location,
2299+ } => {
2300+ let data = match data_location {
2301+ DataLocation :: External ( paths, size) => {
2302+ let path = paths. first ( ) . ok_or_else ( || {
2303+ ActorError :: Inconsistent ( "external data missing" . to_owned ( ) )
2304+ } ) ?;
2305+ MemOrFile :: File ( ( path. clone ( ) , size) )
2306+ }
2307+ DataLocation :: Owned ( size) => MemOrFile :: File ( ( data_path ( ) , size) ) ,
2308+ DataLocation :: Inline ( _) => {
2309+ let data = tables. inline_data ( ) . get ( hash) ?. ok_or_else ( || {
2310+ ActorError :: Inconsistent ( "inline data missing" . to_owned ( ) )
2311+ } ) ?;
2312+ MemOrFile :: Mem ( data. value ( ) . to_vec ( ) . into ( ) )
2313+ }
2314+ } ;
2315+ let outboard = match outboard_location {
2316+ OutboardLocation :: Owned => MemOrFile :: File ( outboard_path ( ) ) ,
2317+ OutboardLocation :: Inline ( _) => MemOrFile :: Mem (
2318+ tables
2319+ . inline_outboard ( )
2320+ . get ( hash) ?
2321+ . ok_or_else ( || {
2322+ ActorError :: Inconsistent ( "inline outboard missing" . to_owned ( ) )
2323+ } ) ?
2324+ . value ( )
2325+ . to_vec ( )
2326+ . into ( ) ,
2327+ ) ,
2328+ OutboardLocation :: NotNeeded => MemOrFile :: Mem ( Bytes :: new ( ) ) ,
2329+ } ;
2330+ Some ( EntryPathOrData { data, outboard } )
2331+ }
2332+ EntryState :: Partial { .. } => {
2333+ let sizes = std:: fs:: File :: open ( sizes_path ( ) ) ?;
2334+ let size = read_current_size ( & sizes) ?;
2335+ Some ( EntryPathOrData {
2336+ data : MemOrFile :: File ( ( data_path ( ) , size) ) ,
2337+ outboard : MemOrFile :: File ( outboard_path ( ) ) ,
2338+ } )
2339+ }
2340+ } ,
2341+ None => None ,
2342+ } )
2343+ }
2344+
22692345 fn handle_toplevel ( & mut self , db : & redb:: Database , msg : ActorMessage ) -> ActorResult < ( ) > {
22702346 match msg {
22712347 ActorMessage :: UpdateInlineOptions {
@@ -2339,6 +2415,10 @@ impl ActorState {
23392415 let res = self . get_full_entry_state ( tables, hash) ;
23402416 tx. send ( res) . ok ( ) ;
23412417 }
2418+ ActorMessage :: EntryPathOrData { hash, tx } => {
2419+ let res = self . entry_path_or_data ( tables, hash) ;
2420+ tx. send ( res) . ok ( ) ;
2421+ }
23422422 x => return Ok ( Err ( x) ) ,
23432423 }
23442424 Ok ( Ok ( ( ) ) )
0 commit comments