start impl garbage collection
This commit is contained in:
parent
529de6c7a3
commit
3d5c11e5d2
|
@ -20,11 +20,11 @@ pub struct ChunkStore {
|
||||||
|
|
||||||
const HEX_CHARS: &'static [u8; 16] = b"0123456789abcdef";
|
const HEX_CHARS: &'static [u8; 16] = b"0123456789abcdef";
|
||||||
|
|
||||||
pub fn u256_to_hex(digest: &[u8; 32]) -> String {
|
pub fn u256_to_hex(digest: &[u8]) -> String {
|
||||||
|
|
||||||
let mut buf = Vec::<u8>::with_capacity(64);
|
let mut buf = Vec::<u8>::with_capacity(digest.len()*2);
|
||||||
|
|
||||||
for i in 0..32 {
|
for i in 0..digest.len() {
|
||||||
buf.push(HEX_CHARS[(digest[i] >> 4) as usize]);
|
buf.push(HEX_CHARS[(digest[i] >> 4) as usize]);
|
||||||
buf.push(HEX_CHARS[(digest[i] & 0xf) as usize]);
|
buf.push(HEX_CHARS[(digest[i] & 0xf) as usize]);
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ pub fn u256_to_hex(digest: &[u8; 32]) -> String {
|
||||||
unsafe { String::from_utf8_unchecked(buf) }
|
unsafe { String::from_utf8_unchecked(buf) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u256_to_prefix(digest: &[u8; 32]) -> PathBuf {
|
fn u256_to_prefix(digest: &[u8]) -> PathBuf {
|
||||||
|
|
||||||
let mut buf = Vec::<u8>::with_capacity(3+1+2+1);
|
let mut buf = Vec::<u8>::with_capacity(3+1+2+1);
|
||||||
|
|
||||||
|
@ -151,6 +151,18 @@ impl ChunkStore {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn touch_chunk(&mut self, digest:&[u8]) -> Result<(), Error> {
|
||||||
|
|
||||||
|
let mut chunk_path = self.chunk_dir.clone();
|
||||||
|
let prefix = u256_to_prefix(&digest);
|
||||||
|
chunk_path.push(&prefix);
|
||||||
|
let digest_str = u256_to_hex(&digest);
|
||||||
|
chunk_path.push(&digest_str);
|
||||||
|
|
||||||
|
std::fs::metadata(&chunk_path)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn insert_chunk(&mut self, chunk: &[u8]) -> Result<(bool, [u8; 32]), Error> {
|
pub fn insert_chunk(&mut self, chunk: &[u8]) -> Result<(bool, [u8; 32]), Error> {
|
||||||
|
|
||||||
self.hasher.reset();
|
self.hasher.reset();
|
||||||
|
@ -205,6 +217,10 @@ impl ChunkStore {
|
||||||
full_path
|
full_path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn base_path(&self) -> PathBuf {
|
||||||
|
self.base.clone()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use failure::*;
|
use failure::*;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::{PathBuf, Path};
|
||||||
|
|
||||||
use crate::config::datastore;
|
use crate::config::datastore;
|
||||||
use super::chunk_store::*;
|
use super::chunk_store::*;
|
||||||
|
@ -40,4 +40,49 @@ impl DataStore {
|
||||||
|
|
||||||
Ok(index)
|
Ok(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn list_images(&self) -> Result<Vec<PathBuf>, Error> {
|
||||||
|
let base = self.chunk_store.base_path();
|
||||||
|
|
||||||
|
let mut list = vec![];
|
||||||
|
|
||||||
|
for entry in std::fs::read_dir(base)? {
|
||||||
|
let entry = entry?;
|
||||||
|
if entry.file_type()?.is_file() {
|
||||||
|
let path = entry.path();
|
||||||
|
if let Some(ext) = path.extension() {
|
||||||
|
if ext == "idx" {
|
||||||
|
list.push(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn sweep_used_chunks(&mut self) -> Result<(), Error> {
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark_used_chunks(&mut self) -> Result<(), Error> {
|
||||||
|
|
||||||
|
let image_list = self.list_images()?;
|
||||||
|
|
||||||
|
for path in image_list {
|
||||||
|
let mut index = self.open_image_reader(path)?;
|
||||||
|
index.mark_used_chunks();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn garbage_collection(&mut self) -> Result<(), Error> {
|
||||||
|
|
||||||
|
self.mark_used_chunks()?;
|
||||||
|
self.sweep_used_chunks()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,24 @@ impl <'a> ImageIndexReader<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mark_used_chunks(&mut self) -> Result<(), Error> {
|
||||||
|
|
||||||
|
if self.index == std::ptr::null_mut() { bail!("detected closed index file."); }
|
||||||
|
|
||||||
|
let index_count = (self.size + self.chunk_size - 1)/self.chunk_size;
|
||||||
|
|
||||||
|
for pos in 0..index_count {
|
||||||
|
|
||||||
|
let digest = unsafe { std::slice::from_raw_parts_mut(self.index.add(pos*32), 32) };
|
||||||
|
if let Err(err) = self.store.touch_chunk(digest) {
|
||||||
|
bail!("unable to access chunk {}, required by {:?} - {}",
|
||||||
|
u256_to_hex(digest), self.filename, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print_info(&self) {
|
pub fn print_info(&self) {
|
||||||
println!("Filename: {:?}", self.filename);
|
println!("Filename: {:?}", self.filename);
|
||||||
println!("Size: {}", self.size);
|
println!("Size: {}", self.size);
|
||||||
|
|
|
@ -46,6 +46,8 @@ fn backup_file(param: Value, _info: &ApiMethod) -> Result<Value, Error> {
|
||||||
index.close()?; // commit changes
|
index.close()?; // commit changes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
datastore.garbage_collection()?;
|
||||||
|
|
||||||
let idx = datastore.open_image_reader(target)?;
|
let idx = datastore.open_image_reader(target)?;
|
||||||
idx.print_info();
|
idx.print_info();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue