@@ -208,27 +208,18 @@ impl FilesystemStoreInner {
208208
209209 fn read ( & self , dest_file_path : PathBuf ) -> lightning:: io:: Result < Vec < u8 > > {
210210 let mut buf = Vec :: new ( ) ;
211- {
212- let inner_lock_ref = self . get_inner_lock_ref ( dest_file_path. clone ( ) ) ;
213- let async_state = inner_lock_ref. read ( ) . unwrap ( ) ;
214211
212+ let inner_lock_ref = self . get_inner_lock_ref ( dest_file_path. clone ( ) ) ;
213+ self . execute_locked_read ( inner_lock_ref, dest_file_path. clone ( ) , || {
215214 let mut f = fs:: File :: open ( dest_file_path. clone ( ) ) ?;
216215 f. read_to_end ( & mut buf) ?;
217-
218- let more_writes_pending =
219- async_state. latest_written_version < async_state. latest_version ;
220-
221- // If there are no more writes pending and no arcs in use elsewhere, we can remove the map entry to prevent
222- // leaking memory. The two arcs are the one in the map and the one held here in inner_lock_ref.
223- if !more_writes_pending && Arc :: strong_count ( & inner_lock_ref) == 2 {
224- self . locks . lock ( ) . unwrap ( ) . remove ( & dest_file_path) ;
225- }
226- }
216+ Ok ( ( ) )
217+ } ) ?;
227218
228219 Ok ( buf)
229220 }
230221
231- fn execute_locked < F : FnOnce ( ) -> Result < ( ) , lightning:: io:: Error > > (
222+ fn execute_locked_write < F : FnOnce ( ) -> Result < ( ) , lightning:: io:: Error > > (
232223 & self , inner_lock_ref : Arc < RwLock < AsyncState > > , dest_file_path : PathBuf ,
233224 version : Option < u64 > , callback : F ,
234225 ) -> Result < ( ) , lightning:: io:: Error > {
@@ -250,15 +241,35 @@ impl FilesystemStoreInner {
250241 } )
251242 } ;
252243
244+ self . clean_locks ( & inner_lock_ref, dest_file_path, & async_state) ;
245+
246+ res
247+ }
248+
249+ fn execute_locked_read < F : FnOnce ( ) -> Result < ( ) , lightning:: io:: Error > > (
250+ & self , inner_lock_ref : Arc < RwLock < AsyncState > > , dest_file_path : PathBuf , callback : F ,
251+ ) -> Result < ( ) , lightning:: io:: Error > {
252+ let async_state = inner_lock_ref. read ( ) . unwrap ( ) ;
253+
254+ // If the version is not stale, we execute the callback. Otherwise we can and must skip writing.
255+ let res = callback ( ) ;
256+
257+ self . clean_locks ( & inner_lock_ref, dest_file_path, & async_state) ;
258+
259+ res
260+ }
261+
262+ fn clean_locks (
263+ & self , inner_lock_ref : & Arc < RwLock < AsyncState > > , dest_file_path : PathBuf ,
264+ async_state : & AsyncState ,
265+ ) {
253266 let more_writes_pending = async_state. latest_written_version < async_state. latest_version ;
254267
255268 // If there are no more writes pending and no arcs in use elsewhere, we can remove the map entry to prevent
256269 // leaking memory. The two arcs are the one in the map and the one held here in inner_lock_ref.
257270 if !more_writes_pending && Arc :: strong_count ( & inner_lock_ref) == 2 {
258271 self . locks . lock ( ) . unwrap ( ) . remove ( & dest_file_path) ;
259272 }
260-
261- res
262273 }
263274
264275 /// Writes a specific version of a key to the filesystem. If a newer version has been written already, this function
@@ -289,7 +300,7 @@ impl FilesystemStoreInner {
289300 tmp_file. sync_all ( ) ?;
290301 }
291302
292- self . execute_locked ( inner_lock_ref, dest_file_path. clone ( ) , version, || {
303+ self . execute_locked_write ( inner_lock_ref, dest_file_path. clone ( ) , version, || {
293304 #[ cfg( not( target_os = "windows" ) ) ]
294305 {
295306 fs:: rename ( & tmp_file_path, & dest_file_path) ?;
@@ -340,7 +351,7 @@ impl FilesystemStoreInner {
340351 & self , inner_lock_ref : Arc < RwLock < AsyncState > > , dest_file_path : PathBuf , lazy : bool ,
341352 version : Option < u64 > ,
342353 ) -> lightning:: io:: Result < ( ) > {
343- self . execute_locked ( inner_lock_ref, dest_file_path. clone ( ) , version, || {
354+ self . execute_locked_write ( inner_lock_ref, dest_file_path. clone ( ) , version, || {
344355 if !dest_file_path. is_file ( ) {
345356 return Ok ( ( ) ) ;
346357 }
0 commit comments