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: AtomicU64Number of log files opened (cache miss = new file open).
n_sequential_reads: AtomicU64Number of sequential read calls.
n_sequential_read_bytes: AtomicU64Total bytes read sequentially.
n_sequential_writes: AtomicU64Number of sequential write calls.
n_sequential_write_bytes: AtomicU64Total bytes written sequentially.
n_random_reads: AtomicU64Number of random (point-lookup) read operations.
n_random_read_bytes: AtomicU64Total bytes from random read operations.
Implementations§
Source§impl FileManager
impl FileManager
Sourcepub fn new(
env_dir: impl AsRef<Path>,
read_only: bool,
max_file_size: u64,
cache_size: usize,
) -> Result<Self>
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 directoryread_only- Whether to open in read-only modemax_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.
Sourcepub fn list_file_numbers(&self) -> Result<Vec<u32>>
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.
Sourcepub fn get_first_file_num(&self) -> Result<Option<u32>>
pub fn get_first_file_num(&self) -> Result<Option<u32>>
Returns the first (lowest numbered) file, or None if no files exist.
Sourcepub fn get_last_file_num(&self) -> Result<Option<u32>>
pub fn get_last_file_num(&self) -> Result<Option<u32>>
Returns the last (highest numbered) file, or None if no files exist.
Sourcepub fn is_read_only(&self) -> bool
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.
pub fn max_file_size(&self) -> u64
Sourcepub fn total_log_size(&self) -> Result<u64>
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.
Sourcepub fn disk_free_space(&self) -> Result<u64>
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.
Sourcepub fn get_current_file_num(&self) -> u32
pub fn get_current_file_num(&self) -> u32
Returns the current file number being written to.
Sourcepub fn get_next_available_lsn(&self) -> Lsn
pub fn get_next_available_lsn(&self) -> Lsn
Returns the next available LSN for writing.
Sourcepub fn get_last_used_lsn(&self) -> Lsn
pub fn get_last_used_lsn(&self) -> Lsn
Returns the last used LSN.
Sourcepub fn set_last_position(&self, next_available_lsn: Lsn, last_used_lsn: Lsn)
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.
Sourcepub fn get_file_handle(&self, file_num: u32) -> Result<Arc<FileHandle>>
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.
Sourcepub fn file_header_size_for(&self, file_num: u32) -> Result<usize>
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.
Sourcepub fn create_file(&self, file_num: u32) -> Result<Arc<FileHandle>>
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.
Sourcepub fn flip_file(&self) -> Result<u32>
pub fn flip_file(&self) -> Result<u32>
Flips to the next log file.
Called when the current file reaches its maximum size.
Sourcepub fn delete_file(&self, file_num: u32) -> Result<()>
pub fn delete_file(&self, file_num: u32) -> Result<()>
Deletes a log file.
Used by the cleaner to remove old log files.
Sourcepub fn clear_cache(&self)
pub fn clear_cache(&self)
Clears the file handle cache.
Sourcepub fn truncate_single_file(&self, file_num: u32, offset: u64) -> Result<()>
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.
Sourcepub fn make_invisible(&self, file_num: u32, offsets: &[u32]) -> Result<()>
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).
Sourcepub fn force(&self, file_nums: &[u32]) -> Result<()>
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.
Sourcepub fn truncate_log(&self, file_num: u32, offset: u64) -> Result<()>
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.
Sourcepub fn write_buffer_to_file(
&self,
file_num: u32,
data: &[u8],
file_offset: u64,
) -> Result<()>
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.
Sourcepub fn write_buffer(&self, data: &[u8], file_offset: u64) -> Result<u32>
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.
Sourcepub fn read_from_file_random(
&self,
file_num: u32,
offset: u64,
buf: &mut [u8],
) -> Result<usize>
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.
Sourcepub fn get_file_length(&self, file_num: u32) -> Result<u64>
pub fn get_file_length(&self, file_num: u32) -> Result<u64>
Returns the length of a log file in bytes.
Sourcepub fn mmap_file(&self, file_num: u32) -> Result<Mmap>
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.
Sourcepub fn get_io_stats(&self) -> FileManagerIoStats
pub fn get_io_stats(&self) -> FileManagerIoStats
Returns current I/O statistics for this FileManager.
Sourcepub fn sync_log_end_and_finish_file(&self) -> Result<()>
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 afterbumpAndWriteDirtywhenflippedFile=true)
Sourcepub fn sync_log_end(&self) -> Result<()>
pub fn sync_log_end(&self) -> Result<()>
Fsyncs the current log file to stable storage.
JE: FileManager.syncLogEnd() (called from syncLogEndAndFinishFile).