Struct swap::file::SwapFile

source ·
pub struct SwapFile<'a> {
    file: &'a File,
    file_mmap: MemoryMapping,
    page_states: Vec<PageState>,
    file_states: FilePageStates,
    cursor_mlock: usize,
    min_possible_present_idx_file: usize,
}
Expand description

SwapFile stores active pages in a memory region.

This shares the swap file with other regions and creates mmap corresponding range in the file.

TODO(kawasin): The file structure is straightforward and is not optimized yet. Each page in the file corresponds to the page in the memory region.

Fields§

§file: &'a File§file_mmap: MemoryMapping§page_states: Vec<PageState>§file_states: FilePageStates§cursor_mlock: usize§min_possible_present_idx_file: usize

Implementations§

source§

impl<'a> SwapFile<'a>

source

pub fn new(file: &'a File, num_of_pages: usize) -> Result<Self, Error>

Creates an initialized SwapFile for a memory region.

The all pages are marked as empty at first time.

§Arguments
  • file - The swap file.
  • num_of_pages - The number of pages in the region.
source

pub fn page_content( &self, idx_page: usize, allow_cleared: bool ) -> Result<Option<VolatileSlice<'_>>, Error>

Returns a content of the page corresponding to the index if it is present.

Returns Option::None if no content in the file.

Returns Error::OutOfRange if the idx is out of range.

§Arguments
  • idx_page - the index of the page from the head of the pages.
source

pub fn lock_and_async_prefetch( &mut self, max_pages: usize ) -> Result<usize, Error>

Start readahead the swap file into the page cache from the head.

This also mlock2(2) the pages not to be dropped again after populated. This does not block the caller thread by I/O wait because:

  • mlock2(2) is executed with MLOCK_ONFAULT.
  • MADV_WILLNEED is the same as readahead(2) which triggers the readahead background.
    • However Linux has a bug that readahead(2) (and also MADV_WILLNEED) may block due to reading the filesystem metadata.

This returns the number of consecutive pages which are newly mlock(2)ed. Returning 0 means that there is no more data to be mlock(2)ed in this file.

The caller must track the number of pages mlock(2)ed not to mlock(2) more pages than RLIMIT_MEMLOCK if it does not have CAP_IPC_LOCK.

§Arguments
  • max_pages - The maximum number of pages to be mlock(2)ed at once.
source

pub fn clear_range( &mut self, idx_page_range: Range<usize> ) -> Result<usize, Error>

Mark the pages in the file corresponding to the index as cleared.

The contents on the swap file are preserved and will be reused by SwapFile::mark_as_present() and reduce disk I/O.

If the pages are mlock(2)ed, unlock them before MADV_DONTNEED. This returns the number of pages munlock(2)ed.

§Arguments
  • idx_page_range - The indices of consecutive pages to be cleared. All the pages must be present and consecutive in the compacted file.
source

pub fn free_range( &mut self, idx_page_range: Range<usize> ) -> Result<usize, Error>

Free the pages corresponding to the given range in the file.

If the pages are mlock(2)ed, unlock them. This returns the number of pages munlock(2)ed.

§Arguments
  • idx_page_range - The indices of consecutive pages to be freed. This may contains non-present pages.
source

pub fn clear_mlock(&mut self) -> Result<(), Error>

munlock(2) pages if there are mlock(2)ed pages in the mmap and reset the internal cursor for mlock(2) tracking.

source

pub fn mark_as_present(&mut self, idx_page: usize) -> Result<(), Error>

Mark the page as present on the file.

The content on the swap file on previous SwapFile::write_to_file() is reused.

§Arguments
  • idx - the index of the page from the head of the pages.
source

pub fn write_to_file( &mut self, idx_page: usize, mem_slice: &[u8] ) -> Result<(), Error>

Writes the contents to the swap file.

§Arguments
  • idx_page - the index of the head page of the content from the head of the pages.
  • mem_slice - the page content(s). this can be more than 1 page. the size must align with the pagesize.
source

pub fn first_data_range(&mut self, max_pages: usize) -> Option<Range<usize>>

Returns the first range of indices of consecutive pages present in the swap file.

§Arguments
  • max_pages - the max size of the returned chunk even if the chunk of consecutive present pages is longer than this.
source

pub fn get_slice( &self, idx_page_range: Range<usize> ) -> Result<VolatileSlice<'_>, Error>

Returns the [VolatileSlice] corresponding to the indices regardless of whether the pages are present or not.

If the range is out of the region, this returns Error::OutOfRange.

§Arguments
  • idx_page_range - the indices of the pages. All the pages must be present and consecutive in the compacted file.
source

pub fn present_pages(&self) -> usize

Returns the count of present pages in the swap file.

source

fn convert_idx_page_range_to_idx_file( &self, idx_page_range: Range<usize> ) -> Result<Range<usize>, Error>

Convert the index range to corresponding index range of compacted file.

This validates that the idx_page_range satisfy:

  • idx_page_range has corresponding page in the file.
  • corresponding index range in the file is consecutive.

Trait Implementations§

source§

impl<'a> Debug for SwapFile<'a>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> RefUnwindSafe for SwapFile<'a>

§

impl<'a> Send for SwapFile<'a>

§

impl<'a> Sync for SwapFile<'a>

§

impl<'a> Unpin for SwapFile<'a>

§

impl<'a> UnwindSafe for SwapFile<'a>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.