rustdb/
wmap.rs

1use crate::{BTreeMap, Data, Storage};
2use std::cmp::min;
3
4#[derive(Default)]
5/// Slice of Data to be written to storage.
6pub struct DataSlice {
7    /// Slice data.
8    pub data: Data,
9    /// Start of slice.
10    pub off: usize,
11    /// Length of slice.
12    pub len: usize,
13}
14
15impl DataSlice {
16    /// Get reference to the whole slice.
17    pub fn all(&self) -> &[u8] {
18        &self.data[self.off..self.off + self.len]
19    }
20    /// Get reference to part of slice.
21    pub fn part(&self, off: usize, len: usize) -> &[u8] {
22        &self.data[self.off + off..self.off + off + len]
23    }
24    /// Trim specified amount from start of slice.
25    pub fn trim(&mut self, trim: usize) {
26        self.off += trim;
27        self.len -= trim;
28    }
29    /// Take the data.
30    pub fn take(&mut self) -> Data {
31        std::mem::take(&mut self.data)
32    }
33}
34
35#[derive(Default)]
36/// Updateable storage based on some underlying storage.
37pub struct WMap {
38    /// Map of writes. Key is the end of the slice.
39    map: BTreeMap<u64, DataSlice>,
40}
41
42impl WMap {
43    /// Is the map empty?
44    pub fn is_empty(&self) -> bool {
45        self.map.is_empty()
46    }
47
48    /// Number of key-value pairs in the map.
49    pub fn len(&self) -> usize {
50        self.map.len()
51    }
52
53    /// Take the map and convert it to a Vec.
54    pub fn to_vec(&mut self) -> Vec<(u64, DataSlice)> {
55        let map = std::mem::take(&mut self.map);
56        let mut result = Vec::with_capacity(map.len());
57        for (end, v) in map {
58            let start = end - v.len as u64;
59            result.push((start, v));
60        }
61        result
62    }
63
64    /// Write the map into storage.
65    pub fn to_storage(&self, stg: &mut dyn Storage) {
66        for (end, v) in self.map.iter() {
67            let start = end - v.len as u64;
68            stg.write_data(start, v.data.clone(), v.off, v.len);
69        }
70    }
71
72    #[cfg(not(feature = "pstd"))]
73    /// Write to storage, existing writes which overlap with new write need to be trimmed or removed.
74    pub fn write(&mut self, start: u64, data: Data, off: usize, len: usize) {
75        if len != 0 {
76            let (mut insert, mut remove) = (Vec::new(), Vec::new());
77            let end = start + len as u64;
78            for (ee, v) in self.map.range_mut(start + 1..) {
79                let ee = *ee;
80                let es = ee - v.len as u64; // Existing write Start.
81                if es >= end {
82                    // Existing write starts after end of new write, nothing to do.
83                    break;
84                } else if start <= es {
85                    if end < ee {
86                        // New write starts before existing write, but doesn't subsume it. Trim existing write.
87                        v.trim((end - es) as usize);
88                        break;
89                    }
90                    // New write subsumes existing write entirely, remove existing write.
91                    remove.push(ee);
92                } else if end < ee {
93                    // New write starts in middle of existing write, ends before end of existing write,
94                    // put start of existing write in insert list, trim existing write.
95                    insert.push((es, v.data.clone(), v.off, (start - es) as usize));
96                    v.trim((end - es) as usize);
97                    break;
98                } else {
99                    // New write starts in middle of existing write, ends after existing write,
100                    // put start of existing write in insert list, remove existing write.
101                    insert.push((es, v.take(), v.off, (start - es) as usize));
102                    remove.push(ee);
103                }
104            }
105            for end in remove {
106                self.map.remove(&end);
107            }
108            for (start, data, off, len) in insert {
109                self.map
110                    .insert(start + len as u64, DataSlice { data, off, len });
111            }
112            self.map
113                .insert(start + len as u64, DataSlice { data, off, len });
114        }
115    }
116
117    #[cfg(feature = "pstd")]
118    /// Write to storage, existing writes which overlap with new write need to be trimmed or removed.
119    pub fn write(&mut self, start: u64, data: Data, off: usize, len: usize) {
120        if len != 0 {
121            let end = start + len as u64;
122            let mut c = self
123                .map
124                .lower_bound_mut(std::ops::Bound::Excluded(&start))
125                .with_mutable_key();
126            while let Some((eend, v)) = c.next() {
127                let ee = *eend;
128                let es = ee - v.len as u64; // Existing write Start.
129                if es >= end {
130                    // Existing write starts after end of new write, nothing to do.
131                    c.prev();
132                    break;
133                } else if start <= es {
134                    if end < ee {
135                        // New write starts before existing write, but doesn't subsume it. Trim existing write.
136                        v.trim((end - es) as usize);
137                        c.prev();
138                        break;
139                    }
140                    // New write subsumes existing write entirely, remove existing write.
141                    c.remove_prev();
142                } else if end < ee {
143                    // New write starts in middle of existing write, ends before end of existing write,
144                    // trim existing write, insert start of existing write.
145                    let (data, off, len) = (v.data.clone(), v.off, (start - es) as usize);
146                    v.trim((end - es) as usize);
147                    c.prev();
148                    c.insert_before_unchecked(es + len as u64, DataSlice { data, off, len });
149                    break;
150                } else {
151                    // New write starts in middle of existing write, ends after existing write,
152                    // Trim existing write ( modifies key, but this is ok as ordering is not affected ).
153                    v.len = (start - es) as usize;
154                    *eend = es + v.len as u64;
155                }
156            }
157            // Insert the new write.
158            c.insert_after_unchecked(start + len as u64, DataSlice { data, off, len });
159        }
160    }
161
162    /// Read from storage, taking map of existing writes into account. Unwritten ranges are read from underlying storage.
163    pub fn read(&self, start: u64, data: &mut [u8], u: &dyn Storage) {
164        let len = data.len();
165        if len != 0 {
166            let mut done = 0;
167            for (&end, v) in self.map.range(start + 1..) {
168                let es = end - v.len as u64; // Existing write Start.
169                let doff = start + done as u64;
170                if es > doff {
171                    // Read from underlying storage.
172                    let a = min(len - done, (es - doff) as usize);
173                    u.read(doff, &mut data[done..done + a]);
174                    done += a;
175                    if done == len {
176                        return;
177                    }
178                }
179                // Use existing write.
180                let skip = (start + done as u64 - es) as usize;
181                let a = min(len - done, v.len - skip);
182                data[done..done + a].copy_from_slice(v.part(skip, a));
183                done += a;
184                if done == len {
185                    return;
186                }
187            }
188            u.read(start + done as u64, &mut data[done..]);
189        }
190    }
191}