gather usage statistics during garbage collection
This commit is contained in:
parent
28b96b56e1
commit
64e53b2835
|
@ -11,6 +11,24 @@ use std::os::unix::io::AsRawFd;
|
||||||
|
|
||||||
use crate::tools;
|
use crate::tools;
|
||||||
|
|
||||||
|
pub struct GarbageCollectionStatus {
|
||||||
|
pub used_bytes: usize,
|
||||||
|
pub used_chunks: usize,
|
||||||
|
pub disk_bytes: usize,
|
||||||
|
pub disk_chunks: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for GarbageCollectionStatus {
|
||||||
|
fn default() -> Self {
|
||||||
|
GarbageCollectionStatus {
|
||||||
|
used_bytes: 0,
|
||||||
|
used_chunks: 0,
|
||||||
|
disk_bytes: 0,
|
||||||
|
disk_chunks: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ChunkStore {
|
pub struct ChunkStore {
|
||||||
name: String, // used for error reporting
|
name: String, // used for error reporting
|
||||||
base: PathBuf,
|
base: PathBuf,
|
||||||
|
@ -140,7 +158,7 @@ impl ChunkStore {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sweep_old_files(&self, handle: &mut nix::dir::Dir) -> Result<(), Error> {
|
fn sweep_old_files(&self, handle: &mut nix::dir::Dir, status: &mut GarbageCollectionStatus) -> Result<(), Error> {
|
||||||
|
|
||||||
let rawfd = handle.as_raw_fd();
|
let rawfd = handle.as_raw_fd();
|
||||||
|
|
||||||
|
@ -168,13 +186,17 @@ impl ChunkStore {
|
||||||
let err = nix::Error::last();
|
let err = nix::Error::last();
|
||||||
bail!("unlink chunk {:?} failed on store '{}' - {}", filename, self.name, err);
|
bail!("unlink chunk {:?} failed on store '{}' - {}", filename, self.name, err);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
status.disk_chunks += 1;
|
||||||
|
status.disk_bytes += stat.st_size as usize;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sweep_used_chunks(&self) -> Result<(), Error> {
|
pub fn sweep_used_chunks(&self, status: &mut GarbageCollectionStatus) -> Result<(), Error> {
|
||||||
|
|
||||||
use nix::fcntl::OFlag;
|
use nix::fcntl::OFlag;
|
||||||
use nix::sys::stat::Mode;
|
use nix::sys::stat::Mode;
|
||||||
|
@ -219,7 +241,7 @@ impl ChunkStore {
|
||||||
"unable to open store '{}' dir {:?}/{:?}/{:?} - {}",
|
"unable to open store '{}' dir {:?}/{:?}/{:?} - {}",
|
||||||
self.name, self.chunk_dir, l1name, l2name, err),
|
self.name, self.chunk_dir, l1name, l2name, err),
|
||||||
};
|
};
|
||||||
self.sweep_old_files(&mut l2_handle)?;
|
self.sweep_old_files(&mut l2_handle, status)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use failure::*;
|
use failure::*;
|
||||||
|
|
||||||
use std::path::{PathBuf, Path};
|
use std::path::{PathBuf, Path};
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use crate::config::datastore;
|
use crate::config::datastore;
|
||||||
use super::chunk_store::*;
|
use super::chunk_store::*;
|
||||||
|
@ -8,6 +9,7 @@ use super::image_index::*;
|
||||||
|
|
||||||
pub struct DataStore {
|
pub struct DataStore {
|
||||||
chunk_store: ChunkStore,
|
chunk_store: ChunkStore,
|
||||||
|
gc_mutex: Mutex<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DataStore {
|
impl DataStore {
|
||||||
|
@ -24,6 +26,7 @@ impl DataStore {
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
chunk_store: chunk_store,
|
chunk_store: chunk_store,
|
||||||
|
gc_mutex: Mutex::new(false),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +54,7 @@ impl DataStore {
|
||||||
if entry.file_type()?.is_file() {
|
if entry.file_type()?.is_file() {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if let Some(ext) = path.extension() {
|
if let Some(ext) = path.extension() {
|
||||||
if ext == "idx" {
|
if ext == "iidx" {
|
||||||
list.push(path);
|
list.push(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,13 +64,13 @@ impl DataStore {
|
||||||
Ok(list)
|
Ok(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_used_chunks(&self) -> Result<(), Error> {
|
fn mark_used_chunks(&self, status: &mut GarbageCollectionStatus) -> Result<(), Error> {
|
||||||
|
|
||||||
let image_list = self.list_images()?;
|
let image_list = self.list_images()?;
|
||||||
|
|
||||||
for path in image_list {
|
for path in image_list {
|
||||||
let index = self.open_image_reader(path)?;
|
let index = self.open_image_reader(path)?;
|
||||||
index.mark_used_chunks()?;
|
index.mark_used_chunks(status)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -75,12 +78,26 @@ impl DataStore {
|
||||||
|
|
||||||
pub fn garbage_collection(&self) -> Result<(), Error> {
|
pub fn garbage_collection(&self) -> Result<(), Error> {
|
||||||
|
|
||||||
println!("Start GC phase1 (mark chunks)");
|
if let Ok(ref mut mutex) = self.gc_mutex.try_lock() {
|
||||||
|
|
||||||
self.mark_used_chunks()?;
|
let mut gc_status = GarbageCollectionStatus::default();
|
||||||
|
gc_status.used_bytes = 0;
|
||||||
|
|
||||||
println!("Start GC phase2 (sweep unused chunks)");
|
println!("Start GC phase1 (mark chunks)");
|
||||||
self.chunk_store.sweep_used_chunks()?;
|
|
||||||
|
self.mark_used_chunks(&mut gc_status)?;
|
||||||
|
|
||||||
|
println!("Start GC phase2 (sweep unused chunks)");
|
||||||
|
self.chunk_store.sweep_used_chunks(&mut gc_status)?;
|
||||||
|
|
||||||
|
println!("Used bytes: {}", gc_status.used_bytes);
|
||||||
|
println!("Used chunks: {}", gc_status.used_chunks);
|
||||||
|
println!("Disk bytes: {}", gc_status.disk_bytes);
|
||||||
|
println!("Disk chunks: {}", gc_status.disk_chunks);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
println!("Start GC failed - (already running/locked)");
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,12 +100,15 @@ impl <'a> ImageIndexReader<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mark_used_chunks(&self) -> Result<(), Error> {
|
pub fn mark_used_chunks(&self, status: &mut GarbageCollectionStatus) -> Result<(), Error> {
|
||||||
|
|
||||||
if self.index == std::ptr::null_mut() { bail!("detected closed index file."); }
|
if self.index == std::ptr::null_mut() { bail!("detected closed index file."); }
|
||||||
|
|
||||||
let index_count = (self.size + self.chunk_size - 1)/self.chunk_size;
|
let index_count = (self.size + self.chunk_size - 1)/self.chunk_size;
|
||||||
|
|
||||||
|
status.used_bytes += index_count * self.chunk_size;
|
||||||
|
status.used_chunks += index_count;
|
||||||
|
|
||||||
for pos in 0..index_count {
|
for pos in 0..index_count {
|
||||||
|
|
||||||
let digest = unsafe { std::slice::from_raw_parts_mut(self.index.add(pos*32), 32) };
|
let digest = unsafe { std::slice::from_raw_parts_mut(self.index.add(pos*32), 32) };
|
||||||
|
|
Loading…
Reference in New Issue