Fix noinlineerr findings: internal/snapshot (refs #61)
This commit is contained in:
@@ -479,7 +479,8 @@ func (b *BackupEngine) Backup(ctx context.Context, fsys fs.FS, root string) (str
|
||||
dummyData := []byte(chunkHash)
|
||||
|
||||
// Upload to S3 as a blob
|
||||
if err := b.s3Client.PutBlob(ctx, blobHash, dummyData); err != nil {
|
||||
err = b.s3Client.PutBlob(ctx, blobHash, dummyData)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@ func DecodeManifest(r io.Reader) (*Manifest, error) {
|
||||
|
||||
// Decode JSON manifest
|
||||
var manifest Manifest
|
||||
if err := json.NewDecoder(zr).Decode(&manifest); err != nil {
|
||||
|
||||
err = json.NewDecoder(zr).Decode(&manifest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decoding manifest: %w", err)
|
||||
}
|
||||
|
||||
@@ -58,13 +60,15 @@ func EncodeManifest(manifest *Manifest, compressionLevel int) ([]byte, error) {
|
||||
return nil, fmt.Errorf("creating zstd writer: %w", err)
|
||||
}
|
||||
|
||||
if _, err := writer.Write(jsonData); err != nil {
|
||||
_, err = writer.Write(jsonData)
|
||||
if err != nil {
|
||||
_ = writer.Close()
|
||||
|
||||
return nil, fmt.Errorf("writing compressed data: %w", err)
|
||||
}
|
||||
|
||||
if err := writer.Close(); err != nil {
|
||||
err = writer.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("closing zstd writer: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +213,8 @@ func (s *Scanner) Scan(ctx context.Context, path string, snapshotID string) (*Sc
|
||||
filesToProcess := scanResult.FilesToProcess
|
||||
|
||||
// Phase 1b: Detect deleted files by comparing DB against scanned files
|
||||
if err := s.detectDeletedFilesFromMap(ctx, knownFiles, existingFiles, result); err != nil {
|
||||
err = s.detectDeletedFilesFromMap(ctx, knownFiles, existingFiles, result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("detecting deleted files: %w", err)
|
||||
}
|
||||
|
||||
@@ -264,7 +265,8 @@ func (s *Scanner) loadDatabaseState(ctx context.Context, path string) (map[strin
|
||||
|
||||
s.ui.Begin("Loading known chunks from local index database.")
|
||||
|
||||
if err := s.loadKnownChunks(ctx); err != nil {
|
||||
err = s.loadKnownChunks(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("loading known chunks: %w", err)
|
||||
}
|
||||
|
||||
@@ -1262,7 +1264,8 @@ func (s *Scanner) handleBlobReady(blobWithReader *blob.BlobWithReader) error {
|
||||
return fmt.Errorf("uploading blob %s: %w", finishedBlob.Hash, err)
|
||||
}
|
||||
|
||||
if err := s.recordBlobMetadata(ctx, finishedBlob, blobExists, startTime); err != nil {
|
||||
err = s.recordBlobMetadata(ctx, finishedBlob, blobExists, startTime)
|
||||
if err != nil {
|
||||
s.cleanupBlobTempFile(blobWithReader)
|
||||
|
||||
return err
|
||||
@@ -1274,7 +1277,8 @@ func (s *Scanner) handleBlobReady(blobWithReader *blob.BlobWithReader) error {
|
||||
s.removePendingChunkHashes(blobWithReader.InsertedChunkHashes)
|
||||
|
||||
// Flush files whose chunks are now all committed
|
||||
if err := s.flushCompletedPendingFiles(ctx); err != nil {
|
||||
err = s.flushCompletedPendingFiles(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("flushing completed files: %w", err)
|
||||
}
|
||||
|
||||
@@ -1287,7 +1291,9 @@ func (s *Scanner) uploadBlobIfNeeded(ctx context.Context, blobPath string, blobW
|
||||
|
||||
// Check if blob already exists (deduplication after restart)
|
||||
destination := s.storage.Info().Location
|
||||
if _, err := s.storage.Stat(ctx, blobPath); err == nil {
|
||||
|
||||
_, err := s.storage.Stat(ctx, blobPath)
|
||||
if err == nil {
|
||||
log.Info("Blob already exists in storage, skipping upload",
|
||||
"hash", finishedBlob.Hash, "size", humanize.Bytes(uint64(finishedBlob.Compressed)))
|
||||
s.ui.Info("Blob %s (%s) already exists at %s. Skipping upload.",
|
||||
@@ -1301,7 +1307,7 @@ func (s *Scanner) uploadBlobIfNeeded(ctx context.Context, blobPath string, blobW
|
||||
|
||||
progressCallback := s.makeUploadProgressCallback(ctx, finishedBlob, startTime)
|
||||
|
||||
err := s.storage.PutWithProgress(ctx, blobPath, blobWithReader.Reader, finishedBlob.Compressed, progressCallback)
|
||||
err = s.storage.PutWithProgress(ctx, blobPath, blobWithReader.Reader, finishedBlob.Compressed, progressCallback)
|
||||
if err != nil {
|
||||
log.Error("Failed to upload blob", "hash", finishedBlob.Hash, "error", err)
|
||||
|
||||
|
||||
@@ -185,11 +185,13 @@ func TestScannerLargeFile(t *testing.T) {
|
||||
largeContent[i] = byte((i * 7919) ^ (i >> 3))
|
||||
}
|
||||
|
||||
if err := fs.MkdirAll("/source", 0755); err != nil {
|
||||
err := fs.MkdirAll("/source", 0755)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := afero.WriteFile(fs, "/source/large.bin", largeContent, 0644); err != nil {
|
||||
err = afero.WriteFile(fs, "/source/large.bin", largeContent, 0644)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -258,7 +258,8 @@ func (sm *SnapshotManager) ExportSnapshotMetadata(ctx context.Context, dbPath st
|
||||
}
|
||||
|
||||
// Step 7: Upload to S3 in snapshot subdirectory
|
||||
if err := sm.uploadSnapshotArtifacts(ctx, snapshotID, finalData, blobManifest); err != nil {
|
||||
err = sm.uploadSnapshotArtifacts(ctx, snapshotID, finalData, blobManifest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -278,7 +279,8 @@ func (sm *SnapshotManager) prepareExportDB(ctx context.Context, dbPath, snapshot
|
||||
tempDBPath := filepath.Join(tempDir, "snapshot.db")
|
||||
log.Debug("Copying database to temporary location", "source", dbPath, "destination", tempDBPath)
|
||||
|
||||
if err := sm.copyFile(dbPath, tempDBPath); err != nil {
|
||||
err := sm.copyFile(dbPath, tempDBPath)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("copying database: %w", err)
|
||||
}
|
||||
|
||||
@@ -304,7 +306,8 @@ func (sm *SnapshotManager) prepareExportDB(ctx context.Context, dbPath, snapshot
|
||||
|
||||
// Step 3: VACUUM the database to remove deleted data and compact
|
||||
// This is critical for security - ensures no stale/deleted data is uploaded
|
||||
if err := sm.vacuumDatabase(tempDBPath); err != nil {
|
||||
err = sm.vacuumDatabase(tempDBPath)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("vacuuming database: %w", err)
|
||||
}
|
||||
|
||||
@@ -312,7 +315,9 @@ func (sm *SnapshotManager) prepareExportDB(ctx context.Context, dbPath, snapshot
|
||||
|
||||
// Step 4: Compress and encrypt the binary database file
|
||||
compressedPath := filepath.Join(tempDir, "db.zst.age")
|
||||
if err := sm.compressFile(tempDBPath, compressedPath); err != nil {
|
||||
|
||||
err = sm.compressFile(tempDBPath, compressedPath)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("compressing database: %w", err)
|
||||
}
|
||||
|
||||
@@ -423,38 +428,46 @@ func (sm *SnapshotManager) cleanSnapshotDB(ctx context.Context, dbPath string, s
|
||||
}()
|
||||
|
||||
// Execute cleanup steps in order
|
||||
if err := sm.deleteOtherSnapshots(ctx, tx, snapshotID); err != nil {
|
||||
err = sm.deleteOtherSnapshots(ctx, tx, snapshotID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("step 1 - delete other snapshots: %w", err)
|
||||
}
|
||||
|
||||
if err := sm.deleteOrphanedSnapshotAssociations(ctx, tx, snapshotID); err != nil {
|
||||
err = sm.deleteOrphanedSnapshotAssociations(ctx, tx, snapshotID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("step 2 - delete orphaned snapshot associations: %w", err)
|
||||
}
|
||||
|
||||
if err := sm.deleteOrphanedFiles(ctx, tx, snapshotID); err != nil {
|
||||
err = sm.deleteOrphanedFiles(ctx, tx, snapshotID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("step 3 - delete orphaned files: %w", err)
|
||||
}
|
||||
|
||||
if err := sm.deleteOrphanedChunkToFileMappings(ctx, tx); err != nil {
|
||||
err = sm.deleteOrphanedChunkToFileMappings(ctx, tx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("step 4 - delete orphaned chunk-to-file mappings: %w", err)
|
||||
}
|
||||
|
||||
if err := sm.deleteOrphanedBlobs(ctx, tx, snapshotID); err != nil {
|
||||
err = sm.deleteOrphanedBlobs(ctx, tx, snapshotID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("step 5 - delete orphaned blobs: %w", err)
|
||||
}
|
||||
|
||||
if err := sm.deleteOrphanedBlobToChunkMappings(ctx, tx); err != nil {
|
||||
err = sm.deleteOrphanedBlobToChunkMappings(ctx, tx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("step 6 - delete orphaned blob-to-chunk mappings: %w", err)
|
||||
}
|
||||
|
||||
if err := sm.deleteOrphanedChunks(ctx, tx); err != nil {
|
||||
err = sm.deleteOrphanedChunks(ctx, tx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("step 7 - delete orphaned chunks: %w", err)
|
||||
}
|
||||
|
||||
// Commit transaction
|
||||
log.Debug("[Temp DB Cleanup] Committing cleanup transaction")
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
err = tx.Commit()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("committing transaction: %w", err)
|
||||
}
|
||||
|
||||
@@ -509,7 +522,8 @@ func (sm *SnapshotManager) vacuumDatabase(dbPath string) error {
|
||||
log.Debug("Running VACUUM on database", "path", dbPath)
|
||||
cmd := exec.Command("sqlite3", dbPath, "VACUUM;")
|
||||
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("running VACUUM: %w (output: %s)", err, string(output))
|
||||
}
|
||||
|
||||
@@ -559,12 +573,14 @@ func (sm *SnapshotManager) compressFile(inputPath, outputPath string) error {
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err := io.Copy(writer, input); err != nil {
|
||||
_, err = io.Copy(writer, input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("compressing data: %w", err)
|
||||
}
|
||||
|
||||
// Close writer to flush all data
|
||||
if err := writer.Close(); err != nil {
|
||||
err = writer.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("closing writer: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -85,13 +85,16 @@ func TestCleanSnapshotDBEmptySnapshot(t *testing.T) {
|
||||
}
|
||||
|
||||
// Close the database
|
||||
if err := db.Close(); err != nil {
|
||||
err = db.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to close database: %v", err)
|
||||
}
|
||||
|
||||
// Copy database
|
||||
tempDBPath := filepath.Join(tempDir, "temp.db")
|
||||
if err := copyFile(fs, dbPath, tempDBPath); err != nil {
|
||||
|
||||
err = copyFile(fs, dbPath, tempDBPath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to copy database: %v", err)
|
||||
}
|
||||
|
||||
@@ -105,7 +108,9 @@ func TestCleanSnapshotDBEmptySnapshot(t *testing.T) {
|
||||
config: cfg,
|
||||
fs: fs,
|
||||
}
|
||||
if _, err := sm.cleanSnapshotDB(ctx, tempDBPath, snapshot.ID.String()); err != nil {
|
||||
|
||||
_, err = sm.cleanSnapshotDB(ctx, tempDBPath, snapshot.ID.String())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to clean snapshot database: %v", err)
|
||||
}
|
||||
|
||||
@@ -171,13 +176,16 @@ func TestCleanSnapshotDBNonExistentSnapshot(t *testing.T) {
|
||||
}
|
||||
|
||||
// Close immediately
|
||||
if err := db.Close(); err != nil {
|
||||
err = db.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to close database: %v", err)
|
||||
}
|
||||
|
||||
// Copy database
|
||||
tempDBPath := filepath.Join(tempDir, "temp.db")
|
||||
if err := copyFile(fs, dbPath, tempDBPath); err != nil {
|
||||
|
||||
err = copyFile(fs, dbPath, tempDBPath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to copy database: %v", err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user