aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib.rs
diff options
context:
space:
mode:
authorJan T <jan@jantuomi.fi>2024-10-01 20:58:08 +0300
committerJan Tuomi <jan@jantuomi.fi>2024-10-01 21:01:31 +0300
commit559c9a7346a263db2fde5abb4820fed4af25c385 (patch)
treef2d1113d1c7b7b475d31bd5e7e806d7700f61698 /src/lib.rs
Initial commit
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs83
1 files changed, 83 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..6a1e1d0
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,83 @@
+#[macro_use]
+extern crate log;
+pub mod log_db {
+ use fs2::FileExt;
+ use priority_queue::PriorityQueue;
+ use std::collections::BTreeMap;
+ use std::fs;
+ use std::io;
+ use std::io::Write;
+ use std::path::{Path, PathBuf};
+
+ const ACTIVE_LOG_FILENAME: &str = "db";
+
+ pub trait Record {
+ fn serialize(&self) -> Vec<u8>;
+ fn deserialize(data: Vec<u8>) -> Self;
+ }
+
+ pub struct Config {
+ /// Directory where the database will store its data.
+ pub data_dir: String,
+ /// The maximum size of a segment file in bytes.
+ /// Once a segment file reaches this size, it is closed and a new one is created.
+ /// Closed segment files can be compacted.
+ pub segment_size: u64,
+ /// The maximum size of a single memtable in bytes.
+ /// Note that each secondary index will have its own memtable.
+ pub memtable_size: u64,
+ }
+
+ pub struct DB<T: Record> {
+ data_dir: String,
+ segment_size: u64,
+ memtable_size: u64,
+
+ pub log_path: PathBuf,
+ primary_memtable: BTreeMap<u64, T>,
+ }
+
+ impl<T: Record> DB<T> {
+ pub fn initialize(config: &Config) -> Result<DB<T>, io::Error> {
+ info!("Initializing DB");
+ // If data_dir does not exist, create it
+ if !fs::exists(&config.data_dir)? {
+ fs::create_dir_all(&config.data_dir)?;
+ }
+
+ let log_path = Path::new(&config.data_dir).join(ACTIVE_LOG_FILENAME);
+
+ let db = DB::<T> {
+ data_dir: config.data_dir.clone(),
+ segment_size: config.segment_size,
+ memtable_size: config.memtable_size,
+
+ log_path,
+ primary_memtable: BTreeMap::new(),
+ };
+ Ok(db)
+ }
+
+ pub fn upsert(&self, record: &T) -> Result<(), io::Error> {
+ let mut file = fs::OpenOptions::new()
+ .create(true)
+ .append(true)
+ .open(&self.log_path)?;
+
+ // Acquire an exclusive lock for writing
+ file.lock_exclusive()?;
+
+ // Write the record to the log
+ let serialized = record.serialize();
+ file.write_all(&serialized)?;
+
+ // Sync to disk
+ file.flush()?;
+ file.sync_all()?;
+
+ file.unlock()?;
+
+ Ok(())
+ }
+ }
+}