pi_store 0.10.2

File storage
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
use std::sync::Arc;
use std::fmt::Debug;
use std::ops::Deref;
use std::hash::Hash;
use std::io::Result;
use std::time::Duration;

use futures::future::BoxFuture;
use url::Url;

use dashmap::DashMap;

pub mod simple_device;

///
/// 块设备中的空块,用于表示不存在、不可用的块或还未分配的块位置
///
pub const EMPTY_BLOCK: u64 = 0;

///
/// 空的块位置,用于表示不存在、不可用或还未分配的块位置
///
pub const EMPTY_BLOCK_LOCATION: BlockLocation = BlockLocation(EMPTY_BLOCK);

///
/// 块设备的类型
///
pub enum DeviceType<D: DeviceDetail> {
    VM(D),      //易失内存
    NVM(D),     //非易失内存
    HDD(D),     //硬盘
    SSD(D),     //固定硬盘
    Disk(D),    //未知硬盘
}

unsafe impl<D: DeviceDetail> Send for DeviceType<D> {}
unsafe impl<D: DeviceDetail> Sync for DeviceType<D> {}

///
/// 块设备详细信息
///
pub trait DeviceDetail: Send + Sync + 'static {
    type Key: Debug + Clone + Hash + Eq + Send + Sync + 'static;
    type Val: Debug + Clone + Hash + Eq + Send + Sync + 'static;

    /// 获取块设备的指定信息
    fn get(&self, key: &Self::Key) -> Option<Self::Val>;
}

///
/// 设备值类型
///
#[derive(Debug, Clone, Hash)]
pub enum DeviceValueType {
    Integer(i128),  //整数
    Str(String),    //字符串
}

unsafe impl Send for DeviceValueType {}
unsafe impl Sync for DeviceValueType {}

impl Eq for DeviceValueType {}
impl PartialEq for DeviceValueType {
    fn eq(&self, other: &Self) -> bool {
        match self {
            DeviceValueType::Integer(x) => {
                match other {
                    DeviceValueType::Integer(y) => {
                        x.to_string().eq(&y.to_string())
                    },
                    DeviceValueType::Str(y) => {
                        x.to_string().eq(y)
                    }
                }
            },
            DeviceValueType::Str(x) => {
                match other {
                    DeviceValueType::Integer(y) => {
                        x.eq(&y.to_string())
                    },
                    DeviceValueType::Str(y) => {
                        x.eq(y)
                    }
                }
            },
        }
    }
}

///
/// 块设备详细信息表
///
pub struct DeviceDetailMap {
    inner:  Arc<DashMap<DeviceValueType, DeviceValueType>>, //共享的块设备详细信息表
}

unsafe impl Send for DeviceDetailMap {}
unsafe impl Sync for DeviceDetailMap {}

impl DeviceDetail for DeviceDetailMap {
    type Key = DeviceValueType;
    type Val = DeviceValueType;

    fn get(&self, key: &Self::Key) -> Option<Self::Val> {
        if let Some(val) = self.inner.get(&key) {
            Some(val.value().clone())
        } else {
            None
        }
    }
}

impl DeviceDetailMap {
    /// 构建块设备详细信息表
    pub fn new() -> Self {
        DeviceDetailMap {
            inner: Arc::new(DashMap::new()),
        }
    }
}

/// 块设备状态
#[derive(Debug, Clone, Hash)]
pub enum DeviceStatus {
    Inited = 0, //已初始化
    Running,    //正在运行
    Busy,       //繁忙
    Pended,     //已挂起
    Closing,    //正在关闭
    Closed,     //已关闭
}

unsafe impl Send for DeviceStatus {}
unsafe impl Sync for DeviceStatus {}

impl From<u8> for DeviceStatus {
    fn from(src: u8) -> Self {
        match src {
            0 => DeviceStatus::Inited,
            1 => DeviceStatus::Running,
            2 => DeviceStatus::Busy,
            3 => DeviceStatus::Pended,
            4 => DeviceStatus::Closing,
            _ => DeviceStatus::Closed,
        }
    }
}

impl From<DeviceStatus> for u8 {
    fn from(value: DeviceStatus) -> Self {
        match value {
            DeviceStatus::Inited => 0,
            DeviceStatus::Running => 1,
            DeviceStatus::Busy => 2,
            DeviceStatus::Pended => 3,
            DeviceStatus::Closing => 4,
            DeviceStatus::Closed => 5,
        }
    }
}

///
/// 块设备统计信息
///
pub struct DeviceStatistics {
    alloc_blocks:       u128,           //累计分配块数量
    alloc_bytes:        u128,           //累计分配大小,单位B
    free_blocks:        u128,           //累计释放块数量
    free_bytes:         u128,           //累计释放大小,单位B
    blocks_in:          u128,           //累计输入块数量
    blocks_out:         u128,           //累计输出块数量
    bytes_in:           u128,           //累计输入大小,单位B
    bytes_out:          u128,           //累计输出大小,单位B
    time:               u128,           //块设备本次运行时长,单位ms
    slow_alloc_count:   Option<u64>,    //块设备慢分配次数
    slow_free_count:    Option<u64>,    //块设备慢释放次数
    slow_in_count:      Option<u64>,    //块设备慢输入次数
    slow_out_count:     Option<u64>,    //块设备慢输出次数
    min_alloc_bytes:    Option<u64>,    //最小分配大小,单位B
    max_alloc_bytes:    Option<u64>,    //最大分配大小,单位B
    min_alloc_time:     Option<u64>,    //最小分配时长,单位ms
    max_alloc_time:     Option<u64>,    //最大分配时长,单位ms
    min_free_time:      Option<u64>,    //最小释放时长,单位ms
    max_free_time:      Option<u64>,    //最大释放时长,单位ms
    min_in_time:        Option<u64>,    //最小输入时长,单位ms
    max_in_time:        Option<u64>,    //最大输入时长,单位ms
    min_out_time:       Option<u64>,    //最小输出时长,单位ms
    max_out_time:       Option<u64>,    //最大输出时长,单位ms
    soft_faults:        Option<u64>,    //软故障次数
    hard_faults:        Option<u64>,    //硬故障次数
}

impl DeviceStatistics {
    /// 构建块设备统计信息
    pub fn new(alloc_blocks: u128,
               alloc_bytes: u128,
               free_blocks: u128,
               free_bytes: u128,
               blocks_in: u128,
               blocks_out: u128,
               bytes_in: u128,
               bytes_out: u128,
               time: u128) -> Self {
        DeviceStatistics {
            alloc_blocks,
            alloc_bytes,
            free_blocks,
            free_bytes,
            blocks_in,
            blocks_out,
            bytes_in,
            bytes_out,
            time,
            slow_alloc_count: None,
            slow_free_count: None,
            slow_in_count: None,
            slow_out_count: None,
            min_alloc_bytes: None,
            max_alloc_bytes: None,
            min_alloc_time: None,
            max_alloc_time: None,
            min_free_time: None,
            max_free_time: None,
            min_in_time: None,
            max_in_time: None,
            min_out_time: None,
            max_out_time: None,
            soft_faults: None,
            hard_faults: None,
        }
    }
}

///
/// 块设备
///
pub trait BlockDevice: Send + Sync + 'static {
    type Uid: Debug + Clone + Hash + Ord + Send + Sync + 'static;
    type Status: Debug + Clone + Hash + Send + Sync + 'static;
    type DetailKey: Debug + Clone + Hash + Eq + Send + Sync + 'static;
    type DetailVal: Debug + Clone + Hash + Eq + Send + Sync + 'static;
    type Detail: DeviceDetail<Key = Self::DetailKey, Val = Self::DetailVal>;
    type Buf: AsRef<[u8]> + Clone + Send + Sync + 'static;

    /// 判断当前块设备是否完全空闲
    fn is_full_free(&self) -> bool;

    /// 判断当前是否是本地块设备
    fn is_local(&self) -> bool;

    /// 判断当前是否是持久化块设备
    fn is_persistent(&self) -> bool;

    /// 判断当前是否是访问安全的块设备
    fn is_security(&self) -> bool;

    /// 判断当前是否是数据稳固的块设备
    fn is_safety(&self) -> bool;

    /// 判断当前块设备是否支持压缩
    fn enable_compression(&self) -> bool;

    /// 判断是否需要外部调用整理方法
    fn is_require_collect(&self) -> bool;

    /// 判断指定块位置是否空闲
    fn is_freed(&self, location: &BlockLocation) -> bool;

    /// 获取当前块设备的容量,返回空表示无限制容量,单位B
    fn capacity(&self) -> Option<u64>;

    /// 获取当前块设备的可用容量,返回空表示有无限制的可用容量,单位B
    fn avail_size(&self) -> Option<u64>;

    /// 获取当前块设备的已用容量,单位B
    fn used_size(&self) -> u64;

    /// 获取块单位长度,单位B
    fn block_unit_len(&self) -> usize;

    /// 获取最大块大小,单位字节
    fn max_block_size(&self) -> usize;

    /// 获取指定块的大小,单位B
    fn block_size(&self, location: &BlockLocation) -> usize;

    /// 获取当前块设备的URL
    fn get_url(&self) -> Option<Url>;

    /// 获取当前块设备的唯一id
    fn get_uid(&self) -> Option<Self::Uid>;

    /// 获取块设备的信息
    fn get_info(&self) -> DeviceType<Self::Detail>;

    /// 获取块设备的状态
    fn get_status(&self) -> Self::Status;

    /// 获取块设备的当前统计信息
    fn statistics(&self) -> Option<DeviceStatistics>;

    /// 异步分配足够容纳指定大小的块,块的实际大小不一定等于指定大小,成功返回块位置,失败返回空块
    /// 分配的块,必须初始化后再使用
    fn alloc_block(&self, size: usize) -> BoxFuture<BlockLocation>;

    /// 异步从块设备的指定块位置上读取数据
    fn read(&self, location: &BlockLocation) -> BoxFuture<Result<Self::Buf>>;

    /// 异步从块设备的指定块位置上写入数据
    fn write(&self,
             location: &BlockLocation,
             buf: &Self::Buf,
             option: WriteOption) -> BoxFuture<Result<usize>>;

    /// 异步释放指定块位置的块,释放未分配的块或释放被释放过的块是未定义行为
    fn free_block(&self, location: &BlockLocation) -> BoxFuture<bool>;

    /// 异步整理已分配的所有块
    fn collect_alloced_blocks(&self, alloced: &[BlockLocation]) -> BoxFuture<Result<usize>>;

    /// 获取一个块迭代器,用于按顺序遍历块设备的所有块
    fn blocks_iter(&self)
        -> BoxFuture<Option<Box<dyn DoubleEndedIterator<Item = BlockLocation>>>>;

    /// 获取当前块设备的提交轮次
    fn commit_round(&self) -> u64;

    /// 监听块设备提交事件
    fn on_commit(&self) -> BoxFuture<Result<Box<dyn CommitEvent>>>;
}

///
/// 异步从块设备的指定块位置上写入数据的选项
///
#[derive(Debug, Clone, Copy)]
pub enum WriteOption {
    None,       //不同步关键数据
    Sync,       //只同步关键数据
    SyncAll,    //同步关键数据和元信息
}

///
/// 块设备提交事件
///
pub trait CommitEvent {
    /// 判断是否正在提交
    fn is_commiting(&self) -> bool;

    /// 判断是否已提交
    fn is_commited(&self) -> bool;

    /// 当前提交轮次
    fn round(&self) -> u64;

    /// 当前提交时间
    fn time(&self) -> Duration;

    /// 当前提交结果
    fn result(&self) -> Option<&Result<()>>;
}

///
/// 块位置,指向块设备内的指定物理地址
/// 块位置可以描述的最大块单位数量为0xffff
/// 块位置可以描述的最大寻址空间为0xffffffffffff
///
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct BlockLocation(u64);

unsafe impl Send for BlockLocation {}
unsafe impl Sync for BlockLocation {}

impl From<u64> for BlockLocation {
    fn from(src: u64) -> Self {
        BlockLocation::new(src)
    }
}

impl From<BlockLocation> for u64 {
    fn from(BlockLocation(locaction): BlockLocation) -> Self {
        locaction
    }
}

impl Deref for BlockLocation {
    type Target = u64;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl AsRef<u64> for BlockLocation {
    fn as_ref(&self) -> &u64 {
        &self.0
    }
}

impl BlockLocation {
    /// 创建块位置
    #[inline]
    pub(crate) fn new(location: u64) -> Self {
        BlockLocation(location)
    }

    /// 创建空块
    #[inline]
    pub fn empty() -> Self {
        BlockLocation(EMPTY_BLOCK)
    }

    /// 判断当前块位置是否为空
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.0 == 0
    }
}