22// Licensed under the MIT License.
33
44use lazy_static:: lazy_static;
5- use log:: trace;
5+ use log:: { trace, warn } ;
66use std:: {
77 collections:: { hash_map:: Entry , HashMap , HashSet } ,
8+ io,
89 path:: PathBuf ,
910 sync:: { Arc , Mutex } ,
1011 time:: SystemTime ,
1112} ;
1213
1314use crate :: {
1415 env:: ResolvedPythonEnv ,
15- fs_cache:: { get_cache_from_file, store_cache_in_file} ,
16+ fs_cache:: { delete_cache_file , get_cache_from_file, store_cache_in_file} ,
1617} ;
1718
1819lazy_static ! {
@@ -25,6 +26,10 @@ pub trait CacheEntry: Send + Sync {
2526 fn track_symlinks ( & self , symlinks : Vec < PathBuf > ) ;
2627}
2728
29+ pub fn clear_cache ( ) -> io:: Result < ( ) > {
30+ CACHE . clear ( )
31+ }
32+
2833pub fn create_cache ( executable : PathBuf ) -> Arc < Mutex < Box < dyn CacheEntry > > > {
2934 CACHE . create_cache ( executable)
3035}
@@ -61,28 +66,39 @@ impl CacheImpl {
6166 /// Once a cache directory has been set, you cannot change it.
6267 /// No point supporting such a scenario.
6368 fn set_cache_directory ( & self , cache_dir : PathBuf ) {
69+ if let Some ( cache_dir) = self . cache_dir . lock ( ) . unwrap ( ) . clone ( ) {
70+ warn ! (
71+ "Cache directory has already been set to {:?}. Cannot change it now." ,
72+ cache_dir
73+ ) ;
74+ return ;
75+ }
76+ trace ! ( "Setting cache directory to {:?}" , cache_dir) ;
6477 self . cache_dir . lock ( ) . unwrap ( ) . replace ( cache_dir) ;
6578 }
79+ fn clear ( & self ) -> io:: Result < ( ) > {
80+ trace ! ( "Clearing cache" ) ;
81+ self . locks . lock ( ) . unwrap ( ) . clear ( ) ;
82+ if let Some ( cache_directory) = self . cache_dir . lock ( ) . unwrap ( ) . clone ( ) {
83+ std:: fs:: remove_dir_all ( cache_directory)
84+ } else {
85+ Ok ( ( ) )
86+ }
87+ }
6688 fn create_cache ( & self , executable : PathBuf ) -> LockableCacheEntry {
67- if let Some ( cache_directory) = self . cache_dir . lock ( ) . unwrap ( ) . as_ref ( ) {
68- match self . locks . lock ( ) . unwrap ( ) . entry ( executable. clone ( ) ) {
69- Entry :: Occupied ( lock) => lock. get ( ) . clone ( ) ,
70- Entry :: Vacant ( lock) => {
71- let cache =
72- Box :: new ( CacheEntryImpl :: create ( cache_directory. clone ( ) , executable) )
73- as Box < ( dyn CacheEntry + ' static ) > ;
74- lock. insert ( Arc :: new ( Mutex :: new ( cache) ) ) . clone ( )
75- }
89+ let cache_directory = self . cache_dir . lock ( ) . unwrap ( ) . clone ( ) ;
90+ match self . locks . lock ( ) . unwrap ( ) . entry ( executable. clone ( ) ) {
91+ Entry :: Occupied ( lock) => lock. get ( ) . clone ( ) ,
92+ Entry :: Vacant ( lock) => {
93+ let cache = Box :: new ( CacheEntryImpl :: create ( cache_directory. clone ( ) , executable) )
94+ as Box < ( dyn CacheEntry + ' static ) > ;
95+ lock. insert ( Arc :: new ( Mutex :: new ( cache) ) ) . clone ( )
7696 }
77- } else {
78- Arc :: new ( Mutex :: new ( Box :: new ( CacheEntryImpl :: empty (
79- executable. clone ( ) ,
80- ) ) ) )
8197 }
8298 }
8399}
84100
85- type FilePathWithMTimeCTime = ( PathBuf , Option < SystemTime > , Option < SystemTime > ) ;
101+ type FilePathWithMTimeCTime = ( PathBuf , SystemTime , SystemTime ) ;
86102
87103struct CacheEntryImpl {
88104 cache_directory : Option < PathBuf > ,
@@ -92,17 +108,9 @@ struct CacheEntryImpl {
92108 symlinks : Arc < Mutex < Vec < FilePathWithMTimeCTime > > > ,
93109}
94110impl CacheEntryImpl {
95- pub fn create ( cache_directory : PathBuf , executable : PathBuf ) -> impl CacheEntry {
111+ pub fn create ( cache_directory : Option < PathBuf > , executable : PathBuf ) -> impl CacheEntry {
96112 CacheEntryImpl {
97- cache_directory : Some ( cache_directory) ,
98- executable,
99- envoronment : Arc :: new ( Mutex :: new ( None ) ) ,
100- symlinks : Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ,
101- }
102- }
103- pub fn empty ( executable : PathBuf ) -> impl CacheEntry {
104- CacheEntryImpl {
105- cache_directory : None ,
113+ cache_directory,
106114 executable,
107115 envoronment : Arc :: new ( Mutex :: new ( None ) ) ,
108116 symlinks : Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ,
@@ -112,10 +120,21 @@ impl CacheEntryImpl {
112120 // Check if any of the exes have changed since we last cached this.
113121 for symlink_info in self . symlinks . lock ( ) . unwrap ( ) . iter ( ) {
114122 if let Ok ( metadata) = symlink_info. 0 . metadata ( ) {
115- if metadata. modified ( ) . ok ( ) != symlink_info. 1
116- || metadata. created ( ) . ok ( ) != symlink_info. 2
123+ if metadata. modified ( ) . ok ( ) != Some ( symlink_info. 1 )
124+ || metadata. created ( ) . ok ( ) != Some ( symlink_info. 2 )
117125 {
126+ trace ! (
127+ "Symlink {:?} has changed since we last cached it. original mtime & ctime {:?}, {:?}, current mtime & ctime {:?}, {:?}" ,
128+ symlink_info. 0 ,
129+ symlink_info. 1 ,
130+ symlink_info. 2 ,
131+ metadata. modified( ) . ok( ) ,
132+ metadata. created( ) . ok( )
133+ ) ;
118134 self . envoronment . lock ( ) . unwrap ( ) . take ( ) ;
135+ if let Some ( cache_directory) = & self . cache_directory {
136+ delete_cache_file ( cache_directory, & self . executable ) ;
137+ }
119138 }
120139 }
121140 }
@@ -149,11 +168,12 @@ impl CacheEntry for CacheEntryImpl {
149168 let mut symlinks = vec ! [ ] ;
150169 for symlink in environment. symlinks . clone ( ) . unwrap_or_default ( ) . iter ( ) {
151170 if let Ok ( metadata) = symlink. metadata ( ) {
152- symlinks. push ( (
153- symlink. clone ( ) ,
154- metadata. modified ( ) . ok ( ) ,
155- metadata. created ( ) . ok ( ) ,
156- ) ) ;
171+ // We only care if we have the information
172+ if let ( Some ( modified) , Some ( created) ) =
173+ ( metadata. modified ( ) . ok ( ) , metadata. created ( ) . ok ( ) )
174+ {
175+ symlinks. push ( ( symlink. clone ( ) , modified, created) ) ;
176+ }
157177 }
158178 }
159179
@@ -167,8 +187,9 @@ impl CacheEntry for CacheEntryImpl {
167187 . unwrap ( )
168188 . replace ( environment. clone ( ) ) ;
169189
190+ trace ! ( "Caching interpreter info for {:?}" , self . executable) ;
191+
170192 if let Some ( ref cache_directory) = self . cache_directory {
171- trace ! ( "Storing cache for {:?}" , self . executable) ;
172193 store_cache_in_file ( cache_directory, & self . executable , & environment, symlinks)
173194 }
174195 }
0 commit comments