move tools::process_locker to pbs-tools

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2021-07-07 14:15:42 +02:00
parent 95f9d67ce9
commit 83771aa037
3 changed files with 44 additions and 24 deletions

View File

@ -3,6 +3,7 @@ pub mod format;
pub mod fs; pub mod fs;
pub mod json; pub mod json;
pub mod nom; pub mod nom;
pub mod process_locker;
pub mod str; pub mod str;
mod command; mod command;

View File

@ -7,11 +7,11 @@
//! the timestamp for the oldest open lock with //! the timestamp for the oldest open lock with
//! `oldest_shared_lock()`. //! `oldest_shared_lock()`.
use anyhow::{bail, Error};
use std::sync::{Arc, Mutex};
use std::os::unix::io::AsRawFd;
use std::collections::HashMap; use std::collections::HashMap;
use std::os::unix::io::AsRawFd;
use std::sync::{Arc, Mutex};
use anyhow::{bail, Error};
// fixme: use F_OFD_ locks when implemented with nix::fcntl // fixme: use F_OFD_ locks when implemented with nix::fcntl
@ -34,16 +34,17 @@ pub struct ProcessLockSharedGuard {
locker: Arc<Mutex<ProcessLocker>>, locker: Arc<Mutex<ProcessLocker>>,
} }
impl Drop for ProcessLockSharedGuard { impl Drop for ProcessLockSharedGuard {
fn drop(&mut self) { fn drop(&mut self) {
let mut data = self.locker.lock().unwrap(); let mut data = self.locker.lock().unwrap();
if data.writers == 0 { panic!("unexpected ProcessLocker state"); } if data.writers == 0 {
panic!("unexpected ProcessLocker state");
}
data.shared_guard_list.remove(&self.guard_id); data.shared_guard_list.remove(&self.guard_id);
if data.writers == 1 && !data.exclusive { if data.writers == 1 && !data.exclusive {
let op = libc::flock { let op = libc::flock {
l_type: libc::F_UNLCK as i16, l_type: libc::F_UNLCK as i16,
l_whence: libc::SEEK_SET as i16, l_whence: libc::SEEK_SET as i16,
@ -52,7 +53,9 @@ impl Drop for ProcessLockSharedGuard {
l_pid: 0, l_pid: 0,
}; };
if let Err(err) = nix::fcntl::fcntl(data.file.as_raw_fd(), nix::fcntl::FcntlArg::F_SETLKW(&op)) { if let Err(err) =
nix::fcntl::fcntl(data.file.as_raw_fd(), nix::fcntl::FcntlArg::F_SETLKW(&op))
{
panic!("unable to drop writer lock - {}", err); panic!("unable to drop writer lock - {}", err);
} }
} }
@ -69,13 +72,19 @@ pub struct ProcessLockExclusiveGuard {
locker: Arc<Mutex<ProcessLocker>>, locker: Arc<Mutex<ProcessLocker>>,
} }
impl Drop for ProcessLockExclusiveGuard { impl Drop for ProcessLockExclusiveGuard {
fn drop(&mut self) { fn drop(&mut self) {
let mut data = self.locker.lock().unwrap(); let mut data = self.locker.lock().unwrap();
if !data.exclusive { panic!("unexpected ProcessLocker state"); } if !data.exclusive {
panic!("unexpected ProcessLocker state");
}
let ltype = if data.writers != 0 { libc::F_RDLCK } else { libc::F_UNLCK }; let ltype = if data.writers != 0 {
libc::F_RDLCK
} else {
libc::F_UNLCK
};
let op = libc::flock { let op = libc::flock {
l_type: ltype as i16, l_type: ltype as i16,
l_whence: libc::SEEK_SET as i16, l_whence: libc::SEEK_SET as i16,
@ -84,7 +93,9 @@ impl Drop for ProcessLockExclusiveGuard {
l_pid: 0, l_pid: 0,
}; };
if let Err(err) = nix::fcntl::fcntl(data.file.as_raw_fd(), nix::fcntl::FcntlArg::F_SETLKW(&op)) { if let Err(err) =
nix::fcntl::fcntl(data.file.as_raw_fd(), nix::fcntl::FcntlArg::F_SETLKW(&op))
{
panic!("unable to drop exclusive lock - {}", err); panic!("unable to drop exclusive lock - {}", err);
} }
@ -93,12 +104,10 @@ impl Drop for ProcessLockExclusiveGuard {
} }
impl ProcessLocker { impl ProcessLocker {
/// Create a new instance for the specified file. /// Create a new instance for the specified file.
/// ///
/// This simply creates the file if it does not exist. /// This simply creates the file if it does not exist.
pub fn new<P: AsRef<std::path::Path>>(lockfile: P) -> Result<Arc<Mutex<Self>>, Error> { pub fn new<P: AsRef<std::path::Path>>(lockfile: P) -> Result<Arc<Mutex<Self>>, Error> {
let file = std::fs::OpenOptions::new() let file = std::fs::OpenOptions::new()
.create(true) .create(true)
.read(true) .read(true)
@ -115,7 +124,6 @@ impl ProcessLocker {
} }
fn try_lock(file: &std::fs::File, ltype: i32) -> Result<(), Error> { fn try_lock(file: &std::fs::File, ltype: i32) -> Result<(), Error> {
let op = libc::flock { let op = libc::flock {
l_type: ltype as i16, l_type: ltype as i16,
l_whence: libc::SEEK_SET as i16, l_whence: libc::SEEK_SET as i16,
@ -133,7 +141,6 @@ impl ProcessLocker {
/// ///
/// On success, this makes sure that no other process can get an exclusive lock for the file. /// On success, this makes sure that no other process can get an exclusive lock for the file.
pub fn try_shared_lock(locker: Arc<Mutex<Self>>) -> Result<ProcessLockSharedGuard, Error> { pub fn try_shared_lock(locker: Arc<Mutex<Self>>) -> Result<ProcessLockSharedGuard, Error> {
let mut data = locker.lock().unwrap(); let mut data = locker.lock().unwrap();
if data.writers == 0 && !data.exclusive { if data.writers == 0 && !data.exclusive {
@ -144,7 +151,10 @@ impl ProcessLocker {
data.writers += 1; data.writers += 1;
let guard = ProcessLockSharedGuard { locker: locker.clone(), guard_id: data.next_guard_id }; let guard = ProcessLockSharedGuard {
locker: locker.clone(),
guard_id: data.next_guard_id,
};
data.next_guard_id += 1; data.next_guard_id += 1;
let now = unsafe { libc::time(std::ptr::null_mut()) }; let now = unsafe { libc::time(std::ptr::null_mut()) };
@ -163,7 +173,13 @@ impl ProcessLocker {
for v in data.shared_guard_list.values() { for v in data.shared_guard_list.values() {
result = match result { result = match result {
None => Some(*v), None => Some(*v),
Some(x) => if x < *v { Some(x) } else { Some(*v) }, Some(x) => {
if x < *v {
Some(x)
} else {
Some(*v)
}
}
}; };
} }
@ -173,8 +189,9 @@ impl ProcessLocker {
/// Try to acquire a exclusive lock /// Try to acquire a exclusive lock
/// ///
/// Make sure the we are the only process which has locks for this file (shared or exclusive). /// Make sure the we are the only process which has locks for this file (shared or exclusive).
pub fn try_exclusive_lock(locker: Arc<Mutex<Self>>) -> Result<ProcessLockExclusiveGuard, Error> { pub fn try_exclusive_lock(
locker: Arc<Mutex<Self>>,
) -> Result<ProcessLockExclusiveGuard, Error> {
let mut data = locker.lock().unwrap(); let mut data = locker.lock().unwrap();
if data.exclusive { if data.exclusive {
@ -187,6 +204,8 @@ impl ProcessLocker {
data.exclusive = true; data.exclusive = true;
Ok(ProcessLockExclusiveGuard { locker: locker.clone() }) Ok(ProcessLockExclusiveGuard {
locker: locker.clone(),
})
} }
} }

View File

@ -26,6 +26,9 @@ use proxmox_http::{
pub use pbs_tools::json; pub use pbs_tools::json;
pub use pbs_tools::nom; pub use pbs_tools::nom;
pub use pbs_tools::{run_command, command_output, command_output_as_string}; pub use pbs_tools::{run_command, command_output, command_output_as_string};
pub use pbs_tools::process_locker::{
ProcessLocker, ProcessLockExclusiveGuard, ProcessLockSharedGuard
};
pub mod acl; pub mod acl;
pub mod apt; pub mod apt;
@ -70,9 +73,6 @@ pub use std_channel_writer::StdChannelWriter;
mod tokio_writer_adapter; mod tokio_writer_adapter;
pub use tokio_writer_adapter::TokioWriterAdapter; pub use tokio_writer_adapter::TokioWriterAdapter;
mod process_locker;
pub use process_locker::{ProcessLocker, ProcessLockExclusiveGuard, ProcessLockSharedGuard};
mod file_logger; mod file_logger;
pub use file_logger::{FileLogger, FileLogOptions}; pub use file_logger::{FileLogger, FileLogOptions};