1use crate::common::*;
2use crate::configure::*;
3use crate::mmapbuf::*;
4use crate::packet::*;
5use bincode::deserialize_from;
6use serde::{Deserialize, Serialize};
7use std::borrow::Borrow;
8use std::fmt;
9use std::{
10 fs::OpenOptions,
11 path::{Path, PathBuf},
12};
13
14#[derive(Debug)]
15pub struct ChunkIndex {
16 configure: &'static Configure,
17 buf_writer: Option<MmapBufWriter>,
18}
19
20impl ChunkIndex {
21 pub fn new(configure: &'static Configure) -> Self {
22 ChunkIndex {
23 configure,
24 buf_writer: None,
25 }
26 }
27
28 pub fn init_dir(&mut self, dir: &Path) -> Result<(), StoreError> {
29 let mut path = PathBuf::new();
30 path.push(dir);
31 path.push("chunkindex.ci");
32 let result = OpenOptions::new()
33 .read(true)
34 .write(true)
35 .create(true)
36 .truncate(false)
37 .open(path);
38 match result {
39 Ok(fd) => {
40 let meta = fd.metadata()?;
41 self.buf_writer = Some(MmapBufWriter::with_arg(
42 fd,
43 meta.len(),
44 self.configure.ci_buff_size,
45 ));
46 }
47 Err(e) => return Err(StoreError::IoError(e)),
48 }
49 Ok(())
50 }
51
52 pub fn change_dir(&mut self) -> Result<(), StoreError> {
53 self.buf_writer = None;
54 Ok(())
55 }
56
57 pub fn write(&mut self, record: ChunkIndexRd) -> Result<u64, StoreError> {
58 let ci_offset = self.buf_writer.borrow().as_ref().unwrap().next_offset();
59 if let Some(ref mut writer) = self.buf_writer {
60 if bincode::serialize_into(writer, &record).is_err() {
61 return Err(StoreError::WriteError(
62 "chunk index write error".to_string(),
63 ));
64 }
65 }
66 Ok(ci_offset)
67 }
68
69 pub fn finish(&mut self) {
70 self.buf_writer = None;
71 }
72}
73
74#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Clone, Copy)]
75pub struct ChunkIndexRd {
76 pub start_time: u128,
77 pub end_time: u128,
78 pub chunk_id: u32,
79 pub chunk_offset: u32,
80 pub tuple5: PacketKey,
81}
82
83impl fmt::Display for ChunkIndexRd {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 write!(
86 f,
87 "ChunkIndexRd {{ start_time: {}, end_time: {}, chunk_id: {}, chunk_offset: {}, tuple5: {:?} }}",
88 ts_date(self.start_time),
89 ts_date(self.end_time),
90 self.chunk_id,
91 self.chunk_offset,
92 self.tuple5,
93 )
94 }
95}
96
97pub fn dump_chunkindex_file(path: PathBuf) -> Result<(), StoreError> {
98 match path.extension() {
99 Some(ext) => {
100 if !ext.to_str().unwrap().eq("ci") {
101 return Err(StoreError::CliError("not chunkindex file".to_string()));
102 }
103 }
104 None => return Err(StoreError::CliError("not chunkindex file".to_string())),
105 };
106
107 let file = match OpenOptions::new()
108 .read(true)
109 .write(true)
110 .create(false)
111 .truncate(false)
112 .open(&path)
113 {
114 Ok(fd) => fd,
115 Err(e) => {
116 return Err(StoreError::CliError(format!("open file error: {}", e)));
117 }
118 };
119 let mut mmap_reader = MmapBufReader::new(file);
120 println!("dump chunkid file: {:?}", path);
121 while let Ok(record) = deserialize_from::<_, ChunkIndexRd>(&mut mmap_reader) {
122 println!("record: {}", record);
123 }
124 Ok(())
125}