Make sure we don't leave the in memory hashmap in an inconsistent state

This commit is contained in:
Louis Dureuil 2023-01-10 17:35:50 +01:00
parent 1116788475
commit 35f6c624bc
No known key found for this signature in database

View File

@ -220,6 +220,7 @@ impl IndexMapper {
drop(lock); drop(lock);
let resize_succeeded = (move || {
let current_size = index.map_size()?; let current_size = index.map_size()?;
let new_size = current_size * 2; let new_size = current_size * 2;
let closing_event = index.prepare_for_closing(); let closing_event = index.prepare_for_closing();
@ -232,21 +233,38 @@ impl IndexMapper {
} }
log::info!("Resized index {name} from {current_size} to {new_size} bytes"); log::info!("Resized index {name} from {current_size} to {new_size} bytes");
let index_path = self.base_path.join(uuid.to_string()); let index_path = self.base_path.join(uuid.to_string());
let index = self.create_or_open_index(&index_path, None, new_size)?; let index = self.create_or_open_index(&index_path, None, new_size)?;
Ok(index)
})();
// Add back the resized index // Put the map back to a consistent state.
// Even if there was an error we don't want to leave the map in an inconsistent state as it would cause
// deadlocks.
let mut lock = self.index_map.write().unwrap(); let mut lock = self.index_map.write().unwrap();
let (resize_operation, resize_succeeded) = match resize_succeeded {
Ok(index) => {
// insert the resized index
let Some(BeingResized(resize_operation)) = lock.insert(uuid, Available(index)) else { let Some(BeingResized(resize_operation)) = lock.insert(uuid, Available(index)) else {
panic!("Index state for index {name} was modified while it was being resized") panic!("Index state for index {name} was modified while it was being resized")
}; };
(resize_operation, Ok(()))
}
Err(error) => {
// there was an error, not much we can do... delete the index from the in-memory map to prevent future errors
let Some(BeingResized(resize_operation)) = lock.remove(&uuid) else {
panic!("Index state for index {name} was modified while it was being resized")
};
(resize_operation, Err(error))
}
};
// drop the lock before signaling completion so that other threads don't immediately await on the lock after waking up. // drop the lock before signaling completion so that other threads don't immediately await on the lock after waking up.
drop(lock); drop(lock);
resize_operation.signal(); resize_operation.signal();
Ok(()) resize_succeeded
} }
/// Return an index, may open it if it wasn't already opened. /// Return an index, may open it if it wasn't already opened.