Skip to content

Commit cec89ce

Browse files
apollo_storage: add mmap file helper methods
1 parent 065a6a8 commit cec89ce

File tree

1 file changed

+47
-7
lines changed
  • crates/apollo_storage/src/mmap_file

1 file changed

+47
-7
lines changed

crates/apollo_storage/src/mmap_file/mod.rs

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,22 @@ struct MMapFile<V: ValueSerde> {
146146
}
147147

148148
impl<V: ValueSerde> MMapFile<V> {
149-
/// Grows the file by the growth step.
150-
fn grow(&mut self) {
149+
/// Grows the file to accommodate at least the target size.
150+
/// Grows in multiples of growth_step for efficiency.
151+
fn grow_to_target(&mut self, target_size: usize) {
152+
if self.size >= target_size {
153+
return;
154+
}
151155
self.flush();
152-
let new_size = self.size + self.config.growth_step;
156+
// Calculate how many growth steps needed, rounding up.
157+
let growth_needed = target_size.saturating_sub(self.size);
158+
let growth_steps = growth_needed.div_ceil(self.config.growth_step);
159+
let new_size = self.size + (growth_steps * self.config.growth_step);
153160
let new_size_u64 = u64::try_from(new_size).expect("usize should fit in u64");
154-
debug!("Growing file to size: {}", new_size);
161+
debug!(
162+
"Growing file to size: {} (target: {}, steps: {})",
163+
new_size, target_size, growth_steps
164+
);
155165
self.file.set_len(new_size_u64).expect("Failed to set the file size");
156166
self.size = new_size;
157167
}
@@ -162,6 +172,35 @@ impl<V: ValueSerde> MMapFile<V> {
162172
self.mmap.flush().expect("Failed to flush the mmap");
163173
self.should_flush = false;
164174
}
175+
176+
/// Writes serialized data to the mmap at the current offset.
177+
/// Returns the location where data was written and updates the offset.
178+
fn write_at_current_offset(&mut self, serialized: &[u8]) -> LocationInFile {
179+
let len = serialized.len();
180+
let offset = self.offset;
181+
182+
trace!("Inserting object at offset: {}", offset);
183+
184+
// Ensure we have enough space before writing.
185+
let final_offset = offset + len;
186+
self.grow_to_target(final_offset);
187+
188+
// Copy data to mmap
189+
let mmap_slice = &mut self.mmap[offset..final_offset];
190+
assert!(
191+
mmap_slice.len() >= len,
192+
"Not enough space in mmap slice: available={}, needed={}",
193+
mmap_slice.len(),
194+
len
195+
);
196+
mmap_slice.copy_from_slice(serialized);
197+
198+
// Update offset
199+
self.offset += len;
200+
self.should_flush = true;
201+
202+
LocationInFile { offset, len }
203+
}
165204
}
166205

167206
/// Open a memory mapped file, create it if it doesn't exist.
@@ -214,11 +253,12 @@ impl<V: ValueSerde> FileHandler<V, RW> {
214253
fn grow_file_if_needed(&mut self, offset: usize) {
215254
let mut mmap_file = self.mmap_file.lock().expect("Lock should not be poisoned");
216255
if mmap_file.size < offset + mmap_file.config.max_object_size {
256+
let target_size = offset + mmap_file.config.max_object_size;
217257
debug!(
218-
"Attempting to grow file. File size: {}, offset: {}, max_object_size: {}",
219-
mmap_file.size, offset, mmap_file.config.max_object_size
258+
"Attempting to grow file. File size: {}, offset: {}, max_object_size: {}, target: {}",
259+
mmap_file.size, offset, mmap_file.config.max_object_size, target_size
220260
);
221-
mmap_file.grow();
261+
mmap_file.grow_to_target(target_size);
222262
}
223263
}
224264
}

0 commit comments

Comments
 (0)