Hold a lock so a second scan fails at once (closes #53)
check / check (push) Successful in 2m22s
check / check (push) Successful in 2m22s
scan takes an exclusive flock(2) on a lock file beside the database (its path with .lock appended) before it walks anything or opens the database, and holds it until it returns. A second scan against the same database fails at once with a one-line error naming the lock file and exits 1. report and trees never take the lock. The lock ends with the process, so a fatal error or an interrupt releases it; the file is never deleted. golang.org/x/sys becomes a direct dependency. The README smoke test now keeps the database outside the scanned tree, where its empty lock file would have joined the empty-file group. Model: opus-5-5
This commit is contained in:
@@ -85,11 +85,13 @@ type fileMeta struct {
|
||||
// least one other file shares are ever hashed: a size-unique file
|
||||
// cannot be a duplicate. A file of headTailMin or more gets its content
|
||||
// hash only when its size, head, and tail match another file's. Flag
|
||||
// parsing and the at-least-one-operand check are done by cobra. Errors
|
||||
// are returned rather than exiting, so that the deferred close — which
|
||||
// takes the database out of WAL mode — always runs. Cancelling ctx
|
||||
// unwinds the worker pools and aborts the scan with the context's
|
||||
// error.
|
||||
// parsing and the at-least-one-operand check are done by cobra. The
|
||||
// scan holds the lock on the database for its whole run, so a second
|
||||
// scan fails before it walks the filesystem or opens the database.
|
||||
// Errors are returned rather than exiting, so that the deferred close —
|
||||
// which takes the database out of WAL mode — always runs, and the lock
|
||||
// is released after it. Cancelling ctx unwinds the worker pools and
|
||||
// aborts the scan with the context's error.
|
||||
func runScan(ctx context.Context, roots []string, workers int,
|
||||
oneFS bool,
|
||||
) error {
|
||||
@@ -104,6 +106,13 @@ func runScan(ctx context.Context, roots []string, workers int,
|
||||
|
||||
dbPath := databasePath()
|
||||
|
||||
lock, err := lockScanDatabase(dbPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() { _ = lock.Close() }()
|
||||
|
||||
db, err := openScanDatabase(ctx, dbPath)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user