use super::SEG_MAGIC;
use core::num::NonZeroU32;
use crate::*;
const SEG_MATURE_TIME: Duration = Duration::from_secs(20);
#[derive(Debug)]
#[repr(C)]
pub struct SegmentHeader {
id: NonZeroU32,
write_offset: i32,
live_bytes: i32,
live_items: i32,
prev_seg: Option<NonZeroU32>,
next_seg: Option<NonZeroU32>,
create_at: Instant,
merge_at: Instant,
ttl: u32,
accessible: bool,
evictable: bool,
pool: SegmentPool,
_pad: [u8; 24],
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
pub(crate) enum SegmentPool {
Main = 0,
Admission = 1,
}
impl SegmentHeader {
pub fn new(id: NonZeroU32) -> Self {
let now = Instant::now();
Self {
id,
write_offset: 0,
live_bytes: 0,
live_items: 0,
prev_seg: None,
next_seg: None,
create_at: now,
ttl: 0,
merge_at: now,
accessible: false,
evictable: false,
pool: SegmentPool::Main,
_pad: [0; 24],
}
}
pub fn init(&mut self) {
assert!(!self.accessible());
assert!(!self.evictable());
let now = Instant::now();
self.reset();
self.prev_seg = None;
self.next_seg = None;
self.live_items = 0;
self.create_at = now;
self.merge_at = now;
self.accessible = true;
}
pub fn reset(&mut self) {
let offset = if cfg!(feature = "magic") {
std::mem::size_of_val(&SEG_MAGIC) as i32
} else {
0
};
self.write_offset = offset;
self.live_bytes = offset;
}
#[inline]
pub fn id(&self) -> NonZeroU32 {
self.id
}
#[inline]
pub fn write_offset(&self) -> i32 {
self.write_offset
}
#[inline]
pub fn set_write_offset(&mut self, bytes: i32) {
self.write_offset = bytes;
}
#[inline]
pub fn incr_write_offset(&mut self, bytes: i32) -> i32 {
let prev = self.write_offset;
self.write_offset += bytes;
prev
}
#[inline]
pub fn accessible(&self) -> bool {
self.accessible
}
#[inline]
pub fn set_accessible(&mut self, accessible: bool) {
self.accessible = accessible;
}
#[inline]
pub fn evictable(&self) -> bool {
self.evictable
}
#[inline]
pub fn set_evictable(&mut self, evictable: bool) {
self.evictable = evictable;
}
#[inline]
pub fn live_items(&self) -> i32 {
self.live_items
}
#[inline]
pub fn incr_live_items(&mut self) {
self.live_items += 1;
}
#[inline]
pub fn decr_live_items(&mut self) {
self.live_items -= 1;
}
#[inline]
pub fn ttl(&self) -> Duration {
Duration::from_secs(self.ttl)
}
#[inline]
pub fn set_ttl(&mut self, ttl: Duration) {
self.ttl = ttl.as_secs();
}
#[inline]
pub fn live_bytes(&self) -> i32 {
self.live_bytes
}
#[inline]
pub fn incr_live_bytes(&mut self, bytes: i32) -> i32 {
let prev = self.live_bytes;
self.live_bytes += bytes;
prev
}
#[inline]
pub fn decr_live_bytes(&mut self, bytes: i32) -> i32 {
let prev = self.live_bytes;
self.live_bytes -= bytes;
prev
}
#[inline]
pub fn prev_seg(&self) -> Option<NonZeroU32> {
self.prev_seg
}
#[inline]
pub fn set_prev_seg(&mut self, id: Option<NonZeroU32>) {
self.prev_seg = id;
}
#[inline]
pub fn next_seg(&self) -> Option<NonZeroU32> {
self.next_seg
}
#[inline]
pub fn set_next_seg(&mut self, id: Option<NonZeroU32>) {
self.next_seg = id;
}
#[inline]
pub fn create_at(&self) -> Instant {
self.create_at
}
#[inline]
pub fn mark_created(&mut self) {
self.create_at = Instant::now();
}
#[inline]
pub fn merge_at(&self) -> Instant {
self.merge_at
}
#[inline]
pub fn mark_merged(&mut self) {
self.merge_at = Instant::now();
}
#[inline]
pub fn pool(&self) -> SegmentPool {
self.pool
}
#[inline]
pub fn set_pool(&mut self, pool: SegmentPool) {
self.pool = pool;
}
#[inline]
pub fn can_evict(&self) -> bool {
self.evictable()
&& self.next_seg().is_some()
&& (self.create_at() + self.ttl()) >= (Instant::now() + SEG_MATURE_TIME)
}
}