cleanup comments, update translations, bump to 0.4.1
This commit is contained in:
parent
9edcc9841b
commit
7d8ab87eee
28 changed files with 412 additions and 1114 deletions
|
|
@ -1,19 +1,14 @@
|
|||
'use strict'
|
||||
|
||||
// Content hashing for the LAN sync, plus the per-file digest cache.
|
||||
//
|
||||
// Syncing a library means hashing tens of thousands of files, so the digest of
|
||||
// every file is remembered on disk (files/data/lansync-hashes.json), keyed by
|
||||
// its FILES-relative path with the size and mtime it was computed from: a file
|
||||
// whose size and mtime are unchanged is never read again, only stat'ed. The
|
||||
// Content hashing for the LAN sync, plus the per-file digest cache
|
||||
// (files/data/lansync-hashes.json, keyed by path with size + mtime). The
|
||||
// cache is machine-local and never travels in a sync.
|
||||
|
||||
const crypto = require('crypto')
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
// BLAKE2b resists collisions like SHA-2 but is noticeably faster. Older
|
||||
// runtimes fall back to SHA-2.
|
||||
// BLAKE2b is faster than SHA-2; older runtimes fall back to SHA-2.
|
||||
const HASH_ALGO = (() => {
|
||||
for (const algo of ['blake2b512', 'sha512', 'sha256']) {
|
||||
try {
|
||||
|
|
@ -24,9 +19,7 @@ const HASH_ALGO = (() => {
|
|||
return 'sha256'
|
||||
})()
|
||||
|
||||
// Streaming through one callback instead of accumulating 'data' chunks keeps
|
||||
// memory flat for huge files, and a small highWaterMark gives the read pump
|
||||
// real backpressure. Digest speed does not care about the chunk size.
|
||||
// Streamed hashing keeps memory flat on huge files.
|
||||
function hashFile(file, onBytes) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const hash = crypto.createHash(HASH_ALGO)
|
||||
|
|
@ -39,11 +32,9 @@ function hashFile(file, onBytes) {
|
|||
})
|
||||
}
|
||||
|
||||
// A quarter million entries is a whole game library; beyond that, entries the
|
||||
// longest time untouched are dropped first.
|
||||
// Beyond a quarter million entries, the least recently touched are dropped.
|
||||
const HASH_CACHE_MAX = 250000
|
||||
// Mid-sync saves are throttled to this (the file can hold tens of megabytes);
|
||||
// callers that must not lose entries (sync end, shutdown) pass force=true.
|
||||
// Mid-sync saves are throttled; callers that must not lose entries pass force=true.
|
||||
const SAVE_MIN_MS = 60000
|
||||
|
||||
function createHashCache(dataDir) {
|
||||
|
|
@ -64,8 +55,7 @@ function createHashCache(dataDir) {
|
|||
return cache
|
||||
}
|
||||
|
||||
// Compact JSON (the entries are arrays) keeps a full cache at tens of
|
||||
// milliseconds instead of the seconds pretty-printed JSON needs.
|
||||
// Compact JSON: a full cache writes in tens of ms.
|
||||
function save(force) {
|
||||
if (!dirty || !cache) return
|
||||
if (!force && Date.now() - savedAt < SAVE_MIN_MS) return
|
||||
|
|
@ -86,10 +76,8 @@ function createHashCache(dataDir) {
|
|||
} catch {}
|
||||
}
|
||||
|
||||
// The remembered digest of a file, or null when it has to be read again.
|
||||
// A hit only marks the cache dirty when its timestamp is actually stale:
|
||||
// marking it on every lookup would force a full rewrite of the file per
|
||||
// sync even though nothing a second sync could reuse has changed.
|
||||
// The remembered digest, or null when it has to be read again. A hit marks
|
||||
// the cache dirty only when the timestamp is stale.
|
||||
function hit(rel, size, mtimeMs) {
|
||||
const known = load()[rel]
|
||||
if (!known || known[0] !== size || known[1] !== mtimeMs || typeof known[2] !== 'string') {
|
||||
|
|
@ -109,9 +97,7 @@ function createHashCache(dataDir) {
|
|||
dirty = true
|
||||
}
|
||||
|
||||
// Digest of a file we already stat'ed: size and mtime unchanged means the
|
||||
// bytes are the same, and the digest from an earlier sync still describes
|
||||
// them. Otherwise the file is read (progress through onBytes) and stored.
|
||||
// Unchanged size + mtime -> cached digest; otherwise read and store.
|
||||
async function cachedHash(rel, abs, size, mtimeMs, onBytes) {
|
||||
const known = hit(rel, size, mtimeMs)
|
||||
if (known) return known
|
||||
|
|
@ -120,8 +106,7 @@ function createHashCache(dataDir) {
|
|||
return hash
|
||||
}
|
||||
|
||||
// The user can drop the cache from the settings view; a corrupted or stale
|
||||
// file is also replaced wholesale this way.
|
||||
// Settings view "clear cache" and stale files go through here.
|
||||
function clear() {
|
||||
cache = null
|
||||
dirty = false
|
||||
|
|
@ -134,8 +119,7 @@ function createHashCache(dataDir) {
|
|||
} catch {}
|
||||
}
|
||||
|
||||
// Dropping the in-memory copy makes the next lookup re-read the file from
|
||||
// disk - what tests use to prove a file was hashed instead of remembered.
|
||||
// Dropping the memory copy makes the next lookup re-read from disk (tests).
|
||||
function forget() {
|
||||
cache = null
|
||||
dirty = false
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue