mmap_storage/anonim.rs
1//!Anonymous memory mapped storage.
2use core::cmp;
3use std::io;
4
5/// Anonymous memory map backed storage
6///
7/// It provides byte storage over anonymous memory map.
8///
9/// When new data is written the storage may be extended
10/// using following strategy:
11///
12/// - If new data is small enough, resize to double size.
13/// - Otherwise resize to new data_size.
14///
15/// If needed you can use `resize` method to shrink or extend storage.
16///
17/// Unless otherwise stated all methods that modify content of storage doesn't perform
18/// flushes, it is callee's responsibility to call it when required
19pub struct Storage {
20 inner: memmap::MmapMut,
21 //Total size of storage
22 size: usize,
23 //Cursor pointing to end of storage
24 end: usize,
25}
26
27impl Storage {
28 /// Creates storage with specified size.
29 pub fn new(size: usize) -> io::Result<Self> {
30 let inner = memmap::MmapOptions::new().len(size).map_anon()?;
31
32 Ok(Self {
33 inner,
34 end: 0,
35 size
36 })
37 }
38
39 #[inline]
40 /// Returns slice with view on written data.
41 pub fn as_slice(&self) -> &[u8] {
42 &self.inner[..self.end]
43 }
44
45 #[inline]
46 /// Returns slice with view on written data.
47 pub fn as_mut_slice(&mut self) -> &mut [u8] {
48 &mut self.inner[..self.end]
49 }
50
51 #[inline]
52 /// Returns overall size of storage(including extra space).
53 pub fn capacity(&self) -> usize {
54 self.size
55 }
56
57 #[inline]
58 /// Asynchronously flushes outstanding memory map modifications to disk.
59 ///
60 /// This method initiates flushing modified pages to durable storage, but it will not wait for
61 /// the operation to complete before returning.
62 pub fn flush_async(&self) -> io::Result<()> {
63 self.inner.flush_async()
64 }
65
66 #[inline]
67 /// Synchronously flushes outstanding memory map modifications to disk.
68 pub fn flush_sync(&self) -> io::Result<()> {
69 self.inner.flush()
70 }
71
72 //Increases mmap size by max(old_size*2, new_size)
73 fn realloc(&mut self, new_size: usize) -> io::Result<()> {
74 let new_size = cmp::max(self.size + self.size, new_size);
75 let mut new_mmap = Self::new(new_size)?;
76 new_mmap.copy_from_slice(self.as_slice());
77 *self = new_mmap;
78 Ok(())
79 }
80
81 /// Appends data to storage
82 ///
83 /// Note that it resizes storage if needed.
84 /// Therefore error can happen.
85 pub fn extend_from_slice(&mut self, data: &[u8]) -> io::Result<()> {
86 if (self.size - self.end) < data.len() {
87 let new_size = self.end + data.len();
88 self.realloc(new_size)?;
89 }
90 self.inner[self.end..self.end+data.len()].copy_from_slice(data);
91 self.end += data.len();
92 Ok(())
93 }
94
95 /// Copies data from slice into storage.
96 ///
97 /// Function panics if data has greater len.
98 ///
99 /// **Note:** It copies data up to storage capacity.
100 pub fn copy_from_slice(&mut self, data: &[u8]) {
101 assert!(self.size >= data.len());
102 self.end = data.len();
103 self.as_mut_slice().copy_from_slice(data);
104 }
105
106 /// Resizes storage by appending or truncating.
107 ///
108 /// As it requires re-create mmap, the error is possible to happen.
109 /// In case of error, original storage is preserved.
110 ///
111 /// After successfully creating new storage, previous storage content gets copied.
112 pub fn resize(&mut self, new_size: usize) -> io::Result<()> {
113 let mut new_mmap = Self::new(new_size)?;
114 new_mmap.copy_from_slice(self.as_slice());
115 *self = new_mmap;
116 Ok(())
117 }
118
119 /// Clears content of storage.
120 ///
121 /// Note that it doesn't affect capacity in any way.
122 pub fn clear(&mut self) {
123 self.end = 0;
124 }
125
126 /// Creates `Vec` from content of storage.
127 pub fn to_vec(&self) -> Vec<u8> {
128 let mut result = Vec::with_capacity(self.end);
129 result.extend_from_slice(self.as_slice());
130 result
131 }
132}
133
134impl Default for Storage {
135 ///Creates default storage with capacity 1024
136 ///
137 ///Note that it panics on error
138 fn default() -> Self {
139 Self::new(1024).expect("To create default mmap storage")
140 }
141}
142
143impl io::Write for Storage {
144 #[inline]
145 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
146 self.extend_from_slice(buf)?;
147 Ok(buf.len())
148 }
149
150 #[inline]
151 fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
152 self.extend_from_slice(buf)
153 }
154
155 #[inline]
156 fn flush(&mut self) -> io::Result<()> {
157 self.inner.flush()
158 }
159}