1#![cfg(unix)]
2use std::fs::File;
9use std::os::unix::fs::FileExt;
10use std::path::Path;
11
12use crate::layout::Layout;
13
14pub struct ShardedStore {
15 pub layout: Layout,
16 files: Vec<File>,
17}
18
19impl ShardedStore {
20 pub fn open(dir: &Path, layout: Layout) -> std::io::Result<Self> {
21 let mut files = Vec::with_capacity(layout.shards as usize);
22 for i in 0..layout.shards {
23 let p = dir.join(format!("shard_{:03}.bin", i));
24 files.push(File::open(p)?);
25 }
26 Ok(Self { layout, files })
27 }
28
29 pub fn gather(&self, keys: &[u64], out: &mut [u8]) -> std::io::Result<()> {
31 let w = self.layout.width as usize;
32 let rb = self.layout.row_bytes as usize;
33 let mut badge_buf = vec![0u8; self.layout.badge_bytes() as usize];
34 let mut current_badge = u64::MAX;
35 for (i, &k) in keys.iter().enumerate() {
36 let (shard, badge, in_badge) = self.layout.locate(k);
37 let off = badge * self.layout.badge_bytes();
38 if (shard, badge) != (current_badge, current_badge >> 32) {
39 self.files[shard as usize].read_exact_at(&mut badge_buf, off)?;
41 current_badge = shard << 32 | badge;
42 }
43 let src = in_badge as usize * rb;
44 let dst = i * w;
45 out[dst..dst + w].copy_from_slice(&badge_buf[src..src + w]);
46 }
47 Ok(())
48 }
49}