Skip to content

Commit aadab5f

Browse files
committed
fix(index): change sqlite schema to (name, ver, blob)
1 parent 4b4a993 commit aadab5f

File tree

2 files changed

+95
-32
lines changed

2 files changed

+95
-32
lines changed

src/cargo/sources/registry/index/cache.rs

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ use crate::CargoResult;
8888
use crate::GlobalContext;
8989

9090
use super::split;
91+
use super::Summaries;
92+
use super::MaybeIndexSummary;
9193
use super::INDEX_V_MAX;
9294

9395
/// The current version of [`SummariesCache`].
@@ -231,18 +233,27 @@ impl<'a> SummariesCache<'a> {
231233
/// An abstraction of the actual cache store.
232234
trait CacheStore {
233235
/// Gets the cache associated with the key.
234-
fn get(&self, key: &str) -> Option<Vec<u8>>;
236+
fn get(&self, key: &str) -> Option<MaybeSummaries>;
235237

236238
/// Associates the value with the key.
237239
fn put(&self, key: &str, value: &[u8]);
238240

241+
/// Associates the value with the key + version tuple.
242+
fn put_summary(&self, key: (&str, &Version), value: &[u8]);
243+
239244
/// Invalidates the cache associated with the key.
240245
fn invalidate(&self, key: &str);
241246
}
242247

248+
pub enum MaybeSummaries {
249+
Unparsed(Vec<u8>),
250+
Parsed(Summaries),
251+
}
252+
243253
/// Manages the on-disk index caches.
244254
pub struct CacheManager<'gctx> {
245255
store: Box<dyn CacheStore + 'gctx>,
256+
is_sqlite: bool,
246257
}
247258

248259
impl<'gctx> CacheManager<'gctx> {
@@ -258,11 +269,15 @@ impl<'gctx> CacheManager<'gctx> {
258269
} else {
259270
Box::new(LocalFileSystem::new(cache_root, gctx))
260271
};
261-
CacheManager { store }
272+
CacheManager { store, is_sqlite: use_sqlite }
273+
}
274+
275+
pub fn is_sqlite(&self) -> bool {
276+
self.is_sqlite
262277
}
263278

264279
/// Gets the cache associated with the key.
265-
pub fn get(&self, key: &str) -> Option<Vec<u8>> {
280+
pub fn get(&self, key: &str) -> Option<MaybeSummaries> {
266281
self.store.get(key)
267282
}
268283

@@ -271,6 +286,11 @@ impl<'gctx> CacheManager<'gctx> {
271286
self.store.put(key, value)
272287
}
273288

289+
/// Associates the value with the key + version tuple.
290+
pub fn put_summary(&self, key: (&str, &Version), value: &[u8]) {
291+
self.store.put_summary(key, value)
292+
}
293+
274294
/// Invalidates the cache associated with the key.
275295
pub fn invalidate(&self, key: &str) {
276296
self.store.invalidate(key)
@@ -301,10 +321,10 @@ impl LocalFileSystem<'_> {
301321
}
302322

303323
impl CacheStore for LocalFileSystem<'_> {
304-
fn get(&self, key: &str) -> Option<Vec<u8>> {
324+
fn get(&self, key: &str) -> Option<MaybeSummaries> {
305325
let cache_path = &self.cache_path(key);
306326
match fs::read(cache_path) {
307-
Ok(contents) => Some(contents),
327+
Ok(contents) => Some(MaybeSummaries::Unparsed(contents)),
308328
Err(e) => {
309329
tracing::debug!(?cache_path, "cache missing: {e}");
310330
None
@@ -324,6 +344,10 @@ impl CacheStore for LocalFileSystem<'_> {
324344
}
325345
}
326346

347+
fn put_summary(&self, _key: (&str, &Version), _value: &[u8]) {
348+
panic!("unsupported");
349+
}
350+
327351
fn invalidate(&self, key: &str) {
328352
let cache_path = &self.cache_path(key);
329353
if let Err(e) = fs::remove_file(cache_path) {
@@ -341,7 +365,7 @@ struct LocalDatabase<'gctx> {
341365
/// Connection to the SQLite database.
342366
conn: OnceCell<Option<RefCell<Connection>>>,
343367
/// [`GlobalContext`] reference for convenience.
344-
deferred_writes: RefCell<BTreeMap<String, Vec<u8>>>,
368+
deferred_writes: RefCell<BTreeMap<String, Vec<(String, Vec<u8>)>>>,
345369
gctx: &'gctx GlobalContext,
346370
}
347371

@@ -351,7 +375,7 @@ impl LocalDatabase<'_> {
351375
LocalDatabase {
352376
cache_root,
353377
conn: OnceCell::new(),
354-
deferred_writes: RefCell::new(BTreeMap::new()),
378+
deferred_writes: Default::default(),
355379
gctx,
356380
}
357381
}
@@ -386,9 +410,11 @@ impl LocalDatabase<'_> {
386410
let mut conn = conn.borrow_mut();
387411
let tx = conn.transaction()?;
388412
let mut stmt =
389-
tx.prepare_cached("INSERT OR REPLACE INTO summaries (name, value) VALUES (?, ?)")?;
390-
for (key, value) in self.deferred_writes.borrow().iter() {
391-
stmt.execute(params!(key, value))?;
413+
tx.prepare_cached("INSERT OR REPLACE INTO summaries (name, version, value) VALUES (?, ?, ?)")?;
414+
for (name, summaries) in self.deferred_writes.borrow().iter() {
415+
for (version, value) in summaries {
416+
stmt.execute(params!(name, version, value))?;
417+
}
392418
}
393419
drop(stmt);
394420
tx.commit()?;
@@ -406,19 +432,36 @@ impl Drop for LocalDatabase<'_> {
406432
}
407433

408434
impl CacheStore for LocalDatabase<'_> {
409-
fn get(&self, key: &str) -> Option<Vec<u8>> {
435+
fn get(&self, key: &str) -> Option<MaybeSummaries> {
410436
self.conn()?
411437
.borrow()
412-
.prepare_cached("SELECT value FROM summaries WHERE name = ? LIMIT 1")
413-
.and_then(|mut stmt| stmt.query_row([key], |row| row.get(0)))
414-
.map_err(|e| tracing::debug!(key, "cache missing: {e}"))
438+
.prepare_cached("SELECT version, value FROM summaries WHERE name = ?")
439+
.and_then(|mut stmt| {
440+
let rows = stmt.query_map([key], |row| Ok((row.get(0)?, row.get(1)?)))?;
441+
let mut summaries = Summaries::default();
442+
for row in rows {
443+
let (version, raw_data): (String, Vec<u8>) = row?;
444+
let version = Version::parse(&version).expect("semver");
445+
summaries.versions.insert(version, MaybeIndexSummary::UnparsedData(raw_data));
446+
}
447+
Ok(MaybeSummaries::Parsed(summaries))
448+
})
449+
.map_err(|e| {
450+
tracing::debug!(key, "cache missing: {e}");
451+
})
415452
.ok()
416453
}
417454

418-
fn put(&self, key: &str, value: &[u8]) {
455+
fn put(&self, _key: &str, _value: &[u8]) {
456+
panic!("unsupported");
457+
}
458+
459+
fn put_summary(&self, (name, version): (&str, &Version), value: &[u8]) {
419460
self.deferred_writes
420461
.borrow_mut()
421-
.insert(key.into(), value.into());
462+
.entry(name.into())
463+
.or_insert(Default::default())
464+
.push((version.to_string(), value.to_vec()));
422465
}
423466

424467
fn invalidate(&self, key: &str) {
@@ -440,8 +483,10 @@ impl CacheStore for LocalDatabase<'_> {
440483
fn migrations() -> Vec<Migration> {
441484
vec![basic_migration(
442485
"CREATE TABLE IF NOT EXISTS summaries (
443-
name TEXT PRIMARY KEY NOT NULL,
444-
value BLOB NOT NULL
486+
name TEXT NOT NULL,
487+
version TEXT NOT NULL,
488+
value BLOB NOT NULL,
489+
PRIMARY KEY (name, version)
445490
)",
446491
)]
447492
}

src/cargo/sources/registry/index/mod.rs

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use std::task::{ready, Poll};
4040
use tracing::{debug, info};
4141

4242
mod cache;
43-
use self::cache::CacheManager;
43+
use self::cache::{CacheManager, MaybeSummaries};
4444
use self::cache::SummariesCache;
4545

4646
/// The maximum schema version of the `v` field in the index this version of
@@ -115,7 +115,8 @@ struct Summaries {
115115
enum MaybeIndexSummary {
116116
/// A summary which has not been parsed, The `start` and `end` are pointers
117117
/// into [`Summaries::raw_data`] which this is an entry of.
118-
Unparsed { start: usize, end: usize },
118+
Unparsed(std::ops::Range<usize>),
119+
UnparsedData(Vec<u8>),
119120

120121
/// An actually parsed summary.
121122
Parsed(IndexSummary),
@@ -551,14 +552,20 @@ impl Summaries {
551552

552553
let mut cached_summaries = None;
553554
let mut index_version = None;
554-
if let Some(contents) = cache_manager.get(name) {
555-
match Summaries::parse_cache(contents) {
556-
Ok((s, v)) => {
557-
cached_summaries = Some(s);
558-
index_version = Some(v);
555+
if let Some(maybe_summaries) = cache_manager.get(name) {
556+
match maybe_summaries {
557+
MaybeSummaries::Unparsed(contents) => match Summaries::parse_cache(contents) {
558+
Ok((s, v)) => {
559+
cached_summaries = Some(s);
560+
index_version = Some(v);
561+
}
562+
Err(e) => {
563+
tracing::debug!("failed to parse {name:?} cache: {e}");
564+
}
559565
}
560-
Err(e) => {
561-
tracing::debug!("failed to parse {name:?} cache: {e}");
566+
MaybeSummaries::Parsed(summaries) => {
567+
cached_summaries = Some(summaries);
568+
index_version = Some("2".into());
562569
}
563570
}
564571
}
@@ -611,9 +618,18 @@ impl Summaries {
611618
}
612619
};
613620
let version = summary.package_id().version().clone();
614-
cache.versions.push((version.clone(), line));
621+
if cache_manager.is_sqlite() {
622+
cache_manager.put_summary((&name, &version), line);
623+
} else {
624+
cache.versions.push((version.clone(), line));
625+
}
615626
ret.versions.insert(version, summary.into());
616627
}
628+
629+
if cache_manager.is_sqlite() {
630+
return Poll::Ready(Ok(Some(ret)));
631+
}
632+
617633
if let Some(index_version) = index_version {
618634
tracing::trace!("caching index_version {}", index_version);
619635
let cache_bytes = cache.serialize(index_version.as_str());
@@ -649,7 +665,7 @@ impl Summaries {
649665
for (version, summary) in cache.versions {
650666
let (start, end) = subslice_bounds(&contents, summary);
651667
ret.versions
652-
.insert(version, MaybeIndexSummary::Unparsed { start, end });
668+
.insert(version, MaybeIndexSummary::Unparsed(start..end));
653669
}
654670
ret.raw_data = contents;
655671
return Ok((ret, index_version));
@@ -680,14 +696,16 @@ impl MaybeIndexSummary {
680696
source_id: SourceId,
681697
bindeps: bool,
682698
) -> CargoResult<&IndexSummary> {
683-
let (start, end) = match self {
684-
MaybeIndexSummary::Unparsed { start, end } => (*start, *end),
699+
let data = match self {
700+
MaybeIndexSummary::Unparsed(range) => &raw_data[range.clone()],
701+
MaybeIndexSummary::UnparsedData(data) => data,
685702
MaybeIndexSummary::Parsed(summary) => return Ok(summary),
686703
};
687-
let summary = IndexSummary::parse(&raw_data[start..end], source_id, bindeps)?;
704+
let summary = IndexSummary::parse(data, source_id, bindeps)?;
688705
*self = MaybeIndexSummary::Parsed(summary);
689706
match self {
690707
MaybeIndexSummary::Unparsed { .. } => unreachable!(),
708+
MaybeIndexSummary::UnparsedData { .. } => unreachable!(),
691709
MaybeIndexSummary::Parsed(summary) => Ok(summary),
692710
}
693711
}

0 commit comments

Comments
 (0)