138 lines
3.7 KiB
Go
138 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"forever-files/db"
|
|
"forever-files/partitioner"
|
|
"forever-files/types"
|
|
"github.com/dustin/go-humanize"
|
|
"github.com/urfave/cli/v2"
|
|
"math"
|
|
)
|
|
|
|
func plan() *cli.Command {
|
|
return &cli.Command{
|
|
Name: "plan",
|
|
Aliases: []string{"p"},
|
|
Usage: "Reads the database and plans the partitions for the backup, stores the partitions in the database",
|
|
Flags: []cli.Flag{
|
|
&cli.StringFlag{
|
|
Name: "targetSize",
|
|
Usage: "The target size for each partition, valid options are DVD-SL, DVD-DL, BD-SL, BD-DL, BD-TL, BD-QL\nor you can provide any specific size e.g. 4.6GB, 8.1GB, 25GB, 50GB, 100GB, 128GB or 5MB!",
|
|
Aliases: []string{"s"},
|
|
Value: "DVD-SL",
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: "verbose",
|
|
Usage: "Print the files in each partition",
|
|
Aliases: []string{"v"},
|
|
Value: false,
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: "left-pack",
|
|
Usage: "Use the left-pack algorithm to calculate partitions",
|
|
Aliases: []string{"l"},
|
|
Value: false,
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: "reset",
|
|
Usage: "Reset the database before planning partitions",
|
|
Aliases: []string{"r"},
|
|
Value: false,
|
|
},
|
|
},
|
|
Action: func(c *cli.Context) error {
|
|
|
|
store, err := db.NewDB(types.AppName)
|
|
if err != nil {
|
|
panic(fmt.Errorf("error creating db: %w", err))
|
|
}
|
|
defer store.Close()
|
|
|
|
err = store.Migrate()
|
|
if err != nil {
|
|
panic(fmt.Errorf("error migrating db: %w", err))
|
|
}
|
|
|
|
if c.Bool("reset") {
|
|
err = store.RemovePartitionAssignment()
|
|
if err != nil {
|
|
return fmt.Errorf("error resetting partitions in the db: %w", err)
|
|
}
|
|
}
|
|
|
|
size := int64(4600000000) // size of a single layer DVD
|
|
targetSize := c.String("targetSize")
|
|
switch targetSize {
|
|
case "DVD-SL":
|
|
size = 4600000000
|
|
case "DVD-DL":
|
|
size = 8100000000
|
|
case "BD-SL":
|
|
size = 25000000000
|
|
case "BD-DL":
|
|
size = 50000000000
|
|
case "BD-TL":
|
|
size = 100000000000
|
|
case "BD-QL":
|
|
size = 128000000000
|
|
default:
|
|
// try to parse the size from human-readable format
|
|
usize, err := humanize.ParseBytes(targetSize)
|
|
if err != nil {
|
|
fmt.Printf("invalid target size: %v\n", err)
|
|
fmt.Println("valid options are DVD-SL, DVD-DL, BD-SL, BD-DL, BD-TL, BD-QL")
|
|
fmt.Println("or you can provide any specific size e.g. 4.6GB, 8.1GB, 25GB, 50GB, 100GB, 128GB or 5MB!")
|
|
size = 4600000000
|
|
}
|
|
if usize > math.MaxInt64 {
|
|
fmt.Println("size is too large")
|
|
size = 4600000000
|
|
}
|
|
size = int64(usize)
|
|
}
|
|
|
|
fmt.Printf("Target Size: %v\n", humanize.Bytes(uint64(size)))
|
|
fmt.Println("Calculating partitions...")
|
|
|
|
var partitions [][]types.FileMetadata
|
|
|
|
if !c.Bool("left-pack") {
|
|
partitions, err = partitioner.CalculatePartitions(store, size)
|
|
if err != nil {
|
|
return fmt.Errorf("error calculating partitions: %w", err)
|
|
}
|
|
}
|
|
|
|
if c.Bool("left-pack") {
|
|
partitions, err = partitioner.CalculatePartitionsLeftPack(store, size)
|
|
if err != nil {
|
|
return fmt.Errorf("error calculating partitions: %w", err)
|
|
}
|
|
}
|
|
|
|
for i, partition := range partitions {
|
|
partSize := int64(0)
|
|
if c.Bool("verbose") {
|
|
fmt.Printf("Partition %v:\n", i)
|
|
}
|
|
for _, file := range partition {
|
|
if c.Bool("verbose") {
|
|
fmt.Printf("%v/%v %v\n", file.Path, file.Name, humanize.Bytes(uint64(file.Size)))
|
|
}
|
|
partSize += file.Size
|
|
// save the planned partitions
|
|
file.PartitionId = fmt.Sprintf("%d", i)
|
|
err = store.StoreFilePartition(file)
|
|
if err != nil {
|
|
return fmt.Errorf("error storing file's partition: %w", err)
|
|
}
|
|
}
|
|
fmt.Printf("Partition %v Size: %v files %v\n", i, len(partition), humanize.Bytes(uint64(partSize)))
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
}
|