Files
kopia/cli/command_storage_sweep.go
Jarek Kowalski 4566213f5d switched formatter to pass IV explicitly
extracted packIndex interface and implemented protoPackIndex to wrap all index data manipulation
2018-04-08 12:20:32 -07:00

68 lines
1.8 KiB
Go

package cli
import (
"context"
"fmt"
"time"
"github.com/kopia/kopia/block"
"github.com/kopia/kopia/repo"
"github.com/kopia/kopia/storage"
)
var (
storageSweepCommand = storageCommands.Command("sweep", "Remove unused storage blocks")
storageSweepAgeThreshold = storageSweepCommand.Flag("min-age", "Minimum age of storage block to delete").Default("24h").Duration()
storageSweepPrintUnused = storageSweepCommand.Flag("print", "Do not delete blocks, but print which ones would be deleted").Short('n').Bool()
)
func runStorageSweepAction(ctx context.Context, rep *repo.Repository) error {
indexBlocks, err := rep.Blocks.ActiveIndexBlocks(ctx)
if err != nil {
return err
}
inUseIndexBlocks := map[block.PhysicalBlockID]bool{}
for _, ib := range indexBlocks {
inUseIndexBlocks[ib.BlockID] = true
}
ctx, cancel := context.WithCancel(ctx)
defer cancel()
ch := rep.Storage.ListBlocks(ctx, "")
for bm := range ch {
if bm.Error != nil {
return bm.Error
}
if err = sweepBlock(ctx, rep, bm, inUseIndexBlocks); err != nil {
return err
}
}
return nil
}
func sweepBlock(ctx context.Context, rep *repo.Repository, bm storage.BlockMetadata, inUseIndexBlocks map[block.PhysicalBlockID]bool) error {
age := time.Since(bm.TimeStamp)
inUse := rep.Blocks.IsStorageBlockInUse(block.PhysicalBlockID(bm.BlockID)) || inUseIndexBlocks[block.PhysicalBlockID(bm.BlockID)] || bm.BlockID == repo.FormatBlockID
keep := inUse || age < *storageSweepAgeThreshold
if keep {
return nil
}
if *storageSweepPrintUnused {
fmt.Printf("unused block %v age %v\n", bm.BlockID, age)
return nil
}
fmt.Printf("deleting unused block %v age %v\n", bm.BlockID, age)
return rep.Storage.DeleteBlock(ctx, bm.BlockID)
}
func init() {
storageSweepCommand.Action(repositoryAction(runStorageSweepAction))
}