Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a8fe5fa

Browse files
committed
Make sure we don't leave the in memory hashmap in an inconsistent state
1 parent 1fe5e91 commit a8fe5fa

File tree

1 file changed

+34
-16
lines changed

1 file changed

+34
-16
lines changed

index-scheduler/src/index_mapper.rs

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -220,33 +220,51 @@ impl IndexMapper {
220220

221221
drop(lock);
222222

223-
let current_size = index.map_size()?;
224-
let new_size = current_size * 2;
225-
let closing_event = index.prepare_for_closing();
223+
let resize_succeeded = (move || {
224+
let current_size = index.map_size()?;
225+
let new_size = current_size * 2;
226+
let closing_event = index.prepare_for_closing();
226227

227-
log::debug!("Waiting for index {name} to close");
228+
log::debug!("Waiting for index {name} to close");
228229

229-
if !closing_event.wait_timeout(std::time::Duration::from_secs(600)) {
230-
// fail after 10 minutes waiting
231-
panic!("Could not resize index {name} (unable to close it)");
232-
}
230+
if !closing_event.wait_timeout(std::time::Duration::from_secs(600)) {
231+
// fail after 10 minutes waiting
232+
panic!("Could not resize index {name} (unable to close it)");
233+
}
233234

234-
log::info!("Resized index {name} from {current_size} to {new_size} bytes");
235+
log::info!("Resized index {name} from {current_size} to {new_size} bytes");
236+
let index_path = self.base_path.join(uuid.to_string());
237+
let index = self.create_or_open_index(&index_path, None, new_size)?;
238+
Ok(index)
239+
})();
235240

236-
let index_path = self.base_path.join(uuid.to_string());
237-
let index = self.create_or_open_index(&index_path, None, new_size)?;
238-
239-
// Add back the resized index
241+
// Put the map back to a consistent state.
242+
// Even if there was an error we don't want to leave the map in an inconsistent state as it would cause
243+
// deadlocks.
240244
let mut lock = self.index_map.write().unwrap();
241-
let Some(BeingResized(resize_operation)) = lock.insert(uuid, Available(index)) else {
242-
panic!("Index state for index {name} was modified while it was being resized")
245+
let (resize_operation, resize_succeeded) = match resize_succeeded {
246+
Ok(index) => {
247+
// insert the resized index
248+
let Some(BeingResized(resize_operation)) = lock.insert(uuid, Available(index)) else {
249+
panic!("Index state for index {name} was modified while it was being resized")
250+
};
251+
252+
(resize_operation, Ok(()))
253+
}
254+
Err(error) => {
255+
// there was an error, not much we can do... delete the index from the in-memory map to prevent future errors
256+
let Some(BeingResized(resize_operation)) = lock.remove(&uuid) else {
257+
panic!("Index state for index {name} was modified while it was being resized")
258+
};
259+
(resize_operation, Err(error))
260+
}
243261
};
244262

245263
// drop the lock before signaling completion so that other threads don't immediately await on the lock after waking up.
246264
drop(lock);
247265
resize_operation.signal();
248266

249-
Ok(())
267+
resize_succeeded
250268
}
251269

252270
/// Return an index, may open it if it wasn't already opened.

0 commit comments

Comments
 (0)