Implement garbage collect on the server
This commit is contained in:
		@ -33,6 +33,20 @@ impl Sha256 {
 | 
			
		||||
 | 
			
		||||
        Sha256(hash_arr)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn from_hex(hex_str: &str) -> Option<Self> {
 | 
			
		||||
        if hex_str.len() != 32 * 2 {
 | 
			
		||||
            return None; // String has wrong length
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let mut out = [0u8; 32];
 | 
			
		||||
        for (i, byte) in out.iter_mut().enumerate() {
 | 
			
		||||
            let string_index = i * 2;
 | 
			
		||||
            *byte = u8::from_str_radix(&hex_str[string_index..=string_index + 1], 16).ok()?;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Some(Sha256(out))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn as_hex<S>(hash: &[u8; 32], serializer: S) -> Result<S::Ok, S::Error>
 | 
			
		||||
@ -48,22 +62,10 @@ where
 | 
			
		||||
{
 | 
			
		||||
    use serde::de::Error;
 | 
			
		||||
 | 
			
		||||
    fn hex2bytes(s: &str) -> Option<[u8; 32]> {
 | 
			
		||||
        if s.len() != 32 * 2 {
 | 
			
		||||
            return None; // String has wrong length
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let mut out = [0u8; 32];
 | 
			
		||||
        for (i, byte) in out.iter_mut().enumerate() {
 | 
			
		||||
            let string_index = i * 2;
 | 
			
		||||
            *byte = u8::from_str_radix(&s[string_index..=string_index + 1], 16).ok()?;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return Some(out);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    String::deserialize(deserializer).and_then(|string| {
 | 
			
		||||
        hex2bytes(&string).ok_or_else(|| Error::custom("Invalid HEX String!".to_string()))
 | 
			
		||||
        Ok(Sha256::from_hex(&string)
 | 
			
		||||
            .ok_or_else(|| Error::custom("Invalid HEX String!".to_string()))?
 | 
			
		||||
            .0)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -182,11 +182,47 @@ impl DataStore {
 | 
			
		||||
        self.textures.iter()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn garbage_collect(&mut self) -> io::Result<()> {
 | 
			
		||||
        //unimplemented!()
 | 
			
		||||
    pub fn extract_hash(filename: &std::ffi::OsStr) -> Option<Sha256> {
 | 
			
		||||
        // directly return None for invalidly encoded file names
 | 
			
		||||
        let str_name = filename.to_str()?;
 | 
			
		||||
        let hash = Sha256::from_hex(str_name)?;
 | 
			
		||||
 | 
			
		||||
        /// VERY TODO:
 | 
			
		||||
        eprintln!("WARNING: We are sorry the GC isn't implemented yet :'( ");
 | 
			
		||||
        // check back to ignore names with lowercase letters
 | 
			
		||||
        if hash.as_hex_string() == str_name {
 | 
			
		||||
            Some(hash)
 | 
			
		||||
        } else {
 | 
			
		||||
            None
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn garbage_collect(&mut self) -> io::Result<()> {
 | 
			
		||||
        let texture_dir = std::fs::read_dir(self.texture_base_path())?;
 | 
			
		||||
 | 
			
		||||
        let mut hashs_on_disk = HashSet::new();
 | 
			
		||||
        for result_direntry in texture_dir {
 | 
			
		||||
            let texture_path = result_direntry?.path();
 | 
			
		||||
            let filename = match texture_path.file_name() {
 | 
			
		||||
                Some(name) => name,
 | 
			
		||||
                None => continue,
 | 
			
		||||
            };
 | 
			
		||||
            match Self::extract_hash(filename) {
 | 
			
		||||
                Some(hash) => {
 | 
			
		||||
                    hashs_on_disk.insert(hash);
 | 
			
		||||
                }
 | 
			
		||||
                None => (), // ignore other files
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let mut unused_files = hashs_on_disk;
 | 
			
		||||
        for texture in &self.textures {
 | 
			
		||||
            unused_files.remove(&texture.texture_hash);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // remove what is still contained in the HashSet
 | 
			
		||||
        for entry in unused_files {
 | 
			
		||||
            let path = self.texture_file_path(&entry);
 | 
			
		||||
            std::fs::remove_file(path)?;
 | 
			
		||||
        }
 | 
			
		||||
        Ok(())
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user