Skip to main content

FileManager

Struct FileManager 

Source
pub struct FileManager {
    pub n_file_opens: AtomicU64,
    pub n_sequential_reads: AtomicU64,
    pub n_sequential_read_bytes: AtomicU64,
    pub n_sequential_writes: AtomicU64,
    pub n_sequential_write_bytes: AtomicU64,
    pub n_random_reads: AtomicU64,
    pub n_random_read_bytes: AtomicU64,
    /* private fields */
}
Expand description

Manages log files in the environment directory.

Fields§

§n_file_opens: AtomicU64

Number of log files opened (cache miss = new file open).

§n_sequential_reads: AtomicU64

Number of sequential read calls.

§n_sequential_read_bytes: AtomicU64

Total bytes read sequentially.

§n_sequential_writes: AtomicU64

Number of sequential write calls.

§n_sequential_write_bytes: AtomicU64

Total bytes written sequentially.

§n_random_reads: AtomicU64

Number of random (point-lookup) read operations.

§n_random_read_bytes: AtomicU64

Total bytes from random read operations.

Implementations§

Source§

impl FileManager

Source

pub fn new( env_dir: impl AsRef<Path>, read_only: bool, max_file_size: u64, cache_size: usize, ) -> Result<Self>

Creates a new FileManager.

§Arguments
  • env_dir - Path to the environment directory
  • read_only - Whether to open in read-only mode
  • max_file_size - Maximum size of a single log file (bytes)
  • cache_size - Maximum number of file handles to cache
§Returns

A new FileManager instance, or an error if the directory is invalid or the environment is locked.

Source

pub fn list_file_numbers(&self) -> Result<Vec<u32>>

Lists all log file numbers in the environment directory.

Returns the file numbers sorted in ascending order.

Source

pub fn get_first_file_num(&self) -> Result<Option<u32>>

Returns the first (lowest numbered) file, or None if no files exist.

Source

pub fn get_last_file_num(&self) -> Result<Option<u32>>

Returns the last (highest numbered) file, or None if no files exist.

Source

pub fn is_read_only(&self) -> bool

Returns the configured maximum log file size in bytes. Returns true if this FileManager was opened read-only.

Source

pub fn max_file_size(&self) -> u64

Source

pub fn env_dir(&self) -> &Path

Returns the environment directory holding the log files.

Source

pub fn total_log_size(&self) -> Result<u64>

Returns the total size, in bytes, of all .ndb log files on disk.

This is the disk-limit “total log size” used by the disk-usage probe. JE computes the analogous value in FileProtector.getLogSizeStats() by summing activeFiles (plus the last file’s length); Noxu has no reserved-file machinery (the cleaner deletes files outright rather than parking them as “reserved”), so the total is simply the sum of every log file’s length — equivalent to JE’s activeSize with reservedSize == 0.

Source

pub fn disk_free_space(&self) -> Result<u64>

Returns the filesystem free (usable) space, in bytes, for the environment directory.

JE calls Cleaner.getDiskFreeSpace()FileStoreInfo.getUsableSpace() (a statvfs). Noxu uses fs2::available_space (also statvfs-backed), which reports space available to a non-privileged process — the same notion JE uses.

Source

pub fn get_current_file_num(&self) -> u32

Returns the current file number being written to.

Source

pub fn get_next_available_lsn(&self) -> Lsn

Returns the next available LSN for writing.

Source

pub fn get_last_used_lsn(&self) -> Lsn

Returns the last used LSN.

Source

pub fn set_last_position(&self, next_available_lsn: Lsn, last_used_lsn: Lsn)

Sets the end-of-log position.

Called during recovery to set where the log should continue from.

Source

pub fn get_file_handle(&self, file_num: u32) -> Result<Arc<FileHandle>>

Gets a file handle for the given file number.

Checks the LRU cache first. On a cache miss the file is opened, its header validated, and the resulting Arc<FileHandle> is inserted — with automatic LRU eviction when the cache is at capacity. Because lru::LruCache::get() mutates the eviction order, the entire lookup+insert is done under a single Mutex lock, eliminating any TOCTOU race between a cache miss and the subsequent insert.

Source

pub fn file_header_size_for(&self, file_num: u32) -> Result<usize>

Returns the on-disk header size (= first-entry byte offset) for a given log file.

Opens (or cache-hits) the file to read its log_version, then returns FileHeader::on_disk_size(version):

  • v2 file → 32 bytes → first entry at offset 32
  • v3 file → 36 bytes → first entry at offset 36

Use this whenever computing the “first entry offset” for an existing file instead of the bare FILE_HEADER_SIZE constant.

Source

pub fn create_file(&self, file_num: u32) -> Result<Arc<FileHandle>>

Creates a new log file with the given file number.

Writes the file header with a link to the previous file.

Source

pub fn flip_file(&self) -> Result<u32>

Flips to the next log file.

Called when the current file reaches its maximum size.

Source

pub fn delete_file(&self, file_num: u32) -> Result<()>

Deletes a log file.

Used by the cleaner to remove old log files.

Source

pub fn clear_cache(&self)

Clears the file handle cache.

Source

pub fn truncate_single_file(&self, file_num: u32, offset: u64) -> Result<()>

Physically truncate log file file_num to offset bytes (JE FileManager.truncateSingleFile, FileManager.java:2345). Used at recovery to remove a torn / half-written trailing entry so it cannot be misread on a later scan. Evicts the cached handle first so a stale open handle does not see the old length.

Source

pub fn make_invisible(&self, file_num: u32, offsets: &[u32]) -> Result<()>

Flip the invisible bit (flags 0x10) on each LSN’s log-entry header, in file order, WITHOUT recomputing the checksum.

Port of JE FileManager.makeInvisible (called from RollbackTracker.setInvisible). The invisible bit is excluded from the CRC at read time (cloaked, see LogEntryHeader.turnOffInvisible / log_manager checksum path), so flipping it in place is a single-byte pwrite per entry. The flags byte is at file_offset + FLAGS_OFFSET (offset 5) of each entry.

Caller must force the affected files afterwards for durability (JE RollbackTracker.recoveryEndFsyncInvisible).

Source

pub fn force(&self, file_nums: &[u32]) -> Result<()>

fsync the given set of log files (JE FileManager.force). Used after make_invisible to make the rollback’s invisible bits durable so a crash mid-rollback does not re-apply rolled-back entries.

Source

pub fn truncate_log(&self, file_num: u32, offset: u64) -> Result<()>

Truncate the log at (file_num, offset): truncate file_num to offset and delete every higher-numbered file, in descending order to avoid a log-entry gap (JE FileManager.truncateLog, FileManager.java:2374, SR [#19463]). If offset == 0 the file header itself is gone, so the whole file is deleted too.

Source

pub fn write_buffer_to_file( &self, file_num: u32, data: &[u8], file_offset: u64, ) -> Result<()>

Writes data to the current log file at the given file offset.

writeToFile(). The caller must supply the exact file-level byte offset at which data should be written (i.e. firstLsn.fileOffset in terms). After a successful write the method checks whether the file has grown past max_file_size; if so it calls flip_file() and returns the new file number, otherwise it returns the current one.

§Arguments
  • data - The raw bytes to append (header + payload).
  • file_offset - Byte offset within the file at which to write.
§Returns

The file number that was actually written to. Writes data at file_offset within log file file_num.

JE faithfulness: JE FileManager.writeLogBuffer uses fullBuffer.getFirstLsn() to determine which file to write to, not currentFileNum. This method mirrors that by accepting an explicit file_num parameter so write_dirty and fill_flush_pending can write dirty buffers to the file their first_lsn belongs to.

The auto-flip (check file_len >= max_file_size and call flip_file) has been removed: file flips are managed exclusively by LogManager::log_internal via the flipped flag and get_write_buffer/sync_log_end_and_finish_file. Auto-flip in this method would race with the explicit flip and double-create files.

Source

pub fn write_buffer(&self, data: &[u8], file_offset: u64) -> Result<u32>

Writes data at file_offset within the CURRENT log file.

For new entries written by LogManager::log_internal when the entry is too large for the buffer pool (temp-buffer path). The current file is always correct here because set_last_position has already advanced current_file_num to the file that holds current_lsn.

Callers that write data belonging to a SPECIFIC file (dirty buffer flush in write_dirty / fill_flush_pending) must use write_buffer_to_file instead to avoid writing old data to the wrong file after a flip.

Source

pub fn read_from_file( &self, file_num: u32, offset: u64, buf: &mut [u8], ) -> Result<usize>

Reads bytes from a log file at a given offset.

§Arguments
  • file_num - The log file number to read from.
  • offset - Byte offset within the file.
  • buf - Output buffer; filled with as many bytes as available (may be less than buf.len() at end of file).
§Returns

The number of bytes actually read.

Source

pub fn read_from_file_random( &self, file_num: u32, offset: u64, buf: &mut [u8], ) -> Result<usize>

Reads bytes from a log file at a given offset, counted as a random (point-lookup) read rather than a sequential scan read.

Used by LogManager::read_at_lsn for in-flight log reads.

Source

pub fn get_file_length(&self, file_num: u32) -> Result<u64>

Returns the length of a log file in bytes.

Source

pub fn mmap_file(&self, file_num: u32) -> Result<Mmap>

Memory-maps a log file for read-only sequential access.

Returns a Mmap covering the entire file. The OS handles page-in lazily with automatic sequential read-ahead, eliminating all per-entry pread64 syscalls during recovery scanning.

§Safety

The caller must not hold a mutable reference into the mapped memory while other processes write to the file. During recovery, log files are read-only, making this safe.

Source

pub fn get_io_stats(&self) -> FileManagerIoStats

Returns current I/O statistics for this FileManager.

Source

pub fn sync_log_end_and_finish_file(&self) -> Result<()>

Fsyncs the current log file to stable storage and removes it from the file-handle cache, making the old file handle eligible for GC.

JE faithfulness (Part-3, DRIFT-3/7): mirrors FileManager.syncLogEndAndFinishFile() which calls syncLogEnd() then endOfLog.close(). Called by LogBufferPool.getWriteBuffer when flippedFile=true, under the LWL, BEFORE advanceLsn advances the LSN bookkeeping to the new file. This establishes the JE invariant that the OLD file is durably closed before any entry is written to the NEW file.

References:

  • JE FileManager.syncLogEndAndFinishFile (line 2077)
  • JE LogBufferPool.getWriteBuffer (called after bumpAndWriteDirty when flippedFile=true)
Source

pub fn sync_log_end(&self) -> Result<()>

Fsyncs the current log file to stable storage.

JE: FileManager.syncLogEnd() (called from syncLogEndAndFinishFile).

Source

pub fn close(&self) -> Result<()>

Closes the file manager, releasing all resources.

Trait Implementations§

Source§

impl Drop for FileManager

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

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>,

Source§

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>,

Source§

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.