foyer_storage/io/device/
partial.rs1use std::sync::{Arc, RwLock};
16
17use foyer_common::error::{Error, Result};
18
19use crate::io::device::{statistics::Statistics, Device, DeviceBuilder, Partition, PartitionId};
20
21#[derive(Debug)]
23pub struct PartialDeviceBuilder {
24 device: Arc<dyn Device>,
25 capacity: usize,
26}
27
28impl PartialDeviceBuilder {
29 pub fn new(device: Arc<dyn Device>) -> Self {
31 let capacity = device.capacity();
32 Self { device, capacity }
33 }
34
35 pub fn with_capacity(mut self, capacity: usize) -> Self {
42 assert!(capacity <= self.device.capacity());
43 self.capacity = capacity;
44 self
45 }
46}
47
48impl DeviceBuilder for PartialDeviceBuilder {
49 fn build(self) -> Result<Arc<dyn Device>> {
50 Ok(Arc::new(PartialDevice {
51 inner: self.device,
52 capacity: self.capacity,
53 partitions: RwLock::new(vec![]),
54 }))
55 }
56}
57
58#[derive(Debug)]
60pub struct PartialDevice {
61 inner: Arc<dyn Device>,
62 capacity: usize,
63 partitions: RwLock<Vec<Arc<PartialPartition>>>,
64}
65
66impl Device for PartialDevice {
67 fn capacity(&self) -> usize {
68 self.capacity
69 }
70
71 fn allocated(&self) -> usize {
72 self.partitions.read().unwrap().iter().map(|p| p.size()).sum()
73 }
74
75 fn create_partition(&self, size: usize) -> Result<Arc<dyn Partition>> {
76 let mut partitions = self.partitions.write().unwrap();
77 let allocated = partitions.iter().map(|p| p.size()).sum::<usize>();
78 if allocated + size > self.capacity {
79 return Err(Error::no_space(self.capacity, allocated, allocated + size));
80 }
81 self.inner.create_partition(size).map(|inner| {
82 let partition = PartialPartition {
83 inner,
84 id: partitions.len() as PartitionId,
85 };
86 let partition = Arc::new(partition);
87 partitions.push(partition.clone());
88 partition as Arc<dyn Partition>
89 })
90 }
91
92 fn partitions(&self) -> usize {
93 self.partitions.read().unwrap().len()
94 }
95
96 fn partition(&self, id: PartitionId) -> Arc<dyn Partition> {
97 self.partitions.read().unwrap()[id as usize].clone()
98 }
99
100 fn statistics(&self) -> &Arc<Statistics> {
101 self.inner.statistics()
102 }
103}
104
105#[derive(Debug)]
106pub struct PartialPartition {
107 inner: Arc<dyn Partition>,
108 id: PartitionId,
109}
110
111impl Partition for PartialPartition {
112 fn id(&self) -> PartitionId {
113 self.id
114 }
115
116 fn size(&self) -> usize {
117 self.inner.size()
118 }
119
120 fn translate(&self, address: u64) -> (super::RawFile, u64) {
121 self.inner.translate(address)
122 }
123
124 fn statistics(&self) -> &Arc<Statistics> {
125 self.inner.statistics()
126 }
127}