diff --git a/.vscode/settings.json b/.vscode/settings.json
index 23fd35f..bac9be1 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,6 @@
{
- "editor.formatOnSave": true
-}
\ No newline at end of file
+ "editor.formatOnSave": true,
+ "[rust]": {
+ "editor.defaultFormatter": "rust-lang.rust-analyzer"
+ }
+}
diff --git a/Cargo.lock b/Cargo.lock
index 30724c6..8ad99a2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -28,9 +28,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.79"
+version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
[[package]]
name = "async-trait"
@@ -745,6 +745,7 @@ dependencies = [
name = "rustyDB"
version = "0.1.0"
dependencies = [
+ "anyhow",
"async-trait",
"protobuf",
"protobuf-codegen",
@@ -754,6 +755,7 @@ dependencies = [
"serde_json",
"tempfile",
"tokio",
+ "tracing",
"uuid",
]
@@ -916,6 +918,37 @@ dependencies = [
"syn 2.0.48",
]
+[[package]]
+name = "tracing"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+dependencies = [
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.48",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+dependencies = [
+ "once_cell",
+]
+
[[package]]
name = "unicode-ident"
version = "1.0.12"
diff --git a/Cargo.toml b/Cargo.toml
index 1ec2a3c..c0153d6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,6 +16,8 @@ tokio = { version = "1.26.0", features = ["full"] }
rand = "0.8.5"
async-trait = "0.1.68"
tempfile = "3.7.0"
+anyhow = "1.0.86"
+tracing = "0.1.40"
[build-dependencies]
protobuf = "3.2.0"
diff --git a/mdbook/src/chapter_5/life_of_a_query.md b/mdbook/src/chapter_5/life_of_a_query.md
index 4c7423d..61218d0 100644
--- a/mdbook/src/chapter_5/life_of_a_query.md
+++ b/mdbook/src/chapter_5/life_of_a_query.md
@@ -6,7 +6,11 @@ The transactional layer of the toy database is composed of many entities. This p
This page is inspired by CRDB's [Life of a SQL Query](https://github.com/cockroachdb/cockroach/blob/530100fd39cc722bc324bfb3869a325622258fb3/docs/tech-notes/life_of_a_query.md) doc, which outlines the lifecycle of a single query through the different layers of CRDB. I found that doc extremely useful when learning how CRDB works.
-From a higher level, the transactional layer of my toy database is composed of these entities:
+Here is a diagram showing the higher level life cycle of a read/write request:
+
+
+
+The transactional layer of my toy database is composed of these entities:
- **Concurrency Manager**: Provides isolation to concurrent and conflicting requests by sequencing them. Once a request is sequenced, it is free to execute as no conflicting requests are running at the same time. The concurrency manager is made up of the latch manager, lock table, and transaction wait queue.
- **Latch Manager**: Serializes accesses for keys. Only one latch guard can be acquired for a key at any given time.
diff --git a/mdbook/src/images/life_of_a_query.png b/mdbook/src/images/life_of_a_query.png
new file mode 100644
index 0000000..7e482f0
Binary files /dev/null and b/mdbook/src/images/life_of_a_query.png differ
diff --git a/src/concurrency/concurrency_manager.rs b/src/concurrency/concurrency_manager.rs
index a532cc5..b449aac 100644
--- a/src/concurrency/concurrency_manager.rs
+++ b/src/concurrency/concurrency_manager.rs
@@ -1,5 +1,6 @@
use std::sync::Arc;
+use anyhow::Result;
use tokio::sync::mpsc::Sender;
use crate::db::db::{TxnLink, TxnMap};
@@ -9,6 +10,7 @@ use crate::latch_manager::latch_manager::{LatchGuard, LatchManager};
use crate::lock_table::lock_table::{LockTable, LockTableGuardLink, UpdateLock, WaitForGuardError};
use crate::storage::mvcc::KVStore;
use crate::storage::Key;
+use tracing::error;
pub struct ConcurrencyManager {
latch_manager: LatchManager,
@@ -83,7 +85,6 @@ impl ConcurrencyManager {
let txn = txn_link.read().unwrap();
let keys = txn.lock_spans.read().unwrap();
keys.clone()
- // TODO: Remove clone
}
pub async fn update_txn_locks(&self, txn: TxnLink, update_lock: UpdateLock) {
diff --git a/src/execute/executor.rs b/src/execute/executor.rs
index 796848b..62501d8 100644
--- a/src/execute/executor.rs
+++ b/src/execute/executor.rs
@@ -64,7 +64,6 @@ impl Executor {
&self,
request: Request,
) -> ExecuteResult {
- // TODO: This should return some form of Result<...>
loop {
let request_union = &request.request_union;
let guard = self.concr_manager.sequence_req(&request).await;
@@ -92,7 +91,6 @@ impl Executor {
Err(err) => match err {
ResponseError::WriteIntentError(err) => {
self.handle_write_intent_error(err.intent.clone());
- println!("Handle write intent error");
}
ResponseError::ReadRefreshError => {
return Err(ExecuteError::ReadRefreshFailure);
@@ -112,10 +110,10 @@ impl Executor {
.get_transaction_record(txn_intent.txn_meta.txn_id);
if let Some(txn_record) = record {
if let TransactionStatus::ABORTED = txn_record.status {
+ // If the txn has aborted, remove the txn record
self.store.mvcc_delete(create_intent_key(&txn_intent.key));
}
}
- // If the txn has aborted, remove the txn record
}
pub async fn execute_write_request(&self, request: &Request, _guard: &Guard) -> ResponseResult {
diff --git a/src/latch_manager/latch_interval_btree.rs b/src/latch_manager/latch_interval_btree.rs
index 05cf575..a3b5986 100644
--- a/src/latch_manager/latch_interval_btree.rs
+++ b/src/latch_manager/latch_interval_btree.rs
@@ -1,11 +1,9 @@
use std::{
- borrow::{Borrow},
+ borrow::Borrow,
sync::{Arc, Mutex, RwLock, Weak},
};
-use tokio::{
- sync::mpsc::{self, Receiver, Sender},
-};
+use tokio::sync::mpsc::{self, Receiver, Sender};
use crate::storage::{mvcc_key::MVCCKey, Key};
diff --git a/src/latch_manager/latch_manager.rs b/src/latch_manager/latch_manager.rs
index ed80df3..8d20e9a 100644
--- a/src/latch_manager/latch_manager.rs
+++ b/src/latch_manager/latch_manager.rs
@@ -41,7 +41,7 @@ impl LatchManager {
if let LatchKeyGuard::NotAcquired(mut wait_guard) = lg {
tokio::select! {
Some(_) = wait_guard.receiver.recv() => {
- println!("retry acquire lock")
+ // wait for conflicting latch to release the guard
}
_ = &mut sleep, if !sleep.is_elapsed() => {
println!("operation timed out. Releasing and retrying");