Skip to content

Commit 1329fd2

Browse files
committed
f Cleanup lock handling
1 parent bc73b39 commit 1329fd2

File tree

1 file changed

+42
-42
lines changed

1 file changed

+42
-42
lines changed

lightning-persister/src/fs_store.rs

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ impl KVStore for FilesystemStore {
7070
dest_file_path.push(namespace);
7171
dest_file_path.push(key);
7272

73-
let mut outer_lock = self.locks.lock().unwrap();
74-
let inner_lock_ref = Arc::clone(&outer_lock.entry(dest_file_path.clone()).or_default());
73+
let inner_lock_ref = {
74+
let mut outer_lock = self.locks.lock().unwrap();
75+
Arc::clone(&outer_lock.entry(dest_file_path.clone()).or_default())
76+
};
7577
let _guard = inner_lock_ref.read().unwrap();
7678

7779
let mut buf = Vec::new();
@@ -103,10 +105,6 @@ impl KVStore for FilesystemStore {
103105
dest_file_path.push(namespace);
104106
dest_file_path.push(key);
105107

106-
let mut outer_lock = self.locks.lock().unwrap();
107-
let inner_lock_ref = Arc::clone(&outer_lock.entry(dest_file_path.clone()).or_default());
108-
let _guard = inner_lock_ref.write().unwrap();
109-
110108
let parent_directory = dest_file_path
111109
.parent()
112110
.ok_or_else(|| {
@@ -132,6 +130,12 @@ impl KVStore for FilesystemStore {
132130
tmp_file.sync_all()?;
133131
}
134132

133+
let inner_lock_ref = {
134+
let mut outer_lock = self.locks.lock().unwrap();
135+
Arc::clone(&outer_lock.entry(dest_file_path.clone()).or_default())
136+
};
137+
let _guard = inner_lock_ref.write().unwrap();
138+
135139
#[cfg(not(target_os = "windows"))]
136140
{
137141
fs::rename(&tmp_file_path, &dest_file_path)?;
@@ -186,51 +190,47 @@ impl KVStore for FilesystemStore {
186190
dest_file_path.push(namespace);
187191
dest_file_path.push(key);
188192

189-
let mut outer_lock = self.locks.lock().unwrap();
190-
let inner_lock_ref = Arc::clone(&outer_lock.entry(dest_file_path.clone()).or_default());
191-
192-
let _guard = inner_lock_ref.write().unwrap();
193-
194193
if !dest_file_path.is_file() {
195194
return Ok(());
196195
}
197196

198-
fs::remove_file(&dest_file_path)?;
199-
#[cfg(not(target_os = "windows"))]
200197
{
201-
let parent_directory = dest_file_path.parent().ok_or_else(|| {
202-
let msg =
203-
format!("Could not retrieve parent directory of {}.", dest_file_path.display());
204-
std::io::Error::new(std::io::ErrorKind::InvalidInput, msg)
205-
})?;
206-
let dir_file = fs::OpenOptions::new().read(true).open(parent_directory)?;
207-
// The above call to `fs::remove_file` corresponds to POSIX `unlink`, whose changes
208-
// to the inode might get cached (and hence possibly lost on crash), depending on
209-
// the target platform and file system.
210-
//
211-
// In order to assert we permanently removed the file in question we therefore
212-
// call `fsync` on the parent directory on platforms that support it,
213-
dir_file.sync_all()?;
214-
}
198+
let inner_lock_ref = {
199+
let mut outer_lock = self.locks.lock().unwrap();
200+
Arc::clone(&outer_lock.entry(dest_file_path.clone()).or_default())
201+
};
202+
let _guard = inner_lock_ref.write().unwrap();
203+
204+
fs::remove_file(&dest_file_path)?;
205+
#[cfg(not(target_os = "windows"))]
206+
{
207+
let parent_directory = dest_file_path.parent().ok_or_else(|| {
208+
let msg =
209+
format!("Could not retrieve parent directory of {}.", dest_file_path.display());
210+
std::io::Error::new(std::io::ErrorKind::InvalidInput, msg)
211+
})?;
212+
let dir_file = fs::OpenOptions::new().read(true).open(parent_directory)?;
213+
// The above call to `fs::remove_file` corresponds to POSIX `unlink`, whose changes
214+
// to the inode might get cached (and hence possibly lost on crash), depending on
215+
// the target platform and file system.
216+
//
217+
// In order to assert we permanently removed the file in question we therefore
218+
// call `fsync` on the parent directory on platforms that support it,
219+
dir_file.sync_all()?;
220+
}
215221

216-
if dest_file_path.is_file() {
217-
return Err(std::io::Error::new(std::io::ErrorKind::Other, "Removing key failed"));
222+
if dest_file_path.is_file() {
223+
return Err(std::io::Error::new(std::io::ErrorKind::Other, "Removing key failed"));
224+
}
218225
}
219226

220-
if Arc::strong_count(&inner_lock_ref) == 2 {
221-
// It's safe to remove the lock entry if we're the only one left holding a strong
222-
// reference. Checking this is necessary to ensure we continue to distribute references to the
223-
// same lock as long as some Readers are around. However, we still want to
224-
// clean up the table when possible.
225-
//
226-
// Note that this by itself is still leaky as lock entries will remain when more Readers/Writers are
227-
// around, but is preferable to doing nothing *or* something overly complex such as
228-
// implementing yet another RAII structure just for this pupose.
229-
outer_lock.remove(&dest_file_path);
230-
}
227+
{
228+
// Retake outer lock for the cleanup.
229+
let mut outer_lock = self.locks.lock().unwrap();
231230

232-
// Garbage collect all lock entries that are not referenced anymore.
233-
outer_lock.retain(|_, v| Arc::strong_count(&v) > 1);
231+
// Garbage collect all lock entries that are not referenced anymore.
232+
outer_lock.retain(|_, v| Arc::strong_count(&v) > 1);
233+
}
234234

235235
Ok(())
236236
}

0 commit comments

Comments
 (0)