From c28a88f843f3209cd18b593bcefa0076dd92ad1b Mon Sep 17 00:00:00 2001 From: Guillaume Binet Date: Fri, 24 May 2024 10:39:33 -0400 Subject: [PATCH] WIP on copper log --- copper_log/Cargo.toml | 2 + copper_log/src/index.rs | 83 +++++++++++++++++++++++++++++++++++++++++ copper_log/src/lib.rs | 5 ++- 3 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 copper_log/src/index.rs diff --git a/copper_log/Cargo.toml b/copper_log/Cargo.toml index fc21e038a..d722b703f 100644 --- a/copper_log/Cargo.toml +++ b/copper_log/Cargo.toml @@ -11,3 +11,5 @@ proc-macro = true proc-macro2 = { version = "1.0.83", features = ["span-locations"] } quote = "1.0.36" syn = { version = "2.0.65", features = ["full"] } +rkv = { version = "0.19.0", features = ["lmdb"] } +lazy_static = { version = "1.4.0" } diff --git a/copper_log/src/index.rs b/copper_log/src/index.rs new file mode 100644 index 000000000..262956506 --- /dev/null +++ b/copper_log/src/index.rs @@ -0,0 +1,83 @@ +use lazy_static::lazy_static; +use rkv::backend::{BackendEnvironment, Lmdb, LmdbDatabase}; +use rkv::backend::{LmdbEnvironment, LmdbRwTransaction}; +use rkv::{Manager, MultiStore, Rkv, SingleStore, StoreOptions, Value, Writer}; +use std::path::Path; +use std::sync::Mutex; + +type SStore = SingleStore; +type MStore = MultiStore; + +lazy_static! { + static ref RKV: Mutex> = { + let outdir = std::env::var("OUT_DIR").expect("no OUT_DIR set, build.rs must be broken"); + let path = Path::new(&outdir).join("copper_log_index.lmdb"); + //if !path.exists() { + // fs::create_dir_all(path).unwrap(); + //} + let env = Rkv::new::(&path).unwrap(); + Mutex::new(env) + }; + static ref DBS: Mutex<(SStore, SStore, SStore, MStore)> = { + let env = RKV.lock().unwrap(); + let counter = env.open_single("counter", StoreOptions::create()).unwrap(); + let index_to_string = env.open_single("index_to_string", StoreOptions::create()).unwrap(); + let string_to_index = env.open_single("string_to_index", StoreOptions::create()).unwrap(); + let index_to_callsites = env.open_multi("index_to_callsites", StoreOptions::create()).unwrap(); + + Mutex::new((counter, index_to_string, string_to_index, index_to_callsites)) + }; +} + +fn check_and_insert(filename: &str, line_number: u32, log_string: &str) -> Option { + let mut env = RKV.lock().unwrap(); + let (counter_store, index_to_string, string_to_index, index_to_callsite) = + &mut *DBS.lock().unwrap(); + // If this string already exists in the store, return the index + { + let reader = env.read().unwrap(); + // check if log_string is already in the string_to_index store + if let Ok(Some(Value::U64(index))) = string_to_index.get(&reader, log_string) { + return Some(index); + }; + } + let mut writer = env.write().unwrap(); + let next_index = get_next_index(&mut writer, counter_store).unwrap(); + // Insert the new string into the store + index_to_string + .put( + &mut writer, + next_index.to_le_bytes(), + &Value::Str(log_string), + ) + .unwrap(); + string_to_index + .put(&mut writer, log_string, &Value::U64(next_index)) + .unwrap(); + index_to_callsite + .put( + &mut writer, + next_index.to_le_bytes(), + &Value::Str(format!("{}:{}", filename, line_number).as_str()), + ) + .unwrap(); + None +} + +const COUNTER_KEY: &str = "__counter__"; +fn get_next_index( + writer: &mut Writer, + counter_store: &SStore, +) -> Result> { + // Get the current counter value + let current_counter = match counter_store.get(writer, COUNTER_KEY)? { + Some(Value::U64(value)) => value as u64, + _ => 0, + }; + + // Increment the counter + let next_counter = current_counter + 1; + counter_store.put(writer, COUNTER_KEY, &Value::U64(next_counter as u64))?; + + Ok(next_counter) +} diff --git a/copper_log/src/lib.rs b/copper_log/src/lib.rs index 376f4e283..db03253b4 100644 --- a/copper_log/src/lib.rs +++ b/copper_log/src/lib.rs @@ -1,7 +1,8 @@ +mod index; + extern crate proc_macro; use proc_macro::TokenStream; -use proc_macro2::Span; use quote::quote; use syn::{parse_macro_input, LitStr}; @@ -13,7 +14,7 @@ pub fn debug(input: TokenStream) -> TokenStream { let expanded = quote! { { let log_message = #message; - println!("Log: {:?}", log_message); + println!("{}:{} Log: {:?}", file!(), line!(), log_message); log_message } };