| Crates.io | jdb_lock |
| lib.rs | jdb_lock |
| version | 0.1.1 |
| created_at | 2025-12-28 17:58:11.7575+00 |
| updated_at | 2025-12-28 17:58:11.7575+00 |
| description | Cross-process file locking for database systems / 数据库系统跨进程文件锁 |
| homepage | https://github.com/js0-site/jdb/tree/main/jdb_lock |
| repository | https://github.com/js0-site/jdb.git |
| max_upload_size | |
| id | 2009211 |
| size | 72,540 |
jdb_lock provides efficient cross-process file locking mechanisms using flock/fcntl system calls. It's designed specifically for database systems to ensure safe concurrent access to WAL (Write-Ahead Log) files while maintaining high performance for frequent operations.
Add this to your Cargo.toml:
[dependencies]
jdb_lock = "0.1.0"
The library implements a layered architecture for file locking:
graph TD
A[WalLock Trait] --> B[Write Lock Implementation]
A --> C[GC Lock Implementation]
A --> D[NoLock Implementation]
B --> E[FileLock Core]
C --> E
C --> F[Auto Cleanup]
E --> G[fd-lock Crate]
G --> H[OS flock/fcntl]
I[Error Module] --> B
I --> C
I --> D
WalLock TraitCommon interface for all WAL file locking implementations:
pub trait WalLock: Default {
fn try_lock(&mut self, path: &Path) -> Result<()>;
}
FileLock (Internal)Internal write lock holder with safe memory management:
Error EnumComprehensive error handling for lock operations:
pub enum Error {
Locked, // File already locked by another process
Io(IoError), // Underlying I/O error
}
Result<T> Type alias for convenient error handling.w::Lock - Write LockProvides exclusive write access to WAL files:
gc::Lock - Garbage Collection LockPrevents concurrent garbage collection on the same WAL:
NoLock - No-op ImplementationLightweight option for scenarios without locking requirements:
use jdb_lock::{w::Lock as WLock, WalLock};
use std::path::Path;
let mut lock = WLock::default();
let path = Path::new("/path/to/wal/file");
match lock.try_lock(path) {
Ok(()) => println!("Lock acquired successfully"),
Err(e) => println!("Failed to acquire lock: {}", e),
}
use jdb_lock::gc::Lock as GcLock;
use std::path::PathBuf;
let lock_path = PathBuf::from("/path/to/lock/file");
match GcLock::try_new(lock_path) {
Ok(gc_lock) => {
// GC operations here
// Lock file automatically cleaned up when gc_lock goes out of scope
}
Err(e) => println!("Failed to acquire GC lock: {}", e),
}
use jdb_lock::{NoLock, WalLock};
use std::path::Path;
let mut lock = NoLock;
let path = Path::new("/path/to/wal/file");
// This always succeeds without actual file locking
lock.try_lock(path).unwrap();
The library follows several key design principles:
fd-lock crate for cross-platform file lockingthiserror for comprehensive error managementaok, compio, log, log_init, static_initjdb_lock/
├── src/
│ ├── lib.rs # Main library entry point and core types
│ ├── error.rs # Error types and result handling
│ ├── gc.rs # Garbage collection lock implementation
│ └── w.rs # Write lock implementation
├── tests/
│ └── main.rs # Test suite and examples
├── readme/
│ ├── en.md # English documentation
│ └── zh.md # Chinese documentation
└── Cargo.toml # Project configuration
The library is optimized for database workloads:
flock/fcntl for maximum efficiencyThe library provides comprehensive error handling:
Error::Locked: Indicates the file is already locked by another processError::Io: Wraps underlying I/O errors from the file systemFile locking has been essential to database systems since the early days of multi-user computing. The concept of using advisory locks through flock originated in BSD Unix and was later adopted by other Unix-like systems.
In database systems, WAL (Write-Ahead Logging) became popular in the 1970s as a recovery mechanism. The challenge of coordinating concurrent access to these log files led to various locking strategies. Modern databases like PostgreSQL and SQLite continue to use similar file-based locking mechanisms.
The jdb_lock library builds on this foundation, providing a Rust-native implementation that respects the established patterns while leveraging Rust's memory safety guarantees. The separation of GC locks from write locks reflects the evolution of database architecture, where garbage collection became a distinct operation requiring its own coordination mechanism.
The use of separate lock files for GC operations (rather than locking the WAL directly) is a pattern seen in many modern databases. This approach allows read operations to continue during maintenance operations, improving overall system availability - a critical requirement for 24/7 services.
This project is an open-source component of js0.site ⋅ Refactoring the Internet Plan.
We are redefining the development paradigm of the Internet in a componentized way. Welcome to follow us:
jdb_lock 使用 flock/fcntl 系统调用提供高效的跨进程文件锁机制。专为数据库系统设计,确保对 WAL(预写日志)文件的安全并发访问,同时保持高频操作的高性能。
在 Cargo.toml 中添加:
[dependencies]
jdb_lock = "0.1.0"
库采用分层架构实现文件锁定:
graph TD
A[WalLock Trait] --> B[写锁实现]
A --> C[GC 锁实现]
A --> D[NoLock 实现]
B --> E[FileLock 核心]
C --> E
C --> F[自动清理]
E --> G[fd-lock Crate]
G --> H[OS flock/fcntl]
I[Error 模块] --> B
I --> C
I --> D
WalLock Trait所有 WAL 文件锁实现的通用接口:
pub trait WalLock: Default {
fn try_lock(&mut self, path: &Path) -> Result<()>;
}
FileLock(内部)内部写锁持有者,具备安全的内存管理:
Error 枚举锁操作的综合错误处理:
pub enum Error {
Locked, // 文件已被其他进程锁定
Io(IoError), // 底层 I/O 错误
}
Result<T> 类型别名,便于错误处理。w::Lock - 写锁提供对 WAL 文件的排他写访问:
gc::Lock - 垃圾回收锁防止对同一 WAL 的并发垃圾回收:
NoLock - 空操作实现无锁定需求场景下的轻量级选项:
use jdb_lock::{w::Lock as WLock, WalLock};
use std::path::Path;
let mut lock = WLock::default();
let path = Path::new("/path/to/wal/file");
match lock.try_lock(path) {
Ok(()) => println!("锁获取成功"),
Err(e) => println!("获取锁失败: {}", e),
}
use jdb_lock::gc::Lock as GcLock;
use std::path::PathBuf;
let lock_path = PathBuf::from("/path/to/lock/file");
match GcLock::try_new(lock_path) {
Ok(gc_lock) => {
// 在这里执行 GC 操作
// gc_lock 离开作用域时锁文件自动清理
}
Err(e) => println!("获取 GC 锁失败: {}", e),
}
use jdb_lock::{NoLock, WalLock};
use std::path::Path;
let mut lock = NoLock;
let path = Path::new("/path/to/wal/file");
// 总是成功,不进行实际文件锁定
lock.try_lock(path).unwrap();
库遵循几个关键设计原则:
fd-lock crate 实现跨平台文件锁定thiserror 提供综合错误管理aok、compio、log、log_init、static_initjdb_lock/
├── src/
│ ├── lib.rs # 主库入口点和核心类型
│ ├── error.rs # 错误类型和结果处理
│ ├── gc.rs # 垃圾回收锁实现
│ └── w.rs # 写锁实现
├── tests/
│ └── main.rs # 测试套件和示例
├── readme/
│ ├── en.md # 英文文档
│ └── zh.md # 中文文档
└── Cargo.toml # 项目配置
库针对数据库工作负载优化:
flock/fcntl 实现最大效率库提供全面的错误处理:
Error::Locked:表示文件已被其他进程锁定Error::Io:包装来自文件系统的底层 I/O 错误文件锁定从多用户计算早期开始就是数据库系统的关键组成部分。通过 flock 使用建议锁的概念起源于 BSD Unix,后来被其他类 Unix 系统采用。
在数据库系统中,WAL(预写日志)在 1970 年代作为恢复机制流行起来。协调对这些日志文件的并发访问挑战导致了各种锁定策略。现代数据库如 PostgreSQL 和 SQLite 继续使用类似的基于文件的锁定机制。
jdb_lock 库在这一基础上构建,提供尊重既定模式的 Rust 原生实现,同时利用 Rust 的内存安全保证。GC 锁与写锁的分离反映了数据库架构的演变,其中垃圾回收成为需要自己协调机制的独立操作。
使用独立锁文件进行 GC 操作(而非直接锁定 WAL)是许多现代数据库中看到的模式。这种方法允许读操作在维护操作期间继续,提高整体系统可用性 - 这是 24/7 服务的关键要求。
本项目为 js0.site ⋅ 重构互联网计划 的开源组件。
我们正在以组件化的方式重新定义互联网的开发范式,欢迎关注: