diff --git a/server/src/engine/storage/v1/mod.rs b/server/src/engine/storage/v1/mod.rs index 04ccb986..ad07016f 100644 --- a/server/src/engine/storage/v1/mod.rs +++ b/server/src/engine/storage/v1/mod.rs @@ -25,3 +25,4 @@ */ mod header_impl; +mod rw; diff --git a/server/src/engine/storage/v1/rw.rs b/server/src/engine/storage/v1/rw.rs new file mode 100644 index 00000000..2474aff0 --- /dev/null +++ b/server/src/engine/storage/v1/rw.rs @@ -0,0 +1,104 @@ +/* + * Created on Fri May 19 2023 + * + * This file is a part of Skytable + * Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source + * NoSQL database written by Sayan Nandan ("the Author") with the + * vision to provide flexibility in data modelling without compromising + * on performance, queryability or scalability. + * + * Copyright (c) 2023, Sayan Nandan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * +*/ + +use { + super::header_impl::SDSSHeader, + crate::{ + util::{ByteRepr, NumericRepr}, + IoResult, + }, + std::{ + fs::{File, OpenOptions}, + io::Write, + }, +}; + +/* + Writer interface +*/ + +pub trait RawWriterInterface: Sized { + fn open_truncated(fname: &str) -> IoResult; + fn open_create(fname: &str) -> IoResult; + fn fwrite_all(&mut self, bytes: &[u8]) -> IoResult<()>; + fn fsync_all(&mut self) -> IoResult<()>; +} + +impl RawWriterInterface for File { + fn open_truncated(fname: &str) -> IoResult { + OpenOptions::new() + .write(true) + .truncate(true) + .create(false) + .open(fname) + } + + fn open_create(fname: &str) -> IoResult { + File::create(fname) + } + + fn fwrite_all(&mut self, bytes: &[u8]) -> IoResult<()> { + Write::write_all(self, bytes) + } + + fn fsync_all(&mut self) -> IoResult<()> { + // FIXME(@ohsayan): too slow? maybe fdatasync only? + File::sync_all(self) + } +} + +/* + Writer +*/ + +pub struct SDSSWriter { + writer: W, +} + +impl SDSSWriter { + pub fn open_create_with_header(file: &str, header: SDSSHeader) -> IoResult { + let mut w = W::open_create(file)?; + w.fwrite_all(header.get0_sr())?; + w.fwrite_all(header.get1_dr_0_mdr())?; + w.fwrite_all(header.get1_dr_1_vhr_0())?; + w.fwrite_all(header.get1_dr_1_vhr_1())?; + w.fsync_all()?; + Ok(Self { writer: w }) + } + pub fn fsync_write(&mut self, data: &D) -> IoResult<()> { + self.writer.fwrite_all(data.repr())?; + self.writer.fsync_all() + } + pub fn newrite_numeric(&mut self, num: impl NumericRepr) -> IoResult<()> { + self.fsync_write(num.repr()) + } + pub fn lewrite_numeric(&mut self, num: impl NumericRepr) -> IoResult<()> { + self.fsync_write(num.le().repr()) + } + pub fn bewrite_numeric(&mut self, num: impl NumericRepr) -> IoResult<()> { + self.fsync_write(num.be().repr()) + } +} diff --git a/server/src/util/mod.rs b/server/src/util/mod.rs index 042c74a8..f29f920c 100644 --- a/server/src/util/mod.rs +++ b/server/src/util/mod.rs @@ -41,6 +41,7 @@ use { marker::PhantomData, mem::{self, MaybeUninit}, ops::Deref, + slice, }, std::process, }; @@ -330,3 +331,34 @@ impl fmt::Debug for MaybeInit { .finish() } } + +pub unsafe trait ByteRepr { + fn repr(&self) -> &[u8]; +} + +unsafe impl ByteRepr for [u8] { + fn repr(&self) -> &[u8] { + self + } +} +unsafe impl ByteRepr for str { + fn repr(&self) -> &[u8] { + self.as_bytes() + } +} + +pub trait NumericRepr: ByteRepr { + fn be(&self) -> Self; + fn le(&self) -> Self; +} + +macro_rules! byte_repr_impls { + ($($ty:ty),*) => { + $( + unsafe impl ByteRepr for $ty { fn repr(&self) -> &[u8] { unsafe { slice::from_raw_parts(self as *const $ty as *const u8, mem::size_of::()) } } } + impl NumericRepr for $ty { fn be(&self) -> $ty { <$ty>::to_be(*self) } fn le(&self) -> $ty { <$ty>::to_le(*self) } } + )* + }; +} + +byte_repr_impls!(u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isize);