1515use crate :: cache:: { Cache , CacheRead , CacheWrite , Storage } ;
1616use crate :: lru_disk_cache:: Error as LruError ;
1717use crate :: lru_disk_cache:: LruDiskCache ;
18- use std:: ffi:: OsStr ;
18+ use std:: ffi:: { OsStr , OsString } ;
1919use std:: path:: { Path , PathBuf } ;
2020use std:: sync:: { Arc , Mutex } ;
2121use std:: time:: { Duration , Instant } ;
2222
2323use crate :: errors:: * ;
2424
25+ enum LazyDiskCache {
26+ Uninit { root : OsString , max_size : u64 } ,
27+ Init ( LruDiskCache ) ,
28+ }
29+
30+ impl LazyDiskCache {
31+ fn get_or_init ( & mut self ) -> Result < & mut LruDiskCache > {
32+ match self {
33+ LazyDiskCache :: Uninit { root, max_size } => {
34+ * self = LazyDiskCache :: Init ( LruDiskCache :: new ( & root, * max_size) ?) ;
35+ self . get_or_init ( )
36+ }
37+ LazyDiskCache :: Init ( d) => Ok ( d) ,
38+ }
39+ }
40+
41+ fn get ( & mut self ) -> Option < & mut LruDiskCache > {
42+ match self {
43+ LazyDiskCache :: Uninit { .. } => None ,
44+ LazyDiskCache :: Init ( d) => Some ( d) ,
45+ }
46+ }
47+
48+ fn path ( & self ) -> & Path {
49+ match self {
50+ LazyDiskCache :: Uninit { root, .. } => root. as_ref ( ) ,
51+ LazyDiskCache :: Init ( d) => d. path ( ) ,
52+ }
53+ }
54+ }
55+
2556/// A cache that stores entries at local disk paths.
26- #[ derive( Clone ) ]
2757pub struct DiskCache {
2858 /// `LruDiskCache` does all the real work here.
29- lru : Arc < Mutex < LruDiskCache > > ,
59+ lru : Arc < Mutex < LazyDiskCache > > ,
3060 /// Thread pool to execute disk I/O
3161 pool : tokio:: runtime:: Handle ,
3262}
3363
3464impl DiskCache {
3565 /// Create a new `DiskCache` rooted at `root`, with `max_size` as the maximum cache size on-disk, in bytes.
3666 pub fn new < T : AsRef < OsStr > > (
37- root : & T ,
67+ root : T ,
3868 max_size : u64 ,
3969 pool : & tokio:: runtime:: Handle ,
4070 ) -> DiskCache {
4171 DiskCache {
42- //TODO: change this function to return a Result
43- lru : Arc :: new ( Mutex :: new (
44- LruDiskCache :: new ( root , max_size) . expect ( "Couldn't instantiate disk cache!" ) ,
45- ) ) ,
72+ lru : Arc :: new ( Mutex :: new ( LazyDiskCache :: Uninit {
73+ root : root . as_ref ( ) . to_os_string ( ) ,
74+ max_size,
75+ } ) ) ,
4676 pool : pool. clone ( ) ,
4777 }
4878 }
@@ -64,7 +94,7 @@ impl Storage for DiskCache {
6494 self . pool
6595 . spawn_blocking ( move || {
6696 let mut lru = lru. lock ( ) . unwrap ( ) ;
67- let io = match lru. get ( & path) {
97+ let io = match lru. get_or_init ( ) ? . get ( & path) {
6898 Ok ( f) => f,
6999 Err ( LruError :: FileNotInCache ) => {
70100 trace ! ( "DiskCache::get({}): FileNotInCache" , key) ;
@@ -93,7 +123,7 @@ impl Storage for DiskCache {
93123 . spawn_blocking ( move || {
94124 let start = Instant :: now ( ) ;
95125 let v = entry. finish ( ) ?;
96- lru. lock ( ) . unwrap ( ) . insert_bytes ( key, & v) ?;
126+ lru. lock ( ) . unwrap ( ) . get_or_init ( ) ? . insert_bytes ( key, & v) ?;
97127 Ok ( start. elapsed ( ) )
98128 } )
99129 . await ?
@@ -104,9 +134,9 @@ impl Storage for DiskCache {
104134 }
105135
106136 async fn current_size ( & self ) -> Result < Option < u64 > > {
107- Ok ( Some ( self . lru . lock ( ) . unwrap ( ) . size ( ) ) )
137+ Ok ( self . lru . lock ( ) . unwrap ( ) . get ( ) . map ( |l| l . size ( ) ) )
108138 }
109139 async fn max_size ( & self ) -> Result < Option < u64 > > {
110- Ok ( Some ( self . lru . lock ( ) . unwrap ( ) . capacity ( ) ) )
140+ Ok ( self . lru . lock ( ) . unwrap ( ) . get ( ) . map ( |l| l . capacity ( ) ) )
111141 }
112142}
0 commit comments