Skip to content

Commit 1664c30

Browse files
Prototype storing cache in git notes
Change: notes-cache
1 parent 84f9cc1 commit 1664c30

File tree

2 files changed

+82
-16
lines changed

2 files changed

+82
-16
lines changed

josh-core/src/cache.rs

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,66 @@
11
use super::*;
22
use std::collections::HashMap;
3+
use std::sync::{LazyLock, RwLock};
34

45
const CACHE_VERSION: u64 = 24;
56

7+
fn josh_commit_signature<'a>() -> JoshResult<git2::Signature<'a>> {
8+
Ok(if let Ok(time) = std::env::var("JOSH_COMMIT_TIME") {
9+
git2::Signature::new(
10+
"JOSH",
11+
"josh@josh-project.dev",
12+
&git2::Time::new(time.parse()?, 0),
13+
)?
14+
} else {
15+
git2::Signature::now("JOSH", "josh@josh-project.dev")?
16+
})
17+
}
18+
19+
fn store_note(repo: &git2::Repository, kind: &str, key: git2::Oid, from: git2::Oid, to: git2::Oid) {
20+
let signature = josh_commit_signature().unwrap();
21+
repo.note(
22+
&signature,
23+
&signature,
24+
Some(&format!("refs/josh/{}/{}/{}", kind, CACHE_VERSION, key)),
25+
from,
26+
&format!("{}", to),
27+
true,
28+
)
29+
.unwrap();
30+
}
31+
32+
fn lookup_note(
33+
repo: &git2::Repository,
34+
kind: &str,
35+
key: git2::Oid,
36+
from: git2::Oid,
37+
) -> Option<git2::Oid> {
38+
if from.as_bytes()[0] != 0 {
39+
return None;
40+
}
41+
if let Ok(note) = repo.find_note(
42+
Some(&format!("refs/josh/{}/{}/{}", kind, CACHE_VERSION, key)),
43+
from,
44+
) {
45+
Some(git2::Oid::from_str(note.message().unwrap()).unwrap())
46+
} else {
47+
None
48+
}
49+
}
50+
651
lazy_static! {
752
static ref DB: std::sync::Mutex<Option<sled::Db>> = std::sync::Mutex::new(None);
8-
static ref REF_CACHE: std::sync::Mutex<HashMap<git2::Oid, HashMap<git2::Oid, git2::Oid>>> =
9-
std::sync::Mutex::new(HashMap::new());
10-
static ref POPULATE_MAP: std::sync::Mutex<HashMap<(git2::Oid, git2::Oid), git2::Oid>> =
11-
std::sync::Mutex::new(HashMap::new());
12-
static ref GLOB_MAP: std::sync::Mutex<HashMap<(git2::Oid, git2::Oid), git2::Oid>> =
13-
std::sync::Mutex::new(HashMap::new());
1453
}
1554

55+
static REF_CACHE: LazyLock<RwLock<HashMap<git2::Oid, HashMap<git2::Oid, git2::Oid>>>> =
56+
LazyLock::new(Default::default);
57+
58+
static POPULATE_MAP: LazyLock<RwLock<HashMap<(git2::Oid, git2::Oid), git2::Oid>>> =
59+
LazyLock::new(Default::default);
60+
61+
static GLOB_MAP: LazyLock<RwLock<HashMap<(git2::Oid, git2::Oid), git2::Oid>>> =
62+
LazyLock::new(Default::default);
63+
1664
pub fn load(path: &std::path::Path) -> JoshResult<()> {
1765
*DB.lock()? = Some(
1866
sled::Config::default()
@@ -272,32 +320,32 @@ impl Transaction {
272320
}
273321

274322
pub fn insert_populate(&self, tree: (git2::Oid, git2::Oid), result: git2::Oid) {
275-
POPULATE_MAP.lock().unwrap().entry(tree).or_insert(result);
323+
POPULATE_MAP.write().unwrap().entry(tree).or_insert(result);
276324
}
277325

278326
pub fn get_populate(&self, tree: (git2::Oid, git2::Oid)) -> Option<git2::Oid> {
279-
return POPULATE_MAP.lock().unwrap().get(&tree).cloned();
327+
POPULATE_MAP.read().unwrap().get(&tree).cloned()
280328
}
281329

282330
pub fn insert_glob(&self, tree: (git2::Oid, git2::Oid), result: git2::Oid) {
283-
GLOB_MAP.lock().unwrap().entry(tree).or_insert(result);
331+
GLOB_MAP.write().unwrap().entry(tree).or_insert(result);
284332
}
285333

286334
pub fn get_glob(&self, tree: (git2::Oid, git2::Oid)) -> Option<git2::Oid> {
287-
return GLOB_MAP.lock().unwrap().get(&tree).cloned();
335+
GLOB_MAP.read().unwrap().get(&tree).cloned()
288336
}
289337

290338
pub fn insert_ref(&self, filter: filter::Filter, from: git2::Oid, to: git2::Oid) {
291339
REF_CACHE
292-
.lock()
340+
.write()
293341
.unwrap()
294342
.entry(filter.id())
295343
.or_default()
296344
.insert(from, to);
297345
}
298346

299347
pub fn get_ref(&self, filter: filter::Filter, from: git2::Oid) -> Option<git2::Oid> {
300-
if let Some(m) = REF_CACHE.lock().unwrap().get(&filter.id()) {
348+
if let Some(m) = REF_CACHE.read().unwrap().get(&filter.id()) {
301349
if let Some(oid) = m.get(&from) {
302350
if self.repo.odb().unwrap().exists(*oid) {
303351
return Some(*oid);
@@ -336,6 +384,9 @@ impl Transaction {
336384
});
337385

338386
t.insert(from.as_bytes(), to.as_bytes()).unwrap();
387+
if from.as_bytes()[0] == 0 {
388+
store_note(&self.repo, "cache", filter.id(), from, to);
389+
}
339390
}
340391
}
341392

@@ -396,8 +447,15 @@ impl Transaction {
396447
.open_tree(filter::spec(filter))
397448
.unwrap()
398449
});
399-
if let Some(oid) = t.get(from.as_bytes()).unwrap() {
400-
let oid = git2::Oid::from_bytes(&oid).unwrap();
450+
let oid = if let Some(oid) = t.get(from.as_bytes()).unwrap() {
451+
Some(git2::Oid::from_bytes(&oid).unwrap())
452+
} else if let Some(oid) = lookup_note(&self.repo, "cache", filter.id(), from) {
453+
Some(oid)
454+
} else {
455+
None
456+
};
457+
458+
if let Some(oid) = oid {
401459
if oid == git2::Oid::zero() {
402460
return Some(oid);
403461
}

tests/proxy/workspace_modify_chain.t

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@
358358
| |-- 20
359359
| | `-- 5dccdc2e37df9aaccec46009520154219134e7
360360
| |-- 27
361+
| | |-- 153f2bc72430a7221a94318d46d2eb1402c9db
361362
| | `-- d0eee16bdbe4a1ade0ebf877f97467de3b218e
362363
| |-- 2a
363364
| | |-- 03ad0fe1720ee0afc95ba8e1bc38a35b87983f
@@ -383,6 +384,8 @@
383384
| | `-- 3b7672b3bcf00bbd95e650076c375528d5f5c3
384385
| |-- 47
385386
| | `-- 8644b35118f1d733b14cafb04c51e5b6579243
387+
| |-- 4a
388+
| | `-- 63d3ce0a2d493bd0cda58ae8fd064be63c9e95
386389
| |-- 4b
387390
| | `-- 825dc642cb6eb9a060e54bf8d69288fbee4904
388391
| |-- 4f
@@ -431,7 +434,8 @@
431434
| |-- a3
432435
| | `-- d027b4cc082c08af95fcbe03eecd9a62a08c48
433436
| |-- a7
434-
| | `-- 3af649c49fa4b0facff36fafdc1e2bef594d4e
437+
| | |-- 3af649c49fa4b0facff36fafdc1e2bef594d4e
438+
| | `-- fe5239814b5bfdbadc9f213abc2a2f2c1f31db
435439
| |-- aa
436440
| | `-- 0654329f0642e4505db87c24aea80ba52fd689
437441
| |-- ac
@@ -484,9 +488,13 @@
484488
| `-- pack
485489
`-- refs
486490
|-- heads
491+
|-- josh
492+
| `-- cache
493+
| `-- 22
494+
| `-- 7bd92d97e96693ea7fd7eb5757b3580002889948
487495
|-- namespaces
488496
`-- tags
489497

490-
122 directories, 117 files
498+
126 directories, 121 files
491499

492500
$ cat ${TESTTMP}/josh-proxy.out | grep VIEW

0 commit comments

Comments
 (0)