Skip to content

Commit 534397c

Browse files
committed
feat(gc): record workspace manifest and target dir in global cache tracker
1 parent bd1cf58 commit 534397c

File tree

3 files changed

+206
-2
lines changed

3 files changed

+206
-2
lines changed

.cargo/config.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ bump-check = "run --package xtask-bump-check --"
77
# HACK: Until this is stabilized, `snapbox`s polyfill could get confused
88
# inside of the rust-lang/rust repo because it looks for the furthest-away `Cargo.toml`
99
CARGO_RUSTC_CURRENT_DIR = { value = "", relative = true }
10+
# CARGO_LOG = { value = "trace" }

src/cargo/core/global_cache_tracker.rs

Lines changed: 196 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ const REGISTRY_CRATE_TABLE: &str = "registry_crate";
138138
const REGISTRY_SRC_TABLE: &str = "registry_src";
139139
const GIT_DB_TABLE: &str = "git_db";
140140
const GIT_CO_TABLE: &str = "git_checkout";
141+
const WORKSPACE_MANIFEST_TABLE: &str = "workspace_manifest_index";
142+
const TARGET_DIR_TABLE: &str = "target_dir_index";
141143

142144
/// How often timestamps will be updated.
143145
///
@@ -209,6 +211,27 @@ pub struct GitCheckout {
209211
pub size: Option<u64>,
210212
}
211213

214+
/// The key for a workspace manifest entry stored in the database.
215+
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
216+
pub struct WorkspaceManifestIndex {
217+
/// A unique name of the workspace manifest.
218+
pub encoded_workspace_manifest_name: InternedString,
219+
}
220+
221+
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
222+
pub struct TargetDirIndex {
223+
/// A unique name of the target directory.
224+
pub encoded_target_dir_name: InternedString,
225+
}
226+
227+
/// The key for a workspace entry stored in the database.
228+
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
229+
pub struct WorkspaceSrc {
230+
pub encoded_workspace_manifest_name: InternedString,
231+
pub encoded_target_dir_name: InternedString,
232+
233+
}
234+
212235
/// Filesystem paths in the global cache.
213236
///
214237
/// Accessing these assumes a lock has already been acquired.
@@ -303,6 +326,30 @@ fn migrations() -> Vec<Migration> {
303326
)?;
304327
Ok(())
305328
}),
329+
basic_migration(
330+
"CREATE TABLE workspace_manifest_index (
331+
id INTEGER PRIMARY KEY AUTOINCREMENT,
332+
name TEXT UNIQUE NOT NULL,
333+
timestamp INTEGER NOT NULL
334+
)",
335+
),
336+
basic_migration(
337+
"CREATE TABLE target_dir_index (
338+
id INTEGER PRIMARY KEY AUTOINCREMENT,
339+
name TEXT UNIQUE NOT NULL,
340+
timestamp INTEGER NOT NULL
341+
)",
342+
),
343+
basic_migration(
344+
"CREATE TABLE workspace_src (
345+
workspace_id INTEGER NOT NULL,
346+
target_dir_id INTEGER NOT NULL,
347+
timestamp INTEGER NOT NULL,
348+
PRIMARY KEY (workspace_id, target_dir_id),
349+
FOREIGN KEY (workspace_id) REFERENCES workspace_manifest_index (id) ON DELETE CASCADE,
350+
FOREIGN KEY (target_dir_id) REFERENCES target_dir_index (id) ON DELETE CASCADE
351+
)",
352+
)
306353
]
307354
}
308355

@@ -1413,7 +1460,16 @@ pub struct DeferredGlobalLastUse {
14131460
/// The key is the git db name (which is its directory name) and the value
14141461
/// is the `id` in the `git_db` table.
14151462
git_keys: HashMap<InternedString, ParentId>,
1416-
1463+
/// Cache of workspace manifest keys, used for faster fetching.
1464+
///
1465+
/// The key is the workspace manifest path and the value
1466+
/// is the `id` in the `workspace_manifest` table.
1467+
workspace_manifest_keys: HashMap<InternedString, ParentId>,
1468+
/// Cache of target dir keys, used for faster fetching.
1469+
///
1470+
/// The key is the target dir path and the value
1471+
/// is the `id` in the `target_dir` table.
1472+
target_dir_keys: HashMap<InternedString, ParentId>,
14171473
/// New registry index entries to insert.
14181474
registry_index_timestamps: HashMap<RegistryIndex, Timestamp>,
14191475
/// New registry `.crate` entries to insert.
@@ -1424,6 +1480,12 @@ pub struct DeferredGlobalLastUse {
14241480
git_db_timestamps: HashMap<GitDb, Timestamp>,
14251481
/// New git checkout entries to insert.
14261482
git_checkout_timestamps: HashMap<GitCheckout, Timestamp>,
1483+
/// New workspace manifest entries to insert.
1484+
workspace_db_timestamps: HashMap<WorkspaceManifestIndex, Timestamp>,
1485+
/// New target dir entries to insert.
1486+
target_dir_db_timestamps: HashMap<TargetDirIndex, Timestamp>,
1487+
/// New workspace src entries to insert.
1488+
workspace_src_timestamps: HashMap<WorkspaceSrc, Timestamp>,
14271489
/// This is used so that a warning about failing to update the database is
14281490
/// only displayed once.
14291491
save_err_has_warned: bool,
@@ -1437,11 +1499,16 @@ impl DeferredGlobalLastUse {
14371499
DeferredGlobalLastUse {
14381500
registry_keys: HashMap::new(),
14391501
git_keys: HashMap::new(),
1502+
workspace_manifest_keys: HashMap::new(),
1503+
target_dir_keys: HashMap::new(),
14401504
registry_index_timestamps: HashMap::new(),
14411505
registry_crate_timestamps: HashMap::new(),
14421506
registry_src_timestamps: HashMap::new(),
14431507
git_db_timestamps: HashMap::new(),
14441508
git_checkout_timestamps: HashMap::new(),
1509+
target_dir_db_timestamps: HashMap::new(),
1510+
workspace_db_timestamps: HashMap::new(),
1511+
workspace_src_timestamps: HashMap::new(),
14451512
save_err_has_warned: false,
14461513
now: now(),
14471514
}
@@ -1453,6 +1520,9 @@ impl DeferredGlobalLastUse {
14531520
&& self.registry_src_timestamps.is_empty()
14541521
&& self.git_db_timestamps.is_empty()
14551522
&& self.git_checkout_timestamps.is_empty()
1523+
&& self.target_dir_db_timestamps.is_empty()
1524+
&& self.workspace_db_timestamps.is_empty()
1525+
&& self.workspace_src_timestamps.is_empty()
14561526
}
14571527

14581528
fn clear(&mut self) {
@@ -1461,6 +1531,9 @@ impl DeferredGlobalLastUse {
14611531
self.registry_src_timestamps.clear();
14621532
self.git_db_timestamps.clear();
14631533
self.git_checkout_timestamps.clear();
1534+
self.target_dir_db_timestamps.clear();
1535+
self.workspace_db_timestamps.clear();
1536+
self.workspace_src_timestamps.clear();
14641537
}
14651538

14661539
/// Indicates the given [`RegistryIndex`] has been used right now.
@@ -1489,6 +1562,13 @@ impl DeferredGlobalLastUse {
14891562
self.mark_git_checkout_used_stamp(git_checkout, None);
14901563
}
14911564

1565+
/// Indicates the given [`WorkspaceManifest`] has been used right now.
1566+
///
1567+
/// Also implicitly marks the workspace manifest used, too.
1568+
pub fn mark_workspace_src_used(&mut self, workspace_src: WorkspaceSrc) {
1569+
self.mark_workspace_src_used_stamp(workspace_src, None);
1570+
}
1571+
14921572
/// Indicates the given [`RegistryIndex`] has been used with the given
14931573
/// time (or "now" if `None`).
14941574
pub fn mark_registry_index_used_stamp(
@@ -1553,6 +1633,24 @@ impl DeferredGlobalLastUse {
15531633
self.git_checkout_timestamps.insert(git_checkout, timestamp);
15541634
}
15551635

1636+
pub fn mark_workspace_src_used_stamp(
1637+
&mut self,
1638+
workspace_src: WorkspaceSrc,
1639+
timestamp: Option<&SystemTime>,
1640+
) {
1641+
let timestamp = timestamp.map_or(self.now, to_timestamp);
1642+
let workspace_db = WorkspaceManifestIndex {
1643+
encoded_workspace_manifest_name: workspace_src.encoded_workspace_manifest_name,
1644+
};
1645+
let target_dir_db = TargetDirIndex {
1646+
encoded_target_dir_name: workspace_src.encoded_target_dir_name,
1647+
};
1648+
self.target_dir_db_timestamps.insert(target_dir_db, timestamp);
1649+
self.workspace_db_timestamps.insert(workspace_db, timestamp);
1650+
self.workspace_src_timestamps
1651+
.insert(workspace_src, timestamp);
1652+
}
1653+
15561654
/// Saves all of the deferred information to the database.
15571655
///
15581656
/// This will also clear the state of `self`.
@@ -1566,9 +1664,13 @@ impl DeferredGlobalLastUse {
15661664
// These must run before the ones that refer to their IDs.
15671665
self.insert_registry_index_from_cache(&tx)?;
15681666
self.insert_git_db_from_cache(&tx)?;
1667+
self.insert_target_dir_index_from_cache(&tx)?;
1668+
self.insert_workspace_manifest_index_from_cache(&tx)?;
1669+
15691670
self.insert_registry_crate_from_cache(&tx)?;
15701671
self.insert_registry_src_from_cache(&tx)?;
15711672
self.insert_git_checkout_from_cache(&tx)?;
1673+
self.insert_workspace_src_from_cache(&tx)?;
15721674
tx.commit()?;
15731675
trace!(target: "gc", "last-use save complete");
15741676
Ok(())
@@ -1632,6 +1734,32 @@ impl DeferredGlobalLastUse {
16321734
);
16331735
}
16341736

1737+
// Flushes all of the `target_dir_db_timestamps` to the database,
1738+
// clearing `target_dir_index_timestamps`.
1739+
fn insert_target_dir_index_from_cache(&mut self, conn: &Connection) -> CargoResult<()> {
1740+
insert_or_update_parent!(
1741+
self,
1742+
conn,
1743+
"target_dir_index",
1744+
target_dir_db_timestamps,
1745+
target_dir_keys,
1746+
encoded_target_dir_name
1747+
);
1748+
}
1749+
1750+
// Flushes all of the `workspace_db_timestamps` to the database,
1751+
// clearing `workspace_manifest_index_timestamps`.
1752+
fn insert_workspace_manifest_index_from_cache(&mut self, conn: &Connection) -> CargoResult<()> {
1753+
insert_or_update_parent!(
1754+
self,
1755+
conn,
1756+
"workspace_manifest_index",
1757+
workspace_db_timestamps,
1758+
workspace_manifest_keys,
1759+
encoded_workspace_manifest_name
1760+
);
1761+
}
1762+
16351763
/// Flushes all of the `registry_crate_timestamps` to the database,
16361764
/// clearing `registry_index_timestamps`.
16371765
fn insert_registry_crate_from_cache(&mut self, conn: &Connection) -> CargoResult<()> {
@@ -1707,6 +1835,73 @@ impl DeferredGlobalLastUse {
17071835
Ok(())
17081836
}
17091837

1838+
// Flushes all of the `workspace_src_timestamps` to the database,
1839+
// clearing `workspace_src_timestamps`.
1840+
fn insert_workspace_src_from_cache(&mut self, conn: &Connection) -> CargoResult<()> {
1841+
let workspace_src_timestamps = std::mem::take(&mut self.workspace_src_timestamps);
1842+
for (workspace_src, timestamp) in workspace_src_timestamps {
1843+
let workspace_id = self.workspace_id(conn, workspace_src.encoded_workspace_manifest_name)?;
1844+
let target_dir_id = self.target_dir_id(conn, workspace_src.encoded_target_dir_name)?;
1845+
let mut stmt = conn.prepare_cached(
1846+
"INSERT INTO workspace_src (workspace_id, target_dir_id, timestamp)
1847+
VALUES (?1, ?2, ?3)
1848+
ON CONFLICT DO UPDATE SET timestamp=excluded.timestamp
1849+
WHERE timestamp < ?4",
1850+
)?;
1851+
stmt.execute(params![
1852+
workspace_id,
1853+
target_dir_id,
1854+
timestamp,
1855+
timestamp - UPDATE_RESOLUTION
1856+
])?;
1857+
}
1858+
Ok(())
1859+
}
1860+
1861+
fn workspace_id(
1862+
&mut self,
1863+
conn: &Connection,
1864+
encoded_workspace_manifest_name: InternedString,
1865+
) -> CargoResult<ParentId> {
1866+
match self.workspace_manifest_keys.get(&encoded_workspace_manifest_name) {
1867+
Some(i) => Ok(*i),
1868+
None => {
1869+
let Some(id) = GlobalCacheTracker::id_from_name(
1870+
conn,
1871+
WORKSPACE_MANIFEST_TABLE,
1872+
&encoded_workspace_manifest_name,
1873+
)?
1874+
else {
1875+
bail!("expected workspace_manifest {encoded_workspace_manifest_name} to exist, but wasn't found");
1876+
};
1877+
self.workspace_manifest_keys.insert(encoded_workspace_manifest_name, id);
1878+
Ok(id)
1879+
}
1880+
}
1881+
}
1882+
1883+
fn target_dir_id(
1884+
&mut self,
1885+
conn: &Connection,
1886+
encoded_target_dir_name: InternedString,
1887+
) -> CargoResult<ParentId> {
1888+
match self.target_dir_keys.get(&encoded_target_dir_name) {
1889+
Some(i) => Ok(*i),
1890+
None => {
1891+
let Some(id) = GlobalCacheTracker::id_from_name(
1892+
conn,
1893+
TARGET_DIR_TABLE,
1894+
&encoded_target_dir_name,
1895+
)?
1896+
else {
1897+
bail!("expected target_dir {encoded_target_dir_name} to exist, but wasn't found");
1898+
};
1899+
self.target_dir_keys.insert(encoded_target_dir_name, id);
1900+
Ok(id)
1901+
}
1902+
}
1903+
}
1904+
17101905
/// Returns the numeric ID of the registry, either fetching from the local
17111906
/// cache, or getting it from the database.
17121907
///

src/cargo/ops/cargo_compile/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use crate::core::compiler::{DefaultExecutor, Executor, UnitInterner};
4949
use crate::core::profiles::Profiles;
5050
use crate::core::resolver::features::{self, CliFeatures, FeaturesFor};
5151
use crate::core::resolver::{HasDevUnits, Resolve};
52-
use crate::core::{PackageId, PackageSet, SourceId, TargetKind, Workspace};
52+
use crate::core::{global_cache_tracker, PackageId, PackageSet, SourceId, TargetKind, Workspace};
5353
use crate::drop_println;
5454
use crate::ops;
5555
use crate::ops::resolve::WorkspaceResolve;
@@ -264,6 +264,14 @@ pub fn create_bcx<'a, 'gctx>(
264264
HasDevUnits::No
265265
}
266266
};
267+
let _ = &gctx
268+
.deferred_global_last_use()?
269+
.mark_workspace_src_used(global_cache_tracker::WorkspaceSrc {
270+
encoded_workspace_manifest_name: InternedString::new(
271+
ws.root_manifest().to_str().unwrap(),
272+
),
273+
encoded_target_dir_name: InternedString::new(ws.target_dir().as_path_unlocked().to_str().unwrap()),
274+
});
267275
let resolve = ops::resolve_ws_with_opts(
268276
ws,
269277
&mut target_data,

0 commit comments

Comments
 (0)