cache.v

2.2 KB · raw

1//! The file cache: a machine-local shortcut so `status` and `save` can skip2//! files whose size, mtime and ctime are unchanged. It caches the working3//! tree, never history, and is safe to drop at any time.45module storage67// CacheRow is what a file looked like when last hashed. It is stale as soon as the file's size, mtime8// or ctime differ; snapshot.hash_file makes that check.9pub struct CacheRow {10pub:11	path     string12	size     i6413	mtime_ns i6414	ctime_ns i6415	hash     string16}1718pub fn (s &Store) load_cache() !map[string]CacheRow {19	mut rows := map[string]CacheRow{}20	mut stmt := s.db.prepare('SELECT path, size, mtime_ns, ctime_ns, hash FROM file_cache')!21	defer {22		stmt.finalize()23	}24	for stmt.step()! {25		row := CacheRow{26			path:     stmt.text(0)27			size:     stmt.int(1)28			mtime_ns: stmt.int(2)29			ctime_ns: stmt.int(3)30			hash:     stmt.text(4)31		}32		rows[row.path] = row33	}34	return rows35}3637// save_cache_rows writes a walk's rows in one transaction, without waiting for38// another writer: the cache only saves time, so while another command holds39// the lock the rows are simply not written.40pub fn (s &Store) save_cache_rows(rows []CacheRow) ! {41	if rows.len == 0 {42		return43	}44	s.db.exec('PRAGMA busy_timeout = 0')!45	defer {46		s.db.exec('PRAGMA busy_timeout = ${busy_timeout_ms}') or {}47	}48	s.db.exec('BEGIN IMMEDIATE')!49	for row in rows {50		s.save_cache(row) or {51			s.rollback()52			return err53		}54	}55	s.end()!56}5758fn (s &Store) save_cache(row CacheRow) ! {59	mut stmt := s.db.prepare('INSERT INTO file_cache (path, size, mtime_ns, ctime_ns, hash)60		VALUES (?, ?, ?, ?, ?)61		ON CONFLICT(path) DO UPDATE SET size = excluded.size, mtime_ns = excluded.mtime_ns,62			ctime_ns = excluded.ctime_ns, hash = excluded.hash')!63	defer {64		stmt.finalize()65	}66	stmt.bind_text(1, row.path)!67	stmt.bind_int(2, row.size)!68	stmt.bind_int(3, row.mtime_ns)!69	stmt.bind_int(4, row.ctime_ns)!70	stmt.bind_text(5, row.hash)!71	stmt.step()!72}7374pub fn (s &Store) drop_cache() ! {75	s.db.exec('DELETE FROM file_cache')!76}7778pub fn (s &Store) cache_count() !i64 {79	mut stmt := s.db.prepare('SELECT COUNT(*) FROM file_cache')!80	defer {81		stmt.finalize()82	}83	if !stmt.step()! {84		return 085	}86	return stmt.int(0)87}