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
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
use std::ops::Deref;
use std::collections::VecDeque;
use std::io::{Error, Result as IOResult, ErrorKind};
use std::marker::PhantomData;
use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};
use std::sync::atomic::AtomicU64;

use async_channel::{Sender as AsyncSender, Receiver as AsyncReceiver, bounded as async_bounded};
use bytes::{Buf, BufMut};

use pi_async_rt::lock::spin_lock::SpinLock;

pub mod page_manager;
pub mod page_pool;
pub mod page_table;
pub mod page_cache;
pub mod utils;

///
/// 虚拟页表中的空页,用于表示不存在或不可用的页,在持久化时用于描述虚拟页表的元信息所在的页
///
pub const EMPTY_PAGE: u128 = 0;

///
/// 虚拟页管理器的块设备编号,即虚拟页管理器是一个默认块设备
///
const VIRTUAL_PAGE_MANAGER_DEVICES_INDEX: u32 = 0;

///
/// 写指令的空编号,用于表示不存在或不可用的写指令
///
const EMPTY_WRITE_INDEX: u64 = 0;

///
/// 默认的编码标记
///
const DEFAULT_ENCODING_TAG: u8 = 0;

///
/// 默认的编码参数
///
const DEFAULT_ENCODING_ARG: u8 = 0;

///
/// 虚拟页的写增量
/// 所有对虚拟页的写操作,都由写增量表达,写增量之间是有顺序的
///
pub trait VirtualPageWriteDelta: Send + 'static {
    type Content: Send + Sized + 'static;  //写增量内容

    /// 获取写增量的大小,不允许比实际写增量小,单位字节
    fn size(&self) -> usize;

    /// 获取写增量所在写指令的编号
    fn get_cmd_index(&self) -> u64;

    /// 设置写增量所在写指令的编号,外部应该保证在运行时写指令的编号是唯一且递增的
    fn set_cmd_index(&mut self, cmd_index: u64);

    /// 获取写增量对应的原始的虚拟页的唯一id
    /// 表示当前写增量是相对于指定的原始虚拟页的增量,也就是增量不需要更改虚拟页唯一id
    /// 原始的虚拟页的唯一id与复制的虚拟页的唯一id相同,则表示是同一个虚拟页
    fn get_origin_page_id(&self) -> PageId;

    /// 获取写增量对应的复制的虚拟页的唯一id
    /// 表示当前写增量是作用于指定目标虚拟页的增量,也就是增量需要更改虚拟页唯一id
    /// 复制的虚拟页的唯一id与原始的虚拟页的唯一id相同,则表示是同一个虚拟页
    fn get_copied_page_id(&self) -> PageId;

    /// 获取写增量的类型
    fn get_type(&self) -> usize;

    /// 获取写增量内容
    fn inner(self) -> Self::Content;
}

///
/// 写时复制的虚拟页缓冲
/// 用于虚拟页池中页缓冲的基页,以及封装对基页的写操作
///
pub trait VirtualPageBuf: Clone + Send + Sync + 'static {
    type Content: Send + 'static; //写增量的内容
    type Delta: VirtualPageWriteDelta<Content = Self::Content>; //写增量
    type Output: Send + 'static; //读输出
    type Bin: BufMut + AsRef<[u8]> + AsMut<[u8]> + Clone + Send + Sync + 'static; //序列化输出

    /// 使用指定的原始的虚拟页的唯一id,复制的虚拟页的唯一id和页类型,构建一个写时复制的虚拟页缓冲
    /// 刚构建的虚拟页缓冲,必须保证不缺页
    fn with_page_type(origin_page_id: PageId,
                      copied_page_id: PageId,
                      page_type: Option<usize>) -> Self;

    /// 获取原始的虚拟页的唯一id
    fn get_original_page_id(&self) -> PageId;

    /// 获取复制的虚拟页的唯一id
    fn get_copied_page_id(&self) -> PageId;

    /// 判断当前虚拟页缓冲是否缺页
    fn is_missing_pages(&self) -> bool;

    /// 获取当前虚拟页缓冲的类型
    fn get_page_type(&self) -> usize;

    /// 获取当前虚拟页缓冲的大小,单位B
    fn page_size(&self) -> usize;

    /// 读虚拟页缓冲为指定的输出
    fn read_page(&self) -> Self::Output;

    /// 写增量,以修改虚拟页缓冲
    fn write_page_delta(&mut self, delta: Self::Delta) -> Result<(), String>;

    /// 将二进制数据反序列化为虚拟页缓冲
    fn deserialize_page<Input>(&mut self, bin: Input)
        where Input: AsRef<[u8]> + Send + Sized + 'static;

    /// 将虚拟页缓冲序列化为二进制数据
    fn serialize_page(self) -> Self::Bin;
}

///
/// 页面id,是指向虚拟块地址的指针
/// 页面id的最高32位,作为虚拟页管理器的唯一ID
/// 页面id的次高32位,作为块设备号,即一个虚拟页管理器支持最多挂载0xffffffff个块设备,0号设备为当前虚拟页管理器
/// 页面id的最低64位,即页表分配的虚拟页id
/// 页面id分配后,将不会改变,只会在确认释放后被回收
///
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct PageId(pub(crate) u128);

unsafe impl Send for PageId {}
unsafe impl Sync for PageId {}

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

impl From<PageId> for u128 {
    fn from(src: PageId) -> Self {
        src.0
    }
}

impl Deref for PageId {
    type Target = u128;

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

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

impl PageId {
    /// 创建页面id
    #[inline]
    pub(crate) fn new(id: u128) -> Self {
        PageId(id)
    }

    /// 创建空页
    #[inline]
    pub fn empty() -> Self {
        PageId(EMPTY_PAGE)
    }

    /// 判断是否是空页
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.0 == EMPTY_PAGE
    }

    /// 判断是否是保留页
    #[inline]
    pub fn is_reserved(&self) -> bool {
        self.owner_uid() == 0
            && self.device_offset() == 0
    }

    /// 判断是否是内部页
    #[inline]
    pub fn is_internal(&self) -> bool {
        self.owner_uid() > 0
            && self.device_offset() == 0
    }

    /// 判断是否是普通页
    #[inline]
    pub fn is_normal(&self) -> bool {
        self.owner_uid() > 0
            && self.device_offset() > 0
    }

    /// 获取页面所属的虚拟页管理器的唯一id
    #[inline]
    pub fn owner_uid(&self) -> u32 {
        (self.0 >> 96) as u32
    }

    /// 获取页面所属的块设备在虚拟页管理器中的偏移
    #[inline]
    pub fn device_offset(&self) -> u32 {
        (self.0 >> 64) as u32
    }

    /// 获取页面所属的虚拟页表的虚拟页唯一id
    #[inline]
    pub fn page_uid(&self) -> u64 {
        self.0 as u64
    }
}

///
/// 虚拟页写指令,用于批量处理关联的多个虚拟页写增量,
/// 虚拟页管理器在逻辑上会一次处理一个写指令
/// 虚拟页写指令的任意写增量执行失败,则整个写指令执行失败
///
pub struct VirtualPageWriteCmd<
    C: Send + 'static,
    D: VirtualPageWriteDelta<Content = C>,
>(Arc<InnerVirtualPageWriteCmd<C, D>>);

unsafe impl<
    C: Send + 'static,
    D: VirtualPageWriteDelta<Content = C>,
> Send for VirtualPageWriteCmd<C, D> {}
unsafe impl<
    C: Send + 'static,
    D: VirtualPageWriteDelta<Content = C>,
> Sync for VirtualPageWriteCmd<C, D> {}

impl<
    C: Send + 'static,
    D: VirtualPageWriteDelta<Content = C>,
> Clone for VirtualPageWriteCmd<C, D> {
    fn clone(&self) -> Self {
        VirtualPageWriteCmd(self.0.clone())
    }
}

/*
* 虚拟页写指令同步方法
*/
impl<
    C: Send + 'static,
    D: VirtualPageWriteDelta<Content = C>,
> VirtualPageWriteCmd<C, D> {
    /// 构建一个空的虚拟页写指令
    pub fn new() -> Self {
        VirtualPageWriteCmd::with_capacity(8, 1)
    }

    /// 构建一个指定初始容量的空的虚拟页写指令
    pub fn with_capacity(capacity: usize,
                         followup_capacity: usize) -> Self {
        let deltas = SpinLock::new(VecDeque::with_capacity(capacity));
        let followups = SpinLock::new(VecDeque::with_capacity(followup_capacity));
        let deltas_count = AtomicUsize::new(0);
        let follow_up_count = AtomicUsize::new(0);
        let (sender, receiver) = async_bounded(capacity + followup_capacity);

        let inner = InnerVirtualPageWriteCmd {
            index: AtomicU64::new(0), //默认的写指令编号
            deltas,
            followups,
            deltas_count,
            follow_up_count,
            sender,
            receiver,
        };

        VirtualPageWriteCmd(Arc::new(inner))
    }

    /// 判断写指令的写增量缓冲是否已同步完成
    pub fn is_synced_deltas(&self) -> bool {
        self.0.deltas_count.load(Ordering::Relaxed) == 0
    }

    /// 判断写指令的后续写增量缓冲是否已同步完成
    pub fn is_synced_followup_deltas(&self) -> bool {
        self.0.follow_up_count.load(Ordering::Relaxed) == 0
    }

    /// 获取写增量队列的长度
    pub fn deltas_len(&self) -> usize {
        self
            .0
            .deltas
            .lock()
            .len()
    }

    /// 获取后续写增量队列的长度
    pub fn followup_len(&self) -> usize {
        self
            .0
            .followups
            .lock()
            .len()
    }

    /// 获取当前写指令的编号
    pub fn get_index(&self) -> u64 {
        self.0.index.load(Ordering::Acquire)
    }

    /// 设置当前写指令的编号
    pub fn set_index(&mut self, index: u64) {
        self.0.index.store(index, Ordering::Release);
    }

    /// 从写指令的写增量队列头弹出一个写增量,写增量队列为空,则返回空
    pub fn pop_front(&self) -> Option<D> {
        let mut delta = self
            .0
            .deltas
            .lock()
            .pop_front();

        if let Some(inner) = delta.as_mut() {
            //为写增量设置写指令编号
            inner.set_cmd_index(self.get_index());
        }

        delta
    }

    /// 追加指定的虚拟页写增量到虚拟页写指令的写增量队列
    /// 当写增量的原始的虚拟页的唯一id等于复制的虚拟页的唯一id,则表示增量只作用于原始的虚拟页
    /// 当写增量的原始的虚拟页的唯一id不等于复制的虚拟页的唯一id,则表示将原始的虚拟页的内容完整复制到复制的虚拟页上,再将增量作用于复制的虚拟页
    /// 所以原始的虚拟页的唯一id为0且复制的虚拟页的唯一id大于0,则表示增量作用直接作用于复制的虚拟页,原始的虚拟页为空
    pub fn append(&self, delta: D) {
        let origin_page_id = delta.get_origin_page_id();
        let copied_page_id = delta.get_copied_page_id();
        if (origin_page_id.is_internal()
            || copied_page_id.is_internal())
            && (origin_page_id != copied_page_id) {
            //原始的虚拟页或复制的虚拟页中有任意一个是内部页,且原始的虚拟页与复制的虚拟页不等,则立即抛出异常
            panic!("Follow up failed, origin_page_id: {:?}, copied_page_id: {:?}, reason: the internal page id must be the same",
                   origin_page_id,
                   copied_page_id);
        }

        //追加写增量
        self
            .0
            .deltas
            .lock()
            .push_back(delta);

        //增加写增量计数
        self.0.deltas_count.fetch_add(1, Ordering::Relaxed);
    }

    /// 从写指令的后续写增量队列头弹出一个写增量,后续写增量队列为空,则返回空
    pub fn pop_front_from_followup(&self) -> Option<D> {
        let mut delta = self
            .0
            .followups
            .lock()
            .pop_front();

        if let Some(inner) = delta.as_mut() {
            //为写增量设置写指令编号
            inner.set_cmd_index(self.get_index());
        }

        delta
    }

    /// 追加指定的虚拟页写增量到虚拟页写指令的后续写增量队列
    /// 后续写增量队列中的写增量会在写增量队列全部执行完成后,再执行
    /// 当写增量的原始的虚拟页的唯一id等于复制的虚拟页的唯一id,则表示增量只作用于原始的虚拟页
    /// 当写增量的原始的虚拟页的唯一id不等于复制的虚拟页的唯一id,则表示将原始的虚拟页的内容完整复制到复制的虚拟页上,再将增量作用于复制的虚拟页
    /// 所以原始的虚拟页的唯一id为0且复制的虚拟页的唯一id大于0,则表示增量作用直接作用于复制的虚拟页,原始的虚拟页为空
    pub fn follow_up(&self, delta: D) {
        let origin_page_id = delta.get_origin_page_id();
        let copied_page_id = delta.get_copied_page_id();
        if (origin_page_id.is_internal()
            || copied_page_id.is_internal())
            && (origin_page_id != copied_page_id) {
            //原始的虚拟页或复制的虚拟页中有任意一个是内部页,且原始的虚拟页与复制的虚拟页不等,则立即抛出异常
            panic!("Follow up failed, origin_page_id: {:?}, copied_page_id: {:?}, reason: the internal page id must be the same",
                   origin_page_id,
                   copied_page_id);
        }

        //追加写增量
        self
            .0
            .followups
            .lock()
            .push_back(delta);

        //增加后续执行的写增量计数
        self.0.follow_up_count.fetch_add(1, Ordering::Relaxed);
    }
}

/*
* 虚拟页写指令异步方法
*/
impl<
    C: Send + 'static,
    D: VirtualPageWriteDelta<Content = C>,
> VirtualPageWriteCmd<C, D> {
    /// 异步写增量到块设备后的回调
    pub async fn callback_by_sync(&self, result: IOResult<u64>) -> Result<(), String> {
        if let Ok(count) = &result {
            let sync_count = *count as usize;

            let current_deltas_count = self
                .0
                .deltas_count
                .load(Ordering::Relaxed);
            if current_deltas_count == 0 {
                //写指令的所有写增量成功同步到块设备
                let current_follow_up_count = self
                    .0
                    .follow_up_count
                    .load(Ordering::Relaxed);

                self
                    .0
                    .follow_up_count
                    .store(current_follow_up_count
                               .checked_sub(sync_count)
                               .unwrap_or(0),
                           Ordering::Relaxed); //减少当前写指令的后续写增量的待同步数量
            } else {
                //写指令的写增量还未全部成功同步到块设备
                self
                    .0
                    .deltas_count
                    .store(current_deltas_count
                               .checked_sub(sync_count)
                               .unwrap_or(0),
                           Ordering::Relaxed); //减少当前写指令的写增量的待同步数量
            }
        }

        if let Err(e) = self.0.sender.send(result).await {
            return Err(format!("Callbak by sync failed, reason: {:?}", e));
        }

        Ok(())
    }

    /// 异步等待写指令的写操作同步完成,成功返回写指令编号
    pub async fn wait_write_sync(&self) -> IOResult<u64> {
        loop {
            match self
                .0
                .receiver
                .recv()
                .await {
                Err(e) => {
                    //等待写指令写操作完成失败,则立即返回错误原因
                    return Err(Error::new(ErrorKind::Other, format!("Wait write through failed, deltas_count: {}, reason: {:?}", self.0.deltas_count.load(Ordering::Relaxed), e)));
                },
                Ok(Err(e)) => {
                    //写指令的写增量同步到块设备失败,则表示写指令的写操作失败,并立即返回
                    return Err(Error::new(ErrorKind::Other, format!("Wait write through failed, deltas_count: {}, reason: {:?}", self.0.deltas_count.load(Ordering::Relaxed), e)));
                },
                Ok(Ok(_count)) => {
                    //指定数量的写增量成功同步到块设备
                    if self
                        .0
                        .deltas_count
                        .load(Ordering::Relaxed) == 0 {
                        //写指令的所有写增量成功同步到块设备,则表示写指令的写操作已完成,并立即返回
                        break;
                    }
                },
            }
        }

        Ok(self.0.index.load(Ordering::Relaxed))
    }

    /// 异步等待写指令的后续写操作同步完成,成功返回写指令编号
    pub async fn wait_write_follow_up_sync(&self) -> IOResult<u64> {
        loop {
            match self
                .0
                .receiver
                .recv()
                .await {
                Err(e) => {
                    //等待写指令写操作完成失败,则立即返回错误原因
                    return Err(Error::new(ErrorKind::Other, format!("Wait write through failed, deltas_count: {}, reason: {:?}", self.0.deltas_count.load(Ordering::Relaxed), e)));
                },
                Ok(Err(e)) => {
                    //写指令的写增量同步到块设备失败,则表示写指令的写操作失败,并立即返回
                    return Err(Error::new(ErrorKind::Other, format!("Wait write through failed, deltas_count: {}, reason: {:?}", self.0.deltas_count.load(Ordering::Relaxed), e)));
                },
                Ok(Ok(_count)) => {
                    //指定数量的写增量成功同步到块设备
                    if self
                        .0
                        .follow_up_count
                        .load(Ordering::Relaxed) == 0 {
                        //写指令的所有后续执行的写增量也成功同步到块设备,则表示写指令的后续写操作已完成,并立即返回
                        break;
                    }
                },
            }
        }

        Ok(self.0.index.load(Ordering::Relaxed))
    }
}

// 内部虚拟页写指令
pub struct InnerVirtualPageWriteCmd<
    C: Send + 'static,
    D: VirtualPageWriteDelta<Content = C>,
> {
    index:              AtomicU64,                      //写指令编号
    deltas:             SpinLock<VecDeque<D>>,          //需要执行的写增量队列
    followups:          SpinLock<VecDeque<D>>,          //需要后续执行的写增量队列
    deltas_count:       AtomicUsize,                    //写增量计数
    follow_up_count:    AtomicUsize,                    //后续执行的写增量计数
    sender:             AsyncSender<IOResult<u64>>,     //写增量同步结果发送器
    receiver:           AsyncReceiver<IOResult<u64>>,   //写增量同步结果接收器
}

///
/// 写编号
///
#[derive(Debug, Clone)]
pub struct WriteIndex(u64);

unsafe impl Send for WriteIndex {}
unsafe impl Sync for WriteIndex {}

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

impl From<WriteIndex> for u64 {
    fn from(src: WriteIndex) -> Self {
        src.0
    }
}

impl Deref for WriteIndex {
    type Target = u64;

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

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

impl WriteIndex {
    /// 创建写编号
    #[inline]
    pub(crate) fn new(index: u64) -> Self {
        WriteIndex(index)
    }

    /// 创建空的写编号
    #[inline]
    pub fn empty() -> Self {
        WriteIndex(EMPTY_WRITE_INDEX)
    }

    /// 判断是否是空的写编号
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.0 == EMPTY_WRITE_INDEX
    }
}

///
/// 虚拟页编码
///
pub trait VirtualPageEncoding: Send + Sync + 'static {
    // 原始类型
    type Raw: AsRef<[u8]> + Send + Sync + 'static;
    // 编码后类型
    type Encoded: AsRef<[u8]> + Send + Sync + 'static;

    /// 获取虚拟页编码的类型
    fn encoding_type(&self) -> VirtualPageEncodingType;

    /// 对指定输入进行编码
    fn encode(&self, raw: Self::Raw) -> IOResult<Self::Encoded>;

    /// 对指定输入进行解码
    fn decode(&self, encoded: Self::Encoded, page_len: usize) -> IOResult<Self::Raw>;
}

///
/// 虚拟页编码类型
///
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum VirtualPageEncodingType {
    Empty,      //空类型
    LZ4(u8),    //LZ4编码类型
}

impl From<(u8, u8)> for VirtualPageEncodingType {
    fn from((tag, arg): (u8, u8)) -> Self {
        match tag {
            0 => VirtualPageEncodingType::Empty,
            _ => VirtualPageEncodingType::LZ4(arg),
        }
    }
}

impl From<VirtualPageEncodingType> for (u8, u8) {
    fn from(value: VirtualPageEncodingType) -> Self {
        match value {
            VirtualPageEncodingType::Empty => (DEFAULT_ENCODING_TAG, DEFAULT_ENCODING_ARG),
            VirtualPageEncodingType::LZ4(tag) => (1, tag),
        }
    }
}

impl VirtualPageEncodingType {
    /// 判断是否是空类型
    pub fn is_empty(&self) -> bool {
        if let VirtualPageEncodingType::Empty = self {
            true
        } else {
            false
        }
    }

    /// 判断是否是LZ4编码类型
    pub fn is_lz4(&self) -> bool {
        if let VirtualPageEncodingType::LZ4(_) = self {
            true
        } else {
            false
        }
    }
}

impl VirtualPageEncodingType {
    /// 构建一个空类型
    pub fn empty() -> VirtualPageEncodingType {
        VirtualPageEncodingType::Empty
    }

    /// 构建一个LZ编码类型
    pub fn with_lz4(level: u8) -> VirtualPageEncodingType {
        VirtualPageEncodingType::LZ4(level)
    }

    /// 获取编码标记
    pub fn encoding_tag(&self) -> u8 {
        match self {
            VirtualPageEncodingType::Empty => DEFAULT_ENCODING_TAG,
            VirtualPageEncodingType::LZ4(_) => 1,
        }
    }

    /// 获取编码参数
    pub fn encoding_arg(&self) -> u8 {
        match self {
            VirtualPageEncodingType::Empty => DEFAULT_ENCODING_ARG,
            VirtualPageEncodingType::LZ4(tag) => *tag,
        }
    }
}

///
/// 默认虚拟页编码器
///
#[derive(Debug, Clone)]
pub struct DefaultVirtualPageEncoder<B: AsRef<[u8]> + Send + Sync + 'static>{
    encoding_type:  VirtualPageEncodingType,    //编码类型
    marker:         PhantomData<B>,
}

impl<B: AsRef<[u8]> + Send + Sync + 'static> Default for DefaultVirtualPageEncoder<B> {
    fn default() -> Self {
        DefaultVirtualPageEncoder {
            encoding_type: VirtualPageEncodingType::empty(),
            marker: PhantomData,
        }
    }
}

impl<B: AsRef<[u8]> + Send + Sync + 'static> VirtualPageEncoding for DefaultVirtualPageEncoder<B> {
    type Raw = B;
    type Encoded = B;

    fn encoding_type(&self) -> VirtualPageEncodingType {
        self.encoding_type
    }

    fn encode(&self, raw: Self::Raw) -> IOResult<Self::Encoded> {
        Ok(raw)
    }

    fn decode(&self, encoded: Self::Encoded, _page_len: usize) -> IOResult<Self::Raw> {
        Ok(encoded)
    }
}