blkcache
blkcache.server
blkcache.server – userspace read-through cache via nbdkit + nbdfuse.
blkcache.file.device
Device file abstraction with ioctl support.
Device class that extends File with block device operations like sector size detection, device sizing, and rotational status.
BLKGETSIZE64
<linux/fs.h> Get device byte-length
BLKSSZGET
Get block device sector size
Device Objects
class Device(File)
Device file with block device operations.
check
@staticmethod
def check(path: Path) -> bool
Check if this is a block device.
device_size
def device_size() -> int
Get device capacity in bytes using ioctl or fallback methods.
sector_size
@property
@lru_cache(maxsize=1)
def sector_size() -> int
Get device sector size using ioctl.
blkcache.file.cached
Cache file abstraction.
CacheFile wraps another File and provides read-through caching. Opens the backing file in its enter method.
CachedFile Objects
class CachedFile(File)
Passthrough cache that wraps another File instance.
check
@staticmethod
def check(path: Path) -> bool
CacheFile doesn’t check paths - it’s a wrapper.
path
@property
def path() -> Path
Return the backing file’s path.
size
def size() -> int
Get size from backing file.
sector_size
@property
def sector_size() -> int
Get sector size from backing file.
pread
def pread(count: int, offset: int) -> bytes
Read with cache - try cache first, then backing file.
pwrite
def pwrite(data: bytes, offset: int) -> int
Write through to both cache and backing file.
fingerprint
def fingerprint(head: int = 65_536) -> str
Get fingerprint from backing file.
__getattr__
def __getattr__(name)
Delegate unknown attributes to backing file.
blkcache.file.mmapped
Memory-mapped file abstraction.
MappedFile uses mmap for efficient access to regular files. Only works with regular files that support memory mapping.
MMappedFile Objects
class MMappedFile(File)
Memory-mapped file with efficient random access.
check
@staticmethod
def check(path: Path) -> bool
Check if this is a regular file that can be memory-mapped.
pread
def pread(count: int, offset: int) -> bytes
Read count bytes at offset using memory map.
pwrite
def pwrite(data: bytes, offset: int) -> int
Write data at offset using memory map.
size
def size() -> int
Get file size from memory map.
blkcache.file.base
File Objects
class File()
Base file class with position-independent read/write operations.
check
@staticmethod
def check(path: Path) -> bool
Check if this class can handle the given path.
depends
def depends(*files)
Register file dependencies for cascading cleanup.
__getattr__
def __getattr__(name)
Delegate unknown attributes to the underlying file object.
pread
def pread(count: int, offset: int) -> bytes
Read count bytes at offset without changing file position.
pwrite
def pwrite(data: bytes, offset: int) -> int
Write data at offset without changing file position.
size
def size() -> int
Get file size without changing file position.
fingerprint
def fingerprint(head: int = 65_536) -> str
Generate content fingerprint from file header.
blkcache.file.atomic
Atomic file writes for frequently-updated or slowly written files.
AtomicFile prevents corruption of small files that are written often, like ddrescue map files, by writing to “name~” then moving into place.
AtomicFile Objects
class AtomicFile(File)
File with atomic write operations via temporary files.
check
@staticmethod
def check(path: Path) -> bool
Atomic files can handle any regular file path.
blkcache.file.removable
Removable device abstraction with media change detection.
Removable class extends Device with functionality for optical drives, USB drives, and other removable media that can be ejected or changed.
CDROM_GET_BLKSIZE
Get CDROM block size
Removable Objects
class Removable(Device)
Removable device with media change detection.
check
@staticmethod
def check(path: Path) -> bool
Check if this is a removable block device.
sector_size
@property
@lru_cache(maxsize=1)
def sector_size() -> int
Get sector size with CDROM-specific ioctl support.
watch_for_changes
def watch_for_changes(stop_event: threading.Event,
callback=None,
logger=None) -> None
Monitor device for media changes.
Arguments:
stop_event
- Threading event to signal when to stop monitoringcallback
- Function to call on media change (old_id, new_id)logger
- Logger for debug messages
blkcache.file
File abstraction package with automatic type detection.
Provides File, Device, and Removable classes with a detect() factory function that automatically chooses the appropriate class for a given path.
detect
def detect(path: Path | str) -> Type[File]
Return the most specific file class that can handle this path.
Checks classes in order of specificity: Removable -> Device -> File Returns the first class whose check() method returns True.
blkcache.file.filemap
File mapping for tracking block/sector status.
Pure data structure for tracking status of byte ranges without any file format dependencies.
STATUS_OK
Successfully read
STATUS_ERROR
Read error
STATUS_UNTRIED
Not tried yet
STATUS_TRIMMED
Trimmed (not tried because of read error)
STATUS_SLOW
Non-trimmed, non-scraped (slow reads)
STATUS_SCRAPED
Non-trimmed, scraped (slow reads completed)
CACHED
Have data
UNCACHED
Need data
ERROR
Can’t get data
STATUSES
All valid statuses
FileMap Objects
class FileMap()
Tracks status of byte ranges using efficient transition-based representation.
Pure data structure with no file format dependencies. Uses slice notation: filemap[start:end] = status
__init__
def __init__(size: int)
Initialize with device/file size.
__setitem__
def __setitem__(key, status)
Set status for range using slice notation: filemap[start:end] = status
__getitem__
def __getitem__(key)
Get status for range using slice notation: filemap[start:end] returns transitions
pos
@property
def pos() -> int
Current position - first untried byte.
status
@property
def status() -> str
Current status - highest priority status found in transitions.
blkcache.backend
nbdkit Python backend integration for block-level device caching.
This module serves as the bridge between nbdkit and our file abstraction layer. It handles the “outside” config (nbdkit parameters) while delegating file operations to the composed file chain.
lookup
def lookup(attr: str, handle: int, table=TABLE)
Generic attribute lookup for dispatch.
open_file_context
def open_file_context(path: Path, mode: str)
Generator to manage file lifecycle.
config
def config(key: str, val: str) -> None
Stores device, cache paths and parses metadata key-value pairs.
config_complete
def config_complete() -> None
Validates required parameters.
open
def open(_readonly: bool) -> int
Opens device and returns handle ID.
get_size
def get_size(h: int) -> int
Get file size.
pread
def pread(h: int, count: int, offset: int) -> bytes
Read data at offset.
close
def close(h: int) -> None
Close file handle.
blkcache.ddrescue
ddrescue file format loading and saving.
Functions to read/write ddrescue-compatible mapfiles with comments, config, and FileMap data.
iter_filemap_ranges
def iter_filemap_ranges(filemap: FileMap)
Iterate over FileMap transitions yielding (pos, size, status) tuples.
load
def load(file, comments: List[str], filemap: FileMap,
config: Dict[str, str]) -> None
Load ddrescue mapfile from file-like object, updating provided containers.
save
def save(file, comments: List[str], filemap: FileMap,
config: Dict[str, str]) -> None
Save ddrescue mapfile to file-like object from provided containers.
parse_status
def parse_status(line: str) -> tuple[int, int, str]
Parse a status line returning (start, size, status).
blkcache.main
blkcache – CLI entry-point.