Add advisory locking for POSIX systems
This commit adds a basic implementation of POSIX advisory record locking which sets a lock on the `data.bin` file when the database server starts and releases the lock when it terminates. This is just done for compliance to let other processes know that we don't want them to use the file. However, the result depends entirely on the process that wants to do 'something' with the file. It is the responsibility of the process to ensure that it respects the file lock. Also, exclusive locks aren't perfect on Linux, so we can't rely on them. See discussion #123 for more information.next
parent
1be348f5a2
commit
a9710587bb
@ -0,0 +1,6 @@
|
||||
use cc;
|
||||
fn main() {
|
||||
cc::Build::new()
|
||||
.file("native/fscposix.c")
|
||||
.compile("libflock.a")
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Created on Fri Apr 16 2021
|
||||
*
|
||||
* This file is a part of Skytable
|
||||
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
|
||||
* NoSQL database written by Sayan Nandan ("the Author") with the
|
||||
* vision to provide flexibility in data modelling without compromising
|
||||
* on performance, queryability or scalability.
|
||||
*
|
||||
* Copyright (c) 2020, Sayan Nandan <ohsayan@outlook.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
use libc::c_int;
|
||||
use std::fs::File;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Error;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
extern "C" {
|
||||
fn lock_file(fd: i32) -> c_int;
|
||||
fn unlock_file(fd: i32) -> c_int;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FileLock {
|
||||
file: File,
|
||||
}
|
||||
|
||||
impl FileLock {
|
||||
pub fn lock(filename: &str) -> Result<Self, Error> {
|
||||
let file = OpenOptions::new()
|
||||
.read(false)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(&filename)?;
|
||||
let raw_err = unsafe { lock_file(file.as_raw_fd()) };
|
||||
match raw_err {
|
||||
0 => Ok(FileLock { file }),
|
||||
x @ _ => Err(Error::from_raw_os_error(x)),
|
||||
}
|
||||
}
|
||||
pub fn unlock(&self) -> Result<(), Error> {
|
||||
let raw_err = unsafe { unlock_file(self.file.as_raw_fd()) };
|
||||
match raw_err {
|
||||
0 => Ok(()),
|
||||
x @ _ => Err(Error::from_raw_os_error(x)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FileLock {
|
||||
fn drop(&mut self) {
|
||||
assert!(self.unlock().is_ok());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue