chunk_store: reduce number of directories
Else, scans everything takes too long ...
This commit is contained in:
		| @ -36,15 +36,14 @@ pub fn digest_to_hex(digest: &[u8]) -> String { | ||||
|  | ||||
| fn digest_to_prefix(digest: &[u8]) -> PathBuf { | ||||
|  | ||||
|     let mut buf = Vec::<u8>::with_capacity(3+1+2+1); | ||||
|     let mut buf = Vec::<u8>::with_capacity(2+1+2+1); | ||||
|  | ||||
|     buf.push(HEX_CHARS[(digest[0] as usize) >> 4]); | ||||
|     buf.push(HEX_CHARS[(digest[0] as usize) &0xf]); | ||||
|     buf.push(HEX_CHARS[(digest[1] as usize) >> 4]); | ||||
|     buf.push('/' as u8); | ||||
|  | ||||
|     buf.push(HEX_CHARS[(digest[1] as usize) >> 4]); | ||||
|     buf.push(HEX_CHARS[(digest[1] as usize) & 0xf]); | ||||
|     buf.push(HEX_CHARS[(digest[2] as usize) >> 4]); | ||||
|     buf.push('/' as u8); | ||||
|  | ||||
|     let path = unsafe { String::from_utf8_unchecked(buf)}; | ||||
| @ -76,13 +75,27 @@ impl ChunkStore { | ||||
|             bail!("unable to create chunk store '{}' subdir {:?} - {}", name, chunk_dir, err); | ||||
|         } | ||||
|  | ||||
|         // create 4096 subdir | ||||
|         for i in 0..4096 { | ||||
|         // create 256*256 subdirs | ||||
|         let mut last_percentage = 0; | ||||
|  | ||||
|         for i in 0..256 { | ||||
|             let mut l1path = chunk_dir.clone(); | ||||
|             l1path.push(format!("{:03x}",i)); | ||||
|             l1path.push(format!("{:02x}",i)); | ||||
|             if let Err(err) = std::fs::create_dir(&l1path) { | ||||
|                 bail!("unable to create chunk store '{}' subdir {:?} - {}", name, l1path, err); | ||||
|             } | ||||
|             for j in 0..256 { | ||||
|                 let mut l2path = l1path.clone(); | ||||
|                 l2path.push(format!("{:02x}",j)); | ||||
|                 if let Err(err) = std::fs::create_dir(&l2path) { | ||||
|                     bail!("unable to create chunk store '{}' subdir {:?} - {}", name, l2path, err); | ||||
|                 } | ||||
|                 let percentage = ((i*256+j)*100)/(256*256); | ||||
|                 if percentage != last_percentage { | ||||
|                     eprintln!("Percentage done: {}", percentage); | ||||
|                     last_percentage = percentage; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Self::open(name, base) | ||||
| @ -146,7 +159,7 @@ impl ChunkStore { | ||||
|             let filename = entry.file_name(); | ||||
|             if let Ok(stat) = nix::sys::stat::fstatat(rawfd, filename, nix::fcntl::AtFlags::AT_SYMLINK_NOFOLLOW) { | ||||
|                 let age = now - stat.st_atime; | ||||
|                 println!("FOUND {}  {:?}", age/(3600*24), filename); | ||||
|                 //println!("FOUND {}  {:?}", age/(3600*24), filename); | ||||
|                 if age/(3600*24) >= 2 { | ||||
|                     println!("UNLINK {}  {:?}", age/(3600*24), filename); | ||||
|                     let res = unsafe { libc::unlinkat(rawfd, filename.as_ptr(), 0) }; | ||||
| @ -175,8 +188,8 @@ impl ChunkStore { | ||||
|  | ||||
|         let base_fd = base_handle.as_raw_fd(); | ||||
|  | ||||
|         for i in 0..4096 { | ||||
|             let l1name = PathBuf::from(format!("{:03x}", i)); | ||||
|         for i in 0..256 { | ||||
|             let l1name = PathBuf::from(format!("{:02x}", i)); | ||||
|             let mut l1_handle = match nix::dir::Dir::openat( | ||||
|                 base_fd, &l1name, OFlag::O_RDONLY, Mode::empty()) { | ||||
|                 Ok(h) => h, | ||||
| @ -186,22 +199,13 @@ impl ChunkStore { | ||||
|  | ||||
|             let l1_fd = l1_handle.as_raw_fd(); | ||||
|  | ||||
|             for l1_entry in l1_handle.iter() { | ||||
|                 let l1_entry = match l1_entry { | ||||
|                     Ok(l1_entry) => l1_entry, | ||||
|                     Err(_) => continue /* ignore errors? */, | ||||
|                 }; | ||||
|                 let file_type = match l1_entry.file_type() { | ||||
|                     Some(file_type) => file_type, | ||||
|                     None => bail!("unsupported file system type on chunk store '{}'", self.name), | ||||
|                 }; | ||||
|                 if file_type != nix::dir::Type::Directory { continue; } | ||||
|             for j in 0..256 { | ||||
|                 let l2name = PathBuf::from(format!("{:02x}", j)); | ||||
|  | ||||
|                 let l2name = l1_entry.file_name(); | ||||
|                 if l2name.to_bytes_with_nul()[0] == b'.' { continue; } | ||||
|                 println!("SCAN {:?} {:?}", l1name, l2name); | ||||
|  | ||||
|                 let mut l2_handle = match Dir::openat( | ||||
|                     l1_fd, l2name, OFlag::O_RDONLY, Mode::empty()) { | ||||
|                     l1_fd, &l2name, OFlag::O_RDONLY, Mode::empty()) { | ||||
|                     Ok(h) => h, | ||||
|                     Err(err) => bail!( | ||||
|                         "unable to open store '{}' dir {:?}/{:?}/{:?} - {}", | ||||
| @ -237,11 +241,6 @@ impl ChunkStore { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         let mut chunk_dir = self.chunk_dir.clone(); | ||||
|         chunk_dir.push(&prefix); | ||||
|  | ||||
|         if let Err(_) = std::fs::create_dir(&chunk_dir) { /* ignore */ } | ||||
|  | ||||
|         let mut tmp_path = chunk_path.clone(); | ||||
|         tmp_path.set_extension("tmp"); | ||||
|         let mut f = std::fs::File::create(&tmp_path)?; | ||||
| @ -269,7 +268,6 @@ impl ChunkStore { | ||||
|     pub fn base_path(&self) -> PathBuf { | ||||
|         self.base.clone() | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -75,8 +75,11 @@ impl DataStore { | ||||
|  | ||||
|     pub fn garbage_collection(&self) -> Result<(), Error> { | ||||
|  | ||||
|         println!("Start GC phase1 (mark chunks)"); | ||||
|  | ||||
|         self.mark_used_chunks()?; | ||||
|  | ||||
|         println!("Start GC phase2 (sweep unused chunks)"); | ||||
|         self.chunk_store.sweep_used_chunks()?; | ||||
|  | ||||
|         Ok(()) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user