diff --git a/Cargo.toml b/Cargo.toml index 0bc1e0183..8e569cfe6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,3 @@ [workspace] -members = ["copper", "copper_derive", "copper_derive_test", "copper_log", "examples/config-gen", "examples/pluginload", "examples/simplelogger", "examples/v4lsrc"] +members = ["copper", "copper_log_test", "copper_derive", "copper_derive_test", "copper_log", "examples/config_gen", "examples/pluginload", "examples/simplelogger", "examples/v4lsrc"] resolver = "2" diff --git a/copper_log/Cargo.toml b/copper_log/Cargo.toml index d722b703f..504a99475 100644 --- a/copper_log/Cargo.toml +++ b/copper_log/Cargo.toml @@ -4,11 +4,16 @@ version = "0.1.0" edition = "2021" [lib] +name = "copper_log" +path = "src/macros.rs" proc-macro = true +[[bin]] +name = "copper_log_extract" +path = "src/log_extract.rs" [dependencies] -proc-macro2 = { version = "1.0.83", features = ["span-locations"] } +proc-macro2 = { version = "1.0.83" } quote = "1.0.36" syn = { version = "2.0.65", features = ["full"] } rkv = { version = "0.19.0", features = ["lmdb"] } diff --git a/copper_log/build.rs b/copper_log/build.rs index e61c5f35f..ca3298467 100644 --- a/copper_log/build.rs +++ b/copper_log/build.rs @@ -3,4 +3,5 @@ use std::env; fn main() { let out_dir = env::var("OUT_DIR").unwrap(); println!("cargo:rustc-env=OUT_DIR={}", out_dir); + println!("cargo:rustc-env=RUSTFLAGS=--cfg procmacro2_semver_exempt"); } diff --git a/copper_log/src/index.rs b/copper_log/src/index.rs index 262956506..21f7dc67c 100644 --- a/copper_log/src/index.rs +++ b/copper_log/src/index.rs @@ -1,83 +1,104 @@ use lazy_static::lazy_static; -use rkv::backend::{BackendEnvironment, Lmdb, LmdbDatabase}; +use rkv::backend::{Lmdb, LmdbDatabase}; use rkv::backend::{LmdbEnvironment, LmdbRwTransaction}; -use rkv::{Manager, MultiStore, Rkv, SingleStore, StoreOptions, Value, Writer}; +use rkv::{MultiStore, Rkv, SingleStore, StoreOptions, Value, Writer}; +use std::fs; use std::path::Path; use std::sync::Mutex; type SStore = SingleStore; type MStore = MultiStore; +type IndexType = u32; 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 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"); + if !path.exists() { + fs::create_dir_all(&path).unwrap(); + } + println!("CLog: Storing log index at: {:?}", path); 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(); + 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)) + 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(); +pub fn check_and_insert(filename: &str, line_number: u32, log_string: &str) -> Option { 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 + let index = { + let env = RKV.lock().unwrap(); + // If this string already exists in the store, return the index + { + let reader = env.read().unwrap(); + let entry = string_to_index.get(&reader, log_string); + // 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) { + println!( + "CLog: Returning existing index #{} -> {}", + index, log_string + ); + return Some(index as IndexType); + }; + } + 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 as u64)) + .unwrap(); + index_to_callsite + .put( + &mut writer, + next_index.to_le_bytes(), + &Value::Str(format!("{}:{}", filename, line_number).as_str()), + ) + .unwrap(); + writer.commit().unwrap(); + Some(next_index) + }; + println!("CLog: Inserted #{} -> {}", index.unwrap(), log_string); + index } const COUNTER_KEY: &str = "__counter__"; fn get_next_index( writer: &mut Writer, counter_store: &SStore, -) -> Result> { - // Get the current counter value +) -> Result> { let current_counter = match counter_store.get(writer, COUNTER_KEY)? { - Some(Value::U64(value)) => value as u64, + Some(Value::U64(value)) => value as IndexType, _ => 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 deleted file mode 100644 index db03253b4..000000000 --- a/copper_log/src/lib.rs +++ /dev/null @@ -1,27 +0,0 @@ -mod index; - -extern crate proc_macro; - -use proc_macro::TokenStream; -use quote::quote; -use syn::{parse_macro_input, LitStr}; - -#[proc_macro] -pub fn debug(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as LitStr); - let message = input.value(); - - let expanded = quote! { - { - let log_message = #message; - println!("{}:{} Log: {:?}", file!(), line!(), log_message); - log_message - } - }; - println!("Found logging string {}", message); - - // print the OUT env vairable - println!("OUT: {}", std::env::var("OUT_DIR").unwrap()); - - TokenStream::from(expanded) -} diff --git a/copper_log/src/log_extract.rs b/copper_log/src/log_extract.rs new file mode 100644 index 000000000..ee53a2250 --- /dev/null +++ b/copper_log/src/log_extract.rs @@ -0,0 +1,3 @@ +fn main (){ + println!("Hello"); +} diff --git a/copper_log/src/macros.rs b/copper_log/src/macros.rs new file mode 100644 index 000000000..89814af6d --- /dev/null +++ b/copper_log/src/macros.rs @@ -0,0 +1,28 @@ +mod index; + +extern crate proc_macro; + +use crate::index::check_and_insert; +use proc_macro::TokenStream; +use proc_macro2::{Span, TokenTree}; +use quote::quote; +use syn::{custom_keyword, parse_macro_input, LitStr}; + +#[proc_macro] +pub fn debug(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as LitStr); + let message = input.value(); + // We put dummy locations here because we cannot get the actual location of the macro invocation + let index = check_and_insert("dummy", 0, &message).expect("Failed to insert log string."); + + let expanded = quote! { + { + let log_message = #message; + println!("#{}:{}:{} Log: {:?}", #index, file!(), line!(), log_message); + log_message + } + }; + println!("#{} -> [{}]", index, message); + + TokenStream::from(expanded) +} diff --git a/copper_log_test/Cargo.toml b/copper_log_test/Cargo.toml new file mode 100644 index 000000000..df9c395f7 --- /dev/null +++ b/copper_log_test/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "copper-log-test" +version = "0.1.0" +edition = "2021" + +[dependencies] +copper-log = { path = "../copper_log" } diff --git a/copper_log_test/build.rs b/copper_log_test/build.rs new file mode 100644 index 000000000..e61c5f35f --- /dev/null +++ b/copper_log_test/build.rs @@ -0,0 +1,6 @@ +use std::env; + +fn main() { + let out_dir = env::var("OUT_DIR").unwrap(); + println!("cargo:rustc-env=OUT_DIR={}", out_dir); +} diff --git a/copper_log_test/src/main.rs b/copper_log_test/src/main.rs new file mode 100644 index 000000000..42d028213 --- /dev/null +++ b/copper_log_test/src/main.rs @@ -0,0 +1,7 @@ +use copper_log::debug; +fn main() { + let a = 2; + let b = 3; + // debug!("Hello, world! {} {}", a, b); + debug!("Hello, world!"); +} diff --git a/examples/config-gen/Cargo.toml b/examples/config_gen/Cargo.toml similarity index 100% rename from examples/config-gen/Cargo.toml rename to examples/config_gen/Cargo.toml diff --git a/examples/config-gen/src/main.rs b/examples/config_gen/src/main.rs similarity index 100% rename from examples/config-gen/src/main.rs rename to examples/config_gen/src/main.rs