@@ -138,6 +138,8 @@ const REGISTRY_CRATE_TABLE: &str = "registry_crate";
138
138
const REGISTRY_SRC_TABLE : & str = "registry_src" ;
139
139
const GIT_DB_TABLE : & str = "git_db" ;
140
140
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" ;
141
143
142
144
/// How often timestamps will be updated.
143
145
///
@@ -209,6 +211,27 @@ pub struct GitCheckout {
209
211
pub size : Option < u64 > ,
210
212
}
211
213
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
+
212
235
/// Filesystem paths in the global cache.
213
236
///
214
237
/// Accessing these assumes a lock has already been acquired.
@@ -303,6 +326,30 @@ fn migrations() -> Vec<Migration> {
303
326
) ?;
304
327
Ok ( ( ) )
305
328
} ) ,
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
+ )
306
353
]
307
354
}
308
355
@@ -1413,7 +1460,16 @@ pub struct DeferredGlobalLastUse {
1413
1460
/// The key is the git db name (which is its directory name) and the value
1414
1461
/// is the `id` in the `git_db` table.
1415
1462
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 > ,
1417
1473
/// New registry index entries to insert.
1418
1474
registry_index_timestamps : HashMap < RegistryIndex , Timestamp > ,
1419
1475
/// New registry `.crate` entries to insert.
@@ -1424,6 +1480,12 @@ pub struct DeferredGlobalLastUse {
1424
1480
git_db_timestamps : HashMap < GitDb , Timestamp > ,
1425
1481
/// New git checkout entries to insert.
1426
1482
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 > ,
1427
1489
/// This is used so that a warning about failing to update the database is
1428
1490
/// only displayed once.
1429
1491
save_err_has_warned : bool ,
@@ -1437,11 +1499,16 @@ impl DeferredGlobalLastUse {
1437
1499
DeferredGlobalLastUse {
1438
1500
registry_keys : HashMap :: new ( ) ,
1439
1501
git_keys : HashMap :: new ( ) ,
1502
+ workspace_manifest_keys : HashMap :: new ( ) ,
1503
+ target_dir_keys : HashMap :: new ( ) ,
1440
1504
registry_index_timestamps : HashMap :: new ( ) ,
1441
1505
registry_crate_timestamps : HashMap :: new ( ) ,
1442
1506
registry_src_timestamps : HashMap :: new ( ) ,
1443
1507
git_db_timestamps : HashMap :: new ( ) ,
1444
1508
git_checkout_timestamps : HashMap :: new ( ) ,
1509
+ target_dir_db_timestamps : HashMap :: new ( ) ,
1510
+ workspace_db_timestamps : HashMap :: new ( ) ,
1511
+ workspace_src_timestamps : HashMap :: new ( ) ,
1445
1512
save_err_has_warned : false ,
1446
1513
now : now ( ) ,
1447
1514
}
@@ -1453,6 +1520,9 @@ impl DeferredGlobalLastUse {
1453
1520
&& self . registry_src_timestamps . is_empty ( )
1454
1521
&& self . git_db_timestamps . is_empty ( )
1455
1522
&& 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 ( )
1456
1526
}
1457
1527
1458
1528
fn clear ( & mut self ) {
@@ -1461,6 +1531,9 @@ impl DeferredGlobalLastUse {
1461
1531
self . registry_src_timestamps . clear ( ) ;
1462
1532
self . git_db_timestamps . clear ( ) ;
1463
1533
self . git_checkout_timestamps . clear ( ) ;
1534
+ self . target_dir_db_timestamps . clear ( ) ;
1535
+ self . workspace_db_timestamps . clear ( ) ;
1536
+ self . workspace_src_timestamps . clear ( ) ;
1464
1537
}
1465
1538
1466
1539
/// Indicates the given [`RegistryIndex`] has been used right now.
@@ -1489,6 +1562,13 @@ impl DeferredGlobalLastUse {
1489
1562
self . mark_git_checkout_used_stamp ( git_checkout, None ) ;
1490
1563
}
1491
1564
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
+
1492
1572
/// Indicates the given [`RegistryIndex`] has been used with the given
1493
1573
/// time (or "now" if `None`).
1494
1574
pub fn mark_registry_index_used_stamp (
@@ -1553,6 +1633,24 @@ impl DeferredGlobalLastUse {
1553
1633
self . git_checkout_timestamps . insert ( git_checkout, timestamp) ;
1554
1634
}
1555
1635
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
+
1556
1654
/// Saves all of the deferred information to the database.
1557
1655
///
1558
1656
/// This will also clear the state of `self`.
@@ -1566,9 +1664,13 @@ impl DeferredGlobalLastUse {
1566
1664
// These must run before the ones that refer to their IDs.
1567
1665
self . insert_registry_index_from_cache ( & tx) ?;
1568
1666
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
+
1569
1670
self . insert_registry_crate_from_cache ( & tx) ?;
1570
1671
self . insert_registry_src_from_cache ( & tx) ?;
1571
1672
self . insert_git_checkout_from_cache ( & tx) ?;
1673
+ self . insert_workspace_src_from_cache ( & tx) ?;
1572
1674
tx. commit ( ) ?;
1573
1675
trace ! ( target: "gc" , "last-use save complete" ) ;
1574
1676
Ok ( ( ) )
@@ -1632,6 +1734,32 @@ impl DeferredGlobalLastUse {
1632
1734
) ;
1633
1735
}
1634
1736
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
+
1635
1763
/// Flushes all of the `registry_crate_timestamps` to the database,
1636
1764
/// clearing `registry_index_timestamps`.
1637
1765
fn insert_registry_crate_from_cache ( & mut self , conn : & Connection ) -> CargoResult < ( ) > {
@@ -1707,6 +1835,73 @@ impl DeferredGlobalLastUse {
1707
1835
Ok ( ( ) )
1708
1836
}
1709
1837
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
+
1710
1905
/// Returns the numeric ID of the registry, either fetching from the local
1711
1906
/// cache, or getting it from the database.
1712
1907
///
0 commit comments