proxmox-backup/pbs-config/src/config_version_cache.rs

122 lines
3.4 KiB
Rust
Raw Normal View History

use std::path::Path;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::mem::MaybeUninit;
use anyhow::{bail, Error};
use once_cell::sync::OnceCell;
use nix::sys::stat::Mode;
use proxmox_sys::fs::{create_path, CreateOptions};
// openssl::sha::sha256(b"Proxmox Backup ConfigVersionCache v1.0")[0..8];
pub const PROXMOX_BACKUP_CONFIG_VERSION_CACHE_MAGIC_1_0: [u8; 8] = [25, 198, 168, 230, 154, 132, 143, 131];
const FILE_PATH: &str = pbs_buildcfg::rundir!("/shmem/config-versions");
use proxmox_shared_memory::*;
#[derive(Debug)]
#[repr(C)]
struct ConfigVersionCacheData {
magic: [u8; 8],
// User (user.cfg) cache generation/version.
user_cache_generation: AtomicUsize,
// Traffic control (traffic-control.cfg) generation/version.
traffic_control_generation: AtomicUsize,
// Add further atomics here (and reduce padding size)
padding: [u8; 4096 - 3*8],
}
impl Init for ConfigVersionCacheData {
fn initialize(this: &mut MaybeUninit<Self>) {
unsafe {
let me = &mut *this.as_mut_ptr();
me.magic = PROXMOX_BACKUP_CONFIG_VERSION_CACHE_MAGIC_1_0;
}
}
fn check_type_magic(this: &MaybeUninit<Self>) -> Result<(), Error> {
unsafe {
let me = &*this.as_ptr();
if me.magic != PROXMOX_BACKUP_CONFIG_VERSION_CACHE_MAGIC_1_0 {
bail!("ConfigVersionCache: wrong magic number");
}
Ok(())
}
}
}
pub struct ConfigVersionCache {
shmem: SharedMemory<ConfigVersionCacheData>
}
static INSTANCE: OnceCell<Arc< ConfigVersionCache>> = OnceCell::new();
impl ConfigVersionCache {
/// Open the memory based communication channel singleton.
pub fn new() -> Result<Arc<Self>, Error> {
INSTANCE.get_or_try_init(Self::open).map(Arc::clone)
}
// Actual work of `new`:
fn open() -> Result<Arc<Self>, Error> {
let user = crate::backup_user()?;
let dir_opts = CreateOptions::new()
.perm(Mode::from_bits_truncate(0o770))
.owner(user.uid)
.group(user.gid);
let file_path = Path::new(FILE_PATH);
let dir_path = file_path.parent().unwrap();
create_path(
dir_path,
Some(dir_opts.clone()),
Some(dir_opts))?;
let file_opts = CreateOptions::new()
.perm(Mode::from_bits_truncate(0o660))
.owner(user.uid)
.group(user.gid);
let shmem: SharedMemory<ConfigVersionCacheData> =
SharedMemory::open(file_path, file_opts)?;
Ok(Arc::new(Self { shmem }))
}
/// Returns the user cache generation number.
pub fn user_cache_generation(&self) -> usize {
self.shmem.data()
.user_cache_generation.load(Ordering::Acquire)
}
/// Increase the user cache generation number.
pub fn increase_user_cache_generation(&self) {
self.shmem.data()
.user_cache_generation
.fetch_add(1, Ordering::AcqRel);
}
/// Returns the traffic control generation number.
pub fn traffic_control_generation(&self) -> usize {
self.shmem.data()
.traffic_control_generation.load(Ordering::Acquire)
}
/// Increase the traffic control generation number.
pub fn increase_traffic_control_generation(&self) {
self.shmem.data()
.traffic_control_generation
.fetch_add(1, Ordering::AcqRel);
}
}