]> git.proxmox.com Git - proxmox-backup.git/commitdiff
start impl garbage collection
authorDietmar Maurer <dietmar@proxmox.com>
Tue, 18 Dec 2018 10:06:03 +0000 (11:06 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Tue, 18 Dec 2018 10:06:03 +0000 (11:06 +0100)
src/backup/chunk_store.rs
src/backup/datastore.rs
src/backup/image_index.rs
src/bin/backup-client.rs

index 009ee2cb15f7a6b8ea5327059bf8c3387f67d26b..18a7285dc37d97fb2554f8c1002f7e36b1073aa9 100644 (file)
@@ -20,11 +20,11 @@ pub struct ChunkStore {
 
 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] & 0xf) as usize]);
     }
@@ -32,7 +32,7 @@ pub fn u256_to_hex(digest: &[u8; 32]) -> String {
     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);
 
@@ -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> {
 
         self.hasher.reset();
@@ -205,6 +217,10 @@ impl ChunkStore {
         full_path
     }
 
+    pub fn base_path(&self) -> PathBuf {
+        self.base.clone()
+    }
+
 }
 
 
index 3c6c5b7f6e63855f12e8c7711f4aa741bd41b6c9..6767f7be4f89c3c59670e7acb672694fac6b513e 100644 (file)
@@ -1,6 +1,6 @@
 use failure::*;
 
-use std::path::Path;
+use std::path::{PathBuf, Path};
 
 use crate::config::datastore;
 use super::chunk_store::*;
@@ -40,4 +40,49 @@ impl DataStore {
 
         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(())
+    }
 }
index 5194406df019542cf61076cc63c92f448b5ecac9..5b9f6eba695e792ec9fffe2cc3ac9367c2436dc2 100644 (file)
@@ -100,6 +100,24 @@ impl <'a> ImageIndexReader<'a> {
         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) {
         println!("Filename: {:?}", self.filename);
         println!("Size: {}", self.size);
index e080f2ec0d8be2a6201aa0355674148c32b10cf2..e1536ee4d9eef837d84a3c383a8e015fa51d647d 100644 (file)
@@ -46,6 +46,8 @@ fn backup_file(param: Value, _info: &ApiMethod) -> Result<Value, Error> {
         index.close()?; // commit changes
     }
 
+    datastore.garbage_collection()?;
+
     let idx = datastore.open_image_reader(target)?;
     idx.print_info();