jdb_alloc/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2
3//! Aligned memory allocator & Raw buffer wrapper for Direct I/O
4//! Direct I/O 对齐内存分配器与原始缓冲区包装器
5
6mod error;
7
8use std::{
9  alloc::{Layout, LayoutError, alloc, alloc_zeroed, dealloc, handle_alloc_error},
10  fmt::{Debug, Formatter, Result as FmtResult},
11  mem::ManuallyDrop,
12  ops::{Deref, DerefMut},
13  ptr::{NonNull, copy_nonoverlapping},
14  slice::{from_raw_parts, from_raw_parts_mut},
15};
16
17use Error::{AllocFailed, Overflow};
18use compio_buf::{IoBuf, IoBufMut, SetBufInit};
19pub use error::{Error, Result};
20
21/// Page size 4KB / 页大小
22pub const PAGE_SIZE: usize = 4096;
23
24/// Direct I/O alignment (must be power of 2) / 对齐要求(必须是2的幂)
25pub const ALIGNMENT: usize = 4096;
26
27/// Mask for alignment checks / 对齐检查掩码
28const ALIGN_MASK: usize = ALIGNMENT - 1;
29
30// --- Layout Cache ---
31
32static PAGE_LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(PAGE_SIZE, ALIGNMENT) };
33
34/// Get layout for given size / 获取指定大小的布局
35#[inline(always)]
36fn layout(size: usize) -> std::result::Result<Layout, LayoutError> {
37  if size == PAGE_SIZE {
38    Ok(PAGE_LAYOUT)
39  } else {
40    Layout::from_size_align(size, ALIGNMENT)
41  }
42}
43
44/// Get layout unchecked (for Drop/Clone where cap is known valid)
45/// 无检查获取布局(用于 Drop/Clone,cap 已知有效)
46#[inline(always)]
47fn layout_unchecked(cap: usize) -> Layout {
48  if cap == PAGE_SIZE {
49    PAGE_LAYOUT
50  } else {
51    unsafe { Layout::from_size_align_unchecked(cap, ALIGNMENT) }
52  }
53}
54
55// ============================================================================
56// AlignedBuf (Owning)
57// ============================================================================
58
59/// Aligned buffer for Direct I/O (Owns memory)
60/// 拥有所有权的对齐缓冲区,Drop 时释放内存
61pub struct AlignedBuf {
62  ptr: NonNull<u8>,
63  len: usize,
64  cap: usize,
65}
66
67unsafe impl Send for AlignedBuf {}
68unsafe impl Sync for AlignedBuf {}
69
70impl AlignedBuf {
71  /// Create with capacity (uninitialized memory)
72  /// 创建指定容量(未初始化内存)
73  #[inline]
74  pub fn with_cap(cap: usize) -> Result<Self> {
75    let cap = cap.max(PAGE_SIZE);
76    let lo = layout(cap)?;
77    let ptr = unsafe { alloc(lo) };
78    let ptr = NonNull::new(ptr).ok_or(AllocFailed)?;
79    Ok(Self { ptr, len: 0, cap })
80  }
81
82  /// Create zeroed buffer (OS optimized zero pages)
83  /// 创建零初始化缓冲区(OS 优化零页)
84  #[inline]
85  pub fn zeroed(size: usize) -> Result<Self> {
86    let cap = size.max(PAGE_SIZE);
87    let lo = layout(cap)?;
88    let ptr = unsafe { alloc_zeroed(lo) };
89    let ptr = NonNull::new(ptr).ok_or(AllocFailed)?;
90    Ok(Self {
91      ptr,
92      len: size,
93      cap,
94    })
95  }
96
97  /// Create one page (4KB, uses cached layout)
98  /// 创建单页(使用缓存 Layout)
99  #[inline]
100  pub fn page() -> Result<Self> {
101    let ptr = unsafe { alloc_zeroed(PAGE_LAYOUT) };
102    let ptr = NonNull::new(ptr).ok_or(AllocFailed)?;
103    Ok(Self {
104      ptr,
105      len: PAGE_SIZE,
106      cap: PAGE_SIZE,
107    })
108  }
109
110  /// Slice into chunks for Buffer Pool Arena initialization
111  /// 切分为多个 RawIoBuf,用于 Buffer Pool Arena 初始化
112  /// # Safety
113  /// AlignedBuf must outlive all returned RawIoBufs
114  pub unsafe fn slice_into_raws(&self, chunk: usize) -> impl Iterator<Item = RawIoBuf> + '_ {
115    debug_assert!(
116      chunk > 0 && (chunk & ALIGN_MASK) == 0,
117      "chunk alignment mismatch"
118    );
119    let count = self.cap / chunk;
120    let base = self.ptr.as_ptr();
121    (0..count).map(move |i| unsafe { RawIoBuf::new(base.add(i * chunk), chunk) })
122  }
123
124  /// Convert to RawIoBuf for zero-copy I/O
125  /// 转为 RawIoBuf 进行零拷贝 I/O
126  /// # Safety
127  /// Caller must ensure `AlignedBuf` outlives the I/O operation
128  #[inline(always)]
129  pub unsafe fn as_raw(&mut self) -> RawIoBuf {
130    unsafe { RawIoBuf::new(self.ptr.as_ptr(), self.cap).with_len(self.len) }
131  }
132
133  /// Get RawIoBuf view from shared reference
134  /// 从共享引用获取 RawIoBuf 视图
135  /// # Safety
136  /// Caller must ensure synchronization via latches/locks
137  #[inline(always)]
138  pub unsafe fn as_raw_view(&self) -> RawIoBuf {
139    unsafe { RawIoBuf::new(self.ptr.as_ptr(), self.cap).with_len(self.len) }
140  }
141
142  /// Deconstruct into raw parts (leak memory)
143  /// 解构为原始部分(放弃所有权,不释放内存)
144  #[inline(always)]
145  pub fn into_raw_parts(self) -> (NonNull<u8>, usize, usize) {
146    let me = ManuallyDrop::new(self);
147    (me.ptr, me.len, me.cap)
148  }
149
150  /// Reconstruct from raw parts
151  /// 从原始部分重建
152  /// # Safety
153  /// Must be created from `into_raw_parts` with same allocator
154  #[inline(always)]
155  pub unsafe fn from_raw_parts(ptr: NonNull<u8>, len: usize, cap: usize) -> Self {
156    Self { ptr, len, cap }
157  }
158
159  #[inline(always)]
160  pub fn len(&self) -> usize {
161    self.len
162  }
163
164  #[inline(always)]
165  pub fn cap(&self) -> usize {
166    self.cap
167  }
168
169  #[inline(always)]
170  pub fn is_empty(&self) -> bool {
171    self.len == 0
172  }
173
174  #[inline(always)]
175  pub fn as_ptr(&self) -> *const u8 {
176    self.ptr.as_ptr()
177  }
178
179  #[inline(always)]
180  pub fn as_mut_ptr(&mut self) -> *mut u8 {
181    self.ptr.as_ptr()
182  }
183
184  #[inline(always)]
185  pub fn clear(&mut self) {
186    self.len = 0;
187  }
188
189  /// Truncate to length / 截断到指定长度
190  #[inline(always)]
191  pub fn truncate(&mut self, len: usize) {
192    if len < self.len {
193      self.len = len;
194    }
195  }
196
197  /// Set length
198  /// # Safety
199  /// Caller must ensure data is initialized up to `len`
200  #[inline(always)]
201  pub unsafe fn set_len(&mut self, len: usize) {
202    debug_assert!(len <= self.cap);
203    self.len = len;
204  }
205
206  /// Try clone, returns error on OOM instead of panic
207  /// 尝试克隆,OOM 时返回错误而非 panic
208  pub fn try_clone(&self) -> Result<Self> {
209    let lo = layout(self.cap)?;
210    let ptr = unsafe { alloc(lo) };
211    let ptr = NonNull::new(ptr).ok_or(AllocFailed)?;
212    unsafe { copy_nonoverlapping(self.ptr.as_ptr(), ptr.as_ptr(), self.len) };
213    Ok(Self {
214      ptr,
215      len: self.len,
216      cap: self.cap,
217    })
218  }
219
220  /// Extend from slice / 从切片扩展
221  #[inline]
222  pub fn extend(&mut self, data: &[u8]) -> Result<()> {
223    let new_len = self.len + data.len();
224    if new_len > self.cap {
225      return Err(Overflow(new_len, self.cap));
226    }
227    unsafe { copy_nonoverlapping(data.as_ptr(), self.ptr.as_ptr().add(self.len), data.len()) };
228    self.len = new_len;
229    Ok(())
230  }
231}
232
233impl Drop for AlignedBuf {
234  fn drop(&mut self) {
235    unsafe { dealloc(self.ptr.as_ptr(), layout_unchecked(self.cap)) }
236  }
237}
238
239impl Deref for AlignedBuf {
240  type Target = [u8];
241
242  #[inline]
243  fn deref(&self) -> &[u8] {
244    unsafe { from_raw_parts(self.ptr.as_ptr(), self.len) }
245  }
246}
247
248impl DerefMut for AlignedBuf {
249  #[inline]
250  fn deref_mut(&mut self) -> &mut [u8] {
251    unsafe { from_raw_parts_mut(self.ptr.as_ptr(), self.len) }
252  }
253}
254
255impl AsRef<[u8]> for AlignedBuf {
256  #[inline]
257  fn as_ref(&self) -> &[u8] {
258    self
259  }
260}
261
262impl AsMut<[u8]> for AlignedBuf {
263  #[inline]
264  fn as_mut(&mut self) -> &mut [u8] {
265    self
266  }
267}
268
269impl Clone for AlignedBuf {
270  fn clone(&self) -> Self {
271    self
272      .try_clone()
273      .unwrap_or_else(|_| handle_alloc_error(layout_unchecked(self.cap)))
274  }
275}
276
277impl Debug for AlignedBuf {
278  fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
279    f.debug_struct("AlignedBuf")
280      .field("len", &self.len)
281      .field("cap", &self.cap)
282      .finish()
283  }
284}
285
286// --- Compio Traits for AlignedBuf ---
287
288unsafe impl IoBuf for AlignedBuf {
289  #[inline(always)]
290  fn as_buf_ptr(&self) -> *const u8 {
291    self.ptr.as_ptr()
292  }
293
294  #[inline(always)]
295  fn buf_len(&self) -> usize {
296    self.len
297  }
298
299  #[inline(always)]
300  fn buf_capacity(&self) -> usize {
301    self.cap
302  }
303}
304
305unsafe impl IoBufMut for AlignedBuf {
306  #[inline(always)]
307  fn as_buf_mut_ptr(&mut self) -> *mut u8 {
308    self.ptr.as_ptr()
309  }
310}
311
312impl SetBufInit for AlignedBuf {
313  #[inline(always)]
314  unsafe fn set_buf_init(&mut self, len: usize) {
315    self.len = len;
316  }
317}
318
319// ============================================================================
320// RawIoBuf (Non-owning, Copy)
321// ============================================================================
322
323/// Raw I/O buffer (Non-owning, Copy)
324/// 原始 I/O 缓冲区(不持有所有权,可复制)
325///
326/// For Buffer Pool Arena mode. Implements `Copy` for ergonomic async IO.
327/// 用于 Buffer Pool Arena 模式,实现 `Copy` 便于异步 IO
328#[repr(C)]
329#[derive(Clone, Copy)]
330pub struct RawIoBuf {
331  ptr: *mut u8,
332  len: usize,
333  cap: usize,
334}
335
336// SAFETY: Caller must ensure synchronized access when sharing across threads
337// 调用者需确保跨线程访问时的同步(如 Buffer Pool Latch)
338unsafe impl Send for RawIoBuf {}
339unsafe impl Sync for RawIoBuf {}
340
341impl RawIoBuf {
342  /// Create new raw buffer wrapper
343  /// # Safety
344  /// ptr must be valid and aligned for Direct I/O
345  #[inline(always)]
346  pub const unsafe fn new(ptr: *mut u8, cap: usize) -> Self {
347    Self { ptr, len: 0, cap }
348  }
349
350  /// Set length (chainable) / 设置长度(链式调用)
351  #[inline(always)]
352  pub const fn with_len(mut self, len: usize) -> Self {
353    self.len = len;
354    self
355  }
356
357  /// Create from raw parts / 从原始部分创建
358  /// # Safety
359  /// ptr must be valid and aligned for Direct I/O
360  #[inline(always)]
361  pub const unsafe fn from_raw_parts(ptr: NonNull<u8>, len: usize, cap: usize) -> Self {
362    Self {
363      ptr: ptr.as_ptr(),
364      len,
365      cap,
366    }
367  }
368
369  /// Create from mutable slice / 从可变切片创建
370  #[inline(always)]
371  pub fn from_slice(slice: &mut [u8]) -> Self {
372    Self {
373      ptr: slice.as_mut_ptr(),
374      len: slice.len(),
375      cap: slice.len(),
376    }
377  }
378
379  /// Slice for reading (len = 0, waiting for IO to fill)
380  /// 切片用于读取(len = 0,等待 IO 填充)
381  /// # Safety
382  /// 1. `offset + len` must not exceed capacity
383  /// 2. `offset` must be aligned for Direct I/O
384  #[inline]
385  pub unsafe fn slice(self, offset: usize, len: usize) -> Self {
386    debug_assert!(offset + len <= self.cap, "slice out of bounds");
387    debug_assert!(
388      (self.ptr as usize + offset) & ALIGN_MASK == 0,
389      "slice not aligned"
390    );
391    Self {
392      ptr: unsafe { self.ptr.add(offset) },
393      len: 0,
394      cap: len,
395    }
396  }
397
398  /// Slice for writing (len = cap, contains data)
399  /// 切片用于写入(len = cap,包含待写数据)
400  /// # Safety
401  /// 1. `offset + len` must not exceed capacity
402  /// 2. `offset` must be aligned for Direct I/O
403  #[inline]
404  pub unsafe fn slice_data(self, offset: usize, len: usize) -> Self {
405    debug_assert!(offset + len <= self.cap, "slice out of bounds");
406    debug_assert!(
407      (self.ptr as usize + offset) & ALIGN_MASK == 0,
408      "slice not aligned"
409    );
410    Self {
411      ptr: unsafe { self.ptr.add(offset) },
412      len,
413      cap: len,
414    }
415  }
416
417  /// Slice unchecked (extreme performance) / 无检查切片(极致性能)
418  /// # Safety
419  /// Caller MUST ensure bounds and alignment
420  #[inline(always)]
421  pub unsafe fn slice_unchecked(self, offset: usize, len: usize) -> Self {
422    Self {
423      ptr: unsafe { self.ptr.add(offset) },
424      len: 0,
425      cap: len,
426    }
427  }
428
429  #[inline(always)]
430  pub const fn len(&self) -> usize {
431    self.len
432  }
433
434  #[inline(always)]
435  pub const fn cap(&self) -> usize {
436    self.cap
437  }
438
439  #[inline(always)]
440  pub const fn is_empty(&self) -> bool {
441    self.len == 0
442  }
443
444  #[inline(always)]
445  pub const fn as_ptr(&self) -> *const u8 {
446    self.ptr
447  }
448
449  #[inline(always)]
450  pub const fn as_mut_ptr(&self) -> *mut u8 {
451    self.ptr
452  }
453
454  #[inline(always)]
455  pub fn as_slice(&self) -> &[u8] {
456    unsafe { from_raw_parts(self.ptr, self.len) }
457  }
458
459  #[inline(always)]
460  pub fn as_mut_slice(&mut self) -> &mut [u8] {
461    unsafe { from_raw_parts_mut(self.ptr, self.len) }
462  }
463
464  /// Set length
465  /// # Safety
466  /// Caller must ensure data is initialized up to `len`
467  #[inline(always)]
468  pub unsafe fn set_len(&mut self, len: usize) {
469    debug_assert!(len <= self.cap);
470    self.len = len;
471  }
472}
473
474impl Debug for RawIoBuf {
475  fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
476    f.debug_struct("RawIoBuf")
477      .field("ptr", &self.ptr)
478      .field("len", &self.len)
479      .field("cap", &self.cap)
480      .finish()
481  }
482}
483
484// --- Compio Traits for RawIoBuf ---
485
486unsafe impl IoBuf for RawIoBuf {
487  #[inline(always)]
488  fn as_buf_ptr(&self) -> *const u8 {
489    self.ptr
490  }
491
492  #[inline(always)]
493  fn buf_len(&self) -> usize {
494    self.len
495  }
496
497  #[inline(always)]
498  fn buf_capacity(&self) -> usize {
499    self.cap
500  }
501}
502
503unsafe impl IoBufMut for RawIoBuf {
504  #[inline(always)]
505  fn as_buf_mut_ptr(&mut self) -> *mut u8 {
506    self.ptr
507  }
508}
509
510impl SetBufInit for RawIoBuf {
511  #[inline(always)]
512  unsafe fn set_buf_init(&mut self, len: usize) {
513    self.len = len;
514  }
515}