bitmap presque entièrement testé

This commit is contained in:
Moysan Gabriel 2023-04-18 04:17:17 +02:00
parent 347cdd9cf3
commit 9a23b1bb37

View File

@ -4,18 +4,28 @@ pub const BITS_IN_WORD: usize = 32;
use std::fs::File;
use std::io::{Cursor, Write, Read};
use crate::drivers::drv_disk::{self, DrvDisk};
use crate::filesys::openfile::OpenFile;
use crate::simulator::disk::SECTOR_SIZE;
pub struct BitMap {
num_bits: usize,
num_words: usize,
map: Vec<u32>,
pub num_bits: usize,
pub num_words: usize,
pub map: Vec<u32>,
}
impl BitMap {
pub fn compute_map_size(n_item : usize, dst_n_item : &mut usize, dst_num_word : &mut usize){
//on effectue un calcul sur n_item pour avoir un nombre de bits multiple de 32
//On fait le choix d'arrondir vers le haut pour que la map puisse acceuillir la taille souhaitée
*dst_n_item = n_item - (n_item%32);
if n_item%32 > 0 {
*dst_n_item += 32;
}
*dst_num_word = *dst_n_item/32;
}
/// Initialize a bitmap with "nitems" bits, so that every bit is clear.
/// it can be added somewhere on a list.
///
@ -23,19 +33,45 @@ impl BitMap {
/// - **nitems** is the number of bits in the bitmap.
///----------------------------------------------------------------------
pub fn init_bitmap(n_items: usize) -> BitMap {
let mut rounded_num_bits = 0;
let mut rounded_num_words = 0;
BitMap::compute_map_size(n_items, &mut rounded_num_bits, &mut rounded_num_words);
BitMap{
num_bits: n_items,
num_words: (n_items + SECTOR_SIZE as usize -1) / SECTOR_SIZE as usize,
map: vec![0,n_items as u32],
num_bits: rounded_num_bits,
num_words: rounded_num_words,//(n_items + SECTOR_SIZE as usize -1) / SECTOR_SIZE as usize,
map: vec![0u32 ; rounded_num_words],
}
}
//values is not borrowed
pub fn init_bitmap_from(values: &mut Vec<u32>)-> BitMap {
let mut tmp: Vec<u32> = Vec::new();
for value in values.iter(){
tmp.push(*value)
}
BitMap{
num_bits: values.len()*std::mem::size_of::<u32>()*8,
num_words: values.len(),
map: tmp
}
}
/// Set the "nth" bit in a bitmap.
/// ### Parameters
/// - **which** is the number of the bit to be set.
pub fn mark(&mut self, which: usize) {
assert!(which >= 0 && which < self.num_bits);
self.map[which / BITS_IN_WORD] |= 1 << (which % BITS_IN_WORD);
//self.map[which / BITS_IN_WORD] |= 1 << (which % BITS_IN_WORD);
let position_modulo = which%BITS_IN_WORD;
let left_shift = BITS_IN_WORD-position_modulo-1;
self.map[which / BITS_IN_WORD] |= (1u32 << left_shift);
}
/// return true if the "nth" bit is set.
@ -44,7 +80,11 @@ impl BitMap {
/// - **which** is the number of the bit to be tested.
pub fn test(&self, which: usize) -> bool {
assert!(which < self.num_bits);
(self.map[which / BITS_IN_WORD] & (1 << (which % BITS_IN_WORD))) != 0
//(self.map[which / BITS_IN_WORD] & (1 << (which % BITS_IN_WORD))) != 0
let position_modulo = which%BITS_IN_WORD;
let left_shift = BITS_IN_WORD-position_modulo-1;
(self.map[which / BITS_IN_WORD] & (1u32 << left_shift)) != 0
}
/// Return the number of the first bit which is clear.
@ -97,15 +137,18 @@ impl BitMap {
println!();
}
/*
///Initialize the contents of a bitmap from a Nachos file.
///
/// ### Parameters
/// - **file** is the place to read the bitmap from
pub fn fetch_from(&mut self, file: &mut OpenFile, drv_disk: &mut DrvDisk) -> std::io::Result<&Vec<u32>> {
let mut num_bytes = self.num_words * std::mem::size_of::<u32>();
pub fn fetch_from(&mut self, file_path: &str) -> std::io::Result<&Vec<u32>> {
// Ouvre le fichier en mode lecture seule
let mut file = File::open(file_path)?;
// Lit les octets du fichier dans un buffer
let mut buffer = vec![0; self.num_words * std::mem::size_of::<u32>()];
OpenFile::read(drv_disk, file, &mut buffer, num_bytes as i32);
file.read_exact(&mut buffer)?;
// Convertit les octets en vecteur de u32
self.map = vec![0; self.num_words];
@ -119,22 +162,218 @@ impl BitMap {
Ok(&self.map)
}
*/
///Initialize the contents of a bitmap from a Nachos file.
///
/// ### Parameters
/// - **file** is the place to read the bitmap from
pub fn fetch_from(&mut self, file_path: &str){
// Ouvre le fichier en mode lecture seule
let mut file = File::open(file_path).expect("BitMap::fetch_from , unable to open file in read only");
let mut buf_to_convert : Vec<u8> = Vec::new();
file.read_to_end(&mut buf_to_convert).expect("BitMap::fetch_from , unable to read from file");
let borne_max_exclue;
//si le fichier contient plus de mots que la map ne peut en acceuillir, on lit de quoi remplir la map
if buf_to_convert.len() > self.num_bits/8 {
borne_max_exclue = self.num_words*4;
}
//sinon on lit ce que le fichier contient, en respectant l'alignement sur 4 octects !
else {
borne_max_exclue = buf_to_convert.len() - (buf_to_convert.len()%4);
}
let mut i = 0;
// !! borne_max_exclue doit etre multiple de 4 !!
while i < borne_max_exclue {
let a : u32 = buf_to_convert[i] as u32;
let b : u32 = buf_to_convert[i+1] as u32;
let c : u32 = buf_to_convert[i+2] as u32;
let d : u32 = buf_to_convert[i+3] as u32;
self.map[i/4] = (a<<24) | (b<<16) | (c<<8) | (d);
i += 4;//on passe aux 4 octets suivants
}
}
/// Store the contents of a bitmap to a Nachos file.
///
/// ### Paramenters
/// - **file** is the place to write the bitmap to
pub fn write_back(&mut self, file: &mut OpenFile, drv_disk: &mut DrvDisk) -> std::io::Result<()> {
let mut num_bytes = self.num_words * std::mem::size_of::<u32>();
pub fn write_back(&mut self, file_path: &str) -> std::io::Result<()> {
// Encapsule le vecteur dans un std::io::Cursor pour l'utiliser comme un std::io::Write
let mut cursor = Cursor::new(Vec::<u8>::new());
for u32_val in self.map.as_mut_slice() {
cursor.write_all(&u32_val.to_le_bytes())?;
}
OpenFile::read_at(drv_disk, file, &mut cursor.into_inner(), num_bytes as i32, 0);
// Ouvre le fichier en mode écriture
let mut file = File::create(file_path)?;
// Écrit les données dans le fichier
file.write_all(&cursor.into_inner())?;
Ok(())
}
pub fn add_word(&mut self, word : u32){
self.map.push(word);
self.num_words += 1;
self.num_bits += std::mem::size_of::<u32>()*8;
}
pub fn add_words(&mut self, words : Vec<u32>){
for word in words.iter(){
self.add_word(*word);
}
}
}
#[cfg(test)]
mod tests {
use std::io::{Seek, SeekFrom};
use super::*;
#[test]
fn test_fetch_from_file_smaller_than_map() {
//println!("\n\n TEST FETCH FROM\n");
//On ecrit la séquence 0x AB CD EF 10 20 2E 3E 4F
let values : [u8 ; 8] = [0xAB, 0xCD, 0xEF, 0x10, 0x20, 0x2E, 0x3E, 0x4F];
let values_for_test : [u32 ; 2] = [0xABCDEF10, 0x202E3E4F];
let mut f = File::options()
.read(true)
.write(true)
.create(true)
.open("test_fetch_bitmap")
.expect("Unable to create File");
f.write_all(&values[..]).expect("Unable to write data");
//creating and loading the bitmap
let mut bit_map : BitMap = BitMap::init_bitmap(100);
bit_map.fetch_from("test_fetch_bitmap");
assert!(bit_map.num_bits == 128);
assert!(bit_map.num_words == 4);
for j in 0..bit_map.map.len(){
if j<2 {
assert!(values_for_test[j] == bit_map.map[j]);
}
else {
assert!(bit_map.map[j] == 0u32);
}
}
//print for debug
/*for val in bit_map.map.iter(){
println!("{:08X?}", *val)
}*/
}
#[test]
fn test_fetch_from_map_smaller_than_file() {
//println!("\n\n TEST FETCH FROM\n");
//On ecrit la séquence 0x AB CD EF 10 20 2E 3E 4F
let mut values : [u8 ; 8] = [0xFE, 0x59, 0xEF, 0x10, 0x20, 0x2E, 0x3E, 0x4F];
let mut f = File::options()
.read(true)
.write(true)
.create(true)
.open("test_fetch_bitmap_2")
.expect("Unable to create File");
f.write_all(&values[..]).expect("Unable to write data");
//creating and loading the bitmap
//1 bit donnera lieu via init_bit_map a une map de 32 bit soit 1 mot
let mut bit_map : BitMap = BitMap::init_bitmap(1);
//println!("\nnombre de bit de la map {} \nnombre de mot {}\n", bit_map.num_bits, bit_map.num_words);
bit_map.fetch_from("test_fetch_bitmap");
assert!(bit_map.num_bits == 32);
assert!(bit_map.num_words == 1);
assert!(bit_map.map[0] == 0xFE59EF10);
//println!("\n\n data loaded into map \n");
//print for debug
/*for val in bit_map.map.iter(){
println!("{:08X?}", *val)
}*/
}
#[test]
fn test_mark() {
let mut bit_map : BitMap = BitMap::init_bitmap(128);
let index_to_set : [usize ; 16] = [0,5,10,15,18,25,28,31,45,70,74,88,99,101,102,127];
for val in index_to_set.iter(){
bit_map.mark(*val);
}
assert!(bit_map.num_bits == 128);
assert!(bit_map.num_words == 4);
/*for i in bit_map.map.iter(){
println!("\n{:#032b}", *i);
}*/
for i in 0..bit_map.num_bits {
let word_index = i/32;
let mask_to_shift : u32 = 0x80000000;//un 1 au debut puis full 0 <=> 0x100000000000000000000000000000000
let shift_value = i%32;
if index_to_set.contains(&i) {
assert!( (bit_map.map[word_index] & (mask_to_shift>>shift_value)) != 0);
}
else{
assert!( (bit_map.map[word_index] & (mask_to_shift>>shift_value)) == 0) ;
}
}
}
#[test]
fn test_test() {
let mut bit_map : BitMap = BitMap::init_bitmap(128);
let index_to_set : [usize ; 16] = [0,5,10,15,18,25,28,31,45,70,74,88,99,101,102,127];
for val in index_to_set.iter(){
bit_map.mark(*val);
}
assert!(bit_map.num_bits == 128);
assert!(bit_map.num_words == 4);
for i in 0..bit_map.num_bits {
if index_to_set.contains(&i) {
assert!( bit_map.test(i) == true);
}
else{
assert!( bit_map.test(i) == false) ;
}
}
}
}