Skip to content

Commit efe3a04

Browse files
committed
feat: add paging for handle with overflow pages
1 parent 9acd6d1 commit efe3a04

12 files changed

Lines changed: 650 additions & 685 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@ fs2 = "0.4.3"
2727
bincode = "1.3.3"
2828
crc32fast = "1.4.2"
2929
glob = "0.3.1"
30-
log = { version = "0.4", features = [
31-
"max_level_debug",
32-
"release_max_level_warn",
33-
] }
30+
log = { version = "0.4", features = ["std"] }
3431

3532
[build-dependencies]
3633
hooky-rs = "1.0.0"

src/error.rs

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,21 @@
1-
use std::fmt::Debug;
2-
3-
use glob::PatternError;
1+
use std::{fmt::Debug, io};
42

53
pub enum Error {
6-
IoError(std::io::Error),
7-
SerializeError(bincode::Error),
8-
Deadlock,
9-
DatabaseLocked,
10-
AlreadyExists(String),
11-
NotFound(String),
12-
CorruptedData(CorruptedDataError),
4+
Io(io::Error),
5+
Parsing(bincode::Error),
6+
Corrupted(CorruptedDataError),
7+
NotEnoughSpace,
138
Other(String),
14-
Cannot(String),
15-
PatternError(PatternError),
169
}
1710

1811
impl Debug for Error {
1912
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2013
match self {
21-
Error::IoError(err) => write!(f, "IO Error: {}", err),
22-
Error::Deadlock => write!(f, "Deadlock"),
23-
Error::DatabaseLocked => {
24-
write!(f, "Database is locked, maybe another instance is running?")
25-
}
26-
Error::Other(err) => write!(f, "Other Error: {}", err),
27-
Error::CorruptedData(err) => write!(f, "{:?}", err),
28-
Error::AlreadyExists(message) => write!(f, "{} already exists", message),
29-
Error::NotFound(message) => write!(f, "{} not found", message),
30-
Error::Cannot(message) => write!(f, "cannot {}", message),
31-
Error::SerializeError(error) => write!(f, "serialize error {}", error),
32-
Error::PatternError(error) => write!(f, "pattern error {}", error),
14+
Error::Io(err) => write!(f, "{err}"),
15+
Error::Parsing(err) => write!(f, "{err}"),
16+
Error::Corrupted(msg) => write!(f, "Corrupted data: {:?}", msg),
17+
Error::NotEnoughSpace => write!(f, "Not enough space"),
18+
Error::Other(msg) => write!(f, "{}", msg),
3319
}
3420
}
3521
}

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ impl DustData {
140140
let dustdata_config = dustdata_config();
141141

142142
fs::remove_dir_all(dustdata_config.data_path.join(name))
143-
.map_err(|_| error::Error::NotFound("collection".to_owned()))?;
143+
.map_err(|_| error::Error::Other("collection not found".to_owned()))?;
144144

145145
Ok(())
146146
}

src/page/io.rs renamed to src/page/block.rs

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use serde::{de::DeserializeOwned, Serialize};
21
use std::{
32
fs::{self, File, OpenOptions},
43
io::{self, Read, Seek, Write},
@@ -10,7 +9,6 @@ use crate::spec::ValueTrait;
109
use super::{
1110
cache::{Cache, CacheBuilder},
1211
layout::BlockHeader,
13-
pager::Pager,
1412
spec::{PageNumber, BLOCK_HEADER_SIZE, PAGE_SIZE},
1513
Page,
1614
};
@@ -30,13 +28,13 @@ use super::{
3028
/// | Page 04 |
3129
/// +--------------+
3230
/// ```
33-
pub struct BlockIO {
31+
pub struct Block {
3432
pub header: BlockHeader,
3533
file: File,
3634
cache: Cache,
3735
}
3836

39-
impl BlockIO {
37+
impl Block {
4038
pub fn new<P>(path: P) -> io::Result<Self>
4139
where
4240
P: AsRef<Path>,
@@ -56,14 +54,11 @@ impl BlockIO {
5654
let header = if is_empty(&file)? {
5755
let header = BlockHeader::new();
5856

59-
let header_bytes = header.to_vec();
60-
61-
file.seek(io::SeekFrom::Start(0))?;
62-
file.write_all(&header_bytes)?;
57+
Self::write_header(&mut file, &header)?;
6358

6459
header
6560
} else {
66-
let header = read_block_header(&mut file)?;
61+
let header = Self::read_header(&mut file)?;
6762

6863
if !header.is_valid() {
6964
return Err(io::Error::new(
@@ -107,7 +102,7 @@ impl BlockIO {
107102
Self::from_file(new_file)
108103
}
109104

110-
pub fn write_new_page(&mut self, page: &Page) -> io::Result<u64> {
105+
pub fn write_new_page(&mut self, page: &Page) -> io::Result<u32> {
111106
let new_index = self.len()?;
112107

113108
self.write_page(new_index.into(), page)?;
@@ -146,35 +141,27 @@ impl BlockIO {
146141
Ok(page)
147142
}
148143

149-
pub fn page<T>(&mut self, page_index: u64) -> io::Result<Pager<T>>
144+
pub fn page<T>(&mut self, page_index: u64) -> io::Result<Page>
150145
where
151146
T: ValueTrait,
152147
{
153148
let page = self.read_page(page_index)?;
154149

155-
Ok(Pager::new(self, page, page_index as u32))
156-
}
157-
158-
pub fn write_header(&mut self) -> io::Result<()> {
159-
self.file.seek(io::SeekFrom::Start(0))?;
160-
161-
self.file.write_all(&self.header.to_vec())?;
162-
163-
Ok(())
150+
Ok(page)
164151
}
165152

166-
pub fn len(&self) -> io::Result<u64> {
153+
pub fn len(&self) -> io::Result<u32> {
167154
let file_size = self.size()?;
168155

169-
Ok(file_size - BLOCK_HEADER_SIZE as u64 / PAGE_SIZE as u64)
156+
Ok((file_size as u32 - BLOCK_HEADER_SIZE as u32) / PAGE_SIZE as u32)
170157
}
171158

172159
pub fn is_empty(&self) -> io::Result<bool> {
173160
Ok(self.len()? == 0)
174161
}
175162

176163
pub fn exists(&self, page_index: PageNumber) -> io::Result<bool> {
177-
Ok(self.len()? > page_index as u64)
164+
Ok(self.len()? > page_index)
178165
}
179166

180167
pub fn index_to_offset(&self, page_index: u64) -> u64 {
@@ -190,6 +177,30 @@ impl BlockIO {
190177
pub fn sync(&self) -> io::Result<()> {
191178
self.file.sync_data()
192179
}
180+
181+
pub fn persist_header(&mut self) -> io::Result<()> {
182+
Self::write_header(&mut self.file, &self.header)?;
183+
184+
Ok(())
185+
}
186+
187+
fn write_header(file: &mut File, header: &BlockHeader) -> io::Result<()> {
188+
file.seek(io::SeekFrom::Start(0))?;
189+
190+
file.write_all(&header.to_vec())?;
191+
192+
Ok(())
193+
}
194+
195+
fn read_header(file: &mut File) -> io::Result<BlockHeader> {
196+
let mut buffer = [0; BLOCK_HEADER_SIZE];
197+
198+
file.seek(io::SeekFrom::Start(0))?;
199+
200+
file.read_exact(&mut buffer)?;
201+
202+
Ok(BlockHeader::from_slice(&buffer))
203+
}
193204
}
194205

195206
pub fn open_file(path: &Path) -> io::Result<File> {
@@ -208,13 +219,3 @@ pub fn is_empty(file: &File) -> io::Result<bool> {
208219

209220
Ok(metadata.is_file() && metadata.len() == 0)
210221
}
211-
212-
pub fn read_block_header(file: &mut File) -> io::Result<BlockHeader> {
213-
let mut buffer = [0; BLOCK_HEADER_SIZE];
214-
215-
file.seek(io::SeekFrom::Start(0))?;
216-
217-
file.read_exact(&mut buffer)?;
218-
219-
Ok(BlockHeader::from_slice(&buffer))
220-
}

src/page/cache/mod.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -238,19 +238,19 @@ mod cache_tests {
238238
fn put_test() {
239239
let mut cache = CacheBuilder::new().max_size(2).build();
240240

241-
cache.put(0, Page::create(0).unwrap());
242-
cache.put(1, Page::create(0).unwrap());
241+
cache.put(0, Page::create(0, 0).unwrap());
242+
cache.put(1, Page::create(0, 0).unwrap());
243243

244244
assert_eq!(cache.len(), 2);
245245
}
246246

247247
#[test]
248248
fn contains_test() {
249249
let mut cache = CacheBuilder::new().max_size(4).build();
250-
let page = Page::create(0).unwrap();
251-
let page1 = Page::create(0).unwrap();
252-
let page2 = Page::create(0).unwrap();
253-
let page3 = Page::create(0).unwrap();
250+
let page = Page::create(0, 0).unwrap();
251+
let page1 = Page::create(0, 0).unwrap();
252+
let page2 = Page::create(0, 0).unwrap();
253+
let page3 = Page::create(0, 0).unwrap();
254254

255255
cache.put(0, page.clone());
256256
cache.put(1, page1.clone());

src/page/layout.rs

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ pub struct PageHeader {
77
pub lower: LocationOffset,
88
pub upper: LocationOffset,
99
pub special: LocationOffset,
10-
pub next_page: Option<u64>,
1110
pub flags: u8,
1211
}
1312

@@ -23,6 +22,10 @@ impl PageHeader {
2322
pub fn has(&self, flag: PageFlag) -> bool {
2423
self.flags & (flag as u8) != 0
2524
}
25+
26+
pub fn not_has(&self, flag: PageFlag) -> bool {
27+
self.flags & (flag as u8) == 0
28+
}
2629
}
2730

2831
pub enum PageFlag {
@@ -34,16 +37,16 @@ pub enum PageFlag {
3437
#[derive(Serialize, Deserialize, Debug, Clone)]
3538
pub struct BlockHeader {
3639
pub magic: [u8; 14],
37-
pub root_page: Option<PageNumber>,
38-
pub first_free_page_overflow: Option<PageNumber>,
40+
pub root_page: PageNumber,
41+
pub free_page_overflow: PageNumber,
3942
}
4043

4144
impl Default for BlockHeader {
4245
fn default() -> Self {
4346
Self {
4447
magic: *BLOCK_MAGIC_BYTES,
45-
root_page: None,
46-
first_free_page_overflow: None,
48+
root_page: 0,
49+
free_page_overflow: 0,
4750
}
4851
}
4952
}
@@ -66,35 +69,46 @@ impl BlockHeader {
6669
}
6770
}
6871

69-
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
70-
pub struct CellPointerMetadata {
72+
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
73+
pub struct TuplePointerMetadata {
7174
pub flags: u8,
72-
pub has_overflow: bool,
7375
}
7476

75-
impl CellPointerMetadata {
77+
impl TuplePointerMetadata {
7678
pub fn to_vec(&self) -> Vec<u8> {
7779
bincode::serialize(self).unwrap()
7880
}
7981

8082
pub fn from_slice(bytes: &[u8]) -> Self {
8183
bincode::deserialize(bytes).unwrap()
8284
}
85+
86+
pub fn set(&mut self, flag: TuplePointerFlags) {
87+
self.flags |= flag as u8
88+
}
89+
90+
pub fn unset(&mut self, flag: TuplePointerFlags) {
91+
self.flags &= !(flag as u8)
92+
}
93+
94+
pub fn has(&self, flag: TuplePointerFlags) -> bool {
95+
self.flags & (flag as u8) != 0
96+
}
97+
98+
pub fn not_has(&self, flag: TuplePointerFlags) -> bool {
99+
self.flags & (flag as u8) == 0
100+
}
83101
}
84102

85-
#[derive(Default, PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
86-
pub enum CellPointerFlags {
87-
#[default]
103+
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
104+
pub enum TuplePointerFlags {
88105
None = 0b0000_0000,
89106
Deleted = 0b0000_0001,
107+
OverflowItem = 0b0000_0010,
90108
}
91109

92-
impl From<u8> for CellPointerFlags {
93-
fn from(byte: u8) -> Self {
94-
match byte {
95-
0b0000_0000 => CellPointerFlags::None,
96-
0b0000_0001 => CellPointerFlags::Deleted,
97-
_ => panic!("Invalid cell pointer metadata: {:#02x}", byte),
98-
}
110+
impl Default for TuplePointerFlags {
111+
fn default() -> Self {
112+
Self::None
99113
}
100114
}

0 commit comments

Comments
 (0)