@@ -1,6 +1,9 @@
Loading
1 1
use crate::{
2 2
    error::PRes,
3 -
    io::{read_u64, write_u64, InfallibleRead, InfallibleWrite, ReadFormat, WriteFormat},
3 +
    io::{
4 +
        read_u64, write_u64, InfallibleRead, InfallibleReadFormat, InfallibleWrite, InfallibleWriteFormat, ReadFormat,
5 +
        WriteFormat,
6 +
    },
4 7
};
5 8
use std::{
6 9
    cmp,
@@ -249,20 +252,34 @@
Loading
249 252
        Ok(())
250 253
    }
251 254
252 -
    pub fn set_next_free(&mut self, next: u64) -> PRes<()> {
255 +
    pub fn set_next_free(&mut self, next: u64) {
253 256
        let pre = self.pos;
254 257
        self.pos = 2;
255 -
        self.write_u64(next)?;
258 +
        InfallibleWriteFormat::write_u64(self, next);
256 259
        self.pos = pre;
257 -
        Ok(())
258 260
    }
259 261
260 -
    pub fn get_next_free(&mut self) -> PRes<u64> {
262 +
    pub fn get_next_free(&mut self) -> u64 {
261 263
        let pre = self.pos;
262 264
        self.pos = 2;
263 -
        let val = self.read_u64()?;
265 +
        let val = InfallibleReadFormat::read_u64(self);
266 +
        self.pos = pre;
267 +
        val
268 +
    }
269 +
270 +
    pub fn set_prev_free(&mut self, next: u64) {
271 +
        let pre = self.pos;
272 +
        self.pos = 10;
273 +
        InfallibleWriteFormat::write_u64(self, next);
274 +
        self.pos = pre;
275 +
    }
276 +
277 +
    pub fn get_prev_free(&mut self) -> u64 {
278 +
        let pre = self.pos;
279 +
        self.pos = 10;
280 +
        let val = InfallibleReadFormat::read_u64(self);
264 281
        self.pos = pre;
265 -
        Ok(val)
282 +
        val
266 283
    }
267 284
268 285
    pub fn reset(&mut self) -> PRes<()> {
@@ -737,10 +754,10 @@
Loading
737 754
    fn set_get_next_free_device(device: &mut dyn Device) {
738 755
        let page = device.create_page(5).unwrap().get_index();
739 756
        let pg = &mut device.load_page(page).unwrap().clone_write();
740 -
        pg.set_next_free(30).unwrap();
757 +
        pg.set_next_free(30);
741 758
        device.flush_page(pg).unwrap();
742 759
        let pg1 = &mut device.load_page(page).unwrap().clone_write();
743 -
        let val = pg1.get_next_free().unwrap();
760 +
        let val = pg1.get_next_free();
744 761
        assert_eq!(val, 30);
745 762
    }
746 763

@@ -212,20 +212,38 @@
Loading
212 212
    }
213 213
214 214
    pub fn remove_from_free(&self, page: u64, exp: u8) -> PRes<()> {
215 -
        //TODO: this at the moment may leak free pages on recover after crash
216 215
        let mut fl = self.free_list.lock()?;
217 -
        if fl.list[exp as usize] == page {
218 -
            fl.list[exp as usize] = 0;
216 +
        let mut pg = self.write_page_int(page)?;
217 +
        if pg.is_free()? {
218 +
            if pg.get_prev_free() == 0 {
219 +
                fl.list[exp as usize] = pg.get_next_free();
220 +
            } else {
221 +
                let mut next = self.write_page_int(pg.get_next_free())?;
222 +
                next.set_prev_free(pg.get_prev_free());
223 +
                self.flush_page(next)?;
224 +
                let mut prev = self.write_page_int(pg.get_prev_free())?;
225 +
                prev.set_next_free(pg.get_next_free());
226 +
                self.flush_page(prev)?;
227 +
            }
228 +
            pg.set_free(false)?;
229 +
            self.flush_page(pg)?;
219 230
        } else {
220 -
            let mut p = fl.list[exp as usize];
221 -
            while p != 0 as u64 {
222 -
                let mut pg = self.write_page_int(p)?;
223 -
                p = pg.get_next_free()?;
224 -
                if p == page {
225 -
                    pg.set_free(false)?;
226 -
                    pg.set_next_free(0)?;
227 -
                    self.flush_page(pg)?;
228 -
                    break;
231 +
            // If we hit this branch and the page is found in the free list
232 +
            // it means that the page free was flushed but not the free list
233 +
            // in this case the safest approach is to truncate the free list
234 +
            // with potential pages leaks, to fix in future free list refactors
235 +
            if fl.list[exp as usize] == page {
236 +
                fl.list[exp as usize] = 0;
237 +
            } else {
238 +
                let mut p = fl.list[exp as usize];
239 +
                while p != 0 {
240 +
                    let mut pg_in_list = self.write_page_int(p)?;
241 +
                    p = pg_in_list.get_next_free();
242 +
                    if p == page {
243 +
                        pg_in_list.set_next_free(0);
244 +
                        self.flush_page(pg_in_list)?;
245 +
                        break;
246 +
                    }
229 247
                }
230 248
            }
231 249
        }
@@ -313,7 +331,7 @@
Loading
313 331
        let disc = Box::new(DiscRef::new(file).unwrap());
314 332
        let (_, allocator) = Allocator::init(disc, &Config::new()).unwrap();
315 333
        // This is needed to avoid the 0 page
316 -
        allocator.allocate(2).unwrap();
334 +
        allocator.allocate(10).unwrap();
317 335
        let first = allocator.allocate(10).unwrap().get_index();
318 336
        let second = allocator.allocate(10).unwrap().get_index();
319 337
        let third = allocator.allocate(11).unwrap().get_index();
@@ -361,9 +379,7 @@
Loading
361 379
        let val = allocator.allocate(10).unwrap().get_index();
362 380
        assert_eq!(val, third);
363 381
        let val = allocator.allocate(10).unwrap().get_index();
364 -
        assert!(val != first);
365 -
        assert!(val != second);
366 -
        assert!(val != third);
382 +
        assert_eq!(val, first);
367 383
    }
368 384
369 385
    #[test]
Files Coverage
src 92.81%
tests 98.56%
Project Totals (29 files) 93.84%
1
coverage:
2
  status:
3
    project:
4
      default:
5
        target: 80%
6
        threshold: 1.0%
7
    patch: off
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading