From 0d6460b01cd74937c9cdae14b6104c9a706b1501 Mon Sep 17 00:00:00 2001 From: yukirij Date: Sun, 13 Apr 2025 00:59:01 -0700 Subject: [PATCH] Change io for tokio async. --- Cargo.lock | 326 ++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 2 + src/bin/test.rs | 19 +-- src/blockfile/mod.rs | 176 +++++++++++------------ src/triefile/mod.rs | 90 ++++++------ 5 files changed, 470 insertions(+), 143 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 81b2551..f325849 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,21 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "autocfg" @@ -8,6 +23,87 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "libc" +version = "0.2.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + [[package]] name = "num" version = "0.4.3" @@ -81,6 +177,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + [[package]] name = "pack" version = "0.1.0" @@ -89,9 +194,228 @@ dependencies = [ "num", ] +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" + +[[package]] +name = "socket2" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "storage" version = "0.1.0" dependencies = [ "pack", + "tokio", ] + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.44.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml index f89161c..92e66b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,4 +5,6 @@ edition = "2021" [dependencies] +tokio = { version = "1.44.1", features = ["full"] } + pack = { git = "https://git.tsukiyo.org/Utility/pack" } diff --git a/src/bin/test.rs b/src/bin/test.rs index 830df4c..125d00f 100644 --- a/src/bin/test.rs +++ b/src/bin/test.rs @@ -1,7 +1,8 @@ //use storage::BlockFile; use storage::*; -fn main() +#[tokio::main] +async fn main() { std::fs::create_dir_all("data").ok(); @@ -16,7 +17,7 @@ fn main() } */ - if let Ok(mut tf) = TrieFile::<8>::open("data/cache_index.bin") { + if let Ok(mut tf) = TrieFile::<8>::open("data/cache_index.bin").await { for s in [ "Hello", @@ -27,31 +28,31 @@ fn main() "Regards", ] { println!("# insert {}", s); - if tf.set(s.as_bytes(), s.as_bytes()).is_err() { + if tf.set(s.as_bytes(), s.as_bytes()).await.is_err() { println!("Failed to insert '{}'.", s); } - if let Ok(Some(id)) = tf.find(s.as_bytes()) { + if let Ok(Some(id)) = tf.find(s.as_bytes()).await { println!("found '{}'.", id); - if let Ok(key) = tf.key(id) { + if let Ok(key) = tf.key(id).await { println!(" > '{}'", String::from_utf8(key).unwrap()); } - if let Ok(Some(data)) = tf.get(id) { + if let Ok(Some(data)) = tf.get(id).await { println!(" = '{}'", String::from_utf8(data).unwrap()); } } } - for i in tf.ids().unwrap() { + for i in tf.ids().await.unwrap() { println!("id {}", i); - if let Ok(key) = tf.key(i) { + if let Ok(key) = tf.key(i).await { println!(" > '{}'", String::from_utf8(key).unwrap()); } - if let Ok(Some(data)) = tf.get(i) { + if let Ok(Some(data)) = tf.get(i).await { println!(" = '{}'", String::from_utf8(data).unwrap()); } } diff --git a/src/blockfile/mod.rs b/src/blockfile/mod.rs index aef39ba..d2b9c76 100644 --- a/src/blockfile/mod.rs +++ b/src/blockfile/mod.rs @@ -14,10 +14,10 @@ use pack::prelude::*; -use std::{ +use std::path::Path; +use tokio::{ fs::File, - io::{Read, Seek, SeekFrom, Write}, - path::Path, + io::{AsyncReadExt, AsyncSeekExt, SeekFrom, AsyncWriteExt}, }; const HEADER_SIZE :usize = 16; @@ -39,7 +39,7 @@ pub struct BlockFile { file:File, } impl BlockFile { - pub fn open>(path:P) -> Result + pub async fn open>(path:P) -> Result { if path.as_ref().exists() { @@ -47,7 +47,7 @@ impl BlockFile { match File::options() .read(true) .write(true) - .open(path) { + .open(path).await { Ok(file) => { Ok(Self { file }) } @@ -60,16 +60,16 @@ impl BlockFile { .create_new(true) .read(true) .write(true) - .open(path) { + .open(path).await { Ok(file) => { - Self { file }.init() + Self { file }.init().await } Err(error) => Err(error), } } } - fn init(mut self) -> Result + async fn init(mut self) -> Result // Write initial headers to the file. // { @@ -95,11 +95,11 @@ impl BlockFile { data[index + 3] = pack_pointer[3]; } - self.file.write(&data)?; + self.file.write(&data).await?; Ok(self) } - pub fn insert(&mut self, data:&[u8]) -> Result + pub async fn insert(&mut self, data:&[u8]) -> Result // Acquire a new object id and write its data to new allocations. // { @@ -108,11 +108,11 @@ impl BlockFile { let block_count = Self::block_count_from_size(data.len()); //println!("block_count {}", block_count); - let blocks = self.allocate(block_count.max(1))?; + let blocks = self.allocate(block_count.max(1)).await?; //println!("blocks {}", blocks.len()); // Get object id - let id = self.acquire_object(blocks[0], data.len())?; + let id = self.acquire_object(blocks[0], data.len()).await?; //println!("obj_id {}", id); @@ -138,37 +138,37 @@ impl BlockFile { block_data[Z - 1] = pack_next[3]; } - self.write_block(blocks[block_index], &block_data)?; + self.write_block(blocks[block_index], &block_data).await?; } Ok(id) } - pub fn update(&mut self, id:usize, data:&[u8]) -> Result<(), std::io::Error> + pub async fn update(&mut self, id:usize, data:&[u8]) -> Result<(), std::io::Error> // Write new data to an object expanding its existing allocation. // { // Get first block and data size - let (mut block_id, _) = self.get_object(id)?; + let (mut block_id, _) = self.get_object(id).await?; let required_blocks = Self::block_count_from_size(data.len()); let mut blocks = Vec::new(); // Count blocks while block_id != 0 { - let next = self.read_block_pointer(block_id)?; + let next = self.read_block_pointer(block_id).await?; blocks.push(block_id); block_id = next; } if blocks.len() > required_blocks { // Free excess blocks - self.release(&blocks[required_blocks..])?; + self.release(&blocks[required_blocks..]).await?; blocks.resize(required_blocks, 0); } else if blocks.len() < required_blocks { // Allocate additional blocks - let allocated_blocks = self.allocate(required_blocks - blocks.len())?; + let allocated_blocks = self.allocate(required_blocks - blocks.len()).await?; blocks.extend_from_slice(&allocated_blocks); } @@ -194,32 +194,32 @@ impl BlockFile { block_data[Z - 1] = pack_next[3]; } - self.write_block(blocks[block_index], &block_data)?; + self.write_block(blocks[block_index], &block_data).await?; } Ok(()) } - pub fn remove(&mut self, _id:usize) -> Result<(), std::io::Error> + pub async fn remove(&mut self, _id:usize) -> Result<(), std::io::Error> // Remove the object with the specified identifier and release its allocation. // { Ok(()) } - pub fn get(&self, id:usize) -> Result, std::io::Error> + pub async fn get(&self, id:usize) -> Result, std::io::Error> // Return the object with the specified identifier. // { let mut block_data = [0u8; Z]; // Get first block and data size - let (mut block_id, size) = self.get_object(id)?; + let (mut block_id, size) = self.get_object(id).await?; let mut data = Vec::new(); // Read blocks until size is full while block_id != 0 { - self.read_block(block_id, &mut block_data)?; + self.read_block(block_id, &mut block_data).await?; let next_block = u32::unpack(&block_data, &mut (Z - 4)).unwrap_or_default(); //println!("size {} len {}", size, data.len()); @@ -238,7 +238,7 @@ impl BlockFile { Ok(data) } - pub fn ids(&self) -> Result, std::io::Error> + pub async fn ids(&self) -> Result, std::io::Error> // Traverses object list and returns allocated ids. // { @@ -249,7 +249,7 @@ impl BlockFile { Ok(output) } - fn allocate(&mut self, count:usize) -> Result, std::io::Error> + async fn allocate(&mut self, count:usize) -> Result, std::io::Error> // Mark as allocated and return the next available N blocks. // { @@ -257,9 +257,9 @@ impl BlockFile { let mut b32 = [0u8; 4]; // Read allocation table root block and depth from file. - self.file.seek(SeekFrom::Start(0))?; - self.file.read_exact(&mut b8)?; - self.file.read_exact(&mut b32)?; + self.file.seek(SeekFrom::Start(0)).await?; + self.file.read_exact(&mut b8).await?; + self.file.read_exact(&mut b32).await?; let root_block = u32::unpack(&b32, &mut 0).unwrap_or_default(); @@ -273,12 +273,12 @@ impl BlockFile { true, count, &mut blocks, - )?; + ).await?; Ok(blocks) } - fn allocate_traverse( + async fn allocate_traverse( &mut self, block_id:u32, depth:u32, @@ -294,7 +294,7 @@ impl BlockFile { //println!("allocate_traverse()"); let mut block_data = [0u8; Z]; - self.read_block(block_id, &mut block_data)?; + self.read_block(block_id, &mut block_data).await?; let mut write_block = false; let mut operation = Operation::None; @@ -325,7 +325,7 @@ impl BlockFile { } } else { // Prepare leaf block. - let leaf_block = self.end_block()?; + let leaf_block = self.end_block().await?; let mut leaf_data = vec![0u8; Z]; leaf_data[0] = 1; @@ -340,10 +340,10 @@ impl BlockFile { table_data.resize(Z, 0); next_block += 1; - self.write_block(next_block, &table_data)?; + self.write_block(next_block, &table_data).await?; } - self.write_block(leaf_block, &leaf_data)?; + self.write_block(leaf_block, &leaf_data).await?; next_block_id = Some(next_block); @@ -358,15 +358,15 @@ impl BlockFile { // If root table allocated last page, generate new root table at greater depth. if is_root && i == Self::table_size() - 1 { - let parent_blocks = self.allocate(1)?; + let parent_blocks = self.allocate(1).await?; let mut table_data = vec![0u8; Z]; // Update file header with new root table and depth. - self.file.seek(SeekFrom::Start(0))?; + self.file.seek(SeekFrom::Start(0)).await?; self.file.write(&[ (depth as u8).pack(), parent_blocks[0].pack(), - ].concat())?; + ].concat()).await?; // Add current table to first element of new table. let packed_id = block_id.pack(); @@ -375,13 +375,13 @@ impl BlockFile { table_data[1] = packed_id[1]; table_data[2] = packed_id[2]; table_data[3] = packed_id[3]; - self.write_block(parent_blocks[0], &table_data)?; + self.write_block(parent_blocks[0], &table_data).await?; // Update current table before restarting recursion. - self.write_block(block_id, &block_data)?; + self.write_block(block_id, &block_data).await?; // Restart recursion with new root. - self.allocate_traverse(parent_blocks[0], depth + 1, 0, true, count, blocks)?; + self.allocate_traverse(parent_blocks[0], depth + 1, 0, true, count, blocks).await?; return Ok(Operation::None); } } @@ -392,7 +392,7 @@ impl BlockFile { //println!("@next basis {} from d {} c {} b {}", next_basis, depth, cell_index, basis); - match self.allocate_traverse(next_block_id, depth - 1, next_basis, false, count, blocks)? { + match self.allocate_traverse(next_block_id, depth - 1, next_basis, false, count, blocks).await? { Operation::SetOccupied => { write_block = true; @@ -450,13 +450,13 @@ impl BlockFile { } if write_block { - self.write_block(block_id, &block_data)?; + self.write_block(block_id, &block_data).await?; } Ok(operation) } - fn release(&mut self, blocks:&[u32]) -> Result<(),std::io::Error> + async fn release(&mut self, blocks:&[u32]) -> Result<(),std::io::Error> // Mark a set of blocks as unallocated. // { @@ -466,9 +466,9 @@ impl BlockFile { let mut block_data = [0u8; Z]; // Read allocation table root block and depth from file. - self.file.seek(SeekFrom::Start(0))?; - self.file.read_exact(&mut b8)?; - self.file.read_exact(&mut b32)?; + self.file.seek(SeekFrom::Start(0)).await?; + self.file.read_exact(&mut b8).await?; + self.file.read_exact(&mut b32).await?; let root_page = u32::unpack(&b32, &mut 0).unwrap_or_default(); let root_depth = b8[0]; @@ -480,7 +480,7 @@ impl BlockFile { let mut offset = 0; while depth > 0 { - self.read_block(page, &mut block_data)?; + self.read_block(page, &mut block_data).await?; let index = (block - offset) / Self::pool_size().pow(depth as u32) as u32; offset = Self::table_cell_offset(depth - 1, index as u32, offset) * Self::pool_size() as u32; @@ -490,19 +490,19 @@ impl BlockFile { depth -= 1; } - self.read_block(page, &mut block_data)?; + self.read_block(page, &mut block_data).await?; let bit_index = block - offset; let byte = bit_index / 8; let bit = bit_index % 8; block_data[byte as usize] &= !(1 << bit); - self.write_block(page, &block_data)?; + self.write_block(page, &block_data).await?; } Ok(()) } - fn acquire_object(&mut self, data_id:u32, length:usize) -> Result + async fn acquire_object(&mut self, data_id:u32, length:usize) -> Result // Allocate the next available object record. // { @@ -514,14 +514,14 @@ impl BlockFile { let mut b32 = [0u8; 4]; // Read allocation table root block and depth from file. - self.file.seek(SeekFrom::Start(5))?; - self.file.read_exact(&mut b8)?; + self.file.seek(SeekFrom::Start(5)).await?; + self.file.read_exact(&mut b8).await?; let mut depth = b8[0] as u32; - self.file.read_exact(&mut b32)?; + self.file.read_exact(&mut b32).await?; let mut block_id = u32::unpack(&b32, &mut 0).unwrap_or_default(); - self.file.read_exact(&mut b32)?; + self.file.read_exact(&mut b32).await?; let object_id = u32::unpack(&b32, &mut 0).unwrap_or_default() as usize; @@ -531,7 +531,7 @@ impl BlockFile { let mut root_data = vec![0u8; Z]; while object_id > range { - let allocation = self.allocate(1)?; + let allocation = self.allocate(1).await?; let packed_id = block_id.pack(); root_data[0] = packed_id[0]; @@ -542,7 +542,7 @@ impl BlockFile { block_id = allocation[0]; depth += 1; - self.write_block(block_id, &root_data)?; + self.write_block(block_id, &root_data).await?; range = Self::table_offset(depth + 1) as usize; } @@ -552,9 +552,9 @@ impl BlockFile { let pack_depth = [ depth as u8 ]; let pack_pointer = block_id.pack(); - self.file.seek(SeekFrom::Start(5))?; - self.file.write(&pack_depth)?; - self.file.write(&pack_pointer)?; + self.file.seek(SeekFrom::Start(5)).await?; + self.file.write(&pack_depth).await?; + self.file.write(&pack_pointer).await?; } let mut basis = 0; @@ -567,7 +567,7 @@ impl BlockFile { //println!("basis: {}", basis); - self.read_block(block_id, &mut block_data)?; + self.read_block(block_id, &mut block_data).await?; let mut write_block = false; let cell_index = (object_id - basis) / Self::table_offset(depth) as usize; @@ -578,7 +578,7 @@ impl BlockFile { // Allocate new page if pointer is zero. let child_id = if cell_data == 0 { - let allocation = self.allocate(1)?; + let allocation = self.allocate(1).await?; // Write new reference to table. let pack_block = allocation[0].pack(); @@ -607,7 +607,7 @@ impl BlockFile { } } - self.write_block(allocation[0], &table_data)?; + self.write_block(allocation[0], &table_data).await?; allocation[0] } else { @@ -615,7 +615,7 @@ impl BlockFile { }; if write_block { - self.write_block(block_id, &block_data)?; + self.write_block(block_id, &block_data).await?; } // Update frame of reference to child table. @@ -627,7 +627,7 @@ impl BlockFile { //println!("end basis: {}", basis); // Update block and header with object information. - self.read_block(block_id, &mut block_data)?; + self.read_block(block_id, &mut block_data).await?; let cell_index = (object_id - basis) / Self::table_offset(depth) as usize; let cell_start = cell_index * 8; @@ -650,16 +650,16 @@ impl BlockFile { // Update header with new pointer. let pack_pointer = next_pointer.pack(); - self.file.seek(SeekFrom::Start(10))?; - self.file.write(&pack_pointer)?; + self.file.seek(SeekFrom::Start(10)).await?; + self.file.write(&pack_pointer).await?; - self.write_block(block_id, &block_data)?; + self.write_block(block_id, &block_data).await?; Ok(object_id) } - fn get_object(&self, id:usize) -> Result<(u32, usize), std::io::Error> + async fn get_object(&self, id:usize) -> Result<(u32, usize), std::io::Error> // Find initial block and data size of an object. // { @@ -667,17 +667,17 @@ impl BlockFile { //println!("get_object()"); - let mut file = self.file.try_clone()?; + let mut file = self.file.try_clone().await?; let mut b8 = [0u8; 1]; let mut b32 = [0u8; 4]; // Read allocation table root block and depth from file. - file.seek(SeekFrom::Start(5))?; - file.read_exact(&mut b8)?; + file.seek(SeekFrom::Start(5)).await?; + file.read_exact(&mut b8).await?; let mut depth = b8[0] as u32; - file.read_exact(&mut b32)?; + file.read_exact(&mut b32).await?; let mut block_id = u32::unpack(&b32, &mut 0).unwrap_or_default(); let mut basis = 0; @@ -688,7 +688,7 @@ impl BlockFile { ** Select child tables containing object_id until depth is 0. */ - self.read_block(block_id, &mut block_data)?; + self.read_block(block_id, &mut block_data).await?; let cell_index = (id - basis) / Self::table_offset(depth) as usize; @@ -708,7 +708,7 @@ impl BlockFile { } // Get object pointer and length from cell. - self.read_block(block_id, &mut block_data)?; + self.read_block(block_id, &mut block_data).await?; let cell_index = (id - basis) / Self::table_offset(depth) as usize; let mut cell_start = cell_index * 8; @@ -718,47 +718,47 @@ impl BlockFile { Ok((pointer, length as usize)) } - fn read_block(&self, block_id:u32, data:&mut [u8;Z]) -> Result<(),std::io::Error> + async fn read_block(&self, block_id:u32, data:&mut [u8;Z]) -> Result<(),std::io::Error> // Read a block from file. // { - let mut file = self.file.try_clone()?; + let mut file = self.file.try_clone().await?; - file.seek(SeekFrom::Start((HEADER_SIZE + (Z * block_id as usize)) as u64))?; - file.read_exact(data)?; + file.seek(SeekFrom::Start((HEADER_SIZE + (Z * block_id as usize)) as u64)).await?; + file.read_exact(data).await?; Ok(()) } - fn read_block_pointer(&self, block_id:u32) -> Result + async fn read_block_pointer(&self, block_id:u32) -> Result // Read the pointer element of a data block. // { - let mut file = self.file.try_clone()?; + let mut file = self.file.try_clone().await?; let mut data = [0u8; 4]; - file.seek(SeekFrom::Start((HEADER_SIZE + (Z * block_id as usize) + Self::data_size()) as u64))?; - file.read(&mut data)?; + file.seek(SeekFrom::Start((HEADER_SIZE + (Z * block_id as usize) + Self::data_size()) as u64)).await?; + file.read(&mut data).await?; Ok(u32::unpack(&data, &mut 0).unwrap()) } - fn write_block(&mut self, block_id:u32, data:&[u8]) -> Result<(), std::io::Error> + async fn write_block(&mut self, block_id:u32, data:&[u8]) -> Result<(), std::io::Error> // Write a block to file. // { - self.file.seek(SeekFrom::Start((HEADER_SIZE + (Z * block_id as usize)) as u64))?; - self.file.write(&data[0..Z])?; + self.file.seek(SeekFrom::Start((HEADER_SIZE + (Z * block_id as usize)) as u64)).await?; + self.file.write(&data[0..Z]).await?; Ok(()) } - fn end_block(&self) -> Result + async fn end_block(&self) -> Result // Id of the last block in the file. // { - let mut file = self.file.try_clone()?; - let index = file.seek(SeekFrom::End(0))? as usize; + let mut file = self.file.try_clone().await?; + let index = file.seek(SeekFrom::End(0)).await? as usize; Ok((1 + (index - HEADER_SIZE) / Z) as u32) } diff --git a/src/triefile/mod.rs b/src/triefile/mod.rs index 02c9621..18fa433 100644 --- a/src/triefile/mod.rs +++ b/src/triefile/mod.rs @@ -9,10 +9,10 @@ use pack::prelude::Pack; -use std::{ +use std::path::Path; +use tokio::{ fs::File, - io::{Read, Seek, SeekFrom, Write}, - path::Path, + io::{AsyncReadExt, AsyncSeekExt, SeekFrom, AsyncWriteExt}, }; struct Node { @@ -91,13 +91,13 @@ pub struct TrieFile { file:File, } impl TrieFile { - pub fn open>(path:P) -> Result + pub async fn open>(path:P) -> Result { match File::options() .create(true) .read(true) .write(true) - .open(path) { + .open(path).await { Ok(file) => { Ok(Self { file, @@ -107,7 +107,7 @@ impl TrieFile { } } - pub fn set(&mut self, key:&[u8], data:&[u8]) -> Result<(),std::io::Error> + pub async fn set(&mut self, key:&[u8], data:&[u8]) -> Result<(),std::io::Error> { let mut node = Node::::new(); @@ -116,9 +116,9 @@ impl TrieFile { let mut parent_index = u32::MAX; // Allocate first chain of nodes if none exist. - if self.block_count()? == 0 { + if self.block_count().await? == 0 { //println!("originate"); - self.trailing_nodes(key, &mut key_index, data, u32::MAX)?; + self.trailing_nodes(key, &mut key_index, data, u32::MAX).await?; return Ok(()); } else { //println!("traverse"); @@ -127,7 +127,7 @@ impl TrieFile { while key_index < key.len() { //println!("start k {}/{}", key_index, key.len()); - self.read_node(node_index, &mut node)?; + self.read_node(node_index, &mut node).await?; // If node shares prefix with key... if node.bytes[0] == key[key_index] { @@ -157,7 +157,7 @@ impl TrieFile { node.data[i] = data[i]; } - self.write_node(node_index, &node)?; + self.write_node(node_index, &node).await?; } // Continue to child node. @@ -172,8 +172,8 @@ impl TrieFile { else { //println!(" - new child"); - node.child = self.trailing_nodes(key, &mut key_index, data, node_index)?; - self.write_node(node_index, &node)?; + node.child = self.trailing_nodes(key, &mut key_index, data, node_index).await?; + self.write_node(node_index, &node).await?; } } @@ -192,7 +192,7 @@ impl TrieFile { node.bytes[i] = 0; } - let child_index = self.allocate()?; + let child_index = self.allocate().await?; let mut child_node = Node::::new(); child_node.parent = node_index; @@ -212,7 +212,7 @@ impl TrieFile { // Write data to trailing nodes. if key_index < key.len() { - let new_branch = self.trailing_nodes(key, &mut key_index, data, node_index)?; + let new_branch = self.trailing_nodes(key, &mut key_index, data, node_index).await?; child_node.next = new_branch; } @@ -224,8 +224,8 @@ impl TrieFile { } } - self.write_node(node_index, &node)?; - self.write_node(child_index, &child_node)?; + self.write_node(node_index, &node).await?; + self.write_node(child_index, &child_node).await?; } } @@ -241,8 +241,8 @@ impl TrieFile { //println!(" - new next"); // Allocate and initialize subsequent nodes until key is resolved. - node.next = self.trailing_nodes(key, &mut key_index, data, parent_index)?; - self.write_node(node_index, &node)?; + node.next = self.trailing_nodes(key, &mut key_index, data, parent_index).await?; + self.write_node(node_index, &node).await?; } } } @@ -251,20 +251,20 @@ impl TrieFile { Ok(()) } - pub fn find(&self, key:&[u8]) -> Result, std::io::Error> + pub async fn find(&self, key:&[u8]) -> Result, std::io::Error> { let mut node = Node::::new(); let mut node_index = 0; let mut key_index = 0; - if self.block_count()? != 0 { + if self.block_count().await? != 0 { // Traverse nodes until key is found. while key_index < key.len() { //println!("start k {}/{}", key_index, key.len()); - self.read_node(node_index, &mut node)?; + self.read_node(node_index, &mut node).await?; // If node shares prefix with key... if node.bytes[0] == key[key_index] { @@ -324,14 +324,14 @@ impl TrieFile { Ok(None) } - pub fn key(&self, id:usize) -> Result, std::io::Error> + pub async fn key(&self, id:usize) -> Result, std::io::Error> { let mut node_id = id as u32; let mut bytes = Vec::new(); let mut node = Node::::new(); while node_id != u32::MAX { - self.read_node(node_id, &mut node)?; + self.read_node(node_id, &mut node).await?; for i in (0..node.length as usize).rev() { bytes.push(node.bytes[i]); @@ -344,10 +344,10 @@ impl TrieFile { Ok(bytes) } - pub fn get(&self, id:usize) -> Result>, std::io::Error> + pub async fn get(&self, id:usize) -> Result>, std::io::Error> { let mut node = Node::::new(); - self.read_node(id as u32, &mut node)?; + self.read_node(id as u32, &mut node).await?; if node.has_data { Ok(Some(node.data.to_vec())) @@ -356,15 +356,15 @@ impl TrieFile { } } - pub fn ids(&self) -> Result, std::io::Error> + pub async fn ids(&self) -> Result, std::io::Error> { let mut output = Vec::new(); let mut node = Node::::new(); - let length = self.block_count()? as usize; + let length = self.block_count().await? as usize; for i in 0..length { - self.read_node(i as u32, &mut node)?; + self.read_node(i as u32, &mut node).await?; if node.has_data { output.push(i); @@ -379,9 +379,9 @@ impl TrieFile { Ok(()) }*/ - fn trailing_nodes(&mut self, key:&[u8], key_index:&mut usize, data:&[u8], parent:u32) -> Result + async fn trailing_nodes(&mut self, key:&[u8], key_index:&mut usize, data:&[u8], parent:u32) -> Result { - let starting_node = self.allocate()?; + let starting_node = self.allocate().await?; let mut node :Node; let mut node_index = starting_node; let mut parent_node = parent; @@ -401,7 +401,7 @@ impl TrieFile { // Allocate child node if key byte remain. if *key_index < key.len() { - node.child = self.allocate()?; + node.child = self.allocate().await?; } // Otherwise, write data to node. @@ -412,45 +412,45 @@ impl TrieFile { } } - self.write_node(node_index, &node)?; + self.write_node(node_index, &node).await?; node_index = node.child; } Ok(starting_node) } - fn read_node(&self, index:u32, node:&mut Node) -> Result<(), std::io::Error> + async fn read_node(&self, index:u32, node:&mut Node) -> Result<(), std::io::Error> { - let mut file = self.file.try_clone()?; + let mut file = self.file.try_clone().await?; let mut data = vec![0u8; Self::block_size()]; - file.seek(SeekFrom::Start((Self::block_size() * index as usize) as u64))?; - file.read_exact(&mut data)?; + file.seek(SeekFrom::Start((Self::block_size() * index as usize) as u64)).await?; + file.read_exact(&mut data).await?; node.decode(&data, &mut 0).map_err(|_| std::io::Error::other("failed to decode node block"))?; Ok(()) } - fn write_node(&mut self, index:u32, node:&Node) -> Result<(), std::io::Error> + async fn write_node(&mut self, index:u32, node:&Node) -> Result<(), std::io::Error> { - self.file.seek(SeekFrom::Start((Self::block_size() * index as usize) as u64))?; - self.file.write(&node.encode())?; + self.file.seek(SeekFrom::Start((Self::block_size() * index as usize) as u64)).await?; + self.file.write(&node.encode()).await?; Ok(()) } - fn allocate(&mut self) -> Result + async fn allocate(&mut self) -> Result { - let block_id = ((self.file.seek(SeekFrom::End(0))? as usize) / Self::block_size()) as u32; - self.file.write(&vec![0u8; Self::block_size()])?; + let block_id = ((self.file.seek(SeekFrom::End(0)).await? as usize) / Self::block_size()) as u32; + self.file.write(&vec![0u8; Self::block_size()]).await?; Ok(block_id) } - fn block_count(&self) -> Result + async fn block_count(&self) -> Result { - let mut file = self.file.try_clone()?; - Ok(((file.seek(SeekFrom::End(0))? as usize) / Self::block_size()) as u32) + let mut file = self.file.try_clone().await?; + Ok(((file.seek(SeekFrom::End(0)).await? as usize) / Self::block_size()) as u32) } const fn block_size() -> usize