various_data_file/
fragment.rs1use std::{mem::size_of, num::NonZeroU64, path::Path};
2
3use file_mmap::FileMmap;
4
5use crate::DataAddress;
6
7pub(super) struct FragmentGetResult {
8 pub(super) fragment_id: NonZeroU64,
9 pub(super) addr: u64,
10}
11
12pub(super) struct Fragment {
13 filemmap: FileMmap,
14}
15
16const DATAADDRESS_SIZE: u64 = size_of::<DataAddress>() as u64;
17const COUNTER_SIZE: u64 = size_of::<u64>() as u64;
18const INIT_SIZE: u64 = COUNTER_SIZE + DATAADDRESS_SIZE;
19
20impl Fragment {
21 pub fn new<P: AsRef<Path>>(path: P) -> Self {
22 let mut filemmap = FileMmap::new(path).unwrap();
23 if filemmap.len() == 0 {
24 filemmap.set_len(INIT_SIZE).unwrap();
25 }
26 Self { filemmap }
27 }
28
29 unsafe fn list(&self) -> *const DataAddress {
30 self.filemmap.as_ptr().offset(COUNTER_SIZE as isize) as *const DataAddress
31 }
32
33 unsafe fn list_mut(&mut self) -> *mut DataAddress {
34 self.filemmap.as_ptr().offset(COUNTER_SIZE as isize) as *mut DataAddress
35 }
36
37 pub fn insert(&mut self, addr: DataAddress) {
38 let record_count = self.filemmap.as_ptr() as *mut u64;
39 let record_count = unsafe {
40 *record_count += 1;
41 *record_count
42 };
43 let size = INIT_SIZE + DATAADDRESS_SIZE * record_count;
44 if self.filemmap.len() < size {
45 self.filemmap.set_len(size).unwrap();
46 }
47 unsafe {
48 *self.list_mut().offset(record_count as isize) = addr;
49 }
50 }
51
52 pub unsafe fn release(&mut self, row: NonZeroU64, len: usize) {
53 let row = row.get() as u64;
54 let s = &mut *self.list_mut().offset(row as isize);
55 s.offset += len as i64;
56 s.len -= len as u64;
57
58 let record_count = self.filemmap.as_ptr() as *mut u64;
59 if s.len == 0 && row == *record_count {
60 *record_count -= 1;
61 }
62 }
63
64 pub fn search_blank(&self, len: usize) -> Option<FragmentGetResult> {
65 let record_count = unsafe { *(self.filemmap.as_ptr() as *const u64) };
66 if record_count != 0 {
67 for index in (-(record_count as isize)..0).map(|i| -i) {
68 let s = unsafe { &*self.list().offset(index) };
69 if s.len as usize >= len {
70 return Some(FragmentGetResult {
71 fragment_id: unsafe { NonZeroU64::new_unchecked(index as u64) },
72 addr: s.offset as u64,
73 });
74 }
75 }
76 }
77 None
78 }
79}