datastore: use new ProcessLocker
To make sure only one process runs garbage collection while having active writers.
This commit is contained in:
		@ -1,13 +1,11 @@
 | 
				
			|||||||
use failure::*;
 | 
					use failure::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::path::{Path, PathBuf};
 | 
					use std::path::{Path, PathBuf};
 | 
				
			||||||
use std::io::{Read, Write};
 | 
					use std::io::{Read, Write};
 | 
				
			||||||
use std::time::Duration;
 | 
					use std::sync::{Arc, Mutex};
 | 
				
			||||||
 | 
					use std::os::unix::io::AsRawFd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use openssl::sha;
 | 
					use openssl::sha;
 | 
				
			||||||
use std::sync::Mutex;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use std::fs::File;
 | 
					 | 
				
			||||||
use std::os::unix::io::AsRawFd;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::tools;
 | 
					use crate::tools;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -35,7 +33,7 @@ pub struct ChunkStore {
 | 
				
			|||||||
    pub (crate) base: PathBuf,
 | 
					    pub (crate) base: PathBuf,
 | 
				
			||||||
    chunk_dir: PathBuf,
 | 
					    chunk_dir: PathBuf,
 | 
				
			||||||
    mutex: Mutex<bool>,
 | 
					    mutex: Mutex<bool>,
 | 
				
			||||||
    _lockfile: File,
 | 
					    locker: Arc<Mutex<tools::ProcessLocker>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: what about sysctl setting vm.vfs_cache_pressure (0 - 100) ?
 | 
					// TODO: what about sysctl setting vm.vfs_cache_pressure (0 - 100) ?
 | 
				
			||||||
@ -131,15 +129,13 @@ impl ChunkStore {
 | 
				
			|||||||
        let mut lockfile_path = base.clone();
 | 
					        let mut lockfile_path = base.clone();
 | 
				
			||||||
        lockfile_path.push(".lock");
 | 
					        lockfile_path.push(".lock");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // make sure only one process/thread/task can use it
 | 
					        let locker = tools::ProcessLocker::new(&lockfile_path)?;
 | 
				
			||||||
        let lockfile = tools::open_file_locked(
 | 
					 | 
				
			||||||
            lockfile_path, Duration::from_secs(10))?;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(ChunkStore {
 | 
					        Ok(ChunkStore {
 | 
				
			||||||
            name: name.to_owned(),
 | 
					            name: name.to_owned(),
 | 
				
			||||||
            base,
 | 
					            base,
 | 
				
			||||||
            chunk_dir,
 | 
					            chunk_dir,
 | 
				
			||||||
            _lockfile: lockfile,
 | 
					            locker,
 | 
				
			||||||
            mutex: Mutex::new(false)
 | 
					            mutex: Mutex::new(false)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -369,6 +365,14 @@ impl ChunkStore {
 | 
				
			|||||||
    pub fn base_path(&self) -> PathBuf {
 | 
					    pub fn base_path(&self) -> PathBuf {
 | 
				
			||||||
        self.base.clone()
 | 
					        self.base.clone()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn try_shared_lock(&self) -> Result<tools::ProcessLockSharedGuard, Error> {
 | 
				
			||||||
 | 
					        tools::ProcessLocker::try_shared_lock(self.locker.clone())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn try_exclusive_lock(&self) -> Result<tools::ProcessLockExclusiveGuard, Error> {
 | 
				
			||||||
 | 
					        tools::ProcessLocker::try_exclusive_lock(self.locker.clone())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -227,6 +227,8 @@ impl DataStore {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if let Ok(ref mut _mutex) = self.gc_mutex.try_lock() {
 | 
					        if let Ok(ref mut _mutex) = self.gc_mutex.try_lock() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let _exclusive_lock =  self.chunk_store.try_exclusive_lock()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let mut gc_status = GarbageCollectionStatus::default();
 | 
					            let mut gc_status = GarbageCollectionStatus::default();
 | 
				
			||||||
            gc_status.used_bytes = 0;
 | 
					            gc_status.used_bytes = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -340,6 +340,8 @@ impl std::io::Seek for  BufferedDynamicReader {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub struct DynamicIndexWriter {
 | 
					pub struct DynamicIndexWriter {
 | 
				
			||||||
    store: Arc<ChunkStore>,
 | 
					    store: Arc<ChunkStore>,
 | 
				
			||||||
 | 
					    _lock: tools::ProcessLockSharedGuard,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    chunker: Chunker,
 | 
					    chunker: Chunker,
 | 
				
			||||||
    writer: BufWriter<File>,
 | 
					    writer: BufWriter<File>,
 | 
				
			||||||
    closed: bool,
 | 
					    closed: bool,
 | 
				
			||||||
@ -366,6 +368,8 @@ impl DynamicIndexWriter {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    pub fn create(store: Arc<ChunkStore>, path: &Path, chunk_size: usize) -> Result<Self, Error> {
 | 
					    pub fn create(store: Arc<ChunkStore>, path: &Path, chunk_size: usize) -> Result<Self, Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let shared_lock = store.try_shared_lock()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let full_path = store.relative_path(path);
 | 
					        let full_path = store.relative_path(path);
 | 
				
			||||||
        let mut tmp_path = full_path.clone();
 | 
					        let mut tmp_path = full_path.clone();
 | 
				
			||||||
        tmp_path.set_extension("tmp_didx");
 | 
					        tmp_path.set_extension("tmp_didx");
 | 
				
			||||||
@ -400,6 +404,7 @@ impl DynamicIndexWriter {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        Ok(Self {
 | 
					        Ok(Self {
 | 
				
			||||||
            store,
 | 
					            store,
 | 
				
			||||||
 | 
					            _lock: shared_lock,
 | 
				
			||||||
            chunker: Chunker::new(chunk_size),
 | 
					            chunker: Chunker::new(chunk_size),
 | 
				
			||||||
            writer: writer,
 | 
					            writer: writer,
 | 
				
			||||||
            closed: false,
 | 
					            closed: false,
 | 
				
			||||||
 | 
				
			|||||||
@ -175,6 +175,7 @@ impl IndexFile for FixedIndexReader {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub struct FixedIndexWriter {
 | 
					pub struct FixedIndexWriter {
 | 
				
			||||||
    store: Arc<ChunkStore>,
 | 
					    store: Arc<ChunkStore>,
 | 
				
			||||||
 | 
					    _lock: tools::ProcessLockSharedGuard,
 | 
				
			||||||
    filename: PathBuf,
 | 
					    filename: PathBuf,
 | 
				
			||||||
    tmp_filename: PathBuf,
 | 
					    tmp_filename: PathBuf,
 | 
				
			||||||
    chunk_size: usize,
 | 
					    chunk_size: usize,
 | 
				
			||||||
@ -204,6 +205,8 @@ impl FixedIndexWriter {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    pub fn create(store: Arc<ChunkStore>, path: &Path, size: usize, chunk_size: usize) -> Result<Self, Error> {
 | 
					    pub fn create(store: Arc<ChunkStore>, path: &Path, size: usize, chunk_size: usize) -> Result<Self, Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let shared_lock = store.try_shared_lock()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let full_path = store.relative_path(path);
 | 
					        let full_path = store.relative_path(path);
 | 
				
			||||||
        let mut tmp_path = full_path.clone();
 | 
					        let mut tmp_path = full_path.clone();
 | 
				
			||||||
        tmp_path.set_extension("tmp_fidx");
 | 
					        tmp_path.set_extension("tmp_fidx");
 | 
				
			||||||
@ -250,6 +253,7 @@ impl FixedIndexWriter {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        Ok(Self {
 | 
					        Ok(Self {
 | 
				
			||||||
            store,
 | 
					            store,
 | 
				
			||||||
 | 
					            _lock: shared_lock,
 | 
				
			||||||
            filename: full_path,
 | 
					            filename: full_path,
 | 
				
			||||||
            tmp_filename: tmp_path,
 | 
					            tmp_filename: tmp_path,
 | 
				
			||||||
            chunk_size,
 | 
					            chunk_size,
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user