an efficient binary archive format
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

re-use vacuum file

+39 -50
+39 -50
src/bindle.rs
··· 196 196 pub fn vacuum(&mut self) -> io::Result<()> { 197 197 let temp_path = self.path.with_extension("tmp"); 198 198 199 - // Create and lock temp file 200 - let result = { 201 - let mut temp_file = OpenOptions::new() 202 - .write(true) 203 - .read(true) 204 - .create(true) 205 - .truncate(true) 206 - .open(&temp_path)?; 199 + // Create temp file and keep handle to reuse after rename 200 + let mut temp_file = OpenOptions::new() 201 + .write(true) 202 + .read(true) 203 + .create(true) 204 + .truncate(true) 205 + .open(&temp_path)?; 207 206 208 - temp_file.lock_exclusive()?; 209 - temp_file.write_all(BNDL_MAGIC)?; 210 - let mut current_offset = HEADER_SIZE as u64; 207 + temp_file.lock_exclusive()?; 208 + temp_file.write_all(BNDL_MAGIC)?; 209 + let mut current_offset = HEADER_SIZE as u64; 211 210 212 - // Copy only live entries from original to temp 213 - for entry in self.index.values_mut() { 214 - let mut buf = vec![0u8; entry.compressed_size() as usize]; 215 - self.file.seek(SeekFrom::Start(entry.offset()))?; 216 - self.file.read_exact(&mut buf)?; 211 + // Copy only live entries from original to temp 212 + for entry in self.index.values_mut() { 213 + let mut buf = vec![0u8; entry.compressed_size() as usize]; 214 + self.file.seek(SeekFrom::Start(entry.offset()))?; 215 + self.file.read_exact(&mut buf)?; 217 216 218 - temp_file.seek(SeekFrom::Start(current_offset))?; 219 - temp_file.write_all(&buf)?; 217 + temp_file.seek(SeekFrom::Start(current_offset))?; 218 + temp_file.write_all(&buf)?; 220 219 221 - entry.set_offset(current_offset); 222 - let pad = pad::<8, u64>(entry.compressed_size()); 223 - if pad > 0 { 224 - write_padding(&mut temp_file, pad as usize)?; 225 - } 226 - current_offset += entry.compressed_size() + pad; 220 + entry.set_offset(current_offset); 221 + let pad = pad::<8, u64>(entry.compressed_size()); 222 + if pad > 0 { 223 + write_padding(&mut temp_file, pad as usize)?; 227 224 } 225 + current_offset += entry.compressed_size() + pad; 226 + } 228 227 229 - // Write the index and footer 230 - let index_start = current_offset; 231 - for (name, entry) in &self.index { 232 - temp_file.write_all(entry.as_bytes())?; 233 - temp_file.write_all(name.as_bytes())?; 234 - let pad = pad::<BNDL_ALIGN, usize>(ENTRY_SIZE + name.len()); 235 - if pad > 0 { 236 - write_padding(&mut temp_file, pad)?; 237 - } 228 + // Write the index and footer 229 + let index_start = current_offset; 230 + for (name, entry) in &self.index { 231 + temp_file.write_all(entry.as_bytes())?; 232 + temp_file.write_all(name.as_bytes())?; 233 + let pad = pad::<BNDL_ALIGN, usize>(ENTRY_SIZE + name.len()); 234 + if pad > 0 { 235 + write_padding(&mut temp_file, pad)?; 238 236 } 239 - 240 - let footer = Footer::new(index_start, self.index.len() as u32, FOOTER_MAGIC); 241 - temp_file.write_all(footer.as_bytes())?; 242 - temp_file.sync_all()?; 243 - 244 - Ok(()) 245 - }; 246 - 247 - // Handle result 248 - if let Err(e) = result { 249 - std::fs::remove_file(&temp_path).ok(); 250 - return Err(e); 251 237 } 252 238 239 + let footer = Footer::new(index_start, self.index.len() as u32, FOOTER_MAGIC); 240 + temp_file.write_all(footer.as_bytes())?; 241 + temp_file.sync_all()?; 242 + 253 243 // Acquire exclusive lock just before rename to prevent concurrent access 254 244 self.file.lock_exclusive()?; 255 245 ··· 260 250 // Atomically replace original with temp 261 251 std::fs::rename(&temp_path, &self.path)?; 262 252 263 - // Re-open the new file 264 - let file = OpenOptions::new().read(true).write(true).open(&self.path)?; 265 - file.lock_shared()?; 266 - let mmap = unsafe { Mmap::map(&file)? }; 253 + // Reuse temp_file handle (still valid after rename) 254 + temp_file.lock_shared()?; 255 + let mmap = unsafe { Mmap::map(&temp_file)? }; 267 256 268 257 let footer_pos = mmap.len() - FOOTER_SIZE; 269 258 let footer = Footer::read_from_bytes(&mmap[footer_pos..]).map_err(|_| { 270 259 io::Error::new(io::ErrorKind::InvalidData, "Failed to read footer after vacuum") 271 260 })?; 272 261 273 - self.file = file; 262 + self.file = temp_file; 274 263 self.mmap = Some(mmap); 275 264 self.data_end = footer.index_offset(); 276 265